Summary: | SharedArrayBuffer posted to AudioWorkletProcessor is not actually shared with the main thread | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | tasnim <tasnimrock2k6> | ||||||||||||
Component: | Web Audio | Assignee: | Chris Dumez <cdumez> | ||||||||||||
Status: | RESOLVED FIXED | ||||||||||||||
Severity: | Normal | CC: | alecflett, beidson, cdumez, darin, eric.carlson, ews-watchlist, ggaren, glenn, jer.noble, jsbell, keith_miller, lolwebkitbugtracker, mark.lam, philipj, sergio, tasnimrock2k6, webkit-bug-importer, ysuzuki | ||||||||||||
Priority: | P2 | Keywords: | InRadar | ||||||||||||
Version: | Safari 15 | ||||||||||||||
Hardware: | Mac (Intel) | ||||||||||||||
OS: | macOS 12 | ||||||||||||||
See Also: |
https://bugs.webkit.org/show_bug.cgi?id=220038 https://bugs.webkit.org/show_bug.cgi?id=237241 |
||||||||||||||
Attachments: |
|
Description
tasnim
2022-02-24 09:54:57 PST
Created attachment 453114 [details]
Same steps in chrome
Attached the same screenshot in chrome where changing value from main thread can be immediately noticed in the AudioWorkletProcessor.
Test seems to rely on AudioWorkletNodeOptions.processorOptions: - https://webaudio.github.io/web-audio-api/#AudioWorkletNodeOptions Looking at our implementation, we don't seem to support that. Not sure if this is a recent addition to the spec or if we missed it. My bet is that if the SharedArrayBuffer was sent to the AudioWorklet via postMessage(), it would work. (In reply to Chris Dumez from comment #2) > Test seems to rely on AudioWorkletNodeOptions.processorOptions: > - https://webaudio.github.io/web-audio-api/#AudioWorkletNodeOptions > > Looking at our implementation, we don't seem to support that. Not sure if > this is a recent addition to the spec or if we missed it. My bet is that if > the SharedArrayBuffer was sent to the AudioWorklet via postMessage(), it > would work. Actually, maybe we do support processorOptions after all, I haven't tested but we do have it in our IDL. Right, I had posted my findings with processorOptions but I just tested with postMessage too. Doesn't work there. See https://jsfiddle.net/6ua5o3jk/ Works perfectly fine in chrome. The SharedArrayBuffer may be getting copied to the other thread and behaving like a normal ArrayBuffer. I verified this when initially setting some values (before sab was transported to the other thread) and later, able to see the same value in the other thread. (Note in both the test, at step-2 in the attached screenshot if you click anywhere in the browser to activate AudioWorkletProcessor, it may not work directly coz of autoplay issue and then you'll have to reload the browser and check again) Ok, so when constructing a SerializedScriptValue, the default SerializationContext is SerializationContext::Default and it is likely what we end up using for sending the options to the AudioWorklet. However, looking at our implementation, SharedArrayBuffer are only serialized as shared when SerializationContext is SerializationContext::WorkerPostMessage. I am not sure why that is (Yusuke, do you know?). In anyway, I bet that using SerializationContext::WorkerPostMessage as serialization context for AudioWorklet will work. I'll test. Created attachment 453228 [details]
WIP Patch
Created attachment 453239 [details]
Patch
Comment on attachment 453239 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=453239&action=review > Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp:94 > - serializedOptions = SerializedScriptValue::create(globalObject, jsOptions, SerializationErrorMode::NonThrowing); > - if (!serializedOptions) > + Vector<RefPtr<MessagePort>> ports; > + auto serializedValue = SerializedScriptValue::create(globalObject, jsOptions, { }, ports, SerializationContext::WorkerPostMessage); I’m finding this interface confusing. Could this difference in semantics be expressed as two differently named functions rather than having both be named "create"? Why does SerializedScriptValue::create do something so different when you pass it different arguments, particularly in a case like this where all the arguments are empty values and empty vectors. Is the key difference SerializationContext::WorkerPostMessage? Created attachment 453253 [details]
Patch
(In reply to Darin Adler from comment #9) > Comment on attachment 453239 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453239&action=review > > > Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp:94 > > - serializedOptions = SerializedScriptValue::create(globalObject, jsOptions, SerializationErrorMode::NonThrowing); > > - if (!serializedOptions) > > + Vector<RefPtr<MessagePort>> ports; > > + auto serializedValue = SerializedScriptValue::create(globalObject, jsOptions, { }, ports, SerializationContext::WorkerPostMessage); > > I’m finding this interface confusing. Could this difference in semantics be > expressed as two differently named functions rather than having both be > named "create"? Why does SerializedScriptValue::create do something so > different when you pass it different arguments, particularly in a case like > this where all the arguments are empty values and empty vectors. Is the key > difference SerializationContext::WorkerPostMessage? Will investigate in a follow-up as it is not trivial it seems. There are a lot of things that the other create() function doesn't serialize for some reason. Committed r290531 (247811@trunk): <https://commits.webkit.org/247811@trunk> Thanks for the quick fix Chris. Much appreciated. Wanted to ask how soon can I try this? Probably, I need to wait for this to show up in https://developer.apple.com/safari/technology-preview/ for trying early, right? (In reply to tasnim from comment #13) > Thanks for the quick fix Chris. Much appreciated. > Wanted to ask how soon can I try this? Probably, I need to wait for this to > show up in https://developer.apple.com/safari/technology-preview/ for trying > early, right? Yes, you’d have to wait until the next Safari technology preview build (or the one after that if unlucky). Note that I only fixed the sending of the shared array buffer via the options objects like in your original example. Sadly, sending the shared array buffer via postMessage() (like in your updated example) is still broken due to bug 220038. I will try and take a stab at it soon but it is a little more complicated to fix because of our current architecture. Cool, thanks! We send shared array buffer only via the options object. So, should be fine for us. (In reply to Darin Adler from comment #9) > Comment on attachment 453239 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=453239&action=review > > > Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp:94 > > - serializedOptions = SerializedScriptValue::create(globalObject, jsOptions, SerializationErrorMode::NonThrowing); > > - if (!serializedOptions) > > + Vector<RefPtr<MessagePort>> ports; > > + auto serializedValue = SerializedScriptValue::create(globalObject, jsOptions, { }, ports, SerializationContext::WorkerPostMessage); > > I’m finding this interface confusing. Could this difference in semantics be > expressed as two differently named functions rather than having both be > named "create"? Why does SerializedScriptValue::create do something so > different when you pass it different arguments, particularly in a case like > this where all the arguments are empty values and empty vectors. Is the key > difference SerializationContext::WorkerPostMessage? Following up in Bug 237241 for the SerializedScriptValue construction. Just wanted to follow up on which next stable build of safari will this fix make in? And, how many estimated weeks away are we from that? I have already verified on safari preview build but am waiting for the next safari stable release when I will be able to verify on iOS and decide on launching our web app. |