feat(script): add resolve_url_like_module_specifier to ModuleTree (#37340)

adding `resolve_url_like_module_specifier` method to `ModuleTree`.

Testing: Existing WPT test for script element should pass.
Fixes: https://github.com/servo/servo/issues/37316, resolving a URL-like
module specifier

Signed-off-by: Jason Tsai <git@pews.dev>
This commit is contained in:
Jason Tsai 2025-06-10 07:30:58 +09:00 committed by GitHub
parent 591057b9af
commit ed09a0ff52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -43,7 +43,6 @@ use net_traits::{
ResourceFetchTiming, ResourceTimingType, ResourceFetchTiming, ResourceTimingType,
}; };
use servo_url::ServoUrl; use servo_url::ServoUrl;
use url::ParseError as UrlParseError;
use uuid::Uuid; use uuid::Uuid;
use crate::document_loader::LoadType; use crate::document_loader::LoadType;
@ -634,7 +633,7 @@ impl ModuleTree {
specifier.handle().into_handle(), specifier.handle().into_handle(),
); );
if url.is_err() { if url.is_none() {
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);
@ -660,24 +659,28 @@ impl ModuleTree {
cx: *mut JSContext, cx: *mut JSContext,
url: &ServoUrl, url: &ServoUrl,
specifier: RawHandle<*mut JSString>, specifier: RawHandle<*mut JSString>,
) -> Result<ServoUrl, UrlParseError> { ) -> Option<ServoUrl> {
let specifier_str = unsafe { jsstring_to_str(cx, ptr::NonNull::new(*specifier).unwrap()) }; let specifier_str = unsafe { jsstring_to_str(cx, ptr::NonNull::new(*specifier).unwrap()) };
// Step 1. // TODO: We return the url here to keep the origianl behavior. should fix when we implement the full spec.
if let Ok(specifier_url) = ServoUrl::parse(&specifier_str) { // Step 7. Let asURL be the result of resolving a URL-like module specifier given specifier and baseURL.
return Ok(specifier_url); Self::resolve_url_like_module_specifier(&specifier_str, url)
} }
// Step 2. /// <https://html.spec.whatwg.org/multipage/#resolving-a-url-like-module-specifier>
if !specifier_str.starts_with('/') && fn resolve_url_like_module_specifier(
!specifier_str.starts_with("./") && specifier: &DOMString,
!specifier_str.starts_with("../") base_url: &ServoUrl,
) -> Option<ServoUrl> {
// Step 1. If specifier starts with "/", "./", or "../", then:
if specifier.starts_with('/') || specifier.starts_with("./") || specifier.starts_with("../")
{ {
return Err(UrlParseError::InvalidDomainCharacter); // Step 1.1. Let url be the result of URL parsing specifier with baseURL.
return ServoUrl::parse_with_base(Some(base_url), specifier).ok();
} }
// Step 3. // Step 2. Let url be the result of URL parsing specifier (with no base URL).
ServoUrl::parse_with_base(Some(url), &specifier_str) ServoUrl::parse_with_base(None, specifier).ok()
} }
/// <https://html.spec.whatwg.org/multipage/#finding-the-first-parse-error> /// <https://html.spec.whatwg.org/multipage/#finding-the-first-parse-error>
@ -1437,7 +1440,7 @@ fn fetch_an_import_module_script_graph(
let url = ModuleTree::resolve_module_specifier(*cx, &base_url, specifier.handle().into()); let url = ModuleTree::resolve_module_specifier(*cx, &base_url, specifier.handle().into());
// Step 2. // Step 2.
if url.is_err() { if url.is_none() {
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);
} }
@ -1514,7 +1517,7 @@ unsafe extern "C" fn HostResolveImportedModule(
); );
// Step 6. // Step 6.
assert!(url.is_ok()); assert!(url.is_some());
let parsed_url = url.unwrap(); let parsed_url = url.unwrap();