diff options
author | bors-servo <servo-ops@mozilla.com> | 2020-07-19 09:29:50 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-19 09:29:50 -0400 |
commit | 086556e706bbb65790e7fb9a918bf7e8051171e0 (patch) | |
tree | fa6ad280c0e2d2be02e0a75071514cb9337c3d46 /components/script/dom | |
parent | ccff00742f42a62b3004f27fdd02cfa0b388d745 (diff) | |
parent | 419cd53561e4abaadc78b2cfea55e0bf0edfb36c (diff) | |
download | servo-086556e706bbb65790e7fb9a918bf7e8051171e0.tar.gz servo-086556e706bbb65790e7fb9a918bf7e8051171e0.zip |
Auto merge of #27026 - CYBAI:dynamic-module, r=jdm
Introduce dynamic module
---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #25439
- [x] There are tests for these changes
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/codegen/Bindings.conf | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 42 | ||||
-rw-r--r-- | components/script/dom/dynamicmoduleowner.rs | 54 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 106 | ||||
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 151 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/servoparser/prefetch.rs | 14 | ||||
-rw-r--r-- | components/script/dom/userscripts.rs | 17 | ||||
-rw-r--r-- | components/script/dom/webidls/DynamicModuleOwner.webidl | 13 | ||||
-rw-r--r-- | components/script/dom/workletglobalscope.rs | 11 |
10 files changed, 314 insertions, 99 deletions
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf index ec8974b6cbd..6c6e0ed6618 100644 --- a/components/script/dom/bindings/codegen/Bindings.conf +++ b/components/script/dom/bindings/codegen/Bindings.conf @@ -47,6 +47,10 @@ DOMInterfaces = { 'inRealms': ['PromiseAttribute', 'PromiseNativeHandler'], }, +'DynamicModuleOwner': { + 'inRealms': ['PromiseAttribute'], +}, + 'URL': { 'weakReferenceable': True, }, diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 121e96b4a0e..92d6ebcb7bf 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -77,12 +77,13 @@ use hyper::Method; use hyper::StatusCode; use indexmap::IndexMap; use ipc_channel::ipc::{IpcReceiver, IpcSender}; -use js::glue::{CallObjectTracer, CallValueTracer}; -use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, JobQueue, TraceKind}; +use js::glue::{CallObjectTracer, CallStringTracer, CallValueTracer}; +use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSString, JSTracer, JobQueue, TraceKind}; use js::jsval::JSVal; use js::rust::{GCMethods, Handle, Runtime}; use js::typedarray::TypedArray; use js::typedarray::TypedArrayElement; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use media::WindowGLContext; use metrics::{InteractiveMetrics, InteractiveWindow}; use mime::Mime; @@ -94,7 +95,7 @@ use msg::constellation_msg::{ServiceWorkerId, ServiceWorkerRegistrationId}; use net_traits::filemanager_thread::RelativePos; use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache::{ImageCache, PendingImageId}; -use net_traits::request::{Referrer, Request, RequestBuilder}; +use net_traits::request::{CredentialsMode, ParserMetadata, Referrer, Request, RequestBuilder}; use net_traits::response::HttpsState; use net_traits::response::{Response, ResponseBody}; use net_traits::storage_thread::StorageType; @@ -134,6 +135,7 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell, UnsafeCell}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::hash::{BuildHasher, Hash}; +use std::mem; use std::ops::{Deref, DerefMut, Range}; use std::path::PathBuf; use std::rc::Rc; @@ -252,6 +254,18 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JS } } +/// Trace a `JSString`. +pub fn trace_string(tracer: *mut JSTracer, description: &str, s: &Heap<*mut JSString>) { + unsafe { + trace!("tracing {}", description); + CallStringTracer( + tracer, + s.ptr.get() as *mut _, + GCTraceKindToAscii(TraceKind::String), + ); + } +} + unsafe impl<T: JSTraceable> JSTraceable for Rc<T> { unsafe fn trace(&self, trc: *mut JSTracer) { (**self).trace(trc) @@ -323,6 +337,15 @@ unsafe impl JSTraceable for Heap<*mut JSObject> { } } +unsafe impl JSTraceable for Heap<*mut JSString> { + unsafe fn trace(&self, trc: *mut JSTracer) { + if self.get().is_null() { + return; + } + trace_string(trc, "heap string", self); + } +} + unsafe impl JSTraceable for Heap<JSVal> { unsafe fn trace(&self, trc: *mut JSTracer) { trace_jsval(trc, "heap value", self); @@ -534,6 +557,8 @@ unsafe_no_jsmanaged_fields!(StyleSharedRwLock); unsafe_no_jsmanaged_fields!(USVString); unsafe_no_jsmanaged_fields!(Referrer); unsafe_no_jsmanaged_fields!(ReferrerPolicy); +unsafe_no_jsmanaged_fields!(CredentialsMode); +unsafe_no_jsmanaged_fields!(ParserMetadata); unsafe_no_jsmanaged_fields!(Response); unsafe_no_jsmanaged_fields!(ResponseBody); unsafe_no_jsmanaged_fields!(ResourceThreads); @@ -1068,6 +1093,17 @@ where } } +impl<T: JSTraceable + MallocSizeOf> MallocSizeOf for RootedTraceableBox<T> { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + // Briefly resurrect the real Box value so we can rely on the existing calculations. + // Then immediately forget about it again to avoid dropping the box. + let inner = unsafe { Box::from_raw(self.ptr) }; + let size = inner.size_of(ops); + mem::forget(inner); + size + } +} + impl<T: JSTraceable + Default> Default for RootedTraceableBox<T> { fn default() -> RootedTraceableBox<T> { RootedTraceableBox::new(T::default()) diff --git a/components/script/dom/dynamicmoduleowner.rs b/components/script/dom/dynamicmoduleowner.rs new file mode 100644 index 00000000000..50fc71fbd79 --- /dev/null +++ b/components/script/dom/dynamicmoduleowner.rs @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::DynamicModuleOwnerBinding::DynamicModuleOwnerMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use dom_struct::dom_struct; +use std::rc::Rc; +use uuid::Uuid; + +/// An unique id for dynamic module +#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)] +pub struct DynamicModuleId(pub Uuid); + +#[dom_struct] +pub struct DynamicModuleOwner { + reflector_: Reflector, + + #[ignore_malloc_size_of = "Rc"] + promise: Rc<Promise>, + + /// Unique id for each dynamic module + #[ignore_malloc_size_of = "Defined in uuid"] + id: DynamicModuleId, +} + +impl DynamicModuleOwner { + #[allow(unrooted_must_root)] + fn new_inherited(promise: Rc<Promise>, id: DynamicModuleId) -> Self { + DynamicModuleOwner { + reflector_: Reflector::new(), + promise, + id, + } + } + + #[allow(unrooted_must_root)] + pub fn new(global: &GlobalScope, promise: Rc<Promise>, id: DynamicModuleId) -> DomRoot<Self> { + reflect_dom_object( + Box::new(DynamicModuleOwner::new_inherited(promise, id)), + global, + ) + } +} + +impl DynamicModuleOwnerMethods for DynamicModuleOwner { + // https://html.spec.whatwg.org/multipage/#integration-with-the-javascript-module-system:import() + fn Promise(&self) -> Rc<Promise> { + self.promise.clone() + } +} diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 5db5942fe0d..a6427224882 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::cell::{DomRefCell, RefMut}; use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods; use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSourceBinding::EventSourceMethods; use crate::dom::bindings::codegen::Bindings::GPUValidationErrorBinding::GPUError; @@ -55,7 +55,8 @@ use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workletglobalscope::WorkletGlobalScope; use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask}; use crate::realms::{enter_realm, AlreadyInRealm, InRealm}; -use crate::script_module::ModuleTree; +use crate::script_module::{DynamicModuleList, ModuleTree}; +use crate::script_module::{ModuleScript, ScriptFetchOptions}; use crate::script_runtime::{ CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan, ScriptPort, }; @@ -81,13 +82,16 @@ use embedder_traits::EmbedderMsg; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use js::glue::{IsWrapper, UnwrapObjectDynamic}; +use js::jsapi::Compile1; +use js::jsapi::SetScriptPrivate; use js::jsapi::{CurrentGlobalOrNull, GetNonCCWObjectGlobal}; use js::jsapi::{HandleObject, Heap}; use js::jsapi::{JSContext, JSObject}; +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::Evaluate2; +use js::rust::wrappers::{JS_ExecuteScript, JS_GetScriptPrivate}; use js::rust::{get_object_class, CompileOptionsWrapper, ParentRuntime, Runtime}; use js::rust::{HandleValue, MutableHandleValue}; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; @@ -306,6 +310,9 @@ pub struct GlobalScope { /// The stack of active group labels for the Console APIs. console_group_stack: DomRefCell<Vec<DOMString>>, + + /// List of ongoing dynamic module imports. + dynamic_modules: DomRefCell<DynamicModuleList>, } /// A wrapper for glue-code between the ipc router and the event-loop. @@ -757,6 +764,7 @@ impl GlobalScope { frozen_supported_performance_entry_types: DomRefCell::new(Default::default()), https_state: Cell::new(HttpsState::None), console_group_stack: DomRefCell::new(Vec::new()), + dynamic_modules: DomRefCell::new(DynamicModuleList::new()), } } @@ -2537,8 +2545,21 @@ impl GlobalScope { } /// Evaluate JS code on this global scope. - pub fn evaluate_js_on_global_with_result(&self, code: &str, rval: MutableHandleValue) -> bool { - self.evaluate_script_on_global_with_result(code, "", rval, 1) + pub fn evaluate_js_on_global_with_result( + &self, + code: &str, + rval: MutableHandleValue, + fetch_options: ScriptFetchOptions, + script_base_url: ServoUrl, + ) -> bool { + self.evaluate_script_on_global_with_result( + code, + "", + rval, + 1, + fetch_options, + script_base_url, + ) } /// Evaluate a JS script on this global scope. @@ -2549,6 +2570,8 @@ impl GlobalScope { filename: &str, rval: MutableHandleValue, line_number: u32, + fetch_options: ScriptFetchOptions, + script_base_url: ServoUrl, ) -> bool { let metadata = profile_time::TimerMetadata { url: if filename.is_empty() { @@ -2570,26 +2593,59 @@ impl GlobalScope { let ar = enter_realm(&*self); let _aes = AutoEntryScript::new(self); - let options = - unsafe { CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number) }; - - debug!("evaluating Dom string"); - let result = unsafe { - Evaluate2( - *cx, - options.ptr, - &mut transform_str_to_source_text(code), - rval, - ) - }; - if !result { - debug!("error evaluating Dom string"); - unsafe { report_pending_exception(*cx, true, InRealm::Entered(&ar)) }; - } + unsafe { + let options = CompileOptionsWrapper::new(*cx, filename.as_ptr(), line_number); - maybe_resume_unwind(); - result + debug!("compiling Dom string"); + rooted!(in(*cx) let compiled_script = + Compile1( + *cx, + options.ptr, + &mut transform_str_to_source_text(code), + ) + ); + + 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 _), + ); + } + + debug!("evaluating Dom string"); + let result = JS_ExecuteScript(*cx, compiled_script.handle(), rval); + + if !result { + debug!("error evaluating Dom string"); + report_pending_exception(*cx, true, InRealm::Entered(&ar)); + } + + maybe_resume_unwind(); + result + } }, ) } @@ -2991,6 +3047,10 @@ impl GlobalScope { pub(crate) fn pop_console_group(&self) { let _ = self.console_group_stack.borrow_mut().pop(); } + + pub(crate) fn dynamic_module_list(&self) -> RefMut<DynamicModuleList> { + self.dynamic_modules.borrow_mut() + } } fn timestamp_in_ms(time: Timespec) -> u64 { diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index b70e83d5a33..2ad7444f7f4 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -28,7 +28,7 @@ use crate::dom::virtualmethods::VirtualMethods; use crate::fetch::create_a_potential_cors_request; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::script_module::fetch_inline_module_script; -use crate::script_module::{fetch_external_module_script, ModuleOwner}; +use crate::script_module::{fetch_external_module_script, ModuleOwner, ScriptFetchOptions}; use content_security_policy as csp; use dom_struct::dom_struct; use encoding_rs::Encoding; @@ -37,8 +37,9 @@ use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::jsval::UndefinedValue; use msg::constellation_msg::PipelineId; -use net_traits::request::{CorsSettings, CredentialsMode, Destination, Referrer, RequestBuilder}; -use net_traits::ReferrerPolicy; +use net_traits::request::{ + CorsSettings, CredentialsMode, Destination, ParserMetadata, RequestBuilder, +}; use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; use net_traits::{ResourceFetchTiming, ResourceTimingType}; use servo_atoms::Atom; @@ -155,24 +156,37 @@ pub struct ScriptOrigin { text: Rc<DOMString>, url: ServoUrl, external: bool, + fetch_options: ScriptFetchOptions, type_: ScriptType, } impl ScriptOrigin { - pub fn internal(text: Rc<DOMString>, url: ServoUrl, type_: ScriptType) -> ScriptOrigin { + pub fn internal( + text: Rc<DOMString>, + url: ServoUrl, + fetch_options: ScriptFetchOptions, + type_: ScriptType, + ) -> ScriptOrigin { ScriptOrigin { text: text, url: url, external: false, + fetch_options, type_, } } - pub fn external(text: Rc<DOMString>, url: ServoUrl, type_: ScriptType) -> ScriptOrigin { + pub fn external( + text: Rc<DOMString>, + url: ServoUrl, + fetch_options: ScriptFetchOptions, + type_: ScriptType, + ) -> ScriptOrigin { ScriptOrigin { text: text, url: url, external: true, + fetch_options, type_, } } @@ -201,6 +215,8 @@ struct ClassicContext { url: ServoUrl, /// Indicates whether the request failed, and why status: Result<(), NetworkError>, + /// The fetch options of the script + fetch_options: ScriptFetchOptions, /// Timing object for this resource resource_timing: ResourceFetchTiming, } @@ -261,6 +277,7 @@ impl FetchResponseListener for ClassicContext { ScriptOrigin::external( Rc::new(DOMString::from(source_text)), metadata.final_url, + self.fetch_options.clone(), ScriptType::Classic, ) }); @@ -322,15 +339,22 @@ pub(crate) fn script_fetch_request( cors_setting: Option<CorsSettings>, origin: ImmutableOrigin, pipeline_id: PipelineId, - referrer: Referrer, - referrer_policy: Option<ReferrerPolicy>, - integrity_metadata: String, + options: ScriptFetchOptions, ) -> RequestBuilder { - create_a_potential_cors_request(url, Destination::Script, cors_setting, None, referrer) - .origin(origin) - .pipeline_id(Some(pipeline_id)) - .referrer_policy(referrer_policy) - .integrity_metadata(integrity_metadata) + // We intentionally ignore options' credentials_mode member for classic scripts. + // The mode is initialized by create_a_potential_cors_request. + create_a_potential_cors_request( + url, + Destination::Script, + cors_setting, + None, + options.referrer, + ) + .origin(origin) + .pipeline_id(Some(pipeline_id)) + .parser_metadata(options.parser_metadata) + .integrity_metadata(options.integrity_metadata.clone()) + .referrer_policy(options.referrer_policy) } /// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script> @@ -339,7 +363,7 @@ fn fetch_a_classic_script( kind: ExternalScriptKind, url: ServoUrl, cors_setting: Option<CorsSettings>, - integrity_metadata: String, + options: ScriptFetchOptions, character_encoding: &'static Encoding, ) { let doc = document_from_node(script); @@ -350,9 +374,7 @@ fn fetch_a_classic_script( cors_setting, doc.origin().immutable().clone(), script.global().pipeline_id(), - script.global().get_referrer(), - doc.get_referrer_policy(), - integrity_metadata, + options.clone(), ); // TODO: Step 3, Add custom steps to perform fetch @@ -365,6 +387,7 @@ fn fetch_a_classic_script( metadata: None, url: url.clone(), status: Ok(()), + fetch_options: options, resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource), })); @@ -400,7 +423,7 @@ impl HTMLScriptElement { let was_parser_inserted = self.parser_inserted.get(); self.parser_inserted.set(false); - // Step 3. + // Step 4. let element = self.upcast::<Element>(); let asynch = element.has_attribute(&local_name!("async")); // Note: confusingly, this is done if the element does *not* have an "async" attribute. @@ -408,13 +431,13 @@ impl HTMLScriptElement { self.non_blocking.set(true); } - // Step 4-5. + // Step 5-6. let text = self.Text(); if text.is_empty() && !element.has_attribute(&local_name!("src")) { return; } - // Step 6. + // Step 7. if !self.upcast::<Node>().is_connected() { return; } @@ -432,26 +455,26 @@ impl HTMLScriptElement { self.non_blocking.set(false); } - // Step 9. + // Step 10. self.already_started.set(true); - // Step 10. + // Step 12. let doc = document_from_node(self); if self.parser_inserted.get() && &*self.parser_document != &*doc { return; } - // Step 11. + // Step 13. if !doc.is_scripting_enabled() { return; } - // Step 12 + // Step 14 if element.has_attribute(&local_name!("nomodule")) && script_type == ScriptType::Classic { return; } - // Step 13. + // Step 15. if !element.has_attribute(&local_name!("src")) && doc.should_elements_inline_type_behavior_be_blocked( &element, @@ -463,7 +486,7 @@ impl HTMLScriptElement { return; } - // Step 14. + // Step 16. if script_type == ScriptType::Classic { let for_attribute = element.get_attribute(&ns!(), &local_name!("for")); let event_attribute = element.get_attribute(&ns!(), &local_name!("event")); @@ -485,31 +508,31 @@ impl HTMLScriptElement { } } - // Step 15. + // Step 17. let encoding = element .get_attribute(&ns!(), &local_name!("charset")) .and_then(|charset| Encoding::for_label(charset.value().as_bytes())) .unwrap_or_else(|| doc.encoding()); - // Step 16. + // Step 18. let cors_setting = cors_setting_for_element(element); - // Step 17. - let credentials_mode = match script_type { - ScriptType::Classic => None, - ScriptType::Module => Some(reflect_cross_origin_attribute(element).map_or( + // Step 19. + let module_credentials_mode = match script_type { + ScriptType::Classic => CredentialsMode::CredentialsSameOrigin, + ScriptType::Module => reflect_cross_origin_attribute(element).map_or( CredentialsMode::CredentialsSameOrigin, |attr| match &*attr { "use-credentials" => CredentialsMode::Include, "anonymous" => CredentialsMode::CredentialsSameOrigin, _ => CredentialsMode::CredentialsSameOrigin, }, - )), + ), }; - // TODO: Step 18: Nonce. + // TODO: Step 20: Nonce. - // Step 19: Integrity metadata. + // Step 21: Integrity metadata. let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity")); let integrity_val = im_attribute.as_ref().map(|a| a.value()); let integrity_metadata = match integrity_val { @@ -517,30 +540,43 @@ impl HTMLScriptElement { None => "", }; - // TODO: Step 20: referrer policy + // TODO: Step 22: referrer policy - // TODO: Step 21: parser state. + // Step 23 + let parser_metadata = if self.parser_inserted.get() { + ParserMetadata::ParserInserted + } else { + ParserMetadata::NotParserInserted + }; - // TODO: Step 22: Fetch options + // Step 24. + let options = ScriptFetchOptions { + cryptographic_nonce: "".into(), + integrity_metadata: integrity_metadata.to_owned(), + parser_metadata, + referrer: self.global().get_referrer(), + referrer_policy: doc.get_referrer_policy(), + credentials_mode: module_credentials_mode, + }; // TODO: Step 23: environment settings object. let base_url = doc.base_url(); if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) { - // Step 24. + // Step 26. - // Step 24.1. + // Step 26.1. let src = src.value(); - // Step 24.2. + // Step 26.2. if src.is_empty() { self.queue_error_event(); return; } - // Step 24.3: The "from an external file"" flag is stored in ScriptOrigin. + // Step 26.3: The "from an external file"" flag is stored in ScriptOrigin. - // Step 24.4-24.5. + // Step 26.4-26.5. let url = match base_url.join(&src) { Ok(url) => url, Err(_) => { @@ -550,7 +586,7 @@ impl HTMLScriptElement { }, }; - // Step 24.6. + // Step 26.6. match script_type { ScriptType::Classic => { // Preparation for step 26. @@ -572,14 +608,7 @@ impl HTMLScriptElement { }; // Step 24.6. - fetch_a_classic_script( - self, - kind, - url, - cors_setting, - integrity_metadata.to_owned(), - encoding, - ); + fetch_a_classic_script(self, kind, url, cors_setting, options, encoding); // Step 23. match kind { @@ -596,8 +625,7 @@ impl HTMLScriptElement { ModuleOwner::Window(Trusted::new(self)), url.clone(), Destination::Script, - integrity_metadata.to_owned(), - credentials_mode.unwrap(), + options, ); if !asynch && was_parser_inserted { @@ -610,19 +638,20 @@ impl HTMLScriptElement { }, } } else { - // Step 25. + // Step 27. assert!(!text.is_empty()); let text_rc = Rc::new(text); - // Step 25-1. & 25-2. + // Step 27-1. & 27-2. let result = Ok(ScriptOrigin::internal( Rc::clone(&text_rc), base_url.clone(), + options.clone(), script_type.clone(), )); - // Step 25-2. + // Step 27-2. match script_type { ScriptType::Classic => { if was_parser_inserted && @@ -630,10 +659,10 @@ impl HTMLScriptElement { .map_or(false, |parser| parser.script_nesting_level() <= 1) && doc.get_script_blocking_stylesheets_count() > 0 { - // Step 26.h: classic, has no src, was parser-inserted, is blocked on stylesheet. + // Step 27.h: classic, has no src, was parser-inserted, is blocked on stylesheet. doc.set_pending_parsing_blocking_script(self, Some(result)); } else { - // Step 26.i: otherwise. + // Step 27.i: otherwise. self.execute(result); } }, @@ -654,7 +683,7 @@ impl HTMLScriptElement { text_rc, base_url.clone(), self.id.clone(), - credentials_mode.unwrap(), + options, ); }, } @@ -855,6 +884,8 @@ impl HTMLScriptElement { script.url.as_str(), rval.handle_mut(), line_number, + script.fetch_options.clone(), + script.url.clone(), ); } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 3047ce2c983..698cff979c9 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -295,6 +295,7 @@ pub mod domrectreadonly; pub mod domstringlist; pub mod domstringmap; pub mod domtokenlist; +pub mod dynamicmoduleowner; pub mod element; pub mod errorevent; pub mod event; diff --git a/components/script/dom/servoparser/prefetch.rs b/components/script/dom/servoparser/prefetch.rs index 6d7d6c24e2c..4de7e765b0c 100644 --- a/components/script/dom/servoparser/prefetch.rs +++ b/components/script/dom/servoparser/prefetch.rs @@ -7,6 +7,7 @@ use crate::dom::bindings::trace::JSTraceable; use crate::dom::document::{determine_policy_for_token, Document}; use crate::dom::htmlimageelement::{image_fetch_request, FromPictureOrSrcSet}; use crate::dom::htmlscriptelement::script_fetch_request; +use crate::script_module::ScriptFetchOptions; use crate::stylesheet_loader::stylesheet_fetch_request; use html5ever::buffer_queue::BufferQueue; use html5ever::tokenizer::states::RawKind; @@ -22,6 +23,8 @@ use html5ever::LocalName; use js::jsapi::JSTracer; use msg::constellation_msg::PipelineId; use net_traits::request::CorsSettings; +use net_traits::request::CredentialsMode; +use net_traits::request::ParserMetadata; use net_traits::request::Referrer; use net_traits::CoreResourceMsg; use net_traits::FetchChannels; @@ -110,9 +113,14 @@ impl TokenSink for PrefetchSink { cors_setting, self.origin.clone(), self.pipeline_id, - self.referrer.clone(), - self.referrer_policy, - integrity_metadata, + ScriptFetchOptions { + referrer: self.referrer.clone(), + referrer_policy: self.referrer_policy, + integrity_metadata, + cryptographic_nonce: String::new(), + credentials_mode: CredentialsMode::CredentialsSameOrigin, + parser_metadata: ParserMetadata::ParserInserted, + }, ); let _ = self .resource_threads diff --git a/components/script/dom/userscripts.rs b/components/script/dom/userscripts.rs index 4e9cc59d27f..a004e0fe6b8 100644 --- a/components/script/dom/userscripts.rs +++ b/components/script/dom/userscripts.rs @@ -7,6 +7,7 @@ use crate::dom::bindings::refcounted::Trusted; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlheadelement::HTMLHeadElement; 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; @@ -38,13 +39,15 @@ pub fn load_script(head: &HTMLHeadElement) { let mut contents = vec![]; f.read_to_end(&mut contents).unwrap(); let script_text = String::from_utf8_lossy(&contents); - win.upcast::<GlobalScope>() - .evaluate_script_on_global_with_result( - &script_text, - &file.to_string_lossy(), - rval.handle_mut(), - 1, - ); + let global = win.upcast::<GlobalScope>(); + global.evaluate_script_on_global_with_result( + &script_text, + &file.to_string_lossy(), + rval.handle_mut(), + 1, + ScriptFetchOptions::default_classic_script(&global), + global.api_base_url(), + ); } })); } diff --git a/components/script/dom/webidls/DynamicModuleOwner.webidl b/components/script/dom/webidls/DynamicModuleOwner.webidl new file mode 100644 index 00000000000..924481d491b --- /dev/null +++ b/components/script/dom/webidls/DynamicModuleOwner.webidl @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +/** + * This is defined for [`Dynamic Module`](https://html.spec.whatwg.org/multipage/#fetch-an-import()-module-script-graph) + * so that we can hold a traceable owner for those dynamic modules which don't hold a owner. + */ + +[NoInterfaceObject, Exposed=Window] +interface DynamicModuleOwner { + readonly attribute Promise<any> promise; +}; diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs index 88b8a13708b..47e6315c940 100644 --- a/components/script/dom/workletglobalscope.rs +++ b/components/script/dom/workletglobalscope.rs @@ -11,6 +11,7 @@ use crate::dom::paintworkletglobalscope::PaintWorkletTask; use crate::dom::testworkletglobalscope::TestWorkletGlobalScope; use crate::dom::testworkletglobalscope::TestWorkletTask; use crate::dom::worklet::WorkletExecutor; +use crate::script_module::ScriptFetchOptions; use crate::script_runtime::JSContext; use crate::script_thread::MainThreadScriptMsg; use crossbeam_channel::Sender; @@ -88,10 +89,14 @@ impl WorkletGlobalScope { /// Evaluate a JS script in this global. pub fn evaluate_js(&self, script: &str) -> bool { - debug!("Evaluating Dom."); + debug!("Evaluating Dom in a worklet."); rooted!(in (*self.globalscope.get_cx()) let mut rval = UndefinedValue()); - self.globalscope - .evaluate_js_on_global_with_result(&*script, rval.handle_mut()) + self.globalscope.evaluate_js_on_global_with_result( + &*script, + rval.handle_mut(), + ScriptFetchOptions::default_classic_script(&self.globalscope), + self.globalscope.api_base_url(), + ) } /// Register a paint worklet to the script thread. |