diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 91227802ac..e5f45ea3c3 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -171,7 +171,7 @@ impl ModuleLoadPreparer { ) .await?; - self.module_graph_builder.graph_roots_valid(graph, roots)?; + self.graph_roots_valid(graph, roots)?; // write the lockfile if there is one if let Some(lockfile) = &self.lockfile { @@ -205,6 +205,14 @@ impl ModuleLoadPreparer { Ok(()) } + + pub fn graph_roots_valid( + &self, + graph: &ModuleGraph, + roots: &[ModuleSpecifier], + ) -> Result<(), AnyError> { + self.module_graph_builder.graph_roots_valid(graph, roots) + } } struct SharedCliModuleLoaderState { @@ -806,8 +814,26 @@ impl ModuleLoader let inner = self.0.clone(); async move { - let graph_container = inner.graph_container.clone(); - let module_load_preparer = inner.shared.module_load_preparer.clone(); + let graph_container = &inner.graph_container; + let module_load_preparer = &inner.shared.module_load_preparer; + + if is_dynamic { + // When the specifier is already in the graph then it means it + // was previously loaded, so we can skip that and only check if + // this part of the graph is valid. + // + // This doesn't acquire a graph update permit because that will + // clone the graph which is a bit slow. + let graph = graph_container.graph(); + if !graph.roots.is_empty() && graph.get(&specifier).is_some() { + log::debug!("Skipping prepare module load."); + // roots are already validated so we can skip those + if !graph.roots.contains(&specifier) { + module_load_preparer.graph_roots_valid(&graph, &[specifier])?; + } + return Ok(()); + } + } let root_permissions = if is_dynamic { inner.dynamic_permissions.clone() diff --git a/tests/specs/run/dynamic_already_prepared/__test__.jsonc b/tests/specs/run/dynamic_already_prepared/__test__.jsonc new file mode 100644 index 0000000000..1a68b88c11 --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "tests": { + "skips_prepare_module_load": { + "args": "run -A --log-level=debug main.ts", + "output": "main.out" + } + } +} diff --git a/tests/specs/run/dynamic_already_prepared/dynamic.ts b/tests/specs/run/dynamic_already_prepared/dynamic.ts new file mode 100644 index 0000000000..296d5492b0 --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/dynamic.ts @@ -0,0 +1 @@ +console.log(1); diff --git a/tests/specs/run/dynamic_already_prepared/dynamic2.ts b/tests/specs/run/dynamic_already_prepared/dynamic2.ts new file mode 100644 index 0000000000..00c424d740 --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/dynamic2.ts @@ -0,0 +1 @@ +await import("./dynamic3.ts"); diff --git a/tests/specs/run/dynamic_already_prepared/dynamic3.ts b/tests/specs/run/dynamic_already_prepared/dynamic3.ts new file mode 100644 index 0000000000..ae6da29f8f --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/dynamic3.ts @@ -0,0 +1 @@ +await import("./dynamic.ts"); diff --git a/tests/specs/run/dynamic_already_prepared/main.out b/tests/specs/run/dynamic_already_prepared/main.out new file mode 100644 index 0000000000..f1f5b25951 --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/main.out @@ -0,0 +1 @@ +[WILDCARD]Prepared module load.[WILDCARD]Skipping prepare module load.[WILDCARD]Skipping prepare module load.[WILDCARD]Skipping prepare module load.[WILDCARD] diff --git a/tests/specs/run/dynamic_already_prepared/main.ts b/tests/specs/run/dynamic_already_prepared/main.ts new file mode 100644 index 0000000000..c7f3948eb7 --- /dev/null +++ b/tests/specs/run/dynamic_already_prepared/main.ts @@ -0,0 +1,2 @@ +await import("./dynamic.ts"); +await import("./dynamic2.ts");