aboutsummaryrefslogtreecommitdiff
path: root/ext/js/application.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/application.js')
-rw-r--r--ext/js/application.js59
1 files changed, 39 insertions, 20 deletions
diff --git a/ext/js/application.js b/ext/js/application.js
index 350a4210..ec5c7e02 100644
--- a/ext/js/application.js
+++ b/ext/js/application.js
@@ -52,6 +52,41 @@ if (checkChromeNotAvailable()) {
}
/**
+ * @param {WebExtension} webExtension
+ */
+async function waitForBackendReady(webExtension) {
+ const {promise, resolve} = /** @type {import('core').DeferredPromiseDetails<void>} */ (deferPromise());
+ /** @type {import('application').ApiMap} */
+ const apiMap = createApiMap([['applicationBackendReady', () => { resolve(); }]]);
+ /** @type {import('extension').ChromeRuntimeOnMessageCallback<import('application').ApiMessageAny>} */
+ const onMessage = ({action, params}, _sender, callback) => invokeApiMapHandler(apiMap, action, params, [], callback);
+ chrome.runtime.onMessage.addListener(onMessage);
+ try {
+ await webExtension.sendMessagePromise({action: 'requestBackendReadySignal'});
+ await promise;
+ } finally {
+ chrome.runtime.onMessage.removeListener(onMessage);
+ }
+}
+
+/**
+ * @returns {Promise<void>}
+ */
+function waitForDomContentLoaded() {
+ return new Promise((resolve) => {
+ if (document.readyState !== 'loading') {
+ resolve();
+ return;
+ }
+ const onDomContentLoaded = () => {
+ document.removeEventListener('DOMContentLoaded', onDomContentLoaded);
+ resolve();
+ };
+ document.addEventListener('DOMContentLoaded', onDomContentLoaded);
+ });
+}
+
+/**
* The Yomitan class is a core component through which various APIs are handled and invoked.
* @augments EventDispatcher<import('application').Events>
*/
@@ -151,18 +186,20 @@ export class Application extends EventDispatcher {
}
/**
+ * @param {boolean} waitForDom
* @param {(application: Application) => (Promise<void>)} mainFunction
*/
- static async main(mainFunction) {
+ static async main(waitForDom, mainFunction) {
const webExtension = new WebExtension();
log.configure(webExtension.extensionName);
const api = new API(webExtension);
- await this.waitForBackendReady(webExtension);
+ await waitForBackendReady(webExtension);
const {tabId, frameId} = await api.frameInformationGet();
const crossFrameApi = new CrossFrameAPI(api, tabId, frameId);
crossFrameApi.prepare();
const application = new Application(api, crossFrameApi);
application.prepare();
+ if (waitForDom) { await waitForDomContentLoaded(); }
try {
await mainFunction(application);
} catch (error) {
@@ -172,24 +209,6 @@ export class Application extends EventDispatcher {
}
}
- /**
- * @param {WebExtension} webExtension
- */
- static async waitForBackendReady(webExtension) {
- const {promise, resolve} = /** @type {import('core').DeferredPromiseDetails<void>} */ (deferPromise());
- /** @type {import('application').ApiMap} */
- const apiMap = createApiMap([['applicationBackendReady', () => { resolve(); }]]);
- /** @type {import('extension').ChromeRuntimeOnMessageCallback<import('application').ApiMessageAny>} */
- const onMessage = ({action, params}, _sender, callback) => invokeApiMapHandler(apiMap, action, params, [], callback);
- chrome.runtime.onMessage.addListener(onMessage);
- try {
- await webExtension.sendMessagePromise({action: 'requestBackendReadySignal'});
- await promise;
- } finally {
- chrome.runtime.onMessage.removeListener(onMessage);
- }
- }
-
// Private
/**