From c967b7a9f13ab7c3e0fe47e83fe5f05debf3aa73 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Thu, 3 Oct 2019 20:22:12 -0400 Subject: Remove event listeners when scanning is disabled --- ext/fg/js/frontend.js | 73 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 58dc0e4a..78f94cd9 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -38,6 +38,9 @@ class Frontend { this.mouseDownPrevent = false; this.clickPrevent = false; this.scrollPrevent = false; + + this.enabled = false; + this.eventListeners = []; } static create() { @@ -53,23 +56,7 @@ class Frontend { async prepare() { try { - this.options = await apiOptionsGet(this.getOptionsContext()); - - window.addEventListener('message', this.onWindowMessage.bind(this)); - window.addEventListener('mousedown', this.onMouseDown.bind(this)); - window.addEventListener('mousemove', this.onMouseMove.bind(this)); - window.addEventListener('mouseover', this.onMouseOver.bind(this)); - window.addEventListener('mouseout', this.onMouseOut.bind(this)); - window.addEventListener('resize', this.onResize.bind(this)); - - if (this.options.scanning.touchInputEnabled) { - window.addEventListener('click', this.onClick.bind(this)); - window.addEventListener('touchstart', this.onTouchStart.bind(this)); - window.addEventListener('touchend', this.onTouchEnd.bind(this)); - window.addEventListener('touchcancel', this.onTouchCancel.bind(this)); - window.addEventListener('touchmove', this.onTouchMove.bind(this), {passive: false}); - window.addEventListener('contextmenu', this.onContextMenu.bind(this)); - } + await this.updateOptions(); chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this)); } catch (e) { @@ -88,7 +75,6 @@ class Frontend { if ( this.pendingLookup || - !this.options.general.enable || (e.buttons & 0x1) !== 0x0 // Left mouse button ) { return; @@ -245,13 +231,56 @@ class Frontend { console.log(error); } - async updateOptions() { - this.options = await apiOptionsGet(this.getOptionsContext()); - if (!this.options.enable) { + setEnabled(enabled) { + if (enabled) { + if (!this.enabled) { + this.hookEvents(); + this.enabled = true; + } + } else { + if (this.enabled) { + this.clearEventListeners(); + this.enabled = false; + } this.searchClear(false); } } + hookEvents() { + this.addEventListener(window, 'message', this.onWindowMessage.bind(this)); + this.addEventListener(window, 'mousedown', this.onMouseDown.bind(this)); + this.addEventListener(window, 'mousemove', this.onMouseMove.bind(this)); + this.addEventListener(window, 'mouseover', this.onMouseOver.bind(this)); + this.addEventListener(window, 'mouseout', this.onMouseOut.bind(this)); + this.addEventListener(window, 'resize', this.onResize.bind(this)); + + if (this.options.scanning.touchInputEnabled) { + this.addEventListener(window, 'click', this.onClick.bind(this)); + this.addEventListener(window, 'touchstart', this.onTouchStart.bind(this)); + this.addEventListener(window, 'touchend', this.onTouchEnd.bind(this)); + this.addEventListener(window, 'touchcancel', this.onTouchCancel.bind(this)); + this.addEventListener(window, 'touchmove', this.onTouchMove.bind(this), {passive: false}); + this.addEventListener(window, 'contextmenu', this.onContextMenu.bind(this)); + } + } + + addEventListener(node, type, listener, options) { + node.addEventListener(type, listener, options); + this.eventListeners.push([node, type, listener, options]); + } + + clearEventListeners() { + for (const [node, type, listener, options] of this.eventListeners) { + node.removeEventListener(type, listener, options); + } + this.eventListeners = []; + } + + async updateOptions() { + this.options = await apiOptionsGet(this.getOptionsContext()); + this.setEnabled(this.options.general.enable); + } + popupTimerSet(callback) { const delay = this.options.scanning.delay; if (delay > 0) { @@ -452,7 +481,7 @@ class Frontend { searchFromTouch(x, y, cause) { this.popupTimerClear(); - if (!this.options.general.enable || this.pendingLookup) { + if (this.pendingLookup) { return; } -- cgit v1.2.3 From 2255fadf52bff17d183f48e0bc72a078568481f2 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 5 Oct 2019 21:38:13 -0400 Subject: Rename Popup.setVisible to setVisibleOverride --- ext/fg/js/frontend.js | 4 ++-- ext/fg/js/popup-proxy-host.js | 6 +++--- ext/fg/js/popup-proxy.js | 4 ++-- ext/fg/js/popup.js | 2 +- ext/mixed/js/display.js | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 58dc0e4a..3fa70357 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -527,8 +527,8 @@ Frontend.runtimeMessageHandlers = { self.updateOptions(); }, - popupSetVisible: (self, {visible}) => { - self.popup.setVisible(visible); + popupSetVisibleOverride: (self, {visible}) => { + self.popup.setVisibleOverride(visible); } }; diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index cb9741be..7fad71c1 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -41,7 +41,7 @@ class PopupProxyHost { show: ({id, elementRect, options}) => this.show(id, elementRect, options), showOrphaned: ({id, elementRect, options}) => this.show(id, elementRect, options), hide: ({id, changeFocus}) => this.hide(id, changeFocus), - setVisible: ({id, visible}) => this.setVisible(id, visible), + setVisibleOverride: ({id, visible}) => this.setVisibleOverride(id, visible), containsPoint: ({id, x, y}) => this.containsPoint(id, x, y), termsShow: ({id, elementRect, writingMode, definitions, options, context}) => this.termsShow(id, elementRect, writingMode, definitions, options, context), kanjiShow: ({id, elementRect, writingMode, definitions, options, context}) => this.kanjiShow(id, elementRect, writingMode, definitions, options, context), @@ -103,9 +103,9 @@ class PopupProxyHost { return popup.hide(changeFocus); } - async setVisible(id, visible) { + async setVisibleOverride(id, visible) { const popup = this.getPopup(id); - return popup.setVisible(visible); + return popup.setVisibleOverride(visible); } async containsPoint(id, x, y) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 072cebc9..99b28549 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -65,9 +65,9 @@ class PopupProxy { return await this.invokeHostApi('hide', {id: this.id, changeFocus}); } - async setVisible(visible) { + async setVisibleOverride(visible) { const id = await this.getPopupId(); - return await this.invokeHostApi('setVisible', {id, visible}); + return await this.invokeHostApi('setVisibleOverride', {id, visible}); } async containsPoint(x, y) { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 9dff6f28..5509c98c 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -238,7 +238,7 @@ class Popup { return this.isInjected && this.container.style.visibility !== 'hidden'; } - setVisible(visible) { + setVisibleOverride(visible) { if (visible) { this.container.style.setProperty('display', ''); } else { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index dc64dbea..b70fa4b8 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -445,7 +445,7 @@ class Display { async getScreenshot() { try { - await this.setPopupVisible(false); + await this.setPopupVisibleOverride(false); await Display.delay(1); // Wait for popup to be hidden. const {format, quality} = this.options.anki.screenshot; @@ -454,7 +454,7 @@ class Display { return {dataUrl, format}; } finally { - await this.setPopupVisible(true); + await this.setPopupVisibleOverride(true); } } @@ -462,8 +462,8 @@ class Display { return this.options.general.resultOutputMode === 'merge' ? 0 : -1; } - setPopupVisible(visible) { - return apiForward('popupSetVisible', {visible}); + setPopupVisibleOverride(visible) { + return apiForward('popupSetVisibleOverride', {visible}); } setSpinnerVisible(visible) { -- cgit v1.2.3 From cd6d4e7ee14b3bfde9efb76eb65d7ee91c740c77 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 5 Oct 2019 21:57:13 -0400 Subject: Update how popup visibility works --- ext/fg/js/popup.js | 49 ++++++++++++++++++++++++------------------------- ext/mixed/js/display.js | 2 +- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 5509c98c..9ca91afa 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -34,6 +34,9 @@ class Popup { this.container.style.height = '0px'; this.injectPromise = null; this.isInjected = false; + this.visible = false; + this.visibleOverride = null; + this.updateVisibility(); } inject(options) { @@ -105,9 +108,11 @@ class Popup { container.style.top = `${y}px`; container.style.width = `${width}px`; container.style.height = `${height}px`; - container.style.visibility = 'visible'; - this.hideChildren(true); + this.setVisible(true); + if (this.child !== null) { + this.child.hide(true); + } } static getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, optionsGeneral) { @@ -209,41 +214,35 @@ class Popup { } hide(changeFocus) { - if (this.isContainerHidden()) { - changeFocus = false; + if (!this.isVisible()) { + return; + } + + this.setVisible(false); + if (this.child !== null) { + this.child.hide(false); } - this.hideChildren(changeFocus); - this.hideContainer(); if (changeFocus) { this.focusParent(); } } - hideChildren(changeFocus) { - // Recursively hides all children. - if (this.child !== null && !this.child.isContainerHidden()) { - this.child.hide(changeFocus); - } - } - - hideContainer() { - this.container.style.visibility = 'hidden'; + isVisible() { + return this.isInjected && (this.visibleOverride !== null ? this.visibleOverride : this.visible); } - isContainerHidden() { - return (this.container.style.visibility === 'hidden'); + setVisible(visible) { + this.visible = visible; + this.updateVisibility(); } - isVisible() { - return this.isInjected && this.container.style.visibility !== 'hidden'; + setVisibleOverride(visible) { + this.visibleOverride = visible; + this.updateVisibility(); } - setVisibleOverride(visible) { - if (visible) { - this.container.style.setProperty('display', ''); - } else { - this.container.style.setProperty('display', 'none', 'important'); - } + updateVisibility() { + this.container.style.setProperty('visibility', this.isVisible() ? 'visible' : 'hidden', 'important'); } focusParent() { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index b70fa4b8..575011fd 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -454,7 +454,7 @@ class Display { return {dataUrl, format}; } finally { - await this.setPopupVisibleOverride(true); + await this.setPopupVisibleOverride(null); } } -- cgit v1.2.3 From 113cc725c1764e5eb814a22ace23a7e7150d016f Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 5 Oct 2019 22:11:05 -0400 Subject: Make the window.onresize handler not change focus --- ext/fg/js/frontend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/fg/js') diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 3fa70357..4ad78aa7 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -145,7 +145,7 @@ class Frontend { } onResize() { - this.searchClear(true); + this.searchClear(false); } onClick(e) { -- cgit v1.2.3 From 88de4271843197d37243a9ac360236f9dfb414e1 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 7 Oct 2019 20:46:02 -0400 Subject: Throw Error instead of string --- ext/bg/js/anki.js | 2 +- ext/bg/js/backend.js | 2 +- ext/bg/js/database.js | 60 +++++++++++++++++-------------------------- ext/fg/js/popup-proxy-host.js | 2 +- ext/mixed/js/display.js | 6 ++--- ext/mixed/js/extension.js | 2 +- 6 files changed, 30 insertions(+), 44 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/bg/js/anki.js b/ext/bg/js/anki.js index bd4e46cd..5c89aad8 100644 --- a/ext/bg/js/anki.js +++ b/ext/bg/js/anki.js @@ -67,7 +67,7 @@ class AnkiConnect { if (this.remoteVersion < this.localVersion) { this.remoteVersion = await this.ankiInvoke('version'); if (this.remoteVersion < this.localVersion) { - throw 'Extension and plugin versions incompatible'; + throw new Error('Extension and plugin versions incompatible'); } } } diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index 3c5ad885..fb77b71e 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -75,7 +75,7 @@ class Backend { const promise = handler(params, sender); promise .then(result => callback({result})) - .catch(error => callback({error: typeof error.toString === 'function' ? error.toString() : error})); + .catch(error => callback(errorToJson(error))); } return true; diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js index c812dee8..771a71c9 100644 --- a/ext/bg/js/database.js +++ b/ext/bg/js/database.js @@ -25,7 +25,7 @@ class Database { async prepare() { if (this.db) { - throw 'Database already initialized'; + throw new Error('Database already initialized'); } this.db = new Dexie('dict'); @@ -48,9 +48,7 @@ class Database { } async purge() { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); this.db.close(); await this.db.delete(); @@ -61,9 +59,7 @@ class Database { } async findTerms(term, titles) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => { @@ -107,9 +103,7 @@ class Database { } async findTermsExact(term, reading, titles) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.terms.where('expression').equals(term).each(row => { @@ -122,9 +116,7 @@ class Database { } async findTermsBySequence(sequence, mainDictionary) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.terms.where('sequence').equals(sequence).each(row => { @@ -137,9 +129,7 @@ class Database { } async findTermMeta(term, titles) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.termMeta.where('expression').equals(term).each(row => { @@ -181,9 +171,7 @@ class Database { } async findKanji(kanji, titles) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.kanji.where('character').equals(kanji).each(row => { @@ -204,9 +192,7 @@ class Database { } async findKanjiMeta(kanji, titles) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const results = []; await this.db.kanjiMeta.where('character').equals(kanji).each(row => { @@ -232,9 +218,7 @@ class Database { } async findTagForTitle(name, title) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const cache = (this.tagCache.hasOwnProperty(title) ? this.tagCache[title] : (this.tagCache[title] = {})); @@ -251,17 +235,13 @@ class Database { } async summarize() { - if (this.db) { - return this.db.dictionaries.toArray(); - } else { - throw 'Database not initialized'; - } + this.validate(); + + return this.db.dictionaries.toArray(); } async importDictionary(archive, progressCallback, exceptions) { - if (!this.db) { - throw 'Database not initialized'; - } + this.validate(); const maxTransactionLength = 1000; const bulkAdd = async (table, items, total, current) => { @@ -301,12 +281,12 @@ class Database { const indexDataLoaded = async summary => { if (summary.version > 3) { - throw 'Unsupported dictionary version'; + throw new Error('Unsupported dictionary version'); } const count = await this.db.dictionaries.where('title').equals(summary.title).count(); if (count > 0) { - throw 'Dictionary is already imported'; + throw new Error('Dictionary is already imported'); } await this.db.dictionaries.add(summary); @@ -432,6 +412,12 @@ class Database { ); } + validate() { + if (this.db === null) { + throw new Error('Database not initialized'); + } + } + static async importDictionaryZip( archive, indexDataLoaded, @@ -445,12 +431,12 @@ class Database { const indexFile = zip.files['index.json']; if (!indexFile) { - throw 'No dictionary index found in archive'; + throw new Error('No dictionary index found in archive'); } const index = JSON.parse(await indexFile.async('string')); if (!index.title || !index.revision) { - throw 'Unrecognized dictionary format'; + throw new Error('Unrecognized dictionary format'); } const summary = { diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index 7fad71c1..f933639c 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -69,7 +69,7 @@ class PopupProxyHost { getPopup(id) { if (!this.popups.hasOwnProperty(id)) { - throw 'Invalid popup ID'; + throw new Error('Invalid popup ID'); } return this.popups[id]; diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 228e554a..9beb2c52 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -39,11 +39,11 @@ class Display { } onError(error) { - throw 'Override me'; + throw new Error('Override me'); } onSearchClear() { - throw 'Override me'; + throw new Error('Override me'); } onSourceTermView(e) { @@ -386,7 +386,7 @@ class Display { viewerButton.dataset.noteId = noteId; } } else { - throw 'Note could note be added'; + throw new Error('Note could not be added'); } } catch (e) { this.onError(e); diff --git a/ext/mixed/js/extension.js b/ext/mixed/js/extension.js index 5c803132..1a87003d 100644 --- a/ext/mixed/js/extension.js +++ b/ext/mixed/js/extension.js @@ -34,7 +34,7 @@ function toIterable(value) { } } - throw 'Could not convert to iterable'; + throw new Error('Could not convert to iterable'); } function extensionHasChrome() { -- cgit v1.2.3 From 6a6e200ef947b92576351e39fc30b6653a576d70 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 7 Oct 2019 21:04:58 -0400 Subject: Update rejections to use Error --- ext/bg/js/audio.js | 4 ++-- ext/bg/js/options.js | 4 ++-- ext/bg/js/request.js | 4 ++-- ext/fg/js/frontend-api-receiver.js | 5 ++--- ext/fg/js/frontend-api-sender.js | 8 ++++---- ext/fg/js/popup-proxy.js | 2 +- ext/fg/js/util.js | 8 ++++---- ext/mixed/js/extension.js | 15 +++++++++++++++ 8 files changed, 32 insertions(+), 18 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js index 2e5db7cc..44da51d1 100644 --- a/ext/bg/js/audio.js +++ b/ext/bg/js/audio.js @@ -57,7 +57,7 @@ async function audioBuildUrl(definition, mode, cache={}) { const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); - xhr.addEventListener('error', () => reject('Failed to scrape audio data')); + xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data'))); xhr.addEventListener('load', () => { cache[definition.expression] = xhr.responseText; resolve(xhr.responseText); @@ -87,7 +87,7 @@ async function audioBuildUrl(definition, mode, cache={}) { } else { const xhr = new XMLHttpRequest(); xhr.open('GET', `https://jisho.org/search/${definition.expression}`); - xhr.addEventListener('error', () => reject('Failed to scrape audio data')); + xhr.addEventListener('error', () => reject(new Error('Failed to scrape audio data'))); xhr.addEventListener('load', () => { cache[definition.expression] = xhr.responseText; resolve(xhr.responseText); diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 2c9de1ec..a2ab8877 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -402,7 +402,7 @@ function optionsLoad() { chrome.storage.local.get(['options'], store => { const error = chrome.runtime.lastError; if (error) { - reject(error); + reject(new Error(error)); } else { resolve(store.options); } @@ -431,7 +431,7 @@ function optionsSave(options) { chrome.storage.local.set({options: JSON.stringify(options)}, () => { const error = chrome.runtime.lastError; if (error) { - reject(error); + reject(new Error(error)); } else { resolve(); } diff --git a/ext/bg/js/request.js b/ext/bg/js/request.js index e4359863..3afc1506 100644 --- a/ext/bg/js/request.js +++ b/ext/bg/js/request.js @@ -22,7 +22,7 @@ function requestJson(url, action, params) { const xhr = new XMLHttpRequest(); xhr.overrideMimeType('application/json'); xhr.addEventListener('load', () => resolve(xhr.responseText)); - xhr.addEventListener('error', () => reject('Failed to connect')); + xhr.addEventListener('error', () => reject(new Error('Failed to connect'))); xhr.open(action, url); if (params) { xhr.send(JSON.stringify(params)); @@ -34,7 +34,7 @@ function requestJson(url, action, params) { return JSON.parse(responseText); } catch (e) { - return Promise.reject('Invalid response'); + return Promise.reject(new Error('Invalid response')); } }); } diff --git a/ext/fg/js/frontend-api-receiver.js b/ext/fg/js/frontend-api-receiver.js index 687e5c3c..fbfb3ab0 100644 --- a/ext/fg/js/frontend-api-receiver.js +++ b/ext/fg/js/frontend-api-receiver.js @@ -46,9 +46,8 @@ class FrontendApiReceiver { result => { this.sendResult(port, id, senderId, {result}); }, - e => { - const error = typeof e.toString === 'function' ? e.toString() : e; - this.sendResult(port, id, senderId, {error}); + error => { + this.sendResult(port, id, senderId, {error: errorToJson(error)}); }); } diff --git a/ext/fg/js/frontend-api-sender.js b/ext/fg/js/frontend-api-sender.js index 2e037e62..c6eeaeb2 100644 --- a/ext/fg/js/frontend-api-sender.js +++ b/ext/fg/js/frontend-api-sender.js @@ -31,7 +31,7 @@ class FrontendApiSender { invoke(action, params, target) { if (this.disconnected) { - return Promise.reject('Disconnected'); + return Promise.reject(new Error('Disconnected')); } if (this.port === null) { @@ -110,8 +110,8 @@ class FrontendApiSender { clearTimeout(info.timer); info.timer = null; - if (typeof data.error === 'string') { - info.reject(data.error); + if (typeof data.error !== 'undefined') { + info.reject(jsonToError(data.error)); } else { info.resolve(data.result); } @@ -122,7 +122,7 @@ class FrontendApiSender { const info = this.callbacks[id]; delete this.callbacks[id]; info.timer = null; - info.reject(reason); + info.reject(new Error(reason)); } static generateId(length) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index 99b28549..efbd28b2 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -98,7 +98,7 @@ class PopupProxy { invokeHostApi(action, params={}) { if (typeof this.parentFrameId !== 'number') { - return Promise.reject('Invalid frame'); + return Promise.reject(new Error('Invalid frame')); } return this.apiSender.invoke(action, params, `popup-proxy-host#${this.parentFrameId}`); } diff --git a/ext/fg/js/util.js b/ext/fg/js/util.js index dc99274e..9a7968a7 100644 --- a/ext/fg/js/util.js +++ b/ext/fg/js/util.js @@ -30,19 +30,19 @@ function utilInvoke(action, params={}) { chrome.runtime.sendMessage(data, (response) => { utilCheckLastError(chrome.runtime.lastError); if (response !== null && typeof response === 'object') { - if (response.error) { - reject(response.error); + if (typeof response.error !== 'undefined') { + reject(jsonToError(response.error)); } else { resolve(response.result); } } else { const message = response === null ? 'Unexpected null response' : `Unexpected response of type ${typeof response}`; - reject(`${message} (${JSON.stringify(data)})`); + reject(new Error(`${message} (${JSON.stringify(data)})`)); } }); } catch (e) { window.yomichan_orphaned = true; - reject(e.message); + reject(e); } }); } diff --git a/ext/mixed/js/extension.js b/ext/mixed/js/extension.js index 1a87003d..5e925124 100644 --- a/ext/mixed/js/extension.js +++ b/ext/mixed/js/extension.js @@ -53,6 +53,21 @@ function extensionHasBrowser() { } } +function errorToJson(error) { + return { + name: error.name, + message: error.message, + stack: error.stack + }; +} + +function jsonToError(jsonError) { + const error = new Error(jsonError.message); + error.name = jsonError.name; + error.stack = jsonError.stack; + return error; +} + const EXTENSION_IS_BROWSER_EDGE = ( extensionHasBrowser() && (!extensionHasChrome() || (typeof chrome.runtime === 'undefined' && typeof browser.runtime !== 'undefined')) -- cgit v1.2.3 From c5d6b9452d1bfa51a5fef9a19082d115ef180a9b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Tue, 8 Oct 2019 21:33:10 -0400 Subject: Create utility function for logging errors --- ext/bg/js/search.js | 2 +- ext/fg/js/float.js | 2 +- ext/fg/js/frontend.js | 2 +- ext/mixed/js/extension.js | 18 ++++++++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 52adab16..ead9ba6f 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -53,7 +53,7 @@ class DisplaySearch extends Display { } onError(error) { - window.alert(`Error: ${error.toString ? error.toString() : error}`); + logError(error, true); } onSearchClear() { diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 88842eef..8fdb6925 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -37,7 +37,7 @@ class DisplayFloat extends Display { if (window.yomichan_orphaned) { this.onOrphaned(); } else { - window.alert(`Error: ${error.toString ? error.toString() : error}`); + logError(error, true); } } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 39433afb..88cb93a9 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -228,7 +228,7 @@ class Frontend { } onError(error) { - console.log(error); + logError(error, false); } setEnabled(enabled) { diff --git a/ext/mixed/js/extension.js b/ext/mixed/js/extension.js index 5e925124..861e52a5 100644 --- a/ext/mixed/js/extension.js +++ b/ext/mixed/js/extension.js @@ -68,6 +68,24 @@ function jsonToError(jsonError) { return error; } +function logError(error, alert) { + const manifest = chrome.runtime.getManifest(); + let errorMessage = `${manifest.name} v${manifest.version} has encountered an error.\n`; + errorMessage += `Originating URL: ${window.location.href}\n`; + + const errorString = `${error.toString ? error.toString() : error}`; + const stack = `${error.stack}`.trimRight(); + errorMessage += (!stack.startsWith(errorString) ? `${errorString}\n${stack}` : `${stack}`); + + errorMessage += '\n\nIssues can be reported at https://github.com/FooSoft/yomichan/issues'; + + console.error(errorMessage); + + if (alert) { + window.alert(`${errorString}\n\nCheck the developer console for more details.`); + } +} + const EXTENSION_IS_BROWSER_EDGE = ( extensionHasBrowser() && (!extensionHasChrome() || (typeof chrome.runtime === 'undefined' && typeof browser.runtime !== 'undefined')) -- cgit v1.2.3 From 22b218d17238cc003938ef46403596c2183a9c1b Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Wed, 9 Oct 2019 22:03:56 -0400 Subject: Pass optionsContext to audioBuildUrl handlers --- ext/bg/js/api.js | 7 ++++--- ext/bg/js/audio.js | 8 ++++---- ext/bg/js/backend.js | 2 +- ext/fg/js/api.js | 4 ++-- ext/mixed/js/display.js | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) (limited to 'ext/fg/js') diff --git a/ext/bg/js/api.js b/ext/bg/js/api.js index ed7171b5..d12104bf 100644 --- a/ext/bg/js/api.js +++ b/ext/bg/js/api.js @@ -68,7 +68,8 @@ async function apiDefinitionAdd(definition, mode, context, optionsContext) { await audioInject( definition, options.anki.terms.fields, - options.general.audioSource + options.general.audioSource, + optionsContext ); } @@ -174,8 +175,8 @@ apiCommandExec.handlers = { } }; -async function apiAudioGetUrl(definition, source) { - return audioBuildUrl(definition, source); +async function apiAudioGetUrl(definition, source, optionsContext) { + return audioBuildUrl(definition, source, optionsContext); } async function apiInjectScreenshot(definition, fields, screenshot) { diff --git a/ext/bg/js/audio.js b/ext/bg/js/audio.js index de4e80f3..36ce03cf 100644 --- a/ext/bg/js/audio.js +++ b/ext/bg/js/audio.js @@ -88,7 +88,7 @@ const audioUrlBuilders = { } }; -async function audioBuildUrl(definition, mode, cache={}) { +async function audioBuildUrl(definition, mode, optionsContext, cache={}) { const cacheKey = `${mode}:${definition.expression}`; if (cache.hasOwnProperty(cacheKey)) { return Promise.resolve(cache[cacheKey]); @@ -96,7 +96,7 @@ async function audioBuildUrl(definition, mode, cache={}) { if (audioUrlBuilders.hasOwnProperty(mode)) { const handler = audioUrlBuilders[mode]; - return handler(definition).then( + return handler(definition, optionsContext).then( (url) => { cache[cacheKey] = url; return url; @@ -138,7 +138,7 @@ function audioBuildFilename(definition) { } } -async function audioInject(definition, fields, mode) { +async function audioInject(definition, fields, mode, optionsContext) { let usesAudio = false; for (const name in fields) { if (fields[name].includes('{audio}')) { @@ -157,7 +157,7 @@ async function audioInject(definition, fields, mode) { audioSourceDefinition = definition.expressions[0]; } - const url = await audioBuildUrl(audioSourceDefinition, mode); + const url = await audioBuildUrl(audioSourceDefinition, mode, optionsContext); const filename = audioBuildFilename(audioSourceDefinition); if (url && filename) { diff --git a/ext/bg/js/backend.js b/ext/bg/js/backend.js index fb77b71e..453f4282 100644 --- a/ext/bg/js/backend.js +++ b/ext/bg/js/backend.js @@ -181,7 +181,7 @@ Backend.messageHandlers = { noteView: ({noteId}) => apiNoteView(noteId), templateRender: ({template, data, dynamic}) => apiTemplateRender(template, data, dynamic), commandExec: ({command}) => apiCommandExec(command), - audioGetUrl: ({definition, source}) => apiAudioGetUrl(definition, source), + audioGetUrl: ({definition, source, optionsContext}) => apiAudioGetUrl(definition, source, optionsContext), screenshotGet: ({options}, sender) => apiScreenshotGet(options, sender), forward: ({action, params}, sender) => apiForward(action, params, sender), frameInformationGet: (params, sender) => apiFrameInformationGet(sender), diff --git a/ext/fg/js/api.js b/ext/fg/js/api.js index d0ac649a..a553e514 100644 --- a/ext/fg/js/api.js +++ b/ext/fg/js/api.js @@ -45,8 +45,8 @@ function apiTemplateRender(template, data, dynamic) { return utilInvoke('templateRender', {data, template, dynamic}); } -function apiAudioGetUrl(definition, source) { - return utilInvoke('audioGetUrl', {definition, source}); +function apiAudioGetUrl(definition, source, optionsContext) { + return utilInvoke('audioGetUrl', {definition, source, optionsContext}); } function apiCommandExec(command) { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 17370654..78e6d8e3 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -404,7 +404,7 @@ class Display { this.setSpinnerVisible(true); const expression = expressionIndex === -1 ? definition : definition.expressions[expressionIndex]; - let url = await apiAudioGetUrl(expression, this.options.general.audioSource); + let url = await apiAudioGetUrl(expression, this.options.general.audioSource, this.optionsContext); if (!url) { url = '/mixed/mp3/button.mp3'; } -- cgit v1.2.3