summaryrefslogtreecommitdiff
path: root/ext/js/display
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2023-12-29 00:02:14 -0500
committerGitHub <noreply@github.com>2023-12-29 05:02:14 +0000
commit8b68504b3b95d0647b4305a43d7b326b801e1936 (patch)
tree106cfa2eb67bb5630c40dc63a4b8d9b2e1d8fa6d /ext/js/display
parent6a072dfdacf26d309bf8cd570c05f4d4b57c9af2 (diff)
Display API safety (#479)
* Remove unused * Add TODOs * Rename * Initial setup * More updates * Simplify naming * Set up window API * Remove type * Move type * Update type
Diffstat (limited to 'ext/js/display')
-rw-r--r--ext/js/display/display-audio.js4
-rw-r--r--ext/js/display/display.js108
2 files changed, 57 insertions, 55 deletions
diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js
index cba9c43c..2df13306 100644
--- a/ext/js/display/display-audio.js
+++ b/ext/js/display/display-audio.js
@@ -89,7 +89,7 @@ export class DisplayAudio {
['playAudioFromSource', this._onHotkeyActionPlayAudioFromSource.bind(this)]
]);
this._display.registerDirectMessageHandlers([
- ['Display.clearAutoPlayTimer', this._onMessageClearAutoPlayTimer.bind(this)]
+ ['displayAudioClearAutoPlayTimer', this._onMessageClearAutoPlayTimer.bind(this)]
]);
/* eslint-enable no-multi-spaces */
this._display.on('optionsUpdated', this._onOptionsUpdated.bind(this));
@@ -260,7 +260,7 @@ export class DisplayAudio {
this.playAudio(this._display.selectedIndex, 0, source);
}
- /** */
+ /** @type {import('display').DirectApiHandler<'displayAudioClearAutoPlayTimer'>} */
_onMessageClearAutoPlayTimer() {
this.clearAutoPlayTimer();
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index 08f640d0..e3c92ee2 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -18,7 +18,9 @@
import {ThemeController} from '../app/theme-controller.js';
import {FrameEndpoint} from '../comm/frame-endpoint.js';
-import {DynamicProperty, EventDispatcher, EventListenerCollection, clone, deepEqual, invokeMessageHandler, log, promiseTimeout} from '../core.js';
+import {DynamicProperty, EventDispatcher, EventListenerCollection, clone, deepEqual, log, promiseTimeout} from '../core.js';
+import {invokeApiMapHandler} from '../core/api-map.js';
+import {ExtensionError} from '../core/extension-error.js';
import {PopupMenu} from '../dom/popup-menu.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {ScrollElement} from '../dom/scroll-element.js';
@@ -87,12 +89,10 @@ export class Display extends EventDispatcher {
contentManager: this._contentManager,
hotkeyHelpController: this._hotkeyHelpController
});
- /** @type {import('core').MessageHandlerMap} */
- this._messageHandlers = new Map();
- /** @type {import('core').MessageHandlerMap} */
- this._directMessageHandlers = new Map();
- /** @type {import('core').MessageHandlerMap} */
- this._windowMessageHandlers = new Map();
+ /** @type {import('display').DirectApiMap} */
+ this._directApiMap = new Map();
+ /** @type {import('display').WindowApiMap} */
+ this._windowApiMap = new Map();
/** @type {DisplayHistory} */
this._history = new DisplayHistory({clearable: true, useBrowserHistory: false});
/** @type {boolean} */
@@ -207,15 +207,15 @@ export class Display extends EventDispatcher {
['previousEntryDifferentDictionary', () => { this._focusEntryWithDifferentDictionary(-1, true); }]
]);
this.registerDirectMessageHandlers([
- ['Display.setOptionsContext', this._onMessageSetOptionsContext.bind(this)],
- ['Display.setContent', this._onMessageSetContent.bind(this)],
- ['Display.setCustomCss', this._onMessageSetCustomCss.bind(this)],
- ['Display.setContentScale', this._onMessageSetContentScale.bind(this)],
- ['Display.configure', this._onMessageConfigure.bind(this)],
- ['Display.visibilityChanged', this._onMessageVisibilityChanged.bind(this)]
+ ['displaySetOptionsContext', this._onMessageSetOptionsContext.bind(this)],
+ ['displaySetContent', this._onMessageSetContent.bind(this)],
+ ['displaySetCustomCss', this._onMessageSetCustomCss.bind(this)],
+ ['displaySetContentScale', this._onMessageSetContentScale.bind(this)],
+ ['displayConfigure', this._onMessageConfigure.bind(this)],
+ ['displayVisibilityChanged', this._onMessageVisibilityChanged.bind(this)]
]);
this.registerWindowMessageHandlers([
- ['Display.extensionUnloaded', this._onMessageExtensionUnloaded.bind(this)]
+ ['displayExtensionUnloaded', this._onMessageExtensionUnloaded.bind(this)]
]);
/* eslint-enable no-multi-spaces */
}
@@ -504,20 +504,20 @@ export class Display extends EventDispatcher {
}
/**
- * @param {import('core').MessageHandlerMapInit} handlers
+ * @param {import('display').DirectApiMapInit} handlers
*/
registerDirectMessageHandlers(handlers) {
for (const [name, handlerInfo] of handlers) {
- this._directMessageHandlers.set(name, handlerInfo);
+ this._directApiMap.set(name, handlerInfo);
}
}
/**
- * @param {import('core').MessageHandlerMapInit} handlers
+ * @param {import('display').WindowApiMapInit} handlers
*/
registerWindowMessageHandlers(handlers) {
for (const [name, handlerInfo] of handlers) {
- this._windowMessageHandlers.set(name, handlerInfo);
+ this._windowApiMap.set(name, handlerInfo);
}
}
@@ -635,22 +635,35 @@ export class Display extends EventDispatcher {
// Message handlers
/**
- * @param {import('frame-client').Message<import('display').MessageDetails>} data
- * @returns {import('core').MessageHandlerResult}
+ * @param {import('frame-client').Message<import('display').DirectApiMessageAny>} data
+ * @returns {Promise<import('display').DirectApiReturnAny>}
* @throws {Error}
*/
_onDirectMessage(data) {
- const {action, params} = this._authenticateMessageData(data);
- const handler = this._directMessageHandlers.get(action);
- if (typeof handler === 'undefined') {
- throw new Error(`Invalid action: ${action}`);
- }
-
- return handler(params);
+ return new Promise((resolve, reject) => {
+ const {action, params} = this._authenticateMessageData(data);
+ invokeApiMapHandler(
+ this._directApiMap,
+ action,
+ params,
+ [],
+ (result) => {
+ const {error} = result;
+ if (typeof error !== 'undefined') {
+ reject(ExtensionError.deserialize(error));
+ } else {
+ resolve(result.result);
+ }
+ },
+ () => {
+ reject(new Error(`Invalid action: ${action}`));
+ }
+ );
+ });
}
/**
- * @param {MessageEvent<import('frame-client').Message<import('display').MessageDetails>>} details
+ * @param {MessageEvent<import('frame-client').Message<import('display').WindowApiMessageAny>>} details
*/
_onWindowMessage({data}) {
let data2;
@@ -660,46 +673,37 @@ export class Display extends EventDispatcher {
return;
}
- const {action, params} = data2;
- const messageHandler = this._windowMessageHandlers.get(action);
- if (typeof messageHandler === 'undefined') { return; }
-
- const callback = () => {}; // NOP
- invokeMessageHandler(messageHandler, params, callback);
+ try {
+ const {action, params} = data2;
+ const callback = () => {}; // NOP
+ invokeApiMapHandler(this._directApiMap, action, params, [], callback);
+ } catch (e) {
+ // NOP
+ }
}
- /**
- * @param {{optionsContext: import('settings').OptionsContext}} details
- */
+ /** @type {import('display').DirectApiHandler<'displaySetOptionsContext'>} */
async _onMessageSetOptionsContext({optionsContext}) {
await this.setOptionsContext(optionsContext);
this.searchLast(true);
}
- /**
- * @param {{details: import('display').ContentDetails}} details
- */
+ /** @type {import('display').DirectApiHandler<'displaySetContent'>} */
_onMessageSetContent({details}) {
this.setContent(details);
}
- /**
- * @param {{css: string}} details
- */
+ /** @type {import('display').DirectApiHandler<'displaySetCustomCss'>} */
_onMessageSetCustomCss({css}) {
this.setCustomCss(css);
}
- /**
- * @param {{scale: number}} details
- */
+ /** @type {import('display').DirectApiHandler<'displaySetContentScale'>} */
_onMessageSetContentScale({scale}) {
this._setContentScale(scale);
}
- /**
- * @param {import('display').ConfigureMessageDetails} details
- */
+ /** @type {import('display').DirectApiHandler<'displayConfigure'>} */
async _onMessageConfigure({depth, parentPopupId, parentFrameId, childrenSupported, scale, optionsContext}) {
this._depth = depth;
this._parentPopupId = parentPopupId;
@@ -709,15 +713,13 @@ export class Display extends EventDispatcher {
await this.setOptionsContext(optionsContext);
}
- /**
- * @param {{value: boolean}} details
- */
+ /** @type {import('display').DirectApiHandler<'displayVisibilityChanged'>} */
_onMessageVisibilityChanged({value}) {
this._frameVisible = value;
this.trigger('frameVisibilityChange', {value});
}
- /** */
+ /** @type {import('display').WindowApiHandler<'displayExtensionUnloaded'>} */
_onMessageExtensionUnloaded() {
if (yomitan.isExtensionUnloaded) { return; }
yomitan.triggerExtensionUnloaded();