diff --git a/components/script/devtools.rs b/components/script/devtools.rs index ce4279b2574..65b41476044 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -12,6 +12,7 @@ use devtools_traits::{ NodeInfo, NodeStyle, RuleModification, TimelineMarker, TimelineMarkerType, }; use ipc_channel::ipc::IpcSender; +use js::conversions::jsstr_to_string; use js::jsval::UndefinedValue; use js::rust::ToString; use servo_config::pref; @@ -28,7 +29,7 @@ use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeConstants; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; -use crate::dom::bindings::conversions::{ConversionResult, FromJSValConvertible, jsstring_to_str}; +use crate::dom::bindings::conversions::{ConversionResult, FromJSValConvertible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; @@ -83,17 +84,17 @@ pub(crate) fn handle_evaluate_js( ) } else if rval.is_string() { let jsstr = std::ptr::NonNull::new(rval.to_string()).unwrap(); - EvaluateJSReply::StringValue(String::from(jsstring_to_str(*cx, jsstr))) + EvaluateJSReply::StringValue(jsstr_to_string(*cx, jsstr)) } else if rval.is_null() { EvaluateJSReply::NullValue } else { assert!(rval.is_object()); let jsstr = std::ptr::NonNull::new(ToString(*cx, rval.handle())).unwrap(); - let class_name = jsstring_to_str(*cx, jsstr); + let class_name = jsstr_to_string(*cx, jsstr); EvaluateJSReply::ActorValue { - class: class_name.to_string(), + class: class_name, uuid: Uuid::new_v4().to_string(), } } diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index 3356b0192b9..f6e6c5da622 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -10,6 +10,7 @@ use devtools_traits::{ ConsoleMessage, ConsoleMessageArgument, ConsoleMessageBuilder, LogLevel, ScriptToDevtoolsControlMsg, StackFrame, }; +use js::conversions::jsstr_to_string; use js::jsapi::{self, ESClass, PropertyDescriptor}; use js::jsval::{Int32Value, UndefinedValue}; use js::rust::wrappers::{ @@ -22,7 +23,6 @@ use js::rust::{ use script_bindings::conversions::get_dom_class; use crate::dom::bindings::codegen::Bindings::ConsoleBinding::consoleMethods; -use crate::dom::bindings::conversions::jsstring_to_str; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; @@ -127,7 +127,7 @@ unsafe fn handle_value_to_string(cx: *mut jsapi::JSContext, value: HandleValue) match std::ptr::NonNull::new(JS_ValueToSource(cx, value)) { Some(js_str) => { js_string.set(js_str.as_ptr()); - jsstring_to_str(cx, js_str) + DOMString::from_string(jsstr_to_string(cx, js_str)) }, None => "".into(), } @@ -140,8 +140,8 @@ fn console_argument_from_handle_value( ) -> ConsoleMessageArgument { if handle_value.is_string() { let js_string = ptr::NonNull::new(handle_value.to_string()).unwrap(); - let dom_string = unsafe { jsstring_to_str(*cx, js_string) }; - return ConsoleMessageArgument::String(dom_string.into()); + let dom_string = unsafe { jsstr_to_string(*cx, js_string) }; + return ConsoleMessageArgument::String(dom_string); } if handle_value.is_int32() { @@ -164,7 +164,8 @@ fn stringify_handle_value(message: HandleValue) -> DOMString { let cx = GlobalScope::get_cx(); unsafe { if message.is_string() { - return jsstring_to_str(*cx, std::ptr::NonNull::new(message.to_string()).unwrap()); + let jsstr = std::ptr::NonNull::new(message.to_string()).unwrap(); + return DOMString::from_string(jsstr_to_string(*cx, jsstr)); } unsafe fn stringify_object_from_handle_value( cx: *mut jsapi::JSContext, @@ -297,7 +298,7 @@ fn maybe_stringify_dom_object(cx: JSContext, value: HandleValue) -> Option".into()); }; let class_name = unsafe { - jsstring_to_str(*cx, class_name) + jsstr_to_string(*cx, class_name) .replace("[object ", "") .replace("]", "") }; @@ -493,7 +494,7 @@ fn get_js_stack(cx: *mut jsapi::JSContext) -> Vec { ); } let function_name = if let Some(nonnull_result) = ptr::NonNull::new(*result) { - unsafe { jsstring_to_str(cx, nonnull_result) }.into() + unsafe { jsstr_to_string(cx, nonnull_result) } } else { "".into() }; @@ -510,7 +511,7 @@ fn get_js_stack(cx: *mut jsapi::JSContext) -> Vec { ); } let filename = if let Some(nonnull_result) = ptr::NonNull::new(*result) { - unsafe { jsstring_to_str(cx, nonnull_result) }.into() + unsafe { jsstr_to_string(cx, nonnull_result) } } else { "".into() }; diff --git a/components/script/dom/dommatrixreadonly.rs b/components/script/dom/dommatrixreadonly.rs index c29bf6057e5..fdd36ababad 100644 --- a/components/script/dom/dommatrixreadonly.rs +++ b/components/script/dom/dommatrixreadonly.rs @@ -9,6 +9,7 @@ use cssparser::{Parser, ParserInput}; use dom_struct::dom_struct; use euclid::Angle; use euclid::default::{Transform2D, Transform3D}; +use js::conversions::jsstr_to_string; use js::jsapi::JSObject; use js::jsval; use js::rust::{CustomAutoRooterGuard, HandleObject, ToString}; @@ -24,7 +25,6 @@ use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::{ use crate::dom::bindings::codegen::Bindings::DOMMatrixReadOnlyBinding::DOMMatrixReadOnlyMethods; use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; use crate::dom::bindings::codegen::UnionTypes::StringOrUnrestrictedDoubleSequence; -use crate::dom::bindings::conversions::jsstring_to_str; use crate::dom::bindings::error; use crate::dom::bindings::error::Fallible; use crate::dom::bindings::inheritance::Castable; @@ -835,11 +835,9 @@ impl DOMMatrixReadOnlyMethods for DOMMatrixReadOnly { unsafe { rooted!(in(*cx) let mut rooted_value = value); - let serialization = ToString(*cx, rooted_value.handle()); - jsstring_to_str( - *cx, - ptr::NonNull::new(serialization).expect("Pointer cannot be null"), - ) + let serialization = std::ptr::NonNull::new(ToString(*cx, rooted_value.handle())) + .expect("Pointer cannot be null"); + jsstr_to_string(*cx, serialization) } }; diff --git a/components/script/indexed_db.rs b/components/script/indexed_db.rs index 88ac90e60c9..f4abd94a6c3 100644 --- a/components/script/indexed_db.rs +++ b/components/script/indexed_db.rs @@ -5,6 +5,7 @@ use std::iter::repeat; use std::ptr; +use js::conversions::jsstr_to_string; use js::gc::MutableHandle; use js::jsapi::{ ESClass, GetBuiltinClass, IsArrayBufferObject, JS_DeleteUCProperty, @@ -18,7 +19,6 @@ use script_bindings::conversions::{SafeToJSValConvertible, root_from_object}; use script_bindings::str::DOMString; use crate::dom::bindings::codegen::UnionTypes::StringOrStringSequence as StrOrStringSequence; -use crate::dom::bindings::conversions::jsstring_to_str; use crate::dom::bindings::error::Error; use crate::dom::bindings::import::module::SafeJSContext; use crate::dom::bindings::structuredclone; @@ -104,7 +104,7 @@ pub fn convert_value_to_key( if input.is_string() { let string_ptr = std::ptr::NonNull::new(input.to_string()).unwrap(); - let key = unsafe { jsstring_to_str(*cx, string_ptr).str().to_string() }; + let key = unsafe { jsstr_to_string(*cx, string_ptr) }; return Ok(IndexedDBKeyType::String(key)); } diff --git a/components/script/script_module.rs b/components/script/script_module.rs index 8dd3be4897b..7285d11205e 100644 --- a/components/script/script_module.rs +++ b/components/script/script_module.rs @@ -17,6 +17,7 @@ use headers::{HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader}; use html5ever::local_name; use hyper_serde::Serde; use indexmap::{IndexMap, IndexSet}; +use js::conversions::jsstr_to_string; use js::jsapi::{ CompileModule1, ExceptionStackBehavior, FinishDynamicModuleImport, GetModuleRequestSpecifier, GetModuleResolveHook, GetRequestedModuleSpecifier, GetRequestedModulesCount, @@ -50,7 +51,6 @@ use uuid::Uuid; use crate::document_loader::LoadType; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods; -use crate::dom::bindings::conversions::jsstring_to_str; use crate::dom::bindings::error::{ Error, ErrorToJsval, report_pending_exception, throw_dom_exception, }; @@ -630,11 +630,10 @@ impl ModuleTree { let length = GetRequestedModulesCount(*cx, module_object); for index in 0..length { - let specifier = jsstring_to_str( - *cx, - ptr::NonNull::new(GetRequestedModuleSpecifier(*cx, module_object, index)) - .unwrap(), - ); + let jsstr = + std::ptr::NonNull::new(GetRequestedModuleSpecifier(*cx, module_object, index)) + .unwrap(); + let specifier = DOMString::from_string(jsstr_to_string(*cx, jsstr)); rooted!(in(*cx) let mut private = UndefinedValue()); JS_GetModulePrivate(module_object.get(), private.handle_mut()); @@ -1519,10 +1518,8 @@ fn fetch_an_import_module_script_graph( // Step 1. let cx = GlobalScope::get_cx(); let specifier = unsafe { - jsstring_to_str( - *cx, - ptr::NonNull::new(GetModuleRequestSpecifier(*cx, module_request)).unwrap(), - ) + let jsstr = std::ptr::NonNull::new(GetModuleRequestSpecifier(*cx, module_request)).unwrap(); + DOMString::from_string(jsstr_to_string(*cx, jsstr)) }; let mut options = ScriptFetchOptions::default_classic_script(global); let module_data = unsafe { module_script_from_reference_private(&reference_private) }; @@ -1594,10 +1591,8 @@ unsafe extern "C" fn HostResolveImportedModule( // Step 5. let module_data = module_script_from_reference_private(&reference_private); - let specifier = jsstring_to_str( - cx, - ptr::NonNull::new(GetModuleRequestSpecifier(cx, specifier)).unwrap(), - ); + let jsstr = std::ptr::NonNull::new(GetModuleRequestSpecifier(cx, specifier)).unwrap(); + let specifier = DOMString::from_string(jsstr_to_string(cx, jsstr)); let url = ModuleTree::resolve_module_specifier(&global_scope, module_data, specifier, CanGc::note()); diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 457f02dbd6f..44fb45dea70 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -13,7 +13,6 @@ use std::ffi::{CStr, CString}; use std::io::{Write, stdout}; use std::ops::Deref; use std::os::raw::c_void; -use std::ptr::NonNull; use std::rc::Rc; use std::sync::Mutex; use std::time::{Duration, Instant}; @@ -490,9 +489,8 @@ unsafe extern "C" fn content_security_policy_allows( allowed = match runtime_code { RuntimeCode::JS => { - let source = NonNull::new(*sample) - .map(|sample| jsstr_to_string(*cx, sample)) - .unwrap_or("".to_string()); + let source = std::ptr::NonNull::new(*sample) + .map_or_else(String::new, |jsstr| jsstr_to_string(*cx, jsstr)); global .get_csp_list() .is_js_evaluation_allowed(global, &source) diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index c86d173052f..44c20ae81e4 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -14,6 +14,7 @@ use embedder_traits::{ use euclid::default::{Point2D, Rect, Size2D}; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcSender}; +use js::conversions::jsstr_to_string; use js::jsapi::{ self, GetPropertyKeys, HandleValueArray, JS_GetOwnPropertyDescriptorById, JS_GetPropertyById, JS_IsExceptionPending, JSAutoRealm, JSContext, JSType, PropertyDescriptor, @@ -52,7 +53,7 @@ use crate::dom::bindings::codegen::Bindings::XPathResultBinding::{ }; use crate::dom::bindings::conversions::{ ConversionBehavior, ConversionResult, FromJSValConvertible, StringificationBehavior, - get_property, get_property_jsval, jsid_to_string, jsstring_to_str, root_from_object, + get_property, get_property_jsval, jsid_to_string, root_from_object, }; use crate::dom::bindings::error::{Error, report_pending_exception, throw_dom_exception}; use crate::dom::bindings::inheritance::Castable; @@ -269,7 +270,7 @@ unsafe fn is_arguments_object(cx: *mut JSContext, value: HandleValue) -> bool { let Some(class_name) = NonNull::new(class_name.get()) else { return false; }; - jsstring_to_str(cx, class_name) == "[object Arguments]" + jsstr_to_string(cx, class_name) == "[object Arguments]" } #[derive(Clone, Eq, Hash, PartialEq)] @@ -327,7 +328,7 @@ unsafe fn jsval_to_webdriver_inner( }, )) } else if val.get().is_string() { - //FIXME: use jsstring_to_str when jsval grows to_jsstring + //FIXME: use jsstr_to_string when jsval grows to_jsstring let string: DOMString = match FromJSValConvertible::from_jsval(cx, val, StringificationBehavior::Default) .unwrap() diff --git a/components/script_bindings/conversions.rs b/components/script_bindings/conversions.rs index 3bf9f077f7e..a529759b351 100644 --- a/components/script_bindings/conversions.rs +++ b/components/script_bindings/conversions.rs @@ -5,7 +5,7 @@ use std::{ptr, slice}; use js::conversions::{ - ConversionResult, FromJSValConvertible, ToJSValConvertible, latin1_to_string, + ConversionResult, FromJSValConvertible, ToJSValConvertible, jsstr_to_string, }; use js::error::throw_type_error; use js::glue::{ @@ -14,7 +14,7 @@ use js::glue::{ }; use js::jsapi::{ Heap, IsWindowProxy, JS_DeprecatedStringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, - JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyN, JSContext, JSObject, JSString, + JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyN, JSContext, JSObject, }; use js::jsval::{ObjectValue, StringValue, UndefinedValue}; use js::rust::wrappers::IsArrayObject; @@ -115,7 +115,9 @@ impl FromJSValConvertible for DOMString { Ok(ConversionResult::Success(DOMString::new())) } else { match ptr::NonNull::new(ToString(cx, value)) { - Some(jsstr) => Ok(ConversionResult::Success(jsstring_to_str(cx, jsstr))), + Some(jsstr) => Ok(ConversionResult::Success(DOMString::from_string( + jsstr_to_string(cx, jsstr), + ))), None => { debug!("ToString failed"); Err(()) @@ -125,34 +127,6 @@ impl FromJSValConvertible for DOMString { } } -/// Convert the given `JSString` to a `DOMString`. Fails if the string does not -/// contain valid UTF-16. -/// -/// # Safety -/// cx and s must point to valid values. -pub unsafe fn jsstring_to_str(cx: *mut JSContext, s: ptr::NonNull) -> DOMString { - let latin1 = JS_DeprecatedStringHasLatin1Chars(s.as_ptr()); - DOMString::from_string(if latin1 { - latin1_to_string(cx, s) - } else { - let mut length = 0; - let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), s.as_ptr(), &mut length); - assert!(!chars.is_null()); - let potentially_ill_formed_utf16 = slice::from_raw_parts(chars, length); - let mut s = String::with_capacity(length); - for item in char::decode_utf16(potentially_ill_formed_utf16.iter().cloned()) { - match item { - Ok(c) => s.push(c), - Err(_) => { - error!("Found an unpaired surrogate in a DOM string."); - s.push('\u{FFFD}'); - }, - } - } - s - }) -} - // http://heycam.github.io/webidl/#es-USVString impl FromJSValConvertible for USVString { type Config = (); @@ -168,8 +142,8 @@ impl FromJSValConvertible for USVString { let latin1 = JS_DeprecatedStringHasLatin1Chars(jsstr.as_ptr()); if latin1 { // FIXME(ajeffrey): Convert directly from DOMString to USVString - return Ok(ConversionResult::Success(USVString(String::from( - jsstring_to_str(cx, jsstr), + return Ok(ConversionResult::Success(USVString(jsstr_to_string( + cx, jsstr, )))); } let mut length = 0; @@ -445,7 +419,7 @@ pub unsafe fn jsid_to_string(cx: *mut JSContext, id: HandleId) -> Option Option( ) -> Result<(Option<&'a T>, DOMString), ()> { match ptr::NonNull::new(ToString(cx, v)) { Some(jsstr) => { - let search = jsstring_to_str(cx, jsstr); + let search = DOMString::from_string(jsstr_to_string(cx, jsstr)); Ok(( pairs .iter()