css-houdini-drafts icon indicating copy to clipboard operation
css-houdini-drafts copied to clipboard

[worklets] Add ability to determine if a module is available

Open a2sheppy opened this issue 4 years ago • 4 comments

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.

a2sheppy avatar Apr 30 '20 21:04 a2sheppy

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?

domenic avatar Oct 16 '20 18:10 domenic

This sounds useful. In addition, we need something to remove a loaded module. This has been specifically requested by the community.

padenot avatar Oct 19 '20 08:10 padenot

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.

nhiroki avatar Oct 19 '20 13:10 nhiroki

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.

nhiroki avatar Oct 19 '20 13:10 nhiroki