This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
# ADR 0001: Run Piper in an ES module worker
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Bundle the Piper worker as an ES module and start it with `new Worker(url, { type: 'module' })`.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Piper loads ONNX Runtime Web and its WebAssembly loader dynamically. The current IIFE/classic worker bundle reports `TypeError: "undefined" cannot be parsed as a URL` during WASM backend initialization, even though the pinned same-origin ONNX loader and binary are available. This is consistent with module-relative URL metadata being lost in the classic bundle.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
The browser must support module workers. Current supported browser targets already require modern WebAssembly and worker support. CI asserts that the worker is built and started in module mode; production acceptance remains the real deployed browser flow.
|
||||||
+3
-1
@@ -6,7 +6,9 @@ const pending = new Map();
|
|||||||
|
|
||||||
function getWorker() {
|
function getWorker() {
|
||||||
if (worker) return worker;
|
if (worker) return worker;
|
||||||
worker = new Worker(workerUrl);
|
// ONNX Runtime resolves its WASM loader relative to the worker module URL.
|
||||||
|
// Keep the worker as ESM so import.meta.url remains available at runtime.
|
||||||
|
worker = new Worker(workerUrl, {type: 'module'});
|
||||||
worker.onmessage = event => {
|
worker.onmessage = event => {
|
||||||
const message = event.data || {};
|
const message = event.data || {};
|
||||||
const request = pending.get(message.id);
|
const request = pending.get(message.id);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ await build({
|
|||||||
entryPoints: [resolve(root, 'piper-worker.js')],
|
entryPoints: [resolve(root, 'piper-worker.js')],
|
||||||
outfile: join(workerRoot, 'piper-worker.js'),
|
outfile: join(workerRoot, 'piper-worker.js'),
|
||||||
bundle: true,
|
bundle: true,
|
||||||
format: 'iife',
|
format: 'esm',
|
||||||
platform: 'browser',
|
platform: 'browser',
|
||||||
target: ['es2022'],
|
target: ['es2022'],
|
||||||
external: ['fs', 'path'],
|
external: ['fs', 'path'],
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ grep -q 'COPY public/tts/piper-wasm-v1/' Dockerfile
|
|||||||
grep -q 'build:piper' .gitea/workflows/publish.yaml
|
grep -q 'build:piper' .gitea/workflows/publish.yaml
|
||||||
grep -q 'Piper' piper-runtime.js
|
grep -q 'Piper' piper-runtime.js
|
||||||
grep -q 'sv_SE-nst-medium' piper-worker.js
|
grep -q 'sv_SE-nst-medium' piper-worker.js
|
||||||
grep -q 'new Worker(workerUrl)' piper-runtime.js
|
grep -q "new Worker(workerUrl, {type: 'module'})" piper-runtime.js
|
||||||
grep -q 'worker.js?v=' piper-runtime.js
|
grep -q 'worker.js?v=' piper-runtime.js
|
||||||
grep -q 'worker.onmessageerror' piper-runtime.js
|
grep -q 'worker.onmessageerror' piper-runtime.js
|
||||||
grep -q 'localPiperModelUrl' piper-worker.js
|
grep -q 'localPiperModelUrl' piper-worker.js
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
const test = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const {readFile} = require('node:fs/promises');
|
||||||
|
const {join} = require('node:path');
|
||||||
|
|
||||||
|
test('Piper worker is built and started as an ES module', async () => {
|
||||||
|
const [buildScript, runtime] = await Promise.all([
|
||||||
|
readFile(join(__dirname, '..', 'scripts', 'build-piper.mjs'), 'utf8'),
|
||||||
|
readFile(join(__dirname, '..', 'piper-runtime.js'), 'utf8'),
|
||||||
|
]);
|
||||||
|
assert.match(buildScript, /outfile: join\(workerRoot, 'piper-worker\.js'\),\s*bundle: true,\s*format: 'esm'/);
|
||||||
|
assert.match(runtime, /new Worker\(workerUrl, \{type: 'module'\}\)/);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user