diff --git a/components/script/dom/bindings/constructor.rs b/components/script/dom/bindings/constructor.rs index 141fb8c1391..8abf4b78f5a 100644 --- a/components/script/dom/bindings/constructor.rs +++ b/components/script/dom/bindings/constructor.rs @@ -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(()) } diff --git a/components/script/dom/cryptokey.rs b/components/script/dom/cryptokey.rs index 5cdd5f3ea79..d98afff0e11 100644 --- a/components/script/dom/cryptokey.rs +++ b/components/script/dom/cryptokey.rs @@ -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 for CryptoKey { NonNull::new(self.algorithm_object.get()).unwrap() } - #[allow(unsafe_code)] /// fn Usages(&self, cx: JSContext) -> NonNull { - 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() } } diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index be672585529..4dbe24a01a3 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -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 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(()) } /// - #[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 for CustomElementRegistr } /// - #[allow(unsafe_code)] fn WhenDefined(&self, name: DOMString, comp: InRealm, can_gc: CanGc) -> Rc { let name = LocalName::from(&*name); @@ -592,16 +586,14 @@ impl CustomElementRegistryMethods 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::()); { // Step 8.1. If definition's disable shadow is true and element's shadow root is non-null, @@ -1128,7 +1118,6 @@ impl CustomElementReactionStack { } /// - #[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![ diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index d0c84084b72..2f754020564 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -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_, diff --git a/components/script/dom/idbobjectstore.rs b/components/script/dom/idbobjectstore.rs index d350ed12572..1d406035e4d 100644 --- a/components/script/dom/idbobjectstore.rs +++ b/components/script/dom/idbobjectstore.rs @@ -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; } diff --git a/components/script/dom/idbopendbrequest.rs b/components/script/dom/idbopendbrequest.rs index dfb899c06ce..e437cbf433b 100644 --- a/components/script/dom/idbopendbrequest.rs +++ b/components/script/dom/idbopendbrequest.rs @@ -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( diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index 57fb08aee65..b21df0a66db 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -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 { 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 { 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(&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(&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); } diff --git a/components/script/dom/readablestream.rs b/components/script/dom/readablestream.rs index 4f82dfd7884..1f7732a7397 100644 --- a/components/script/dom/readablestream.rs +++ b/components/script/dom/readablestream.rs @@ -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 { } /// - #[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 { /// /// Add a handler for port’s 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); diff --git a/components/script/dom/readablestreamdefaultcontroller.rs b/components/script/dom/readablestreamdefaultcontroller.rs index 80c800d1bbe..3be1fc48988 100644 --- a/components/script/dom/readablestreamdefaultcontroller.rs +++ b/components/script/dom/readablestreamdefaultcontroller.rs @@ -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::()); create_buffer_source::(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.") }, diff --git a/components/script/dom/rtcdatachannel.rs b/components/script/dom/rtcdatachannel.rs index 2f9d962dd87..818874bbd6d 100644 --- a/components/script/dom/rtcdatachannel.rs +++ b/components/script/dom/rtcdatachannel.rs @@ -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::()); + "arraybuffer" => { + rooted!(in(*cx) let mut array_buffer = ptr::null_mut::()); + 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) { diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index 9466b756fea..22064158f77 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -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::()); + 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::()); + // 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(), + ); } } diff --git a/components/script/dom/webxr/xrinputsource.rs b/components/script/dom/webxr/xrinputsource.rs index e454e785424..dcee3670da6 100644 --- a/components/script/dom/webxr/xrinputsource.rs +++ b/components/script/dom/webxr/xrinputsource.rs @@ -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 } diff --git a/components/script/dom/webxr/xrviewerpose.rs b/components/script/dom/webxr/xrviewerpose.rs index 880ed6fcdb4..f9e6d587128 100644 --- a/components/script/dom/webxr/xrviewerpose.rs +++ b/components/script/dom/webxr/xrviewerpose.rs @@ -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 } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index d2802841835..cdd7aa5df34 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -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 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); } } diff --git a/components/script/dom/writablestream.rs b/components/script/dom/writablestream.rs index b07ddac2a31..0776fa23fa2 100644 --- a/components/script/dom/writablestream.rs +++ b/components/script/dom/writablestream.rs @@ -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 { /// /// Add a handler for port’s 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); diff --git a/components/script_bindings/conversions.rs b/components/script_bindings/conversions.rs index adbf21d96e3..96fdc2040f3 100644 --- a/components/script_bindings/conversions.rs +++ b/components/script_bindings/conversions.rs @@ -31,10 +31,22 @@ use crate::inheritance::Castable; use crate::num::Finite; use crate::reflector::{DomObject, Reflector}; use crate::root::DomRoot; +use crate::script_runtime::JSContext as SafeJSContext; use crate::str::{ByteString, DOMString, USVString}; use crate::trace::RootedTraceableBox; use crate::utils::{DOMClass, DOMJSClass}; +/// A safe wrapper for `ToJSValConvertible`. +pub trait SafeToJSValConvertible { + fn safe_to_jsval(&self, cx: SafeJSContext, rval: MutableHandleValue); +} + +impl SafeToJSValConvertible for T { + fn safe_to_jsval(&self, cx: SafeJSContext, rval: MutableHandleValue) { + unsafe { self.to_jsval(*cx, rval) }; + } +} + /// A trait to check whether a given `JSObject` implements an IDL interface. pub trait IDLInterface { /// Returns whether the given DOM class derives that interface.