diff --git a/Cargo.lock b/Cargo.lock index 7d1eb788c0b..ff3094ecbd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -681,9 +681,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" dependencies = [ "jobserver", "libc", @@ -4000,7 +4000,7 @@ dependencies = [ [[package]] name = "mozjs" version = "0.14.1" -source = "git+https://github.com/servo/mozjs#369f2902e6481b8f237cca1652f56e61f508a0ad" +source = "git+https://github.com/servo/mozjs#fb8225ed5eb87c0d6d0b4d6126c11f5bc98687ce" dependencies = [ "bindgen", "cc", @@ -4013,8 +4013,8 @@ dependencies = [ [[package]] name = "mozjs_sys" -version = "0.115.13-0" -source = "git+https://github.com/servo/mozjs#369f2902e6481b8f237cca1652f56e61f508a0ad" +version = "0.115.13-2" +source = "git+https://github.com/servo/mozjs#fb8225ed5eb87c0d6d0b4d6126c11f5bc98687ce" dependencies = [ "bindgen", "cc", @@ -5204,6 +5204,7 @@ dependencies = [ "backtrace", "base", "base64", + "bincode", "bitflags 2.6.0", "bluetooth_traits", "canvas_traits", diff --git a/Cargo.toml b/Cargo.toml index 6042e2da92a..db0c046f293 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ background_hang_monitor_api = { path = "components/shared/background_hang_monito backtrace = "0.3" base = { path = "components/shared/base" } base64 = "0.21.7" +bincode = "1" bitflags = "2.6" bluetooth_traits = { path = "components/shared/bluetooth" } byteorder = "1.5" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 96f5502fd0c..0bf0e4958b8 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -34,6 +34,7 @@ background_hang_monitor_api = { workspace = true } backtrace = { workspace = true } base = { workspace = true } base64 = { workspace = true } +bincode = { workspace = true } bitflags = { workspace = true } bluetooth_traits = { workspace = true } canvas_traits = { workspace = true } diff --git a/components/script/dom/bindings/principals.rs b/components/script/dom/bindings/principals.rs index f408f92cbc7..14a3a826f3a 100644 --- a/components/script/dom/bindings/principals.rs +++ b/components/script/dom/bindings/principals.rs @@ -11,10 +11,15 @@ use js::glue::{ CreateRustJSPrincipals, DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, JSPrincipalsCallbacks, }; -use js::jsapi::{JSPrincipals, JS_DropPrincipals, JS_HoldPrincipals}; +use js::jsapi::{ + JSContext, JSPrincipals, JSStructuredCloneReader, JSStructuredCloneWriter, JS_DropPrincipals, + JS_HoldPrincipals, JS_ReadUint32Pair, +}; use js::rust::Runtime; use servo_url::MutableOrigin; +use super::structuredclone::StructuredCloneTags; + /// An owned reference to Servo's `JSPrincipals` instance. #[repr(transparent)] pub struct ServoJSPrincipals(NonNull); @@ -123,8 +128,60 @@ pub unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals DestroyRustJSPrincipals(principals); } +pub unsafe extern "C" fn write_jsprincipal( + principal: *mut JSPrincipals, + _cx: *mut JSContext, + writer: *mut JSStructuredCloneWriter, +) -> bool { + let Some(principal) = NonNull::new(principal) else { + return false; + }; + let obj = ServoJSPrincipalsRef::from_raw_nonnull(principal); + let origin = obj.origin(); + let Ok(bytes_of_origin) = bincode::serialize(&origin) else { + return false; + }; + let Ok(len) = bytes_of_origin.len().try_into() else { + return false; + }; + if !js::jsapi::JS_WriteUint32Pair(writer, StructuredCloneTags::Principals as u32, len) { + return false; + } + if !js::jsapi::JS_WriteBytes(writer, bytes_of_origin.as_ptr() as _, len as usize) { + return false; + } + true +} + +pub unsafe extern "C" fn read_jsprincipal( + _cx: *mut JSContext, + reader: *mut JSStructuredCloneReader, + principals: *mut *mut JSPrincipals, +) -> bool { + let mut tag: u32 = 0; + let mut len: u32 = 0; + if !JS_ReadUint32Pair(reader, &mut tag as *mut u32, &mut len as *mut u32) { + return false; + } + if tag != StructuredCloneTags::Principals as u32 { + return false; + } + let mut bytes = vec![0u8; len as usize]; + if !js::jsapi::JS_ReadBytes(reader, bytes.as_mut_ptr() as _, len as usize) { + return false; + } + let Ok(origin) = bincode::deserialize(&bytes[..]) else { + return false; + }; + let principal = ServoJSPrincipals::new(&origin); + *principals = principal.as_raw(); + // we transferred ownership of principal to the caller + std::mem::forget(principal); + true +} + const PRINCIPALS_CALLBACKS: JSPrincipalsCallbacks = JSPrincipalsCallbacks { - write: None, + write: Some(write_jsprincipal), isSystemOrAddonPrincipal: Some(principals_is_system_or_addon_principal), }; diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index d63299a5bab..a5a3e309371 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -44,11 +44,12 @@ use crate::script_runtime::JSContext as SafeJSContext; // NOTE: Current values found at https://dxr.mozilla.org/mozilla-central/ // rev/ff04d410e74b69acfab17ef7e73e7397602d5a68/js/public/StructuredClone.h#323 #[repr(u32)] -enum StructuredCloneTags { +pub(super) enum StructuredCloneTags { /// To support additional types, add new tags with values incremented from the last one before Max. Min = 0xFFFF8000, DomBlob = 0xFFFF8001, MessagePort = 0xFFFF8002, + Principals = 0xFFFF8003, Max = 0xFFFFFFFF, } diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index f635bd0b1a7..4aad9317a45 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -30,12 +30,12 @@ use js::jsapi::{ GetPromiseUserInputEventHandlingState, HandleObject, Heap, InitConsumeStreamCallback, InitDispatchToEventLoop, JSContext as RawJSContext, JSGCParamKey, JSGCStatus, JSJitCompilerOption, JSObject, JSSecurityCallbacks, JSTracer, JS_AddExtraGCRootsTracer, - JS_InitDestroyPrincipalsCallback, JS_RequestInterruptCallback, JS_SetGCCallback, - JS_SetGCParameter, JS_SetGlobalJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, - JS_SetParallelParsingEnabled, JS_SetSecurityCallbacks, JobQueue, MimeType, - PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, SetDOMCallbacks, - SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks, SetProcessBuildIdOp, - SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer, + JS_InitDestroyPrincipalsCallback, JS_InitReadPrincipalsCallback, JS_RequestInterruptCallback, + JS_SetGCCallback, JS_SetGCParameter, JS_SetGlobalJitCompilerOption, + JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled, JS_SetSecurityCallbacks, + JobQueue, MimeType, PromiseRejectionHandlingState, PromiseUserInputEventHandlingState, + SetDOMCallbacks, SetGCSliceCallback, SetJobQueue, SetPreserveWrapperCallbacks, + SetProcessBuildIdOp, SetPromiseRejectionTrackerCallback, StreamConsumer as JSStreamConsumer, }; use js::jsval::UndefinedValue; use js::panic::wrap_panic; @@ -466,6 +466,7 @@ unsafe fn new_rt_and_cx_with_parent( JS_SetSecurityCallbacks(cx, &SECURITY_CALLBACKS); JS_InitDestroyPrincipalsCallback(cx, Some(principals::destroy_servo_jsprincipal)); + JS_InitReadPrincipalsCallback(cx, Some(principals::read_jsprincipal)); // Needed for debug assertions about whether GC is running. if cfg!(debug_assertions) { diff --git a/components/url/origin.rs b/components/url/origin.rs index ce557eade60..ede6b134135 100644 --- a/components/url/origin.rs +++ b/components/url/origin.rs @@ -92,7 +92,7 @@ pub struct OpaqueOrigin(Uuid); malloc_size_of_is_0!(OpaqueOrigin); /// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2). -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct MutableOrigin(Rc<(ImmutableOrigin, RefCell>)>); malloc_size_of_is_0!(MutableOrigin);