diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index f98e7df100a..bf3de043ff5 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -870,52 +870,40 @@ impl HTMLScriptElement {
let global = window.upcast::();
let _aes = AutoEntryScript::new(&global);
- if script.external {
- let module_map = global.get_module_map().borrow();
+ let tree = if script.external {
+ global.get_module_map().borrow().get(&script.url).cloned()
+ } else {
+ global
+ .get_inline_module_map()
+ .borrow()
+ .get(&self.id.clone())
+ .cloned()
+ };
- if let Some(module_tree) = module_map.get(&script.url) {
- // Step 6.
- {
- let module_error = module_tree.get_error().borrow();
- if module_error.is_some() {
- module_tree.report_error(&global);
- return;
- }
- }
-
- let module_record = module_tree.get_record().borrow();
- if let Some(record) = &*module_record {
- let evaluated = module_tree.execute_module(global, record.handle());
-
- if let Err(exception) = evaluated {
- module_tree.set_error(Some(exception.clone()));
- module_tree.report_error(&global);
- return;
- }
+ if let Some(module_tree) = tree {
+ // Step 6.
+ {
+ let module_error = module_tree.get_rethrow_error().borrow();
+ let network_error = module_tree.get_network_error().borrow();
+ if module_error.is_some() && network_error.is_none() {
+ module_tree.report_error(&global);
+ return;
}
}
- } else {
- let inline_module_map = global.get_inline_module_map().borrow();
- if let Some(module_tree) = inline_module_map.get(&self.id.clone()) {
- // Step 6.
- {
- let module_error = module_tree.get_error().borrow();
- if module_error.is_some() {
- module_tree.report_error(&global);
- return;
- }
- }
+ let record = module_tree
+ .get_record()
+ .borrow()
+ .as_ref()
+ .map(|record| record.handle());
- let module_record = module_tree.get_record().borrow();
- if let Some(record) = &*module_record {
- let evaluated = module_tree.execute_module(global, record.handle());
+ if let Some(record) = record {
+ let evaluated = module_tree.execute_module(global, record);
- if let Err(exception) = evaluated {
- module_tree.set_error(Some(exception.clone()));
- module_tree.report_error(&global);
- return;
- }
+ if let Err(exception) = evaluated {
+ module_tree.set_rethrow_error(exception);
+ module_tree.report_error(&global);
+ return;
}
}
}
diff --git a/components/script/script_module.rs b/components/script/script_module.rs
index ae8d57cad98..0ffe66d540e 100644
--- a/components/script/script_module.rs
+++ b/components/script/script_module.rs
@@ -12,7 +12,7 @@ use crate::dom::bindings::conversions::jsstring_to_str;
use crate::dom::bindings::error::report_pending_exception;
use crate::dom::bindings::error::Error;
use crate::dom::bindings::inheritance::Castable;
-use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
+use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::settings_stack::AutoIncumbentScript;
@@ -37,19 +37,19 @@ use crate::task::TaskBox;
use crate::task_source::TaskSourceName;
use encoding_rs::UTF_8;
use hyper_serde::Serde;
+use indexmap::{IndexMap, IndexSet};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::jsapi::Handle as RawHandle;
use js::jsapi::HandleObject;
use js::jsapi::HandleValue as RawHandleValue;
-use js::jsapi::{
- CompileModule, ExceptionStackBehavior, GetModuleResolveHook, JSRuntime, SetModuleResolveHook,
-};
+use js::jsapi::{CompileModule, ExceptionStackBehavior};
+use js::jsapi::{GetModuleResolveHook, JSRuntime, SetModuleResolveHook};
use js::jsapi::{GetRequestedModules, SetModuleMetadataHook};
-use js::jsapi::{GetWaitForAllPromise, ModuleEvaluate, ModuleInstantiate};
use js::jsapi::{Heap, JSContext, JS_ClearPendingException, SetModulePrivate};
use js::jsapi::{JSAutoRealm, JSObject, JSString};
use js::jsapi::{JS_DefineProperty4, JS_NewStringCopyN, JSPROP_ENUMERATE};
+use js::jsapi::{ModuleEvaluate, ModuleInstantiate};
use js::jsapi::{SetModuleDynamicImportHook, SetScriptPrivateReferenceHooks};
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
use js::rust::jsapi_wrapped::{GetRequestedModuleSpecifier, JS_GetPendingException};
@@ -57,9 +57,7 @@ use js::rust::jsapi_wrapped::{JS_GetArrayLength, JS_GetElement};
use js::rust::transform_u16_to_source_text;
use js::rust::wrappers::JS_SetPendingException;
use js::rust::CompileOptionsWrapper;
-use js::rust::IntoHandle;
-use js::rust::RootedObjectVectorWrapper;
-use js::rust::{Handle, HandleValue};
+use js::rust::{Handle, HandleValue, IntoHandle};
use mime::Mime;
use net_traits::request::{CredentialsMode, Destination, ParserMetadata};
use net_traits::request::{Referrer, RequestBuilder, RequestMode};
@@ -67,22 +65,19 @@ use net_traits::{FetchMetadata, Metadata};
use net_traits::{FetchResponseListener, NetworkError};
use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
-use std::cmp::Ordering;
-use std::collections::{HashMap, HashSet};
+use std::collections::HashSet;
use std::ffi;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use url::ParseError as UrlParseError;
-use indexmap::IndexSet;
-
#[allow(unsafe_code)]
-unsafe fn gen_type_error(global: &GlobalScope, string: String) -> ModuleError {
+unsafe fn gen_type_error(global: &GlobalScope, string: String) -> RethrowError {
rooted!(in(*global.get_cx()) let mut thrown = UndefinedValue());
Error::Type(string).to_jsval(*global.get_cx(), &global, thrown.handle_mut());
- return ModuleError::RawException(RootedTraceableBox::from_box(Heap::boxed(thrown.get())));
+ return RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get())));
}
#[derive(JSTraceable)]
@@ -96,57 +91,19 @@ impl ModuleObject {
}
#[derive(JSTraceable)]
-pub enum ModuleError {
- Network(NetworkError),
- RawException(RootedTraceableBox>),
-}
+pub struct RethrowError(RootedTraceableBox>);
-impl Eq for ModuleError {}
-
-impl PartialEq for ModuleError {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Self::Network(_), Self::RawException(_)) |
- (Self::RawException(_), Self::Network(_)) => false,
- _ => true,
- }
+impl RethrowError {
+ fn handle(&self) -> Handle {
+ self.0.handle()
}
}
-impl Ord for ModuleError {
- fn cmp(&self, other: &Self) -> Ordering {
- match (self, other) {
- (Self::Network(_), Self::RawException(_)) => Ordering::Greater,
- (Self::RawException(_), Self::Network(_)) => Ordering::Less,
- _ => Ordering::Equal,
- }
- }
-}
-
-impl PartialOrd for ModuleError {
- fn partial_cmp(&self, other: &Self) -> Option {
- Some(self.cmp(other))
- }
-}
-
-impl ModuleError {
- #[allow(unsafe_code)]
- pub fn handle(&self) -> Handle {
- match self {
- Self::Network(_) => unreachable!(),
- Self::RawException(exception) => exception.handle(),
- }
- }
-}
-
-impl Clone for ModuleError {
+impl Clone for RethrowError {
fn clone(&self) -> Self {
- match self {
- Self::Network(network_error) => Self::Network(network_error.clone()),
- Self::RawException(exception) => Self::RawException(RootedTraceableBox::from_box(
- Heap::boxed(exception.get().clone()),
- )),
- }
+ Self(RootedTraceableBox::from_box(Heap::boxed(
+ self.0.get().clone(),
+ )))
}
}
@@ -154,6 +111,35 @@ struct ModuleScript {
base_url: ServoUrl,
}
+/// Identity for a module which will be
+/// used to retrieve the module when we'd
+/// like to get it from module map.
+///
+/// For example, we will save module parents with
+/// module identity so that we can get module tree
+/// from a descendant no matter the parent is an
+/// inline script or a external script
+#[derive(Clone, Eq, Hash, JSTraceable, PartialEq)]
+pub enum ModuleIdentity {
+ ScriptId(ScriptId),
+ ModuleUrl(ServoUrl),
+}
+
+impl ModuleIdentity {
+ pub fn get_module_tree(&self, global: &GlobalScope) -> Rc {
+ match self {
+ ModuleIdentity::ModuleUrl(url) => {
+ let module_map = global.get_module_map().borrow();
+ module_map.get(&url.clone()).unwrap().clone()
+ },
+ ModuleIdentity::ScriptId(script_id) => {
+ let inline_module_map = global.get_inline_module_map().borrow();
+ inline_module_map.get(&script_id).unwrap().clone()
+ },
+ }
+ }
+}
+
#[derive(JSTraceable)]
pub struct ModuleTree {
url: ServoUrl,
@@ -168,36 +154,37 @@ pub struct ModuleTree {
// By default all maps in web specs are ordered maps
// (https://infra.spec.whatwg.org/#ordered-map), however we can usually get away with using
// stdlib maps and sets because we rarely iterate over them.
- parent_urls: DomRefCell>,
+ parent_identities: DomRefCell>,
descendant_urls: DomRefCell>,
+ // A set to memoize which descendants are under fetching
+ incomplete_fetch_urls: DomRefCell>,
visited_urls: DomRefCell>,
- error: DomRefCell