Skip to content

Revise instantiation process of AudioWorkletNode and AudioWorkletProcessor #1265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 24, 2017

Conversation

hoch
Copy link
Member

@hoch hoch commented Jun 21, 2017

@hoch
Copy link
Member Author

hoch commented Jun 26, 2017

@annevk It would be great to have your feedback here as well. @domenic helped a lot when I started working on this.

index.html Outdated
<dd>
Belongs to <a>BaseAudioContext</a>. This contains a collection of
<a>AudioParamDescriptor</a>s with an associated string key of
node name. This internal storage is populated from <a>node name

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would reference the preceding definition of the string key so that it is clearer that the keys are the same in both internal maps.

index.html Outdated
When <a>AudioWorkletNode</a>(<var>context</var>, <var>name</var>,
<var>options</var>) constructor is called, the user agent must run
the following steps <a data-lt="atomic">atomically</a>.
Note that the instantiation of these two objects spans with the

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo - remove "with"

index.html Outdated
<li>Return <var>this</var> as a result of the construction.
<li>Queue a task the <a>control thread</a> to fire
<code>running</code> event to the associated
<a>AudioWorkletNode</a>.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be described as "setting the node's state to running and firing a state change event"?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, should the communication of the parameter descriptors list to the control thread be mentioned here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is correct that queueing a task 1) to change the node state and 2) to fire a state change event. In the rendering thread, the node's state cannot be changed.

Also the communication of parameter descriptors does not happen at the individual regsiterProcessor call. The synchronization of registered definitions should happen at the end of addModule() call. I filed an issue for this step.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not seeing a clarification of the nature of the event -- the point is that 1) the change in the node state is not an event, but an action by the control thread task, and 2) the event is astatechange event not a running event/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. I will make the fix.

@annevk
Copy link

annevk commented Jun 27, 2017

In the preview "Queue a control message" is a dead link.

"If processorConstructor is undefined, throw a NotSupportedError DOMException." this happens in the rendering thread, but where would this exception end up? There's no global.onerror to catch them, right? Might as well terminate these steps then? Or maybe there's other ways to create these objects where the exception would be observable?

@hoch
Copy link
Member Author

hoch commented Jun 30, 2017

@annevk A good point. The PaintWorklet spec also throws when anything bad happens in PaintWorkletGlobalScope. (e.g. registerPaint() call) I am not sure how this behavior is explained in that spec. Perhaps it has the same issue?

WorkletGlobalScope.onerror actually makes sense. That way we can delegate user agents with how to handle a thrown exception.

@hoch hoch force-pushed the revise-awn-awp-instantiation branch 2 times, most recently from 0f41913 to 20b5f76 Compare June 30, 2017 23:17
@hoch
Copy link
Member Author

hoch commented Jun 30, 2017

Sorry for the messy commits. Please take a look at the last one: 0f41913

@padenot
Copy link
Member

padenot commented Jul 4, 2017

This really needs to be rebased cleanly on top of gh-pages, I can't make sense of it. Let me know if you need help.

@joeberkovitz
Copy link

@hoch I can't review this yet either, it includes a bunch of diffs from unmerged commits in gh-pages

@hoch
Copy link
Member Author

hoch commented Jul 6, 2017

Sorry, I think I have to recreate a PR. I failed to rebase it cleanly and now it is difficult to resolve it. I have to cherry-pick my own edits and replay them on top of the current gh-pages.

@hoch hoch closed this Jul 6, 2017
@padenot
Copy link
Member

padenot commented Jul 6, 2017

Yes, that's what you should do. You can then force-push to this branch and it will be clean. No need to close and re-open.

@padenot padenot reopened this Jul 6, 2017
@hoch hoch force-pushed the revise-awn-awp-instantiation branch from ea6f033 to 4340858 Compare July 6, 2017 20:10
@hoch
Copy link
Member Author

hoch commented Jul 6, 2017

@padenot @joeberkovitz Sorry for the confusion and updated the PR with the force-push.

