summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-02-14 17:52:01 -0500
committerGitHub <noreply@github.com>2021-02-14 17:52:01 -0500
commit9279ced68660610764931da681f22c8b71bf1b6e (patch)
tree2a4d015cf57adfe74af72615bad19c9308388e99
parent286534e648af350d24fbf3c7892a7ec81aaeb4bd (diff)
Log refactoring (#1393)
* Create Logger class and log instance * Replace yomichan.logWarning with log.warn * Replace yomichan.logError with log.error * Replace yomichan.log with log.log * Update the Yomichan class to use the global log object * Update lint rules
-rw-r--r--.eslintrc.json4
-rw-r--r--ext/js/app/content-script-main.js2
-rw-r--r--ext/js/app/frontend.js4
-rw-r--r--ext/js/app/popup-proxy.js2
-rw-r--r--ext/js/background/backend.js8
-rw-r--r--ext/js/comm/cross-frame-api.js6
-rw-r--r--ext/js/core.js108
-rw-r--r--ext/js/display/display.js6
-rw-r--r--ext/js/display/popup-main.js2
-rw-r--r--ext/js/display/query-parser.js2
-rw-r--r--ext/js/display/search-main.js2
-rw-r--r--ext/js/general/task-accumulator.js2
-rw-r--r--ext/js/language/dictionary-database.js2
-rw-r--r--ext/js/language/text-scanner.js2
-rw-r--r--ext/js/pages/info-main.js2
-rw-r--r--ext/js/pages/permissions-main.js2
-rw-r--r--ext/js/pages/welcome-main.js2
-rw-r--r--ext/js/settings/anki-controller.js2
-rw-r--r--ext/js/settings/backup-controller.js4
-rw-r--r--ext/js/settings/dictionary-controller.js2
-rw-r--r--ext/js/settings/dictionary-import-controller.js2
-rw-r--r--ext/js/settings/main.js2
-rw-r--r--ext/js/settings/pitch-accents-preview-main.js2
-rw-r--r--ext/js/settings/popup-preview-frame-main.js2
-rw-r--r--ext/js/settings/settings-main.js2
-rw-r--r--ext/js/yomichan.js64
26 files changed, 144 insertions, 96 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
index e2197916..fca1449b 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -111,9 +111,11 @@
"deepEqual": "readonly",
"generateId": "readonly",
"promiseAnimationFrame": "readonly",
+ "log": "readonly",
"DynamicProperty": "readonly",
"EventDispatcher": "readonly",
- "EventListenerCollection": "readonly"
+ "EventListenerCollection": "readonly",
+ "Logger": "readonly"
}
},
{
diff --git a/ext/js/app/content-script-main.js b/ext/js/app/content-script-main.js
index a09e52ea..1c0c6d49 100644
--- a/ext/js/app/content-script-main.js
+++ b/ext/js/app/content-script-main.js
@@ -52,6 +52,6 @@
yomichan.ready();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index 74cc63d2..02707f41 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -276,7 +276,7 @@ class Frontend {
this._showExtensionUnloaded(textSource);
}
} else {
- yomichan.logError(error);
+ log.error(error);
}
} if (type !== null) {
this._stopClearSelectionDelayed();
@@ -563,7 +563,7 @@ class Frontend {
);
this._lastShowPromise.catch((error) => {
if (yomichan.isExtensionUnloaded) { return; }
- yomichan.logError(error);
+ log.error(error);
});
return this._lastShowPromise;
}
diff --git a/ext/js/app/popup-proxy.js b/ext/js/app/popup-proxy.js
index 19856e3f..63ecc254 100644
--- a/ext/js/app/popup-proxy.js
+++ b/ext/js/app/popup-proxy.js
@@ -201,7 +201,7 @@ class PopupProxy extends EventDispatcher {
}
this._frameOffsetUpdatedAt = now;
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
} finally {
this._frameOffsetPromise = null;
}
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 69c90aca..698724fc 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -204,7 +204,7 @@ class Backend {
try {
await this._dictionaryDatabase.prepare();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
const deinflectionReasions = await this._fetchAsset('/data/deinflect.json', true);
@@ -226,7 +226,7 @@ class Backend {
this._sendMessageAllTabsIgnoreResponse('backendReady', {});
this._sendMessageIgnoreResponse({action: 'backendReady', params: {}});
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
throw e;
} finally {
if (this._badgePrepareDelayTimer !== null) {
@@ -358,7 +358,7 @@ class Backend {
forwardPort.onDisconnect.addListener(cleanup);
} catch (e) {
port.disconnect();
- yomichan.logError(e);
+ log.error(e);
}
}
@@ -612,7 +612,7 @@ class Backend {
}
_onApiLog({error, level, context}) {
- yomichan.log(deserializeError(error), level, context);
+ log.log(deserializeError(error), level, context);
}
_onApiLogIndicatorClear() {
diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js
index 997249c8..7dbfb411 100644
--- a/ext/js/comm/cross-frame-api.js
+++ b/ext/js/comm/cross-frame-api.js
@@ -111,7 +111,7 @@ class CrossFrameAPIPort extends EventDispatcher {
_onAck(id) {
const invocation = this._activeInvocations.get(id);
if (typeof invocation === 'undefined') {
- yomichan.logWarning(new Error(`Request ${id} not found for acknowledgement`));
+ log.warn(new Error(`Request ${id} not found for acknowledgement`));
return;
}
@@ -140,7 +140,7 @@ class CrossFrameAPIPort extends EventDispatcher {
_onResult(id, data) {
const invocation = this._activeInvocations.get(id);
if (typeof invocation === 'undefined') {
- yomichan.logWarning(new Error(`Request ${id} not found`));
+ log.warn(new Error(`Request ${id} not found`));
return;
}
@@ -269,7 +269,7 @@ class CrossFrameAPI {
this._setupCommPort(otherTabId, otherFrameId, port);
} catch (e) {
port.disconnect();
- yomichan.logError(e);
+ log.error(e);
}
}
diff --git a/ext/js/core.js b/ext/js/core.js
index 9305739a..4384d9f0 100644
--- a/ext/js/core.js
+++ b/ext/js/core.js
@@ -607,3 +607,111 @@ class DynamicProperty extends EventDispatcher {
this.trigger('change', {value});
}
}
+
+/**
+ * This class handles logging of messages to the console and triggering
+ * an event for log calls.
+ */
+class Logger extends EventDispatcher {
+ /**
+ * Creates a new instance.
+ */
+ constructor() {
+ super();
+ this._extensionName = 'Yomichan';
+ try {
+ const {name, version} = chrome.runtime.getManifest();
+ this._extensionName = `${name} ${version}`;
+ } catch (e) {
+ // NOP
+ }
+ }
+
+ /**
+ * Logs a generic error. This will trigger the 'log' event with the same arguments as the function invocation.
+ * @param error The error to log. This is typically an `Error` or `Error`-like object.
+ * @param level The level to log at. Values include `'info'`, `'debug'`, `'warn'`, and `'error'`.
+ * Other values will be logged at a non-error level.
+ * @param context An optional context object for the error which should typically include a `url` field.
+ */
+ log(error, level, context=null) {
+ if (!isObject(context)) {
+ context = {url: location.href};
+ }
+
+ let errorString;
+ try {
+ if (typeof error === 'string') {
+ errorString = error;
+ } else {
+ errorString = error.toString();
+ if (/^\[object \w+\]$/.test(errorString)) {
+ errorString = JSON.stringify(error);
+ }
+ }
+ } catch (e) {
+ errorString = `${error}`;
+ }
+
+ let errorStack;
+ try {
+ errorStack = (typeof error.stack === 'string' ? error.stack.trimRight() : '');
+ } catch (e) {
+ errorStack = '';
+ }
+
+ let errorData;
+ try {
+ errorData = error.data;
+ } catch (e) {
+ // NOP
+ }
+
+ if (errorStack.startsWith(errorString)) {
+ errorString = errorStack;
+ } else if (errorStack.length > 0) {
+ errorString += `\n${errorStack}`;
+ }
+
+ let message = `${this._extensionName} has encountered a problem.`;
+ message += `\nOriginating URL: ${context.url}\n`;
+ message += errorString;
+ if (typeof errorData !== 'undefined') {
+ message += `\nData: ${JSON.stringify(errorData, null, 4)}`;
+ }
+ message += '\n\nIssues can be reported at https://github.com/FooSoft/yomichan/issues';
+
+ switch (level) {
+ case 'info': console.info(message); break;
+ case 'debug': console.debug(message); break;
+ case 'warn': console.warn(message); break;
+ case 'error': console.error(message); break;
+ default: console.log(message); break;
+ }
+
+ this.trigger('log', {error, level, context});
+ }
+
+ /**
+ * Logs a warning. This function invokes `log` internally.
+ * @param error The error to log. This is typically an `Error` or `Error`-like object.
+ * @param context An optional context object for the error which should typically include a `url` field.
+ */
+ warn(error, context=null) {
+ this.log(error, 'warn', context);
+ }
+
+ /**
+ * Logs an error. This function invokes `log` internally.
+ * @param error The error to log. This is typically an `Error` or `Error`-like object.
+ * @param context An optional context object for the error which should typically include a `url` field.
+ */
+ error(error, context=null) {
+ this.log(error, 'error', context);
+ }
+}
+
+/**
+ * This object is the default logger used by the runtime.
+ */
+const log = new Logger();
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index 553c17e7..b7477bb8 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -272,7 +272,7 @@ class Display extends EventDispatcher {
onError(error) {
if (yomichan.isExtensionUnloaded) { return; }
- yomichan.logError(error);
+ log.error(error);
}
getOptions() {
@@ -1552,7 +1552,7 @@ class Display extends EventDispatcher {
}
await this._frontendSetupPromise;
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
return;
} finally {
this._frontendSetupPromise = null;
@@ -1721,7 +1721,7 @@ class Display extends EventDispatcher {
_onDefinitionTextScannerSearched({type, definitions, sentence, textSource, optionsContext, error}) {
if (error !== null && !yomichan.isExtensionUnloaded) {
- yomichan.logError(error);
+ log.error(error);
}
if (type === null) { return; }
diff --git a/ext/js/display/popup-main.js b/ext/js/display/popup-main.js
index 24be6c01..55f19984 100644
--- a/ext/js/display/popup-main.js
+++ b/ext/js/display/popup-main.js
@@ -49,6 +49,6 @@
yomichan.ready();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js
index 29401657..d6a3b4da 100644
--- a/ext/js/display/query-parser.js
+++ b/ext/js/display/query-parser.js
@@ -89,7 +89,7 @@ class QueryParser extends EventDispatcher {
_onSearched(e) {
const {error} = e;
if (error !== null) {
- yomichan.logError(error);
+ log.error(error);
return;
}
if (e.type === null) { return; }
diff --git a/ext/js/display/search-main.js b/ext/js/display/search-main.js
index 08645833..5ad50500 100644
--- a/ext/js/display/search-main.js
+++ b/ext/js/display/search-main.js
@@ -50,6 +50,6 @@
yomichan.ready();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/general/task-accumulator.js b/ext/js/general/task-accumulator.js
index 82691b43..3f3d8ff7 100644
--- a/ext/js/general/task-accumulator.js
+++ b/ext/js/general/task-accumulator.js
@@ -69,7 +69,7 @@ class TaskAccumulator {
];
await this._runTasks(allTasks);
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
}
diff --git a/ext/js/language/dictionary-database.js b/ext/js/language/dictionary-database.js
index b363ed25..62c22289 100644
--- a/ext/js/language/dictionary-database.js
+++ b/ext/js/language/dictionary-database.js
@@ -122,7 +122,7 @@ class DictionaryDatabase {
await Database.deleteDatabase(this._dbName);
result = true;
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
await this.prepare();
return result;
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index e91498ba..073b1a6c 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -830,7 +830,7 @@ class TextScanner extends EventDispatcher {
}
}
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
} finally {
this._pendingLookup = false;
}
diff --git a/ext/js/pages/info-main.js b/ext/js/pages/info-main.js
index 45c28d25..ca7d792e 100644
--- a/ext/js/pages/info-main.js
+++ b/ext/js/pages/info-main.js
@@ -120,6 +120,6 @@ function getOperatingSystemDisplayName(os) {
document.documentElement.dataset.loaded = 'true';
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js
index 0cb37e93..782ea9ec 100644
--- a/ext/js/pages/permissions-main.js
+++ b/ext/js/pages/permissions-main.js
@@ -96,6 +96,6 @@ function setupPermissionsToggles() {
document.documentElement.dataset.loaded = 'true';
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js
index 5a6bb2a5..27d0af6a 100644
--- a/ext/js/pages/welcome-main.js
+++ b/ext/js/pages/welcome-main.js
@@ -81,6 +81,6 @@ async function setupGenericSettingsController(genericSettingController) {
const settingsDisplayController = new SettingsDisplayController(settingsController, modalController);
settingsDisplayController.prepare();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/settings/anki-controller.js b/ext/js/settings/anki-controller.js
index db3e3c14..26cab68f 100644
--- a/ext/js/settings/anki-controller.js
+++ b/ext/js/settings/anki-controller.js
@@ -638,7 +638,7 @@ class AnkiCardController {
try {
await this._settingsController.permissionsUtil.setPermissionsGranted({permissions}, true);
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
}
diff --git a/ext/js/settings/backup-controller.js b/ext/js/settings/backup-controller.js
index 117f2422..649645d4 100644
--- a/ext/js/settings/backup-controller.js
+++ b/ext/js/settings/backup-controller.js
@@ -173,7 +173,7 @@ class BackupController {
}
_showSettingsImportError(error) {
- yomichan.logError(error);
+ log.error(error);
document.querySelector('#settings-import-error-message').textContent = `${error}`;
this._settingsImportErrorModal.setVisible(true);
}
@@ -412,7 +412,7 @@ class BackupController {
try {
await this._settingsImportSetOptionsFull(optionsFull);
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
}
}
diff --git a/ext/js/settings/dictionary-controller.js b/ext/js/settings/dictionary-controller.js
index 78173202..e12017f2 100644
--- a/ext/js/settings/dictionary-controller.js
+++ b/ext/js/settings/dictionary-controller.js
@@ -476,7 +476,7 @@ class DictionaryController {
await this._deleteDictionaryInternal(dictionaryTitle, onProgress);
await this._deleteDictionarySettings(dictionaryTitle);
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
} finally {
prevention.end();
for (const progress of progressContainers) { progress.hidden = true; }
diff --git a/ext/js/settings/dictionary-import-controller.js b/ext/js/settings/dictionary-import-controller.js
index 00eb7b95..1389b7f0 100644
--- a/ext/js/settings/dictionary-import-controller.js
+++ b/ext/js/settings/dictionary-import-controller.js
@@ -253,7 +253,7 @@ class DictionaryImportController {
_showErrors(errors) {
const uniqueErrors = new Map();
for (const error of errors) {
- yomichan.logError(error);
+ log.error(error);
const errorString = this._errorToString(error);
let count = uniqueErrors.get(errorString);
if (typeof count === 'undefined') {
diff --git a/ext/js/settings/main.js b/ext/js/settings/main.js
index 51cd5f27..9785ee0e 100644
--- a/ext/js/settings/main.js
+++ b/ext/js/settings/main.js
@@ -104,6 +104,6 @@ async function setupEnvironmentInfo() {
yomichan.ready();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/settings/pitch-accents-preview-main.js b/ext/js/settings/pitch-accents-preview-main.js
index fe3bd36d..d9d56727 100644
--- a/ext/js/settings/pitch-accents-preview-main.js
+++ b/ext/js/settings/pitch-accents-preview-main.js
@@ -30,6 +30,6 @@
await displayGenerator.prepare();
displayGenerator.preparePitchAccents();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/settings/popup-preview-frame-main.js b/ext/js/settings/popup-preview-frame-main.js
index a62e8d28..80e248be 100644
--- a/ext/js/settings/popup-preview-frame-main.js
+++ b/ext/js/settings/popup-preview-frame-main.js
@@ -38,6 +38,6 @@
document.documentElement.dataset.loaded = 'true';
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/settings/settings-main.js b/ext/js/settings/settings-main.js
index a5bb642c..273142cd 100644
--- a/ext/js/settings/settings-main.js
+++ b/ext/js/settings/settings-main.js
@@ -149,6 +149,6 @@ async function setupGenericSettingsController(genericSettingController) {
const settingsDisplayController = new SettingsDisplayController(settingsController, modalController);
settingsDisplayController.prepare();
} catch (e) {
- yomichan.logError(e);
+ log.error(e);
}
})();
diff --git a/ext/js/yomichan.js b/ext/js/yomichan.js
index 73deeab9..107694e9 100644
--- a/ext/js/yomichan.js
+++ b/ext/js/yomichan.js
@@ -103,7 +103,7 @@ class Yomichan extends EventDispatcher {
this.sendMessage({action: 'requestBackendReadySignal'});
await this._isBackendReadyPromise;
- this.on('log', this._onForwardLog.bind(this));
+ log.on('log', this._onForwardLog.bind(this));
}
}
@@ -156,68 +156,6 @@ class Yomichan extends EventDispatcher {
});
}
- logWarning(error) {
- this.log(error, 'warn');
- }
-
- logError(error) {
- this.log(error, 'error');
- }
-
- log(error, level, context=null) {
- if (!isObject(context)) {
- context = this._getLogContext();
- }
-
- let errorString;
- try {
- errorString = error.toString();
- if (/^\[object \w+\]$/.test(errorString)) {
- errorString = JSON.stringify(error);
- }
- } catch (e) {
- errorString = `${error}`;
- }
-
- let errorStack;
- try {
- errorStack = (typeof error.stack === 'string' ? error.stack.trimRight() : '');
- } catch (e) {
- errorStack = '';
- }
-
- let errorData;
- try {
- errorData = error.data;
- } catch (e) {
- // NOP
- }
-
- if (errorStack.startsWith(errorString)) {
- errorString = errorStack;
- } else if (errorStack.length > 0) {
- errorString += `\n${errorStack}`;
- }
-
- let message = `${this._extensionName} has encountered a problem.`;
- message += `\nOriginating URL: ${context.url}\n`;
- message += errorString;
- if (typeof errorData !== 'undefined') {
- message += `\nData: ${JSON.stringify(errorData, null, 4)}`;
- }
- message += '\n\nIssues can be reported at https://github.com/FooSoft/yomichan/issues';
-
- switch (level) {
- case 'info': console.info(message); break;
- case 'debug': console.debug(message); break;
- case 'warn': console.warn(message); break;
- case 'error': console.error(message); break;
- default: console.log(message); break;
- }
-
- this.trigger('log', {error, level, context});
- }
-
sendMessage(...args) {
try {
return chrome.runtime.sendMessage(...args);