From f717f6b848fe77ee948424b82d4419dcc5666c52 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 25 Mar 2025 10:08:45 -0400 Subject: [PATCH] script: Support converting JS values to Rc with FromJSValConvertible. (#36097) Signed-off-by: Josh Matthews --- Cargo.lock | 4 ++-- components/script/dom/promise.rs | 23 ++++++++++++++++++- components/script/dom/testbinding.rs | 1 + .../script_bindings/codegen/Bindings.conf | 2 +- .../webidls/TestBinding.webidl | 1 + 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b153b07382a..8cc72e69b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4702,7 +4702,7 @@ dependencies = [ [[package]] name = "mozjs" version = "0.14.1" -source = "git+https://github.com/servo/mozjs#26c35182c1b2b7fb2fbfa93b82669533d92c3a60" +source = "git+https://github.com/servo/mozjs#39db84352d79ffa3e4fe756c8034af9def788f22" dependencies = [ "bindgen 0.71.1", "cc", @@ -4714,7 +4714,7 @@ dependencies = [ [[package]] name = "mozjs_sys" version = "0.128.9-0" -source = "git+https://github.com/servo/mozjs#26c35182c1b2b7fb2fbfa93b82669533d92c3a60" +source = "git+https://github.com/servo/mozjs#39db84352d79ffa3e4fe756c8034af9def788f22" dependencies = [ "bindgen 0.71.1", "cc", diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index d7c309a7ded..dd09b1df3a1 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -15,7 +15,7 @@ use std::ptr; use std::rc::Rc; use dom_struct::dom_struct; -use js::conversions::ToJSValConvertible; +use js::conversions::{ConversionResult, FromJSValConvertibleRc, ToJSValConvertible}; use js::jsapi::{ AddRawValueRoot, CallArgs, GetFunctionNativeReserved, Heap, JS_ClearPendingException, JS_GetFunctionObject, JS_NewFunction, JSAutoRealm, JSContext, JSObject, @@ -405,3 +405,24 @@ impl PromiseHelpers for Promise { Promise::new_resolved(global, cx, value, CanGc::note()) } } + +impl FromJSValConvertibleRc for Promise { + #[allow(unsafe_code)] + unsafe fn from_jsval( + cx: *mut JSContext, + value: HandleValue, + ) -> Result>, ()> { + if value.get().is_null() { + return Ok(ConversionResult::Failure("null not allowed".into())); + } + if !value.get().is_object() { + return Ok(ConversionResult::Failure("not an object".into())); + } + rooted!(in(cx) let obj = value.get().to_object()); + if !IsPromiseObject(obj.handle()) { + return Ok(ConversionResult::Failure("not a promise".into())); + } + let promise = Promise::new_with_js_promise(obj.handle(), SafeJSContext::from_ptr(cx)); + Ok(ConversionResult::Success(promise)) + } +} diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index d03196de940..4095ba1319a 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -910,6 +910,7 @@ impl TestBindingMethods for TestBinding { fn FuncControlledMethodDisabled(&self) {} fn FuncControlledMethodEnabled(&self) {} + fn PassRecordPromise(&self, _: Record>) {} fn PassRecord(&self, _: Record) {} fn PassRecordWithUSVStringKey(&self, _: Record) {} fn PassRecordWithByteStringKey(&self, _: Record) {} diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index 4fa998a84c3..d5b1dc5c281 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -490,7 +490,7 @@ DOMInterfaces = { 'Promise': { 'spiderMonkeyInterface': True, - 'additionalTraits': ["crate::dom::promise::PromiseHelpers"] + 'additionalTraits': ["crate::dom::promise::PromiseHelpers", "js::conversions::FromJSValConvertibleRc"] }, 'Range': { diff --git a/components/script_bindings/webidls/TestBinding.webidl b/components/script_bindings/webidls/TestBinding.webidl index 88f1b4d51f7..92d95e4fe73 100644 --- a/components/script_bindings/webidls/TestBinding.webidl +++ b/components/script_bindings/webidls/TestBinding.webidl @@ -479,6 +479,7 @@ interface TestBinding { sequence> returnSequenceSequence(); undefined passUnionSequenceSequence((long or sequence>) seq); + undefined passRecordPromise(record> arg); undefined passRecord(record arg); undefined passRecordWithUSVStringKey(record arg); undefined passRecordWithByteStringKey(record arg);