Preview

index.html Outdated
populated when a promise from <a href=
"https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule">addModule()</a>
on <a href="#widl-Window-audioWorklet">audioWorklet</a> gets
resolevd.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: resolevd

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

index.html Outdated
<a>AudioWorkletGlobalScope</a>’s <a>node name to processor
definition map</a>, throw a <code>NotSupportedError</code>
exception and abort these steps.
exception and abort these steps. <a>BaseAudioContext</a>’s <a>node

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you had a merge problem here with duplicated language. I assume that the control thread only checks the BaseAudioContext map, not the AWGS map.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. It was a mistake.

index.html Outdated
an exception (either explicitly or implicitly), abort the rest of
steps and queue a task on the control thread to fire <a href=
"#widl-AudioWorkletNode-onprocessorstatechange"><code>processorstatechange</code></a>
event to <var>node</var>.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to say what the resulting state of the node is (i.e. "error"), yes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@hoch hoch force-pushed the revise-awn-awp-instantiation branch from a234a5e to 593949c Compare July 12, 2017 21:28
exception and abort these steps.
<li>If <var>nodeName</var> does not exists as a key in the
<a>BaseAudioContext</a>’s <a>node name to parameter descriptor
map</a>, throw a <code>NotSupportedError</code> exception and abort
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to wrap the "throw" part in a <span synchronous> tag.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is <span synchronous>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it's a way of explicitly saying "this operation is synchronous". However, I am not sure why that is necessary here. This section of algorithm happens in the main thread, so everything is sequential and synchronous.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and it's actually <span class="synchronous">. And not really sure it's needed, but most of the spec has this wherever we throw an error.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like a really weird convention. Where did it come from? In general I'd recommend following the conventions established by https://infra.spec.whatwg.org/ and HTML.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case it seems moot if we are in the main thread and not employing any contexts belonging to other threads. In the past, we had been looking at data belonging to the AWP.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we digressed. Is there anything to be fixed in this PR? I think the current spec text here has a clear distinction between the main thread and the worklet thread. So adding a synchronous icon seems redundant to me.

index.html Outdated
<dfn>node name to parameter descriptor map</dfn>
</dt>
<dd>
Belongs to <a>BaseAudioContext</a>. This map contains the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "the" -> "an"

index.html Outdated
"#widl-AudioWorkletNode-port">port</a> to <var>nodePort</var>.
</li>
<li>Let <var>parameterDescriptors</var> be the result of retrieval
by <var>nodeName</var> from <a>node name to parameter descriptor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"by" or "of"?

