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
This commit is contained in:
parent
286534e648
commit
9279ced686
@ -111,9 +111,11 @@
|
||||
"deepEqual": "readonly",
|
||||
"generateId": "readonly",
|
||||
"promiseAnimationFrame": "readonly",
|
||||
"log": "readonly",
|
||||
"DynamicProperty": "readonly",
|
||||
"EventDispatcher": "readonly",
|
||||
"EventListenerCollection": "readonly"
|
||||
"EventListenerCollection": "readonly",
|
||||
"Logger": "readonly"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -52,6 +52,6 @@
|
||||
|
||||
yomichan.ready();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ class PopupProxy extends EventDispatcher {
|
||||
}
|
||||
this._frameOffsetUpdatedAt = now;
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
} finally {
|
||||
this._frameOffsetPromise = null;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
108
ext/js/core.js
108
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();
|
||||
|
@ -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; }
|
||||
|
@ -49,6 +49,6 @@
|
||||
|
||||
yomichan.ready();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -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; }
|
||||
|
@ -50,6 +50,6 @@
|
||||
|
||||
yomichan.ready();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -69,7 +69,7 @@ class TaskAccumulator {
|
||||
];
|
||||
await this._runTasks(allTasks);
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -830,7 +830,7 @@ class TextScanner extends EventDispatcher {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
} finally {
|
||||
this._pendingLookup = false;
|
||||
}
|
||||
|
@ -120,6 +120,6 @@ function getOperatingSystemDisplayName(os) {
|
||||
|
||||
document.documentElement.dataset.loaded = 'true';
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -96,6 +96,6 @@ function setupPermissionsToggles() {
|
||||
|
||||
document.documentElement.dataset.loaded = 'true';
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -81,6 +81,6 @@ async function setupGenericSettingsController(genericSettingController) {
|
||||
const settingsDisplayController = new SettingsDisplayController(settingsController, modalController);
|
||||
settingsDisplayController.prepare();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -638,7 +638,7 @@ class AnkiCardController {
|
||||
try {
|
||||
await this._settingsController.permissionsUtil.setPermissionsGranted({permissions}, true);
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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') {
|
||||
|
@ -104,6 +104,6 @@ async function setupEnvironmentInfo() {
|
||||
|
||||
yomichan.ready();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -30,6 +30,6 @@
|
||||
await displayGenerator.prepare();
|
||||
displayGenerator.preparePitchAccents();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -38,6 +38,6 @@
|
||||
|
||||
document.documentElement.dataset.loaded = 'true';
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -149,6 +149,6 @@ async function setupGenericSettingsController(genericSettingController) {
|
||||
const settingsDisplayController = new SettingsDisplayController(settingsController, modalController);
|
||||
settingsDisplayController.prepare();
|
||||
} catch (e) {
|
||||
yomichan.logError(e);
|
||||
log.error(e);
|
||||
}
|
||||
})();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user