diff options
author | AbhishekSharma102 <20724848+AbhishekSharma102@users.noreply.github.com> | 2020-07-13 06:04:00 +0000 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2020-07-21 16:20:51 -0400 |
commit | 1119dd119ed335b6d6e448290b56e0eeab6de25f (patch) | |
tree | c1d2ae2b369a20923cfe8e24496193896c4ad473 | |
parent | bfb7bea704340e19583b04fb02b444fadd35e9e1 (diff) | |
download | servo-1119dd119ed335b6d6e448290b56e0eeab6de25f.tar.gz servo-1119dd119ed335b6d6e448290b56e0eeab6de25f.zip |
Added off thread compilation
Co-authored-by: Gregory Terzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: Abhishek Sharma <20724848+AbhishekSharma102@users.noreply.github.com>
-rw-r--r-- | components/config/prefs.rs | 3 | ||||
-rw-r--r-- | components/script/devtools.rs | 5 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 27 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 99 | ||||
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 261 | ||||
-rw-r--r-- | components/script/dom/userscripts.rs | 7 | ||||
-rw-r--r-- | resources/prefs.json | 1 | ||||
-rw-r--r-- | tests/wpt/metadata/custom-elements/customized-built-in-constructor-exceptions.html.ini | 2 |
8 files changed, 315 insertions, 90 deletions
diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 5ac6b19d940..db889d419ee 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -186,6 +186,9 @@ mod gen { allowed_in_nonsecure_contexts: bool, } }, + script: { + asynch: bool, + }, serviceworker: { enabled: bool, timeout_seconds: i64, diff --git a/components/script/devtools.rs b/components/script/devtools.rs index cb5dfa27b7f..04c35755b89 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -14,6 +14,7 @@ use crate::dom::bindings::str::DOMString; use crate::dom::document::AnimationFrameCallback; use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; +use crate::dom::htmlscriptelement::SourceCode; use crate::dom::node::{window_from_node, Node, ShadowIncluding}; use crate::realms::enter_realm; use crate::script_module::ScriptFetchOptions; @@ -25,6 +26,7 @@ use js::jsval::UndefinedValue; use js::rust::wrappers::ObjectClassName; use msg::constellation_msg::PipelineId; use std::ffi::CStr; +use std::rc::Rc; use std::str; use uuid::Uuid; @@ -35,8 +37,9 @@ pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<E let cx = global.get_cx(); let _ac = enter_realm(global); rooted!(in(*cx) let mut rval = UndefinedValue()); + let source_code = SourceCode::Text(Rc::new(DOMString::from_string(eval))); global.evaluate_script_on_global_with_result( - &eval, + &source_code, "<eval>", rval.handle_mut(), 1, diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 92d6ebcb7bf..a752b129a12 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -77,8 +77,10 @@ use hyper::Method; use hyper::StatusCode; use indexmap::IndexMap; use ipc_channel::ipc::{IpcReceiver, IpcSender}; -use js::glue::{CallObjectTracer, CallStringTracer, CallValueTracer}; -use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSString, JSTracer, JobQueue, TraceKind}; +use js::glue::{CallObjectTracer, CallScriptTracer, CallStringTracer, CallValueTracer}; +use js::jsapi::{ + GCTraceKindToAscii, Heap, JSObject, JSScript, JSString, JSTracer, JobQueue, TraceKind, +}; use js::jsval::JSVal; use js::rust::{GCMethods, Handle, Runtime}; use js::typedarray::TypedArray; @@ -219,6 +221,18 @@ unsafe_no_jsmanaged_fields!(Cow<'static, str>); unsafe_no_jsmanaged_fields!(CspList); +/// Trace a `JSScript`. +pub fn trace_script(tracer: *mut JSTracer, description: &str, script: &Heap<*mut JSScript>) { + unsafe { + trace!("tracing {}", description); + CallScriptTracer( + tracer, + script.ptr.get() as *mut _, + GCTraceKindToAscii(TraceKind::Script), + ); + } +} + /// Trace a `JSVal`. pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) { unsafe { @@ -328,6 +342,15 @@ unsafe impl<T: JSTraceable> JSTraceable for RefCell<T> { } } +unsafe impl JSTraceable for Heap<*mut JSScript> { + unsafe fn trace(&self, trc: *mut JSTracer) { + if self.get().is_null() { + return; + } + trace_script(trc, "heap script", self); + } +} + unsafe impl JSTraceable for Heap<*mut JSObject> { unsafe fn trace(&self, trc: *mut JSTracer) { if self.get().is_null() { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index a6427224882..9917d602ab3 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -38,7 +38,7 @@ use crate::dom::file::File; use crate::dom::gpudevice::GPUDevice; use crate::dom::gpuoutofmemoryerror::GPUOutOfMemoryError; use crate::dom::gpuvalidationerror::GPUValidationError; -use crate::dom::htmlscriptelement::ScriptId; +use crate::dom::htmlscriptelement::{ScriptId, SourceCode}; use crate::dom::identityhub::Identities; use crate::dom::imagebitmap::ImageBitmap; use crate::dom::messageevent::MessageEvent; @@ -91,9 +91,9 @@ use js::jsval::PrivateValue; use js::jsval::{JSVal, UndefinedValue}; use js::panic::maybe_resume_unwind; use js::rust::transform_str_to_source_text; -use js::rust::wrappers::{JS_ExecuteScript, JS_GetScriptPrivate}; +use js::rust::wrappers::{JS_ExecuteScript, JS_ExecuteScript1, JS_GetScriptPrivate}; use js::rust::{get_object_class, CompileOptionsWrapper, ParentRuntime, Runtime}; -use js::rust::{HandleValue, MutableHandleValue}; +use js::rust::{HandleScript, HandleValue, MutableHandleValue}; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use msg::constellation_msg::{ BlobId, BroadcastChannelRouterId, MessagePortId, MessagePortRouterId, PipelineId, @@ -2552,8 +2552,9 @@ impl GlobalScope { fetch_options: ScriptFetchOptions, script_base_url: ServoUrl, ) -> bool { + let source_code = SourceCode::Text(Rc::new(DOMString::from_string((*code).to_string()))); self.evaluate_script_on_global_with_result( - code, + &source_code, "", rval, 1, @@ -2566,7 +2567,7 @@ impl GlobalScope { #[allow(unsafe_code)] pub fn evaluate_script_on_global_with_result( &self, - code: &str, + code: &SourceCode, filename: &str, rval: MutableHandleValue, line_number: u32, @@ -2595,48 +2596,58 @@ impl GlobalScope { let _aes = AutoEntryScript::new(self); unsafe { - let options = CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number); - - debug!("compiling Dom string"); - rooted!(in(*cx) let compiled_script = - Compile1( - *cx, - options.ptr, - &mut transform_str_to_source_text(code), - ) - ); + let result = match code { + SourceCode::Text(text_code) => { + let options = + CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number); + + debug!("compiling Dom string"); + rooted!(in(*cx) let compiled_script = + Compile1( + *cx, + options.ptr, + &mut transform_str_to_source_text(text_code), + ) + ); - if compiled_script.is_null() { - debug!("error compiling Dom string"); - report_pending_exception(*cx, true, InRealm::Entered(&ar)); - return false; - } + if compiled_script.is_null() { + debug!("error compiling Dom string"); + report_pending_exception(*cx, true, InRealm::Entered(&ar)); + return false; + } - rooted!(in(*cx) let mut script_private = UndefinedValue()); - JS_GetScriptPrivate(*compiled_script, script_private.handle_mut()); - - // When `ScriptPrivate` for the compiled script is undefined, - // we need to set it so that it can be used in dynamic import context. - if script_private.is_undefined() { - debug!("Set script private for {}", script_base_url); - - let module_script_data = Rc::new(ModuleScript::new( - script_base_url, - fetch_options, - // We can't initialize an module owner here because - // the executing context of script might be different - // from the dynamic import script's executing context. - None, - )); - - SetScriptPrivate( - *compiled_script, - &PrivateValue(Rc::into_raw(module_script_data) as *const _), - ); - } + rooted!(in(*cx) let mut script_private = UndefinedValue()); + JS_GetScriptPrivate(*compiled_script, script_private.handle_mut()); + + // When `ScriptPrivate` for the compiled script is undefined, + // we need to set it so that it can be used in dynamic import context. + if script_private.is_undefined() { + debug!("Set script private for {}", script_base_url); + + let module_script_data = Rc::new(ModuleScript::new( + script_base_url, + fetch_options, + // We can't initialize an module owner here because + // the executing context of script might be different + // from the dynamic import script's executing context. + None, + )); + + SetScriptPrivate( + *compiled_script, + &PrivateValue(Rc::into_raw(module_script_data) as *const _), + ); + } - debug!("evaluating Dom string"); - let result = JS_ExecuteScript(*cx, compiled_script.handle(), rval); + debug!("evaluating Dom string"); + JS_ExecuteScript(*cx, compiled_script.handle(), rval) + }, + SourceCode::Compiled(compiled_script) => { + let script = compiled_script.source_code.get(); + let script_handle = HandleScript::new(&script); + JS_ExecuteScript1(*cx, script_handle) + }, + }; if !result { debug!("error evaluating Dom string"); diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 2ad7444f7f4..baa22d4dfe6 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -13,6 +13,7 @@ use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::settings_stack::AutoEntryScript; use crate::dom::bindings::str::{DOMString, USVString}; +use crate::dom::bindings::trace::RootedTraceableBox; use crate::dom::document::Document; use crate::dom::element::{ cors_setting_for_element, reflect_cross_origin_attribute, set_cross_origin_attribute, @@ -27,15 +28,25 @@ use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::virtualmethods::VirtualMethods; use crate::fetch::create_a_potential_cors_request; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; +use crate::realms::enter_realm; use crate::script_module::fetch_inline_module_script; use crate::script_module::{fetch_external_module_script, ModuleOwner, ScriptFetchOptions}; +use crate::task::TaskCanceller; +use crate::task_source::dom_manipulation::DOMManipulationTaskSource; +use crate::task_source::TaskSource; +use crate::task_source::TaskSourceName; use content_security_policy as csp; +use core::ffi::c_void; use dom_struct::dom_struct; use encoding_rs::Encoding; use html5ever::{LocalName, Prefix}; use ipc_channel::ipc; use ipc_channel::router::ROUTER; +use js::jsapi::{ + CanCompileOffThread, CompileOffThread, FinishOffThreadScript, Heap, JSScript, OffThreadToken, +}; use js::jsval::UndefinedValue; +use js::rust::{transform_u16_to_source_text, CompileOptionsWrapper}; use msg::constellation_msg::PipelineId; use net_traits::request::{ CorsSettings, CredentialsMode, Destination, ParserMetadata, RequestBuilder, @@ -43,11 +54,13 @@ use net_traits::request::{ use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; use net_traits::{ResourceFetchTiming, ResourceTimingType}; use servo_atoms::Atom; +use servo_config::pref; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; use std::cell::Cell; use std::fs::{create_dir_all, read_to_string, File}; use std::io::{Read, Seek, Write}; +use std::mem::replace; use std::path::PathBuf; use std::process::Command; use std::rc::Rc; @@ -55,6 +68,82 @@ use std::sync::{Arc, Mutex}; use style::str::{StaticStringVec, HTML_SPACE_CHARACTERS}; use uuid::Uuid; +pub struct OffThreadCompilationContext { + script_element: Trusted<HTMLScriptElement>, + script_kind: ExternalScriptKind, + final_url: ServoUrl, + url: ServoUrl, + task_source: DOMManipulationTaskSource, + canceller: TaskCanceller, + script_text: String, + utf16_chars: Vec<u16>, + fetch_options: ScriptFetchOptions, +} + +/// A wrapper to mark OffThreadToken as Send, +/// which should be safe according to +/// mozjs/js/public/OffThreadScriptCompilation.h +struct OffThreadCompilationToken(*mut OffThreadToken); + +#[allow(unsafe_code)] +unsafe impl Send for OffThreadCompilationToken {} + +#[allow(unsafe_code)] +unsafe extern "C" fn off_thread_compilation_callback( + token: *mut OffThreadToken, + callback_data: *mut c_void, +) { + let mut context = Box::from_raw(callback_data as *mut OffThreadCompilationContext); + let token = OffThreadCompilationToken(token); + + let url = context.url.clone(); + let final_url = context.final_url.clone(); + let script_element = context.script_element.clone(); + let script_kind = context.script_kind.clone(); + let script = replace(&mut context.script_text, String::new()); + let fetch_options = context.fetch_options.clone(); + + // Continue with <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> + let _ = context.task_source.queue_with_canceller( + task!(off_thread_compile_continue: move || { + let elem = script_element.root(); + let global = elem.global(); + let cx = global.get_cx(); + let _ar = enter_realm(&*global); + + rooted!(in(*cx) + let compiled_script = FinishOffThreadScript(*cx, token.0) + ); + + let load = if compiled_script.get().is_null() { + Err(NetworkError::Internal( + "Off-thread compilation failed.".into(), + )) + } else { + let script_text = DOMString::from(script); + let heap = Heap::default(); + let source_code = RootedTraceableBox::new(heap); + source_code.set(compiled_script.get()); + let code = SourceCode::Compiled(CompiledSourceCode { + source_code: source_code, + original_text: Rc::new(script_text), + }); + + Ok(ScriptOrigin { + code, + url: final_url, + external: true, + fetch_options: fetch_options, + type_: ScriptType::Classic, + }) + }; + + finish_fetching_a_classic_script(&*elem, script_kind, url, load); + }), + &context.canceller, + ); +} + /// An unique id for script element. #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)] pub struct ScriptId(Uuid); @@ -151,9 +240,23 @@ pub enum ScriptType { } #[derive(JSTraceable, MallocSizeOf)] +pub struct CompiledSourceCode { + #[ignore_malloc_size_of = "SM handles JS values"] + pub source_code: RootedTraceableBox<Heap<*mut JSScript>>, + #[ignore_malloc_size_of = "Rc is hard"] + pub original_text: Rc<DOMString>, +} + +#[derive(JSTraceable)] +pub enum SourceCode { + Text(Rc<DOMString>), + Compiled(CompiledSourceCode), +} + +#[derive(JSTraceable, MallocSizeOf)] pub struct ScriptOrigin { #[ignore_malloc_size_of = "Rc is hard"] - text: Rc<DOMString>, + code: SourceCode, url: ServoUrl, external: bool, fetch_options: ScriptFetchOptions, @@ -168,7 +271,7 @@ impl ScriptOrigin { type_: ScriptType, ) -> ScriptOrigin { ScriptOrigin { - text: text, + code: SourceCode::Text(text), url: url, external: false, fetch_options, @@ -183,7 +286,7 @@ impl ScriptOrigin { type_: ScriptType, ) -> ScriptOrigin { ScriptOrigin { - text: text, + code: SourceCode::Text(text), url: url, external: true, fetch_options, @@ -192,10 +295,37 @@ impl ScriptOrigin { } pub fn text(&self) -> Rc<DOMString> { - Rc::clone(&self.text) + match &self.code { + SourceCode::Text(text) => Rc::clone(&text), + SourceCode::Compiled(compiled_script) => Rc::clone(&compiled_script.original_text), + } } } +/// Final steps of <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> +fn finish_fetching_a_classic_script( + elem: &HTMLScriptElement, + script_kind: ExternalScriptKind, + url: ServoUrl, + load: ScriptResult, +) { + // Step 11, Asynchronously complete this algorithm with script, + // which refers to step 26.6 "When the chosen algorithm asynchronously completes", + // of https://html.spec.whatwg.org/multipage/#prepare-a-script + let document = document_from_node(&*elem); + + match script_kind { + ExternalScriptKind::Asap => document.asap_script_loaded(&elem, load), + ExternalScriptKind::AsapInOrder => document.asap_in_order_script_loaded(&elem, load), + ExternalScriptKind::Deferred => document.deferred_script_loaded(&elem, load), + ExternalScriptKind::ParsingBlocking => { + document.pending_parsing_blocking_script_loaded(&elem, load) + }, + } + + document.finish_load(LoadType::Script(url)); +} + pub type ScriptResult = Result<ScriptOrigin, NetworkError>; /// The context required for asynchronously loading an external script source. @@ -261,43 +391,79 @@ impl FetchResponseListener for ClassicContext { /// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> /// step 4-9 + #[allow(unsafe_code)] fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) { - // Step 5. - let load = response.and(self.status.clone()).map(|_| { - let metadata = self.metadata.take().unwrap(); - - // Step 6. - let encoding = metadata - .charset - .and_then(|encoding| Encoding::for_label(encoding.as_bytes())) - .unwrap_or(self.character_encoding); + let (source_text, final_url) = match (response.as_ref(), self.status.as_ref()) { + (Err(err), _) | (_, Err(err)) => { + // Step 6, response is an error. + finish_fetching_a_classic_script( + &*self.elem.root(), + self.kind.clone(), + self.url.clone(), + Err(err.clone()), + ); + return; + }, + (Ok(_), Ok(_)) => { + let metadata = self.metadata.take().unwrap(); + + // Step 7. + let encoding = metadata + .charset + .and_then(|encoding| Encoding::for_label(encoding.as_bytes())) + .unwrap_or(self.character_encoding); + + // Step 8. + let (source_text, _, _) = encoding.decode(&self.data); + (source_text, metadata.final_url) + }, + }; - // Step 7. - let (source_text, _, _) = encoding.decode(&self.data); - ScriptOrigin::external( + let elem = self.elem.root(); + let global = elem.global(); + let cx = global.get_cx(); + let _ar = enter_realm(&*global); + + let options = + unsafe { CompileOptionsWrapper::new(*cx, final_url.as_str().as_ptr() as *const i8, 1) }; + + let can_compile_off_thread = pref!(dom.script.asynch) && + unsafe { CanCompileOffThread(*cx, options.ptr as *const _, source_text.len()) }; + + if can_compile_off_thread { + let source_string = source_text.to_string(); + let source_text: Vec<u16> = source_text.encode_utf16().collect(); + + let context = Box::new(OffThreadCompilationContext { + script_element: self.elem.clone(), + script_kind: self.kind.clone(), + final_url, + url: self.url.clone(), + task_source: global.dom_manipulation_task_source(), + canceller: global.task_canceller(TaskSourceName::DOMManipulation), + script_text: source_string, + utf16_chars: source_text, + fetch_options: self.fetch_options.clone(), + }); + + unsafe { + assert!(CompileOffThread( + *cx, + options.ptr as *const _, + &mut transform_u16_to_source_text(&context.utf16_chars) as *mut _, + Some(off_thread_compilation_callback), + Box::into_raw(context) as *mut c_void, + )); + } + } else { + let load = ScriptOrigin::external( Rc::new(DOMString::from(source_text)), - metadata.final_url, + final_url.clone(), self.fetch_options.clone(), ScriptType::Classic, - ) - }); - - // Step 9. - // https://html.spec.whatwg.org/multipage/#prepare-a-script - // Step 18.6 (When the chosen algorithm asynchronously completes). - let elem = self.elem.root(); - let document = document_from_node(&*elem); - - match self.kind { - ExternalScriptKind::Asap => document.asap_script_loaded(&elem, load), - ExternalScriptKind::AsapInOrder => document.asap_in_order_script_loaded(&elem, load), - ExternalScriptKind::Deferred => document.deferred_script_loaded(&elem, load), - ExternalScriptKind::ParsingBlocking => { - document.pending_parsing_blocking_script_loaded(&elem, load) - }, + ); + finish_fetching_a_classic_script(&*elem, self.kind.clone(), self.url.clone(), Ok(load)); } - - document.finish_load(LoadType::Script(self.url.clone())); } fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming { @@ -702,7 +868,16 @@ impl HTMLScriptElement { // unminified content. let (input, output) = (tempfile::NamedTempFile::new(), tempfile::tempfile()); if let (Ok(mut input), Ok(mut output)) = (input, output) { - input.write_all(script.text.as_bytes()).unwrap(); + match &script.code { + SourceCode::Text(text) => { + input.write_all(text.as_bytes()).unwrap(); + }, + SourceCode::Compiled(compiled_source_code) => { + input + .write_all(compiled_source_code.original_text.as_bytes()) + .unwrap(); + }, + } match Command::new("js-beautify") .arg(input.path()) .stdout(output.try_clone().unwrap()) @@ -712,7 +887,7 @@ impl HTMLScriptElement { let mut script_content = String::new(); output.seek(std::io::SeekFrom::Start(0)).unwrap(); output.read_to_string(&mut script_content).unwrap(); - script.text = Rc::new(DOMString::from(script_content)); + script.code = SourceCode::Text(Rc::new(DOMString::from(script_content))); }, _ => { warn!("Failed to execute js-beautify. Will store unmodified script"); @@ -763,7 +938,13 @@ impl HTMLScriptElement { debug!("script will be stored in {:?}", path); match File::create(&path) { - Ok(mut file) => file.write_all(script.text.as_bytes()).unwrap(), + Ok(mut file) => match &script.code { + SourceCode::Text(text) => file.write_all(text.as_bytes()).unwrap(), + SourceCode::Compiled(compiled_source_code) => { + file.write_all(compiled_source_code.original_text.as_bytes()) + .unwrap(); + }, + }, Err(why) => warn!("Could not store script {:?}", why), } } @@ -790,7 +971,7 @@ impl HTMLScriptElement { match read_to_string(path.clone()) { Ok(local_script) => { debug!("Found script stored at: {:?}", path); - script.text = Rc::new(DOMString::from(local_script)); + script.code = SourceCode::Text(Rc::new(DOMString::from(local_script))); }, Err(why) => warn!("Could not restore script from file {:?}", why), } @@ -880,7 +1061,7 @@ impl HTMLScriptElement { rooted!(in(*window.get_cx()) let mut rval = UndefinedValue()); let global = window.upcast::<GlobalScope>(); global.evaluate_script_on_global_with_result( - &script.text, + &script.code, script.url.as_str(), rval.handle_mut(), line_number, diff --git a/components/script/dom/userscripts.rs b/components/script/dom/userscripts.rs index a004e0fe6b8..047b3345b0c 100644 --- a/components/script/dom/userscripts.rs +++ b/components/script/dom/userscripts.rs @@ -4,14 +4,17 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; +use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlheadelement::HTMLHeadElement; +use crate::dom::htmlscriptelement::SourceCode; use crate::dom::node::document_from_node; use crate::script_module::ScriptFetchOptions; use js::jsval::UndefinedValue; use std::fs::{read_dir, File}; use std::io::Read; use std::path::PathBuf; +use std::rc::Rc; pub fn load_script(head: &HTMLHeadElement) { let doc = document_from_node(head); @@ -38,7 +41,9 @@ pub fn load_script(head: &HTMLHeadElement) { let mut f = File::open(&file).unwrap(); let mut contents = vec![]; f.read_to_end(&mut contents).unwrap(); - let script_text = String::from_utf8_lossy(&contents); + let script_text = SourceCode::Text( + Rc::new(DOMString::from_string(String::from_utf8_lossy(&contents).to_string())) + ); let global = win.upcast::<GlobalScope>(); global.evaluate_script_on_global_with_result( &script_text, diff --git a/resources/prefs.json b/resources/prefs.json index d48175de8b4..ecb0e31faa0 100644 --- a/resources/prefs.json +++ b/resources/prefs.json @@ -18,6 +18,7 @@ "dom.offscreen_canvas.enabled": false, "dom.permissions.enabled": false, "dom.permissions.testing.allowed_in_nonsecure_contexts": false, + "dom.script.asynch": true, "dom.serviceworker.enabled": false, "dom.serviceworker.timeout_seconds": 60, "dom.servo_helpers.enabled": false, diff --git a/tests/wpt/metadata/custom-elements/customized-built-in-constructor-exceptions.html.ini b/tests/wpt/metadata/custom-elements/customized-built-in-constructor-exceptions.html.ini deleted file mode 100644 index 10c7e55eab6..00000000000 --- a/tests/wpt/metadata/custom-elements/customized-built-in-constructor-exceptions.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[customized-built-in-constructor-exceptions.html] - expected: CRASH |