summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/integration/run_tests.rs5
-rw-r--r--cli/tests/testdata/followup_dyn_import_resolves/main.ts14
-rw-r--r--cli/tests/testdata/followup_dyn_import_resolves/main.ts.out3
-rw-r--r--cli/tests/testdata/followup_dyn_import_resolves/sub1.ts2
-rw-r--r--cli/tests/testdata/followup_dyn_import_resolves/sub2.ts1
-rw-r--r--core/modules.rs6
-rw-r--r--core/runtime.rs31
7 files changed, 51 insertions, 11 deletions
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 09a1ba500..bd27cd8dd 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -2733,3 +2733,8 @@ itest!(test_and_bench_are_noops_in_run {
args: "run test_and_bench_in_run.js",
output_str: Some(""),
});
+
+itest!(followup_dyn_import_resolved {
+ args: "run --unstable --allow-read followup_dyn_import_resolves/main.ts",
+ output: "followup_dyn_import_resolves/main.ts.out",
+});
diff --git a/cli/tests/testdata/followup_dyn_import_resolves/main.ts b/cli/tests/testdata/followup_dyn_import_resolves/main.ts
new file mode 100644
index 000000000..a8508f942
--- /dev/null
+++ b/cli/tests/testdata/followup_dyn_import_resolves/main.ts
@@ -0,0 +1,14 @@
+// https://github.com/denoland/deno/issues/14726
+
+// Any dynamic modules that are only pending on a TLA import should be resolved
+// in the same event loop iteration as the imported module.
+
+// Long-running timer so the event loop doesn't have a next iteration for a
+// while.
+setTimeout(() => {}, 24 * 60 * 60 * 1000);
+
+await import("./sub1.ts");
+
+// If we reach here, the test is passed.
+console.log("Done.");
+Deno.exit();
diff --git a/cli/tests/testdata/followup_dyn_import_resolves/main.ts.out b/cli/tests/testdata/followup_dyn_import_resolves/main.ts.out
new file mode 100644
index 000000000..a19976d4a
--- /dev/null
+++ b/cli/tests/testdata/followup_dyn_import_resolves/main.ts.out
@@ -0,0 +1,3 @@
+sub2
+sub1
+Done.
diff --git a/cli/tests/testdata/followup_dyn_import_resolves/sub1.ts b/cli/tests/testdata/followup_dyn_import_resolves/sub1.ts
new file mode 100644
index 000000000..d06c30221
--- /dev/null
+++ b/cli/tests/testdata/followup_dyn_import_resolves/sub1.ts
@@ -0,0 +1,2 @@
+await import("./sub2.ts");
+console.log("sub1");
diff --git a/cli/tests/testdata/followup_dyn_import_resolves/sub2.ts b/cli/tests/testdata/followup_dyn_import_resolves/sub2.ts
new file mode 100644
index 000000000..cce2b524c
--- /dev/null
+++ b/cli/tests/testdata/followup_dyn_import_resolves/sub2.ts
@@ -0,0 +1 @@
+console.log("sub2");
diff --git a/core/modules.rs b/core/modules.rs
index 8c4f25d48..e86fdbf73 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -1803,15 +1803,11 @@ import "/a.js";
)
.unwrap();
- // First poll runs `prepare_load` hook.
- assert!(matches!(runtime.poll_event_loop(cx, false), Poll::Pending));
- assert_eq!(prepare_load_count.load(Ordering::Relaxed), 1);
-
- // Second poll actually loads modules into the isolate.
assert!(matches!(
runtime.poll_event_loop(cx, false),
Poll::Ready(Ok(_))
));
+ assert_eq!(prepare_load_count.load(Ordering::Relaxed), 1);
assert_eq!(resolve_count.load(Ordering::Relaxed), 7);
assert_eq!(load_count.load(Ordering::Relaxed), 1);
assert!(matches!(
diff --git a/core/runtime.rs b/core/runtime.rs
index 97c822848..f82f06207 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -886,13 +886,28 @@ impl JsRuntime {
// Dynamic module loading - ie. modules loaded using "import()"
{
- let poll_imports = self.prepare_dyn_imports(cx)?;
- assert!(poll_imports.is_ready());
+ // Run in a loop so that dynamic imports that only depend on another
+ // dynamic import can be resolved in this event loop iteration.
+ //
+ // For example, a dynamically imported module like the following can be
+ // immediately resolved after `dependency.ts` is fully evaluated, but it
+ // wouldn't if not for this loop.
+ //
+ // await delay(1000);
+ // await import("./dependency.ts");
+ // console.log("test")
+ //
+ loop {
+ let poll_imports = self.prepare_dyn_imports(cx)?;
+ assert!(poll_imports.is_ready());
- let poll_imports = self.poll_dyn_imports(cx)?;
- assert!(poll_imports.is_ready());
+ let poll_imports = self.poll_dyn_imports(cx)?;
+ assert!(poll_imports.is_ready());
- self.evaluate_dyn_imports();
+ if !self.evaluate_dyn_imports() {
+ break;
+ }
+ }
self.check_promise_exceptions()?;
}
@@ -1505,7 +1520,9 @@ impl JsRuntime {
}
}
- fn evaluate_dyn_imports(&mut self) {
+ // Returns true if some dynamic import was resolved.
+ fn evaluate_dyn_imports(&mut self) -> bool {
+ let mut resolved_any = false;
let state_rc = Self::state(self.v8_isolate());
let mut still_pending = vec![];
let pending =
@@ -1536,6 +1553,7 @@ impl JsRuntime {
};
if let Some(result) = maybe_result {
+ resolved_any = true;
match result {
Ok((dyn_import_id, module_id)) => {
self.dynamic_import_resolve(dyn_import_id, module_id);
@@ -1547,6 +1565,7 @@ impl JsRuntime {
}
}
state_rc.borrow_mut().pending_dyn_mod_evaluate = still_pending;
+ resolved_any
}
/// Asynchronously load specified module and all of its dependencies.