diff --git a/packages/@textlint/script-compiler/src/CodeGenerator/worker-codegen.ts b/packages/@textlint/script-compiler/src/CodeGenerator/worker-codegen.ts index 82ded81..c8c5848 100644 --- a/packages/@textlint/script-compiler/src/CodeGenerator/worker-codegen.ts +++ b/packages/@textlint/script-compiler/src/CodeGenerator/worker-codegen.ts @@ -40,10 +40,22 @@ export type TextlintWorkerCommandResponseFix = { command: "fix:result"; result: TextlintFixResult; }; +export type TextlintWorkerCommandResponseLintError = { + id: MessageId | undefined; + command: "lint:error"; + error: any; +}; +export type TextlintWorkerCommandResponseFixError = { + id: MessageId | undefined; + command: "fix:error"; + error: any; +}; export type TextlintWorkerCommandResponse = | TextlintWorkerCommandResponseInit | TextlintWorkerCommandResponseLint - | TextlintWorkerCommandResponseFix; + | TextlintWorkerCommandResponseFix + | TextlintWorkerCommandResponseLintError + | TextlintWorkerCommandResponseFixError; export const generateCode = async (config: TextlintConfigDescriptor) => { // macro replacement @@ -139,6 +151,12 @@ self.addEventListener('message', (event) => { command: "lint:result", result }); + }).catch(error => { + return self.postMessage({ + id: data.id, + command: "lint:error", + error + }); }); case "fix": return kernel.fixText(data.text, { @@ -153,6 +171,12 @@ self.addEventListener('message', (event) => { command: "fix:result", result }); + }).catch(error => { + return self.postMessage({ + id: data.id, + command: "fix:error", + error + }); }); default: console.log("Unknown command: " + data.command); diff --git a/packages/textchecker-element/index.ts b/packages/textchecker-element/index.ts index 2c3bbb9..90b58b1 100644 --- a/packages/textchecker-element/index.ts +++ b/packages/textchecker-element/index.ts @@ -41,16 +41,40 @@ const generateMessageId = () => crypto.randomUUID(); const createTextlint = ({ worker, ext }: { worker: Worker; ext: string }) => { const lintText: LintEngineAPI["lintText"] = async ({ text }: { text: string }): Promise => { updateStatus("linting..."); - return new Promise((resolve, _reject) => { + return new Promise((resolve, reject) => { const id = generateMessageId(); - worker.addEventListener("message", function handler(event) { - const data: TextlintWorkerCommandResponse = event.data; - if (data.command === "lint:result" && data.id === id) { - resolve([data.result]); - worker.removeEventListener("message", handler); + function onMessage(event: MessageEvent) { + const data = event.data; + if ("id" in data && data.id === id) { + if (data.command === "lint:error") { + reject(data.error); + updateStatus("failed to lint"); + } else if (data.command === "lint:result") { + resolve([data.result]); + updateStatus("linted"); + } + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); } - updateStatus("linted"); - }); + } + function onMessageError(event: MessageEvent) { + reject(new Error(event.data)); + updateStatus("failed to lint"); + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); + } + function onError(event: ErrorEvent) { + reject(new Error(event.message)); + updateStatus("failed to lint"); + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); + } + worker.addEventListener("message", onMessage); + worker.addEventListener("messageerror", onMessageError); + worker.addEventListener("error", onError); return worker.postMessage({ id, command: "lint", @@ -67,16 +91,40 @@ const createTextlint = ({ worker, ext }: { worker: Worker; ext: string }) => { message?: TextlintMessage; }): Promise => { updateStatus("fixing..."); - return new Promise((resolve, _reject) => { + return new Promise((resolve, reject) => { const id = generateMessageId(); - worker.addEventListener("message", function handler(event) { - const data: TextlintWorkerCommandResponse = event.data; - if (data.command === "fix:result" && data.id === id) { - resolve(data.result); - worker.removeEventListener("message", handler); + function onMessage(event: MessageEvent) { + const data = event.data; + if ("id" in data && data.id === id) { + if (data.command === "fix:error") { + reject(data.error); + updateStatus("failed to fix"); + } else if (data.command === "fix:result") { + resolve(data.result); + updateStatus("fixed"); + } + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); } - updateStatus("fixed"); - }); + } + function onMessageError(event: MessageEvent) { + reject(event.data); + updateStatus("failed to fix"); + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); + } + function onError(event: ErrorEvent) { + reject(event); + updateStatus("failed to fix"); + worker.removeEventListener("message", onMessage); + worker.removeEventListener("messageerror", onMessageError); + worker.removeEventListener("error", onError); + } + worker.addEventListener("message", onMessage); + worker.addEventListener("messageerror", onMessageError); + worker.addEventListener("error", onError); return worker.postMessage({ id, command: "fix", diff --git a/packages/textchecker-element/src/attach-to-text-area.ts b/packages/textchecker-element/src/attach-to-text-area.ts index 0b74ccd..8f8a873 100644 --- a/packages/textchecker-element/src/attach-to-text-area.ts +++ b/packages/textchecker-element/src/attach-to-text-area.ts @@ -155,9 +155,15 @@ export const attachToTextArea = ({ // dismiss card before update annotations // dismissCards(); const text = textAreaElement.value; - const results = await lintEngine.lintText({ - text - }); + let results; + try { + results = await lintEngine.lintText({ + text + }); + } catch (e) { + debug("lint error", e); + results = [] as const; + } debug("lint results", results); const updateText = async (newText: string, card: TextCheckerCard) => { const currentText = textAreaElement.value; diff --git a/packages/webextension/app/scripts/background/textlint.ts b/packages/webextension/app/scripts/background/textlint.ts index e4458a4..87a6140 100644 --- a/packages/webextension/app/scripts/background/textlint.ts +++ b/packages/webextension/app/scripts/background/textlint.ts @@ -56,15 +56,36 @@ export const createTextlintWorker = (script: Script) => { const defaultWorker = new Worker(workerUrl); const workerRef = createWorkerRef(defaultWorker); const lintText = async ({ text, ext }: { text: string; ext: string }): Promise => { - return new Promise((resolve, _reject) => { + return new Promise((resolve, reject) => { const id = generateMessageId(); - workerRef.current.addEventListener("message", function handler(event) { - const data: TextlintWorkerCommandResponse = event.data; - if (data.command === "lint:result" && data.id === id) { - resolve([data.result]); - workerRef.current.removeEventListener("message", handler); + function onMessage(event: MessageEvent) { + const data = event.data; + if ("id" in data && data.id === id) { + if (data.command === "lint:error") { + reject(data.error); + } else if (data.command === "lint:result") { + resolve([data.result]); + } + workerRef.current.removeEventListener("message", onMessage); + workerRef.current.removeEventListener("messageerror", onMessageError); + workerRef.current.removeEventListener("error", onError); } - }); + } + function onMessageError(event: MessageEvent) { + reject(event.data); + workerRef.current.removeEventListener("message", onMessage); + workerRef.current.removeEventListener("messageerror", onMessageError); + workerRef.current.removeEventListener("error", onError); + } + function onError(event: ErrorEvent) { + reject(event); + workerRef.current.removeEventListener("message", onMessage); + workerRef.current.removeEventListener("messageerror", onMessageError); + workerRef.current.removeEventListener("error", onError); + } + workerRef.current.addEventListener("message", onMessage); + workerRef.current.addEventListener("messageerror", onMessageError); + workerRef.current.addEventListener("error", onError); return workerRef.current.postMessage({ id, command: "lint",