diff --git a/crates/turbopack-build/src/chunking_context.rs b/crates/turbopack-build/src/chunking_context.rs index 41cd417078c63..88ad9189ff564 100644 --- a/crates/turbopack-build/src/chunking_context.rs +++ b/crates/turbopack-build/src/chunking_context.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use indexmap::IndexSet; use turbo_tasks::{ graph::{AdjacencyMap, GraphTraversal}, @@ -16,14 +16,14 @@ use turbopack_core::{ ident::AssetIdentVc, }; use turbopack_css::chunk::CssChunkVc; -use turbopack_ecmascript::{ - chunk::{EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc}, - EcmascriptModuleAssetVc, +use turbopack_ecmascript::chunk::{ + EcmascriptChunkPlaceableVc, EcmascriptChunkVc, EcmascriptChunkingContext, + EcmascriptChunkingContextVc, }; use turbopack_ecmascript_runtime::RuntimeType; use crate::ecmascript::node::{ - chunk::EcmascriptBuildNodeChunkVc, evaluate::chunk::EcmascriptBuildNodeEvaluateChunkVc, + chunk::EcmascriptBuildNodeChunkVc, entry::chunk::EcmascriptBuildNodeEntryChunkVc, }; /// A builder for [`BuildChunkingContextVc`]. @@ -37,6 +37,11 @@ impl BuildChunkingContextBuilder { self } + pub fn layer(mut self, layer: impl Into) -> Self { + self.context.layer = Some(layer.into()); + self + } + /// Builds the chunking context. pub fn build(self) -> BuildChunkingContextVc { BuildChunkingContextVc::new(Value::new(self.context)) @@ -104,46 +109,32 @@ impl BuildChunkingContextVc { this.into_value().cell() } - #[turbo_tasks::function] - fn generate_evaluate_chunk( - self_vc: BuildChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, - ) -> AssetVc { - EcmascriptBuildNodeEvaluateChunkVc::new( - self_vc, - entry_chunk, - other_chunks, - evaluatable_assets, - exported_module, - ) - .into() - } - /// Generates an output chunk that: /// * evaluates the given assets; and /// * exports the result of evaluating the given module as a CommonJS /// default export. #[turbo_tasks::function] - pub async fn generate_exported_chunk( + pub async fn generate_entry_chunk( self_vc: BuildChunkingContextVc, - module: EcmascriptModuleAssetVc, + path: FileSystemPathVc, + module: EcmascriptChunkPlaceableVc, evaluatable_assets: EvaluatableAssetsVc, ) -> Result { let entry_chunk = module.as_root_chunk(self_vc.into()); - let assets = self_vc - .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) + let other_chunks = self_vc + .get_chunk_assets(entry_chunk, evaluatable_assets) .await?; - let asset = self_vc.generate_evaluate_chunk( + let asset = EcmascriptBuildNodeEntryChunkVc::new( + path, + self_vc, entry_chunk, - AssetsVc::cell(assets), + AssetsVc::cell(other_chunks), evaluatable_assets, - Some(module), - ); + module, + ) + .into(); Ok(asset) } @@ -161,7 +152,7 @@ impl BuildChunkingContextVc { } impl BuildChunkingContextVc { - async fn get_evaluate_chunk_assets( + async fn get_chunk_assets( self, entry_chunk: ChunkVc, evaluatable_assets: EvaluatableAssetsVc, @@ -296,22 +287,13 @@ impl ChunkingContext for BuildChunkingContext { #[turbo_tasks::function] async fn evaluated_chunk_group( - self_vc: BuildChunkingContextVc, - entry_chunk: ChunkVc, - evaluatable_assets: EvaluatableAssetsVc, + _self_vc: BuildChunkingContextVc, + _entry_chunk: ChunkVc, + _evaluatable_assets: EvaluatableAssetsVc, ) -> Result { - let mut assets = self_vc - .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) - .await?; - - assets.push(self_vc.generate_evaluate_chunk( - entry_chunk, - AssetsVc::cell(assets.clone()), - evaluatable_assets, - None, - )); - - Ok(AssetsVc::cell(assets)) + // TODO(alexkirsz) This method should be part of a separate trait that is + // only implemented for client/edge runtimes. + bail!("the build chunking context does not support evaluated chunk groups") } } diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs b/crates/turbopack-build/src/ecmascript/node/entry/chunk.rs similarity index 76% rename from crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs rename to crates/turbopack-build/src/ecmascript/node/entry/chunk.rs index 72fb451378417..f1f747d952dda 100644 --- a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs +++ b/crates/turbopack-build/src/ecmascript/node/entry/chunk.rs @@ -2,8 +2,8 @@ use std::io::Write; use anyhow::{bail, Result}; use indoc::writedoc; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::File; +use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks_fs::{File, FileSystemPathVc}; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc}, @@ -17,7 +17,6 @@ use turbopack_core::{ use turbopack_ecmascript::{ chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, utils::StringifyJs, - EcmascriptModuleAssetVc, }; use super::runtime::EcmascriptBuildNodeRuntimeReferenceVc; @@ -26,26 +25,29 @@ use crate::BuildChunkingContextVc; /// An Ecmascript chunk that loads a list of parallel chunks, then instantiates /// runtime entries. #[turbo_tasks::value(shared)] -pub(crate) struct EcmascriptBuildNodeEvaluateChunk { +pub(crate) struct EcmascriptBuildNodeEntryChunk { + path: FileSystemPathVc, chunking_context: BuildChunkingContextVc, entry_chunk: ChunkVc, other_chunks: AssetsVc, evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, + exported_module: EcmascriptChunkPlaceableVc, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeEvaluateChunkVc { - /// Creates a new [`EcmascriptBuildNodeEvaluateChunkVc`]. +impl EcmascriptBuildNodeEntryChunkVc { + /// Creates a new [`EcmascriptBuildNodeEntryChunkVc`]. #[turbo_tasks::function] pub fn new( + path: FileSystemPathVc, chunking_context: BuildChunkingContextVc, entry_chunk: ChunkVc, other_chunks: AssetsVc, evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, + exported_module: EcmascriptChunkPlaceableVc, ) -> Self { - EcmascriptBuildNodeEvaluateChunk { + EcmascriptBuildNodeEntryChunk { + path, chunking_context, entry_chunk, other_chunks, @@ -136,20 +138,19 @@ impl EcmascriptBuildNodeEvaluateChunkVc { } } - if let Some(exported_module) = this.exported_module { - let runtime_module_id = exported_module - .as_chunk_item(this.chunking_context.into()) - .id() - .await?; + let runtime_module_id = this + .exported_module + .as_chunk_item(this.chunking_context.into()) + .id() + .await?; - writedoc!( - code, - r#" + writedoc!( + code, + r#" module.exports = runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH).exports; "#, - StringifyJs(&*runtime_module_id), - )?; - } + StringifyJs(&*runtime_module_id), + )?; Ok(CodeVc::cell(code.build())) } @@ -164,7 +165,7 @@ impl EcmascriptBuildNodeEvaluateChunkVc { } #[turbo_tasks::value_impl] -impl ValueToString for EcmascriptBuildNodeEvaluateChunk { +impl ValueToString for EcmascriptBuildNodeEntryChunk { #[turbo_tasks::function] async fn to_string(&self) -> Result { Ok(StringVc::cell( @@ -184,32 +185,14 @@ fn chunk_reference_description() -> StringVc { } #[turbo_tasks::value_impl] -impl Asset for EcmascriptBuildNodeEvaluateChunk { +impl Asset for EcmascriptBuildNodeEntryChunk { #[turbo_tasks::function] - async fn ident(&self) -> Result { - let mut ident = self.entry_chunk.ident().await?.clone_value(); - - ident.add_modifier(modifier()); - - ident.modifiers.extend( - self.evaluatable_assets - .await? - .iter() - .map(|entry| entry.ident().to_string()), - ); - - for chunk in &*self.other_chunks.await? { - ident.add_modifier(chunk.ident().to_string()); - } - - let ident = AssetIdentVc::new(Value::new(ident)); - Ok(AssetIdentVc::from_path( - self.chunking_context.chunk_path(ident, ".js"), - )) + fn ident(&self) -> AssetIdentVc { + AssetIdentVc::from_path(self.path) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { + async fn references(self_vc: EcmascriptBuildNodeEntryChunkVc) -> Result { let this = self_vc.await?; let mut references = vec![self_vc.runtime_reference().into()]; @@ -232,16 +215,16 @@ impl Asset for EcmascriptBuildNodeEvaluateChunk { } #[turbo_tasks::function] - async fn content(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { + async fn content(self_vc: EcmascriptBuildNodeEntryChunkVc) -> Result { let code = self_vc.code().await?; Ok(File::from(code.source_code().clone()).into()) } } #[turbo_tasks::value_impl] -impl GenerateSourceMap for EcmascriptBuildNodeEvaluateChunk { +impl GenerateSourceMap for EcmascriptBuildNodeEntryChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> OptionSourceMapVc { + fn generate_source_map(self_vc: EcmascriptBuildNodeEntryChunkVc) -> OptionSourceMapVc { self_vc.code().generate_source_map() } } diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs b/crates/turbopack-build/src/ecmascript/node/entry/mod.rs similarity index 100% rename from crates/turbopack-build/src/ecmascript/node/evaluate/mod.rs rename to crates/turbopack-build/src/ecmascript/node/entry/mod.rs diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs b/crates/turbopack-build/src/ecmascript/node/entry/runtime.rs similarity index 100% rename from crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs rename to crates/turbopack-build/src/ecmascript/node/entry/runtime.rs diff --git a/crates/turbopack-build/src/ecmascript/node/mod.rs b/crates/turbopack-build/src/ecmascript/node/mod.rs index 5b9b729122ed5..1b045f3d973ff 100644 --- a/crates/turbopack-build/src/ecmascript/node/mod.rs +++ b/crates/turbopack-build/src/ecmascript/node/mod.rs @@ -1,3 +1,3 @@ pub(crate) mod chunk; pub(crate) mod content; -pub(crate) mod evaluate; +pub(crate) mod entry; diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index 84246069d6dac..d0597183f3635 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -8,7 +8,7 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{anyhow, Context, Result}; +use anyhow::{bail, Context, Result}; use dunce::canonicalize; use serde::Deserialize; use turbo_tasks::{debug::ValueDebug, NothingVc, TryJoinIterExt, TurboTasks, Value, ValueToString}; @@ -31,7 +31,7 @@ use turbopack::{ }; use turbopack_build::BuildChunkingContextVc; use turbopack_core::{ - asset::{Asset, AssetVc}, + asset::{Asset, AssetVc, AssetsVc}, chunk::{ ChunkableAsset, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc, @@ -194,7 +194,6 @@ async fn run_test(resource: &str) -> Result { let project_path = project_root.join(&relative_path); let entry_asset = project_path.join(&options.entry); - let entry_paths = vec![entry_asset]; let env = EnvironmentVc::new(Value::new(match options.environment { Environment::Browser => { @@ -291,6 +290,7 @@ async fn run_test(resource: &str) -> Result { let chunk_root_path = path.join("output"); let static_root_path = path.join("static"); + let chunking_context: ChunkingContextVc = match options.runtime { Runtime::Dev => DevChunkingContextVc::builder( project_root, @@ -319,43 +319,54 @@ async fn run_test(resource: &str) -> Result { .copied() .collect(); - let modules = entry_paths.into_iter().map(SourceAssetVc::new).map(|p| { - context.process( - p.into(), - Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)), - ) - }); + let entry_module = context.process( + SourceAssetVc::new(entry_asset).into(), + Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)), + ); - let chunk_groups = modules - .map(|module| async move { - if let Some(ecmascript) = EcmascriptModuleAssetVc::resolve_from(module).await? { - // TODO: Load runtime entries from snapshots - Ok(chunking_context.evaluated_chunk_group( + let chunks = + if let Some(ecmascript) = EcmascriptModuleAssetVc::resolve_from(entry_module).await? { + // TODO: Load runtime entries from snapshots + match options.runtime { + Runtime::Dev => chunking_context.evaluated_chunk_group( ecmascript.as_root_chunk(chunking_context), runtime_entries .unwrap_or_else(EvaluatableAssetsVc::empty) .with_entry(ecmascript.into()), - )) - } else if let Some(chunkable) = ChunkableAssetVc::resolve_from(module).await? { - Ok(chunking_context.chunk_group(chunkable.as_root_chunk(chunking_context))) - } else { - // TODO convert into a serve-able asset - Err(anyhow!( - "Entry module is not chunkable, so it can't be used to bootstrap the \ - application" - )) + ), + Runtime::Build => { + AssetsVc::cell(vec![BuildChunkingContextVc::resolve_from(chunking_context) + .await? + .unwrap() + .generate_entry_chunk( + // `expected` expects a completely flat output directory. + chunk_root_path + .join( + entry_module + .ident() + .path() + .file_stem() + .await? + .as_deref() + .unwrap(), + ) + .with_extension("entry.js"), + ecmascript.into(), + runtime_entries + .unwrap_or_else(EvaluatableAssetsVc::empty) + .with_entry(ecmascript.into()), + )]) + } } - }) - .try_join() - .await?; + } else if let Some(chunkable) = ChunkableAssetVc::resolve_from(entry_module).await? { + chunking_context.chunk_group(chunkable.as_root_chunk(chunking_context)) + } else { + // TODO convert into a serve-able asset + bail!("Entry module is not chunkable, so it can't be used to bootstrap the application") + }; let mut seen = HashSet::new(); - let mut queue = VecDeque::with_capacity(32); - for chunks in chunk_groups { - for chunk in &*chunks.await? { - queue.push_back(*chunk); - } - } + let mut queue: VecDeque<_> = chunks.await?.iter().copied().collect(); let output_path = path.await?; while let Some(asset) = queue.pop_front() { diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/index.entry.js similarity index 51% rename from crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js rename to crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/index.entry.js index d409bc3eda3c5..6a55604141957 100644 --- a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js +++ b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/index.entry.js @@ -1,4 +1,5 @@ -const CHUNK_PUBLIC_PATH = "output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js"; +const CHUNK_PUBLIC_PATH = "output/index.entry.js"; const runtime = require("./[turbopack]_runtime.js"); runtime.loadChunk("output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_e254c5.js"); -runtime.getOrInstantiateRuntimeModule("[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)", CHUNK_PUBLIC_PATH); \ No newline at end of file +runtime.getOrInstantiateRuntimeModule("[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)", CHUNK_PUBLIC_PATH); +module.exports = runtime.getOrInstantiateRuntimeModule("[project]/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/input/index.js (ecmascript)", CHUNK_PUBLIC_PATH).exports; \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js.map b/crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/index.entry.js.map similarity index 100% rename from crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/79fb1_turbopack-tests_tests_snapshot_runtime_default_build_runtime_input_index_7c123c.js.map rename to crates/turbopack-tests/tests/snapshot/runtime/default_build_runtime/output/index.entry.js.map