Script evaluation in AudioWorkletGlobalScope: global variables are unreachable |
||
Issue descriptionRepro: https://glitch.com/edit/#!/aw-example-1 Multiple addModule() call on AudioWorklet doesn't seem to be sharing the same GlobalScope. The code implicates Chrome only creates a single AWGS, so the global variables in the scope should be visible even if the code is loaded by different addModule() call. Consider the following example: ``` /** AWGS, file A **/ function rand() { return Math.random() * 2 - 1; } ``` ``` /** AWGS, file B **/ class MyProcessor extends AudioWorkletProcessor { process() { console.log(rand()); return false; } } ``` ``` /** index.js **/ const audioContext = new AudioContext(); async function load() { await audioContext.audioWorklet.addModule('file-a.js'); return await audioContext.audioWorklet.addModule('file-b.js'); } load().then(() => { const workletNode = new AudioWorkletNode(audioContext, 'my-processor'); workletNode.connect(audioContext.destination); }); ``` If the file A is fetched/invoked before the file B, rand() function call should work. Currently Chrome throws an exception: Uncaught ReferenceError: rand is not defined at AudioWorkletProcessor.process (awgs-processor.js:...) WDYT? nhiroki@
,
Jun 10 2018
Hi, I filed the original issue on GitHub. I tried the suggestion by nhiroki, however it results in a new error for me: "Uncaught (in promise) DOMException: The user aborted a request." I've attached my test code. I'm running Chrome Version 66.0.3359.181 on Mac OS 10.11.6. Best, Aatish
,
Jun 10 2018
Live version here: https://glitch.com/edit/#!/indigo-ptarmigan
,
Jun 11 2018
It looks like the given module path for static import is invalid. Static import requires an absolute path or a relative path with "./" prefix like this: import "./loop.js"; Unfortunately, an error of import failures on worklets is not really helpful (issue 782066). We'll rethink the priority of the issue.
,
Jun 11 2018
nhiroki@ I was unaware that you can use 'import' in WorkletGlobalScope. This was the decision I knew - https://github.com/w3c/css-houdini-drafts/issues/506. Has it been changed somehow? Can you provide a reference for it? If this change is official, it could be a good news for many AudioWorklet developers. On the other hand, this opens up the network stack with a blocking operation thus calling it while rendering audio can cause glitches.
,
Jun 11 2018
I also can confirm that the global function in the imported script is not visible from the "file-b" side. Do we need an experimental flag on this? (69.0.3453.3 Canary, MacOS)
,
Jun 11 2018
@nhiroki Thanks for the info, this was helpful. Just using import did not work for me as this seems to run the module code but not import the variables (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import). However adding export {functionName}; to the end of file-a.js and adding import {functionName} from './file-a.js' to the start of file-b.js did the trick. My use case is somewhat specific.. I'm working on a wrapper for web audio worklet so that any user written code can be easily run on a worklet. (similar to: https://acarabott.github.io/audio-dsp-playground/ ) Ideally I would like to import all user defined functions (without knowing in advance what these might be called) into the scope of the worklet where they can be executed. Currently the workaround I'm using to do this is data URLs + template literals: https://github.com/aatishb/synthfromscratch/tree/master/sine-wave That works fine for me, but I'm curious if there's any other simpler way to import all variables from a file into the worklet scope.
,
Jun 11 2018
aatish@ Thanks for bringing this to my attention. Your use case is not really specific. I can assure you that many WebAudio developers in the slack channel will be happy to see this. This is how we make the code scales. :) There is still a question I have above, but that's not a part of the reported issue. I am closing this.
,
Jun 11 2018
c#5: The issue disallows "dynamic import" that runs on script evaluation phase, but not disallow "static import" that runs script parse phase. This is because "dynamic import" potentially violates the "code idempotency" rule defined in the Worklets spec.
// hello-world.js
export const message = "Hello, world!";
// static import
import * as module from "./hello-world.js";
console.log(module.message);
// dynamic import
import('./hello-world.js').then(module => console.log(module.message));
,
Jun 11 2018
Thanks for clarification!
,
Jun 11 2018
c#7: I think the data URL is the simplest way if user code is not modifiable.
In general it would be better that user code imports a library than the library imports user code in terms of code modularity like this:
// library.js
export function doSomething() { ... }
export const value = "42";
// user.js
import * as library from './library.js'
library.doSomething();
userFunc(library.value);
Inlining libraries (variables and functions) may cause namescope conflict that ES Modules is trying to avoid.
|
||
►
Sign in to add a comment |
||
Comment 1 by nhiroki@chromium.org
, Jun 10 2018