mirror of
https://github.com/servo/servo.git
synced 2025-06-29 03:23:41 +01:00
script: complete resolve_module_specifier
(#37552)
Implement whole spec of `resolve_module_specifier`. Servo can now support script element with import map type! Testing: `tests/wpt/tests/import-map` Fixes: #37316 #36394 --------- Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>
This commit is contained in:
parent
d7269c0f3b
commit
927573de97
35 changed files with 376 additions and 281 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use std::cell::{Cell, OnceCell, Ref};
|
use std::cell::{Cell, OnceCell, Ref};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@ -137,7 +137,7 @@ use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{NetworkListener, PreInvoke};
|
||||||
use crate::realms::{InRealm, enter_realm};
|
use crate::realms::{InRealm, enter_realm};
|
||||||
use crate::script_module::{
|
use crate::script_module::{
|
||||||
DynamicModuleList, ImportMap, ModuleScript, ModuleTree, ScriptFetchOptions,
|
DynamicModuleList, ImportMap, ModuleScript, ModuleTree, ResolvedModule, ScriptFetchOptions,
|
||||||
};
|
};
|
||||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, ThreadSafeJSContext};
|
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, ThreadSafeJSContext};
|
||||||
use crate::script_thread::{ScriptThread, with_script_thread};
|
use crate::script_thread::{ScriptThread, with_script_thread};
|
||||||
|
@ -385,6 +385,9 @@ pub(crate) struct GlobalScope {
|
||||||
///
|
///
|
||||||
/// <https://html.spec.whatwg.org/multipage/#import-maps>
|
/// <https://html.spec.whatwg.org/multipage/#import-maps>
|
||||||
import_map: DomRefCell<ImportMap>,
|
import_map: DomRefCell<ImportMap>,
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#resolved-module-set>
|
||||||
|
resolved_module_set: DomRefCell<HashSet<ResolvedModule>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper for glue-code between the ipc router and the event-loop.
|
/// A wrapper for glue-code between the ipc router and the event-loop.
|
||||||
|
@ -789,6 +792,7 @@ impl GlobalScope {
|
||||||
count_queuing_strategy_size_function: OnceCell::new(),
|
count_queuing_strategy_size_function: OnceCell::new(),
|
||||||
notification_permission_request_callback_map: Default::default(),
|
notification_permission_request_callback_map: Default::default(),
|
||||||
import_map: Default::default(),
|
import_map: Default::default(),
|
||||||
|
resolved_module_set: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3487,8 +3491,40 @@ impl GlobalScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn import_map(&self) -> &DomRefCell<ImportMap> {
|
pub(crate) fn import_map(&self) -> Ref<'_, ImportMap> {
|
||||||
&self.import_map
|
self.import_map.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn import_map_mut(&self) -> RefMut<'_, ImportMap> {
|
||||||
|
self.import_map.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn resolved_module_set(&self) -> Ref<'_, HashSet<ResolvedModule>> {
|
||||||
|
self.resolved_module_set.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn resolved_module_set_mut(&self) -> RefMut<'_, HashSet<ResolvedModule>> {
|
||||||
|
self.resolved_module_set.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#add-module-to-resolved-module-set>
|
||||||
|
pub(crate) fn add_module_to_resolved_module_set(
|
||||||
|
&self,
|
||||||
|
base_url: &str,
|
||||||
|
specifier: &str,
|
||||||
|
specifier_url: Option<ServoUrl>,
|
||||||
|
) {
|
||||||
|
// Step 1. Let global be settingsObject's global object.
|
||||||
|
// Step 2. If global does not implement Window, then return.
|
||||||
|
if self.is::<Window>() {
|
||||||
|
// Step 3. Let record be a new specifier resolution record, with serialized base URL
|
||||||
|
// set to serializedBaseURL, specifier set to normalizedSpecifier, and specifier as
|
||||||
|
// a URL set to asURL.
|
||||||
|
let record =
|
||||||
|
ResolvedModule::new(base_url.to_owned(), specifier.to_owned(), specifier_url);
|
||||||
|
// Step 4. Append record to global's resolved module set.
|
||||||
|
self.resolved_module_set.borrow_mut().insert(record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -856,7 +856,9 @@ impl HTMLScriptElement {
|
||||||
credentials_mode: module_credentials_mode,
|
credentials_mode: module_credentials_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Step 30. Environment settings object.
|
// Step 30. Let settings object be el's node document's relevant settings object.
|
||||||
|
// This is done by passing ModuleOwner in step 31.11 and step 32.2.
|
||||||
|
// What we actually need is global's import map eventually.
|
||||||
|
|
||||||
let base_url = doc.base_url();
|
let base_url = doc.base_url();
|
||||||
if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) {
|
if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) {
|
||||||
|
|
|
@ -22,13 +22,13 @@ use js::jsapi::{
|
||||||
GetModuleResolveHook, GetRequestedModuleSpecifier, GetRequestedModulesCount,
|
GetModuleResolveHook, GetRequestedModuleSpecifier, GetRequestedModulesCount,
|
||||||
Handle as RawHandle, HandleObject, HandleValue as RawHandleValue, Heap,
|
Handle as RawHandle, HandleObject, HandleValue as RawHandleValue, Heap,
|
||||||
JS_ClearPendingException, JS_DefineProperty4, JS_IsExceptionPending, JS_NewStringCopyN,
|
JS_ClearPendingException, JS_DefineProperty4, JS_IsExceptionPending, JS_NewStringCopyN,
|
||||||
JSAutoRealm, JSContext, JSObject, JSPROP_ENUMERATE, JSRuntime, JSString, ModuleErrorBehaviour,
|
JSAutoRealm, JSContext, JSObject, JSPROP_ENUMERATE, JSRuntime, ModuleErrorBehaviour,
|
||||||
ModuleEvaluate, ModuleLink, MutableHandleValue, SetModuleDynamicImportHook,
|
ModuleEvaluate, ModuleLink, MutableHandleValue, SetModuleDynamicImportHook,
|
||||||
SetModuleMetadataHook, SetModulePrivate, SetModuleResolveHook, SetScriptPrivateReferenceHooks,
|
SetModuleMetadataHook, SetModulePrivate, SetModuleResolveHook, SetScriptPrivateReferenceHooks,
|
||||||
ThrowOnModuleEvaluationFailure, Value,
|
ThrowOnModuleEvaluationFailure, Value,
|
||||||
};
|
};
|
||||||
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
|
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
|
||||||
use js::rust::wrappers::{JS_GetPendingException, JS_SetPendingException};
|
use js::rust::wrappers::{JS_GetModulePrivate, JS_GetPendingException, JS_SetPendingException};
|
||||||
use js::rust::{
|
use js::rust::{
|
||||||
CompileOptionsWrapper, Handle, HandleObject as RustHandleObject, HandleValue, IntoHandle,
|
CompileOptionsWrapper, Handle, HandleObject as RustHandleObject, HandleValue, IntoHandle,
|
||||||
MutableHandleObject as RustMutableHandleObject, transform_str_to_source_text,
|
MutableHandleObject as RustMutableHandleObject, transform_str_to_source_text,
|
||||||
|
@ -512,7 +512,6 @@ impl ModuleTree {
|
||||||
self.resolve_requested_module_specifiers(
|
self.resolve_requested_module_specifiers(
|
||||||
global,
|
global,
|
||||||
module_script.handle().into_handle(),
|
module_script.handle().into_handle(),
|
||||||
url,
|
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
@ -616,7 +615,6 @@ impl ModuleTree {
|
||||||
&self,
|
&self,
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
module_object: HandleObject,
|
module_object: HandleObject,
|
||||||
base_url: &ServoUrl,
|
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Result<IndexSet<ServoUrl>, RethrowError> {
|
) -> Result<IndexSet<ServoUrl>, RethrowError> {
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
|
@ -628,17 +626,19 @@ impl ModuleTree {
|
||||||
let length = GetRequestedModulesCount(*cx, module_object);
|
let length = GetRequestedModulesCount(*cx, module_object);
|
||||||
|
|
||||||
for index in 0..length {
|
for index in 0..length {
|
||||||
rooted!(in(*cx) let specifier = GetRequestedModuleSpecifier(
|
let specifier = jsstring_to_str(
|
||||||
*cx, module_object, index
|
|
||||||
));
|
|
||||||
|
|
||||||
let url = ModuleTree::resolve_module_specifier(
|
|
||||||
*cx,
|
*cx,
|
||||||
base_url,
|
ptr::NonNull::new(GetRequestedModuleSpecifier(*cx, module_object, index))
|
||||||
specifier.handle().into_handle(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if url.is_none() {
|
rooted!(in(*cx) let mut private = UndefinedValue());
|
||||||
|
JS_GetModulePrivate(module_object.get(), private.handle_mut());
|
||||||
|
let private = private.handle().into_handle();
|
||||||
|
let script = module_script_from_reference_private(&private);
|
||||||
|
let url = ModuleTree::resolve_module_specifier(global, script, specifier, can_gc);
|
||||||
|
|
||||||
|
if url.is_err() {
|
||||||
let specifier_error =
|
let specifier_error =
|
||||||
gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
|
gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
|
||||||
|
|
||||||
|
@ -652,24 +652,111 @@ impl ModuleTree {
|
||||||
Ok(specifier_urls)
|
Ok(specifier_urls)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The following module specifiers are allowed by the spec:
|
|
||||||
/// - a valid absolute URL
|
|
||||||
/// - a valid relative URL that starts with "/", "./" or "../"
|
|
||||||
///
|
|
||||||
/// Bareword module specifiers are currently disallowed as these may be given
|
|
||||||
/// special meanings in the future.
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#resolve-a-module-specifier>
|
/// <https://html.spec.whatwg.org/multipage/#resolve-a-module-specifier>
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn resolve_module_specifier(
|
fn resolve_module_specifier(
|
||||||
cx: *mut JSContext,
|
global: &GlobalScope,
|
||||||
url: &ServoUrl,
|
script: Option<&ModuleScript>,
|
||||||
specifier: RawHandle<*mut JSString>,
|
specifier: DOMString,
|
||||||
) -> Option<ServoUrl> {
|
can_gc: CanGc,
|
||||||
let specifier_str = unsafe { jsstring_to_str(cx, ptr::NonNull::new(*specifier).unwrap()) };
|
) -> Fallible<ServoUrl> {
|
||||||
|
// Step 1~3 to get settingsObject and baseURL
|
||||||
|
let script_global = script.and_then(|s| s.owner.as_ref().map(|o| o.global()));
|
||||||
|
// Step 1. Let settingsObject and baseURL be null.
|
||||||
|
let (global, base_url): (&GlobalScope, &ServoUrl) = match script {
|
||||||
|
// Step 2. If referringScript is not null, then:
|
||||||
|
// Set settingsObject to referringScript's settings object.
|
||||||
|
// Set baseURL to referringScript's base URL.
|
||||||
|
Some(s) => (script_global.as_ref().map_or(global, |g| g), &s.base_url),
|
||||||
|
// Step 3. Otherwise:
|
||||||
|
// Set settingsObject to the current settings object.
|
||||||
|
// Set baseURL to settingsObject's API base URL.
|
||||||
|
// FIXME(#37553): Is this the correct current settings object?
|
||||||
|
None => (global, &global.api_base_url()),
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: We return the url here to keep the origianl behavior. should fix when we implement the full spec.
|
// Step 4. Let importMap be an empty import map.
|
||||||
|
// Step 5. If settingsObject's global object implements Window, then set importMap to settingsObject's
|
||||||
|
// global object's import map.
|
||||||
|
let import_map = if global.is::<Window>() {
|
||||||
|
Some(global.import_map())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 6. Let serializedBaseURL be baseURL, serialized.
|
||||||
|
let serialized_base_url = base_url.as_str();
|
||||||
// Step 7. Let asURL be the result of resolving a URL-like module specifier given specifier and baseURL.
|
// Step 7. Let asURL be the result of resolving a URL-like module specifier given specifier and baseURL.
|
||||||
Self::resolve_url_like_module_specifier(&specifier_str, url)
|
let as_url = Self::resolve_url_like_module_specifier(&specifier, base_url);
|
||||||
|
// Step 8. Let normalizedSpecifier be the serialization of asURL, if asURL is non-null;
|
||||||
|
// otherwise, specifier.
|
||||||
|
let normalized_specifier = match &as_url {
|
||||||
|
Some(url) => url.as_str(),
|
||||||
|
None => &specifier,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 9. Let result be a URL-or-null, initially null.
|
||||||
|
let mut result = None;
|
||||||
|
if let Some(map) = import_map {
|
||||||
|
// Step 10. For each scopePrefix → scopeImports of importMap's scopes:
|
||||||
|
for (prefix, imports) in &map.scopes {
|
||||||
|
// Step 10.1 If scopePrefix is serializedBaseURL, or if scopePrefix ends with U+002F (/)
|
||||||
|
// and scopePrefix is a code unit prefix of serializedBaseURL, then:
|
||||||
|
let prefix = prefix.as_str();
|
||||||
|
if prefix == serialized_base_url ||
|
||||||
|
(serialized_base_url.starts_with(prefix) && prefix.ends_with('\u{002f}'))
|
||||||
|
{
|
||||||
|
// Step 10.1.1 Let scopeImportsMatch be the result of resolving an imports match
|
||||||
|
// given normalizedSpecifier, asURL, and scopeImports.
|
||||||
|
// Step 10.1.2 If scopeImportsMatch is not null, then set result to scopeImportsMatch,
|
||||||
|
// and break.
|
||||||
|
result = resolve_imports_match(
|
||||||
|
normalized_specifier,
|
||||||
|
as_url.as_ref(),
|
||||||
|
imports,
|
||||||
|
can_gc,
|
||||||
|
)?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 11. If result is null, set result to the result of resolving an imports match given
|
||||||
|
// normalizedSpecifier, asURL, and importMap's imports.
|
||||||
|
if result.is_none() {
|
||||||
|
result = resolve_imports_match(
|
||||||
|
normalized_specifier,
|
||||||
|
as_url.as_ref(),
|
||||||
|
&map.imports,
|
||||||
|
can_gc,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 12. If result is null, set it to asURL.
|
||||||
|
if result.is_none() {
|
||||||
|
result = as_url.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 13. If result is not null, then:
|
||||||
|
match result {
|
||||||
|
Some(result) => {
|
||||||
|
// Step 13.1 Add module to resolved module set given settingsObject, serializedBaseURL,
|
||||||
|
// normalizedSpecifier, and asURL.
|
||||||
|
global.add_module_to_resolved_module_set(
|
||||||
|
serialized_base_url,
|
||||||
|
normalized_specifier,
|
||||||
|
as_url.clone(),
|
||||||
|
);
|
||||||
|
// Step 13.2 Return result.
|
||||||
|
Ok(result)
|
||||||
|
},
|
||||||
|
// Step 14. Throw a TypeError indicating that specifier was a bare specifier,
|
||||||
|
// but was not remapped to anything by importMap.
|
||||||
|
None => Err(Error::Type(
|
||||||
|
"Specifier was a bare specifier, but was not remapped to anything by importMap."
|
||||||
|
.to_owned(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#resolving-a-url-like-module-specifier>
|
/// <https://html.spec.whatwg.org/multipage/#resolving-a-url-like-module-specifier>
|
||||||
|
@ -773,12 +860,9 @@ impl ModuleTree {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
// Step 5.
|
// Step 5.
|
||||||
Some(raw_record) => self.resolve_requested_module_specifiers(
|
Some(raw_record) => {
|
||||||
&global,
|
self.resolve_requested_module_specifiers(&global, raw_record.handle(), can_gc)
|
||||||
raw_record.handle(),
|
},
|
||||||
&self.url,
|
|
||||||
can_gc,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1333,6 +1417,7 @@ unsafe extern "C" fn host_release_top_level_script(value: *const Value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
/// <https://tc39.es/ecma262/#sec-hostimportmoduledynamically>
|
||||||
/// <https://html.spec.whatwg.org/multipage/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)>
|
/// <https://html.spec.whatwg.org/multipage/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)>
|
||||||
pub(crate) unsafe extern "C" fn host_import_module_dynamically(
|
pub(crate) unsafe extern "C" fn host_import_module_dynamically(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
|
@ -1344,20 +1429,6 @@ pub(crate) unsafe extern "C" fn host_import_module_dynamically(
|
||||||
let cx = SafeJSContext::from_ptr(cx);
|
let cx = SafeJSContext::from_ptr(cx);
|
||||||
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
|
let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
|
||||||
let global_scope = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
|
let global_scope = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
|
||||||
|
|
||||||
// Step 2.
|
|
||||||
let mut base_url = global_scope.api_base_url();
|
|
||||||
|
|
||||||
// Step 3.
|
|
||||||
let mut options = ScriptFetchOptions::default_classic_script(&global_scope);
|
|
||||||
|
|
||||||
// Step 4.
|
|
||||||
let module_data = module_script_from_reference_private(&reference_private);
|
|
||||||
if let Some(data) = module_data {
|
|
||||||
base_url = data.base_url.clone();
|
|
||||||
options = data.options.descendant_fetch_options();
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise = Promise::new_with_js_promise(Handle::from_raw(promise), cx);
|
let promise = Promise::new_with_js_promise(Handle::from_raw(promise), cx);
|
||||||
|
|
||||||
//Step 5 & 6.
|
//Step 5 & 6.
|
||||||
|
@ -1365,8 +1436,6 @@ pub(crate) unsafe extern "C" fn host_import_module_dynamically(
|
||||||
&global_scope,
|
&global_scope,
|
||||||
specifier,
|
specifier,
|
||||||
reference_private,
|
reference_private,
|
||||||
base_url,
|
|
||||||
options,
|
|
||||||
promise,
|
promise,
|
||||||
CanGc::note(),
|
CanGc::note(),
|
||||||
) {
|
) {
|
||||||
|
@ -1434,18 +1503,26 @@ fn fetch_an_import_module_script_graph(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
module_request: RawHandle<*mut JSObject>,
|
module_request: RawHandle<*mut JSObject>,
|
||||||
reference_private: RawHandleValue,
|
reference_private: RawHandleValue,
|
||||||
base_url: ServoUrl,
|
|
||||||
options: ScriptFetchOptions,
|
|
||||||
promise: Rc<Promise>,
|
promise: Rc<Promise>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Result<(), RethrowError> {
|
) -> Result<(), RethrowError> {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
rooted!(in(*cx) let specifier = unsafe { GetModuleRequestSpecifier(*cx, module_request) });
|
let specifier = unsafe {
|
||||||
let url = ModuleTree::resolve_module_specifier(*cx, &base_url, specifier.handle().into());
|
jsstring_to_str(
|
||||||
|
*cx,
|
||||||
|
ptr::NonNull::new(GetModuleRequestSpecifier(*cx, module_request)).unwrap(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut options = ScriptFetchOptions::default_classic_script(global);
|
||||||
|
let module_data = unsafe { module_script_from_reference_private(&reference_private) };
|
||||||
|
if let Some(data) = module_data {
|
||||||
|
options = data.options.descendant_fetch_options();
|
||||||
|
}
|
||||||
|
let url = ModuleTree::resolve_module_specifier(global, module_data, specifier, can_gc);
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
if url.is_none() {
|
if url.is_err() {
|
||||||
let specifier_error = gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
|
let specifier_error = gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
|
||||||
return Err(specifier_error);
|
return Err(specifier_error);
|
||||||
}
|
}
|
||||||
|
@ -1494,8 +1571,8 @@ fn fetch_an_import_module_script_graph(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code, non_snake_case)]
|
#[allow(unsafe_code, non_snake_case)]
|
||||||
/// <https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule>
|
/// <https://tc39.es/ecma262/#sec-HostLoadImportedModule>
|
||||||
/// <https://html.spec.whatwg.org/multipage/#hostresolveimportedmodule(referencingscriptormodule%2C-specifier)>
|
/// <https://html.spec.whatwg.org/multipage/#hostloadimportedmodule>
|
||||||
unsafe extern "C" fn HostResolveImportedModule(
|
unsafe extern "C" fn HostResolveImportedModule(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
reference_private: RawHandleValue,
|
reference_private: RawHandleValue,
|
||||||
|
@ -1504,25 +1581,17 @@ unsafe extern "C" fn HostResolveImportedModule(
|
||||||
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
|
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
|
||||||
let global_scope = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
|
let global_scope = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
|
||||||
|
|
||||||
// Step 2.
|
|
||||||
let mut base_url = global_scope.api_base_url();
|
|
||||||
|
|
||||||
// Step 3.
|
|
||||||
let module_data = module_script_from_reference_private(&reference_private);
|
|
||||||
if let Some(data) = module_data {
|
|
||||||
base_url = data.base_url.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5.
|
// Step 5.
|
||||||
rooted!(in(*GlobalScope::get_cx()) let specifier = GetModuleRequestSpecifier(cx, specifier));
|
let module_data = module_script_from_reference_private(&reference_private);
|
||||||
let url = ModuleTree::resolve_module_specifier(
|
let specifier = jsstring_to_str(
|
||||||
*GlobalScope::get_cx(),
|
cx,
|
||||||
&base_url,
|
ptr::NonNull::new(GetModuleRequestSpecifier(cx, specifier)).unwrap(),
|
||||||
specifier.handle().into(),
|
|
||||||
);
|
);
|
||||||
|
let url =
|
||||||
|
ModuleTree::resolve_module_specifier(&global_scope, module_data, specifier, CanGc::note());
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
assert!(url.is_some());
|
assert!(url.is_ok());
|
||||||
|
|
||||||
let parsed_url = url.unwrap();
|
let parsed_url = url.unwrap();
|
||||||
|
|
||||||
|
@ -1870,6 +1939,32 @@ pub(crate) fn fetch_inline_module_script(
|
||||||
pub(crate) type ModuleSpecifierMap = IndexMap<String, Option<ServoUrl>>;
|
pub(crate) type ModuleSpecifierMap = IndexMap<String, Option<ServoUrl>>;
|
||||||
pub(crate) type ModuleIntegrityMap = IndexMap<ServoUrl, String>;
|
pub(crate) type ModuleIntegrityMap = IndexMap<ServoUrl, String>;
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record>
|
||||||
|
#[derive(Default, Eq, Hash, JSTraceable, MallocSizeOf, PartialEq)]
|
||||||
|
pub(crate) struct ResolvedModule {
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-serialized-base-url>
|
||||||
|
base_url: String,
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-specifier>
|
||||||
|
specifier: String,
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-as-url>
|
||||||
|
#[no_trace]
|
||||||
|
specifier_url: Option<ServoUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResolvedModule {
|
||||||
|
pub(crate) fn new(
|
||||||
|
base_url: String,
|
||||||
|
specifier: String,
|
||||||
|
specifier_url: Option<ServoUrl>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
base_url,
|
||||||
|
specifier,
|
||||||
|
specifier_url,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#import-map-processing-model>
|
/// <https://html.spec.whatwg.org/multipage/#import-map-processing-model>
|
||||||
#[derive(Default, JSTraceable, MallocSizeOf)]
|
#[derive(Default, JSTraceable, MallocSizeOf)]
|
||||||
pub(crate) struct ImportMap {
|
pub(crate) struct ImportMap {
|
||||||
|
@ -1910,15 +2005,52 @@ fn merge_existing_and_new_import_maps(
|
||||||
let new_import_map_scopes = new_import_map.scopes;
|
let new_import_map_scopes = new_import_map.scopes;
|
||||||
|
|
||||||
// Step 2. Let oldImportMap be global's import map.
|
// Step 2. Let oldImportMap be global's import map.
|
||||||
let mut old_import_map = global.import_map().borrow_mut();
|
let mut old_import_map = global.import_map_mut();
|
||||||
|
|
||||||
// Step 3. Let newImportMapImports be a deep copy of newImportMap's imports.
|
// Step 3. Let newImportMapImports be a deep copy of newImportMap's imports.
|
||||||
let new_import_map_imports = new_import_map.imports;
|
let mut new_import_map_imports = new_import_map.imports;
|
||||||
|
|
||||||
|
let resolved_module_set = global.resolved_module_set();
|
||||||
// Step 4. For each scopePrefix → scopeImports of newImportMapScopes:
|
// Step 4. For each scopePrefix → scopeImports of newImportMapScopes:
|
||||||
for (scope_prefix, scope_imports) in new_import_map_scopes {
|
for (scope_prefix, mut scope_imports) in new_import_map_scopes {
|
||||||
// TODO: implement after we complete `resolve_module_specifier`
|
|
||||||
// Step 4.1. For each record of global's resolved module set:
|
// Step 4.1. For each record of global's resolved module set:
|
||||||
|
for record in resolved_module_set.iter() {
|
||||||
|
// If scopePrefix is record's serialized base URL, or if scopePrefix ends with
|
||||||
|
// U+002F (/) and scopePrefix is a code unit prefix of record's serialized base URL, then:
|
||||||
|
let prefix = scope_prefix.as_str();
|
||||||
|
if prefix == record.base_url ||
|
||||||
|
(record.base_url.starts_with(prefix) && prefix.ends_with('\u{002f}'))
|
||||||
|
{
|
||||||
|
// For each specifierKey → resolutionResult of scopeImports:
|
||||||
|
scope_imports.retain(|key, val| {
|
||||||
|
// If specifierKey is record's specifier, or if all of the following conditions are true:
|
||||||
|
// specifierKey ends with U+002F (/);
|
||||||
|
// specifierKey is a code unit prefix of record's specifier;
|
||||||
|
// either record's specifier as a URL is null or is special,
|
||||||
|
if *key == record.specifier ||
|
||||||
|
(key.ends_with('\u{002f}') &&
|
||||||
|
record.specifier.starts_with(key) &&
|
||||||
|
(record.specifier_url.is_none() ||
|
||||||
|
record
|
||||||
|
.specifier_url
|
||||||
|
.as_ref()
|
||||||
|
.map(|u| u.is_special_scheme())
|
||||||
|
.unwrap_or_default()))
|
||||||
|
{
|
||||||
|
// The user agent may report a warning to the console indicating the ignored rule.
|
||||||
|
// They may choose to avoid reporting if the rule is identical to an existing one.
|
||||||
|
Console::internal_warn(
|
||||||
|
global,
|
||||||
|
DOMString::from(format!("Ignored rule: {key} -> {val:?}.")),
|
||||||
|
);
|
||||||
|
// Remove scopeImports[specifierKey].
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step 4.2 If scopePrefix exists in oldImportMap's scopes
|
// Step 4.2 If scopePrefix exists in oldImportMap's scopes
|
||||||
if old_import_map.scopes.contains_key(&scope_prefix) {
|
if old_import_map.scopes.contains_key(&scope_prefix) {
|
||||||
|
@ -1959,8 +2091,25 @@ fn merge_existing_and_new_import_maps(
|
||||||
.insert(url.clone(), integrity.clone());
|
.insert(url.clone(), integrity.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement after we complete `resolve_module_specifier`
|
|
||||||
// Step 6. For each record of global's resolved module set:
|
// Step 6. For each record of global's resolved module set:
|
||||||
|
for record in resolved_module_set.iter() {
|
||||||
|
// For each specifier → url of newImportMapImports:
|
||||||
|
new_import_map_imports.retain(|specifier, val| {
|
||||||
|
// If specifier starts with record's specifier, then:
|
||||||
|
if specifier.starts_with(&record.specifier) {
|
||||||
|
// The user agent may report a warning to the console indicating the ignored rule.
|
||||||
|
// They may choose to avoid reporting if the rule is identical to an existing one.
|
||||||
|
Console::internal_warn(
|
||||||
|
global,
|
||||||
|
DOMString::from(format!("Ignored rule: {specifier} -> {val:?}.")),
|
||||||
|
);
|
||||||
|
// Remove newImportMapImports[specifier].
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Step 7. Set oldImportMap's imports to the result of merge module specifier maps,
|
// Step 7. Set oldImportMap's imports to the result of merge module specifier maps,
|
||||||
// given newImportMapImports and oldImportMap's imports.
|
// given newImportMapImports and oldImportMap's imports.
|
||||||
|
@ -2318,3 +2467,87 @@ fn normalize_specifier_key(
|
||||||
// step 4. Return specifierKey.
|
// step 4. Return specifierKey.
|
||||||
Some(specifier_key.to_string())
|
Some(specifier_key.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#resolving-an-imports-match>
|
||||||
|
///
|
||||||
|
/// When the error is thrown, it will terminate the entire resolve a module specifier algorithm
|
||||||
|
/// without any further fallbacks.
|
||||||
|
pub(crate) fn resolve_imports_match(
|
||||||
|
normalized_specifier: &str,
|
||||||
|
as_url: Option<&ServoUrl>,
|
||||||
|
specifier_map: &ModuleSpecifierMap,
|
||||||
|
_can_gc: CanGc,
|
||||||
|
) -> Fallible<Option<ServoUrl>> {
|
||||||
|
// Step 1. For each specifierKey → resolutionResult of specifierMap:
|
||||||
|
for (specifier_key, resolution_result) in specifier_map {
|
||||||
|
// Step 1.1 If specifierKey is normalizedSpecifier, then:
|
||||||
|
if specifier_key == normalized_specifier {
|
||||||
|
if let Some(resolution_result) = resolution_result {
|
||||||
|
// Step 1.1.2 Assert: resolutionResult is a URL.
|
||||||
|
// This is checked by Url type already.
|
||||||
|
// Step 1.1.3 Return resolutionResult.
|
||||||
|
return Ok(Some(resolution_result.clone()));
|
||||||
|
} else {
|
||||||
|
// Step 1.1.1 If resolutionResult is null, then throw a TypeError.
|
||||||
|
return Err(Error::Type(
|
||||||
|
"Resolution of specifierKey was blocked by a null entry.".to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1.2 If all of the following are true:
|
||||||
|
// - specifierKey ends with U+002F (/)
|
||||||
|
// - specifierKey is a code unit prefix of normalizedSpecifier
|
||||||
|
// - either asURL is null, or asURL is special, then:
|
||||||
|
if specifier_key.ends_with('\u{002f}') &&
|
||||||
|
normalized_specifier.starts_with(specifier_key) &&
|
||||||
|
(as_url.is_none() || as_url.map(|u| u.is_special_scheme()).unwrap_or_default())
|
||||||
|
{
|
||||||
|
// Step 1.2.1 If resolutionResult is null, then throw a TypeError.
|
||||||
|
// Step 1.2.2 Assert: resolutionResult is a URL.
|
||||||
|
let Some(resolution_result) = resolution_result else {
|
||||||
|
return Err(Error::Type(
|
||||||
|
"Resolution of specifierKey was blocked by a null entry.".to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 1.2.3 Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.
|
||||||
|
let after_prefix = normalized_specifier
|
||||||
|
.strip_prefix(specifier_key)
|
||||||
|
.expect("specifier_key should be the prefix of normalized_specifier");
|
||||||
|
|
||||||
|
// Step 1.2.4 Assert: resolutionResult, serialized, ends with U+002F (/), as enforced during parsing.
|
||||||
|
debug_assert!(resolution_result.as_str().ends_with('\u{002f}'));
|
||||||
|
|
||||||
|
// Step 1.2.5 Let url be the result of URL parsing afterPrefix with resolutionResult.
|
||||||
|
let url = ServoUrl::parse_with_base(Some(resolution_result), after_prefix);
|
||||||
|
|
||||||
|
// Step 1.2.6 If url is failure, then throw a TypeError
|
||||||
|
// Step 1.2.7 Assert: url is a URL.
|
||||||
|
let Ok(url) = url else {
|
||||||
|
return Err(Error::Type(
|
||||||
|
"Resolution of normalizedSpecifier was blocked since
|
||||||
|
the afterPrefix portion could not be URL-parsed relative to
|
||||||
|
the resolutionResult mapped to by the specifierKey prefix."
|
||||||
|
.to_owned(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 1.2.8 If the serialization of resolutionResult is not
|
||||||
|
// a code unit prefix of the serialization of url, then throw a TypeError
|
||||||
|
if !url.as_str().starts_with(resolution_result.as_str()) {
|
||||||
|
return Err(Error::Type(
|
||||||
|
"Resolution of normalizedSpecifier was blocked due to
|
||||||
|
it backtracking above its prefix specifierKey."
|
||||||
|
.to_owned(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1.2.9 Return url.
|
||||||
|
return Ok(Some(url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2. Return null.
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
|
@ -105,6 +105,17 @@ impl ServoUrl {
|
||||||
scheme == "about" || scheme == "blob" || scheme == "data"
|
scheme == "about" || scheme == "blob" || scheme == "data"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://url.spec.whatwg.org/#special-scheme>
|
||||||
|
pub fn is_special_scheme(&self) -> bool {
|
||||||
|
let scheme = self.scheme();
|
||||||
|
scheme == "ftp" ||
|
||||||
|
scheme == "file" ||
|
||||||
|
scheme == "http" ||
|
||||||
|
scheme == "https" ||
|
||||||
|
scheme == "ws" ||
|
||||||
|
scheme == "wss"
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
self.0.as_str()
|
self.0.as_str()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[dynamic-import.html]
|
|
||||||
[After a dynamic import(), import maps work fine]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[modulepreload-link-header.html]
|
|
||||||
[With modulepreload link header, import maps work fine]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[modulepreload.html]
|
|
||||||
[After <link rel=modulepreload> import maps should work fine]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[script-tag-inline.html]
|
|
||||||
[After inline <script type="module"> import maps work fine]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[script-tag.html]
|
|
||||||
[After <script type="module"> import maps work fine]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[worker-request.html]
|
|
||||||
[After module worker creation import maps are still effective]
|
|
||||||
expected: FAIL
|
|
|
@ -1,27 +0,0 @@
|
||||||
[bare-specifiers.sub.html]
|
|
||||||
[bare/bare: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/cross-origin-bare: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/cross-origin-bare: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/cross-origin-bare: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/to-data: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/to-data: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/to-data: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
|
@ -1,6 +0,0 @@
|
||||||
[applied-to-target-dynamic.sub.html]
|
|
||||||
[The URL after mapping violates CSP (but not the URL before mapping)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[The URL before mapping violates CSP (but not the URL after mapping)]
|
|
||||||
expected: FAIL
|
|
|
@ -1,6 +0,0 @@
|
||||||
[applied-to-target.sub.html]
|
|
||||||
[The URL after mapping violates CSP (but not the URL before mapping)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[The URL before mapping violates CSP (but not the URL after mapping)]
|
|
||||||
expected: FAIL
|
|
3
tests/wpt/meta/import-maps/csp/hash.html.ini
vendored
3
tests/wpt/meta/import-maps/csp/hash.html.ini
vendored
|
@ -1,3 +0,0 @@
|
||||||
[hash.html]
|
|
||||||
[Importmap should be accepted due to hash]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[nonce.html]
|
|
||||||
[Importmap should be accepted according to its correct nonce]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[unsafe-inline.html]
|
|
||||||
[Importmap should be accepted due to unsafe-inline]
|
|
||||||
expected: FAIL
|
|
|
@ -1,36 +0,0 @@
|
||||||
[data-url-specifiers.sub.html]
|
|
||||||
[data:text/javascript,log.push('data:foo'): static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:foo'): dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:foo'): dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:cross-origin-foo'): static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:cross-origin-foo'): dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:cross-origin-foo'): dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-data'): static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-data'): dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-data'): dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-bare'): static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-bare'): dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[data:text/javascript,log.push('data:to-bare'): dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
|
@ -2,14 +2,11 @@
|
||||||
[script was not loaded, as its resolved URL failed its integrity check]
|
[script was not loaded, as its resolved URL failed its integrity check]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[script was loaded, as its resolved URL had no integrity check, despite its specifier having one]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Script with no import definition was not loaded, as it failed its integrity check]
|
[Script with no import definition was not loaded, as it failed its integrity check]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Bare specifier used for integrity loaded, as its definition should have used the URL]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Script imported inside an event handler was not loaded as its integrity check failed]
|
[Script imported inside an event handler was not loaded as its integrity check failed]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[Bare specifier script was not loaded, as it failed its integrity check]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
[http-url-like-specifiers.sub.html]
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=foo: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=cross-origin-foo: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-data: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[http://web-platform.test:8000/import-maps/resources/log.js?pipe=sub&name=to-bare: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
|
@ -1,18 +0,0 @@
|
||||||
[import-maps-base-url.sub.html]
|
|
||||||
[bare/bare: static import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from module)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from text/javascript)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: static import with inject <base>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from module) with inject <base>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[bare/bare: dynamic import (from text/javascript) with inject <base>]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[module-map-key.html]
|
|
||||||
[Module map's key is the URL after import map resolution]
|
|
||||||
expected: FAIL
|
|
2
tests/wpt/meta/import-maps/multiple-import-maps/already-resolved-dropped.html.ini
vendored
Normal file
2
tests/wpt/meta/import-maps/multiple-import-maps/already-resolved-dropped.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[already-resolved-dropped.html]
|
||||||
|
expected: CRASH
|
|
@ -1,3 +0,0 @@
|
||||||
[basic.html]
|
|
||||||
[Second import map should be used for resolution]
|
|
||||||
expected: FAIL
|
|
|
@ -1,9 +0,0 @@
|
||||||
[conflict-first-persists.html]
|
|
||||||
[First defined rule persists in case of conflict]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[First defined rule persists in case of conflict - prefixed bare specifiers]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[First defined rule persists in case of conflict - non-prefix bare specifier]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[resolution-consistency-in-module-tree-inline.html]
|
|
||||||
[Module tree that started to download before a new import map should still take it into account]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[resolution-consistency-in-module-tree.html]
|
|
||||||
[Module tree that started to download before a new import map should still take it into account]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[url-resolution-conflict.html]
|
|
||||||
[Second import map should not override same resolved URL]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +0,0 @@
|
||||||
[with-errors.html]
|
|
||||||
[Second import map should be used for resolution even after an import map with errors]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +1,4 @@
|
||||||
[dynamic.html]
|
[dynamic.html]
|
||||||
|
expected: CRASH
|
||||||
[Resolution after import map should not be redefined]
|
[Resolution after import map should not be redefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -1,2 +1,9 @@
|
||||||
[external-script-bare-descendent.html]
|
[external-script-bare-descendent.html]
|
||||||
expected: ERROR
|
[Resolution after import map should not be redefined]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Resolution after import map should not be redefined for bare prefixes or exact matches]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Resolution after import map should be redefined for non-prefixes]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[integrity.html]
|
|
||||||
[Static script loaded as its integrity check passed]
|
|
||||||
expected: FAIL
|
|
|
@ -1,3 +1,4 @@
|
||||||
[prefix.html]
|
[prefix.html]
|
||||||
|
expected: CRASH
|
||||||
[Prefix resolution after import map should not be redefined]
|
[Prefix resolution after import map should not be redefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
[Static script did not load as it failed its integrity check]
|
[Static script did not load as it failed its integrity check]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Static script loaded as its integrity check passed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Static script did not load as it failed its integrity check, even without an import defined]
|
[Static script did not load as it failed its integrity check, even without an import defined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[script-enforcement-006.html]
|
|
||||||
[Untrusted HTMLScriptElement of importmap type uses the source text returned by the default policy.]
|
|
||||||
expected: FAIL
|
|
|
@ -1,6 +1,3 @@
|
||||||
[script-enforcement-008.https.html]
|
[script-enforcement-008.https.html]
|
||||||
[script-src CSP directive is properly set.]
|
[script-src CSP directive is properly set.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Untrusted HTMLScriptElement of importmap type uses the source text returned by the default policy for inline CSP check.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue