diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index d910d30c..b4438f80 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -60,24 +60,20 @@ class PopupProxy extends EventDispatcher { return true; } - async setOptionsContext(optionsContext, source) { - return await this._invoke('setOptionsContext', {id: this._id, optionsContext, source}); + setOptionsContext(optionsContext, source) { + return this._invokeSafe('setOptionsContext', {id: this._id, optionsContext, source}); } hide(changeFocus) { - this._invoke('hide', {id: this._id, changeFocus}); + return this._invokeSafe('hide', {id: this._id, changeFocus}); } - async isVisible() { - try { - return await this._invoke('isVisible', {id: this._id}); - } catch (e) { - return false; - } + isVisible() { + return this._invokeSafe('isVisible', {id: this._id}, false); } setVisibleOverride(visible) { - this._invoke('setVisibleOverride', {id: this._id, visible}); + return this._invokeSafe('setVisibleOverride', {id: this._id, visible}); } async containsPoint(x, y) { @@ -85,7 +81,7 @@ class PopupProxy extends EventDispatcher { await this._updateFrameOffset(); [x, y] = this._applyFrameOffset(x, y); } - return await this._invoke('containsPoint', {id: this._id, x, y}); + return await this._invokeSafe('containsPoint', {id: this._id, x, y}, false); } async showContent(details, displayDetails) { @@ -98,23 +94,19 @@ class PopupProxy extends EventDispatcher { } details.elementRect = {x, y, width, height}; } - return await this._invoke('showContent', {id: this._id, details, displayDetails}); + return await this._invokeSafe('showContent', {id: this._id, details, displayDetails}); } setCustomCss(css) { - this._invoke('setCustomCss', {id: this._id, css}); + return this._invokeSafe('setCustomCss', {id: this._id, css}); } - async clearAutoPlayTimer() { - try { - await this._invoke('clearAutoPlayTimer', {id: this._id}); - } catch (e) { - // NOP - } + clearAutoPlayTimer() { + return this._invokeSafe('clearAutoPlayTimer', {id: this._id}); } setContentScale(scale) { - this._invoke('setContentScale', {id: this._id, scale}); + return this._invokeSafe('setContentScale', {id: this._id, scale}); } // Private @@ -123,6 +115,15 @@ class PopupProxy extends EventDispatcher { return api.crossFrame.invoke(this._parentFrameId, action, params); } + async _invokeSafe(action, params={}, defaultReturnValue) { + try { + return await this._invoke(action, params); + } catch (e) { + if (!yomichan.isExtensionUnloaded) { throw e; } + return defaultReturnValue; + } + } + async _updateFrameOffset() { const now = Date.now(); const firstRun = this._frameOffsetUpdatedAt === null; diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 281913c6..22672706 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -97,7 +97,7 @@ class Popup { this._options = await api.optionsGet(optionsContext); this.updateTheme(); - this._invokeApi('setOptionsContext', {optionsContext}); + this._invokeSafe('setOptionsContext', {optionsContext}); } hide(changeFocus) { @@ -146,25 +146,21 @@ class Popup { } if (displayDetails !== null) { - this._invokeApi('setContent', {details: displayDetails}); + this._invokeSafe('setContent', {details: displayDetails}); } } setCustomCss(css) { - this._invokeApi('setCustomCss', {css}); + this._invokeSafe('setCustomCss', {css}); } - async clearAutoPlayTimer() { - try { - await this._invokeApi('clearAutoPlayTimer'); - } catch (e) { - // NOP - } + clearAutoPlayTimer() { + this._invokeSafe('clearAutoPlayTimer'); } setContentScale(scale) { this._contentScale = scale; - this._invokeApi('setContentScale', {scale}); + this._invokeSafe('setContentScale', {scale}); } // Popup-only public functions @@ -266,7 +262,7 @@ class Popup { await frameClient.connect(this._frame, this._targetOrigin, this._frameId, setupFrame); // Configure - await this._invokeApi('configure', { + await this._invokeSafe('configure', { frameId: this._frameId, ownerFrameId: this._ownerFrameId, popupId: this._id, @@ -448,7 +444,7 @@ class Popup { return dark ? 'dark' : 'light'; } - async _invokeApi(action, params={}) { + async _invoke(action, params={}) { const contentWindow = this._frame.contentWindow; if (this._frameClient === null || !this._frameClient.isConnected() || contentWindow === null) { return; } @@ -456,7 +452,16 @@ class Popup { return await api.crossFrame.invoke(this._frameClient.frameId, 'popupMessage', message); } - _invokeWindowApi(action, params={}) { + async _invokeSafe(action, params={}, defaultReturnValue) { + try { + return await this._invoke(action, params); + } catch (e) { + if (!yomichan.isExtensionUnloaded) { throw e; } + return defaultReturnValue; + } + } + + _invokeWindow(action, params={}) { const contentWindow = this._frame.contentWindow; if (this._frameClient === null || !this._frameClient.isConnected() || contentWindow === null) { return; } @@ -465,7 +470,7 @@ class Popup { } _onExtensionUnloaded() { - this._invokeWindowApi('extensionUnloaded'); + this._invokeWindow('extensionUnloaded'); } _getFrameParentElement() { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index d1f92722..93272666 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -69,6 +69,7 @@ class Display extends EventDispatcher { this._historyChangeIgnore = false; this._historyHasChanged = false; this._navigationHeader = document.querySelector('#navigation-header'); + this._contentType = 'clear'; this._defaultTitle = 'Yomichan Search'; this._defaultTitleMaxLength = 1000; this._fullQuery = ''; @@ -393,6 +394,7 @@ class Display extends EventDispatcher { let asigned = false; const eventArgs = {type, urlSearchParams, token}; this._historyHasChanged = true; + this._contentType = type; this._mediaLoader.unloadAll(); switch (type) { case 'terms': @@ -416,8 +418,10 @@ class Display extends EventDispatcher { const stale = (this._setContentToken !== token); if (!stale) { if (!asigned) { + type = 'clear'; + this._contentType = type; const {content} = this._history; - eventArgs.type = 'clear'; + eventArgs.type = type; eventArgs.content = content; this.trigger('contentUpdating', eventArgs); this._clearContent(); @@ -451,10 +455,12 @@ class Display extends EventDispatcher { } _onExtensionUnloaded() { + const type = 'unloaded'; + if (this._contentType === type) { return; } const details = { focus: false, history: false, - params: {type: 'unloaded'}, + params: {type}, state: {}, content: {} };