script: Impl cloning of JSPrincipals (#32706)

* Impl cloning of JSPrincipals

* bincode as workspace dependency

* Update mozjs and cc
This commit is contained in:
Samson 2024-07-06 12:25:38 +02:00 committed by GitHub
parent 5a9dc98f07
commit 59d0f1fe1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 77 additions and 15 deletions

View file

@ -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 }

View file

@ -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<JSPrincipals>);
@ -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),
};

View file

@ -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,
}

View file

@ -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) {