From bf17ad4567b2c07638e7ade47f3b33343cda92f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 5 Jul 2021 18:29:34 +0200 Subject: [PATCH] Switching setVariable to a query and fixing error hangling in query mechanism --- front/src/Api/Events/IframeEvent.ts | 5 +- front/src/Api/IframeListener.ts | 48 ++++++++++--------- front/src/Api/iframe/room.ts | 4 +- .../src/Phaser/Game/SharedVariablesManager.ts | 5 +- front/src/iframe_api.ts | 24 +++++----- maps/tests/Variables/script.js | 6 ++- 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index a0e7717a..54319fd3 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -50,7 +50,6 @@ export type IframeEventMap = { getState: undefined; registerMenuCommand: MenuItemRegisterEvent; setTiles: SetTilesEvent; - setVariable: SetVariableEvent; }; export interface IframeEvent { type: T; @@ -93,6 +92,10 @@ export type IframeQueryMap = { query: undefined, answer: MapDataEvent, }, + setVariable: { + query: SetVariableEvent, + answer: void + } } export interface IframeQuery { diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index c74e68a7..ee969721 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -105,9 +105,6 @@ class IframeListener { private readonly _setTilesStream: Subject = new Subject(); public readonly setTilesStream = this._setTilesStream.asObservable(); - private readonly _setVariableStream: Subject = new Subject(); - public readonly setVariableStream = this._setVariableStream.asObservable(); - private readonly iframes = new Set(); private readonly iframeCloseCallbacks = new Map void)[]>(); private readonly scripts = new Map(); @@ -171,13 +168,7 @@ class IframeListener { return; } - Promise.resolve(answerer(query.data)).then((value) => { - iframe?.contentWindow?.postMessage({ - id: queryId, - type: query.type, - data: value - }, '*'); - }).catch(reason => { + const errorHandler = (reason: any) => { console.error('An error occurred while responding to an iFrame query.', reason); let reasonMsg: string; if (reason instanceof Error) { @@ -191,8 +182,31 @@ class IframeListener { type: query.type, error: reasonMsg } as IframeErrorAnswerEvent, '*'); - }); + }; + try { + Promise.resolve(answerer(query.data)).then((value) => { + iframe?.contentWindow?.postMessage({ + id: queryId, + type: query.type, + data: value + }, '*'); + }).catch(errorHandler); + } catch (reason) { + errorHandler(reason); + } + + if (isSetVariableIframeEvent(payload.query)) { + // Let's dispatch the message to the other iframes + for (iframe of this.iframes) { + if (iframe.contentWindow !== message.source) { + iframe.contentWindow?.postMessage({ + 'type': 'setVariable', + 'data': payload.query.data + }, '*'); + } + } + } } else if (isIframeEventWrapper(payload)) { if (payload.type === "showLayer" && isLayerEvent(payload.data)) { this._showLayerStream.next(payload.data); @@ -246,18 +260,6 @@ class IframeListener { handleMenuItemRegistrationEvent(payload.data); } else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) { this._setTilesStream.next(payload.data); - } else if (isSetVariableIframeEvent(payload)) { - this._setVariableStream.next(payload.data); - - // Let's dispatch the message to the other iframes - for (iframe of this.iframes) { - if (iframe.contentWindow !== message.source) { - iframe.contentWindow?.postMessage({ - 'type': 'setVariable', - 'data': payload.data - }, '*'); - } - } } } }, diff --git a/front/src/Api/iframe/room.ts b/front/src/Api/iframe/room.ts index 00d974dc..db639cd9 100644 --- a/front/src/Api/iframe/room.ts +++ b/front/src/Api/iframe/room.ts @@ -119,9 +119,9 @@ export class WorkadventureRoomCommands extends IframeApiContribution { variables.set(key, value); - sendToWorkadventure({ + return queryWorkadventure({ type: 'setVariable', data: { key, diff --git a/front/src/Phaser/Game/SharedVariablesManager.ts b/front/src/Phaser/Game/SharedVariablesManager.ts index aeb26d68..dfedcf80 100644 --- a/front/src/Phaser/Game/SharedVariablesManager.ts +++ b/front/src/Phaser/Game/SharedVariablesManager.ts @@ -14,7 +14,6 @@ interface Variable { export class SharedVariablesManager { private _variables = new Map(); - private iframeListenerSubscription: Subscription; private variableObjects: Map; constructor(private roomConnection: RoomConnection, private gameMap: GameMap) { @@ -28,7 +27,7 @@ export class SharedVariablesManager { } // When a variable is modified from an iFrame - this.iframeListenerSubscription = iframeListener.setVariableStream.subscribe((event) => { + iframeListener.registerAnswerer('setVariable', (event) => { const key = event.key; if (!this.variableObjects.has(key)) { @@ -75,7 +74,7 @@ export class SharedVariablesManager { } public close(): void { - this.iframeListenerSubscription.unsubscribe(); + iframeListener.unregisterAnswerer('setVariable'); } get variables(): Map { diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts index fb44738f..da2e922e 100644 --- a/front/src/iframe_api.ts +++ b/front/src/iframe_api.ts @@ -192,7 +192,18 @@ window.addEventListener( console.debug(payload); - if (isIframeAnswerEvent(payload)) { + if (isIframeErrorAnswerEvent(payload)) { + const queryId = payload.id; + const payloadError = payload.error; + + const resolver = answerPromises.get(queryId); + if (resolver === undefined) { + throw new Error('In Iframe API, got an error answer for a question that we have no track of.'); + } + resolver.reject(new Error(payloadError)); + + answerPromises.delete(queryId); + } else if (isIframeAnswerEvent(payload)) { const queryId = payload.id; const payloadData = payload.data; @@ -202,17 +213,6 @@ window.addEventListener( } resolver.resolve(payloadData); - answerPromises.delete(queryId); - } else if (isIframeErrorAnswerEvent(payload)) { - const queryId = payload.id; - const payloadError = payload.error; - - const resolver = answerPromises.get(queryId); - if (resolver === undefined) { - throw new Error('In Iframe API, got an error answer for a question that we have no track of.'); - } - resolver.reject(payloadError); - answerPromises.delete(queryId); } else if (isIframeResponseEventWrapper(payload)) { const payloadData = payload.data; diff --git a/maps/tests/Variables/script.js b/maps/tests/Variables/script.js index cef9818e..ea381018 100644 --- a/maps/tests/Variables/script.js +++ b/maps/tests/Variables/script.js @@ -2,8 +2,10 @@ WA.onInit().then(() => { console.log('Trying to read variable "doorOpened" whose default property is true. This should display "true".'); console.log('doorOpened', WA.room.loadVariable('doorOpened')); - console.log('Trying to set variable "not_exists". This should display an error in the console.') - WA.room.saveVariable('not_exists', 'foo'); + console.log('Trying to set variable "not_exists". This should display an error in the console, followed by a log saying the error was caught.') + WA.room.saveVariable('not_exists', 'foo').catch((e) => { + console.log('Successfully caught error: ', e); + }); console.log('Trying to set variable "config". This should work.'); WA.room.saveVariable('config', {'foo': 'bar'});