mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
feat: Add support for import assertions and JSON modules (#12866)
This commit adds proper support for import assertions and JSON modules. Implementation of "core/modules.rs" was changed to account for multiple possible module types, instead of always assuming that the code is an "ES module". In effect "ModuleMap" now has knowledge about each modules' type (stored via "ModuleType" enum). Module loading pipeline now stores information about expected module type for each request and validates that expected type matches discovered module type based on file's "MediaType". Relevant tests were added to "core/modules.rs" and integration tests, additionally multiple WPT tests were enabled. There are still some rough edges in the implementation and not all WPT were enabled, due to: a) unclear BOM handling in source code by "FileFetcher" b) design limitation of Deno's "FileFetcher" that doesn't download the same module multiple times in a single run Co-authored-by: Kitson Kelly <me@kitsonkelly.com>
This commit is contained in:
parent
ec7d90666f
commit
a1f0796fcc
28 changed files with 916 additions and 228 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -836,9 +836,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_graph"
|
||||
version = "0.14.0"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b72e7615cd00e7c9b93d804fad6c2a25c9c40a647bf3b5cf857f91aa4c107792"
|
||||
checksum = "8f3280596f5b5825b0363142b72fe2786163905c61dfeb18bd5db1c390a94093"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if 1.0.0",
|
||||
|
|
|
@ -104,6 +104,7 @@ pub const IGNORED_COMPILER_OPTIONS: &[&str] = &[
|
|||
"paths",
|
||||
"preserveConstEnums",
|
||||
"reactNamespace",
|
||||
"resolveJsonModule",
|
||||
"rootDir",
|
||||
"rootDirs",
|
||||
"skipLibCheck",
|
||||
|
|
24
cli/emit.rs
24
cli/emit.rs
|
@ -153,6 +153,7 @@ pub(crate) fn get_ts_config(
|
|||
"isolatedModules": true,
|
||||
"lib": lib,
|
||||
"module": "esnext",
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"tsBuildInfoFile": "deno:///.tsbuildinfo",
|
||||
|
@ -186,6 +187,7 @@ pub(crate) fn get_ts_config(
|
|||
"jsx": "react",
|
||||
"jsxFactory": "React.createElement",
|
||||
"jsxFragmentFactory": "React.Fragment",
|
||||
"resolveJsonModule": true,
|
||||
})),
|
||||
ConfigType::RuntimeEmit { tsc_emit } => {
|
||||
let mut ts_config = TsConfig::new(json!({
|
||||
|
@ -403,14 +405,15 @@ pub(crate) fn check_and_maybe_emit(
|
|||
log::debug!("module missing, skipping emit for {}", specifier);
|
||||
continue;
|
||||
};
|
||||
// Sometimes if `tsc` sees a CommonJS file it will _helpfully_ output it
|
||||
// to ESM, which we don't really want to do unless someone has enabled
|
||||
// check_js.
|
||||
if !check_js
|
||||
&& matches!(
|
||||
media_type,
|
||||
MediaType::JavaScript | MediaType::Cjs | MediaType::Mjs
|
||||
)
|
||||
// Sometimes if `tsc` sees a CommonJS file or a JSON module, it will
|
||||
// _helpfully_ output it, which we don't really want to do unless
|
||||
// someone has enabled check_js.
|
||||
if matches!(media_type, MediaType::Json)
|
||||
|| (!check_js
|
||||
&& matches!(
|
||||
media_type,
|
||||
MediaType::JavaScript | MediaType::Cjs | MediaType::Mjs
|
||||
))
|
||||
{
|
||||
log::debug!("skipping emit for {}", specifier);
|
||||
continue;
|
||||
|
@ -429,7 +432,10 @@ pub(crate) fn check_and_maybe_emit(
|
|||
MediaType::Dts | MediaType::Dcts | MediaType::Dmts => {
|
||||
cache.set(CacheType::Declaration, &specifier, emit.data)?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
_ => unreachable!(
|
||||
"unexpected media_type {} {}",
|
||||
emit.media_type, specifier
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -569,6 +569,7 @@ impl Inner {
|
|||
"lib": ["deno.ns", "deno.window"],
|
||||
"module": "esnext",
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true,
|
||||
|
|
|
@ -31,6 +31,7 @@ use deno_core::url::Url;
|
|||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::ModuleSource;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::ModuleType;
|
||||
use deno_core::SharedArrayBufferStore;
|
||||
use deno_graph::create_graph;
|
||||
use deno_graph::Dependency;
|
||||
|
@ -68,6 +69,7 @@ pub struct ProcState(Arc<Inner>);
|
|||
enum ModuleEntry {
|
||||
Module {
|
||||
code: String,
|
||||
media_type: MediaType,
|
||||
dependencies: BTreeMap<String, Dependency>,
|
||||
},
|
||||
Error(ModuleGraphError),
|
||||
|
@ -584,6 +586,7 @@ impl ProcState {
|
|||
| MediaType::Unknown
|
||||
| MediaType::Cjs
|
||||
| MediaType::Mjs
|
||||
| MediaType::Json
|
||||
) {
|
||||
module.maybe_source().unwrap_or("").to_string()
|
||||
// The emit may also be missing when a declaration file is in the
|
||||
|
@ -602,7 +605,11 @@ impl ProcState {
|
|||
module.maybe_dependencies().cloned().unwrap_or_default();
|
||||
graph_data.modules.insert(
|
||||
specifier.clone(),
|
||||
ModuleEntry::Module { code, dependencies },
|
||||
ModuleEntry::Module {
|
||||
code,
|
||||
dependencies,
|
||||
media_type: *media_type,
|
||||
},
|
||||
);
|
||||
if let Some(dependencies) = module.maybe_dependencies() {
|
||||
for dep in dependencies.values() {
|
||||
|
@ -724,10 +731,16 @@ impl ProcState {
|
|||
_ => &specifier,
|
||||
};
|
||||
match graph_data.modules.get(found_specifier) {
|
||||
Some(ModuleEntry::Module { code, .. }) => Ok(ModuleSource {
|
||||
Some(ModuleEntry::Module {
|
||||
code, media_type, ..
|
||||
}) => Ok(ModuleSource {
|
||||
code: code.clone(),
|
||||
module_url_specified: specifier.to_string(),
|
||||
module_url_found: found_specifier.to_string(),
|
||||
module_type: match media_type {
|
||||
MediaType::Json => ModuleType::Json,
|
||||
_ => ModuleType::JavaScript,
|
||||
},
|
||||
}),
|
||||
_ => Err(anyhow!(
|
||||
"Loading unprepared module: {}",
|
||||
|
|
|
@ -164,6 +164,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
|
||||
Ok(deno_core::ModuleSource {
|
||||
code,
|
||||
module_type: deno_core::ModuleType::JavaScript,
|
||||
module_url_specified: module_specifier.to_string(),
|
||||
module_url_found: module_specifier.to_string(),
|
||||
})
|
||||
|
|
|
@ -2407,3 +2407,36 @@ fn issue12807() {
|
|||
.unwrap();
|
||||
assert!(status.success());
|
||||
}
|
||||
|
||||
itest!(import_assertions_static_import {
|
||||
args: "run --allow-read import_assertions/static_import.ts",
|
||||
output: "import_assertions/static_import.out",
|
||||
});
|
||||
|
||||
itest!(import_assertions_static_export {
|
||||
args: "run --allow-read import_assertions/static_export.ts",
|
||||
output: "import_assertions/static_export.out",
|
||||
});
|
||||
|
||||
itest!(import_assertions_static_error {
|
||||
args: "run --allow-read import_assertions/static_error.ts",
|
||||
output: "import_assertions/static_error.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(import_assertions_dynamic_import {
|
||||
args: "run --allow-read import_assertions/dynamic_import.ts",
|
||||
output: "import_assertions/dynamic_import.out",
|
||||
});
|
||||
|
||||
itest!(import_assertions_dynamic_error {
|
||||
args: "run --allow-read import_assertions/dynamic_error.ts",
|
||||
output: "import_assertions/dynamic_error.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(import_assertions_type_check {
|
||||
args: "run --allow-read import_assertions/type_check.ts",
|
||||
output: "import_assertions/type_check.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
|
6
cli/tests/testdata/import_assertions/data.json
vendored
Normal file
6
cli/tests/testdata/import_assertions/data.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"a": "b",
|
||||
"c": {
|
||||
"d": 10
|
||||
}
|
||||
}
|
5
cli/tests/testdata/import_assertions/dynamic_error.out
vendored
Normal file
5
cli/tests/testdata/import_assertions/dynamic_error.out
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
[WILDCARD]
|
||||
error: Uncaught (in promise) TypeError: Expected a "JavaScript" module but loaded a "JSON" module.
|
||||
const data = await import("./data.json");
|
||||
^
|
||||
at async [WILDCARD]dynamic_error.ts:1:14
|
3
cli/tests/testdata/import_assertions/dynamic_error.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/dynamic_error.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
const data = await import("./data.json");
|
||||
|
||||
console.log(data);
|
2
cli/tests/testdata/import_assertions/dynamic_import.out
vendored
Normal file
2
cli/tests/testdata/import_assertions/dynamic_import.out
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[WILDCARD]
|
||||
Module { default: { a: "b", c: { d: 10 } } }
|
3
cli/tests/testdata/import_assertions/dynamic_import.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/dynamic_import.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
const data = await import("./data.json", { assert: { type: "json" } });
|
||||
|
||||
console.log(data);
|
5
cli/tests/testdata/import_assertions/static_error.out
vendored
Normal file
5
cli/tests/testdata/import_assertions/static_error.out
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
[WILDCARD]
|
||||
error: An unsupported media type was attempted to be imported as a module.
|
||||
Specifier: [WILDCARD]data.json
|
||||
MediaType: Json
|
||||
at [WILDCARD]static_error.ts:1:18
|
3
cli/tests/testdata/import_assertions/static_error.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/static_error.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import data from "./data.json";
|
||||
|
||||
console.log(data);
|
2
cli/tests/testdata/import_assertions/static_export.out
vendored
Normal file
2
cli/tests/testdata/import_assertions/static_export.out
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[WILDCARD]
|
||||
{ a: "b", c: { d: 10 } }
|
3
cli/tests/testdata/import_assertions/static_export.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/static_export.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import data from "./static_reexport.ts";
|
||||
|
||||
console.log(data);
|
2
cli/tests/testdata/import_assertions/static_import.out
vendored
Normal file
2
cli/tests/testdata/import_assertions/static_import.out
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[WILDCARD]
|
||||
{ a: "b", c: { d: 10 } }
|
3
cli/tests/testdata/import_assertions/static_import.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/static_import.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import data from "./data.json" assert { type: "json" };
|
||||
|
||||
console.log(data);
|
1
cli/tests/testdata/import_assertions/static_reexport.ts
vendored
Normal file
1
cli/tests/testdata/import_assertions/static_reexport.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export { default } from "./data.json" assert { type: "json" };
|
5
cli/tests/testdata/import_assertions/type_check.out
vendored
Normal file
5
cli/tests/testdata/import_assertions/type_check.out
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
[WILDCARD]
|
||||
error: TS2339 [ERROR]: Property 'foo' does not exist on type '{ a: string; c: { d: number; }; }'.
|
||||
console.log(data.foo);
|
||||
~~~
|
||||
at [WILDCARD]type_check.ts:3:18
|
3
cli/tests/testdata/import_assertions/type_check.ts
vendored
Normal file
3
cli/tests/testdata/import_assertions/type_check.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
import data from "./data.json" assert { type: "json" };
|
||||
|
||||
console.log(data.foo);
|
20
cli/tsc.rs
20
cli/tsc.rs
|
@ -352,6 +352,24 @@ struct LoadArgs {
|
|||
specifier: String,
|
||||
}
|
||||
|
||||
fn as_ts_script_kind(media_type: &MediaType) -> i32 {
|
||||
match media_type {
|
||||
MediaType::JavaScript => 1,
|
||||
MediaType::Jsx => 2,
|
||||
MediaType::Mjs => 1,
|
||||
MediaType::Cjs => 1,
|
||||
MediaType::TypeScript => 3,
|
||||
MediaType::Mts => 3,
|
||||
MediaType::Cts => 3,
|
||||
MediaType::Dts => 3,
|
||||
MediaType::Dmts => 3,
|
||||
MediaType::Dcts => 3,
|
||||
MediaType::Tsx => 4,
|
||||
MediaType::Json => 6,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn op_load(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
||||
let v: LoadArgs = serde_json::from_value(args)
|
||||
.context("Invalid request from JavaScript for \"op_load\".")?;
|
||||
|
@ -395,7 +413,7 @@ fn op_load(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
|||
};
|
||||
|
||||
Ok(
|
||||
json!({ "data": data, "hash": hash, "scriptKind": media_type.as_ts_script_kind() }),
|
||||
json!({ "data": data, "hash": hash, "scriptKind": as_ts_script_kind(&media_type) }),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::error::is_instance_of_error;
|
||||
use crate::modules::get_module_type_from_assertions;
|
||||
use crate::modules::parse_import_assertions;
|
||||
use crate::modules::validate_import_assertions;
|
||||
use crate::modules::ImportAssertionsKind;
|
||||
use crate::modules::ModuleMap;
|
||||
use crate::resolve_url_or_path;
|
||||
use crate::JsRuntime;
|
||||
|
@ -243,7 +247,7 @@ pub extern "C" fn host_import_module_dynamically_callback(
|
|||
context: v8::Local<v8::Context>,
|
||||
referrer: v8::Local<v8::ScriptOrModule>,
|
||||
specifier: v8::Local<v8::String>,
|
||||
_import_assertions: v8::Local<v8::FixedArray>,
|
||||
import_assertions: v8::Local<v8::FixedArray>,
|
||||
) -> *mut v8::Promise {
|
||||
let scope = &mut unsafe { v8::CallbackScope::new(context) };
|
||||
|
||||
|
@ -267,6 +271,22 @@ pub extern "C" fn host_import_module_dynamically_callback(
|
|||
let resolver = v8::PromiseResolver::new(scope).unwrap();
|
||||
let promise = resolver.get_promise(scope);
|
||||
|
||||
let assertions = parse_import_assertions(
|
||||
scope,
|
||||
import_assertions,
|
||||
ImportAssertionsKind::DynamicImport,
|
||||
);
|
||||
|
||||
{
|
||||
let tc_scope = &mut v8::TryCatch::new(scope);
|
||||
validate_import_assertions(tc_scope, &assertions);
|
||||
if tc_scope.has_caught() {
|
||||
let e = tc_scope.exception().unwrap();
|
||||
resolver.reject(tc_scope, e);
|
||||
}
|
||||
}
|
||||
let module_type = get_module_type_from_assertions(&assertions);
|
||||
|
||||
let resolver_handle = v8::Global::new(scope, resolver);
|
||||
{
|
||||
let state_rc = JsRuntime::state(scope);
|
||||
|
@ -280,6 +300,7 @@ pub extern "C" fn host_import_module_dynamically_callback(
|
|||
module_map_rc,
|
||||
&specifier_str,
|
||||
&referrer_name_str,
|
||||
module_type,
|
||||
resolver_handle,
|
||||
);
|
||||
state_rc.borrow_mut().notify_new_dynamic_import();
|
||||
|
@ -294,13 +315,29 @@ pub extern "C" fn host_import_module_dynamically_callback(
|
|||
_rv: v8::ReturnValue| {
|
||||
let arg = args.get(0);
|
||||
if is_instance_of_error(scope, arg) {
|
||||
let e: crate::error::NativeJsError =
|
||||
serde_v8::from_v8(scope, arg).unwrap();
|
||||
let name = e.name.unwrap_or_else(|| "Error".to_string());
|
||||
let message = v8::Exception::create_message(scope, arg);
|
||||
if message.get_stack_trace(scope).unwrap().get_frame_count() == 0 {
|
||||
let arg: v8::Local<v8::Object> = arg.try_into().unwrap();
|
||||
let message_key = v8::String::new(scope, "message").unwrap();
|
||||
let message = arg.get(scope, message_key.into()).unwrap();
|
||||
let exception =
|
||||
v8::Exception::type_error(scope, message.try_into().unwrap());
|
||||
let exception = match name.as_str() {
|
||||
"RangeError" => {
|
||||
v8::Exception::range_error(scope, message.try_into().unwrap())
|
||||
}
|
||||
"TypeError" => {
|
||||
v8::Exception::type_error(scope, message.try_into().unwrap())
|
||||
}
|
||||
"SyntaxError" => {
|
||||
v8::Exception::syntax_error(scope, message.try_into().unwrap())
|
||||
}
|
||||
"ReferenceError" => {
|
||||
v8::Exception::reference_error(scope, message.try_into().unwrap())
|
||||
}
|
||||
_ => v8::Exception::error(scope, message.try_into().unwrap()),
|
||||
};
|
||||
let code_key = v8::String::new(scope, "code").unwrap();
|
||||
let code_value =
|
||||
v8::String::new(scope, "ERR_MODULE_NOT_FOUND").unwrap();
|
||||
|
@ -1311,7 +1348,7 @@ fn create_host_object(
|
|||
pub fn module_resolve_callback<'s>(
|
||||
context: v8::Local<'s, v8::Context>,
|
||||
specifier: v8::Local<'s, v8::String>,
|
||||
_import_assertions: v8::Local<'s, v8::FixedArray>,
|
||||
import_assertions: v8::Local<'s, v8::FixedArray>,
|
||||
referrer: v8::Local<'s, v8::Module>,
|
||||
) -> Option<v8::Local<'s, v8::Module>> {
|
||||
let scope = &mut unsafe { v8::CallbackScope::new(context) };
|
||||
|
@ -1328,8 +1365,17 @@ pub fn module_resolve_callback<'s>(
|
|||
|
||||
let specifier_str = specifier.to_rust_string_lossy(scope);
|
||||
|
||||
let maybe_module =
|
||||
module_map.resolve_callback(scope, &specifier_str, &referrer_name);
|
||||
let assertions = parse_import_assertions(
|
||||
scope,
|
||||
import_assertions,
|
||||
ImportAssertionsKind::StaticImport,
|
||||
);
|
||||
let maybe_module = module_map.resolve_callback(
|
||||
scope,
|
||||
&specifier_str,
|
||||
&referrer_name,
|
||||
assertions,
|
||||
);
|
||||
if let Some(module) = maybe_module {
|
||||
return Some(module);
|
||||
}
|
||||
|
|
|
@ -158,9 +158,9 @@ fn get_property<'a>(
|
|||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct NativeJsError {
|
||||
name: Option<String>,
|
||||
message: Option<String>,
|
||||
pub(crate) struct NativeJsError {
|
||||
pub name: Option<String>,
|
||||
pub message: Option<String>,
|
||||
// Warning! .stack is special so handled by itself
|
||||
// stack: Option<String>,
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ pub use crate::modules::ModuleLoadId;
|
|||
pub use crate::modules::ModuleLoader;
|
||||
pub use crate::modules::ModuleSource;
|
||||
pub use crate::modules::ModuleSourceFuture;
|
||||
pub use crate::modules::ModuleType;
|
||||
pub use crate::modules::NoopModuleLoader;
|
||||
pub use crate::runtime::CompiledWasmModuleStore;
|
||||
pub use crate::runtime::SharedArrayBufferStore;
|
||||
|
|
868
core/modules.rs
868
core/modules.rs
File diff suppressed because it is too large
Load diff
|
@ -1259,12 +1259,15 @@ impl JsRuntime {
|
|||
|
||||
if let Some(load_stream_result) = maybe_result {
|
||||
match load_stream_result {
|
||||
Ok(info) => {
|
||||
Ok((request, info)) => {
|
||||
// A module (not necessarily the one dynamically imported) has been
|
||||
// fetched. Create and register it, and if successful, poll for the
|
||||
// next recursive-load event related to this dynamic import.
|
||||
let register_result =
|
||||
load.register_and_recurse(&mut self.handle_scope(), &info);
|
||||
let register_result = load.register_and_recurse(
|
||||
&mut self.handle_scope(),
|
||||
&request,
|
||||
&info,
|
||||
);
|
||||
|
||||
match register_result {
|
||||
Ok(()) => {
|
||||
|
@ -1417,7 +1420,7 @@ impl JsRuntime {
|
|||
) -> Result<ModuleId, Error> {
|
||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||
if let Some(code) = code {
|
||||
module_map_rc.borrow_mut().new_module(
|
||||
module_map_rc.borrow_mut().new_es_module(
|
||||
&mut self.handle_scope(),
|
||||
// main module
|
||||
true,
|
||||
|
@ -1429,10 +1432,10 @@ impl JsRuntime {
|
|||
let mut load =
|
||||
ModuleMap::load_main(module_map_rc.clone(), specifier.as_str()).await?;
|
||||
|
||||
while let Some(info_result) = load.next().await {
|
||||
let info = info_result?;
|
||||
while let Some(load_result) = load.next().await {
|
||||
let (request, info) = load_result?;
|
||||
let scope = &mut self.handle_scope();
|
||||
load.register_and_recurse(scope, &info)?;
|
||||
load.register_and_recurse(scope, &request, &info)?;
|
||||
}
|
||||
|
||||
let root_id = load.root_module_id.expect("Root module should be loaded");
|
||||
|
@ -1454,7 +1457,7 @@ impl JsRuntime {
|
|||
) -> Result<ModuleId, Error> {
|
||||
let module_map_rc = Self::module_map(self.v8_isolate());
|
||||
if let Some(code) = code {
|
||||
module_map_rc.borrow_mut().new_module(
|
||||
module_map_rc.borrow_mut().new_es_module(
|
||||
&mut self.handle_scope(),
|
||||
// not main module
|
||||
false,
|
||||
|
@ -1466,10 +1469,10 @@ impl JsRuntime {
|
|||
let mut load =
|
||||
ModuleMap::load_side(module_map_rc.clone(), specifier.as_str()).await?;
|
||||
|
||||
while let Some(info_result) = load.next().await {
|
||||
let info = info_result?;
|
||||
while let Some(load_result) = load.next().await {
|
||||
let (request, info) = load_result?;
|
||||
let scope = &mut self.handle_scope();
|
||||
load.register_and_recurse(scope, &info)?;
|
||||
load.register_and_recurse(scope, &request, &info)?;
|
||||
}
|
||||
|
||||
let root_id = load.root_module_id.expect("Root module should be loaded");
|
||||
|
@ -1630,6 +1633,7 @@ pub mod tests {
|
|||
use crate::error::custom_error;
|
||||
use crate::modules::ModuleSource;
|
||||
use crate::modules::ModuleSourceFuture;
|
||||
use crate::modules::ModuleType;
|
||||
use crate::op_async;
|
||||
use crate::op_sync;
|
||||
use crate::ZeroCopyBuf;
|
||||
|
@ -2642,6 +2646,7 @@ assertEquals(1, notify_return_value);
|
|||
code: "console.log('hello world');".to_string(),
|
||||
module_url_specified: "file:///main.js".to_string(),
|
||||
module_url_found: "file:///main.js".to_string(),
|
||||
module_type: ModuleType::JavaScript,
|
||||
})
|
||||
}
|
||||
.boxed_local()
|
||||
|
|
|
@ -6352,52 +6352,25 @@
|
|||
"semantics": {
|
||||
"scripting-1": {
|
||||
"the-script-element": {
|
||||
"import-assertions": {
|
||||
"dynamic-import-with-assertion-argument.any.html": [
|
||||
"Dynamic import with an unsupported type assertion should fail"
|
||||
],
|
||||
"dynamic-import-with-assertion-argument.any.worker.html": [
|
||||
"Dynamic import with an unsupported type assertion should fail"
|
||||
]
|
||||
},
|
||||
"import-assertions": true,
|
||||
"json-module": {
|
||||
"charset-bom.any.html": [
|
||||
"UTF-8 BOM should be stripped when decoding JSON module script",
|
||||
"UTF-16BE BOM should result in parse error in JSON module script",
|
||||
"UTF-16LE BOM should result in parse error in JSON module script"
|
||||
],
|
||||
"charset-bom.any.worker.html": [
|
||||
"UTF-8 BOM should be stripped when decoding JSON module script",
|
||||
"UTF-16BE BOM should result in parse error in JSON module script",
|
||||
"UTF-16LE BOM should result in parse error in JSON module script"
|
||||
],
|
||||
"invalid-content-type.any.html": true,
|
||||
"invalid-content-type.any.worker.html": true,
|
||||
"non-object.any.html": [
|
||||
"Non-object: null",
|
||||
"Non-object: true",
|
||||
"Non-object: false",
|
||||
"Non-object: string",
|
||||
"Non-object: array"
|
||||
],
|
||||
"non-object.any.worker.html": [
|
||||
"Non-object: null",
|
||||
"Non-object: true",
|
||||
"Non-object: false",
|
||||
"Non-object: string",
|
||||
"Non-object: array"
|
||||
],
|
||||
"non-object.any.html": true,
|
||||
"non-object.any.worker.html": true,
|
||||
"repeated-imports.any.html": [
|
||||
"Importing a specifier that previously failed due to an incorrect type assertion can succeed if the correct assertion is later given",
|
||||
"Importing a specifier that previously succeeded with the correct type assertion should fail if the incorrect assertion is later given",
|
||||
"Two modules of different type with the same specifier can load if the server changes its responses",
|
||||
"If an import previously succeeded for a given specifier/type assertion pair, future uses of that pair should yield the same result"
|
||||
"Two modules of different type with the same specifier can load if the server changes its responses"
|
||||
],
|
||||
"repeated-imports.any.worker.html": [
|
||||
"Importing a specifier that previously failed due to an incorrect type assertion can succeed if the correct assertion is later given",
|
||||
"Importing a specifier that previously succeeded with the correct type assertion should fail if the incorrect assertion is later given",
|
||||
"Two modules of different type with the same specifier can load if the server changes its responses",
|
||||
"If an import previously succeeded for a given specifier/type assertion pair, future uses of that pair should yield the same result"
|
||||
"Two modules of different type with the same specifier can load if the server changes its responses"
|
||||
]
|
||||
},
|
||||
"microtasks": {
|
||||
|
|
Loading…
Add table
Reference in a new issue