Skip to content

Commit

Permalink
[TASK] Declare TypeScript types for global TYPO3 object
Browse files Browse the repository at this point in the history
Missing declarations caused some method calls
and assignments to not be type checked, as all
members of the (top.|window.)TYPO3 object were
declared to `any`.
This actually revealed some invalid API usage.
which is fixed as a drive-by. (No real bugs were found,
as type checking in the APIs caught/ignored such cases)

Resolves: #101644
Releases: main, 12.4
Change-Id: I2e188e53a02d9e0ae875084cadc28600c7a59aa6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80502
Reviewed-by: Benjamin Franzke <ben@bnf.dev>
Tested-by: Benjamin Franzke <ben@bnf.dev>
Tested-by: core-ci <typo3@b13.com>
  • Loading branch information
bnf committed Aug 10, 2023
1 parent ec4a8c2 commit 51b843c
Show file tree
Hide file tree
Showing 12 changed files with 55 additions and 38 deletions.
3 changes: 2 additions & 1 deletion Build/Sources/TypeScript/backend/modal.ts
Expand Up @@ -482,8 +482,9 @@ class Modal {
* Initialize markup with data attributes
*
* @param {HTMLDocument} theDocument
* @internal
*/
private initializeMarkupTrigger(theDocument: Document): void {
public initializeMarkupTrigger(theDocument: Document): void {
const modalTrigger = (evt: Event, triggerElement: HTMLElement): void => {
evt.preventDefault();
const content = triggerElement.dataset.bsContent || triggerElement.dataset.content || TYPO3.lang['message.confirmation'] || 'Are you sure?';
Expand Down
6 changes: 5 additions & 1 deletion Build/Sources/TypeScript/backend/module-menu.ts
Expand Up @@ -518,11 +518,15 @@ class ModuleMenu {
}
}

interface ModuleMenuNamespace {
App: ModuleMenu;
}

if (!top.TYPO3.ModuleMenu) {
top.TYPO3.ModuleMenu = {
App: new ModuleMenu(),
};
}
const moduleMenuApp = top.TYPO3.ModuleMenu;
const moduleMenuApp = <ModuleMenuNamespace>top.TYPO3.ModuleMenu;

export default moduleMenuApp;
8 changes: 4 additions & 4 deletions Build/Sources/TypeScript/backend/multi-step-wizard.ts
Expand Up @@ -541,21 +541,21 @@ class MultiStepWizard {
}
}

let multistepWizardObject;
let multistepWizardObject: MultiStepWizard;
try {
// fetch from opening window
if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.MultiStepWizard) {
multistepWizardObject = window.opener.TYPO3.MultiStepWizard;
multistepWizardObject = <MultiStepWizard>window.opener.TYPO3.MultiStepWizard;
}

// fetch from parent
if (parent && parent.window.TYPO3 && parent.window.TYPO3.MultiStepWizard) {
multistepWizardObject = parent.window.TYPO3.MultiStepWizard;
multistepWizardObject = <MultiStepWizard>parent.window.TYPO3.MultiStepWizard;
}

// fetch object from outer frame
if (top && top.TYPO3 && top.TYPO3.MultiStepWizard) {
multistepWizardObject = top.TYPO3.MultiStepWizard;
multistepWizardObject = <MultiStepWizard>top.TYPO3.MultiStepWizard;
}
} catch (e) {
// This only happens if the opener, parent or top is some other url (eg a local file)
Expand Down
10 changes: 9 additions & 1 deletion Build/Sources/TypeScript/backend/toolbar/live-search.ts
Expand Up @@ -243,4 +243,12 @@ class LiveSearch {
}
}

export default top.TYPO3.LiveSearch ?? new LiveSearch();
let liveSearchObject: LiveSearch;
if (!top.TYPO3.LiveSearch) {
liveSearchObject = new LiveSearch();
top.TYPO3.LiveSearch = liveSearchObject;
} else {
liveSearchObject = top.TYPO3.LiveSearch;
}

export default liveSearchObject;
4 changes: 2 additions & 2 deletions Build/Sources/TypeScript/backend/wizard.ts
Expand Up @@ -259,7 +259,7 @@ class Wizard {
}).width(initialStep + '%').text(
top.TYPO3.lang['wizard.progress']
.replace('{0}', '1')
.replace('{1}', slideCount),
.replace('{1}', slideCount.toString()),
),
),
);
Expand Down Expand Up @@ -293,7 +293,7 @@ class Wizard {
}
}

let wizardObject: any;
let wizardObject: Wizard;
try {
// fetch from opening window
if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Wizard) {
Expand Down
8 changes: 4 additions & 4 deletions Build/Sources/TypeScript/filelist/context-menu-actions.ts
Expand Up @@ -207,7 +207,7 @@ class ContextMenuActions {
}
};
(new AjaxRequest(url)).withQueryArguments(queryArguments).get().finally((): void => {
top.TYPO3.Backend.ContentContainer.refresh(true);
top.TYPO3.Backend.ContentContainer.refresh();
});
}

