mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Add AsHandleValue trait to Heap<Value> and make Heap values rooted (#38024)
Encapsulates the unsafe conversion from Heap<Value> to HandleValue<'a>, and reducing repetitive unsafe code at call. fix #37258
This commit is contained in:
parent
9416251cab
commit
04ec710e60
17 changed files with 204 additions and 146 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -5240,7 +5240,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "mozjs"
|
||||
version = "0.14.1"
|
||||
source = "git+https://github.com/servo/mozjs#4035b0c4e9e2df5cacc68c4b71e7375a48605902"
|
||||
source = "git+https://github.com/servo/mozjs#903a158b36c10902a40c7fda766406d698f98bf4"
|
||||
dependencies = [
|
||||
"bindgen 0.71.1",
|
||||
"cc",
|
||||
|
@ -5252,7 +5252,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "mozjs_sys"
|
||||
version = "0.128.13-3"
|
||||
source = "git+https://github.com/servo/mozjs#4035b0c4e9e2df5cacc68c4b71e7375a48605902"
|
||||
source = "git+https://github.com/servo/mozjs#903a158b36c10902a40c7fda766406d698f98bf4"
|
||||
dependencies = [
|
||||
"bindgen 0.71.1",
|
||||
"cc",
|
||||
|
|
|
@ -42,6 +42,7 @@ use js::typedarray::{
|
|||
};
|
||||
|
||||
use crate::dom::bindings::error::{Error, Fallible};
|
||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||
#[cfg(feature = "webgpu")]
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::script_runtime::{CanGc, JSContext};
|
||||
|
@ -52,15 +53,14 @@ use crate::script_runtime::{CanGc, JSContext};
|
|||
/// provides a view onto an `ArrayBuffer`.
|
||||
///
|
||||
/// See: <https://webidl.spec.whatwg.org/#BufferSource>
|
||||
#[derive(PartialEq)]
|
||||
pub(crate) enum BufferSource {
|
||||
/// Represents an `ArrayBufferView` (e.g., `Uint8Array`, `DataView`).
|
||||
/// See: <https://webidl.spec.whatwg.org/#ArrayBufferView>
|
||||
ArrayBufferView(Box<Heap<*mut JSObject>>),
|
||||
ArrayBufferView(RootedTraceableBox<Heap<*mut JSObject>>),
|
||||
|
||||
/// Represents an `ArrayBuffer`, a fixed-length binary data buffer.
|
||||
/// See: <https://webidl.spec.whatwg.org/#idl-ArrayBuffer>
|
||||
ArrayBuffer(Box<Heap<*mut JSObject>>),
|
||||
ArrayBuffer(RootedTraceableBox<Heap<*mut JSObject>>),
|
||||
}
|
||||
|
||||
pub(crate) fn create_heap_buffer_source_with_length<T>(
|
||||
|
@ -80,7 +80,7 @@ where
|
|||
}
|
||||
|
||||
Ok(HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(
|
||||
Heap::boxed(*array.handle()),
|
||||
RootedTraceableBox::from_box(Heap::boxed(*array.handle())),
|
||||
)))
|
||||
}
|
||||
|
||||
|
@ -100,8 +100,8 @@ where
|
|||
BufferSource::ArrayBufferView(heap) | BufferSource::ArrayBuffer(heap) => match &other
|
||||
.buffer_source
|
||||
{
|
||||
BufferSource::ArrayBufferView(from_heap) | BufferSource::ArrayBuffer(from_heap) => unsafe {
|
||||
heap.handle() == from_heap.handle()
|
||||
BufferSource::ArrayBufferView(from_heap) | BufferSource::ArrayBuffer(from_heap) => {
|
||||
std::ptr::eq(heap.get(), from_heap.get())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -122,14 +122,16 @@ where
|
|||
pub(crate) fn from_view(
|
||||
chunk: CustomAutoRooterGuard<TypedArray<T, *mut JSObject>>,
|
||||
) -> HeapBufferSource<T> {
|
||||
HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(Heap::boxed(unsafe {
|
||||
*chunk.underlying_object()
|
||||
})))
|
||||
HeapBufferSource::<T>::new(BufferSource::ArrayBufferView(RootedTraceableBox::from_box(
|
||||
Heap::boxed(unsafe { *chunk.underlying_object() }),
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn default() -> Self {
|
||||
HeapBufferSource {
|
||||
buffer_source: BufferSource::ArrayBufferView(Heap::boxed(std::ptr::null_mut())),
|
||||
buffer_source: BufferSource::ArrayBufferView(RootedTraceableBox::from_box(
|
||||
Heap::boxed(std::ptr::null_mut()),
|
||||
)),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -174,11 +176,11 @@ where
|
|||
BufferSource::ArrayBufferView(buffer) => unsafe {
|
||||
let mut is_shared = false;
|
||||
rooted!(in (*cx) let view_buffer =
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle(), &mut is_shared));
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle().into(), &mut is_shared));
|
||||
|
||||
HeapBufferSource::<ArrayBufferU8>::new(BufferSource::ArrayBuffer(Heap::boxed(
|
||||
*view_buffer.handle(),
|
||||
)))
|
||||
HeapBufferSource::<ArrayBufferU8>::new(BufferSource::ArrayBuffer(
|
||||
RootedTraceableBox::from_box(Heap::boxed(*view_buffer.handle())),
|
||||
))
|
||||
},
|
||||
BufferSource::ArrayBuffer(_) => {
|
||||
unreachable!("BufferSource::ArrayBuffer does not have a view buffer.")
|
||||
|
@ -196,7 +198,7 @@ where
|
|||
// assert buffer is an ArrayBuffer view
|
||||
assert!(JS_IsArrayBufferViewObject(*buffer.handle()));
|
||||
rooted!(in (*cx) let view_buffer =
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle(), &mut is_shared));
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle().into(), &mut is_shared));
|
||||
// This buffer is always created unshared
|
||||
debug_assert!(!is_shared);
|
||||
// Detach the ArrayBuffer
|
||||
|
@ -204,7 +206,7 @@ where
|
|||
}
|
||||
},
|
||||
BufferSource::ArrayBuffer(buffer) => unsafe {
|
||||
DetachArrayBuffer(*cx, Handle::from_raw(buffer.handle()))
|
||||
DetachArrayBuffer(*cx, Handle::from_raw(buffer.handle().into()))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +228,7 @@ where
|
|||
unsafe {
|
||||
assert!(JS_IsArrayBufferViewObject(*buffer.handle()));
|
||||
rooted!(in (*cx) let view_buffer =
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle(), &mut is_shared));
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle().into(), &mut is_shared));
|
||||
debug_assert!(!is_shared);
|
||||
IsDetachedArrayBufferObject(*view_buffer.handle())
|
||||
}
|
||||
|
@ -245,7 +247,7 @@ where
|
|||
unsafe {
|
||||
assert!(JS_IsArrayBufferViewObject(*buffer.handle()));
|
||||
rooted!(in (*cx) let view_buffer =
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle(), &mut is_shared));
|
||||
JS_GetArrayBufferViewBuffer(*cx, buffer.handle().into(), &mut is_shared));
|
||||
debug_assert!(!is_shared);
|
||||
GetArrayBufferByteLength(*view_buffer.handle())
|
||||
}
|
||||
|
@ -429,13 +431,16 @@ where
|
|||
) -> Option<HeapBufferSource<ArrayBufferU8>> {
|
||||
match &self.buffer_source {
|
||||
BufferSource::ArrayBufferView(heap) | BufferSource::ArrayBuffer(heap) => {
|
||||
let result =
|
||||
unsafe { ArrayBufferClone(*cx, heap.handle(), byte_offset, byte_length) };
|
||||
let result = unsafe {
|
||||
ArrayBufferClone(*cx, heap.handle().into(), byte_offset, byte_length)
|
||||
};
|
||||
if result.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(HeapBufferSource::<ArrayBufferU8>::new(
|
||||
BufferSource::ArrayBuffer(Heap::boxed(result)),
|
||||
BufferSource::ArrayBuffer(RootedTraceableBox::from_box(Heap::boxed(
|
||||
result,
|
||||
))),
|
||||
))
|
||||
}
|
||||
},
|
||||
|
@ -466,11 +471,9 @@ where
|
|||
match &from_buffer.buffer_source {
|
||||
BufferSource::ArrayBufferView(from_heap) |
|
||||
BufferSource::ArrayBuffer(from_heap) => {
|
||||
unsafe {
|
||||
if heap.handle() == from_heap.handle() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if std::ptr::eq(heap.get(), from_heap.get()) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -514,9 +517,9 @@ where
|
|||
BufferSource::ArrayBufferView(from_heap) |
|
||||
BufferSource::ArrayBuffer(from_heap) => ArrayBufferCopyData(
|
||||
*cx,
|
||||
heap.handle(),
|
||||
heap.handle().into(),
|
||||
dest_start,
|
||||
from_heap.handle(),
|
||||
from_heap.handle().into(),
|
||||
from_byte_offset,
|
||||
bytes_to_copy,
|
||||
),
|
||||
|
@ -541,7 +544,7 @@ where
|
|||
let mut is_defined = false;
|
||||
match &self.buffer_source {
|
||||
BufferSource::ArrayBufferView(heap) | BufferSource::ArrayBuffer(heap) => unsafe {
|
||||
if !HasDefinedArrayBufferDetachKey(*cx, heap.handle(), &mut is_defined) {
|
||||
if !HasDefinedArrayBufferDetachKey(*cx, heap.handle().into(), &mut is_defined) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
@ -568,7 +571,7 @@ where
|
|||
// Step 2 (Reordered)
|
||||
let buffer_data = match &self.buffer_source {
|
||||
BufferSource::ArrayBufferView(buffer) | BufferSource::ArrayBuffer(buffer) => unsafe {
|
||||
StealArrayBufferContents(*cx, buffer.handle())
|
||||
StealArrayBufferContents(*cx, buffer.handle().into())
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -588,9 +591,9 @@ where
|
|||
// whose [[ArrayBufferData]] internal slot value is arrayBufferData and
|
||||
// whose [[ArrayBufferByteLength]] internal slot value is arrayBufferByteLength.
|
||||
Ok(HeapBufferSource::<ArrayBufferU8>::new(
|
||||
BufferSource::ArrayBuffer(Heap::boxed(unsafe {
|
||||
BufferSource::ArrayBuffer(RootedTraceableBox::from_box(Heap::boxed(unsafe {
|
||||
NewArrayBufferWithContents(*cx, buffer_length, buffer_data)
|
||||
})),
|
||||
}))),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -679,9 +682,9 @@ pub(crate) fn create_buffer_source_with_constructor(
|
|||
match &buffer_source.buffer_source {
|
||||
BufferSource::ArrayBuffer(heap) => match constructor {
|
||||
Constructor::DataView => Ok(HeapBufferSource::new(BufferSource::ArrayBufferView(
|
||||
Heap::boxed(unsafe {
|
||||
JS_NewDataView(*cx, heap.handle(), byte_offset, byte_length)
|
||||
}),
|
||||
RootedTraceableBox::from_box(Heap::boxed(unsafe {
|
||||
JS_NewDataView(*cx, heap.handle().into(), byte_offset, byte_length)
|
||||
})),
|
||||
))),
|
||||
Constructor::Name(name_type) => construct_typed_array(
|
||||
cx,
|
||||
|
@ -709,45 +712,78 @@ fn construct_typed_array(
|
|||
BufferSource::ArrayBuffer(heap) => {
|
||||
let array_view = unsafe {
|
||||
match name_type {
|
||||
Type::Int8 => {
|
||||
JS_NewInt8ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Uint8 => {
|
||||
JS_NewUint8ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Uint16 => {
|
||||
JS_NewUint16ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Int16 => {
|
||||
JS_NewInt16ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Int32 => {
|
||||
JS_NewInt32ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Uint32 => {
|
||||
JS_NewUint32ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Float32 => {
|
||||
JS_NewFloat32ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Float64 => {
|
||||
JS_NewFloat64ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Uint8Clamped => JS_NewUint8ClampedArrayWithBuffer(
|
||||
Type::Int8 => JS_NewInt8ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle(),
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Uint8 => JS_NewUint8ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Uint16 => JS_NewUint16ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Int16 => JS_NewInt16ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Int32 => JS_NewInt32ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Uint32 => JS_NewUint32ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Float32 => JS_NewFloat32ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Float64 => JS_NewFloat64ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Uint8Clamped => JS_NewUint8ClampedArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::BigInt64 => JS_NewBigInt64ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::BigUint64 => JS_NewBigUint64ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::Float16 => JS_NewFloat16ArrayWithBuffer(
|
||||
*cx,
|
||||
heap.handle().into(),
|
||||
byte_offset,
|
||||
byte_length,
|
||||
),
|
||||
Type::BigInt64 => {
|
||||
JS_NewBigInt64ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::BigUint64 => {
|
||||
JS_NewBigUint64ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Float16 => {
|
||||
JS_NewFloat16ArrayWithBuffer(*cx, heap.handle(), byte_offset, byte_length)
|
||||
},
|
||||
Type::Int64 | Type::Simd128 | Type::MaxTypedArrayViewType => {
|
||||
unreachable!("Invalid TypedArray type")
|
||||
},
|
||||
|
@ -755,7 +791,7 @@ fn construct_typed_array(
|
|||
};
|
||||
|
||||
Ok(HeapBufferSource::new(BufferSource::ArrayBufferView(
|
||||
Heap::boxed(array_view),
|
||||
RootedTraceableBox::from_box(Heap::boxed(array_view)),
|
||||
)))
|
||||
},
|
||||
BufferSource::ArrayBufferView(_) => {
|
||||
|
@ -779,7 +815,7 @@ pub(crate) fn create_array_buffer_with_size(
|
|||
Err(Error::Type("can't create array buffer".to_owned()))
|
||||
} else {
|
||||
Ok(HeapBufferSource::<ArrayBufferU8>::new(
|
||||
BufferSource::ArrayBuffer(Heap::boxed(result)),
|
||||
BufferSource::ArrayBuffer(RootedTraceableBox::from_box(Heap::boxed(result))),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -866,6 +902,7 @@ impl DataBlock {
|
|||
|
||||
#[cfg(feature = "webgpu")]
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) struct DataView {
|
||||
#[no_trace]
|
||||
range: Range<usize>,
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::dom::bindings::utils::to_frozen_array;
|
|||
use crate::script_runtime::{CanGc, JSContext};
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) struct CachedFrozenArray {
|
||||
frozen_value: DomRefCell<Option<Heap<JSVal>>>,
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@ use std::hash::{Hash, Hasher};
|
|||
use std::marker::PhantomData;
|
||||
use std::{mem, ptr};
|
||||
|
||||
use js::jsapi::{JSObject, JSTracer};
|
||||
use js::jsapi::{Heap, JSObject, JSTracer, Value};
|
||||
use js::rust::HandleValue;
|
||||
use layout_api::TrustedNodeAddress;
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
pub(crate) use script_bindings::root::*;
|
||||
|
@ -409,3 +410,21 @@ where
|
|||
&*(slice as *const [Dom<T>] as *const [LayoutDom<T>])
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a rooted `Heap<Value>` into a `HandleValue`.
|
||||
///
|
||||
/// This is only safe if the `Heap` is rooted (e.g., held inside a `Dom`-managed struct),
|
||||
/// and the `#[must_root]` crown lint is active to enforce rooting at compile time.
|
||||
/// Avoids repeating unsafe `from_raw` calls at each usage site.
|
||||
pub trait AsHandleValue<'a> {
|
||||
fn as_handle_value(&'a self) -> HandleValue<'a>;
|
||||
}
|
||||
|
||||
impl<'a> AsHandleValue<'a> for Heap<Value> {
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
fn as_handle_value(&'a self) -> HandleValue<'a> {
|
||||
// SAFETY: `self` is assumed to be rooted, and `handle()` ties
|
||||
// the lifetime to `&self`, which the compiler can enforce.
|
||||
unsafe { HandleValue::from_marked_location(self.ptr.get() as *const _) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use js::glue::UnwrapObjectStatic;
|
|||
use js::jsapi::{HandleValueArray, Heap, IsCallable, IsConstructor, JSAutoRealm, JSObject};
|
||||
use js::jsval::{BooleanValue, JSVal, NullValue, ObjectValue, UndefinedValue};
|
||||
use js::rust::wrappers::{Construct1, JS_GetProperty, SameValue};
|
||||
use js::rust::{HandleObject, HandleValue, MutableHandleValue};
|
||||
use js::rust::{HandleObject, MutableHandleValue};
|
||||
use script_bindings::conversions::{SafeFromJSValConvertible, SafeToJSValConvertible};
|
||||
|
||||
use super::bindings::trace::HashMapTracedValues;
|
||||
|
@ -32,7 +32,7 @@ use crate::dom::bindings::error::{
|
|||
};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, DomObject, Reflector, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::root::{AsHandleValue, Dom, DomRoot};
|
||||
use crate::dom::bindings::settings_stack::is_execution_stack_empty;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::document::Document;
|
||||
|
@ -999,7 +999,6 @@ pub(crate) enum CustomElementReaction {
|
|||
|
||||
impl CustomElementReaction {
|
||||
/// <https://html.spec.whatwg.org/multipage/#invoke-custom-element-reactions>
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn invoke(&self, element: &Element, can_gc: CanGc) {
|
||||
// Step 2.1
|
||||
match *self {
|
||||
|
@ -1008,10 +1007,7 @@ impl CustomElementReaction {
|
|||
},
|
||||
CustomElementReaction::Callback(ref callback, ref arguments) => {
|
||||
// We're rooted, so it's safe to hand out a handle to objects in Heap
|
||||
let arguments = arguments
|
||||
.iter()
|
||||
.map(|arg| unsafe { HandleValue::from_raw(arg.handle()) })
|
||||
.collect();
|
||||
let arguments = arguments.iter().map(|arg| arg.as_handle_value()).collect();
|
||||
rooted!(in(*GlobalScope::get_cx()) let mut value: JSVal);
|
||||
let _ = callback.Call_(
|
||||
element,
|
||||
|
@ -1112,6 +1108,7 @@ impl CustomElementReactionStack {
|
|||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction>
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn enqueue_callback_reaction(
|
||||
&self,
|
||||
element: &Element,
|
||||
|
|
|
@ -422,6 +422,7 @@ impl Element {
|
|||
self.ensure_rare_data().custom_element_definition = None;
|
||||
}
|
||||
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn push_callback_reaction(&self, function: Rc<Function>, args: Box<[Heap<JSVal>]>) {
|
||||
self.ensure_rare_data()
|
||||
.custom_element_reaction_queue
|
||||
|
|
|
@ -115,7 +115,7 @@ pub(crate) enum FileReaderReadyState {
|
|||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub(crate) enum FileReaderResult {
|
||||
ArrayBuffer(#[ignore_malloc_size_of = "mozjs"] Heap<JSVal>),
|
||||
ArrayBuffer(#[ignore_malloc_size_of = "mozjs"] RootedTraceableBox<Heap<JSVal>>),
|
||||
String(DOMString),
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,8 @@ impl FileReader {
|
|||
.is_ok()
|
||||
);
|
||||
|
||||
*result.borrow_mut() = Some(FileReaderResult::ArrayBuffer(Heap::default()));
|
||||
*result.borrow_mut() =
|
||||
Some(FileReaderResult::ArrayBuffer(RootedTraceableBox::default()));
|
||||
|
||||
if let Some(FileReaderResult::ArrayBuffer(ref mut heap)) = *result.borrow_mut() {
|
||||
heap.set(jsval::ObjectValue(array_buffer.get()));
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
|||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::root::{AsHandleValue, Dom, DomRoot};
|
||||
use crate::dom::bindings::str::{DOMString, USVString};
|
||||
use crate::dom::bindings::structuredclone;
|
||||
use crate::dom::event::Event;
|
||||
|
@ -53,18 +53,18 @@ pub(crate) struct History {
|
|||
|
||||
impl History {
|
||||
pub(crate) fn new_inherited(window: &Window) -> History {
|
||||
let state = Heap::default();
|
||||
state.set(NullValue());
|
||||
History {
|
||||
reflector_: Reflector::new(),
|
||||
window: Dom::from_ref(window),
|
||||
state,
|
||||
state: Heap::default(),
|
||||
state_id: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(window: &Window, can_gc: CanGc) -> DomRoot<History> {
|
||||
reflect_dom_object(Box::new(History::new_inherited(window)), window, can_gc)
|
||||
let dom_root = reflect_dom_object(Box::new(History::new_inherited(window)), window, can_gc);
|
||||
dom_root.state.set(NullValue());
|
||||
dom_root
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,6 @@ impl History {
|
|||
|
||||
/// <https://html.spec.whatwg.org/multipage/#history-traversal>
|
||||
/// Steps 5-16
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn activate_state(
|
||||
&self,
|
||||
state_id: Option<HistoryStateId>,
|
||||
|
@ -145,7 +144,7 @@ impl History {
|
|||
PopStateEvent::dispatch_jsval(
|
||||
self.window.upcast::<EventTarget>(),
|
||||
&self.window,
|
||||
unsafe { HandleValue::from_raw(self.state.handle()) },
|
||||
self.state.as_handle_value(),
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -166,7 +166,6 @@ impl Notification {
|
|||
) -> Self {
|
||||
// TODO: missing call to https://html.spec.whatwg.org/multipage/#structuredserializeforstorage
|
||||
// may be find in `dom/bindings/structuredclone.rs`
|
||||
let data = Heap::default();
|
||||
|
||||
let title = title.clone();
|
||||
let dir = options.dir;
|
||||
|
@ -234,7 +233,7 @@ impl Notification {
|
|||
serviceworker_registration: None,
|
||||
title,
|
||||
body,
|
||||
data,
|
||||
data: Heap::default(),
|
||||
dir,
|
||||
image,
|
||||
icon,
|
||||
|
|
|
@ -35,6 +35,7 @@ use script_bindings::conversions::SafeToJSValConvertible;
|
|||
use crate::dom::bindings::conversions::root_from_object;
|
||||
use crate::dom::bindings::error::{Error, ErrorToJsval};
|
||||
use crate::dom::bindings::reflector::{DomGlobal, DomObject, MutDomObject, Reflector};
|
||||
use crate::dom::bindings::root::AsHandleValue;
|
||||
use crate::dom::bindings::settings_stack::AutoEntryScript;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
|
||||
|
@ -435,7 +436,6 @@ struct WaitForAllFulfillmentHandler {
|
|||
}
|
||||
|
||||
impl Callback for WaitForAllFulfillmentHandler {
|
||||
#[allow(unsafe_code)]
|
||||
fn callback(&self, _cx: SafeJSContext, v: HandleValue, _realm: InRealm, _can_gc: CanGc) {
|
||||
// Let fulfillmentHandler be the following steps given arg:
|
||||
|
||||
|
@ -453,15 +453,10 @@ impl Callback for WaitForAllFulfillmentHandler {
|
|||
|
||||
// If fulfilledCount equals total, then perform successSteps given result.
|
||||
if equals_total {
|
||||
// Safety: the values are kept alive by the Heap
|
||||
// while their handles are passed to the the success steps.
|
||||
let result_handles: Vec<HandleValue> = unsafe {
|
||||
self.result
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|val| HandleValue::from_raw(val.handle()))
|
||||
.collect()
|
||||
};
|
||||
let result_ref = self.result.borrow();
|
||||
let result_handles: Vec<HandleValue> =
|
||||
result_ref.iter().map(|v| v.as_handle_value()).collect();
|
||||
|
||||
(self.success_steps)(result_handles);
|
||||
}
|
||||
}
|
||||
|
@ -496,6 +491,7 @@ impl Callback for WaitForAllRejectionHandler {
|
|||
}
|
||||
|
||||
/// <https://webidl.spec.whatwg.org/#wait-for-all>
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn wait_for_all(
|
||||
cx: SafeJSContext,
|
||||
global: &GlobalScope,
|
||||
|
|
|
@ -154,7 +154,7 @@ pub(crate) struct PipeTo {
|
|||
/// The error potentially passed to shutdown,
|
||||
/// stored here because we must keep it across a microtask.
|
||||
#[ignore_malloc_size_of = "mozjs"]
|
||||
shutdown_error: Rc<RefCell<Option<Heap<JSVal>>>>,
|
||||
shutdown_error: Rc<RefCell<Option<RootedTraceableBox<Heap<JSVal>>>>>,
|
||||
|
||||
/// The promise returned by a shutdown action.
|
||||
/// We keep it to only continue when it is not pending anymore.
|
||||
|
@ -376,7 +376,7 @@ impl PipeTo {
|
|||
/// Setting shutdown error in a way that ensures it isn't
|
||||
/// moved after it has been set.
|
||||
fn set_shutdown_error(&self, error: SafeHandleValue) {
|
||||
*self.shutdown_error.borrow_mut() = Some(Heap::default());
|
||||
*self.shutdown_error.borrow_mut() = Some(RootedTraceableBox::new(Heap::default()));
|
||||
let Some(ref heap) = *self.shutdown_error.borrow() else {
|
||||
unreachable!("Option set to Some(heap) above.");
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::rc::Rc;
|
|||
|
||||
use constellation_traits::ScriptToConstellationMessage;
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::Heap;
|
||||
use js::jsapi::HandleObject;
|
||||
use webgpu_traits::WebGPUAdapterResponse;
|
||||
use wgpu_types::PowerPreference;
|
||||
|
||||
|
@ -117,7 +117,7 @@ impl RoutedPromiseListener<WebGPUAdapterResponse> for GPU {
|
|||
"{} ({:?})",
|
||||
adapter.adapter_info.name, adapter.adapter_id.0
|
||||
)),
|
||||
Heap::default(),
|
||||
HandleObject::null(),
|
||||
adapter.features,
|
||||
adapter.limits,
|
||||
adapter.adapter_info,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::jsapi::{HandleObject, Heap, JSObject};
|
||||
use webgpu_traits::{
|
||||
RequestDeviceError, WebGPU, WebGPUAdapter, WebGPUDeviceResponse, WebGPURequest,
|
||||
};
|
||||
|
@ -49,7 +49,6 @@ impl GPUAdapter {
|
|||
fn new_inherited(
|
||||
channel: WebGPU,
|
||||
name: DOMString,
|
||||
extensions: Heap<*mut JSObject>,
|
||||
features: &GPUSupportedFeatures,
|
||||
limits: &GPUSupportedLimits,
|
||||
info: &GPUAdapterInfo,
|
||||
|
@ -59,7 +58,7 @@ impl GPUAdapter {
|
|||
reflector_: Reflector::new(),
|
||||
channel,
|
||||
name,
|
||||
extensions,
|
||||
extensions: Heap::default(),
|
||||
features: Dom::from_ref(features),
|
||||
limits: Dom::from_ref(limits),
|
||||
info: Dom::from_ref(info),
|
||||
|
@ -72,7 +71,7 @@ impl GPUAdapter {
|
|||
global: &GlobalScope,
|
||||
channel: WebGPU,
|
||||
name: DOMString,
|
||||
extensions: Heap<*mut JSObject>,
|
||||
extensions: HandleObject,
|
||||
features: wgpu_types::Features,
|
||||
limits: wgpu_types::Limits,
|
||||
info: wgpu_types::AdapterInfo,
|
||||
|
@ -82,13 +81,15 @@ impl GPUAdapter {
|
|||
let features = GPUSupportedFeatures::Constructor(global, None, features, can_gc).unwrap();
|
||||
let limits = GPUSupportedLimits::new(global, limits, can_gc);
|
||||
let info = GPUAdapterInfo::new(global, info, can_gc);
|
||||
reflect_dom_object(
|
||||
let dom_root = reflect_dom_object(
|
||||
Box::new(GPUAdapter::new_inherited(
|
||||
channel, name, extensions, &features, &limits, &info, adapter,
|
||||
channel, name, &features, &limits, &info, adapter,
|
||||
)),
|
||||
global,
|
||||
can_gc,
|
||||
)
|
||||
);
|
||||
dom_root.extensions.set(*extensions);
|
||||
dom_root
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +227,7 @@ impl RoutedPromiseListener<WebGPUDeviceResponse> for GPUAdapter {
|
|||
&self.global(),
|
||||
self.channel.clone(),
|
||||
self,
|
||||
Heap::default(),
|
||||
HandleObject::null(),
|
||||
descriptor.required_features,
|
||||
descriptor.required_limits,
|
||||
device_id,
|
||||
|
@ -259,7 +260,7 @@ impl RoutedPromiseListener<WebGPUDeviceResponse> for GPUAdapter {
|
|||
&self.global(),
|
||||
self.channel.clone(),
|
||||
self,
|
||||
Heap::default(),
|
||||
HandleObject::null(),
|
||||
wgpu_types::Features::default(),
|
||||
wgpu_types::Limits::default(),
|
||||
device_id,
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::cell::Cell;
|
|||
use std::rc::Rc;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject};
|
||||
use js::jsapi::{HandleObject, Heap, JSObject};
|
||||
use webgpu_traits::{
|
||||
PopError, WebGPU, WebGPUComputePipeline, WebGPUComputePipelineResponse, WebGPUDevice,
|
||||
WebGPUPoppedErrorScopeResponse, WebGPUQueue, WebGPURenderPipeline,
|
||||
|
@ -114,7 +114,6 @@ impl GPUDevice {
|
|||
fn new_inherited(
|
||||
channel: WebGPU,
|
||||
adapter: &GPUAdapter,
|
||||
extensions: Heap<*mut JSObject>,
|
||||
features: &GPUSupportedFeatures,
|
||||
limits: &GPUSupportedLimits,
|
||||
device: WebGPUDevice,
|
||||
|
@ -126,7 +125,7 @@ impl GPUDevice {
|
|||
eventtarget: EventTarget::new_inherited(),
|
||||
channel,
|
||||
adapter: Dom::from_ref(adapter),
|
||||
extensions,
|
||||
extensions: Heap::default(),
|
||||
features: Dom::from_ref(features),
|
||||
limits: Dom::from_ref(limits),
|
||||
label: DomRefCell::new(USVString::from(label)),
|
||||
|
@ -142,7 +141,7 @@ impl GPUDevice {
|
|||
global: &GlobalScope,
|
||||
channel: WebGPU,
|
||||
adapter: &GPUAdapter,
|
||||
extensions: Heap<*mut JSObject>,
|
||||
extensions: HandleObject,
|
||||
features: wgpu_types::Features,
|
||||
limits: wgpu_types::Limits,
|
||||
device: WebGPUDevice,
|
||||
|
@ -158,7 +157,6 @@ impl GPUDevice {
|
|||
Box::new(GPUDevice::new_inherited(
|
||||
channel,
|
||||
adapter,
|
||||
extensions,
|
||||
&features,
|
||||
&limits,
|
||||
device,
|
||||
|
@ -170,6 +168,7 @@ impl GPUDevice {
|
|||
can_gc,
|
||||
);
|
||||
queue.set_device(&device);
|
||||
device.extensions.set(*extensions);
|
||||
device
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,16 +88,15 @@ fn gen_type_error(global: &GlobalScope, string: String, can_gc: CanGc) -> Rethro
|
|||
}
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
pub(crate) struct ModuleObject(Box<Heap<*mut JSObject>>);
|
||||
pub(crate) struct ModuleObject(RootedTraceableBox<Heap<*mut JSObject>>);
|
||||
|
||||
impl ModuleObject {
|
||||
fn new(obj: RustHandleObject) -> ModuleObject {
|
||||
ModuleObject(Heap::boxed(obj.get()))
|
||||
ModuleObject(RootedTraceableBox::from_box(Heap::boxed(obj.get())))
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub(crate) fn handle(&self) -> HandleObject {
|
||||
unsafe { self.0.handle() }
|
||||
self.0.handle().into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
|||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, DomObject};
|
||||
use crate::dom::bindings::root::Dom;
|
||||
use crate::dom::bindings::root::{AsHandleValue, Dom};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::csp::CspReporting;
|
||||
use crate::dom::document::{ImageAnimationUpdateCallback, RefreshRedirectDue};
|
||||
|
@ -395,6 +395,7 @@ pub(crate) enum TimerCallback {
|
|||
}
|
||||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
enum InternalTimerCallback {
|
||||
StringTimerCallback(DOMString),
|
||||
FunctionTimerCallback(
|
||||
|
@ -416,6 +417,7 @@ impl Default for JsTimers {
|
|||
|
||||
impl JsTimers {
|
||||
// see https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn set_timeout_or_interval(
|
||||
&self,
|
||||
global: &GlobalScope,
|
||||
|
@ -583,13 +585,8 @@ impl JsTimerTask {
|
|||
}
|
||||
}
|
||||
|
||||
// Returning Handles directly from Heap values is inherently unsafe, but here it's
|
||||
// always done via rooted JsTimers, which is safe.
|
||||
#[allow(unsafe_code)]
|
||||
fn collect_heap_args<'b>(&self, args: &'b [Heap<JSVal>]) -> Vec<HandleValue<'b>> {
|
||||
args.iter()
|
||||
.map(|arg| unsafe { HandleValue::from_raw(arg.handle()) })
|
||||
.collect()
|
||||
args.iter().map(|arg| arg.as_handle_value()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -955,39 +955,51 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
|
||||
if is_typed_array(type):
|
||||
if failureCode is None:
|
||||
unwrapFailureCode = (f'throw_type_error(*cx, "{sourceDescription} is not a typed array.");\n'
|
||||
f'{exceptionCode}')
|
||||
unwrapFailureCode = (
|
||||
f'throw_type_error(*cx, "{sourceDescription} is not a typed array.");\n'
|
||||
f'{exceptionCode}'
|
||||
)
|
||||
else:
|
||||
unwrapFailureCode = failureCode
|
||||
|
||||
typeName = type.unroll().name # unroll because it may be nullable
|
||||
|
||||
if isMember == "Union":
|
||||
is_union_member = (isMember == "Union")
|
||||
|
||||
if is_union_member:
|
||||
typeName = f"Heap{typeName}"
|
||||
map_call = ".map(RootedTraceableBox::new)"
|
||||
else:
|
||||
map_call = ""
|
||||
|
||||
templateBody = fill(
|
||||
"""
|
||||
match typedarray::${ty}::from($${val}.get().to_object()) {
|
||||
f"""
|
||||
match typedarray::${{ty}}::from($${{val}}.get().to_object()){map_call} {{
|
||||
Ok(val) => val,
|
||||
Err(()) => {
|
||||
$*{failureCode}
|
||||
}
|
||||
}
|
||||
Err(()) => {{
|
||||
$*{{failureCode}}
|
||||
}}
|
||||
}}
|
||||
""",
|
||||
ty=typeName,
|
||||
failureCode=f"{unwrapFailureCode}\n",
|
||||
)
|
||||
|
||||
if isMember == "Union":
|
||||
templateBody = f"RootedTraceableBox::new({templateBody})"
|
||||
|
||||
declType = CGGeneric(f"typedarray::{typeName}")
|
||||
if is_union_member:
|
||||
declType = CGWrapper(declType, pre="RootedTraceableBox<", post=">")
|
||||
|
||||
if type.nullable():
|
||||
templateBody = f"Some({templateBody})"
|
||||
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||
|
||||
templateBody = wrapObjectTemplate(templateBody, "None",
|
||||
isDefinitelyObject, type, failureCode)
|
||||
templateBody = wrapObjectTemplate(
|
||||
templateBody,
|
||||
"None",
|
||||
isDefinitelyObject,
|
||||
type,
|
||||
failureCode,
|
||||
)
|
||||
|
||||
return handleOptional(templateBody, declType, handleDefault("None"))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue