diff --git a/packages/api-browser/src/message-service.ts b/packages/api-browser/src/message-service.ts index 51bb14b..34f8cf6 100644 --- a/packages/api-browser/src/message-service.ts +++ b/packages/api-browser/src/message-service.ts @@ -2,32 +2,34 @@ import { distributeMessage } from './accessible-windows'; const listenerMap = new Map(); -const currentWindowId = (): string => { - return ssf.Window.getCurrentWindow().getId(); +const currentWindowId = (): Promise => { + return ssf.Window.getCurrentWindow() + .then(win => win.getId()); }; export class MessageService implements ssf.MessageService { static send(windowId: string, topic: string, message: any) { - const senderId = currentWindowId(); - - distributeMessage({ - senderId, - windowId, - topic, - message + currentWindowId().then(senderId => { + distributeMessage({ + senderId, + windowId, + topic, + message + }); }); } static subscribe(windowId: string, topic: string, listener: (message: string|object, sender: string) => void) { const receiveMessage = (event) => { - const thisId = currentWindowId(); - if ((windowId === '*' || windowId === event.data.senderId) - && (event.data.windowId === '*' || thisId === event.data.windowId) - && event.data.senderId !== thisId - && topic === event.data.topic) { - // Message intended for this window - listener(event.data.message, event.data.senderId); - } + currentWindowId().then(thisId => { + if ((windowId === '*' || windowId === event.data.senderId) + && (event.data.windowId === '*' || thisId === event.data.windowId) + && event.data.senderId !== thisId + && topic === event.data.topic) { + // Message intended for this window + listener(event.data.message, event.data.senderId); + } + }); }; window.addEventListener('message', receiveMessage, false); diff --git a/packages/api-browser/src/window.ts b/packages/api-browser/src/window.ts index bcf334a..e3949e3 100644 --- a/packages/api-browser/src/window.ts +++ b/packages/api-browser/src/window.ts @@ -12,7 +12,7 @@ const DEFAULT_OPTIONS = { height: 600 }; -let currentWindow = null; +let currentWindowPromise: Promise = null; const getWindowOffsets = (win) => { const xOffset = (win.outerWidth / 2); @@ -21,7 +21,7 @@ const getWindowOffsets = (win) => { }; export class Window extends Emitter implements ssf.WindowCore { - children: ssf.Window[]; + children: Window[]; innerWindow: any; id: string; @@ -30,35 +30,38 @@ export class Window extends Emitter implements ssf.WindowCore { this.children = []; if (!options) { + // Wrap existing window this.innerWindow = window; this.id = window.name; if (callback) { callback(this); } } else { + // Open a new window const winOptions = Object.assign({}, DEFAULT_OPTIONS, options); this.innerWindow = window.open(options.url, options.name, objectToFeaturesString(winOptions)); this.id = this.innerWindow.name; const [xOffset, yOffset] = getWindowOffsets(this.innerWindow); this.setPosition(options.x || (screen.width / 2) - xOffset, options.y || (screen.height / 2) - yOffset); - const currentWindow = Window.getCurrentWindow(); - const childClose = () => this.innerWindow.close(); - - this.innerWindow.addEventListener('beforeunload', () => { - const index = currentWindow.children.indexOf(this); - if (index !== -1) { - currentWindow.children.splice(index, 1); - currentWindow.innerWindow.removeEventListener('beforeunload', childClose); + Window.getCurrentWindow().then(currentWindow => { + const childClose = () => this.innerWindow.close(); + + this.innerWindow.addEventListener('beforeunload', () => { + const index = currentWindow.children.indexOf(this); + if (index !== -1) { + currentWindow.children.splice(index, 1); + currentWindow.innerWindow.removeEventListener('beforeunload', childClose); + } + removeAccessibleWindow(this.innerWindow.name); + }); + + if (options.child) { + currentWindow.children.push(this); + currentWindow.innerWindow.addEventListener('beforeunload', childClose); } - removeAccessibleWindow(this.innerWindow.name); + addAccessibleWindow(options.name, this.innerWindow); }); - - if (options.child) { - currentWindow.children.push(this); - currentWindow.innerWindow.addEventListener('beforeunload', childClose); - } - addAccessibleWindow(options.name, this.innerWindow); } if (callback) { @@ -165,7 +168,7 @@ export class Window extends Emitter implements ssf.WindowCore { } getChildWindows() { - return new Promise(resolve => resolve(this.children)); + return new Promise>(resolve => resolve(this.children)); } asPromise(fn: (...args: any[]) => any): Promise { @@ -178,13 +181,13 @@ export class Window extends Emitter implements ssf.WindowCore { }); } - static getCurrentWindow(callback?: (win: Window) => void, errorCallback?: (err?: any) => void) { - if (currentWindow) { - return currentWindow; + static getCurrentWindow(): Promise { + if (!currentWindowPromise) { + currentWindowPromise = new Promise((resolve, reject) => { + new Window(null, resolve, reject); + }); } - - currentWindow = new Window(null, callback, errorCallback); - return currentWindow; + return currentWindowPromise; } static wrap(win: BrowserWindow) { diff --git a/packages/api-demo/src/messaging/messaging-api-demo.js b/packages/api-demo/src/messaging/messaging-api-demo.js index ce7cfa0..5a44602 100644 --- a/packages/api-demo/src/messaging/messaging-api-demo.js +++ b/packages/api-demo/src/messaging/messaging-api-demo.js @@ -9,7 +9,9 @@ const appReady = ssf.app.ready(); appReady.then(() => { const windowDetailsId = document.getElementById('window-uuid'); - windowDetailsId.innerText = ssf.Window.getCurrentWindow().getId(); + ssf.Window.getCurrentWindow().then(win => { + windowDetailsId.innerText = win.getId(); + }); newWindowButton.onclick = () => { // Create a random hex string as the window name diff --git a/packages/api-electron/src/preload/window.ts b/packages/api-electron/src/preload/window.ts index bce68a1..96cca88 100644 --- a/packages/api-electron/src/preload/window.ts +++ b/packages/api-electron/src/preload/window.ts @@ -8,7 +8,7 @@ import { Emitter, Display } from 'containerjs-api-utility'; import { MessageService } from './message-service'; import { IpcMessages } from '../common/constants'; -let currentWindow = null; +let currentWindowPromise: Promise = null; const isUrlPattern = /^https?:\/\//i; export class Window extends Emitter implements ssf.Window { @@ -23,6 +23,7 @@ export class Window extends Emitter implements ssf.Window { }); if (!options) { + // Wrap existing window this.innerWindow = remote.getCurrentWindow(); this.id = String(this.innerWindow.id); if (callback) { @@ -31,6 +32,7 @@ export class Window extends Emitter implements ssf.Window { return this; } + // Open a new window const electronOptions = Object.assign({}, options); Display.getDisplayAlteredPosition(options.display, { x: options.x || 0, y: options.y || 0 }).then(({ x, y }) => { @@ -277,13 +279,13 @@ export class Window extends Emitter implements ssf.Window { }); } - static getCurrentWindow(callback: (win: Window) => void, errorCallback: (err?: any) => void) { - if (currentWindow) { - return currentWindow; + static getCurrentWindow(): Promise { + if (!currentWindowPromise) { + currentWindowPromise = new Promise((resolve, reject) => { + new Window(null, resolve, reject); + }); } - - currentWindow = new Window(null, callback, errorCallback); - return currentWindow; + return currentWindowPromise; } static wrap(win: Electron.BrowserWindow) { diff --git a/packages/api-openfin/src/window.ts b/packages/api-openfin/src/window.ts index b4690ad..395bb3f 100644 --- a/packages/api-openfin/src/window.ts +++ b/packages/api-openfin/src/window.ts @@ -3,7 +3,7 @@ import { MessageService } from './message-service'; import { createMainProcess } from './main-process'; import { Screen } from './screen'; -let currentWindow: Window = null; +let currentWindowPromise: Promise = null; const eventMap = { 'auth-requested': 'auth-requested', @@ -136,6 +136,7 @@ export class Window extends Emitter implements ssf.Window { }); if (!options) { + // Wrap existing window this.innerWindow = fin.desktop.Window.getCurrent(); this.id = `${this.innerWindow.uuid}:${this.innerWindow.name}`; if (callback) { @@ -144,6 +145,7 @@ export class Window extends Emitter implements ssf.Window { return this; } + // Open a new window const optionsCopy = Object.assign({}, options); const currentPosition: ssf.Position = { x: optionsCopy.x || 0, y: optionsCopy.y || 0 }; Display.getDisplayAlteredPosition(optionsCopy.display, currentPosition).then(({x, y}) => { @@ -170,7 +172,9 @@ export class Window extends Emitter implements ssf.Window { } } - fin.desktop.Window.getCurrent().getOptions((windowOptions) => { + const currentFinWindow = fin.desktop.Window.getCurrent(); + + currentFinWindow.getOptions((windowOptions) => { openFinOptions.preload = windowOptions.preload; const appOptions = { name: openFinOptions.name, @@ -186,7 +190,7 @@ export class Window extends Emitter implements ssf.Window { fin.desktop.InterApplicationBus.publish('ssf-new-window', { windowName: this.innerWindow.uuid, - parentName: options.child ? Window.getCurrentWindow().innerWindow.uuid : null + parentName: options.child ? currentFinWindow.uuid : null }); if (callback) { @@ -442,13 +446,13 @@ export class Window extends Emitter implements ssf.Window { MessageService.send(`${this.innerWindow.uuid}:${this.innerWindow.name}`, 'ssf-window-message', message); } - static getCurrentWindow(callback?: (win: Window) => void, errorCallback?: (err?: any) => void) { - if (currentWindow) { - return currentWindow; + static getCurrentWindow(): Promise { + if (!currentWindowPromise) { + currentWindowPromise = new Promise((resolve, reject) => { + new Window(null, resolve, reject); + }); } - - currentWindow = new Window(null, callback, errorCallback); - return currentWindow; + return currentWindowPromise; } static wrap(win: fin.OpenFinWindow) { diff --git a/packages/api-specification/interface/event-emitter.ts b/packages/api-specification/interface/event-emitter.ts index 93acf25..789ebb3 100644 --- a/packages/api-specification/interface/event-emitter.ts +++ b/packages/api-specification/interface/event-emitter.ts @@ -6,9 +6,11 @@ declare namespace ssf { * such as Window. * *
-   * ssf.Window.getCurrentWindow().on('focus', () => {
-   *  console.log('Window received focus');
-   * });
+   * ssf.Window.getCurrentWindow().then(win => {
+   *   win.on('focus', () => {
+   *    console.log('Window received focus');
+   *   });
+   * })
    * 
*/ abstract class EventEmitter { diff --git a/packages/api-specification/interface/window.ts b/packages/api-specification/interface/window.ts index a785e25..3c80082 100644 --- a/packages/api-specification/interface/window.ts +++ b/packages/api-specification/interface/window.ts @@ -186,7 +186,7 @@ declare namespace ssf { * @param errorCallback A callback that is called if window creation fails * @returns The window. */ - constructor(opts?: WindowOptions, callback?: (window: Window) => void, errorCallback?: () => void); + constructor(opts?: WindowOptions, callback?: (window: WindowCore) => void, errorCallback?: () => void); /** * Removes focus from the window. @@ -232,7 +232,7 @@ declare namespace ssf { * * @returns A promise that resolves to an array of child windows. */ - getChildWindows(): Promise>; + getChildWindows(): Promise>; /** * Gets the id of the window. @@ -260,7 +260,7 @@ declare namespace ssf { * * @returns The parent window. */ - getParentWindow(): Promise; + getParentWindow(): Promise; /** * Get the position of the window. @@ -353,20 +353,20 @@ declare namespace ssf { * *
      * // Close the current window
-     * ssf.Window.getCurrentWindow().close();
+     * ssf.Window.getCurrentWindow().then(win => {
+     *   win.close();
+     * });
      * 
* - * @param callback - Function that is called when the window is ready to be used (if newly created). - * @param errorCallback - Function that is called when the window wrapper could not be created. * @returns The window. */ - static getCurrentWindow(callback?: () => void, errorCallback?: () => void): Window; + static getCurrentWindow(): Promise; /** * Wraps a native container window with a ContainerJS window. * @param window The native window to wrap. */ - static wrap(window: Electron.BrowserWindow | fin.OpenFinWindow | BrowserWindow): Window; + static wrap(window: Electron.BrowserWindow | fin.OpenFinWindow | BrowserWindow): WindowCore; /** * Captures the current visible content for the given Window. Returns the image as a base64 encoded png string. @@ -405,6 +405,46 @@ declare namespace ssf { * See WindowEvent for a list of events. */ export class Window extends WindowCore { + /** + * Create a new window. + * @param opts A window options object + * @param callback A callback that is called if the window creation succeeds + * @param errorCallback A callback that is called if window creation fails + * @returns The window. + */ + constructor(opts?: WindowOptions, callback?: (window: WindowCore) => void, errorCallback?: () => void); + + /** + * Get the child windows of the window. + * + *
+     * // Close all child windows
+     * window.getChildWindows().then(children => {
+     *   children.forEach(child => {
+     *     child.close();
+     *   });
+     * });
+     * 
+ * + * @returns A promise that resolves to an array of child windows. + */ + getChildWindows(): Promise>; + + /** + * Get the parent of the window. Null will be returned if the window has no parent. + * + *
+     * // Send the parent window a message
+     * window.getParentWindow().then(parent => {
+     *   const parentId = parent.getId();
+     *   ssf.MessageService.send(parentId, 'greetings', 'Hello parent window');
+     * });
+     * 
+ * + * @returns The parent window. + */ + getParentWindow(): Promise; + /** * Flashes the window's frame and taskbar icon. * @param flag - Flag to start or stop the window flashing. @@ -571,6 +611,20 @@ declare namespace ssf { */ unmaximize(): Promise; + /** + * Gets the current window object. + * + *
+     * // Close the current window
+     * ssf.Window.getCurrentWindow().then(win => {
+     *   win.close();
+     * });
+     * 
+ * + * @returns The window. + */ + static getCurrentWindow(): Promise; + /** * Get the window object with a particular id. Returns null if no window with that id exists. * @param id The id of the window. diff --git a/packages/api-symphony-compatibility/src/mapping.ts b/packages/api-symphony-compatibility/src/mapping.ts index 4fd0edd..3647773 100644 --- a/packages/api-symphony-compatibility/src/mapping.ts +++ b/packages/api-symphony-compatibility/src/mapping.ts @@ -28,15 +28,17 @@ export namespace map { /** API defined at https://symphonyoss.atlassian.net/wiki/display/WGDWAPI/RegisterBoundsChange+API */ static registerBoundsChange(callback: Function) { - // Not fully implemented in containerjs, only listens to the current window, not its children as well - containerjsSsf.Window.getCurrentWindow().addListener('resize', () => { - containerjsSsf.Window.getCurrentWindow().getBounds().then((bounds) => { - callback(bounds); + containerjsSsf.Window.getCurrentWindow().then(win => { + // Not fully implemented in containerjs, only listens to the current window, not its children as well + win.addListener('resize', () => { + win.getBounds().then((bounds) => { + callback(bounds); + }); }); - }); - containerjsSsf.Window.getCurrentWindow().addListener('move', () => { - containerjsSsf.Window.getCurrentWindow().getBounds().then((bounds) => { - callback(bounds); + win.addListener('move', () => { + win.getBounds().then((bounds) => { + callback(bounds); + }); }); }); } diff --git a/packages/api-tests/test/messaging.spec.js b/packages/api-tests/test/messaging.spec.js index 0fb553c..c3b1c5c 100644 --- a/packages/api-tests/test/messaging.spec.js +++ b/packages/api-tests/test/messaging.spec.js @@ -43,7 +43,9 @@ describe('Messaging API', function(done) { }; ssf.app.ready().then(() => { ssf.MessageService.subscribe(id, topic, window.messageServiceFunction); - callback(ssf.Window.getCurrentWindow().getId()); + ssf.Window.getCurrentWindow().then(win => { + callback(win.getId()); + }); }); }; const unsubscribeScript = (id, topic, callback) => { diff --git a/packages/api-tests/test/window.core.spec.js b/packages/api-tests/test/window.core.spec.js index 80cb020..462eb71 100644 --- a/packages/api-tests/test/window.core.spec.js +++ b/packages/api-tests/test/window.core.spec.js @@ -42,9 +42,10 @@ const retrieveWebUrl = () => { const callAsyncWindowMethod = (method, ...args) => { const script = (method, args, callback) => { ssf.app.ready().then(() => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin[method](...args).then((data) => { - callback(data); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin[method](...args).then((data) => { + callback(data); + }); }); }); }; @@ -54,8 +55,9 @@ const callAsyncWindowMethod = (method, ...args) => { const callWindowMethod = (method, ...args) => { const script = (method, args, callback) => { ssf.app.ready().then(() => { - var currentWin = ssf.Window.getCurrentWindow(); - callback(currentWin[method](...args)); + ssf.Window.getCurrentWindow().then(currentWin => { + callback(currentWin[method](...args)); + }); }); }; @@ -64,9 +66,10 @@ const callWindowMethod = (method, ...args) => { const getChildWindowsCount = () => { const script = (callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.getChildWindows().then((wins) => { - callback(wins.length); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.getChildWindows().then((wins) => { + callback(wins.length); + }); }); }; return executeAsyncJavascript(app.client, script); @@ -113,9 +116,10 @@ describe('WindowCore API', function(done) { const addWindowListener = (event) => { const script = (event, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.addListener(event, () => console.log(event)); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.addListener(event, () => console.log(event)); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; @@ -264,10 +268,11 @@ describe('WindowCore API', function(done) { const getParentWindowTitle = () => { const script = (callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.getParentWindow().then((parent) => { - parent.getTitle().then((title) => { - callback(title); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.getParentWindow().then((parent) => { + parent.getTitle().then((title) => { + callback(title); + }); }); }); }; @@ -403,11 +408,12 @@ describe('WindowCore API', function(done) { // We MUST run the callback before we call loadURL otherwise webdriver loses the context const executeLoadURL = (url) => { const script = (url, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - setTimeout(() => { - currentWin.loadURL(url); - }, 100); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + setTimeout(() => { + currentWin.loadURL(url); + }, 100); + callback(); + }); }; return executeAsyncJavascript(app.client, script, url); }; @@ -432,9 +438,10 @@ describe('WindowCore API', function(done) { const addWindowListener = (event) => { const script = (event, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.on(event, () => console.log(event)); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.on(event, () => console.log(event)); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; @@ -464,9 +471,10 @@ describe('WindowCore API', function(done) { const addWindowListener = (event) => { const script = (event, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.once(event, () => console.log(event)); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.once(event, () => console.log(event)); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; @@ -498,18 +506,20 @@ describe('WindowCore API', function(done) { const script = (event, callback) => { // We need to save the function, as we need to pass the same function object to removeListener window.customListener = () => console.log(event); - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.addListener(event, window.customListener); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.addListener(event, window.customListener); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; const removeWindowListener = (event) => { const script = (event, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.removeListener(event, window.customListener); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.removeListener(event, window.customListener); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; @@ -534,18 +544,20 @@ describe('WindowCore API', function(done) { const addWindowListener = (event, data) => { const script = (event, data, callback) => { // We need to save the function, as we need to pass the same function object to removeListener - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.addListener(event, () => console.log(event + data)); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.addListener(event, () => console.log(event + data)); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event, data); }; const removeWindowListeners = (event) => { const script = (event, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.removeAllListeners(event); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.removeAllListeners(event); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; @@ -574,18 +586,20 @@ describe('WindowCore API', function(done) { const addWindowListener = (event, data) => { const script = (event, data, callback) => { // We need to save the function, as we need to pass the same function object to removeListener - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.addListener(event, () => console.log(event + data)); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.addListener(event, () => console.log(event + data)); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event, data); }; const removeWindowListeners = () => { const script = (callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin.removeAllListeners(); - callback(); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.removeAllListeners(); + callback(); + }); }; return executeAsyncJavascript(app.client, script); }; @@ -674,9 +688,11 @@ describe('WindowCore API', function(done) { const wrapScript = (callback) => { ssf.app.ready().then(() => { - const inner = ssf.Window.getCurrentWindow().innerWindow; - const win = ssf.Window.wrap(inner); - callback(win.innerWindow != null); + ssf.Window.getCurrentWindow().then(currentWin => { + const inner = currentWin.innerWindow; + const win = ssf.Window.wrap(inner); + callback(win.innerWindow != null); + }); }); }; @@ -755,12 +771,12 @@ describe('WindowCore API', function(done) { // Track the calls to the event listener var eventName = `evt_${event}_count`; window[eventName] = []; - var currentWin = ssf.Window.getCurrentWindow(); - - currentWin.addListener(event, evt => { - window[eventName].push(evt.data); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin.addListener(event, evt => { + window[eventName].push(evt.data); + }); + callback(); }); - callback(); }; return executeAsyncJavascript(app.client, script, event); }; @@ -842,9 +858,10 @@ describe('WindowCore API', function(done) { const addListener = (event) => { const script = (event, callback) => { - const currentWindow = ssf.Window.getCurrentWindow(); - currentWindow.addListener(event, () => { window.listenEventResult = true; }); - callback(); + ssf.Window.getCurrentWindow().then(currentWindow => { + currentWindow.addListener(event, () => { window.listenEventResult = true; }); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); }; diff --git a/packages/api-tests/test/window.spec.js b/packages/api-tests/test/window.spec.js index 5947327..e339b5b 100644 --- a/packages/api-tests/test/window.spec.js +++ b/packages/api-tests/test/window.spec.js @@ -35,9 +35,10 @@ const initialisePositionSteps = () => [ const callAsyncWindowMethod = (method, ...args) => { const script = (method, args, callback) => { - var currentWin = ssf.Window.getCurrentWindow(); - currentWin[method](...args).then((data) => { - callback(data); + ssf.Window.getCurrentWindow().then(currentWin => { + currentWin[method](...args).then((data) => { + callback(data); + }); }); }; return executeAsyncJavascript(app.client, script, method, args); @@ -744,9 +745,10 @@ if (process.env.MOCHA_CONTAINER !== 'browser') { describe('Event Listeners', function() { const addListener = (event) => { const script = (event, callback) => { - const currentWindow = ssf.Window.getCurrentWindow(); - currentWindow.addListener(event, () => { window.listenEventResult = true; }); - callback(); + ssf.Window.getCurrentWindow().then(currentWindow => { + currentWindow.addListener(event, () => { window.listenEventResult = true; }); + callback(); + }); }; return executeAsyncJavascript(app.client, script, event); };