css-houdini-drafts
css-houdini-drafts copied to clipboard
[worklets] Add ability to determine if a module is available
While the addModule()
method available on Worklets lets you load and install modules into the worklet, and uses a promise to let the caller know success or failure, there's no after-the-fact method available to determine the state of the module.
One scenario (slightly contrived but not in a very improbable way) in which this could come into play is a function which is used to set up a new AudioWorkletNode
that looks like this:
let audioInfo = {
audioContext: null,
myAudioProcessor: null,
...
};
async function createMyAudioProcessor() {
if (!audioInfo.audioContext) {
try {
audioInfo.audioContext = new AudioContext();
await audioInfo.audioContext.resume();
await audioInfo.audioContext.audioWorklet.addModule(
"module-url/module.js");
} catch(e) {
return null;
}
}
return new AudioWorkletNode(audioInfo.audioContext,
"processor-name");
}
This function checks the specified AudioContext
to see if it's null
and if it is, creates the context and installs the processor module into it before then proceeding to create a new AudioWorkletNode
and return it to the caller.
However, if the user does the following, there's a problem:
let audioInfo.audioContext = new AudioContext();
let audioInfo.myAudioProcessor = createMyProcessor(context);
This will fail because the module hasn't been loaded. To solve problems like this, a method to determine if the module has been loaded would be helpful. That would let the createMyAudioProcessor()
function become something like:
async function createMyAudioProcessor() {
if (!audioInfo.audioContext) {
try {
audioInfo.audioContext = new AudioContext();
await audioInfo.audioContext.resume();
} catch(e) {
return null;
}
}
if (!audioContext.isModuleLoaded("module-url/module.js") {
await audioInfo.audioContext.audioWorklet.addModule(
"module-url/module.js");
}
return new AudioWorkletNode(audioInfo.audioContext,
"processor-name");
}
This now will work even if the context has already been created:
let audioInfo = {
audioContext: null,
myAudioProcessor: null,
...
};
audioInfo.audioContext = new AudioContext();
audioInfo.myAudioProcessor = createMyAudioProcessor();
An alternative to isModuleLoaded()
would be a method on Worklet
that returns a status string, such as:
let moduleStatus = audioContext.audioWorklet.getModuleStatus(
"module-url/module.js");
This could also be done at the AudioWorklet
level to ask about a processor rather than a module:
let moduleStatus = audioContext.audioWorklet.getProcessorStatus(
"processor-name");
The could be a string such as available
or unavailable
, with the possibility of other statuses.
Worklets have moved to HTML, so now I am on point for issue triage :).
@hoch @nhiroki @padenot what do you think of this feature request? It'd be quite easy to spec at the generic worklet level. Or should it be audio worklet-specific, as outlined toward the end of the post?
This sounds useful. In addition, we need something to remove a loaded module. This has been specifically requested by the community.
Regarding AudioWorklet-specific getProcessorStatus()
, I have no opinions. I'd like to hear @hoch's thoughts.
Regarding generic isModuleLoaded()
and getModuleStatus()
, implementation-wise it'd be easy to implement this in Chromium. I assume each entry in the Worklet's module responses map will have a status bit.
cc: @hiroshige-g , let us know if you have any thoughts on this especially from the perspective of module script.
Does the use case want to know if module script files are not only loaded but also evaluated? If so, this could be a bit complicated because the Worklet's module responses map doesn't know which module script files are included in the compiled module script to be evaluated.