From 26f4da824907946569fb673a249a2c9035c1d1e4 Mon Sep 17 00:00:00 2001 From: Andrei Volykhin Date: Wed, 9 Jul 2025 17:47:55 +0300 Subject: [PATCH] script: Propagate a pending JS exception on structured cloning (#37964) During the object (de)serialization steps on structured cloning https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data it is possible to throw a JS exception. `self.postMessage({ get whatever() { throw customError } }));` Require to propagate a pending JS exception and not throw the default "DataCloneError" DOM exception. Testing: Improvements in the following tests - html/infrastructure/safe-passing-of-structured-data/* - html/webappapis/structured-clone/structured-clone.any.js* - wasm/serialization/arraybuffer/transfer.window.js - webmessaging/without-ports/026.html - workers/semantics/structured-clone/dedicated.html Signed-off-by: Andrei Volykhin --- .../script/dom/bindings/structuredclone.rs | 20 ++++++++++++++----- .../messagechannel.any.js.ini | 6 ------ .../structured-cloning-error-extra.html.ini | 3 --- .../transfer-errors.window.js.ini | 12 ----------- .../window-postmessage.window.js.ini | 3 --- .../structured-clone.any.js.ini | 6 ------ .../arraybuffer/transfer.window.js.ini | 3 --- .../webmessaging/without-ports/026.html.ini | 3 --- .../structured-clone/dedicated.html.ini | 3 --- 9 files changed, 15 insertions(+), 44 deletions(-) delete mode 100644 tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-extra.html.ini delete mode 100644 tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/transfer-errors.window.js.ini delete mode 100644 tests/wpt/meta/wasm/serialization/arraybuffer/transfer.window.js.ini delete mode 100644 tests/wpt/meta/webmessaging/without-ports/026.html.ini diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index 7ee1dccd170..929209f7432 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -24,7 +24,7 @@ use js::glue::{ NewJSAutoStructuredCloneBuffer, WriteBytesToJSStructuredCloneData, }; use js::jsapi::{ - CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_ClearPendingException, + CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_IsExceptionPending, JS_ReadUint32Pair, JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject, JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter, MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership, @@ -619,8 +619,13 @@ pub(crate) fn write( val.handle(), ); if !result { - JS_ClearPendingException(*cx); - return Err(sc_writer.error.unwrap_or(Error::DataClone(None))); + let error = if JS_IsExceptionPending(*cx) { + Error::JSFailed + } else { + sc_writer.error.unwrap_or(Error::DataClone(None)) + }; + + return Err(error); } let nbytes = GetLengthOfJSStructuredCloneData(scdata); @@ -696,8 +701,13 @@ pub(crate) fn read( sc_reader_ptr as *mut raw::c_void, ); if !result { - JS_ClearPendingException(*cx); - return Err(sc_reader.error.unwrap_or(Error::DataClone(None))); + let error = if JS_IsExceptionPending(*cx) { + Error::JSFailed + } else { + sc_reader.error.unwrap_or(Error::DataClone(None)) + }; + + return Err(error); } DeleteJSAutoStructuredCloneBuffer(scbuf); diff --git a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/messagechannel.any.js.ini b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/messagechannel.any.js.ini index 71a1c6a92be..656f868a09c 100644 --- a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/messagechannel.any.js.ini +++ b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/messagechannel.any.js.ini @@ -5,9 +5,6 @@ [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [Growable SharedArrayBuffer] expected: FAIL @@ -52,8 +49,5 @@ [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [Growable SharedArrayBuffer] expected: FAIL diff --git a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-extra.html.ini b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-extra.html.ini deleted file mode 100644 index 1c432ed55a0..00000000000 --- a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/structured-cloning-error-extra.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[structured-cloning-error-extra.html] - [Throwing name getter fails serialization] - expected: FAIL diff --git a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/transfer-errors.window.js.ini b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/transfer-errors.window.js.ini deleted file mode 100644 index 826d5912b1d..00000000000 --- a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/transfer-errors.window.js.ini +++ /dev/null @@ -1,12 +0,0 @@ -[transfer-errors.window.html] - [Serialize should throw before a detached ArrayBuffer is found] - expected: FAIL - - [Serialize should throw before a detached MessagePort is found] - expected: FAIL - - [Serialize should throw before a detached ImageBitmap is found] - expected: FAIL - - [Serialize should throw before a detached OffscreenCanvas is found] - expected: FAIL diff --git a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.js.ini b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.js.ini index 06b9002470b..c4155850d86 100644 --- a/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.js.ini +++ b/tests/wpt/meta/html/infrastructure/safe-passing-of-structured-data/window-postmessage.window.js.ini @@ -32,8 +32,5 @@ [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [Growable SharedArrayBuffer] expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/structured-clone/structured-clone.any.js.ini b/tests/wpt/meta/html/webappapis/structured-clone/structured-clone.any.js.ini index 2bc19a50005..9400f27c030 100644 --- a/tests/wpt/meta/html/webappapis/structured-clone/structured-clone.any.js.ini +++ b/tests/wpt/meta/html/webappapis/structured-clone/structured-clone.any.js.ini @@ -5,9 +5,6 @@ [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [Growable SharedArrayBuffer] expected: FAIL @@ -46,8 +43,5 @@ [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [Growable SharedArrayBuffer] expected: FAIL diff --git a/tests/wpt/meta/wasm/serialization/arraybuffer/transfer.window.js.ini b/tests/wpt/meta/wasm/serialization/arraybuffer/transfer.window.js.ini deleted file mode 100644 index e5ac1ff2620..00000000000 --- a/tests/wpt/meta/wasm/serialization/arraybuffer/transfer.window.js.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transfer.window.html] - [Transfering a WebAssembly.Memory-backed ArrayBuffer throws] - expected: FAIL diff --git a/tests/wpt/meta/webmessaging/without-ports/026.html.ini b/tests/wpt/meta/webmessaging/without-ports/026.html.ini deleted file mode 100644 index 4cb0e0412a6..00000000000 --- a/tests/wpt/meta/webmessaging/without-ports/026.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[026.html] - [Cloning objects with getter properties] - expected: FAIL diff --git a/tests/wpt/meta/workers/semantics/structured-clone/dedicated.html.ini b/tests/wpt/meta/workers/semantics/structured-clone/dedicated.html.ini index 4e647012bd5..345ca3dd450 100644 --- a/tests/wpt/meta/workers/semantics/structured-clone/dedicated.html.ini +++ b/tests/wpt/meta/workers/semantics/structured-clone/dedicated.html.ini @@ -29,9 +29,6 @@ [Object ImageData object, ImageData 1x1 non-transparent non-black] expected: FAIL - [Object with a getter that throws] - expected: FAIL - [A subclass instance will deserialize as its closest serializable superclass] expected: FAIL