From fdda8a460da8abc41fce699a0e690a252337c400 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Sun, 11 Oct 2026 21:06:58 +0800 Subject: [PATCH] fix(events): preserve rejection event object identity Extracted from wpt-misc-fix. Source-commit: 658efaec07e6653e083c9817ce4288c0b798ac69 --- .../events/subclasses/data.rs | 2 +- .../misc/extracted/events_errors.rs | 21 ++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/moli-renderer-v8/src/context_bootstrap/events/subclasses/data.rs b/moli-renderer-v8/src/context_bootstrap/events/subclasses/data.rs index f0dcc83869..87cc937dca 100644 --- a/moli-renderer-v8/src/context_bootstrap/events/subclasses/data.rs +++ b/moli-renderer-v8/src/context_bootstrap/events/subclasses/data.rs @@ -225,7 +225,7 @@ struct PromiseRejectionEventInitDeclaration<'scope> { #[webidl(prefix = "PromiseRejectionEventInit")] struct PromiseRejectionEventInitMembers<'s> { #[webidl(required)] - promise: v8::Local<'s, v8::Promise>, + promise: v8::Local<'s, v8::Object>, #[webidl(converter = "raw")] reason: Option>, } diff --git a/moli-renderer-v8/src/script_vm/tests/browser_api/misc/extracted/events_errors.rs b/moli-renderer-v8/src/script_vm/tests/browser_api/misc/extracted/events_errors.rs index b410a960ac..43316d8c06 100644 --- a/moli-renderer-v8/src/script_vm/tests/browser_api/misc/extracted/events_errors.rs +++ b/moli-renderer-v8/src/script_vm/tests/browser_api/misc/extracted/events_errors.rs @@ -59,6 +59,7 @@ fn promise_rejection_event_constructor_parses_required_promise_and_optional_reas r#" (() => { const promise = Promise.resolve("settled"); + Object.defineProperty(promise, "then", {get() {throw Error("promise is an object member");}}); const omitted = new PromiseRejectionEvent("unhandledrejection", { promise }); const explicitUndefined = new PromiseRejectionEvent("unhandledrejection", { promise, @@ -68,7 +69,20 @@ fn promise_rejection_event_constructor_parses_required_promise_and_optional_reas promise, reason: null }); - const wrapped = new PromiseRejectionEvent("unhandledrejection", { promise: 42 }); + const revoked = Proxy.revocable({}, {}); + revoked.revoke(); + const objects = [{get then() {throw Error("then must not be read");}}, [], () => {}, + new Proxy({}, {get() {throw Error("payload must not be read");}}), revoked.proxy]; + const objectIdentityPreserved = objects.every(value => + new PromiseRejectionEvent("unhandledrejection", {promise: value}).promise === value); + const primitivesRejected = [undefined, null, false, 42, "promise", Symbol(), 1n].every(value => { + try { + new PromiseRejectionEvent("unhandledrejection", {promise: value}); + } catch (error) { + return error instanceof TypeError; + } + return false; + }); let missingPromiseThrows = false; try { @@ -92,7 +106,8 @@ fn promise_rejection_event_constructor_parses_required_promise_and_optional_reas omitted.reason === undefined, explicitUndefined.reason === undefined, explicitNull.reason === null, - wrapped.promise instanceof Promise, + objectIdentityPreserved, + primitivesRejected, missingPromiseThrows, getterErrorPreserved ].join("|"); @@ -101,7 +116,7 @@ fn promise_rejection_event_constructor_parses_required_promise_and_optional_reas ) .expect("PromiseRejectionEvent constructor probe should evaluate"); - assert_eq!(result, "true|true|true|true|true|true|true"); + assert_eq!(result, "true|true|true|true|true|true|true|true"); } #[test] fn host_dispatched_events_ignore_user_replaced_event_constructor() {