node-web-audio-api 0.21.3 → 0.21.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/js/AudioWorklet.js +31 -27
- package/js/AudioWorkletGlobalScope.js +14 -8
- package/js/AudioWorkletNode.js +2 -1
- package/node-web-audio-api.darwin-arm64.node +0 -0
- package/node-web-audio-api.darwin-x64.node +0 -0
- package/node-web-audio-api.linux-arm-gnueabihf.node +0 -0
- package/node-web-audio-api.linux-arm64-gnu.node +0 -0
- package/node-web-audio-api.linux-x64-gnu.node +0 -0
- package/node-web-audio-api.win32-arm64-msvc.node +0 -0
- package/node-web-audio-api.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.21.5 (23/12/2024)
|
|
4
|
+
|
|
5
|
+
- Fix: Use module import for `AudioWorklet#addModule`
|
|
6
|
+
- Feat: Resolve `AudioWorkletNode` when installed in `node_modules`
|
|
7
|
+
- Ensure support of `AudioWorkletNode` that use Web Assembly
|
|
8
|
+
|
|
9
|
+
## v0.21.4 (16/12/2024)
|
|
10
|
+
|
|
11
|
+
- Update upstream crate to [v1.1.0](https://github.com/orottier/web-audio-api-rs/blob/main/CHANGELOG.md#version-110-2024-12-11)
|
|
12
|
+
|
|
3
13
|
## v0.21.3 (06/10/2024)
|
|
4
14
|
|
|
5
15
|
- Fix typescript export
|
package/js/AudioWorklet.js
CHANGED
|
@@ -28,40 +28,38 @@ const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch
|
|
|
28
28
|
/**
|
|
29
29
|
* Retrieve code with different module resolution strategies
|
|
30
30
|
* - file - absolute or relative to cwd path
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
31
|
+
*
|
|
32
|
+
* - URL - do not support import within module
|
|
33
|
+
* - Blob - do not support import within module
|
|
33
34
|
* - fallback: relative to caller site
|
|
34
|
-
* + in fs
|
|
35
|
+
* + in fs - support import within module
|
|
35
36
|
* + caller site is url - required for wpt, probably no other use case
|
|
36
37
|
*/
|
|
37
38
|
const resolveModule = async (moduleUrl) => {
|
|
38
|
-
let code;
|
|
39
|
+
let code = null;
|
|
40
|
+
let absPathname = null;
|
|
39
41
|
|
|
40
42
|
if (existsSync(moduleUrl)) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
code = buffer.toString();
|
|
46
|
-
} catch (err) {
|
|
47
|
-
throw new Error(`Failed to execute 'addModule' on 'AudioWorklet': ${err.message}`);
|
|
43
|
+
if (path.isAbsolute(moduleUrl)) {
|
|
44
|
+
absPathname = moduleUrl;
|
|
45
|
+
} else { // moduleUrl is relative to process.cwd();
|
|
46
|
+
absPathname = path.join(process.cwd(), moduleUrl);
|
|
48
47
|
}
|
|
49
48
|
} else if (moduleUrl.startsWith('http')) {
|
|
50
49
|
try {
|
|
51
50
|
const res = await fetch(moduleUrl);
|
|
52
51
|
code = await res.text();
|
|
53
52
|
} catch (err) {
|
|
54
|
-
throw new
|
|
53
|
+
throw new DOMException(`Failed to execute 'addModule' on 'AudioWorklet': ${err.message}`, 'AbortError');
|
|
55
54
|
}
|
|
56
55
|
} else if (moduleUrl.startsWith('blob:')) {
|
|
57
56
|
try {
|
|
58
57
|
const blob = resolveObjectURL(moduleUrl);
|
|
59
58
|
code = await blob.text();
|
|
60
59
|
} catch (err) {
|
|
61
|
-
throw new
|
|
60
|
+
throw new DOMException(`Failed to execute 'addModule' on 'AudioWorklet': ${err.message}`, 'AbortError');
|
|
62
61
|
}
|
|
63
62
|
} else {
|
|
64
|
-
// get caller site from error stack trace
|
|
65
63
|
const callerSite = caller(2);
|
|
66
64
|
|
|
67
65
|
if (callerSite.startsWith('http')) { // this branch exists for wpt where caller site is an url
|
|
@@ -80,27 +78,28 @@ const resolveModule = async (moduleUrl) => {
|
|
|
80
78
|
const res = await fetch(url);
|
|
81
79
|
code = await res.text();
|
|
82
80
|
} catch (err) {
|
|
83
|
-
throw new
|
|
81
|
+
throw new DOMException(`Failed to execute 'addModule' on 'AudioWorklet': ${err.message}`, 'AbortError');
|
|
84
82
|
}
|
|
85
83
|
} else {
|
|
86
|
-
|
|
84
|
+
// filesystem, relative to caller site or in node_modules
|
|
85
|
+
const dirname = callerSite.substring(0, callerSite.lastIndexOf(path.sep));
|
|
87
86
|
const absDirname = dirname.replace('file://', '');
|
|
88
87
|
const pathname = path.join(absDirname, moduleUrl);
|
|
89
88
|
|
|
90
|
-
if (existsSync(pathname)) {
|
|
89
|
+
if (existsSync(pathname)) { // relative to caller site
|
|
90
|
+
absPathname = pathname;
|
|
91
|
+
} else {
|
|
91
92
|
try {
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
// try resolve according to process.cwd()
|
|
94
|
+
absPathname = require.resolve(moduleUrl, { paths: [process.cwd()] });
|
|
94
95
|
} catch (err) {
|
|
95
|
-
throw new
|
|
96
|
+
throw new DOMException(`Failed to execute 'addModule' on 'AudioWorklet': Cannot resolve module ${moduleUrl}`, 'AbortError');
|
|
96
97
|
}
|
|
97
|
-
} else {
|
|
98
|
-
throw new Error(`Failed to execute 'addModule' on 'AudioWorklet': Cannot resolve module ${moduleUrl}`);
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
return code;
|
|
102
|
+
return { absPathname, code };
|
|
104
103
|
}
|
|
105
104
|
|
|
106
105
|
class AudioWorklet {
|
|
@@ -125,6 +124,9 @@ class AudioWorklet {
|
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
#bindEvents() {
|
|
127
|
+
// @todo
|
|
128
|
+
// - better error handling, stack trace, etc.
|
|
129
|
+
// - handle 'node-web-audio-api:worklet:ctor-error' message
|
|
128
130
|
this.#port.on('message', event => {
|
|
129
131
|
switch (event.cmd) {
|
|
130
132
|
case 'node-web-audio-api:worklet:module-added': {
|
|
@@ -135,10 +137,9 @@ class AudioWorklet {
|
|
|
135
137
|
break;
|
|
136
138
|
}
|
|
137
139
|
case 'node-web-audio-api:worklet:add-module-failed': {
|
|
138
|
-
const { promiseId,
|
|
140
|
+
const { promiseId, err } = event;
|
|
139
141
|
const { reject } = this.#idPromiseMap.get(promiseId);
|
|
140
142
|
this.#idPromiseMap.delete(promiseId);
|
|
141
|
-
const err = new globalThis[ctor](message, name);
|
|
142
143
|
reject(err);
|
|
143
144
|
break;
|
|
144
145
|
}
|
|
@@ -161,7 +162,9 @@ class AudioWorklet {
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
async addModule(moduleUrl) {
|
|
164
|
-
|
|
165
|
+
// @important - `resolveModule` must be called first because it uses `caller`
|
|
166
|
+
// which will return `null` if this is not in the first line...
|
|
167
|
+
const resolved = await resolveModule(moduleUrl);
|
|
165
168
|
|
|
166
169
|
// launch Worker if not exists
|
|
167
170
|
if (!this.#port) {
|
|
@@ -187,7 +190,8 @@ class AudioWorklet {
|
|
|
187
190
|
|
|
188
191
|
this.#port.postMessage({
|
|
189
192
|
cmd: 'node-web-audio-api:worklet:add-module',
|
|
190
|
-
|
|
193
|
+
moduleUrl: resolved.absPathname,
|
|
194
|
+
code: resolved.code,
|
|
191
195
|
promiseId,
|
|
192
196
|
});
|
|
193
197
|
});
|
|
@@ -298,7 +298,7 @@ globalThis.registerProcessor = function registerProcessor(name, processorCtor) {
|
|
|
298
298
|
// process.stdout.write('closing worklet');
|
|
299
299
|
// });
|
|
300
300
|
|
|
301
|
-
parentPort.on('message', event => {
|
|
301
|
+
parentPort.on('message', async event => {
|
|
302
302
|
switch (event.cmd) {
|
|
303
303
|
case 'node-web-audio-api:worklet:init': {
|
|
304
304
|
const { workletId, processors, promiseId } = event;
|
|
@@ -313,11 +313,18 @@ parentPort.on('message', event => {
|
|
|
313
313
|
break;
|
|
314
314
|
}
|
|
315
315
|
case 'node-web-audio-api:worklet:add-module': {
|
|
316
|
-
const { code, promiseId } = event;
|
|
317
|
-
const func = new Function('AudioWorkletProcessor', 'registerProcessor', code);
|
|
316
|
+
const { moduleUrl, code, promiseId } = event;
|
|
318
317
|
|
|
319
318
|
try {
|
|
320
|
-
|
|
319
|
+
// 1. If given module is a "real" file, we can import it as is,
|
|
320
|
+
// 2. If module is a blob or loaded from an URL, we use the raw text as
|
|
321
|
+
// input. In this case, if the module uses `import` it will crash
|
|
322
|
+
if (moduleUrl !== null) {
|
|
323
|
+
await import(moduleUrl);
|
|
324
|
+
} else {
|
|
325
|
+
await import(`data:text/javascript;base64,${btoa(unescape(encodeURIComponent(code)))}`);
|
|
326
|
+
}
|
|
327
|
+
|
|
321
328
|
// send registered param descriptors on main thread and resolve Promise
|
|
322
329
|
parentPort.postMessage({
|
|
323
330
|
cmd: 'node-web-audio-api:worklet:module-added',
|
|
@@ -327,9 +334,7 @@ parentPort.on('message', event => {
|
|
|
327
334
|
parentPort.postMessage({
|
|
328
335
|
cmd: 'node-web-audio-api:worklet:add-module-failed',
|
|
329
336
|
promiseId,
|
|
330
|
-
|
|
331
|
-
name: err.name,
|
|
332
|
-
message: err.message,
|
|
337
|
+
err,
|
|
333
338
|
});
|
|
334
339
|
}
|
|
335
340
|
break;
|
|
@@ -338,7 +343,7 @@ parentPort.on('message', event => {
|
|
|
338
343
|
const { name, id, options, port } = event;
|
|
339
344
|
const ctor = nameProcessorCtorMap.get(name);
|
|
340
345
|
|
|
341
|
-
//
|
|
346
|
+
// re-wrap options of interest for the AudioWorkletNodeBaseClass
|
|
342
347
|
pendingProcessorConstructionData = {
|
|
343
348
|
port,
|
|
344
349
|
numberOfInputs: options.numberOfInputs,
|
|
@@ -352,6 +357,7 @@ parentPort.on('message', event => {
|
|
|
352
357
|
instance = new ctor(options);
|
|
353
358
|
} catch (err) {
|
|
354
359
|
port.postMessage({ cmd: 'node-web-audio-api:worklet:ctor-error', err });
|
|
360
|
+
return;
|
|
355
361
|
}
|
|
356
362
|
|
|
357
363
|
pendingProcessorConstructionData = null;
|
package/js/AudioWorkletNode.js
CHANGED
|
@@ -222,7 +222,8 @@ module.exports = (jsExport, nativeBinding) => {
|
|
|
222
222
|
);
|
|
223
223
|
|
|
224
224
|
this.#port.on('message', msg => {
|
|
225
|
-
//
|
|
225
|
+
// Handle 'processorerror' ErrorEvent
|
|
226
|
+
// cf. https://webaudio.github.io/web-audio-api/#dom-audioworkletnode-onprocessorerror
|
|
226
227
|
switch (msg.cmd) {
|
|
227
228
|
case 'node-web-audio-api:worklet:ctor-error': {
|
|
228
229
|
const message = `Failed to construct '${parsedName}' AudioWorkletProcessor: ${msg.err.message}`;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|