Expand All @@ -223,7 +223,7 @@ class ContextMenuActions {
}
};
(new AjaxRequest(url)).withQueryArguments(queryArguments).get().finally((): void => {
top.TYPO3.Backend.ContentContainer.refresh(true);
top.TYPO3.Backend.ContentContainer.refresh();
});
}

Expand All @@ -238,7 +238,7 @@ class ContextMenuActions {
}
};
(new AjaxRequest(url)).withQueryArguments(queryArguments).get().finally((): void => {
top.TYPO3.Backend.ContentContainer.refresh(true);
top.TYPO3.Backend.ContentContainer.refresh();
});
}

Expand All @@ -253,7 +253,7 @@ class ContextMenuActions {
}
};
(new AjaxRequest(url)).withQueryArguments(queryArguments).get().finally((): void => {
top.TYPO3.Backend.ContentContainer.refresh(true);
top.TYPO3.Backend.ContentContainer.refresh();
});
}

Expand Down
2 changes: 1 addition & 1 deletion Build/Sources/TypeScript/install/init-install.ts
@@ -1,2 +1,2 @@
self.TYPO3 = {};
self.TYPO3 = <typeof TYPO3>{};
(window as any).importShim('@typo3/install/install.js');
2 changes: 1 addition & 1 deletion Build/Sources/TypeScript/install/init-installer.ts
@@ -1,2 +1,2 @@
self.TYPO3 = {};
self.TYPO3 = <typeof TYPO3>{};
(window as any).importShim('@typo3/install/installer.js');
44 changes: 24 additions & 20 deletions Build/types/TYPO3/index.d.ts
Expand Up @@ -5,25 +5,29 @@
* Add types as you use them
*/
declare namespace TYPO3 {
export let Backend: any;
export let ExtensionManager: any;
export let FormEngine: any;
export let Icons: any;
export let InfoWindow: any;
export let LoginRefresh: any;
export let ModuleMenu: any;
export let MultiStepWizard: any;
export let Notification: any;
export let Modal: any;
export let OpendocsMenu: any;
export let Permissions: any;
export let Severity: any;
export let ShortcutMenu: any;
export let Storage: any;
export let Tooltip: any;
export let WindowManager: any;
export let Wizard: any;
export let WorkspacesMenu: any;
export let Backend: typeof import('@typo3/backend/viewport').default;
export let ExtensionManager: typeof import('@typo3/extensionmanager/main').default;
export let FORMEDITOR_APP: any; // @todo migrate to typescript, then use: InstanceType<import('@typo3/form/backend/form-editor').FormEditor>;
export let FORMMANAGER_APP: any; // @todo migrate to typescript, then use: InstanceType<import('@typo3/form/backend/form-manager').FormManager>;
export let FormEngine: typeof import('@typo3/backend/form-engine').default;
export let Icons: typeof import('@typo3/backend/icons').default;
export let InfoWindow: typeof import('@typo3/backend/info-window').default;
export let LoginRefresh: typeof import('@typo3/backend/login-refresh').default;
export namespace ModuleMenu {
export let App: typeof import('@typo3/backend/module-menu').default.App;
}
export let MultiStepWizard: typeof import('@typo3/backend/multi-step-wizard').default;
export let Notification: typeof import('@typo3/backend/notification').default;
export let Modal: typeof import('@typo3/backend/modal').default;
export let LiveSearch: typeof import('@typo3/backend/toolbar/live-search').default;
export let LiveSearchConfigurator: typeof import('@typo3/backend/live-search/live-search-configurator').default;
export let OpendocsMenu: typeof import('@typo3/opendocs/toolbar/opendocs-menu').default;
export let Severity: import('@typo3/backend/severity').default;
export let ShortcutMenu: typeof import('@typo3/backend/toolbar/shortcut-menu').default;
export let Tooltip: typeof import('@typo3/backend/tooltip').default;
export let WindowManager: typeof import('@typo3/backend/window-manager').default;
export let Wizard: typeof import('@typo3/backend/wizard').default;
export let WorkspacesMenu: typeof import('@typo3/workspaces/toolbar/workspaces-menu').default;
export let settings: any;
export const lang: { [key: string]: string };
export const configuration: any;
Expand Down Expand Up @@ -68,7 +72,7 @@ declare module '@typo3/ckeditor5-bundle' {

// type definition for global namespace object
interface Window {
TYPO3: any;
TYPO3: Partial<typeof TYPO3>;
require: (moduleName: string) => void;
list_frame: Window;
CKEditorInspector: any;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 51b843c

Please sign in to comment.