mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
script: Allow to throw a custom exception on structured cloning (#37948)
The structured cloning with transfer list https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer throws a "DataCloneError" DOM expection by default if serialization/transferral is not possible, but a platform object can throw a custom excepton on its serialization/transfer steps. One example is OffscreenCanvas, which can throw an "InvalidStateError" exception if the context mode is not none on transfer steps. https://html.spec.whatwg.org/multipage/#the-offscreencanvas-interface:transfer-steps Testing: Improvements in the following tests - html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable* Fixes: #37919 Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This commit is contained in:
parent
cae73341b2
commit
a5b02047f9
10 changed files with 165 additions and 130 deletions
|
@ -1222,11 +1222,12 @@ impl Transferable for WritableStream {
|
|||
type Index = MessagePortIndex;
|
||||
type Data = MessagePortImpl;
|
||||
|
||||
/// <https://streams.spec.whatwg.org/#ref-for-writablestream%E2%91%A0%E2%91%A4>
|
||||
fn transfer(&self) -> Result<(MessagePortId, MessagePortImpl), ()> {
|
||||
// If ! IsWritableStreamLocked(value) is true, throw a "DataCloneError" DOMException.
|
||||
/// <https://streams.spec.whatwg.org/#ref-for-transfer-steps①>
|
||||
fn transfer(&self) -> Fallible<(MessagePortId, MessagePortImpl)> {
|
||||
// Step 1. If ! IsWritableStreamLocked(value) is true, throw a
|
||||
// "DataCloneError" DOMException.
|
||||
if self.is_locked() {
|
||||
return Err(());
|
||||
return Err(Error::DataClone(None));
|
||||
}
|
||||
|
||||
let global = self.global();
|
||||
|
@ -1235,34 +1236,34 @@ impl Transferable for WritableStream {
|
|||
let cx = GlobalScope::get_cx();
|
||||
let can_gc = CanGc::note();
|
||||
|
||||
// Let port1 be a new MessagePort in the current Realm.
|
||||
// Step 2. Let port1 be a new MessagePort in the current Realm.
|
||||
let port_1 = MessagePort::new(&global, can_gc);
|
||||
global.track_message_port(&port_1, None);
|
||||
|
||||
// Let port2 be a new MessagePort in the current Realm.
|
||||
// Step 3. Let port2 be a new MessagePort in the current Realm.
|
||||
let port_2 = MessagePort::new(&global, can_gc);
|
||||
global.track_message_port(&port_2, None);
|
||||
|
||||
// Entangle port1 and port2.
|
||||
// Step 4. Entangle port1 and port2.
|
||||
global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
|
||||
|
||||
// Let readable be a new ReadableStream in the current Realm.
|
||||
// Step 5. Let readable be a new ReadableStream in the current Realm.
|
||||
let readable = ReadableStream::new_with_proto(&global, None, can_gc);
|
||||
|
||||
// Perform ! SetUpCrossRealmTransformReadable(readable, port1).
|
||||
// Step 6. Perform ! SetUpCrossRealmTransformReadable(readable, port1).
|
||||
readable.setup_cross_realm_transform_readable(cx, &port_1, can_gc);
|
||||
|
||||
// Let promise be ! ReadableStreamPipeTo(readable, value, false, false, false).
|
||||
// Step 7. Let promise be ! ReadableStreamPipeTo(readable, value, false, false, false).
|
||||
let promise = readable.pipe_to(cx, &global, self, false, false, false, None, comp, can_gc);
|
||||
|
||||
// Set promise.[[PromiseIsHandled]] to true.
|
||||
// Step 8. Set promise.[[PromiseIsHandled]] to true.
|
||||
promise.set_promise_is_handled();
|
||||
|
||||
// Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2, « port2 »).
|
||||
// Step 9. Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2, « port2 »).
|
||||
port_2.transfer()
|
||||
}
|
||||
|
||||
/// <https://streams.spec.whatwg.org/#ref-for-writablestream%E2%91%A0%E2%91%A4>
|
||||
/// <https://streams.spec.whatwg.org/#ref-for-transfer-receiving-steps①>
|
||||
fn transfer_receive(
|
||||
owner: &GlobalScope,
|
||||
id: MessagePortId,
|
||||
|
@ -1275,13 +1276,15 @@ impl Transferable for WritableStream {
|
|||
// Note: dataHolder is used in `structuredclone.rs`, and value is created here.
|
||||
let value = WritableStream::new_with_proto(owner, None, can_gc);
|
||||
|
||||
// Let deserializedRecord be ! StructuredDeserializeWithTransfer(dataHolder.[[port]], the current Realm).
|
||||
// Step 1. Let deserializedRecord be !
|
||||
// StructuredDeserializeWithTransfer(dataHolder.[[port]], the current
|
||||
// Realm).
|
||||
// Done with the `Deserialize` derive of `MessagePortImpl`.
|
||||
|
||||
// Let port be deserializedRecord.[[Deserialized]].
|
||||
// Step 2. Let port be deserializedRecord.[[Deserialized]].
|
||||
let transferred_port = MessagePort::transfer_receive(owner, id, port_impl)?;
|
||||
|
||||
// Perform ! SetUpCrossRealmTransformWritable(value, port).
|
||||
// Step 3. Perform ! SetUpCrossRealmTransformWritable(value, port).
|
||||
value.setup_cross_realm_transform_writable(cx, &transferred_port, can_gc);
|
||||
Ok(value)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue