From 7ed6faa56c72e0372ed7523081d79ce57130d4c7 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Thu, 22 May 2025 00:48:46 -0400 Subject: [PATCH] Update to SpiderMonkey 137. Signed-off-by: Josh Matthews --- Cargo.lock | 4 +- Cargo.toml | 5 ++ components/config/prefs.rs | 2 - components/script/dom/bindings/utils.rs | 13 +++ components/script/dom/eventtarget.rs | 11 +-- components/script/dom/globalscope.rs | 3 +- components/script/script_runtime.rs | 83 ++++++++++++++----- tests/wpt/mozilla/meta/MANIFEST.json | 2 +- tests/wpt/mozilla/tests/mozilla/interfaces.js | 1 + 9 files changed, 90 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7aa149ecdd..86980088dec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4653,7 +4653,7 @@ dependencies = [ [[package]] name = "mozjs" version = "0.14.1" -source = "git+https://github.com/servo/mozjs#728acdf3d4ce0604e9f75dd1d539dc6f291ccec7" +source = "git+https://github.com/jdm/mozjs?branch=137up#91a576a85a3f8902f5f2eaab6e1b9cd1d2d1bbca" dependencies = [ "bindgen 0.71.1", "cc", @@ -4665,7 +4665,7 @@ dependencies = [ [[package]] name = "mozjs_sys" version = "0.128.9-2" -source = "git+https://github.com/servo/mozjs#728acdf3d4ce0604e9f75dd1d539dc6f291ccec7" +source = "git+https://github.com/jdm/mozjs?branch=137up#91a576a85a3f8902f5f2eaab6e1b9cd1d2d1bbca" dependencies = [ "bindgen 0.71.1", "cc", diff --git a/Cargo.toml b/Cargo.toml index 1373440d67e..fce1135ac44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -248,3 +248,8 @@ codegen-units = 1 # [patch."https://github.com/servo/rust-content-security-policy"] # content-security-policy = { path = "../rust-content-security-policy/" } # content-security-policy = { git = "https://github.com/timvdlippe/rust-content-security-policy/", branch = "fix-report-checks", features = ["serde"] } +[patch."https://github.com/servo/mozjs"] +#mozjs = { path = "../mozjs/mozjs" } +#mozjs_sys = { path = "../mozjs/mozjs-sys" } +mozjs = { git = "https://github.com/jdm/mozjs", branch = "137up" } +mozjs_sys = { git = "https://github.com/jdm/mozjs", branch = "137up" } diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 64dd9659e56..97b82a347d8 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -173,7 +173,6 @@ pub struct Preferences { pub js_mem_gc_decommit_threshold_mb: i64, pub js_mem_gc_dynamic_heap_growth_enabled: bool, pub js_mem_gc_dynamic_mark_slice_enabled: bool, - pub js_mem_gc_empty_chunk_count_max: i64, pub js_mem_gc_empty_chunk_count_min: i64, pub js_mem_gc_high_frequency_heap_growth_max: i64, pub js_mem_gc_high_frequency_heap_growth_min: i64, @@ -346,7 +345,6 @@ impl Preferences { js_mem_gc_decommit_threshold_mb: 32, js_mem_gc_dynamic_heap_growth_enabled: true, js_mem_gc_dynamic_mark_slice_enabled: true, - js_mem_gc_empty_chunk_count_max: 30, js_mem_gc_empty_chunk_count_min: 1, js_mem_gc_high_frequency_heap_growth_max: 300, js_mem_gc_high_frequency_heap_growth_min: 150, diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index ba7db745832..f05c3ff4a28 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -113,9 +113,22 @@ unsafe extern "C" fn instance_class_has_proto_at_depth( domclass.dom_class.interface_chain[depth as usize] as u32 == proto_id } +/// +unsafe extern "C" fn instance_class_is_error(clasp: *const js::jsapi::JSClass) -> bool { + if !is_dom_class(&*clasp) { + return false; + } + let domclass: *const DOMJSClass = clasp as *const _; + let domclass = &*domclass; + let root_interface = domclass.dom_class.interface_chain[0] as u32; + // TODO: support checking bare Exception prototype as well. + root_interface == PrototypeList::ID::DOMException as u32 +} + #[allow(missing_docs)] // FIXME pub(crate) const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks { instanceClassMatchesProto: Some(instance_class_has_proto_at_depth), + instanceClassIsError: Some(instance_class_is_error), }; /// Eagerly define all relevant WebIDL interface constructors on the diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index 1a5aafb0ae7..3f6fb555dd8 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -15,11 +15,11 @@ use content_security_policy as csp; use deny_public_fields::DenyPublicFields; use dom_struct::dom_struct; use fnv::FnvHasher; -use js::jsapi::JS_GetFunctionObject; +use js::jsapi::JS::CompileFunction; +use js::jsapi::{JS_GetFunctionObject, SupportUnscopables}; use js::jsval::JSVal; -use js::rust::wrappers::CompileFunction; use js::rust::{ - CompileOptionsWrapper, HandleObject, RootedObjectVectorWrapper, transform_u16_to_source_text, + CompileOptionsWrapper, HandleObject, transform_u16_to_source_text, }; use libc::c_char; use servo_url::ServoUrl; @@ -642,7 +642,8 @@ impl EventTarget { }; // Step 3.9, subsection Scope steps 1-6 - let scopechain = RootedObjectVectorWrapper::new(*cx); + //let scopechain = RootedObjectVectorWrapper::new(*cx); + let scopechain = js::rust::EnvironmentChain::new(*cx, SupportUnscopables::Yes); if let Some(element) = element { scopechain.append(document.reflector().get_jsobject().get()); @@ -655,7 +656,7 @@ impl EventTarget { rooted!(in(*cx) let mut handler = unsafe { CompileFunction( *cx, - scopechain.handle(), + scopechain.get(), options.ptr, name.as_ptr(), args.len() as u32, diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 55db2e4d248..fcd1fba9cf1 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -36,7 +36,7 @@ use ipc_channel::router::ROUTER; use js::glue::{IsWrapper, UnwrapObjectDynamic}; use js::jsapi::{ Compile1, CurrentGlobalOrNull, GetNonCCWObjectGlobal, HandleObject, Heap, - InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, SetScriptPrivate, + InstantiateGlobalStencil, InstantiateOptions, JSContext, JSObject, JSScript, SetScriptPrivate, DelazificationOption, }; use js::jsval::{PrivateValue, UndefinedValue}; use js::panic::maybe_resume_unwind; @@ -2834,6 +2834,7 @@ impl GlobalScope { skipFilenameValidation: false, hideScriptFromDebugger: false, deferDebugMetadata: false, + eagerDelazificationStrategy_: DelazificationOption::OnDemandOnly, }; let script = InstantiateGlobalStencil( *cx, diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index c407f9cfc73..75e4d3bb71e 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -24,12 +24,12 @@ use js::conversions::jsstr_to_string; use js::glue::{ CollectServoSizes, CreateJobQueue, DeleteJobQueue, DispatchableRun, JobQueueTraps, RUST_js_GetErrorMessage, SetBuildId, StreamConsumerConsumeChunk, - StreamConsumerNoteResponseURLs, StreamConsumerStreamEnd, StreamConsumerStreamError, + StreamConsumerNoteResponseURLs, StreamConsumerStreamEnd, StreamConsumerStreamError, JS_GetReservedSlot, }; use js::jsapi::{ - AsmJSOption, BuildIdCharVector, ContextOptionsRef, DisableIncrementalGC, + AsmJSOption, BuildIdCharVector, ContextOptionsRef, Dispatchable as JSRunnable, Dispatchable_MaybeShuttingDown, GCDescription, GCOptions, - GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, HandleString, Heap, + GCProgress, GCReason, GetPromiseUserInputEventHandlingState, HandleObject, HandleString, Heap, MutableHandleObject, CompilationType, HandleValue, InitConsumeStreamCallback, InitDispatchToEventLoop, JS_AddExtraGCRootsTracer, JS_InitDestroyPrincipalsCallback, JS_InitReadPrincipalsCallback, JS_SetGCCallback, JS_SetGCParameter, JS_SetGlobalJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, @@ -37,9 +37,9 @@ use js::jsapi::{ JSGCStatus, JSJitCompilerOption, JSObject, JSSecurityCallbacks, JSTracer, JobQueue, MimeType, PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, RuntimeCode, SetDOMCallbacks, SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks, - SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer, + SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer, JS_NewObject, JSClass, JSCLASS_RESERVED_SLOTS_MASK, JSCLASS_RESERVED_SLOTS_SHIFT, JSClassOps, JS_SetReservedSlot, }; -use js::jsval::UndefinedValue; +use js::jsval::{ObjectValue, UndefinedValue}; use js::panic::wrap_panic; pub(crate) use js::rust::ThreadSafeJSContext; use js::rust::wrappers::{GetPromiseIsHandled, JS_GetPromiseResult}; @@ -79,19 +79,20 @@ use crate::dom::promise::Promise; use crate::dom::promiserejectionevent::PromiseRejectionEvent; use crate::dom::response::Response; use crate::microtask::{EnqueuedPromiseCallback, Microtask, MicrotaskQueue}; -use crate::realms::{AlreadyInRealm, InRealm}; +use crate::realms::{AlreadyInRealm, InRealm, enter_realm}; use crate::script_module::EnsureModuleHooksInitialized; use crate::script_thread::trace_thread; use crate::task_source::SendableTaskSource; static JOB_QUEUE_TRAPS: JobQueueTraps = JobQueueTraps { - getIncumbentGlobal: Some(get_incumbent_global), + getHostDefinedData: Some(get_host_defined_data), enqueuePromiseJob: Some(enqueue_promise_job), empty: Some(empty), }; static SECURITY_CALLBACKS: JSSecurityCallbacks = JSSecurityCallbacks { contentSecurityPolicyAllows: Some(content_security_policy_allows), + codeForEvalGets: None, //TODO subsumes: Some(principals::subsumes), }; @@ -216,19 +217,49 @@ impl From for ScriptHangAnnotation { } } +static HOST_DEFINED_DATA: JSClassOps = JSClassOps { + addProperty: None, + delProperty: None, + enumerate: None, + newEnumerate: None, + resolve: None, + mayResolve: None, + finalize: None, + call: None, + construct: None, + trace: None, +}; + +static HOST_DEFINED_DATA_CLASS: JSClass = JSClass { + name: c"HostDefinedData".as_ptr(), + flags: (HOST_DEFINED_DATA_SLOTS & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT, + cOps: &HOST_DEFINED_DATA, + spec: ptr::null(), + ext: ptr::null(), + oOps: ptr::null(), +}; + +const INCUMBENT_SETTING_SLOT: u32 = 0; +const HOST_DEFINED_DATA_SLOTS: u32 = 1; + #[allow(unsafe_code)] -unsafe extern "C" fn get_incumbent_global(_: *const c_void, _: *mut RawJSContext) -> *mut JSObject { - let mut result = ptr::null_mut(); +unsafe extern "C" fn get_host_defined_data(_: *const c_void, cx: *mut RawJSContext, data: MutableHandleObject) -> bool { wrap_panic(&mut || { - let incumbent_global = GlobalScope::incumbent(); + let Some(incumbent_global) = GlobalScope::incumbent() else { + data.set(ptr::null_mut()); + return; + }; - assert!(incumbent_global.is_some()); + let _realm = enter_realm(&*incumbent_global); - result = incumbent_global - .map(|g| g.reflector().get_jsobject().get()) - .unwrap_or(ptr::null_mut()) + rooted!(in(cx) let result = JS_NewObject(cx, &HOST_DEFINED_DATA_CLASS)); + assert!(!result.is_null()); + + JS_SetReservedSlot(*result, INCUMBENT_SETTING_SLOT, &ObjectValue(*incumbent_global.reflector().get_jsobject())); + + data.set(result.get()); }); - result + true } #[allow(unsafe_code)] @@ -250,14 +281,16 @@ unsafe extern "C" fn enqueue_promise_job( promise: HandleObject, job: HandleObject, _allocation_site: HandleObject, - incumbent_global: HandleObject, + host_defined_data: HandleObject, ) -> bool { let cx = JSContext::from_ptr(cx); let mut result = false; wrap_panic(&mut || { let microtask_queue = &*(extra as *const MicrotaskQueue); - let global = if !incumbent_global.is_null() { - GlobalScope::from_object(incumbent_global.get()) + let global = if !host_defined_data.is_null() { + let mut incumbent_global = UndefinedValue(); + JS_GetReservedSlot(host_defined_data.get(), INCUMBENT_SETTING_SLOT, &mut incumbent_global); + GlobalScope::from_object(incumbent_global.to_object()) } else { let realm = AlreadyInRealm::assert_for_cx(cx); GlobalScope::from_context(*cx, InRealm::already(&realm)) @@ -367,6 +400,12 @@ unsafe extern "C" fn content_security_policy_allows( cx: *mut RawJSContext, runtime_code: RuntimeCode, sample: HandleString, + _compilation_type: CompilationType, + _parameter_strings: u8, //FIXME in bindings generation + _body_string: HandleString, + _parameter_args: u8, //FIXME in bindings generation + _body_arg: HandleValue, + can_compile_strings: *mut bool, ) -> bool { let mut allowed = false; let cx = JSContext::from_ptr(cx); @@ -393,7 +432,8 @@ unsafe extern "C" fn content_security_policy_allows( global.report_csp_violations(violations, None); allowed = is_evaluation_allowed == CheckResult::Allowed; }); - allowed + *can_compile_strings = allowed; + true } #[allow(unsafe_code)] @@ -549,7 +589,7 @@ impl Runtime { Some(empty_has_released_callback), ); // Pre barriers aren't working correctly at the moment - DisableIncrementalGC(cx); + JS_SetGCParameter(cx, JSGCParamKey::JSGC_INCREMENTAL_GC_ENABLED, 0); unsafe extern "C" fn dispatch_to_event_loop( closure: *mut c_void, @@ -720,9 +760,6 @@ impl Runtime { if let Some(val) = in_range(pref!(js_mem_gc_empty_chunk_count_min), 0, 10_000) { JS_SetGCParameter(cx, JSGCParamKey::JSGC_MIN_EMPTY_CHUNK_COUNT, val as u32); } - if let Some(val) = in_range(pref!(js_mem_gc_empty_chunk_count_max), 0, 10_000) { - JS_SetGCParameter(cx, JSGCParamKey::JSGC_MAX_EMPTY_CHUNK_COUNT, val as u32); - } Runtime { rt: runtime, diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index bf19c365d17..f3afeb99903 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -10573,7 +10573,7 @@ [] ], "interfaces.js": [ - "fbfc396b62c55415c0493b7528bd5e2b959452e6", + "29caf5f592034c3b68800ad398f29066335d9f06", [] ], "max-session-history-frame.html": [ diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.js b/tests/wpt/mozilla/tests/mozilla/interfaces.js index fbfc396b62c..29caf5f5920 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.js +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.js @@ -19,6 +19,7 @@ function test_interfaces(interfaceNamesInGlobalScope) { "Error", "EvalError", "FinalizationRegistry", + "Float16Array", "Float32Array", "Float64Array", "Function",