-
Notifications
You must be signed in to change notification settings - Fork 168
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
Conversation
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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>. |
There was a problem hiding this comment.
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"?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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/
There was a problem hiding this comment.
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.
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? |
@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?
|
0f41913
to
20b5f76
Compare
Sorry for the messy commits. Please take a look at the last one: 0f41913 |
This really needs to be rebased cleanly on top of |
@hoch I can't review this yet either, it includes a bunch of diffs from unmerged commits in |
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 |
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. |
ea6f033
to
4340858
Compare
@padenot @joeberkovitz Sorry for the confusion and updated the PR with the force-push. |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: resolevd
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
a234a5e
to
593949c
Compare
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is <span synchronous>
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NotSupportedError or InvalidStateError?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
@padenot did this change quite some time ago. I no longer remember the
reason or the issue/pull request for this.
…On Tue, Jul 25, 2017 at 12:42 AM, Anne van Kesteren < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In index.html
<#1265 (comment)>
:
> </p>
<ol>
<li>Let <var>this</var> be the instance being created by
constructor of <a>AudioWorkletNode</a> or its subclass.
</li>
- <li>If <var>name</var> does not exists as a key in the
- <a>AudioWorkletGlobalScope</a>’s <a>node name to processor
- definition map</a>, throw a <code>NotSupportedError</code>
- 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
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.
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#1265 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAofPNfztdI779VFW1oGDg0KGwoFlWJyks5sRZx-gaJpZM4OBhgJ>
.
--
Ray
|
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. |
Here's where I am on this:
@rtoy @annevk @padenot @joeberkovitz WDYT? |
It's reasonable to treat error handling separately. A tracking issue would be good. |
I prefer consistency, but I don't care that much. |
@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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
must or MUST ?
- Rewrite the algorithm. - Add `node name to parameter descriptor map`.
6abadb0
to
71c1f3a
Compare
Still waiting for the @joeberkovitz's approval. |
I was on vacation at the time but the changes looked fine to me. |
PTAL.
Preview (update)