From 4da4827bcbcdd1ef163f635d9b29416ff272b0bb Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 12:48:14 -0500 Subject: Add JSDoc type annotations to project (rebased) --- ext/js/comm/cross-frame-api.js | 156 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 14 deletions(-) (limited to 'ext/js/comm/cross-frame-api.js') diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js index fe220f21..34f3f36a 100644 --- a/ext/js/comm/cross-frame-api.js +++ b/ext/js/comm/cross-frame-api.js @@ -16,34 +16,66 @@ * along with this program. If not, see . */ -import {EventDispatcher, EventListenerCollection, deserializeError, invokeMessageHandler, log, serializeError} from '../core.js'; +import {EventDispatcher, EventListenerCollection, invokeMessageHandler, log} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {yomitan} from '../yomitan.js'; +/** + * @augments EventDispatcher + */ class CrossFrameAPIPort extends EventDispatcher { + /** + * @param {?number} otherTabId + * @param {number} otherFrameId + * @param {chrome.runtime.Port} port + * @param {import('core').MessageHandlerMap} messageHandlers + */ constructor(otherTabId, otherFrameId, port, messageHandlers) { super(); + /** @type {?number} */ this._otherTabId = otherTabId; + /** @type {number} */ this._otherFrameId = otherFrameId; + /** @type {?chrome.runtime.Port} */ this._port = port; + /** @type {import('core').MessageHandlerMap} */ this._messageHandlers = messageHandlers; + /** @type {Map} */ this._activeInvocations = new Map(); + /** @type {number} */ this._invocationId = 0; + /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); } + /** @type {?number} */ get otherTabId() { return this._otherTabId; } + /** @type {number} */ get otherFrameId() { return this._otherFrameId; } + /** + * @throws {Error} + */ prepare() { + if (this._port === null) { throw new Error('Invalid state'); } this._eventListeners.addListener(this._port.onDisconnect, this._onDisconnect.bind(this)); this._eventListeners.addListener(this._port.onMessage, this._onMessage.bind(this)); } + /** + * @template [TParams=import('core').SerializableObject] + * @template [TReturn=unknown] + * @param {string} action + * @param {TParams} params + * @param {number} ackTimeout + * @param {number} responseTimeout + * @returns {Promise} + */ invoke(action, params, ackTimeout, responseTimeout) { return new Promise((resolve, reject) => { if (this._port === null) { @@ -52,6 +84,7 @@ class CrossFrameAPIPort extends EventDispatcher { } const id = this._invocationId++; + /** @type {import('cross-frame-api').Invocation} */ const invocation = { id, resolve, @@ -73,19 +106,21 @@ class CrossFrameAPIPort extends EventDispatcher { } try { - this._port.postMessage({type: 'invoke', id, data: {action, params}}); + this._port.postMessage(/** @type {import('cross-frame-api').InvokeMessage} */ ({type: 'invoke', id, data: {action, params}})); } catch (e) { this._onError(id, e); } }); } + /** */ disconnect() { this._onDisconnect(); } // Private + /** */ _onDisconnect() { if (this._port === null) { return; } this._eventListeners.removeAllEventListeners(); @@ -96,22 +131,29 @@ class CrossFrameAPIPort extends EventDispatcher { this.trigger('disconnect', this); } - _onMessage({type, id, data}) { + /** + * @param {import('cross-frame-api').Message} details + */ + _onMessage(details) { + const {type, id} = details; switch (type) { case 'invoke': - this._onInvoke(id, data); + this._onInvoke(id, details.data); break; case 'ack': this._onAck(id); break; case 'result': - this._onResult(id, data); + this._onResult(id, details.data); break; } } // Response handlers + /** + * @param {number} id + */ _onAck(id) { const invocation = this._activeInvocations.get(id); if (typeof invocation === 'undefined') { @@ -141,6 +183,10 @@ class CrossFrameAPIPort extends EventDispatcher { } } + /** + * @param {number} id + * @param {import('core').Response} data + */ _onResult(id, data) { const invocation = this._activeInvocations.get(id); if (typeof invocation === 'undefined') { @@ -162,17 +208,21 @@ class CrossFrameAPIPort extends EventDispatcher { const error = data.error; if (typeof error !== 'undefined') { - invocation.reject(deserializeError(error)); + invocation.reject(ExtensionError.deserialize(error)); } else { invocation.resolve(data.result); } } + /** + * @param {number} id + * @param {unknown} error + */ _onError(id, error) { const invocation = this._activeInvocations.get(id); if (typeof invocation === 'undefined') { return; } - if (typeof error === 'string') { + if (!(error instanceof Error)) { error = new Error(`${error} (${invocation.action})`); } @@ -186,6 +236,11 @@ class CrossFrameAPIPort extends EventDispatcher { // Invocation + /** + * @param {number} id + * @param {import('cross-frame-api').InvocationData} details + * @returns {boolean} + */ _onInvoke(id, {action, params}) { const messageHandler = this._messageHandlers.get(action); this._sendAck(id); @@ -194,10 +249,17 @@ class CrossFrameAPIPort extends EventDispatcher { return false; } + /** + * @param {import('core').Response} data + * @returns {void} + */ const callback = (data) => this._sendResult(id, data); return invokeMessageHandler(messageHandler, params, callback); } + /** + * @param {import('cross-frame-api').Message} data + */ _sendResponse(data) { if (this._port === null) { return; } try { @@ -207,45 +269,85 @@ class CrossFrameAPIPort extends EventDispatcher { } } + /** + * @param {number} id + */ _sendAck(id) { this._sendResponse({type: 'ack', id}); } + /** + * @param {number} id + * @param {import('core').Response} data + */ _sendResult(id, data) { this._sendResponse({type: 'result', id, data}); } + /** + * @param {number} id + * @param {Error} error + */ _sendError(id, error) { - this._sendResponse({type: 'result', id, data: {error: serializeError(error)}}); + this._sendResponse({type: 'result', id, data: {error: ExtensionError.serialize(error)}}); } } export class CrossFrameAPI { constructor() { + /** @type {number} */ this._ackTimeout = 3000; // 3 seconds + /** @type {number} */ this._responseTimeout = 10000; // 10 seconds + /** @type {Map>} */ this._commPorts = new Map(); + /** @type {import('core').MessageHandlerMap} */ this._messageHandlers = new Map(); + /** @type {(port: CrossFrameAPIPort) => void} */ this._onDisconnectBind = this._onDisconnect.bind(this); + /** @type {?number} */ this._tabId = null; + /** @type {?number} */ this._frameId = null; } + /** */ async prepare() { chrome.runtime.onConnect.addListener(this._onConnect.bind(this)); - ({tabId: this._tabId, frameId: this._frameId} = await yomitan.api.frameInformationGet()); + ({tabId: this._tabId = null, frameId: this._frameId = null} = await yomitan.api.frameInformationGet()); } - invoke(targetFrameId, action, params={}) { + /** + * @template [TParams=import('core').SerializableObject] + * @template [TReturn=unknown] + * @param {number} targetFrameId + * @param {string} action + * @param {TParams} params + * @returns {Promise} + */ + invoke(targetFrameId, action, params) { return this.invokeTab(null, targetFrameId, action, params); } - async invokeTab(targetTabId, targetFrameId, action, params={}) { + /** + * @template [TParams=import('core').SerializableObject] + * @template [TReturn=unknown] + * @param {?number} targetTabId + * @param {number} targetFrameId + * @param {string} action + * @param {TParams} params + * @returns {Promise} + */ + async invokeTab(targetTabId, targetFrameId, action, params) { if (typeof targetTabId !== 'number') { targetTabId = this._tabId; } const commPort = await this._getOrCreateCommPort(targetTabId, targetFrameId); return await commPort.invoke(action, params, this._ackTimeout, this._responseTimeout); } + /** + * @param {import('core').MessageHandlerArray} messageHandlers + * @throws {Error} + */ registerHandlers(messageHandlers) { for (const [key, value] of messageHandlers) { if (this._messageHandlers.has(key)) { @@ -255,12 +357,19 @@ export class CrossFrameAPI { } } + /** + * @param {string} key + * @returns {boolean} + */ unregisterHandler(key) { return this._messageHandlers.delete(key); } // Private + /** + * @param {chrome.runtime.Port} port + */ _onConnect(port) { try { let details; @@ -280,6 +389,9 @@ export class CrossFrameAPI { } } + /** + * @param {CrossFrameAPIPort} commPort + */ _onDisconnect(commPort) { commPort.off('disconnect', this._onDisconnectBind); const {otherTabId, otherFrameId} = commPort; @@ -292,7 +404,12 @@ export class CrossFrameAPI { } } - _getOrCreateCommPort(otherTabId, otherFrameId) { + /** + * @param {?number} otherTabId + * @param {number} otherFrameId + * @returns {Promise} + */ + async _getOrCreateCommPort(otherTabId, otherFrameId) { const tabPorts = this._commPorts.get(otherTabId); if (typeof tabPorts !== 'undefined') { const commPort = tabPorts.get(otherFrameId); @@ -300,9 +417,13 @@ export class CrossFrameAPI { return commPort; } } - return this._createCommPort(otherTabId, otherFrameId); + return await this._createCommPort(otherTabId, otherFrameId); } - + /** + * @param {?number} otherTabId + * @param {number} otherFrameId + * @returns {Promise} + */ async _createCommPort(otherTabId, otherFrameId) { await yomitan.api.openCrossFramePort(otherTabId, otherFrameId); @@ -313,8 +434,15 @@ export class CrossFrameAPI { return commPort; } } + throw new Error('Comm port didn\'t open'); } + /** + * @param {?number} otherTabId + * @param {number} otherFrameId + * @param {chrome.runtime.Port} port + * @returns {CrossFrameAPIPort} + */ _setupCommPort(otherTabId, otherFrameId, port) { const commPort = new CrossFrameAPIPort(otherTabId, otherFrameId, port, this._messageHandlers); let tabPorts = this._commPorts.get(otherTabId); -- cgit v1.2.3 From 14d12f6ba20b837a04c638b935773f3120e194ff Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 19:33:01 -0500 Subject: Update timer types and such --- dev/jsconfig.json | 2 +- ext/js/app/frontend.js | 11 +++++++++-- ext/js/background/backend.js | 4 ++-- ext/js/background/offscreen.js | 4 +++- ext/js/comm/api.js | 2 +- ext/js/comm/clipboard-monitor.js | 2 +- ext/js/comm/cross-frame-api.js | 21 +++++++++++++-------- ext/js/comm/frame-ancestry-handler.js | 2 +- ext/js/comm/frame-client.js | 2 +- ext/js/comm/mecab.js | 2 +- ext/js/core.js | 2 +- ext/js/display/display-audio.js | 2 +- ext/js/display/display-notification.js | 2 +- ext/js/display/display.js | 2 +- ext/js/display/element-overflow-controller.js | 8 ++++---- ext/js/display/option-toggle-hotkey-handler.js | 2 +- ext/js/display/search-display-controller.js | 2 +- ext/js/dom/document-util.js | 2 +- ext/js/dom/panel-element.js | 2 +- ext/js/language/text-scanner.js | 6 +++--- ext/js/media/audio-downloader.js | 2 +- ext/js/pages/settings/popup-preview-frame.js | 2 +- test/jsconfig.json | 2 +- types/ext/core.d.ts | 2 ++ types/ext/cross-frame-api.d.ts | 2 +- types/ext/offscreen.d.ts | 2 +- types/other/globals.d.ts | 22 ++++++++++++++++++++++ types/other/web-set-timeout.d.ts | 24 ------------------------ 28 files changed, 77 insertions(+), 63 deletions(-) create mode 100644 types/other/globals.d.ts delete mode 100644 types/other/web-set-timeout.d.ts (limited to 'ext/js/comm/cross-frame-api.js') diff --git a/dev/jsconfig.json b/dev/jsconfig.json index 518f97ad..d4efe694 100644 --- a/dev/jsconfig.json +++ b/dev/jsconfig.json @@ -71,7 +71,7 @@ "../ext/js/language/translator.js", "../ext/js/media/media-util.js", "../types/dev/**/*.ts", - "../types/other/web-set-timeout.d.ts" + "../types/other/globals.d.ts" ], "exclude": [ "../node_modules" diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js index 628c504e..e1f8d8c9 100644 --- a/ext/js/app/frontend.js +++ b/ext/js/app/frontend.js @@ -99,7 +99,7 @@ export class Frontend { this._popupEventListeners = new EventListenerCollection(); /** @type {?import('core').TokenObject} */ this._updatePopupToken = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._clearSelectionTimer = null; /** @type {boolean} */ this._isPointerOverPopup = false; @@ -840,7 +840,7 @@ export class Frontend { */ async _waitForFrontendReady(frameId, timeout) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timeoutId = null; const cleanup = () => { @@ -973,6 +973,13 @@ export class Frontend { await yomitan.api.loadExtensionScripts([ '/js/accessibility/google-docs-util.js' ]); + this._prepareGoogleDocs2(); + } + + /** + * @returns {Promise} + */ + async _prepareGoogleDocs2() { if (typeof GoogleDocsUtil === 'undefined') { return; } DocumentUtil.registerGetRangeFromPointHandler(GoogleDocsUtil.getRangeFromPoint.bind(GoogleDocsUtil)); } diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 44f5a42d..f1a47e7f 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -138,7 +138,7 @@ export class Backend { /** @type {?string} */ this._defaultBrowserActionTitle = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._badgePrepareDelayTimer = null; /** @type {?import('log').LogLevel} */ this._logErrorLevel = null; @@ -1981,7 +1981,7 @@ export class Backend { */ _waitUntilTabFrameIsReady(tabId, frameId, timeout=null) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; /** @type {?import('extension').ChromeRuntimeOnMessageCallback} */ let onMessage = (message, sender) => { diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index 45345c01..8da661ad 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -51,7 +51,7 @@ export class Offscreen { }); /** @type {import('offscreen').MessageHandlerMap} */ - this._messageHandlers = new Map([ + const messageHandlers = new Map([ ['clipboardGetTextOffscreen', {async: true, handler: this._getTextHandler.bind(this)}], ['clipboardGetImageOffscreen', {async: true, handler: this._getImageHandler.bind(this)}], ['clipboardSetBrowserOffscreen', {async: false, handler: this._setClipboardBrowser.bind(this)}], @@ -65,6 +65,8 @@ export class Offscreen { ['getTermFrequenciesOffscreen', {async: true, handler: this._getTermFrequenciesHandler.bind(this)}], ['clearDatabaseCachesOffscreen', {async: false, handler: this._clearDatabaseCachesHandler.bind(this)}] ]); + /** @type {import('offscreen').MessageHandlerMap} */ + this._messageHandlers = messageHandlers; const onMessage = this._onMessage.bind(this); chrome.runtime.onMessage.addListener(onMessage); diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js index 0cfdba59..26218595 100644 --- a/ext/js/comm/api.js +++ b/ext/js/comm/api.js @@ -431,7 +431,7 @@ export class API { */ _createActionPort(timeout) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const portDetails = deferPromise(); diff --git a/ext/js/comm/clipboard-monitor.js b/ext/js/comm/clipboard-monitor.js index 06e95438..3b3a56a9 100644 --- a/ext/js/comm/clipboard-monitor.js +++ b/ext/js/comm/clipboard-monitor.js @@ -31,7 +31,7 @@ export class ClipboardMonitor extends EventDispatcher { this._japaneseUtil = japaneseUtil; /** @type {import('clipboard-monitor').ClipboardReaderLike} */ this._clipboardReader = clipboardReader; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._timerId = null; /** @type {?import('core').TokenObject} */ this._timerToken = null; diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js index 34f3f36a..3ac38cf2 100644 --- a/ext/js/comm/cross-frame-api.js +++ b/ext/js/comm/cross-frame-api.js @@ -25,14 +25,14 @@ import {yomitan} from '../yomitan.js'; */ class CrossFrameAPIPort extends EventDispatcher { /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @param {chrome.runtime.Port} port * @param {import('core').MessageHandlerMap} messageHandlers */ constructor(otherTabId, otherFrameId, port, messageHandlers) { super(); - /** @type {?number} */ + /** @type {number} */ this._otherTabId = otherTabId; /** @type {number} */ this._otherFrameId = otherFrameId; @@ -48,7 +48,7 @@ class CrossFrameAPIPort extends EventDispatcher { this._eventListeners = new EventListenerCollection(); } - /** @type {?number} */ + /** @type {number} */ get otherTabId() { return this._otherTabId; } @@ -299,7 +299,7 @@ export class CrossFrameAPI { this._ackTimeout = 3000; // 3 seconds /** @type {number} */ this._responseTimeout = 10000; // 10 seconds - /** @type {Map>} */ + /** @type {Map>} */ this._commPorts = new Map(); /** @type {import('core').MessageHandlerMap} */ this._messageHandlers = new Map(); @@ -339,7 +339,12 @@ export class CrossFrameAPI { * @returns {Promise} */ async invokeTab(targetTabId, targetFrameId, action, params) { - if (typeof targetTabId !== 'number') { targetTabId = this._tabId; } + if (typeof targetTabId !== 'number') { + targetTabId = this._tabId; + if (typeof targetTabId !== 'number') { + throw new Error('Unknown target tab id for invocation'); + } + } const commPort = await this._getOrCreateCommPort(targetTabId, targetFrameId); return await commPort.invoke(action, params, this._ackTimeout, this._responseTimeout); } @@ -405,7 +410,7 @@ export class CrossFrameAPI { } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @returns {Promise} */ @@ -420,7 +425,7 @@ export class CrossFrameAPI { return await this._createCommPort(otherTabId, otherFrameId); } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @returns {Promise} */ @@ -438,7 +443,7 @@ export class CrossFrameAPI { } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @param {chrome.runtime.Port} port * @returns {CrossFrameAPIPort} diff --git a/ext/js/comm/frame-ancestry-handler.js b/ext/js/comm/frame-ancestry-handler.js index 49c96c22..687ec368 100644 --- a/ext/js/comm/frame-ancestry-handler.js +++ b/ext/js/comm/frame-ancestry-handler.js @@ -122,7 +122,7 @@ export class FrameAncestryHandler { const responseMessageId = `${this._responseMessageIdBase}${uniqueId}`; /** @type {number[]} */ const results = []; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const cleanup = () => { diff --git a/ext/js/comm/frame-client.js b/ext/js/comm/frame-client.js index 1519cf7f..8aa8c6d6 100644 --- a/ext/js/comm/frame-client.js +++ b/ext/js/comm/frame-client.js @@ -83,7 +83,7 @@ export class FrameClient { _connectInternal(frame, targetOrigin, hostFrameId, setupFrame, timeout) { return new Promise((resolve, reject) => { const tokenMap = new Map(); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const deferPromiseDetails = /** @type {import('core').DeferredPromiseDetails} */ (deferPromise()); const frameLoadedPromise = deferPromiseDetails.promise; diff --git a/ext/js/comm/mecab.js b/ext/js/comm/mecab.js index 072b42f3..0a87463b 100644 --- a/ext/js/comm/mecab.js +++ b/ext/js/comm/mecab.js @@ -31,7 +31,7 @@ export class Mecab { this._port = null; /** @type {number} */ this._sequence = 0; - /** @type {Map void, reject: (reason?: unknown) => void, timer: number}>} */ + /** @type {Map void, reject: (reason?: unknown) => void, timer: import('core').Timeout}>} */ this._invocations = new Map(); /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); diff --git a/ext/js/core.js b/ext/js/core.js index cdac2020..a53d5572 100644 --- a/ext/js/core.js +++ b/ext/js/core.js @@ -307,7 +307,7 @@ export function promiseAnimationFrame(timeout) { return; } - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; /** @type {?number} */ let frameRequest = null; diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index 3fbfc3c8..3576decb 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -36,7 +36,7 @@ export class DisplayAudio { this._playbackVolume = 1.0; /** @type {boolean} */ this._autoPlay = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._autoPlayAudioTimer = null; /** @type {number} */ this._autoPlayAudioDelay = 400; diff --git a/ext/js/display/display-notification.js b/ext/js/display/display-notification.js index b3f20700..d1cfa537 100644 --- a/ext/js/display/display-notification.js +++ b/ext/js/display/display-notification.js @@ -34,7 +34,7 @@ export class DisplayNotification { this._closeButton = /** @type {HTMLElement} */ (node.querySelector('.footer-notification-close-button')); /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._closeTimer = null; } diff --git a/ext/js/display/display.js b/ext/js/display/display.js index f14291d1..6e1450c3 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -117,7 +117,7 @@ export class Display extends EventDispatcher { this._queryOffset = 0; /** @type {HTMLElement} */ this._progressIndicator = /** @type {HTMLElement} */ (document.querySelector('#progress-indicator')); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._progressIndicatorTimer = null; /** @type {DynamicProperty} */ this._progressIndicatorVisible = new DynamicProperty(false); diff --git a/ext/js/display/element-overflow-controller.js b/ext/js/display/element-overflow-controller.js index 1d2c808f..35277fa5 100644 --- a/ext/js/display/element-overflow-controller.js +++ b/ext/js/display/element-overflow-controller.js @@ -22,7 +22,7 @@ export class ElementOverflowController { constructor() { /** @type {Element[]} */ this._elements = []; - /** @type {?number} */ + /** @type {?(number|import('core').Timeout)} */ this._checkTimer = null; /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); @@ -154,7 +154,7 @@ export class ElementOverflowController { /** * @param {() => void} callback * @param {number} timeout - * @returns {number} + * @returns {number|import('core').Timeout} */ _requestIdleCallback(callback, timeout) { if (typeof requestIdleCallback === 'function') { @@ -165,11 +165,11 @@ export class ElementOverflowController { } /** - * @param {number} handle + * @param {number|import('core').Timeout} handle */ _cancelIdleCallback(handle) { if (typeof cancelIdleCallback === 'function') { - cancelIdleCallback(handle); + cancelIdleCallback(/** @type {number} */ (handle)); } else { clearTimeout(handle); } diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js index 531e208d..edd7de5b 100644 --- a/ext/js/display/option-toggle-hotkey-handler.js +++ b/ext/js/display/option-toggle-hotkey-handler.js @@ -29,7 +29,7 @@ export class OptionToggleHotkeyHandler { this._display = display; /** @type {?import('./display-notification.js').DisplayNotification} */ this._notification = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._notificationHideTimer = null; /** @type {number} */ this._notificationHideTimeout = 5000; diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index b93757c2..98a4666b 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -63,7 +63,7 @@ export class SearchDisplayController { this._wanakanaBound = false; /** @type {boolean} */ this._introVisible = true; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._introAnimationTimer = null; /** @type {boolean} */ this._clipboardMonitorEnabled = false; diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js index cf58d39f..549a8195 100644 --- a/ext/js/dom/document-util.js +++ b/ext/js/dom/document-util.js @@ -360,7 +360,7 @@ export class DocumentUtil { /** * Adds a fullscreen change event listener. This function handles all of the browser-specific variants. * @param {EventListener} onFullscreenChanged The event callback. - * @param {?EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to. + * @param {?import('../core.js').EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to. */ static addFullscreenChangeEventListener(onFullscreenChanged, eventListenerCollection=null) { const target = document; diff --git a/ext/js/dom/panel-element.js b/ext/js/dom/panel-element.js index 314eb2fd..748c3a36 100644 --- a/ext/js/dom/panel-element.js +++ b/ext/js/dom/panel-element.js @@ -37,7 +37,7 @@ export class PanelElement extends EventDispatcher { this._mutationObserver = null; /** @type {boolean} */ this._visible = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._closeTimer = null; } diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index f6bcde8d..d1b033e6 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -120,7 +120,7 @@ export class TextScanner extends EventDispatcher { /** @type {boolean} */ this._preventNextClickScan = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._preventNextClickScanTimer = null; /** @type {number} */ this._preventNextClickScanTimerDuration = 50; @@ -145,7 +145,7 @@ export class TextScanner extends EventDispatcher { /** @type {boolean} */ this._canClearSelection = true; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._textSelectionTimer = null; /** @type {boolean} */ this._yomitanIsChangingTextSelectionNow = false; @@ -995,7 +995,7 @@ export class TextScanner extends EventDispatcher { async _scanTimerWait() { const delay = this._delay; const promise = /** @type {Promise} */ (new Promise((resolve) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timeout = setTimeout(() => { timeout = null; resolve(true); diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 0847d479..e041cc67 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -316,7 +316,7 @@ export class AudioDownloader { let signal; /** @type {?import('request-builder.js').ProgressCallback} */ let onProgress = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let idleTimer = null; if (typeof idleTimeout === 'number') { const abortController = new AbortController(); diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js index bb00829f..dab21f4d 100644 --- a/ext/js/pages/settings/popup-preview-frame.js +++ b/ext/js/pages/settings/popup-preview-frame.js @@ -43,7 +43,7 @@ export class PopupPreviewFrame { this._apiOptionsGetOld = null; /** @type {boolean} */ this._popupShown = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._themeChangeTimeout = null; /** @type {?import('text-source').TextSource} */ this._textSource = null; diff --git a/test/jsconfig.json b/test/jsconfig.json index 261ec345..934aab81 100644 --- a/test/jsconfig.json +++ b/test/jsconfig.json @@ -31,7 +31,7 @@ "../ext/**/*.js", "../types/ext/**/*.ts", "../types/dev/**/*.ts", - "../types/other/web-set-timeout.d.ts" + "../types/other/globals.d.ts" ], "exclude": [ "../node_modules", diff --git a/types/ext/core.d.ts b/types/ext/core.d.ts index ce3a09f0..b83e6a74 100644 --- a/types/ext/core.d.ts +++ b/types/ext/core.d.ts @@ -100,3 +100,5 @@ export type MessageHandlerDetails = { export type MessageHandlerMap = Map; export type MessageHandlerArray = [key: string, handlerDetails: MessageHandlerDetails][]; + +export type Timeout = number | NodeJS.Timeout; diff --git a/types/ext/cross-frame-api.d.ts b/types/ext/cross-frame-api.d.ts index 5cedbec9..88ce59a7 100644 --- a/types/ext/cross-frame-api.d.ts +++ b/types/ext/cross-frame-api.d.ts @@ -50,5 +50,5 @@ export type Invocation = { responseTimeout: number; action: string; ack: boolean; - timer: number | null; + timer: Core.Timeout | null; }; diff --git a/types/ext/offscreen.d.ts b/types/ext/offscreen.d.ts index 7dd64d1e..ddf7eadc 100644 --- a/types/ext/offscreen.d.ts +++ b/types/ext/offscreen.d.ts @@ -112,4 +112,4 @@ export type MessageHandler< details: MessageDetailsMap[TMessage], ) => (TIsAsync extends true ? Promise> : MessageReturn); -export type MessageHandlerMap = Map; +export type MessageHandlerMap = Map; diff --git a/types/other/globals.d.ts b/types/other/globals.d.ts new file mode 100644 index 00000000..330f16c2 --- /dev/null +++ b/types/other/globals.d.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +declare global { + function clearTimeout(timeoutId: NodeJS.Timeout | string | number | undefined): void; +} + +export {}; diff --git a/types/other/web-set-timeout.d.ts b/types/other/web-set-timeout.d.ts deleted file mode 100644 index 98e40dab..00000000 --- a/types/other/web-set-timeout.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2023 Yomitan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -declare module 'web-set-timeout' { - global { - // These types are used to ensure that setTimeout returns a number - function setTimeout(callback: (...args: TArgs) => void, ms?: number, ...args: TArgs): number; - function setTimeout(callback: (args: void) => void, ms?: number): number; - } -} -- cgit v1.2.3