script: support JSON modules (#42138)

With import attributes enabled we can now support non javascript
modules, for now we are limited to json ones.
Switch `GlobalScope` `modulemap` to be keyed by the tuple url and
module's type.

Testing: Enabled a new directory, new tests should pass

---------

Signed-off-by: Gae24 <96017547+Gae24@users.noreply.github.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Gae24
2026-01-31 02:18:51 +01:00
committed by GitHub
parent 58b56edf97
commit 9c4d17e9e1
18 changed files with 221 additions and 179 deletions

View File

@@ -13,12 +13,12 @@ use std::collections::HashSet;
use std::rc::Rc;
use js::conversions::jsstr_to_string;
use js::jsapi::{HandleValue as RawHandleValue, IsCyclicModule, JSObject};
use js::jsapi::{HandleValue as RawHandleValue, IsCyclicModule, JSObject, ModuleType};
use js::jsval::{ObjectValue, UndefinedValue};
use js::realm::CurrentRealm;
use js::rust::wrappers::{
GetModuleNamespace, GetRequestedModuleSpecifier, GetRequestedModulesCount, JS_GetModulePrivate,
ModuleEvaluate,
GetModuleNamespace, GetRequestedModuleSpecifier, GetRequestedModuleType,
GetRequestedModulesCount, JS_GetModulePrivate, ModuleEvaluate,
};
use js::rust::{HandleValue, IntoHandle};
use net_traits::request::{Destination, Referrer};
@@ -145,6 +145,7 @@ fn inner_module_loading(
// i. If AllImportAttributesSupported(request.[[Attributes]]) is false, then
// Note: Gecko will call hasFirstUnsupportedAttributeKey on each module request,
// GetRequestedModuleSpecifier will do it for us.
// In addition it will also check if specifier has an unknown module type.
let jsstr = unsafe { GetRequestedModuleSpecifier(*cx, module_handle, index) };
if jsstr.is_null() {
@@ -164,10 +165,12 @@ fn inner_module_loading(
} else {
let specifier =
unsafe { jsstr_to_string(*cx, std::ptr::NonNull::new(jsstr).unwrap()) };
let module_type = unsafe { GetRequestedModuleType(*cx, module_handle, index) };
// ii. Else if module.[[LoadedModules]] contains a LoadedModuleRequest Record record
// such that ModuleRequestsEqual(record, request) is true, then
let loaded_module = module.find_descendant_inside_module_map(global, &specifier);
let loaded_module =
module.find_descendant_inside_module_map(global, &specifier, module_type);
match loaded_module {
// 1. Perform InnerModuleLoading(state, record.[[Module]]).
@@ -183,6 +186,7 @@ fn inner_module_loading(
Some(module.clone()),
referrer.handle().into_handle(),
specifier,
module_type,
state.load_state.clone(),
Payload::GraphRecord(state.clone()),
);
@@ -407,6 +411,7 @@ pub(crate) fn host_load_imported_module(
referrer_module: Option<Rc<ModuleTree>>,
referrer: RawHandleValue,
specifier: String,
module_type: ModuleType,
load_state: Option<Rc<LoadState>>,
payload: Payload,
) {
@@ -541,12 +546,14 @@ pub(crate) fn host_load_imported_module(
// Step 14 Fetch a single imported module script given url, fetchClient, destination, fetchOptions, settingsObject,
// fetchReferrer, moduleRequest, and onSingleFetchComplete as defined below.
// If loadState is not undefined and loadState.[[PerformFetch]] is not null, pass loadState.[[PerformFetch]] along as well.
// Note: we don't have access to the requested `ModuleObject`, so we pass only its type.
fetch_a_single_imported_module_script(
url.unwrap(),
fetch_client,
destination,
fetch_options,
fetch_referrer,
module_type,
on_single_fetch_complete,
);
}
@@ -558,6 +565,7 @@ fn fetch_a_single_imported_module_script(
destination: Destination,
options: ScriptFetchOptions,
referrer: Referrer,
module_type: ModuleType,
on_complete: impl FnOnce(Option<Rc<ModuleTree>>) + 'static,
) {
// TODO Step 1. Assert: moduleRequest.[[Attributes]] does not contain any Record entry such that entry.[[Key]] is not "type",
@@ -565,8 +573,12 @@ fn fetch_a_single_imported_module_script(
// TODO Step 2. Let moduleType be the result of running the module type from module request steps given moduleRequest.
// TODO Step 3. If the result of running the module type allowed steps given moduleType and settingsObject is false,
// Step 3. If the result of running the module type allowed steps given moduleType and settingsObject is false,
// then run onComplete given null, and return.
match module_type {
ModuleType::Unknown => return on_complete(None),
ModuleType::JavaScript | ModuleType::JSON => (),
}
// Step 4. Fetch a single module script given url, fetchClient, destination, options, settingsObject, referrer,
// moduleRequest, false, and onComplete. If performFetch was given, pass it along as well.
@@ -576,6 +588,7 @@ fn fetch_a_single_imported_module_script(
destination,
options,
referrer,
Some(module_type),
false,
Some(IntroductionType::IMPORTED_MODULE),
on_complete,