WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 220038
Unable to postMessage a WebAssembly module to a worklet
https://bugs.webkit.org/show_bug.cgi?id=220038
Summary
Unable to postMessage a WebAssembly module to a worklet
Richard Newman
Reported
2020-12-19 09:50:16 PST
WebAssembly modules can be sent between workers and pages via postMessage. Both Firefox and Chrome also allow WebAssembly modules to be sent from a page to an AudioWorklet via its MessagePort:
https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletNode/port
E.g., ``` this.port.postMessage({ message: 'hey', module }); ``` in Safari Technology Preview (117, WebKit 15611.1.7.2), this throws ``` DataCloneError: The object can not be cloned. ``` (FWIW, adding `module` to the transfer list doesn't help; I guess Safari doesn't support transfer lists either?) The lack of this capability prevents a common code loading approach for AudioWorklets, where some large chunk of WebAssembly is loaded in a worker and sent via the page down to the AudioWorklet via the MessagePort. I have not yet verified whether there's a workaround by posting a multi-megabyte ArrayBuffer and compiling it inside the worklet.
Attachments
WIP Patch
(8.86 KB, patch)
2021-01-28 17:06 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Test case
(87.28 KB, application/zip)
2021-08-12 09:39 PDT
,
letz
no flags
Details
WIP patch
(19.28 KB, patch)
2021-08-18 14:39 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
WIP patch
(19.16 KB, patch)
2021-08-18 14:45 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
WIP patch
(29.80 KB, patch)
2021-08-18 16:09 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
WIP patch
(23.10 KB, patch)
2021-08-18 17:18 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
WIP patch
(23.56 KB, patch)
2021-08-19 08:25 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(30.42 KB, patch)
2021-08-19 08:42 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(30.45 KB, patch)
2021-08-19 08:59 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(35.85 KB, patch)
2021-08-19 10:40 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(35.88 KB, patch)
2021-08-23 08:11 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(37.13 KB, patch)
2021-08-23 10:21 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(10)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2020-12-22 12:28:34 PST
<
rdar://problem/72596556
>
Yusuke Suzuki
Comment 2
2020-12-30 21:47:06 PST
Currently, MessagePort postMessage w/ WebAssembly.Module is not supported. We need to know the notion of the followings. 1. This pair of MessagePorts are in the same process so that we can send SerializedScriptValue without using IPC back-and-force 2. This pair of MessagePorts are in the different process so that we should just throw an onmessageerror exception. Chris, do you know about MessagePort's remote/not-remote flags? Is it specified? Note:
https://bugzilla.mozilla.org/show_bug.cgi?id=1605566
Yusuke Suzuki
Comment 3
2020-12-30 22:05:13 PST
Note that LayoutTests/imported/w3c/web-platform-tests/wasm/serialization/module/window-messagechannel-success.html covers this.
Chris Dumez
Comment 4
2021-01-05 08:48:39 PST
(In reply to Yusuke Suzuki from
comment #2
)
> Currently, MessagePort postMessage w/ WebAssembly.Module is not supported. > > We need to know the notion of the followings. > > 1. This pair of MessagePorts are in the same process so that we can send > SerializedScriptValue without using IPC back-and-force > 2. This pair of MessagePorts are in the different process so that we should > just throw an onmessageerror exception. > > Chris, do you know about MessagePort's remote/not-remote flags? Is it > specified? > > Note:
https://bugzilla.mozilla.org/show_bug.cgi?id=1605566
@Yusuke: I don't quite understand the need for "different-process". Our worklets always run in process. The only case where we use message port cross-process is with service workers, which are different from worklets.
Chris Dumez
Comment 5
2021-01-05 09:47:04 PST
(In reply to Chris Dumez from
comment #4
)
> (In reply to Yusuke Suzuki from
comment #2
) > > Currently, MessagePort postMessage w/ WebAssembly.Module is not supported. > > > > We need to know the notion of the followings. > > > > 1. This pair of MessagePorts are in the same process so that we can send > > SerializedScriptValue without using IPC back-and-force > > 2. This pair of MessagePorts are in the different process so that we should > > just throw an onmessageerror exception. > > > > Chris, do you know about MessagePort's remote/not-remote flags? Is it > > specified? > > > > Note:
https://bugzilla.mozilla.org/show_bug.cgi?id=1605566
> > @Yusuke: I don't quite understand the need for "different-process". Our > worklets always run in process. > > The only case where we use message port cross-process is with service > workers, which are different from worklets.
Based on the error, it looks like nobody implemented the serialization of modules in SerializedScriptValue? If so, sending the module to an iframe via postMessage would fail too (has this been tested?)
Richard Newman
Comment 6
2021-01-05 09:55:59 PST
I have not tested iframe messaging. Web worker to page seems to work correctly.
Chris Dumez
Comment 7
2021-01-05 09:59:44 PST
(In reply to Richard Newman from
comment #6
)
> I have not tested iframe messaging. > > Web worker to page seems to work correctly.
Oh I see. If worker to page works then I would imagine iframe messaging would work too. This must be specific to worklets somehow.
Chris Dumez
Comment 8
2021-01-05 10:05:01 PST
(In reply to Chris Dumez from
comment #7
)
> (In reply to Richard Newman from
comment #6
) > > I have not tested iframe messaging. > > > > Web worker to page seems to work correctly. > > Oh I see. If worker to page works then I would imagine iframe messaging > would work too. This must be specific to worklets somehow.
In SerializedScriptValue: if (m_context != SerializationContext::WorkerPostMessage) { code = SerializationReturnCode::DataCloneError; return true; } When encoding wasm modules. We are likely not using the WorkerPostMessage SerializationContext when messaging audio worklets?
Chris Dumez
Comment 9
2021-01-05 10:08:27 PST
(In reply to Chris Dumez from
comment #8
)
> (In reply to Chris Dumez from
comment #7
) > > (In reply to Richard Newman from
comment #6
) > > > I have not tested iframe messaging. > > > > > > Web worker to page seems to work correctly. > > > > Oh I see. If worker to page works then I would imagine iframe messaging > > would work too. This must be specific to worklets somehow. > > In SerializedScriptValue: > > if (m_context != SerializationContext::WorkerPostMessage) { > code = SerializationReturnCode::DataCloneError; > return true; > } > > When encoding wasm modules. We are likely not using the WorkerPostMessage > SerializationContext when messaging audio worklets?
MessagePort::postMessage() seems to use the default serialization context, no matter in which context the message port is used: === ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, JSC::JSValue messageValue, PostMessageOptions&& options) { LOG(MessagePorts, "Attempting to post message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data()); registerLocalActivity(); Vector<RefPtr<MessagePort>> ports; auto messageData = SerializedScriptValue::create(state, messageValue, WTFMove(options.transfer), ports); ===
Yusuke Suzuki
Comment 10
2021-01-05 12:52:16 PST
(In reply to Chris Dumez from
comment #9
)
> (In reply to Chris Dumez from
comment #8
) > > (In reply to Chris Dumez from
comment #7
) > > > (In reply to Richard Newman from
comment #6
) > > > > I have not tested iframe messaging. > > > > > > > > Web worker to page seems to work correctly. > > > > > > Oh I see. If worker to page works then I would imagine iframe messaging > > > would work too. This must be specific to worklets somehow. > > > > In SerializedScriptValue: > > > > if (m_context != SerializationContext::WorkerPostMessage) { > > code = SerializationReturnCode::DataCloneError; > > return true; > > } > > > > When encoding wasm modules. We are likely not using the WorkerPostMessage > > SerializationContext when messaging audio worklets? > > MessagePort::postMessage() seems to use the default serialization context, > no matter in which context the message port is used: > > === > ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, > JSC::JSValue messageValue, PostMessageOptions&& options) > { > LOG(MessagePorts, "Attempting to post message to port %s (to be received > by port %s)", m_identifier.logString().utf8().data(), > m_remoteIdentifier.logString().utf8().data()); > > registerLocalActivity(); > > Vector<RefPtr<MessagePort>> ports; > auto messageData = SerializedScriptValue::create(state, messageValue, > WTFMove(options.transfer), ports); > ===
I changed it to WorkerPostMessage serialization context, and it didn't work because MessagePort always serialize (via IPC encoder) SerializedScriptValue and deserialized it even though both ports are used by the workers/worklets in the same process. The problem is that we do not support full serialization of WebAssembly.Module. 1. It becomes super huge size 2. It is really complicated 3. Serialize and deserialize it will double memory size while WebAssembly.Module can be shared between multiple threads safely (it is designed to be a thread-safe). So, we need a notion of "MessageChannel is not used among different processes", and we should avoid using IPC encoder / decoder to serialize SerializedScriptValue for MessagePort. And I think this is what gecko is doing.
Chris Dumez
Comment 11
2021-01-05 17:48:19 PST
(In reply to Yusuke Suzuki from
comment #10
)
> (In reply to Chris Dumez from
comment #9
) > > (In reply to Chris Dumez from
comment #8
) > > > (In reply to Chris Dumez from
comment #7
) > > > > (In reply to Richard Newman from
comment #6
) > > > > > I have not tested iframe messaging. > > > > > > > > > > Web worker to page seems to work correctly. > > > > > > > > Oh I see. If worker to page works then I would imagine iframe messaging > > > > would work too. This must be specific to worklets somehow. > > > > > > In SerializedScriptValue: > > > > > > if (m_context != SerializationContext::WorkerPostMessage) { > > > code = SerializationReturnCode::DataCloneError; > > > return true; > > > } > > > > > > When encoding wasm modules. We are likely not using the WorkerPostMessage > > > SerializationContext when messaging audio worklets? > > > > MessagePort::postMessage() seems to use the default serialization context, > > no matter in which context the message port is used: > > > > === > > ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, > > JSC::JSValue messageValue, PostMessageOptions&& options) > > { > > LOG(MessagePorts, "Attempting to post message to port %s (to be received > > by port %s)", m_identifier.logString().utf8().data(), > > m_remoteIdentifier.logString().utf8().data()); > > > > registerLocalActivity(); > > > > Vector<RefPtr<MessagePort>> ports; > > auto messageData = SerializedScriptValue::create(state, messageValue, > > WTFMove(options.transfer), ports); > > === > > I changed it to WorkerPostMessage serialization context, and it didn't work > because MessagePort always serialize (via IPC encoder) SerializedScriptValue > and deserialized it even though both ports are used by the workers/worklets > in the same process. > The problem is that we do not support full serialization of > WebAssembly.Module. > > 1. It becomes super huge size > 2. It is really complicated > 3. Serialize and deserialize it will double memory size while > WebAssembly.Module can be shared between multiple threads safely (it is > designed to be a thread-safe). > > So, we need a notion of "MessageChannel is not used among different > processes", and we should avoid using IPC encoder / decoder to serialize > SerializedScriptValue for MessagePort. And I think this is what gecko is > doing.
From MessagePort, you can query identifier() and remoteIdentifier(). Each returns a MessagePortIdentifier which is a struct that contains both a processIdentifier and a portIdentifier. It should therefore be trivial to figure out if the local and remote ports are hosted in the same process check comparing identifier().processIdentifier and remoteIdentifier().processIdentifier.
Chris Dumez
Comment 12
2021-01-14 10:31:08 PST
(In reply to Chris Dumez from
comment #11
)
> (In reply to Yusuke Suzuki from
comment #10
) > > (In reply to Chris Dumez from
comment #9
) > > > (In reply to Chris Dumez from
comment #8
) > > > > (In reply to Chris Dumez from
comment #7
) > > > > > (In reply to Richard Newman from
comment #6
) > > > > > > I have not tested iframe messaging. > > > > > > > > > > > > Web worker to page seems to work correctly. > > > > > > > > > > Oh I see. If worker to page works then I would imagine iframe messaging > > > > > would work too. This must be specific to worklets somehow. > > > > > > > > In SerializedScriptValue: > > > > > > > > if (m_context != SerializationContext::WorkerPostMessage) { > > > > code = SerializationReturnCode::DataCloneError; > > > > return true; > > > > } > > > > > > > > When encoding wasm modules. We are likely not using the WorkerPostMessage > > > > SerializationContext when messaging audio worklets? > > > > > > MessagePort::postMessage() seems to use the default serialization context, > > > no matter in which context the message port is used: > > > > > > === > > > ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, > > > JSC::JSValue messageValue, PostMessageOptions&& options) > > > { > > > LOG(MessagePorts, "Attempting to post message to port %s (to be received > > > by port %s)", m_identifier.logString().utf8().data(), > > > m_remoteIdentifier.logString().utf8().data()); > > > > > > registerLocalActivity(); > > > > > > Vector<RefPtr<MessagePort>> ports; > > > auto messageData = SerializedScriptValue::create(state, messageValue, > > > WTFMove(options.transfer), ports); > > > === > > > > I changed it to WorkerPostMessage serialization context, and it didn't work > > because MessagePort always serialize (via IPC encoder) SerializedScriptValue > > and deserialized it even though both ports are used by the workers/worklets > > in the same process. > > The problem is that we do not support full serialization of > > WebAssembly.Module. > > > > 1. It becomes super huge size > > 2. It is really complicated > > 3. Serialize and deserialize it will double memory size while > > WebAssembly.Module can be shared between multiple threads safely (it is > > designed to be a thread-safe). > > > > So, we need a notion of "MessageChannel is not used among different > > processes", and we should avoid using IPC encoder / decoder to serialize > > SerializedScriptValue for MessagePort. And I think this is what gecko is > > doing. > > From MessagePort, you can query identifier() and remoteIdentifier(). Each > returns a MessagePortIdentifier which is a struct that contains both a > processIdentifier and a portIdentifier. It should therefore be trivial to > figure out if the local and remote ports are hosted in the same process > check comparing identifier().processIdentifier and > remoteIdentifier().processIdentifier.
Indeed, it seems we are going to the NetworkProcess via IPC even though the source and destination processes are identical. This is definitely suboptimal in general and breaking for Wasm modules since those are currently not IPC-encoded.
Chris Dumez
Comment 13
2021-01-14 11:49:31 PST
With the WIP patch at
Bug 220627
(to avoid IPC when both MessagePorts are in the same process) and with a change to MessagePort::postMessage() to use SerializationContext::WorkerPostMessage when necessary, LayoutTests/imported/w3c/web-platform-tests/wasm/serialization/module/window-messagechannel-success.html starts to PASS.
Yusuke Suzuki
Comment 14
2021-01-14 12:42:06 PST
(In reply to Chris Dumez from
comment #13
)
> With the WIP patch at
Bug 220627
(to avoid IPC when both MessagePorts are in > the same process) and with a change to MessagePort::postMessage() to use > SerializationContext::WorkerPostMessage when necessary, > LayoutTests/imported/w3c/web-platform-tests/wasm/serialization/module/window- > messagechannel-success.html starts to PASS.
Perfect!
Chris Dumez
Comment 15
2021-01-28 17:06:09 PST
Created
attachment 418682
[details]
WIP Patch
Chris Dumez
Comment 16
2021-01-28 17:18:02 PST
Comment on
attachment 418682
[details]
WIP Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=418682&action=review
> Source/WebCore/dom/MessagePort.cpp:141 > + // FIXME: At the time of serialization, we don't know if the target is a window, a worker or something else. We will only know at the time of
@Yusuke: Not sure how to best deal with this. Passing SerializationContext::WorkerPostMessage unconditionally here is a hack.
Yusuke Suzuki
Comment 17
2021-02-01 02:03:23 PST
Comment on
attachment 418682
[details]
WIP Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=418682&action=review
> LayoutTests/imported/w3c/web-platform-tests/wasm/serialization/module/window-messagechannel-success-expected.txt:2 > +PASS postMessaging to a dedicated worker via MessageChannel allows them to instantiate
Can we have a test case that is posting wasm module to message-ports tied to the different process and getting an error in deserialization side? Ideally, we should throw an error, and we should report onmessageerror since we failed deserialization. Maybe, we should add a test for checking that error, and after that, we should file a bug for `onmessageerror` handler invocation and implement it.
https://developer.mozilla.org/en-US/docs/Web/API/Worker/onmessageerror
https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessageerror
>> Source/WebCore/dom/MessagePort.cpp:141 >> + // FIXME: At the time of serialization, we don't know if the target is a window, a worker or something else. We will only know at the time of > > @Yusuke: Not sure how to best deal with this. Passing SerializationContext::WorkerPostMessage unconditionally here is a hack.
This hack looks OK to me! If we attempt to deserialize non-sharable-between-processes objects, then we will get an error at deserialization (not causing catastrophic crash) since our SerializedScriptValue's deserialization is robust enough against that.
letz
Comment 18
2021-08-12 09:39:46 PDT
Created
attachment 435429
[details]
Test case
letz
Comment 19
2021-08-12 09:42:17 PDT
Note that WebAssembly modules should be serialisable to be used in processorOptions at construction time between an AudioWorkletNote and and AudioWorkletProcessor.
Chris Dumez
Comment 20
2021-08-18 14:10:06 PDT
Comment on
attachment 418682
[details]
WIP Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=418682&action=review
>> LayoutTests/imported/w3c/web-platform-tests/wasm/serialization/module/window-messagechannel-success-expected.txt:2 >> +PASS postMessaging to a dedicated worker via MessageChannel allows them to instantiate > > Can we have a test case that is posting wasm module to message-ports tied to the different process and getting an error in deserialization side? > Ideally, we should throw an error, and we should report onmessageerror since we failed deserialization. > Maybe, we should add a test for checking that error, and after that, we should file a bug for `onmessageerror` handler invocation and implement it. >
https://developer.mozilla.org/en-US/docs/Web/API/Worker/onmessageerror
>
https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessageerror
WebKit currently doesn't support onmessageerror AFAIK
Chris Dumez
Comment 21
2021-08-18 14:39:25 PDT
Created
attachment 435798
[details]
WIP patch
Chris Dumez
Comment 22
2021-08-18 14:45:03 PDT
Created
attachment 435799
[details]
WIP patch
Chris Dumez
Comment 23
2021-08-18 16:09:52 PDT
Created
attachment 435812
[details]
WIP patch
Chris Dumez
Comment 24
2021-08-18 17:18:06 PDT
Created
attachment 435820
[details]
WIP patch
Chris Dumez
Comment 25
2021-08-19 08:25:04 PDT
Created
attachment 435860
[details]
WIP patch
Chris Dumez
Comment 26
2021-08-19 08:42:54 PDT
Created
attachment 435862
[details]
Patch
Chris Dumez
Comment 27
2021-08-19 08:59:22 PDT
Created
attachment 435865
[details]
Patch
Chris Dumez
Comment 28
2021-08-19 10:40:38 PDT
Created
attachment 435882
[details]
Patch
Chris Dumez
Comment 29
2021-08-23 08:11:05 PDT
Created
attachment 436196
[details]
Patch
Chris Dumez
Comment 30
2021-08-23 10:21:14 PDT
Created
attachment 436207
[details]
Patch
Ian Kettlewell
Comment 31
2021-12-18 09:59:52 PST
A key detail worth noting: It looks like WebAssembly.Memory objects cannot be sent between workers via postMessage either. An important use for postMessaging WebAssembly modules / memory is to use an Audio Worklet in a way similar to how a non-web dedicated audio thread would work. The Audio Worklet runs a Wasm instance backed by a SharedArrayBuffer that communicates with the main thread via Wasm atomics. That flow makes it *much* easier to for things like game engines to share audio backend code between non-web and web. I think (but haven't verified) the module being un-postMessageable can be worked around by postMessaging the code and re-instantiating the module on the Worklet. However as far as I'm aware the WebAssembly.Memory object being non-postMessagable does not have a workaround. That blocks the use-case I've described here.
letz
Comment 32
2022-01-27 01:01:17 PST
Any news on this issue? Any expected date for a proper fix to appear? Thanks.
Tibor Klajnscek
Comment 33
2022-03-09 04:20:29 PST
+1 for a status update - this is blocking us from using our audio worklet backend which is critical to consistent and crackle-free audio in our products.
Attila Haraszti
Comment 34
2022-04-19 03:16:37 PDT
This is currently a blocker for us, a fix would be highly appreciated.
Tibor Klajnscek
Comment 35
2022-07-22 03:46:39 PDT
This seems to work in the latest Safari dev preview, but I haven't found any release notes mentioning it. Is it just a fluke or has it been fixed? And if so, will it make it into Safari 16?
Ahmad Saleem
Comment 36
2022-09-30 08:15:36 PDT
@Chris - it seems this patch passes all tests and only have "style" issues? Is it something on your radar and "see also" bug is also fixed? Thanks!
Chris Dumez
Comment 37
2022-11-17 11:05:20 PST
Pull request:
https://github.com/WebKit/WebKit/pull/6596
EWS
Comment 38
2022-11-18 13:31:52 PST
Committed
256853@main
(a9d61c9d9e2e): <
https://commits.webkit.org/256853@main
> Reviewed commits have been landed. Closing PR #6596 and removing active labels.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug