script: introduce safe wrappers for js val conversions (#38004)

Introduce a safe wrapper trait for the unsafe `ToJSValConvertible`, and
use it in `script/dom` where the default `T` implementation works.

Part of https://github.com/servo/servo/issues/37951

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
This commit is contained in:
Gregory Terzian 2025-07-15 08:57:15 +07:00 committed by GitHub
parent 9e2ee0029a
commit 027954dbad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 149 additions and 187 deletions

View file

@ -6,11 +6,11 @@ use std::ptr;
use html5ever::interface::QualName;
use html5ever::{LocalName, local_name, ns};
use js::conversions::ToJSValConvertible;
use js::glue::{UnwrapObjectDynamic, UnwrapObjectStatic};
use js::jsapi::{CallArgs, CurrentGlobalOrNull, JSAutoRealm, JSObject};
use js::rust::wrappers::{JS_SetPrototype, JS_WrapObject};
use js::rust::{HandleObject, MutableHandleObject, MutableHandleValue};
use script_bindings::conversions::SafeToJSValConvertible;
use script_bindings::interface::get_desired_proto;
use super::utils::ProtoOrIfaceArray;
@ -242,7 +242,7 @@ fn html_constructor(
JS_SetPrototype(*cx, element.handle(), prototype.handle());
result.to_jsval(*cx, MutableHandleValue::from_raw(call_args.rval()));
result.safe_to_jsval(cx, MutableHandleValue::from_raw(call_args.rval()));
}
Ok(())
}

View file

@ -8,6 +8,7 @@ use std::ptr::NonNull;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject, Value};
use js::rust::HandleObject;
use script_bindings::conversions::SafeToJSValConvertible;
use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
CryptoKeyMethods, KeyType, KeyUsage,
@ -16,7 +17,6 @@ use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::js::conversions::ToJSValConvertible;
use crate::script_runtime::{CanGc, JSContext};
/// The underlying cryptographic data this key represents
@ -135,14 +135,11 @@ impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
NonNull::new(self.algorithm_object.get()).unwrap()
}
#[allow(unsafe_code)]
/// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
fn Usages(&self, cx: JSContext) -> NonNull<JSObject> {
unsafe {
rooted!(in(*cx) let mut usages: Value);
self.usages.to_jsval(*cx, usages.handle_mut());
NonNull::new(usages.to_object()).unwrap()
}
rooted!(in(*cx) let mut usages: Value);
self.usages.safe_to_jsval(cx, usages.handle_mut());
NonNull::new(usages.to_object()).unwrap()
}
}

View file

@ -10,12 +10,12 @@ use std::{mem, ptr};
use dom_struct::dom_struct;
use html5ever::{LocalName, Namespace, Prefix, ns};
use js::conversions::ToJSValConvertible;
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 script_bindings::conversions::SafeToJSValConvertible;
use super::bindings::trace::HashMapTracedValues;
use crate::dom::bindings::callback::{CallbackContainer, ExceptionHandling};
@ -539,24 +539,19 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
// Step 16, 16.3
let promise = self.when_defined.borrow_mut().remove(&name);
if let Some(promise) = promise {
unsafe {
rooted!(in(*cx) let mut constructor = UndefinedValue());
definition
.constructor
.to_jsval(*cx, constructor.handle_mut());
promise.resolve_native(&constructor.get(), can_gc);
}
rooted!(in(*cx) let mut constructor = UndefinedValue());
definition
.constructor
.safe_to_jsval(cx, constructor.handle_mut());
promise.resolve_native(&constructor.get(), can_gc);
}
Ok(())
}
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-get>
#[allow(unsafe_code)]
fn Get(&self, cx: JSContext, name: DOMString, mut retval: MutableHandleValue) {
match self.definitions.borrow().get(&LocalName::from(&*name)) {
Some(definition) => unsafe {
definition.constructor.to_jsval(*cx, retval);
},
Some(definition) => definition.constructor.safe_to_jsval(cx, retval),
None => retval.set(UndefinedValue()),
}
}
@ -572,7 +567,6 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
}
/// <https://html.spec.whatwg.org/multipage/#dom-customelementregistry-whendefined>
#[allow(unsafe_code)]
fn WhenDefined(&self, name: DOMString, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let name = LocalName::from(&*name);
@ -592,16 +586,14 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
// Step 2
if let Some(definition) = self.definitions.borrow().get(&LocalName::from(&*name)) {
unsafe {
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut constructor = UndefinedValue());
definition
.constructor
.to_jsval(*cx, constructor.handle_mut());
let promise = Promise::new_in_current_realm(comp, can_gc);
promise.resolve_native(&constructor.get(), can_gc);
return promise;
}
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let mut constructor = UndefinedValue());
definition
.constructor
.safe_to_jsval(cx, constructor.handle_mut());
let promise = Promise::new_in_current_realm(comp, can_gc);
promise.resolve_native(&constructor.get(), can_gc);
return promise;
}
// Steps 3, 4, 5
@ -927,9 +919,7 @@ fn run_upgrade_constructor(
let cx = GlobalScope::get_cx();
rooted!(in(*cx) let constructor_val = ObjectValue(constructor.callback()));
rooted!(in(*cx) let mut element_val = UndefinedValue());
unsafe {
element.to_jsval(*cx, element_val.handle_mut());
}
element.safe_to_jsval(cx, element_val.handle_mut());
rooted!(in(*cx) let mut construct_result = ptr::null_mut::<JSObject>());
{
// Step 8.1. If definition's disable shadow is true and element's shadow root is non-null,
@ -1128,7 +1118,6 @@ impl CustomElementReactionStack {
}
/// <https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction>
#[allow(unsafe_code)]
pub(crate) fn enqueue_callback_reaction(
&self,
element: &Element,
@ -1174,30 +1163,22 @@ impl CustomElementReactionStack {
let local_name = DOMString::from(&*local_name);
rooted!(in(*cx) let mut name_value = UndefinedValue());
unsafe {
local_name.to_jsval(*cx, name_value.handle_mut());
}
local_name.safe_to_jsval(cx, name_value.handle_mut());
rooted!(in(*cx) let mut old_value = NullValue());
if let Some(old_val) = old_val {
unsafe {
old_val.to_jsval(*cx, old_value.handle_mut());
}
old_val.safe_to_jsval(cx, old_value.handle_mut());
}
rooted!(in(*cx) let mut value = NullValue());
if let Some(val) = val {
unsafe {
val.to_jsval(*cx, value.handle_mut());
}
val.safe_to_jsval(cx, value.handle_mut());
}
rooted!(in(*cx) let mut namespace_value = NullValue());
if namespace != ns!() {
let namespace = DOMString::from(&*namespace);
unsafe {
namespace.to_jsval(*cx, namespace_value.handle_mut());
}
namespace.safe_to_jsval(cx, namespace_value.handle_mut());
}
let args = vec![

View file

@ -14,7 +14,6 @@ use http::StatusCode;
use http::header::{self, HeaderName, HeaderValue};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::conversions::ToJSValConvertible;
use js::jsval::UndefinedValue;
use js::rust::HandleObject;
use mime::{self, Mime};
@ -23,6 +22,7 @@ use net_traits::{
CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, FetchResponseMsg,
FilteredMetadata, NetworkError, ResourceFetchTiming, ResourceTimingType,
};
use script_bindings::conversions::SafeToJSValConvertible;
use servo_url::ServoUrl;
use stylo_atoms::Atom;
@ -231,7 +231,6 @@ impl EventSourceContext {
}
// https://html.spec.whatwg.org/multipage/#dispatchMessage
#[allow(unsafe_code)]
fn dispatch_event(&mut self, can_gc: CanGc) {
let event_source = self.event_source.root();
// Step 1
@ -258,10 +257,8 @@ impl EventSourceContext {
let event = {
let _ac = enter_realm(&*event_source);
rooted!(in(*GlobalScope::get_cx()) let mut data = UndefinedValue());
unsafe {
self.data
.to_jsval(*GlobalScope::get_cx(), data.handle_mut())
};
self.data
.safe_to_jsval(GlobalScope::get_cx(), data.handle_mut());
MessageEvent::new(
&event_source.global(),
type_,

View file

@ -5,7 +5,6 @@
use std::ptr;
use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible;
use js::jsapi::{
ESClass, GetBuiltinClass, IsArrayBufferObject, JS_DeleteUCProperty,
JS_GetOwnUCPropertyDescriptor, JS_GetStringLength, JS_IsArrayBufferViewObject, JSObject,
@ -20,6 +19,7 @@ use net_traits::indexeddb_thread::{
IndexedDBThreadMsg, SyncOperation,
};
use profile_traits::ipc;
use script_bindings::conversions::SafeToJSValConvertible;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::IDBDatabaseBinding::IDBObjectStoreParameters;
@ -236,7 +236,7 @@ impl IDBObjectStore {
rooted!(in(*cx) let input_val = current_val.to_string());
unsafe {
let string_len = JS_GetStringLength(*input_val) as u64;
string_len.to_jsval(*cx, return_val);
string_len.safe_to_jsval(cx, return_val);
}
break;
}

View file

@ -9,6 +9,7 @@ use js::rust::HandleValue;
use net_traits::IpcSend;
use net_traits::indexeddb_thread::{IndexedDBThreadMsg, SyncOperation};
use profile_traits::ipc;
use script_bindings::conversions::SafeToJSValConvertible;
use stylo_atoms::Atom;
use crate::dom::bindings::codegen::Bindings::IDBOpenDBRequestBinding::IDBOpenDBRequestMethods;
@ -25,7 +26,6 @@ use crate::dom::idbdatabase::IDBDatabase;
use crate::dom::idbrequest::IDBRequest;
use crate::dom::idbtransaction::IDBTransaction;
use crate::dom::idbversionchangeevent::IDBVersionChangeEvent;
use crate::js::conversions::ToJSValConvertible;
use crate::realms::enter_realm;
use crate::script_runtime::CanGc;
@ -140,7 +140,6 @@ impl IDBOpenDBRequest {
reflect_dom_object(Box::new(IDBOpenDBRequest::new_inherited()), global, can_gc)
}
#[allow(unsafe_code)]
// https://www.w3.org/TR/IndexedDB-2/#run-an-upgrade-transaction
fn upgrade_db_version(&self, connection: &IDBDatabase, version: u64, can_gc: CanGc) {
let global = self.global();
@ -178,9 +177,7 @@ impl IDBOpenDBRequest {
// Step 8.1
let _ac = enter_realm(&*conn);
rooted!(in(*cx) let mut connection_val = UndefinedValue());
unsafe {
conn.to_jsval(*cx, connection_val.handle_mut());
}
conn.safe_to_jsval(cx, connection_val.handle_mut());
this.idbrequest.set_result(connection_val.handle());
// Step 8.2
@ -328,7 +325,6 @@ impl IDBOpenDBRequest {
.unwrap();
}
#[allow(unsafe_code)]
pub fn dispatch_success(&self, result: &IDBDatabase) {
let global = self.global();
let this = Trusted::new(self);
@ -344,9 +340,7 @@ impl IDBOpenDBRequest {
let _ac = enter_realm(&*result);
rooted!(in(*cx) let mut result_val = UndefinedValue());
unsafe {
result.to_jsval(*cx, result_val.handle_mut());
}
result.safe_to_jsval(cx, result_val.handle_mut());
this.set_result(result_val.handle());
let event = Event::new(

View file

@ -16,7 +16,7 @@ use std::ptr;
use std::rc::Rc;
use dom_struct::dom_struct;
use js::conversions::{ConversionResult, FromJSValConvertibleRc, ToJSValConvertible};
use js::conversions::{ConversionResult, FromJSValConvertibleRc};
use js::jsapi::{
AddRawValueRoot, CallArgs, GetFunctionNativeReserved, Heap, JS_ClearPendingException,
JS_GetFunctionObject, JS_NewFunction, JSAutoRealm, JSContext, JSObject,
@ -30,6 +30,7 @@ use js::rust::wrappers::{
ResolvePromise, SetAnyPromiseIsHandled, SetPromiseUserInputEventHandlingState,
};
use js::rust::{HandleObject, HandleValue, MutableHandleObject, Runtime};
use script_bindings::conversions::SafeToJSValConvertible;
use crate::dom::bindings::conversions::root_from_object;
use crate::dom::bindings::error::{Error, ErrorToJsval};
@ -156,13 +157,13 @@ impl Promise {
pub(crate) fn new_resolved(
global: &GlobalScope,
cx: SafeJSContext,
value: impl ToJSValConvertible,
value: impl SafeToJSValConvertible,
_can_gc: CanGc,
) -> Rc<Promise> {
let _ac = JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
rooted!(in(*cx) let mut rval = UndefinedValue());
value.safe_to_jsval(cx, rval.handle_mut());
unsafe {
rooted!(in(*cx) let mut rval = UndefinedValue());
value.to_jsval(*cx, rval.handle_mut());
rooted!(in(*cx) let p = CallOriginalPromiseResolve(*cx, rval.handle()));
assert!(!p.handle().is_null());
Promise::new_with_js_promise(p.handle(), cx)
@ -174,30 +175,27 @@ impl Promise {
pub(crate) fn new_rejected(
global: &GlobalScope,
cx: SafeJSContext,
value: impl ToJSValConvertible,
value: impl SafeToJSValConvertible,
_can_gc: CanGc,
) -> Rc<Promise> {
let _ac = JSAutoRealm::new(*cx, global.reflector().get_jsobject().get());
rooted!(in(*cx) let mut rval = UndefinedValue());
value.safe_to_jsval(cx, rval.handle_mut());
unsafe {
rooted!(in(*cx) let mut rval = UndefinedValue());
value.to_jsval(*cx, rval.handle_mut());
rooted!(in(*cx) let p = CallOriginalPromiseReject(*cx, rval.handle()));
assert!(!p.handle().is_null());
Promise::new_with_js_promise(p.handle(), cx)
}
}
#[allow(unsafe_code)]
pub(crate) fn resolve_native<T>(&self, val: &T, can_gc: CanGc)
where
T: ToJSValConvertible,
T: SafeToJSValConvertible,
{
let cx = GlobalScope::get_cx();
let _ac = enter_realm(self);
rooted!(in(*cx) let mut v = UndefinedValue());
unsafe {
val.to_jsval(*cx, v.handle_mut());
}
val.safe_to_jsval(cx, v.handle_mut());
self.resolve(cx, v.handle(), can_gc);
}
@ -211,17 +209,14 @@ impl Promise {
}
}
#[allow(unsafe_code)]
pub(crate) fn reject_native<T>(&self, val: &T, can_gc: CanGc)
where
T: ToJSValConvertible,
T: SafeToJSValConvertible,
{
let cx = GlobalScope::get_cx();
let _ac = enter_realm(self);
rooted!(in(*cx) let mut v = UndefinedValue());
unsafe {
val.to_jsval(*cx, v.handle_mut());
}
val.safe_to_jsval(cx, v.handle_mut());
self.reject(cx, v.handle(), can_gc);
}

View file

@ -12,7 +12,7 @@ use base::id::{MessagePortId, MessagePortIndex};
use constellation_traits::MessagePortImpl;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSharedMemory;
use js::conversions::ToJSValConvertible;
use script_bindings::conversions::SafeToJSValConvertible;
use js::jsapi::{Heap, JSObject};
use js::jsval::{JSVal, ObjectValue, UndefinedValue};
use js::rust::{
@ -1595,7 +1595,6 @@ impl ReadableStream {
}
/// <https://streams.spec.whatwg.org/#readable-stream-cancel>
#[allow(unsafe_code)]
pub(crate) fn cancel(
&self,
cx: SafeJSContext,
@ -1613,12 +1612,10 @@ impl ReadableStream {
// If stream.[[state]] is "errored", return a promise rejected with stream.[[storedError]].
if self.is_errored() {
let promise = Promise::new(global, can_gc);
unsafe {
rooted!(in(*cx) let mut rval = UndefinedValue());
self.stored_error.to_jsval(*cx, rval.handle_mut());
promise.reject_native(&rval.handle(), can_gc);
return promise;
}
rooted!(in(*cx) let mut rval = UndefinedValue());
self.stored_error.safe_to_jsval(cx, rval.handle_mut());
promise.reject_native(&rval.handle(), can_gc);
return promise;
}
// Perform ! ReadableStreamClose(stream).
self.close(can_gc);
@ -2322,7 +2319,6 @@ impl CrossRealmTransformReadable {
/// <https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformwritable>
/// Add a handler for ports messageerror event with the following steps:
#[allow(unsafe_code)]
pub(crate) fn handle_error(
&self,
cx: SafeJSContext,
@ -2334,7 +2330,7 @@ impl CrossRealmTransformReadable {
// Let error be a new "DataCloneError" DOMException.
let error = DOMException::new(global, DOMErrorName::DataCloneError, can_gc);
rooted!(in(*cx) let mut rooted_error = UndefinedValue());
unsafe { error.to_jsval(*cx, rooted_error.handle_mut()) };
error.safe_to_jsval(cx, rooted_error.handle_mut());
// Perform ! CrossRealmTransformSendError(port, error).
port.cross_realm_transform_send_error(rooted_error.handle(), can_gc);

View file

@ -13,6 +13,7 @@ use js::jsval::{JSVal, UndefinedValue};
use js::rust::wrappers::JS_GetPendingException;
use js::rust::{HandleObject, HandleValue as SafeHandleValue, HandleValue, MutableHandleValue};
use js::typedarray::Uint8;
use script_bindings::conversions::SafeToJSValConvertible;
use super::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
use super::bindings::root::Dom;
@ -30,7 +31,6 @@ use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::readablestream::ReadableStream;
use crate::dom::readablestreamdefaultreader::ReadRequest;
use crate::dom::underlyingsourcecontainer::{UnderlyingSourceContainer, UnderlyingSourceType};
use crate::js::conversions::ToJSValConvertible;
use crate::realms::{InRealm, enter_realm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
@ -147,18 +147,15 @@ impl EnqueuedValue {
}
}
#[allow(unsafe_code)]
fn to_jsval(&self, cx: SafeJSContext, rval: MutableHandleValue, can_gc: CanGc) {
match self {
EnqueuedValue::Native(chunk) => {
rooted!(in(*cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
create_buffer_source::<Uint8>(cx, chunk, array_buffer_ptr.handle_mut(), can_gc)
.expect("failed to create buffer source for native chunk.");
unsafe { array_buffer_ptr.to_jsval(*cx, rval) };
},
EnqueuedValue::Js(value_with_size) => unsafe {
value_with_size.value.to_jsval(*cx, rval);
array_buffer_ptr.safe_to_jsval(cx, rval);
},
EnqueuedValue::Js(value_with_size) => value_with_size.value.safe_to_jsval(cx, rval),
EnqueuedValue::CloseSentinel => {
unreachable!("The close sentinel is never made available as a js val.")
},

View file

@ -7,11 +7,11 @@ use std::ptr;
use constellation_traits::BlobImpl;
use dom_struct::dom_struct;
use js::conversions::ToJSValConvertible;
use js::jsapi::{JSAutoRealm, JSObject};
use js::jsval::UndefinedValue;
use js::rust::CustomAutoRooterGuard;
use js::typedarray::{ArrayBuffer, ArrayBufferView, CreateWith};
use script_bindings::conversions::SafeToJSValConvertible;
use script_bindings::weakref::WeakRef;
use servo_media::webrtc::{
DataChannelId, DataChannelInit, DataChannelMessage, DataChannelState, WebRtcError,
@ -195,27 +195,27 @@ impl RTCDataChannel {
#[allow(unsafe_code)]
pub(crate) fn on_message(&self, channel_message: DataChannelMessage, can_gc: CanGc) {
unsafe {
let global = self.global();
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue());
let global = self.global();
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, self.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue());
match channel_message {
DataChannelMessage::Text(text) => {
text.to_jsval(*cx, message.handle_mut());
match channel_message {
DataChannelMessage::Text(text) => {
text.safe_to_jsval(cx, message.handle_mut());
},
DataChannelMessage::Binary(data) => match &**self.binary_type.borrow() {
"blob" => {
let blob = Blob::new(
&global,
BlobImpl::new_from_bytes(data, "".to_owned()),
can_gc,
);
blob.safe_to_jsval(cx, message.handle_mut());
},
DataChannelMessage::Binary(data) => match &**self.binary_type.borrow() {
"blob" => {
let blob = Blob::new(
&global,
BlobImpl::new_from_bytes(data, "".to_owned()),
can_gc,
);
blob.to_jsval(*cx, message.handle_mut());
},
"arraybuffer" => {
rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
"arraybuffer" => {
rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
unsafe {
assert!(
ArrayBuffer::create(
*cx,
@ -223,24 +223,24 @@ impl RTCDataChannel {
array_buffer.handle_mut()
)
.is_ok()
);
)
};
(*array_buffer).to_jsval(*cx, message.handle_mut());
},
_ => unreachable!(),
(*array_buffer).safe_to_jsval(cx, message.handle_mut());
},
}
MessageEvent::dispatch_jsval(
self.upcast(),
&global,
message.handle(),
Some(&global.origin().immutable().ascii_serialization()),
None,
vec![],
can_gc,
);
_ => unreachable!(),
},
}
MessageEvent::dispatch_jsval(
self.upcast(),
&global,
message.handle(),
Some(&global.origin().immutable().ascii_serialization()),
None,
vec![],
can_gc,
);
}
pub(crate) fn on_state_change(&self, state: DataChannelState, can_gc: CanGc) {

View file

@ -22,13 +22,13 @@ use net_traits::{
CoreResourceMsg, FetchChannels, MessageData, WebSocketDomAction, WebSocketNetworkEvent,
};
use profile_traits::ipc as ProfiledIpc;
use script_bindings::conversions::SafeToJSValConvertible;
use servo_url::{ImmutableOrigin, ServoUrl};
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use crate::dom::bindings::codegen::Bindings::WebSocketBinding::{BinaryType, WebSocketMethods};
use crate::dom::bindings::codegen::UnionTypes::StringOrStringSequence;
use crate::dom::bindings::conversions::ToJSValConvertible;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
@ -590,24 +590,24 @@ impl TaskOnce for MessageReceivedTask {
// Step 2-5.
let global = ws.global();
// GlobalScope::get_cx() returns a valid `JSContext` pointer, so this is safe.
unsafe {
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, ws.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue());
match self.message {
MessageData::Text(text) => text.to_jsval(*cx, message.handle_mut()),
MessageData::Binary(data) => match ws.binary_type.get() {
BinaryType::Blob => {
let blob = Blob::new(
&global,
BlobImpl::new_from_bytes(data, "".to_owned()),
CanGc::note(),
);
blob.to_jsval(*cx, message.handle_mut());
},
BinaryType::Arraybuffer => {
rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
let cx = GlobalScope::get_cx();
let _ac = JSAutoRealm::new(*cx, ws.reflector().get_jsobject().get());
rooted!(in(*cx) let mut message = UndefinedValue());
match self.message {
MessageData::Text(text) => text.safe_to_jsval(cx, message.handle_mut()),
MessageData::Binary(data) => match ws.binary_type.get() {
BinaryType::Blob => {
let blob = Blob::new(
&global,
BlobImpl::new_from_bytes(data, "".to_owned()),
CanGc::note(),
);
blob.safe_to_jsval(cx, message.handle_mut());
},
BinaryType::Arraybuffer => {
rooted!(in(*cx) let mut array_buffer = ptr::null_mut::<JSObject>());
// GlobalScope::get_cx() returns a valid `JSContext` pointer, so this is safe.
unsafe {
assert!(
ArrayBuffer::create(
*cx,
@ -615,21 +615,21 @@ impl TaskOnce for MessageReceivedTask {
array_buffer.handle_mut()
)
.is_ok()
);
)
};
(*array_buffer).to_jsval(*cx, message.handle_mut());
},
(*array_buffer).safe_to_jsval(cx, message.handle_mut());
},
}
MessageEvent::dispatch_jsval(
ws.upcast(),
&global,
message.handle(),
Some(&ws.origin().ascii_serialization()),
None,
vec![],
CanGc::note(),
);
},
}
MessageEvent::dispatch_jsval(
ws.upcast(),
&global,
message.handle(),
Some(&ws.origin().ascii_serialization()),
None,
vec![],
CanGc::note(),
);
}
}

View file

@ -4,10 +4,10 @@
use dom_struct::dom_struct;
use embedder_traits::GamepadSupportedHapticEffects;
use js::conversions::ToJSValConvertible;
use js::jsapi::Heap;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::MutableHandleValue;
use script_bindings::conversions::SafeToJSValConvertible;
use webxr_api::{Handedness, InputFrame, InputId, InputSource, TargetRayMode};
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
@ -73,7 +73,6 @@ impl XRInputSource {
}
}
#[allow(unsafe_code)]
pub(crate) fn new(
window: &Window,
session: &XRSession,
@ -88,11 +87,12 @@ impl XRInputSource {
let _ac = enter_realm(window);
let cx = GlobalScope::get_cx();
unsafe {
rooted!(in(*cx) let mut profiles = UndefinedValue());
source.info.profiles.to_jsval(*cx, profiles.handle_mut());
source.profiles.set(profiles.get());
}
rooted!(in(*cx) let mut profiles = UndefinedValue());
source
.info
.profiles
.safe_to_jsval(cx, profiles.handle_mut());
source.profiles.set(profiles.get());
source
}

View file

@ -4,10 +4,10 @@
use dom_struct::dom_struct;
use euclid::RigidTransform3D;
use js::conversions::ToJSValConvertible;
use js::jsapi::Heap;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::MutableHandleValue;
use script_bindings::conversions::SafeToJSValConvertible;
use webxr_api::{Viewer, ViewerPose, Views};
use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
@ -38,7 +38,6 @@ impl XRViewerPose {
}
}
#[allow(unsafe_code)]
pub(crate) fn new(
window: &Window,
session: &XRSession,
@ -183,11 +182,9 @@ impl XRViewerPose {
);
let cx = GlobalScope::get_cx();
unsafe {
rooted!(in(*cx) let mut jsval = UndefinedValue());
views.to_jsval(*cx, jsval.handle_mut());
pose.views.set(jsval.get());
}
rooted!(in(*cx) let mut jsval = UndefinedValue());
views.safe_to_jsval(cx, jsval.handle_mut());
pose.views.set(jsval.get());
pose
}

View file

@ -40,7 +40,6 @@ use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as
use euclid::{Point2D, Scale, Size2D, Vector2D};
use fonts::FontContext;
use ipc_channel::ipc::{self, IpcSender};
use js::conversions::ToJSValConvertible;
use js::glue::DumpJSStack;
use js::jsapi::{
GCReason, Heap, JS_GC, JSAutoRealm, JSContext as RawJSContext, JSObject, JSPROP_ENUMERATE,
@ -70,6 +69,7 @@ use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_bindings::codegen::GenericBindings::NavigatorBinding::NavigatorMethods;
use script_bindings::codegen::GenericBindings::PerformanceBinding::PerformanceMethods;
use script_bindings::conversions::SafeToJSValConvertible;
use script_bindings::interfaces::WindowHelpers;
use script_bindings::root::Root;
use script_traits::ScriptThreadMessage;
@ -1796,12 +1796,9 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
}
// https://dom.spec.whatwg.org/#dom-window-event
#[allow(unsafe_code)]
fn Event(&self, cx: JSContext, rval: MutableHandleValue) {
if let Some(ref event) = *self.current_event.borrow() {
unsafe {
event.reflector().get_jsobject().to_jsval(*cx, rval);
}
event.reflector().get_jsobject().safe_to_jsval(cx, rval);
}
}

View file

@ -18,6 +18,7 @@ use js::rust::{
MutableHandleValue as SafeMutableHandleValue,
};
use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods;
use script_bindings::conversions::SafeToJSValConvertible;
use super::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
use crate::dom::bindings::cell::DomRefCell;
@ -41,7 +42,6 @@ use crate::dom::writablestreamdefaultcontroller::{
UnderlyingSinkType, WritableStreamDefaultController,
};
use crate::dom::writablestreamdefaultwriter::WritableStreamDefaultWriter;
use crate::js::conversions::ToJSValConvertible;
use crate::realms::{InRealm, enter_realm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
@ -1191,7 +1191,6 @@ impl CrossRealmTransformWritable {
/// <https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformwritable>
/// Add a handler for ports messageerror event with the following steps:
#[allow(unsafe_code)]
pub(crate) fn handle_error(
&self,
cx: SafeJSContext,
@ -1203,7 +1202,7 @@ impl CrossRealmTransformWritable {
// Let error be a new "DataCloneError" DOMException.
let error = DOMException::new(global, DOMErrorName::DataCloneError, can_gc);
rooted!(in(*cx) let mut rooted_error = UndefinedValue());
unsafe { error.to_jsval(*cx, rooted_error.handle_mut()) };
error.safe_to_jsval(cx, rooted_error.handle_mut());
// Perform ! CrossRealmTransformSendError(port, error).
port.cross_realm_transform_send_error(rooted_error.handle(), can_gc);