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:
Andrei Volykhin 2025-07-09 14:43:09 +03:00 committed by GitHub
parent cae73341b2
commit a5b02047f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 165 additions and 130 deletions

View file

@ -152,16 +152,24 @@ impl Transferable for OffscreenCanvas {
type Data = TransferableOffscreenCanvas;
/// <https://html.spec.whatwg.org/multipage/#the-offscreencanvas-interface:transfer-steps>
fn transfer(&self) -> Result<(OffscreenCanvasId, TransferableOffscreenCanvas), ()> {
// TODO(#37919) Step 1. If value's context mode is not equal to none,
// then throw an "InvalidStateError" DOMException.
fn transfer(&self) -> Fallible<(OffscreenCanvasId, TransferableOffscreenCanvas)> {
// <https://html.spec.whatwg.org/multipage/#structuredserializewithtransfer>
// Step 5.2. If transferable has a [[Detached]] internal slot and
// transferable.[[Detached]] is true, then throw a "DataCloneError"
// DOMException.
if let Some(OffscreenRenderingContext::Detached) = *self.context.borrow() {
return Err(Error::DataClone(None));
}
// Step 1. If value's context mode is not equal to none, then throw an
// "InvalidStateError" DOMException.
if !self.context.borrow().is_none() {
return Err(());
return Err(Error::InvalidState);
}
// TODO(#37882): Allow to transfer with a placeholder canvas element.
if self.placeholder.is_some() {
return Err(());
return Err(Error::InvalidState);
}
// Step 2. Set value's context mode to detached.