aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2024-01-15 06:12:33 -0500
committerGitHub <noreply@github.com>2024-01-15 11:12:33 +0000
commit48f1d012ad5045319d4e492dfbefa39da92817b2 (patch)
tree51b5b53a7b1192f04a8292c3a9aa0f5063c64b46
parent9cfa20cbd2289d82a5abf05a2e5ea8af5016222c (diff)
Add toError utility function (#523)
* Add asError utility function * Rename to toError
-rw-r--r--dev/dictionary-validate.js7
-rw-r--r--dev/to-error.js18
-rw-r--r--ext/js/comm/mecab.js3
-rw-r--r--ext/js/core/to-error.js26
-rw-r--r--ext/js/dictionary/dictionary-importer.js3
-rw-r--r--ext/js/display/display-anki.js17
-rw-r--r--ext/js/display/display.js5
-rw-r--r--ext/js/display/option-toggle-hotkey-handler.js3
-rw-r--r--ext/js/dom/text-source-range.js3
-rw-r--r--ext/js/pages/settings/anki-controller.js7
-rw-r--r--ext/js/pages/settings/anki-templates-controller.js3
-rw-r--r--ext/js/pages/settings/backup-controller.js3
-rw-r--r--ext/js/pages/settings/dictionary-import-controller.js5
-rw-r--r--ext/js/pages/settings/mecab-controller.js3
-rw-r--r--ext/js/pages/settings/permissions-origin-controller.js3
-rw-r--r--ext/js/pages/settings/recommended-permissions-controller.js3
16 files changed, 85 insertions, 27 deletions
diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js
index 51edcc50..3727310e 100644
--- a/dev/dictionary-validate.js
+++ b/dev/dictionary-validate.js
@@ -23,6 +23,7 @@ import {performance} from 'perf_hooks';
import {fileURLToPath} from 'url';
import {parseJson} from './json.js';
import {createJsonSchema} from './schema-validate.js';
+import {toError} from './to-error.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -47,7 +48,7 @@ async function validateDictionaryBanks(mode, zip, fileNameFormat, schema) {
try {
jsonSchema = createJsonSchema(mode, schema);
} catch (e) {
- const e2 = e instanceof Error ? e : new Error(`${e}`);
+ const e2 = toError(e);
e2.message += `\n(in file ${fileNameFormat})}`;
throw e2;
}
@@ -62,7 +63,7 @@ async function validateDictionaryBanks(mode, zip, fileNameFormat, schema) {
try {
jsonSchema.validate(data);
} catch (e) {
- const e2 = e instanceof Error ? e : new Error(`${e}`);
+ const e2 = toError(e);
e2.message += `\n(in file ${fileName})}`;
throw e2;
}
@@ -92,7 +93,7 @@ export async function validateDictionary(mode, archive, schemas) {
const jsonSchema = createJsonSchema(mode, schemas.index);
jsonSchema.validate(index);
} catch (e) {
- const e2 = e instanceof Error ? e : new Error(`${e}`);
+ const e2 = toError(e);
e2.message += `\n(in file ${indexFileName})}`;
throw e2;
}
diff --git a/dev/to-error.js b/dev/to-error.js
new file mode 100644
index 00000000..1cc84f50
--- /dev/null
+++ b/dev/to-error.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+export {toError} from '../ext/js/core/to-error.js';
diff --git a/ext/js/comm/mecab.js b/ext/js/comm/mecab.js
index 6d0f3f40..f3ad7b51 100644
--- a/ext/js/comm/mecab.js
+++ b/ext/js/comm/mecab.js
@@ -17,6 +17,7 @@
*/
import {EventListenerCollection} from '../core.js';
+import {toError} from '../core/to-error.js';
/**
* This class is used to connect Yomitan to a native component that is
@@ -235,7 +236,7 @@ export class Mecab {
try {
await this._setupPortPromise;
} catch (e) {
- throw new Error(e instanceof Error ? e.message : `${e}`);
+ throw toError(e);
}
}
diff --git a/ext/js/core/to-error.js b/ext/js/core/to-error.js
new file mode 100644
index 00000000..4866c3da
--- /dev/null
+++ b/ext/js/core/to-error.js
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Utility function to convert an unknown value to an error.
+ * This is useful for try-catch situations where the catch parameter has the `unknown` type.
+ * @param {unknown} value
+ * @returns {Error}
+ */
+export function toError(value) {
+ return value instanceof Error ? value : new Error(`${value}`);
+}
diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js
index 2c0c7e9c..bfd7a8b2 100644
--- a/ext/js/dictionary/dictionary-importer.js
+++ b/ext/js/dictionary/dictionary-importer.js
@@ -27,6 +27,7 @@ import {
import {stringReverse} from '../core.js';
import {ExtensionError} from '../core/extension-error.js';
import {parseJson} from '../core/json.js';
+import {toError} from '../core/to-error.js';
import {MediaUtil} from '../media/media-util.js';
const ajvSchemas = /** @type {import('dictionary-importer').CompiledSchemaValidators} */ (/** @type {unknown} */ (ajvSchemas0));
@@ -206,7 +207,7 @@ export class DictionaryImporter {
try {
await dictionaryDatabase.bulkAdd(objectStoreName, entries, i, count);
} catch (e) {
- errors.push(e instanceof Error ? e : new Error(`${e}`));
+ errors.push(toError(e));
}
this._progressData.index += count;
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index 759998c4..77ba7ffb 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -17,6 +17,7 @@
*/
import {EventListenerCollection, deferPromise} from '../core.js';
+import {toError} from '../core/to-error.js';
import {AnkiNoteBuilder} from '../data/anki-note-builder.js';
import {AnkiUtil} from '../data/anki-util.js';
import {PopupMenu} from '../dom/popup-menu.js';
@@ -159,7 +160,7 @@ export class DisplayAnki {
try {
({note: note, errors, requirements} = await this._createNote(dictionaryEntry, mode, []));
} catch (e) {
- errors = [e instanceof Error ? e : new Error(`${e}`)];
+ errors = [toError(e)];
}
/** @type {import('display-anki').AnkiNoteLogData} */
const entry = {mode, note};
@@ -174,7 +175,7 @@ export class DisplayAnki {
return {
ankiNoteData,
- ankiNoteDataException: ankiNoteDataException instanceof Error ? ankiNoteDataException : new Error(`${ankiNoteDataException}`),
+ ankiNoteDataException: toError(ankiNoteDataException),
ankiNotes
};
}
@@ -490,7 +491,7 @@ export class DisplayAnki {
addNoteOkay = true;
} catch (e) {
allErrors.length = 0;
- allErrors.push(e instanceof Error ? e : new Error(`${e}`));
+ allErrors.push(toError(e));
}
if (addNoteOkay) {
@@ -501,7 +502,7 @@ export class DisplayAnki {
try {
await yomitan.api.suspendAnkiCardsForNote(noteId);
} catch (e) {
- allErrors.push(e instanceof Error ? e : new Error(`${e}`));
+ allErrors.push(toError(e));
}
}
button.disabled = true;
@@ -509,7 +510,7 @@ export class DisplayAnki {
}
}
} catch (e) {
- allErrors.push(e instanceof Error ? e : new Error(`${e}`));
+ allErrors.push(toError(e));
} finally {
progressIndicatorVisible.clearOverride(overrideToken);
}
@@ -647,7 +648,7 @@ export class DisplayAnki {
}
} catch (e) {
infos = this._getAnkiNoteInfoForceValue(notes, false);
- ankiError = e instanceof Error ? e : new Error(`${e}`);
+ ankiError = toError(e);
}
/** @type {import('display-anki').DictionaryEntryDetails[]} */
@@ -855,11 +856,11 @@ export class DisplayAnki {
await yomitan.api.noteView(noteIds[0], this._noteGuiMode, false);
} catch (e) {
const displayErrors = (
- e instanceof Error && e.message === 'Mode not supported' ?
+ toError(e).message === 'Mode not supported' ?
[this._display.displayGenerator.instantiateTemplateFragment('footer-notification-anki-view-note-error')] :
void 0
);
- this._showErrorNotification([e instanceof Error ? e : new Error(`${e}`)], displayErrors);
+ this._showErrorNotification([toError(e)], displayErrors);
return;
}
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index ff77d203..7e7dd426 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -21,6 +21,7 @@ import {FrameEndpoint} from '../comm/frame-endpoint.js';
import {DynamicProperty, EventDispatcher, EventListenerCollection, clone, deepEqual, log, promiseTimeout} from '../core.js';
import {extendApiMap, invokeApiMapHandler} from '../core/api-map.js';
import {ExtensionError} from '../core/extension-error.js';
+import {toError} from '../core/to-error.js';
import {PopupMenu} from '../dom/popup-menu.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {ScrollElement} from '../dom/scroll-element.js';
@@ -787,7 +788,7 @@ export class Display extends EventDispatcher {
break;
}
} catch (e) {
- this.onError(e instanceof Error ? e : new Error(`${e}`));
+ this.onError(toError(e));
}
}
@@ -922,7 +923,7 @@ export class Display extends EventDispatcher {
};
this.setContent(details);
} catch (error) {
- this.onError(error instanceof Error ? error : new Error(`${error}`));
+ this.onError(toError(error));
}
}
diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js
index 73c92d59..ba4c8578 100644
--- a/ext/js/display/option-toggle-hotkey-handler.js
+++ b/ext/js/display/option-toggle-hotkey-handler.js
@@ -18,6 +18,7 @@
import {generateId} from '../core.js';
import {ExtensionError} from '../core/extension-error.js';
+import {toError} from '../core/to-error.js';
import {yomitan} from '../yomitan.js';
export class OptionToggleHotkeyHandler {
@@ -132,7 +133,7 @@ export class OptionToggleHotkeyHandler {
* @returns {DocumentFragment}
*/
_createErrorMessage(path, error) {
- const message = error instanceof Error ? error.message : `${error}`;
+ const message = toError(error).message;
const fragment = document.createDocumentFragment();
const n1 = document.createElement('em');
n1.textContent = path;
diff --git a/ext/js/dom/text-source-range.js b/ext/js/dom/text-source-range.js
index fd09fdda..7f4db4f2 100644
--- a/ext/js/dom/text-source-range.js
+++ b/ext/js/dom/text-source-range.js
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {toError} from '../core/to-error.js';
import {DocumentUtil} from './document-util.js';
import {DOMTextScanner} from './dom-text-scanner.js';
@@ -228,7 +229,7 @@ export class TextSourceRange {
try {
return this._range.compareBoundaryPoints(Range.START_TO_START, other.range) === 0;
} catch (e) {
- if (e instanceof Error && e.name === 'WrongDocumentError') {
+ if (toError(e).name === 'WrongDocumentError') {
// This can happen with shadow DOMs if the ranges are in different documents.
return false;
}
diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js
index d64034a5..c8daa85b 100644
--- a/ext/js/pages/settings/anki-controller.js
+++ b/ext/js/pages/settings/anki-controller.js
@@ -19,6 +19,7 @@
import {AnkiConnect} from '../../comm/anki-connect.js';
import {EventListenerCollection, log} from '../../core.js';
import {ExtensionError} from '../../core/extension-error.js';
+import {toError} from '../../core/to-error.js';
import {AnkiUtil} from '../../data/anki-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {SelectorObserver} from '../../dom/selector-observer.js';
@@ -409,7 +410,7 @@ export class AnkiController {
this._sortStringArray(result);
return [result, null];
} catch (e) {
- return [[], e instanceof Error ? e : new Error(`${e}`)];
+ return [[], toError(e)];
}
}
@@ -422,7 +423,7 @@ export class AnkiController {
this._sortStringArray(result);
return [result, null];
} catch (e) {
- return [[], e instanceof Error ? e : new Error(`${e}`)];
+ return [[], toError(e)];
}
}
@@ -487,7 +488,7 @@ export class AnkiController {
try {
await this._testAnkiNoteViewer(mode);
} catch (e) {
- this._setAnkiNoteViewerStatus(true, e instanceof Error ? e : new Error(`${e}`));
+ this._setAnkiNoteViewerStatus(true, toError(e));
return;
}
this._setAnkiNoteViewerStatus(true, null);
diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js
index 56e992b0..0c82cecc 100644
--- a/ext/js/pages/settings/anki-templates-controller.js
+++ b/ext/js/pages/settings/anki-templates-controller.js
@@ -17,6 +17,7 @@
*/
import {ExtensionError} from '../../core/extension-error.js';
+import {toError} from '../../core/to-error.js';
import {AnkiNoteBuilder} from '../../data/anki-note-builder.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {JapaneseUtil} from '../../language/sandbox/japanese-util.js';
@@ -266,7 +267,7 @@ export class AnkiTemplatesController {
allErrors.push(...errors);
}
} catch (e) {
- allErrors.push(e instanceof Error ? e : new Error(`${e}`));
+ allErrors.push(toError(e));
}
/**
diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js
index 2ae52925..457acc18 100644
--- a/ext/js/pages/settings/backup-controller.js
+++ b/ext/js/pages/settings/backup-controller.js
@@ -19,6 +19,7 @@
import {Dexie} from '../../../lib/dexie.js';
import {isObject, log} from '../../core.js';
import {parseJson} from '../../core/json.js';
+import {toError} from '../../core/to-error.js';
import {OptionsUtil} from '../../data/options-util.js';
import {ArrayBufferUtil} from '../../data/sandbox/array-buffer-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
@@ -498,7 +499,7 @@ export class BackupController {
try {
await this._importSettingsFile(file);
} catch (error) {
- this._showSettingsImportError(error instanceof Error ? error : new Error(`${error}`));
+ this._showSettingsImportError(toError(error));
}
}
diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js
index eadfcb91..0c2fa7a5 100644
--- a/ext/js/pages/settings/dictionary-import-controller.js
+++ b/ext/js/pages/settings/dictionary-import-controller.js
@@ -18,6 +18,7 @@
import {log} from '../../core.js';
import {ExtensionError} from '../../core/extension-error.js';
+import {toError} from '../../core/to-error.js';
import {DictionaryWorker} from '../../dictionary/dictionary-worker.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {yomitan} from '../../yomitan.js';
@@ -126,7 +127,7 @@ export class DictionaryImportController {
this._showErrors(errors);
}
} catch (error) {
- this._showErrors([error instanceof Error ? error : new Error(`${error}`)]);
+ this._showErrors([toError(error)]);
} finally {
prevention.end();
this._setModifying(false);
@@ -200,7 +201,7 @@ export class DictionaryImportController {
await this._importDictionary(files[i], importDetails, onProgress);
}
} catch (err) {
- this._showErrors([err instanceof Error ? err : new Error(`${err}`)]);
+ this._showErrors([toError(err)]);
} finally {
prevention.end();
for (const progress of progressContainers) { progress.hidden = true; }
diff --git a/ext/js/pages/settings/mecab-controller.js b/ext/js/pages/settings/mecab-controller.js
index 9c55c9a0..f57bc3c9 100644
--- a/ext/js/pages/settings/mecab-controller.js
+++ b/ext/js/pages/settings/mecab-controller.js
@@ -16,6 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {toError} from '../../core/to-error.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {yomitan} from '../../yomitan.js';
@@ -57,7 +58,7 @@ export class MecabController {
await yomitan.api.testMecab();
this._setStatus('Connection was successful', false);
} catch (e) {
- this._setStatus(e instanceof Error ? e.message : `${e}`, true);
+ this._setStatus(toError(e).message, true);
} finally {
this._testActive = false;
/** @type {HTMLButtonElement} */ (this._testButton).disabled = false;
diff --git a/ext/js/pages/settings/permissions-origin-controller.js b/ext/js/pages/settings/permissions-origin-controller.js
index 3a9db602..73f06a56 100644
--- a/ext/js/pages/settings/permissions-origin-controller.js
+++ b/ext/js/pages/settings/permissions-origin-controller.js
@@ -17,6 +17,7 @@
*/
import {EventListenerCollection} from '../../core.js';
+import {toError} from '../../core/to-error.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
export class PermissionsOriginController {
@@ -155,7 +156,7 @@ export class PermissionsOriginController {
} catch (e) {
const errorContainer = /** @type {HTMLElement} */ (this._errorContainer);
errorContainer.hidden = false;
- errorContainer.textContent = e instanceof Error ? e.message : `${e}`;
+ errorContainer.textContent = toError(e).message;
}
if (!added) { return false; }
await this._updatePermissions();
diff --git a/ext/js/pages/settings/recommended-permissions-controller.js b/ext/js/pages/settings/recommended-permissions-controller.js
index a870de50..0500759e 100644
--- a/ext/js/pages/settings/recommended-permissions-controller.js
+++ b/ext/js/pages/settings/recommended-permissions-controller.js
@@ -17,6 +17,7 @@
*/
import {EventListenerCollection} from '../../core.js';
+import {toError} from '../../core/to-error.js';
export class RecommendedPermissionsController {
/**
@@ -92,7 +93,7 @@ export class RecommendedPermissionsController {
} catch (e) {
if (this._errorContainer !== null) {
this._errorContainer.hidden = false;
- this._errorContainer.textContent = e instanceof Error ? e.message : `${e}`;
+ this._errorContainer.textContent = toError(e).message;
}
}
if (!added) { return false; }