index.html Outdated
"value", <a href="https://tc39.github.io/ecma262/#sec-get-o-p">
Get</a>(O=<var>options</var>, P=<var>paramName</var>),
false).
<li>For each <var>paramNameInOption</var> → <var>value</var> of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the little arrow character be some html character entity instead? (Can't remember how html works with non-ASCII stuff.)

index.html Outdated
<li>For each <var>paramNameInOption</var> → <var>value</var> of
<var>options</var>:
<ol>
<li>If there exists an entry with name member equal to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be some markup for "name" or "name member" so that it denotes a variable or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name nor name member is not defined anywhere. We can fully expand this section but I wanted avoid too much clutter. Do you think this is too confusing?

index.html Outdated
<var>paramNameInOption</var> inside
<var>audioParamMap</var>, set that <a>AudioParam</a>'s
value to <var>value</var>.
</li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe describe what happens if the entry doesn't exist? (In code, it's obvious, but with text and lists, it's not so clear.)

<a>AudioWorkletProcessor</a>, given a string <var>nodeName</var>, a
serialization record <var>processorPortSerialization</var>, and an
<a>AudioWorkletNode</a> <var>node</var>, perform the following
steps on the <a>rendering thread</a>. If any of these steps throws
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the rendering thread throw an exception? And if it can, where does it go? I think what you're saying is if something bad happens on the rendering thread, the rendering thread stops processing and queues a task to the control thread. We're not throwing an exception in the JS sense?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bfgeek What should happen when JS code throws in WorkletGlobalScope?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to @bfgeek, WorkletGlobalScope does not have any error handling. So any exception that is being thrown here will be silently ignored. I think this issue should be handled by the worklet infra.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't audio worklets introduce a subclass of that class? Couldn't you add something there? Since you have message passing it seems good to be able to catch uncaught exceptions as well. (Maybe best discussed as a new issue?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO adding its own error handling whereas the parent class does not one is likely to cause the layering issue. What if the error handling will be added into WorkletGlobalScope in the future and it is different from what we do in AudioWorkletGlobalScope?

By the way, I filed an issue to Worklet folks.

name to processor definition map</a>.
</li>
<li>If <var>processorConstructor</var> is <code>undefined</code>,
throw a <code>NotSupportedError</code> DOMException.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NotSupportedError or InvalidStateError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PaintWorklet throws TypeError. According to ES spec, it "Indicates the actual type of an operand is different than the expected type."

Makes sense to me. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some Chrome CLs, haraken@ said that TypeError should be handled at the JS binding layer. If the binding handles this (which is seems it could?), then TypeError is fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a part of Worklet infra, so we should follow what it does.

@rtoy
Copy link
Member

rtoy commented Jul 25, 2017 via email

@padenot
Copy link
Member

padenot commented Jul 28, 2017

That seems like a really weird convention. Where did it come from? In general I'd recommend following the conventions established by https://infra.spec.whatwg.org/ and HTML.

infra didn't exist back then ! I followed a pattern I found in HTML, for example in the media resource selection algorithm.

In practice it's useful because most of what the Web Audio API needs to do is async.

@hoch
Copy link
Member Author

hoch commented Aug 4, 2017

Here's where I am on this:

  1. This section will not use <span synchronous> because here we clearly define synchronous/asynchronous operations.
  2. The error handling on AudioWorkletGlobalScope should be discussed/defined in the Worklet spec first, then we can downstream the fix to AudioWorklet. I want to handle this in a different PR.

@rtoy @annevk @padenot @joeberkovitz WDYT?

@annevk
Copy link

annevk commented Aug 4, 2017

It's reasonable to treat error handling separately. A tracking issue would be good.

@hoch
Copy link
Member Author

hoch commented Aug 4, 2017

Tracking issue is here: #1282

@annevk Can you approve this PR? You're one of reviewers.

@padenot
Copy link
Member

padenot commented Aug 8, 2017

This section will not use because here we clearly define synchronous/asynchronous operations.

I prefer consistency, but I don't care that much.

@hoch
Copy link
Member Author

hoch commented Aug 8, 2017

@padenot Your last comment doesn't sound like an LGTM. I would like to have another approval before I actually merge this change.

index.html Outdated
</li>
<li>If <var>processor</var> does not implement the
<a>AudioWorkletProcessor</a> interface, throw an
<code>"InvalidStateError"</code> DOMException. NOTE: this can occur
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For notes, use <div class=note></div>.

index.html Outdated
<li>If <var>processor</var> does not implement the
<a>AudioWorkletProcessor</a> interface, throw an
<code>"InvalidStateError"</code> DOMException. NOTE: this can occur
if the author-supplied constructor uses JavaScript's
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in a non normative section or an example section or something like that.

index.html Outdated
<p>
When <a>AudioWorkletNode</a>(<var>context</var>,
<var>nodeName</var>, <var>options</var>) constructor is invoked,
the user agent must perform the following steps on the control
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must or MUST ?

@hoch hoch force-pushed the revise-awn-awp-instantiation branch from 6abadb0 to 71c1f3a Compare August 23, 2017 15:35
@hoch
Copy link
Member Author

hoch commented Aug 23, 2017

Still waiting for the @joeberkovitz's approval.

@hoch hoch merged commit 354c298 into WebAudio:gh-pages Aug 24, 2017
@joeberkovitz
Copy link

I was on vacation at the time but the changes looked fine to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants