diff --git a/crates/next-core/src/app_render/next_layout_entry_transition.rs b/crates/next-core/src/app_render/next_layout_entry_transition.rs index 16688d2df17bc..0166f42b1777d 100644 --- a/crates/next-core/src/app_render/next_layout_entry_transition.rs +++ b/crates/next-core/src/app_render/next_layout_entry_transition.rs @@ -9,7 +9,7 @@ use turbopack::{ }; use turbopack_core::{ asset::{Asset, AssetVc}, - environment::EnvironmentVc, + compile_time_info::CompileTimeInfoVc, virtual_asset::VirtualAssetVc, }; use turbopack_ecmascript::chunk::EcmascriptChunkPlaceableVc; @@ -20,7 +20,7 @@ use crate::{ #[turbo_tasks::value(shared)] pub struct NextLayoutEntryTransition { - pub rsc_environment: EnvironmentVc, + pub rsc_compile_time_info: CompileTimeInfoVc, pub rsc_module_options_context: ModuleOptionsContextVc, pub rsc_resolve_options_context: ResolveOptionsContextVc, pub server_root: FileSystemPathVc, @@ -38,8 +38,11 @@ impl Transition for NextLayoutEntryTransition { } #[turbo_tasks::function] - fn process_environment(&self, _environment: EnvironmentVc) -> EnvironmentVc { - self.rsc_environment + fn process_compile_time_info( + &self, + _compile_time_info: CompileTimeInfoVc, + ) -> CompileTimeInfoVc { + self.rsc_compile_time_info } #[turbo_tasks::function] diff --git a/crates/next-core/src/app_source.rs b/crates/next-core/src/app_source.rs index d5714000bf967..c120c19124f37 100644 --- a/crates/next-core/src/app_source.rs +++ b/crates/next-core/src/app_source.rs @@ -52,8 +52,9 @@ use crate::{ fallback::get_fallback_page, next_client::{ context::{ - get_client_chunking_context, get_client_environment, get_client_module_options_context, - get_client_resolve_options_context, get_client_runtime_entries, ClientContextType, + get_client_chunking_context, get_client_compile_time_info, + get_client_module_options_context, get_client_resolve_options_context, + get_client_runtime_entries, ClientContextType, }, transition::NextClientTransition, }, @@ -65,7 +66,7 @@ use crate::{ next_config::NextConfigVc, next_route_matcher::NextParamsMatcherVc, next_server::context::{ - get_server_environment, get_server_module_options_context, + get_server_compile_time_info, get_server_module_options_context, get_server_resolve_options_context, ServerContextType, }, util::pathname_for_path, @@ -82,13 +83,17 @@ async fn next_client_transition( next_config: NextConfigVc, ) -> Result { let ty = Value::new(ClientContextType::App { app_dir }); - let client_environment = get_client_environment(browserslist_query); - let client_chunking_context = - get_client_chunking_context(project_path, server_root, client_environment, ty); + let client_compile_time_info = get_client_compile_time_info(browserslist_query); + let client_chunking_context = get_client_chunking_context( + project_path, + server_root, + client_compile_time_info.environment(), + ty, + ); let client_module_options_context = get_client_module_options_context( project_path, execution_context, - client_environment, + client_compile_time_info.environment(), ty, next_config, ); @@ -102,7 +107,7 @@ async fn next_client_transition( client_chunking_context, client_module_options_context, client_resolve_options_context, - client_environment, + client_compile_time_info, runtime_entries: client_runtime_entries, } .cell() @@ -131,7 +136,7 @@ fn next_ssr_client_module_transition( ty, next_config, ), - ssr_environment: get_server_environment(ty, process_env, server_addr), + ssr_environment: get_server_compile_time_info(ty, process_env, server_addr), } .cell() .into() @@ -148,14 +153,14 @@ fn next_layout_entry_transition( server_addr: ServerAddrVc, ) -> TransitionVc { let ty = Value::new(ServerContextType::AppRSC { app_dir }); - let rsc_environment = get_server_environment(ty, process_env, server_addr); + let rsc_compile_time_info = get_server_compile_time_info(ty, process_env, server_addr); let rsc_resolve_options_context = get_server_resolve_options_context(project_path, ty, next_config); let rsc_module_options_context = get_server_module_options_context(project_path, execution_context, ty, next_config); NextLayoutEntryTransition { - rsc_environment, + rsc_compile_time_info, rsc_module_options_context, rsc_resolve_options_context, server_root, @@ -236,7 +241,7 @@ fn app_context( let ssr_ty = Value::new(ServerContextType::AppSSR { app_dir }); ModuleAssetContextVc::new( TransitionsByNameVc::cell(transitions), - get_server_environment(ssr_ty, env, server_addr), + get_server_compile_time_info(ssr_ty, env, server_addr), get_server_module_options_context(project_path, execution_context, ssr_ty, next_config), get_server_resolve_options_context(project_path, ssr_ty, next_config), ) @@ -637,7 +642,7 @@ import BOOTSTRAP from {}; intermediate_output_path, intermediate_output_path.join("chunks"), this.server_root.join("_next/static/assets"), - context.environment(), + context.compile_time_info().environment(), ) .layer("ssr") .css_chunk_root_path(this.server_root.join("_next/static/chunks")) @@ -652,7 +657,7 @@ import BOOTSTRAP from {}; EcmascriptInputTransform::React { refresh: false }, EcmascriptInputTransform::TypeScript, ]), - context.environment(), + context.compile_time_info(), ), chunking_context, intermediate_output_path, diff --git a/crates/next-core/src/fallback.rs b/crates/next-core/src/fallback.rs index 5fcf68acb18c7..1c08860060a1b 100644 --- a/crates/next-core/src/fallback.rs +++ b/crates/next-core/src/fallback.rs @@ -17,8 +17,9 @@ use turbopack_node::execution_context::ExecutionContextVc; use crate::{ next_client::context::{ - get_client_chunking_context, get_client_environment, get_client_module_options_context, - get_client_resolve_options_context, get_client_runtime_entries, ClientContextType, + get_client_chunking_context, get_client_compile_time_info, + get_client_module_options_context, get_client_resolve_options_context, + get_client_runtime_entries, ClientContextType, }, next_config::NextConfigVc, next_import_map::{insert_alias_option, insert_next_shared_aliases}, @@ -35,17 +36,21 @@ pub async fn get_fallback_page( next_config: NextConfigVc, ) -> Result { let ty = Value::new(ClientContextType::Fallback); - let environment = get_client_environment(browserslist_query); + let client_compile_time_info = get_client_compile_time_info(browserslist_query); let resolve_options_context = get_client_resolve_options_context(project_path, ty, next_config); let module_options_context = get_client_module_options_context( project_path, execution_context, - environment, + client_compile_time_info.environment(), ty, next_config, ); - let chunking_context = - get_client_chunking_context(project_path, dev_server_root, environment, ty); + let chunking_context = get_client_chunking_context( + project_path, + dev_server_root, + client_compile_time_info.environment(), + ty, + ); let entries = get_client_runtime_entries(project_path, env, ty, next_config); let mut import_map = ImportMap::empty(); @@ -60,7 +65,7 @@ pub async fn get_fallback_page( let context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - environment, + client_compile_time_info, module_options_context, resolve_options_context.with_extended_import_map(import_map.cell()), ) diff --git a/crates/next-core/src/next_client/context.rs b/crates/next-core/src/next_client/context.rs index ead27ff751010..00ac32c9f3497 100644 --- a/crates/next-core/src/next_client/context.rs +++ b/crates/next-core/src/next_client/context.rs @@ -16,6 +16,7 @@ use turbopack::{ }; use turbopack_core::{ chunk::{dev::DevChunkingContextVc, ChunkingContextVc}, + compile_time_info::{CompileTimeInfo, CompileTimeInfoVc}, context::AssetContextVc, environment::{BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment}, resolve::{parse::RequestVc, pattern::Pattern}, @@ -39,19 +40,22 @@ use crate::{ }; #[turbo_tasks::function] -pub fn get_client_environment(browserslist_query: &str) -> EnvironmentVc { - EnvironmentVc::new( - Value::new(ExecutionEnvironment::Browser( - BrowserEnvironment { - dom: true, - web_worker: false, - service_worker: false, - browserslist_query: browserslist_query.to_owned(), - } - .into(), - )), - Value::new(EnvironmentIntention::Client), - ) +pub fn get_client_compile_time_info(browserslist_query: &str) -> CompileTimeInfoVc { + CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::Browser( + BrowserEnvironment { + dom: true, + web_worker: false, + service_worker: false, + browserslist_query: browserslist_query.to_owned(), + } + .into(), + )), + Value::new(EnvironmentIntention::Client), + ), + } + .cell() } #[turbo_tasks::value(serialization = "auto_for_input")] @@ -145,7 +149,7 @@ pub async fn get_client_module_options_context( pub fn get_client_asset_context( project_path: FileSystemPathVc, execution_context: ExecutionContextVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ty: Value, next_config: NextConfigVc, ) -> AssetContextVc { @@ -153,14 +157,14 @@ pub fn get_client_asset_context( let module_options_context = get_client_module_options_context( project_path, execution_context, - environment, + compile_time_info.environment(), ty, next_config, ); let context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - environment, + compile_time_info, module_options_context, resolve_options_context, ) diff --git a/crates/next-core/src/next_client/transition.rs b/crates/next-core/src/next_client/transition.rs index 39759494fae41..0dc444d6e6a53 100644 --- a/crates/next-core/src/next_client/transition.rs +++ b/crates/next-core/src/next_client/transition.rs @@ -11,7 +11,7 @@ use turbopack::{ use turbopack_core::{ asset::{Asset, AssetVc}, chunk::{ChunkableAssetVc, ChunkingContextVc}, - environment::EnvironmentVc, + compile_time_info::CompileTimeInfoVc, virtual_asset::VirtualAssetVc, }; @@ -26,7 +26,7 @@ use crate::embed_js::next_js_file; #[turbo_tasks::value(shared)] pub struct NextClientTransition { pub is_app: bool, - pub client_environment: EnvironmentVc, + pub client_compile_time_info: CompileTimeInfoVc, pub client_module_options_context: ModuleOptionsContextVc, pub client_resolve_options_context: ResolveOptionsContextVc, pub client_chunking_context: ChunkingContextVc, @@ -54,8 +54,11 @@ impl Transition for NextClientTransition { } #[turbo_tasks::function] - fn process_environment(&self, _environment: EnvironmentVc) -> EnvironmentVc { - self.client_environment + fn process_compile_time_info( + &self, + _compile_time_info: CompileTimeInfoVc, + ) -> CompileTimeInfoVc { + self.client_compile_time_info } #[turbo_tasks::function] diff --git a/crates/next-core/src/next_client_chunks/client_chunks_transition.rs b/crates/next-core/src/next_client_chunks/client_chunks_transition.rs index c00d342c22492..515d11d1bb7d7 100644 --- a/crates/next-core/src/next_client_chunks/client_chunks_transition.rs +++ b/crates/next-core/src/next_client_chunks/client_chunks_transition.rs @@ -8,21 +8,23 @@ use turbopack::{ transition::{Transition, TransitionVc}, ModuleAssetContextVc, }; -use turbopack_core::{asset::AssetVc, chunk::ChunkingContextVc, environment::EnvironmentVc}; +use turbopack_core::{ + asset::AssetVc, chunk::ChunkingContextVc, compile_time_info::CompileTimeInfoVc, +}; use turbopack_node::execution_context::ExecutionContextVc; use super::with_chunks::WithChunksAsset; use crate::{ next_client::context::{ - get_client_chunking_context, get_client_environment, get_client_module_options_context, - get_client_resolve_options_context, ClientContextType, + get_client_chunking_context, get_client_compile_time_info, + get_client_module_options_context, get_client_resolve_options_context, ClientContextType, }, next_config::NextConfigVc, }; #[turbo_tasks::value(shared)] pub struct NextClientChunksTransition { - pub client_environment: EnvironmentVc, + pub client_compile_time_info: CompileTimeInfoVc, pub client_module_options_context: ModuleOptionsContextVc, pub client_resolve_options_context: ResolveOptionsContextVc, pub client_chunking_context: ChunkingContextVc, @@ -40,14 +42,18 @@ impl NextClientChunksTransitionVc { browserslist_query: &str, next_config: NextConfigVc, ) -> NextClientChunksTransitionVc { - let client_environment = get_client_environment(browserslist_query); - let client_chunking_context = - get_client_chunking_context(project_path, server_root, client_environment, ty); + let client_compile_time_info = get_client_compile_time_info(browserslist_query); + let client_chunking_context = get_client_chunking_context( + project_path, + server_root, + client_compile_time_info.environment(), + ty, + ); let client_module_options_context = get_client_module_options_context( project_path, execution_context, - client_environment, + client_compile_time_info.environment(), ty, next_config, ); @@ -59,7 +65,7 @@ impl NextClientChunksTransitionVc { ty, next_config, ), - client_environment, + client_compile_time_info, server_root, } .cell() @@ -69,8 +75,11 @@ impl NextClientChunksTransitionVc { #[turbo_tasks::value_impl] impl Transition for NextClientChunksTransition { #[turbo_tasks::function] - fn process_environment(&self, _environment: EnvironmentVc) -> EnvironmentVc { - self.client_environment + fn process_compile_time_info( + &self, + _compile_time_info: CompileTimeInfoVc, + ) -> CompileTimeInfoVc { + self.client_compile_time_info } #[turbo_tasks::function] diff --git a/crates/next-core/src/next_client_component/ssr_client_module_transition.rs b/crates/next-core/src/next_client_component/ssr_client_module_transition.rs index e5e96517fa8c1..052085cb48348 100644 --- a/crates/next-core/src/next_client_component/ssr_client_module_transition.rs +++ b/crates/next-core/src/next_client_component/ssr_client_module_transition.rs @@ -6,13 +6,13 @@ use turbopack::{ transition::{Transition, TransitionVc}, ModuleAssetContextVc, }; -use turbopack_core::{asset::AssetVc, environment::EnvironmentVc}; +use turbopack_core::{asset::AssetVc, compile_time_info::CompileTimeInfoVc}; use super::with_chunking_context_scope_asset::WithChunkingContextScopeAsset; #[turbo_tasks::value(shared)] pub struct NextSSRClientModuleTransition { - pub ssr_environment: EnvironmentVc, + pub ssr_environment: CompileTimeInfoVc, pub ssr_module_options_context: ModuleOptionsContextVc, pub ssr_resolve_options_context: ResolveOptionsContextVc, } @@ -20,7 +20,10 @@ pub struct NextSSRClientModuleTransition { #[turbo_tasks::value_impl] impl Transition for NextSSRClientModuleTransition { #[turbo_tasks::function] - fn process_environment(&self, _environment: EnvironmentVc) -> EnvironmentVc { + fn process_compile_time_info( + &self, + _compile_time_info: CompileTimeInfoVc, + ) -> CompileTimeInfoVc { self.ssr_environment } diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index a64ff1d3d19ae..542a22b6a1f50 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -563,7 +563,7 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result EnvironmentVc { - EnvironmentVc::new( - Value::new(ExecutionEnvironment::EdgeWorker( - EdgeWorkerEnvironment { server_addr }.into(), - )), - Value::new(EnvironmentIntention::Api), - ) +pub fn get_edge_compile_time_info(server_addr: ServerAddrVc) -> CompileTimeInfoVc { + CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::EdgeWorker( + EdgeWorkerEnvironment { server_addr }.into(), + )), + Value::new(EnvironmentIntention::Api), + ), + } + .cell() } #[turbo_tasks::function] diff --git a/crates/next-core/src/next_edge/transition.rs b/crates/next-core/src/next_edge/transition.rs index 7f644f38b3058..7f52926b801e6 100644 --- a/crates/next-core/src/next_edge/transition.rs +++ b/crates/next-core/src/next_edge/transition.rs @@ -10,7 +10,7 @@ use turbopack::{ use turbopack_core::{ asset::{Asset, AssetVc}, chunk::{ChunkableAssetVc, ChunkingContextVc}, - environment::EnvironmentVc, + compile_time_info::CompileTimeInfoVc, virtual_asset::VirtualAssetVc, }; use turbopack_ecmascript::{chunk_group_files_asset::ChunkGroupFilesAsset, utils::stringify_str}; @@ -19,7 +19,7 @@ use crate::embed_js::next_js_file; #[turbo_tasks::value(shared)] pub struct NextEdgeTransition { - pub edge_environment: EnvironmentVc, + pub edge_compile_time_info: CompileTimeInfoVc, pub edge_chunking_context: ChunkingContextVc, pub edge_resolve_options_context: ResolveOptionsContextVc, pub output_path: FileSystemPathVc, @@ -55,8 +55,11 @@ impl Transition for NextEdgeTransition { } #[turbo_tasks::function] - fn process_environment(&self, _environment: EnvironmentVc) -> EnvironmentVc { - self.edge_environment + fn process_compile_time_info( + &self, + _compile_time_info: CompileTimeInfoVc, + ) -> CompileTimeInfoVc { + self.edge_compile_time_info } #[turbo_tasks::function] diff --git a/crates/next-core/src/next_server/context.rs b/crates/next-core/src/next_server/context.rs index 87581c2654feb..547561a9ae0c0 100644 --- a/crates/next-core/src/next_server/context.rs +++ b/crates/next-core/src/next_server/context.rs @@ -6,8 +6,12 @@ use turbopack::{ module_options::{ModuleOptionsContext, ModuleOptionsContextVc, PostCssTransformOptions}, resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc}, }; -use turbopack_core::environment::{ - EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironmentVc, ServerAddrVc, +use turbopack_core::{ + compile_time_info::{CompileTimeInfo, CompileTimeInfoVc}, + environment::{ + EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironmentVc, + ServerAddrVc, + }, }; use turbopack_ecmascript::EcmascriptInputTransform; use turbopack_node::execution_context::ExecutionContextVc; @@ -112,23 +116,28 @@ pub async fn get_server_resolve_options_context( } #[turbo_tasks::function] -pub fn get_server_environment( +pub fn get_server_compile_time_info( ty: Value, process_env: ProcessEnvVc, server_addr: ServerAddrVc, -) -> EnvironmentVc { - EnvironmentVc::new( - Value::new(ExecutionEnvironment::NodeJsLambda( - NodeJsEnvironmentVc::current(process_env, server_addr), - )), - match ty.into_value() { - ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => { - Value::new(EnvironmentIntention::ServerRendering) - } - ServerContextType::AppSSR { .. } => Value::new(EnvironmentIntention::Prerendering), - ServerContextType::AppRSC { .. } => Value::new(EnvironmentIntention::ServerRendering), - }, - ) +) -> CompileTimeInfoVc { + CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironmentVc::current(process_env, server_addr), + )), + match ty.into_value() { + ServerContextType::Pages { .. } | ServerContextType::PagesData { .. } => { + Value::new(EnvironmentIntention::ServerRendering) + } + ServerContextType::AppSSR { .. } => Value::new(EnvironmentIntention::Prerendering), + ServerContextType::AppRSC { .. } => { + Value::new(EnvironmentIntention::ServerRendering) + } + }, + ), + } + .cell() } #[turbo_tasks::function] diff --git a/crates/next-core/src/page_loader.rs b/crates/next-core/src/page_loader.rs index 6ecb0692068d7..162cd80e99c7f 100644 --- a/crates/next-core/src/page_loader.rs +++ b/crates/next-core/src/page_loader.rs @@ -84,7 +84,7 @@ impl PageLoaderAssetVc { this.client_context, turbo_tasks::Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - this.client_context.environment(), + this.client_context.compile_time_info(), ); let chunk_group = diff --git a/crates/next-core/src/page_source.rs b/crates/next-core/src/page_source.rs index 9a22d43ef25c8..97d67b690f214 100644 --- a/crates/next-core/src/page_source.rs +++ b/crates/next-core/src/page_source.rs @@ -50,7 +50,7 @@ use crate::{ fallback::get_fallback_page, next_client::{ context::{ - get_client_assets_path, get_client_chunking_context, get_client_environment, + get_client_assets_path, get_client_chunking_context, get_client_compile_time_info, get_client_module_options_context, get_client_resolve_options_context, get_client_runtime_entries, ClientContextType, }, @@ -59,7 +59,7 @@ use crate::{ next_client_chunks::client_chunks_transition::NextClientChunksTransitionVc, next_config::NextConfigVc, next_edge::{ - context::{get_edge_environment, get_edge_resolve_options_context}, + context::{get_edge_compile_time_info, get_edge_resolve_options_context}, transition::NextEdgeTransition, }, next_route_matcher::{ @@ -67,7 +67,7 @@ use crate::{ NextPrefixSuffixParamsMatcherVc, }, next_server::context::{ - get_server_environment, get_server_module_options_context, + get_server_compile_time_info, get_server_module_options_context, get_server_resolve_options_context, ServerContextType, }, page_loader::create_page_loader, @@ -103,11 +103,11 @@ pub async fn create_page_source( let server_ty = Value::new(ServerContextType::Pages { pages_dir }); let server_data_ty = Value::new(ServerContextType::PagesData { pages_dir }); - let client_environment = get_client_environment(browserslist_query); + let client_compile_time_info = get_client_compile_time_info(browserslist_query); let client_module_options_context = get_client_module_options_context( project_path, execution_context, - client_environment, + client_compile_time_info.environment(), client_ty, next_config, ); @@ -115,14 +115,18 @@ pub async fn create_page_source( get_client_resolve_options_context(project_path, client_ty, next_config); let client_context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - client_environment, + client_compile_time_info, client_module_options_context, client_resolve_options_context, ) .into(); - let client_chunking_context = - get_client_chunking_context(project_path, server_root, client_environment, client_ty); + let client_chunking_context = get_client_chunking_context( + project_path, + server_root, + client_compile_time_info.environment(), + client_ty, + ); let client_runtime_entries = get_client_runtime_entries(project_path, env, client_ty, next_config); @@ -132,14 +136,14 @@ pub async fn create_page_source( client_chunking_context, client_module_options_context, client_resolve_options_context, - client_environment, + client_compile_time_info, server_root, runtime_entries: client_runtime_entries, } .cell() .into(); - let edge_environment = get_edge_environment(server_addr); + let edge_compile_time_info = get_edge_compile_time_info(server_addr); let edge_chunking_context = DevChunkingContextVc::builder( project_path, @@ -149,14 +153,14 @@ pub async fn create_page_source( server_root, Value::new(ClientContextType::Pages { pages_dir }), ), - edge_environment, + edge_compile_time_info.environment(), ) .build(); let edge_resolve_options_context = get_edge_resolve_options_context(project_path, server_ty, next_config); let next_edge_transition = NextEdgeTransition { - edge_environment, + edge_compile_time_info, edge_chunking_context, edge_resolve_options_context, output_path, @@ -165,7 +169,7 @@ pub async fn create_page_source( .cell() .into(); - let server_environment = get_server_environment(server_ty, env, server_addr); + let server_compile_time_info = get_server_compile_time_info(server_ty, env, server_addr); let server_resolve_options_context = get_server_resolve_options_context(project_path, server_ty, next_config); @@ -194,7 +198,7 @@ pub async fn create_page_source( let server_context: AssetContextVc = ModuleAssetContextVc::new( server_transitions, - server_environment, + server_compile_time_info, server_module_options_context, server_resolve_options_context, ) @@ -209,7 +213,7 @@ pub async fn create_page_source( let server_data_context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - server_environment, + server_compile_time_info, server_data_module_options_context, server_resolve_options_context, ) @@ -327,7 +331,7 @@ async fn create_page_source_for_file( server_root, Value::new(ClientContextType::Pages { pages_dir }), ), - server_context.environment(), + server_context.compile_time_info().environment(), ) .build(); @@ -341,14 +345,14 @@ async fn create_page_source_for_file( server_root, Value::new(ClientContextType::Pages { pages_dir }), ), - server_context.environment(), + server_context.compile_time_info().environment(), ) .build(); let client_chunking_context = get_client_chunking_context( context_path, server_root, - client_context.environment(), + client_context.compile_time_info().environment(), Value::new(ClientContextType::Pages { pages_dir }), ); @@ -474,14 +478,14 @@ async fn create_not_found_page_source( server_root, Value::new(ClientContextType::Pages { pages_dir }), ), - server_context.environment(), + server_context.compile_time_info().environment(), ) .build(); let client_chunking_context = get_client_chunking_context( context_path, server_root, - client_context.environment(), + client_context.compile_time_info().environment(), Value::new(ClientContextType::Pages { pages_dir }), ); @@ -706,7 +710,7 @@ impl SsrEntryVc { EcmascriptInputTransform::TypeScript, EcmascriptInputTransform::React { refresh: false }, ]), - this.context.environment(), + this.context.compile_time_info(), ), chunking_context: this.chunking_context, intermediate_output_path: this.intermediate_output_path, diff --git a/crates/next-core/src/router.rs b/crates/next-core/src/router.rs index 1280f6f04f8ef..9453c38af2f26 100644 --- a/crates/next-core/src/router.rs +++ b/crates/next-core/src/router.rs @@ -132,7 +132,7 @@ async fn extra_configs( context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), ) .as_ecmascript_chunk_placeable(); Ok(EcmascriptChunkPlaceablesVc::cell(vec![config_chunk])) @@ -145,7 +145,7 @@ fn route_executor(context: AssetContextVc, project_path: FileSystemPathVc) -> As context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), ) .into() } diff --git a/crates/next-core/src/web_entry_source.rs b/crates/next-core/src/web_entry_source.rs index e1c46113ca97e..9e5449d2c46f9 100644 --- a/crates/next-core/src/web_entry_source.rs +++ b/crates/next-core/src/web_entry_source.rs @@ -17,7 +17,7 @@ use turbopack_node::execution_context::ExecutionContextVc; use crate::{ embed_js::wrap_with_next_js_fs, next_client::context::{ - get_client_asset_context, get_client_chunking_context, get_client_environment, + get_client_asset_context, get_client_chunking_context, get_client_compile_time_info, get_client_runtime_entries, ClientContextType, }, next_config::NextConfigVc, @@ -37,15 +37,20 @@ pub async fn create_web_entry_source( let project_root = wrap_with_next_js_fs(project_root); let ty = Value::new(ClientContextType::Other); - let environment = get_client_environment(browserslist_query); + let compile_time_info = get_client_compile_time_info(browserslist_query); let context = get_client_asset_context( project_root, execution_context, - environment, + compile_time_info, ty, next_config, ); - let chunking_context = get_client_chunking_context(project_root, server_root, environment, ty); + let chunking_context = get_client_chunking_context( + project_root, + server_root, + compile_time_info.environment(), + ty, + ); let entries = get_client_runtime_entries(project_root, env, ty, next_config); let runtime_entries = entries.resolve_entries(context); diff --git a/crates/node-file-trace/src/lib.rs b/crates/node-file-trace/src/lib.rs index 1dcf76412009c..fffb04de50e8b 100644 --- a/crates/node-file-trace/src/lib.rs +++ b/crates/node-file-trace/src/lib.rs @@ -40,6 +40,7 @@ use turbopack::{ use turbopack_cli_utils::issue::{ConsoleUi, IssueSeverityCliOption, LogOptions}; use turbopack_core::{ asset::{Asset, AssetVc, AssetsVc}, + compile_time_info::CompileTimeInfo, context::{AssetContext, AssetContextVc}, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, issue::{IssueSeverity, IssueVc}, @@ -255,6 +256,7 @@ async fn input_to_modules<'a>( )), Value::new(EnvironmentIntention::Api), ); + let compile_time_info = CompileTimeInfo { environment: env }.cell(); let glob_mappings = vec![ ( root, @@ -269,7 +271,7 @@ async fn input_to_modules<'a>( ]; let context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - env, + compile_time_info, ModuleOptionsContext { enable_types: true, enable_mdx, diff --git a/crates/turbopack-core/src/compile_time_info.rs b/crates/turbopack-core/src/compile_time_info.rs new file mode 100644 index 0000000000000..27ea3148d6dc6 --- /dev/null +++ b/crates/turbopack-core/src/compile_time_info.rs @@ -0,0 +1,21 @@ +use anyhow::Result; + +use crate::environment::EnvironmentVc; + +#[turbo_tasks::value(shared)] +pub struct CompileTimeInfo { + pub environment: EnvironmentVc, +} + +#[turbo_tasks::value_impl] +impl CompileTimeInfoVc { + #[turbo_tasks::function] + pub fn new(environment: EnvironmentVc) -> Self { + CompileTimeInfo { environment }.cell() + } + + #[turbo_tasks::function] + pub async fn environment(self) -> Result { + Ok(self.await?.environment) + } +} diff --git a/crates/turbopack-core/src/context.rs b/crates/turbopack-core/src/context.rs index 86f4a22e12a5d..7c095f0bbbff6 100644 --- a/crates/turbopack-core/src/context.rs +++ b/crates/turbopack-core/src/context.rs @@ -4,7 +4,7 @@ use turbo_tasks_fs::FileSystemPathVc; use crate::{ asset::AssetVc, - environment::EnvironmentVc, + compile_time_info::CompileTimeInfoVc, reference_type::ReferenceType, resolve::{options::ResolveOptionsVc, parse::RequestVc, ResolveResultVc}, }; @@ -14,7 +14,7 @@ use crate::{ /// type (e. g. from SourceAsset to ModuleAsset). #[turbo_tasks::value_trait] pub trait AssetContext { - fn environment(&self) -> EnvironmentVc; + fn compile_time_info(&self) -> CompileTimeInfoVc; fn resolve_options( &self, origin_path: FileSystemPathVc, diff --git a/crates/turbopack-core/src/lib.rs b/crates/turbopack-core/src/lib.rs index 6d8c6f80242e1..7446d0a2f1066 100644 --- a/crates/turbopack-core/src/lib.rs +++ b/crates/turbopack-core/src/lib.rs @@ -8,6 +8,7 @@ pub mod asset; pub mod chunk; pub mod code_builder; +pub mod compile_time_info; pub mod context; pub mod environment; pub mod introspect; diff --git a/crates/turbopack-ecmascript/benches/analyzer.rs b/crates/turbopack-ecmascript/benches/analyzer.rs index d9363486b00fd..10f0dd5821136 100644 --- a/crates/turbopack-ecmascript/benches/analyzer.rs +++ b/crates/turbopack-ecmascript/benches/analyzer.rs @@ -13,6 +13,7 @@ use swc_core::{ use turbo_tasks::Value; use turbo_tasks_testing::VcStorage; use turbopack_core::{ + compile_time_info::CompileTimeInfo, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, target::CompileTargetVc, }; @@ -92,21 +93,24 @@ fn bench_link(b: &mut Bencher, input: &BenchInput) { b.to_async(rt).iter(|| async { for val in input.var_graph.values.values() { VcStorage::with(async { - let env = EnvironmentVc::new( - Value::new(ExecutionEnvironment::NodeJsLambda( - NodeJsEnvironment { - compile_target: CompileTargetVc::unknown(), - ..Default::default() - } - .into(), - )), - Value::new(EnvironmentIntention::ServerRendering), - ); + let compile_time_info = CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment { + compile_target: CompileTargetVc::unknown(), + ..Default::default() + } + .into(), + )), + Value::new(EnvironmentIntention::ServerRendering), + ), + } + .cell(); link( &input.var_graph, val.clone(), &early_visitor, - &(|val| visitor(val, env)), + &(|val| visitor(val, compile_time_info)), Default::default(), ) .await diff --git a/crates/turbopack-ecmascript/src/analyzer/mod.rs b/crates/turbopack-ecmascript/src/analyzer/mod.rs index 43d71db318535..f0260d32c0920 100644 --- a/crates/turbopack-ecmascript/src/analyzer/mod.rs +++ b/crates/turbopack-ecmascript/src/analyzer/mod.rs @@ -2497,7 +2497,7 @@ pub mod test_utils { use std::sync::Arc; use anyhow::Result; - use turbopack_core::environment::EnvironmentVc; + use turbopack_core::compile_time_info::CompileTimeInfoVc; use super::{ builtin::early_replace_builtin, well_known::replace_well_known, FreeVarKind, JsValue, @@ -2510,7 +2510,10 @@ pub mod test_utils { Ok((v, m)) } - pub async fn visitor(v: JsValue, environment: EnvironmentVc) -> Result<(JsValue, bool)> { + pub async fn visitor( + v: JsValue, + compile_time_info: CompileTimeInfoVc, + ) -> Result<(JsValue, bool)> { let mut new_value = match v { JsValue::Call( _, @@ -2545,7 +2548,7 @@ pub mod test_utils { _ => return Ok((v, false)), }, _ => { - let (mut v, m1) = replace_well_known(v, environment).await?; + let (mut v, m1) = replace_well_known(v, compile_time_info).await?; let m2 = replace_builtin(&mut v); let m = m1 || m2 || v.make_nested_operations_unknown(); return Ok((v, m)); @@ -2570,6 +2573,7 @@ mod tests { }; use turbo_tasks::{util::FormatDuration, Value}; use turbopack_core::{ + compile_time_info::CompileTimeInfo, environment::{ EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment, }, @@ -2831,33 +2835,35 @@ mod tests { } async fn resolve(var_graph: &VarGraph, val: JsValue) -> JsValue { - turbo_tasks_testing::VcStorage::with(link( - var_graph, - val, - &super::test_utils::early_visitor, - &(|val| { - Box::pin(super::test_utils::visitor( - val, - EnvironmentVc::new( - Value::new(ExecutionEnvironment::NodeJsLambda( - NodeJsEnvironment { - compile_target: CompileTarget { - arch: Arch::X64, - platform: Platform::Linux, - endianness: Endianness::Little, - libc: Libc::Glibc, - } - .into(), - ..Default::default() + turbo_tasks_testing::VcStorage::with(async { + let compile_time_info = CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment { + compile_target: CompileTarget { + arch: Arch::X64, + platform: Platform::Linux, + endianness: Endianness::Little, + libc: Libc::Glibc, } .into(), - )), - Value::new(EnvironmentIntention::ServerRendering), - ), - )) - }), - Default::default(), - )) + ..Default::default() + } + .into(), + )), + Value::new(EnvironmentIntention::ServerRendering), + ), + } + .cell(); + link( + var_graph, + val, + &super::test_utils::early_visitor, + &(|val| Box::pin(super::test_utils::visitor(val, compile_time_info))), + Default::default(), + ) + .await + }) .await .unwrap() } diff --git a/crates/turbopack-ecmascript/src/analyzer/well_known.rs b/crates/turbopack-ecmascript/src/analyzer/well_known.rs index 011b7005203e2..2d83cc044950a 100644 --- a/crates/turbopack-ecmascript/src/analyzer/well_known.rs +++ b/crates/turbopack-ecmascript/src/analyzer/well_known.rs @@ -1,7 +1,7 @@ use std::{mem::take, sync::Arc}; use anyhow::Result; -use turbopack_core::environment::EnvironmentVc; +use turbopack_core::compile_time_info::CompileTimeInfoVc; use url::Url; use super::{ @@ -11,7 +11,7 @@ use super::{ pub async fn replace_well_known( value: JsValue, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result<(JsValue, bool)> { Ok(match value { JsValue::Call(_, box JsValue::WellKnownFunction(kind), args) => ( @@ -19,7 +19,7 @@ pub async fn replace_well_known( kind, JsValue::Unknown(None, "this is not analyzed yet"), args, - environment, + compile_time_info, ) .await?, true, @@ -35,7 +35,7 @@ pub async fn replace_well_known( (JsValue::Call(usize, callee, args), false) } JsValue::Member(_, box JsValue::WellKnownObject(kind), box prop) => ( - well_known_object_member(kind, prop, environment).await?, + well_known_object_member(kind, prop, compile_time_info).await?, true, ), JsValue::Member(_, box JsValue::WellKnownFunction(kind), box prop) => { @@ -49,7 +49,7 @@ pub async fn well_known_function_call( kind: WellKnownFunctionKind, _this: JsValue, args: Vec, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result { Ok(match kind { WellKnownFunctionKind::ObjectAssign => object_assign(args), @@ -65,12 +65,22 @@ pub async fn well_known_function_call( ), WellKnownFunctionKind::Require => require(args), WellKnownFunctionKind::PathToFileUrl => path_to_file_url(args), - WellKnownFunctionKind::OsArch => environment.compile_target().await?.arch.as_str().into(), - WellKnownFunctionKind::OsPlatform => { - environment.compile_target().await?.platform.as_str().into() - } + WellKnownFunctionKind::OsArch => compile_time_info + .environment() + .compile_target() + .await? + .arch + .as_str() + .into(), + WellKnownFunctionKind::OsPlatform => compile_time_info + .environment() + .compile_target() + .await? + .platform + .as_str() + .into(), WellKnownFunctionKind::ProcessCwd => { - if let Some(cwd) = &*environment.cwd().await? { + if let Some(cwd) = &*compile_time_info.environment().cwd().await? { cwd.clone().into() } else { JsValue::Unknown( @@ -82,7 +92,8 @@ pub async fn well_known_function_call( ) } } - WellKnownFunctionKind::OsEndianness => environment + WellKnownFunctionKind::OsEndianness => compile_time_info + .environment() .compile_target() .await? .endianness @@ -384,7 +395,7 @@ pub fn well_known_function_member(kind: WellKnownFunctionKind, prop: JsValue) -> pub async fn well_known_object_member( kind: WellKnownObjectKind, prop: JsValue, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result { Ok(match kind { WellKnownObjectKind::GlobalObject => global_object(prop), @@ -403,7 +414,7 @@ pub async fn well_known_object_member( WellKnownObjectKind::OsModule | WellKnownObjectKind::OsModuleDefault => { os_module_member(kind, prop) } - WellKnownObjectKind::NodeProcess => node_process_member(prop, environment).await?, + WellKnownObjectKind::NodeProcess => node_process_member(prop, compile_time_info).await?, WellKnownObjectKind::NodePreGyp => node_pre_gyp(prop), WellKnownObjectKind::NodeExpressApp => express(prop), WellKnownObjectKind::NodeProtobufLoader => protobuf_loader(prop), @@ -540,10 +551,25 @@ fn os_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue { } } -async fn node_process_member(prop: JsValue, environment: EnvironmentVc) -> Result { +async fn node_process_member( + prop: JsValue, + compile_time_info: CompileTimeInfoVc, +) -> Result { Ok(match prop.as_str() { - Some("arch") => environment.compile_target().await?.arch.as_str().into(), - Some("platform") => environment.compile_target().await?.platform.as_str().into(), + Some("arch") => compile_time_info + .environment() + .compile_target() + .await? + .arch + .as_str() + .into(), + Some("platform") => compile_time_info + .environment() + .compile_target() + .await? + .platform + .as_str() + .into(), Some("cwd") => JsValue::WellKnownFunction(WellKnownFunctionKind::ProcessCwd), _ => JsValue::Unknown( Some(Arc::new(JsValue::member( diff --git a/crates/turbopack-ecmascript/src/lib.rs b/crates/turbopack-ecmascript/src/lib.rs index 359085ae2b362..5ab9b6a120963 100644 --- a/crates/turbopack-ecmascript/src/lib.rs +++ b/crates/turbopack-ecmascript/src/lib.rs @@ -49,8 +49,8 @@ use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ asset::{Asset, AssetContentVc, AssetOptionVc, AssetVc}, chunk::{ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, ChunkableAssetVc, ChunkingContextVc}, + compile_time_info::CompileTimeInfoVc, context::AssetContextVc, - environment::EnvironmentVc, reference::AssetReferencesVc, resolve::{ origin::{ResolveOrigin, ResolveOriginVc}, @@ -95,7 +95,7 @@ pub struct EcmascriptModuleAsset { pub context: AssetContextVc, pub ty: EcmascriptModuleAssetType, pub transforms: EcmascriptInputTransformsVc, - pub environment: EnvironmentVc, + pub compile_time_info: CompileTimeInfoVc, pub inner_assets: Option, } @@ -107,14 +107,14 @@ impl EcmascriptModuleAssetVc { context: AssetContextVc, ty: Value, transforms: EcmascriptInputTransformsVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Self { Self::cell(EcmascriptModuleAsset { source, context, ty: ty.into_value(), transforms, - environment, + compile_time_info, inner_assets: None, }) } @@ -125,7 +125,7 @@ impl EcmascriptModuleAssetVc { context: AssetContextVc, ty: Value, transforms: EcmascriptInputTransformsVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, inner_assets: InnerAssetsVc, ) -> Self { Self::cell(EcmascriptModuleAsset { @@ -133,7 +133,7 @@ impl EcmascriptModuleAssetVc { context, ty: ty.into_value(), transforms, - environment, + compile_time_info, inner_assets: Some(inner_assets), }) } @@ -155,7 +155,7 @@ impl EcmascriptModuleAssetVc { self.as_resolve_origin(), Value::new(this.ty), this.transforms, - this.environment, + this.compile_time_info, )) } diff --git a/crates/turbopack-ecmascript/src/references/mod.rs b/crates/turbopack-ecmascript/src/references/mod.rs index d4f6683076858..82c3ea42fa22b 100644 --- a/crates/turbopack-ecmascript/src/references/mod.rs +++ b/crates/turbopack-ecmascript/src/references/mod.rs @@ -38,7 +38,7 @@ use turbo_tasks::{TryJoinIterExt, Value}; use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ asset::{Asset, AssetVc}, - environment::EnvironmentVc, + compile_time_info::CompileTimeInfoVc, reference::{AssetReferenceVc, AssetReferencesVc, SourceMapReferenceVc}, reference_type::{CommonJsReferenceSubType, ReferenceType}, resolve::{ @@ -75,8 +75,7 @@ use super::{ graph::{create_graph, Effect}, linker::link, well_known::replace_well_known, - ConstantValue, FreeVarKind, JsValue, ObjectPart, WellKnownFunctionKind, - WellKnownObjectKind, + FreeVarKind, JsValue, ObjectPart, WellKnownFunctionKind, WellKnownObjectKind, }, errors, parse::{parse, ParseResult}, @@ -94,7 +93,7 @@ use crate::{ builtin::early_replace_builtin, graph::{ConditionalKind, EffectArg, EvalContext}, imports::Reexport, - ModuleValue, + ConstantValue, ModuleValue, }, chunk::{EcmascriptExports, EcmascriptExportsVc}, code_gen::{CodeGenerateableVc, CodeGenerateablesVc}, @@ -185,7 +184,7 @@ pub(crate) async fn analyze_ecmascript_module( origin: ResolveOriginVc, ty: Value, transforms: EcmascriptInputTransformsVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result { let mut analysis = AnalyzeEcmascriptModuleResultBuilder::new(); let path = source.path(); @@ -440,7 +439,7 @@ pub(crate) async fn analyze_ecmascript_module( link_value: &'a F, add_effects: &'a G, analysis: &'a mut AnalyzeEcmascriptModuleResultBuilder, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Pin> + Send + 'a>> { Box::pin(handle_call( handler, @@ -454,7 +453,7 @@ pub(crate) async fn analyze_ecmascript_module( link_value, add_effects, analysis, - environment, + compile_time_info, )) } @@ -474,7 +473,7 @@ pub(crate) async fn analyze_ecmascript_module( link_value: &F, add_effects: &G, analysis: &mut AnalyzeEcmascriptModuleResultBuilder, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result<()> { fn explain_args(args: &[JsValue]) -> (String, String) { JsValue::explain_args(args, 10, 2) @@ -515,7 +514,7 @@ pub(crate) async fn analyze_ecmascript_module( link_value, add_effects, analysis, - environment, + compile_time_info, ) .await?; } @@ -805,7 +804,7 @@ pub(crate) async fn analyze_ecmascript_module( analysis.add_reference(NodePreGypConfigReferenceVc::new( source.path().parent(), pat.into(), - environment.compile_target(), + compile_time_info.environment().compile_target(), )); return Ok(()); } @@ -834,7 +833,7 @@ pub(crate) async fn analyze_ecmascript_module( source.path().root().join(s.trim_start_matches("/ROOT/")); analysis.add_reference(NodeGypBuildReferenceVc::new( current_context, - environment.compile_target(), + compile_time_info.environment().compile_target(), )); return Ok(()); } @@ -962,8 +961,8 @@ pub(crate) async fn analyze_ecmascript_module( box JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin), vec![ JsValue::FreeVar(FreeVarKind::Dirname), - JsValue::Constant(ConstantValue::StrWord(p.into())), - JsValue::Constant(ConstantValue::StrWord("intl".into())), + p.into(), + "intl".into(), ], )) .await?; @@ -1106,7 +1105,7 @@ pub(crate) async fn analyze_ecmascript_module( .get_mut() .extend(effects.into_iter().map(Action::Effect).rev()); - let linker = |value| value_visitor(source, origin, value, environment); + let linker = |value| value_visitor(source, origin, value, compile_time_info); // There can be many references to import.meta, but only the first should hoist // the object allocation. let mut first_import_meta = true; @@ -1261,7 +1260,7 @@ pub(crate) async fn analyze_ecmascript_module( &link_value, &add_effects, &mut analysis, - environment, + compile_time_info, ) .await?; } @@ -1320,7 +1319,7 @@ pub(crate) async fn analyze_ecmascript_module( &link_value, &add_effects, &mut analysis, - environment, + compile_time_info, ) .await?; } @@ -1384,7 +1383,7 @@ pub(crate) async fn analyze_ecmascript_module( analysis.add_reference(UrlAssetReferenceVc::new( origin, RequestVc::parse(Value::new(pat)), - environment.rendering(), + compile_time_info.environment().rendering(), AstPathVc::cell(ast_path), )); } @@ -1575,9 +1574,9 @@ async fn value_visitor( source: AssetVc, origin: ResolveOriginVc, v: JsValue, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result<(JsValue, bool)> { - let (mut v, modified) = value_visitor_inner(source, origin, v, environment).await?; + let (mut v, modified) = value_visitor_inner(source, origin, v, compile_time_info).await?; v.normalize_shallow(); Ok((v, modified)) } @@ -1586,136 +1585,123 @@ async fn value_visitor_inner( source: AssetVc, origin: ResolveOriginVc, v: JsValue, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, ) -> Result<(JsValue, bool)> { - Ok(( - match v { - JsValue::Call( - _, - box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), - args, - ) => { - if args.len() == 1 { - let pat = js_value_to_pattern(&args[0]); - let request = RequestVc::parse(Value::new(pat.clone())); - let resolved = cjs_resolve(origin, request).await?; - let mut values = resolved - .primary - .iter() - .map(|result| async move { - Ok(if let PrimaryResolveResult::Asset(asset) = result { - Some(require_resolve(asset.path()).await?) - } else { - None - }) + let value = match v { + JsValue::Call( + _, + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), + args, + ) => { + if args.len() == 1 { + let pat = js_value_to_pattern(&args[0]); + let request = RequestVc::parse(Value::new(pat.clone())); + let resolved = cjs_resolve(origin, request).await?; + let mut values = resolved + .primary + .iter() + .map(|result| async move { + Ok(if let PrimaryResolveResult::Asset(asset) = result { + Some(require_resolve(asset.path()).await?) + } else { + None }) - .try_join() - .await? - .into_iter() - .flatten() - .collect::>(); - match values.len() { - 0 => JsValue::Unknown( - Some(Arc::new(JsValue::call( - box JsValue::WellKnownFunction( - WellKnownFunctionKind::RequireResolve, - ), - args, - ))), - "unresolveable request", - ), - 1 => values.pop().unwrap(), - _ => JsValue::alternatives(values), - } - } else { - JsValue::Unknown( + }) + .try_join() + .await? + .into_iter() + .flatten() + .collect::>(); + match values.len() { + 0 => JsValue::Unknown( Some(Arc::new(JsValue::call( box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), args, ))), - "only a single argument is supported", - ) + "unresolveable request", + ), + 1 => values.pop().unwrap(), + _ => JsValue::alternatives(values), } + } else { + JsValue::Unknown( + Some(Arc::new(JsValue::call( + box JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve), + args, + ))), + "only a single argument is supported", + ) } - JsValue::FreeVar(ref kind) => match kind { - FreeVarKind::Dirname => as_abs_path(source.path().parent()).await?, - FreeVarKind::Filename => as_abs_path(source.path()).await?, - - FreeVarKind::Require => JsValue::WellKnownFunction(WellKnownFunctionKind::Require), - FreeVarKind::Define => JsValue::WellKnownFunction(WellKnownFunctionKind::Define), - FreeVarKind::Import => JsValue::WellKnownFunction(WellKnownFunctionKind::Import), - FreeVarKind::NodeProcess => { - JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess) - } - FreeVarKind::Object => JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject), - _ => JsValue::Unknown(Some(Arc::new(v)), "unknown global"), - }, - JsValue::Module(ModuleValue { - module: ref name, .. - }) => match &**name { + } + JsValue::FreeVar(ref kind) => match kind { + FreeVarKind::Dirname => as_abs_path(source.path().parent()).await?, + FreeVarKind::Filename => as_abs_path(source.path()).await?, + + FreeVarKind::Require => JsValue::WellKnownFunction(WellKnownFunctionKind::Require), + FreeVarKind::Define => JsValue::WellKnownFunction(WellKnownFunctionKind::Define), + FreeVarKind::Import => JsValue::WellKnownFunction(WellKnownFunctionKind::Import), + FreeVarKind::NodeProcess => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + FreeVarKind::Object => JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject), + _ => JsValue::Unknown(Some(Arc::new(v)), "unknown global"), + }, + JsValue::Module(ModuleValue { + module: ref name, .. + }) => { + if *compile_time_info.environment().node_externals().await? { // TODO check externals - "path" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::PathModule) - } - "fs/promises" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::FsModule) - } - "fs" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::FsModule) - } - "child_process" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::ChildProcess) - } - "os" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::OsModule) - } - "process" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess) - } - "@mapbox/node-pre-gyp" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp) - } - "node-gyp-build" if *environment.node_externals().await? => { - JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) - } - "bindings" if *environment.node_externals().await? => { - JsValue::WellKnownFunction(WellKnownFunctionKind::NodeBindings) - } - "express" if *environment.node_externals().await? => { - JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpress) - } - "strong-globalize" if *environment.node_externals().await? => { - JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalize) - } - "resolve-from" if *environment.node_externals().await? => { - JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) - } - "@grpc/proto-loader" if *environment.node_externals().await? => { - JsValue::WellKnownObject(WellKnownObjectKind::NodeProtobufLoader) + match &**name { + "path" => JsValue::WellKnownObject(WellKnownObjectKind::PathModule), + "fs/promises" => JsValue::WellKnownObject(WellKnownObjectKind::FsModule), + "fs" => JsValue::WellKnownObject(WellKnownObjectKind::FsModule), + "child_process" => JsValue::WellKnownObject(WellKnownObjectKind::ChildProcess), + "os" => JsValue::WellKnownObject(WellKnownObjectKind::OsModule), + "process" => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + "@mapbox/node-pre-gyp" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp) + } + "node-gyp-build" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) + } + "bindings" => JsValue::WellKnownFunction(WellKnownFunctionKind::NodeBindings), + "express" => JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpress), + "strong-globalize" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalize) + } + "resolve-from" => { + JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) + } + "@grpc/proto-loader" => { + JsValue::WellKnownObject(WellKnownObjectKind::NodeProtobufLoader) + } + _ => JsValue::Unknown( + Some(Arc::new(v)), + "cross module analyzing is not yet supported", + ), } - _ => JsValue::Unknown( + } else { + JsValue::Unknown( Some(Arc::new(v)), "cross module analyzing is not yet supported", - ), - }, - JsValue::Argument(..) => JsValue::Unknown( - Some(Arc::new(v)), - "cross function analyzing is not yet supported", - ), - JsValue::Member( - _, - box JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), - box JsValue::Constant(value), - ) if value.as_str() == Some("turbopack") => JsValue::Constant(ConstantValue::True), - _ => { - let (mut v, mut modified) = replace_well_known(v, environment).await?; - modified = replace_builtin(&mut v) || modified; - modified = modified || v.make_nested_operations_unknown(); - return Ok((v, modified)); + ) } - }, - true, - )) + } + JsValue::Argument(..) => JsValue::Unknown( + Some(Arc::new(v)), + "cross function analyzing is not yet supported", + ), + JsValue::Member( + _, + box JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess), + box JsValue::Constant(value), + ) if value.as_str() == Some("turbopack") => JsValue::Constant(ConstantValue::True), + _ => { + let (mut v, mut modified) = replace_well_known(v, compile_time_info).await?; + modified = replace_builtin(&mut v) || modified; + modified = modified || v.make_nested_operations_unknown(); + return Ok((v, modified)); + } + }; + Ok((value, true)) } #[derive(Debug)] diff --git a/crates/turbopack-mdx/src/lib.rs b/crates/turbopack-mdx/src/lib.rs index 8a6b031e98a60..583e950a8c870 100644 --- a/crates/turbopack-mdx/src/lib.rs +++ b/crates/turbopack-mdx/src/lib.rs @@ -62,7 +62,7 @@ async fn into_ecmascript_module_asset( this.context, Value::new(EcmascriptModuleAssetType::Typescript), this.transforms, - this.context.environment(), + this.context.compile_time_info(), )) } diff --git a/crates/turbopack-node/src/evaluate.rs b/crates/turbopack-node/src/evaluate.rs index 38d16186a5821..24168aa9ed4db 100644 --- a/crates/turbopack-node/src/evaluate.rs +++ b/crates/turbopack-node/src/evaluate.rs @@ -55,7 +55,7 @@ pub async fn get_evaluate_pool( intermediate_output_path, intermediate_output_path.join("chunks"), intermediate_output_path.join("assets"), - context.environment(), + context.compile_time_info().environment(), ) .build(); @@ -64,7 +64,7 @@ pub async fn get_evaluate_pool( context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), ) .as_asset(); @@ -89,7 +89,7 @@ pub async fn get_evaluate_pool( context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), InnerAssetsVc::cell(HashMap::from([ ("INNER".to_string(), module_asset), ("RUNTIME".to_string(), runtime_asset), diff --git a/crates/turbopack-node/src/transforms/postcss.rs b/crates/turbopack-node/src/transforms/postcss.rs index 0ce56c783b8fd..95e016a71d41a 100644 --- a/crates/turbopack-node/src/transforms/postcss.rs +++ b/crates/turbopack-node/src/transforms/postcss.rs @@ -143,7 +143,7 @@ async fn extra_configs( context, Value::new(EcmascriptModuleAssetType::Ecmascript), EcmascriptInputTransformsVc::cell(vec![]), - context.environment(), + context.compile_time_info(), ) .as_ecmascript_chunk_placeable() }), @@ -174,7 +174,7 @@ fn postcss_executor(context: AssetContextVc, postcss_config_path: FileSystemPath context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), InnerAssetsVc::cell(HashMap::from([("CONFIG".to_string(), config_asset)])), ) .into() diff --git a/crates/turbopack-node/src/transforms/webpack.rs b/crates/turbopack-node/src/transforms/webpack.rs index abf2fb55b5fa3..010552e263f1b 100644 --- a/crates/turbopack-node/src/transforms/webpack.rs +++ b/crates/turbopack-node/src/transforms/webpack.rs @@ -125,7 +125,7 @@ fn webpack_loaders_executor(project_root: FileSystemPathVc, context: AssetContex context, Value::new(EcmascriptModuleAssetType::Typescript), EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]), - context.environment(), + context.compile_time_info(), ) .into() } diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index e8f250be321fd..ef153a2059286 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -31,6 +31,7 @@ use turbopack::{ use turbopack_core::{ asset::{Asset, AssetContent, AssetContentVc, AssetVc}, chunk::{dev::DevChunkingContextVc, ChunkableAsset, ChunkableAssetVc}, + compile_time_info::CompileTimeInfo, context::{AssetContext, AssetContextVc}, environment::{BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment}, issue::IssueVc, @@ -158,10 +159,11 @@ async fn run_test(resource: String) -> Result { )), Value::new(EnvironmentIntention::Client), ); + let compile_time_info = CompileTimeInfo { environment: env }.cell(); let context: AssetContextVc = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - env, + compile_time_info, ModuleOptionsContext { enable_jsx: true, enable_emotion: true, diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js b/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js new file mode 100644 index 0000000000000..92d476000959c --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js @@ -0,0 +1,37 @@ +if (DEFINED_VALUE) { + console.log('DEFINED_VALUE'); +} + +if (DEFINED_TRUE) { + console.log('DEFINED_VALUE'); +} + +if (A.VERY.LONG.DEFINED.VALUE) { + console.log('A.VERY.LONG.DEFINED.VALUE'); +} + +if (process.env.NODE_ENV) { + console.log('something'); +} + +if (process.env.NODE_ENV === 'production') { + console.log('production'); +} + +var p = process; + +// TODO: replacement is not implemented yet +console.log(A.VERY.LONG.DEFINED.VALUE); +console.log(DEFINED_VALUE); +console.log(p.env.NODE_ENV); + +if (p.env.NODE_ENV === 'production') { + console.log('production'); +} + +// TODO tenary is not implemented yet +p.env.NODE_ENV == 'production' ? console.log('production') : console.log('development'); + +// TODO short-circuit is not implemented yet +p.env.NODE_ENV != 'production' && console.log('development'); +p.env.NODE_ENV == 'production' && console.log('production'); diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js new file mode 100644 index 0000000000000..1da4a1ba7df2b --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js @@ -0,0 +1,1083 @@ +(self.TURBOPACK = self.TURBOPACK || []).push(["output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js", { + +"[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)": (function({ r: __turbopack_require__, x: __turbopack_external_require__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, p: process, g: global, __dirname, m: module, e: exports }) { !function() { + +if (DEFINED_VALUE) { + console.log('DEFINED_VALUE'); +} +if (DEFINED_TRUE) { + console.log('DEFINED_VALUE'); +} +if (A.VERY.LONG.DEFINED.VALUE) { + console.log('A.VERY.LONG.DEFINED.VALUE'); +} +if (process.env.NODE_ENV) { + console.log('something'); +} +if (process.env.NODE_ENV === 'production') { + console.log('production'); +} +var p = process; +console.log(A.VERY.LONG.DEFINED.VALUE); +console.log(DEFINED_VALUE); +console.log(p.env.NODE_ENV); +if (p.env.NODE_ENV === 'production') { + console.log('production'); +} +p.env.NODE_ENV == 'production' ? console.log('production') : console.log('development'); +p.env.NODE_ENV != 'production' && console.log('development'); +p.env.NODE_ENV == 'production' && console.log('production'); + +}.call(this) }), +}, ({ loadedChunks, instantiateRuntimeModule }) => { + if(!(true && loadedChunks.has("output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_282715.js"))) return true; + instantiateRuntimeModule("[project]/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js (ecmascript)"); +}]); +(() => { +if (!Array.isArray(globalThis.TURBOPACK)) { + return; +} +/** @typedef {import('../types/backend').RuntimeBackend} RuntimeBackend */ + +/** @type {RuntimeBackend} */ +const BACKEND = { + loadChunk(chunkPath, _from) { + return new Promise((resolve, reject) => { + if (chunkPath.endsWith(".css")) { + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = `/${chunkPath}`; + link.onerror = () => { + reject(); + }; + link.onload = () => { + // CSS chunks do not register themselves, and as such must be marked as + // loaded instantly. + resolve(); + }; + document.body.appendChild(link); + } else if (chunkPath.endsWith(".js")) { + const script = document.createElement("script"); + script.src = `/${chunkPath}`; + // We'll only mark the chunk as loaded once the script has been executed, + // which happens in `registerChunk`. Hence the absence of `resolve()` in + // this branch. + script.onerror = () => { + reject(); + }; + document.body.appendChild(script); + } else { + throw new Error(`can't infer type of chunk from path ${chunkPath}`); + } + }); + }, + + restart: () => self.location.reload(), +}; +/* eslint-disable @next/next/no-assign-module-variable */ + +/** @typedef {import('../types').ChunkRegistration} ChunkRegistration */ +/** @typedef {import('../types').ModuleFactory} ModuleFactory */ + +/** @typedef {import('../types').ChunkPath} ChunkPath */ +/** @typedef {import('../types').ModuleId} ModuleId */ +/** @typedef {import('../types').GetFirstModuleChunk} GetFirstModuleChunk */ + +/** @typedef {import('../types').Module} Module */ +/** @typedef {import('../types').Exports} Exports */ +/** @typedef {import('../types').EsmInteropNamespace} EsmInteropNamespace */ +/** @typedef {import('../types').Runnable} Runnable */ + +/** @typedef {import('../types').Runtime} Runtime */ + +/** @typedef {import('../types').RefreshHelpers} RefreshHelpers */ +/** @typedef {import('../types/hot').Hot} Hot */ +/** @typedef {import('../types/hot').HotData} HotData */ +/** @typedef {import('../types/hot').AcceptCallback} AcceptCallback */ +/** @typedef {import('../types/hot').AcceptErrorHandler} AcceptErrorHandler */ +/** @typedef {import('../types/hot').HotState} HotState */ +/** @typedef {import('../types/protocol').EcmascriptChunkUpdate} EcmascriptChunkUpdate */ +/** @typedef {import('../types/protocol').HmrUpdateEntry} HmrUpdateEntry */ + +/** @typedef {import('../types/runtime').Loader} Loader */ +/** @typedef {import('../types/runtime').ModuleEffect} ModuleEffect */ + +/** @type {Array} */ +let runnable = []; +/** @type {Object.} */ +const moduleFactories = { __proto__: null }; +/** @type {Object.} */ +const moduleCache = { __proto__: null }; +/** + * Contains the IDs of all chunks that have been loaded. + * + * @type {Set} + */ +const loadedChunks = new Set(); +/** + * Maps a chunk ID to the chunk's loader if the chunk is currently being loaded. + * + * @type {Map} + */ +const chunkLoaders = new Map(); +/** + * Maps module IDs to persisted data between executions of their hot module + * implementation (`hot.data`). + * + * @type {Map} + */ +const moduleHotData = new Map(); +/** + * Maps module instances to their hot module state. + * + * @type {Map} + */ +const moduleHotState = new Map(); +/** + * Module IDs that are instantiated as part of the runtime of a chunk. + * + * @type {Set} + */ +const runtimeModules = new Set(); +/** + * Map from module ID to the chunks that contain this module. + * + * In HMR, we need to keep track of which modules are contained in which so + * chunks. This is so we don't eagerly dispose of a module when it is removed + * from chunk A, but still exists in chunk B. + * + * @type {Map>} + */ +const moduleChunksMap = new Map(); +const hOP = Object.prototype.hasOwnProperty; +const _process = + typeof process !== "undefined" + ? process + : { + env: {}, + // Some modules rely on `process.browser` to execute browser-specific code. + // NOTE: `process.browser` is specific to Webpack. + browser: true, + }; + +const toStringTag = typeof Symbol !== "undefined" && Symbol.toStringTag; + +/** + * @param {any} obj + * @param {PropertyKey} name + * @param {PropertyDescriptor & ThisType} options + */ +function defineProp(obj, name, options) { + if (!hOP.call(obj, name)) Object.defineProperty(obj, name, options); +} + +/** + * Adds the getters to the exports object + * + * @param {Exports} exports + * @param {Record any>} getters + */ +function esm(exports, getters) { + defineProp(exports, "__esModule", { value: true }); + if (toStringTag) defineProp(exports, toStringTag, { value: "Module" }); + for (const key in getters) { + defineProp(exports, key, { get: getters[key], enumerable: true }); + } +} + +/** + * Adds the getters to the exports object + * + * @param {Exports} exports + * @param {Record} props + */ +function cjs(exports, props) { + for (const key in props) { + defineProp(exports, key, { get: () => props[key], enumerable: true }); + } +} + +/** + * @param {Module} module + * @param {any} value + */ +function exportValue(module, value) { + module.exports = value; +} + +/** + * @param {Record} obj + * @param {string} key + */ +function createGetter(obj, key) { + return () => obj[key]; +} + +/** + * @param {Exports} raw + * @param {EsmInteropNamespace} ns + * @param {boolean} [allowExportDefault] + */ +function interopEsm(raw, ns, allowExportDefault) { + /** @type {Object. any>} */ + const getters = { __proto__: null }; + for (const key in raw) { + getters[key] = createGetter(raw, key); + } + if (!(allowExportDefault && "default" in getters)) { + getters["default"] = () => raw; + } + esm(ns, getters); +} + +/** + * @param {Module} sourceModule + * @param {ModuleId} id + * @param {boolean} allowExportDefault + * @returns {EsmInteropNamespace} + */ +function esmImport(sourceModule, id, allowExportDefault) { + const module = getOrInstantiateModuleFromParent(id, sourceModule); + const raw = module.exports; + if (raw.__esModule) return raw; + if (module.interopNamespace) return module.interopNamespace; + const ns = (module.interopNamespace = {}); + interopEsm(raw, ns, allowExportDefault); + return ns; +} + +/** + * @param {Module} sourceModule + * @param {ModuleId} id + * @returns {Exports} + */ +function commonJsRequire(sourceModule, id) { + return getOrInstantiateModuleFromParent(id, sourceModule).exports; +} + +function externalRequire(id, esm) { + let raw; + try { + raw = require(id); + } catch (err) { + // TODO(alexkirsz) This can happen when a client-side module tries to load + // an external module we don't provide a shim for (e.g. querystring, url). + // For now, we fail semi-silently, but in the future this should be a + // compilation error. + throw new Error(`Failed to load external module ${id}: ${err}`); + } + if (!esm || raw.__esModule) { + return raw; + } + const ns = {}; + interopEsm(raw, ns, true); + return ns; +} +externalRequire.resolve = (name, opt) => { + return require.resolve(name, opt); +}; + +/** + * @param {ModuleId} from + * @param {string} chunkPath + * @returns {Promise | undefined} + */ +function loadChunk(from, chunkPath) { + if (loadedChunks.has(chunkPath)) { + return Promise.resolve(); + } + + const chunkLoader = getOrCreateChunkLoader(chunkPath, from); + + return chunkLoader.promise; +} + +/** + * @param {string} chunkPath + * @param {ModuleId} from + * @returns {Loader} + */ +function getOrCreateChunkLoader(chunkPath, from) { + let chunkLoader = chunkLoaders.get(chunkPath); + if (chunkLoader) { + return chunkLoader; + } + + let resolve; + let reject; + const promise = new Promise((innerResolve, innerReject) => { + resolve = innerResolve; + reject = innerReject; + }); + + const onError = (error) => { + chunkLoaders.delete(chunkPath); + reject( + new Error( + `Failed to load chunk from ${chunkPath}${error ? `: ${error}` : ""}` + ) + ); + }; + + const onLoad = () => { + loadedChunks.add(chunkPath); + chunkLoaders.delete(chunkPath); + resolve(); + }; + + chunkLoader = { + promise, + onLoad, + }; + chunkLoaders.set(chunkPath, chunkLoader); + + BACKEND.loadChunk(chunkPath, from).then(onLoad, onError); + + return chunkLoader; +} + +/** + * @enum {number} + */ +const SourceType = { + /** + * The module was instantiated because it was included in an evaluated chunk's + * runtime. + */ + Runtime: 0, + /** + * The module was instantiated because a parent module imported it. + */ + Parent: 1, + /** + * The module was instantiated because it was included in a chunk's hot module + * update. + */ + Update: 2, +}; + +/** + * + * @param {ModuleId} id + * @param {SourceType} sourceType + * @param {ModuleId} [sourceId] + * @returns {Module} + */ +function instantiateModule(id, sourceType, sourceId) { + const moduleFactory = moduleFactories[id]; + if (typeof moduleFactory !== "function") { + // This can happen if modules incorrectly handle HMR disposes/updates, + // e.g. when they keep a `setTimeout` around which still executes old code + // and contains e.g. a `require("something")` call. + let instantiationReason; + switch (sourceType) { + case SourceType.Runtime: + instantiationReason = "as a runtime entry"; + break; + case SourceType.Parent: + instantiationReason = `because it was required from module ${sourceId}`; + break; + case SourceType.Update: + instantiationReason = "because of an HMR update"; + break; + } + throw new Error( + `Module ${id} was instantiated ${instantiationReason}, but the module factory is not available. It might have been deleted in an HMR update.` + ); + } + + const hotData = moduleHotData.get(id); + const { hot, hotState } = createModuleHot(hotData); + + /** @type {Module} */ + const module = { + exports: {}, + loaded: false, + id, + parents: [], + children: [], + interopNamespace: undefined, + hot, + }; + moduleCache[id] = module; + moduleHotState.set(module, hotState); + + if (sourceType === SourceType.Runtime) { + runtimeModules.add(id); + } else if (sourceType === SourceType.Parent) { + module.parents.push(sourceId); + + // No need to add this module as a child of the parent module here, this + // has already been taken care of in `getOrInstantiateModuleFromParent`. + } + + runModuleExecutionHooks(module, () => { + moduleFactory.call(module.exports, { + e: module.exports, + r: commonJsRequire.bind(null, module), + x: externalRequire, + i: esmImport.bind(null, module), + s: esm.bind(null, module.exports), + j: cjs.bind(null, module.exports), + v: exportValue.bind(null, module), + m: module, + c: moduleCache, + l: loadChunk.bind(null, id), + p: _process, + g: globalThis, + __dirname: module.id.replace(/(^|\/)[\/]+$/, ""), + }); + }); + + module.loaded = true; + if (module.interopNamespace) { + // in case of a circular dependency: cjs1 -> esm2 -> cjs1 + interopEsm(module.exports, module.interopNamespace); + } + + return module; +} + +/** + * NOTE(alexkirsz) Webpack has an "module execution" interception hook that + * Next.js' React Refresh runtime hooks into to add module context to the + * refresh registry. + * + * @param {Module} module + * @param {() => void} executeModule + */ +function runModuleExecutionHooks(module, executeModule) { + const cleanupReactRefreshIntercept = + typeof globalThis.$RefreshInterceptModuleExecution$ === "function" + ? globalThis.$RefreshInterceptModuleExecution$(module.id) + : () => {}; + + executeModule(); + + if ("$RefreshHelpers$" in globalThis) { + // This pattern can also be used to register the exports of + // a module with the React Refresh runtime. + registerExportsAndSetupBoundaryForReactRefresh( + module, + globalThis.$RefreshHelpers$ + ); + } + + cleanupReactRefreshIntercept(); +} + +/** + * Retrieves a module from the cache, or instantiate it if it is not cached. + * + * @param {ModuleId} id + * @param {Module} sourceModule + * @returns {Module} + */ +function getOrInstantiateModuleFromParent(id, sourceModule) { + if (!sourceModule.hot.active) { + console.warn( + `Unexpected import of module ${id} from module ${sourceModule.id}, which was deleted by an HMR update` + ); + } + + const module = moduleCache[id]; + + if (sourceModule.children.indexOf(id) === -1) { + sourceModule.children.push(id); + } + + if (module) { + if (module.parents.indexOf(sourceModule.id) === -1) { + module.parents.push(sourceModule.id); + } + + return module; + } + + return instantiateModule(id, SourceType.Parent, sourceModule.id); +} + +/** + * This is adapted from https://github.com/vercel/next.js/blob/3466862d9dc9c8bb3131712134d38757b918d1c0/packages/react-refresh-utils/internal/ReactRefreshModule.runtime.ts + * + * @param {Module} module + * @param {RefreshHelpers} helpers + */ +function registerExportsAndSetupBoundaryForReactRefresh(module, helpers) { + const currentExports = module.exports; + const prevExports = module.hot.data.prevExports ?? null; + + helpers.registerExportsForReactRefresh(currentExports, module.id); + + // A module can be accepted automatically based on its exports, e.g. when + // it is a Refresh Boundary. + if (helpers.isReactRefreshBoundary(currentExports)) { + // Save the previous exports on update so we can compare the boundary + // signatures. + module.hot.dispose((data) => { + data.prevExports = currentExports; + }); + // Unconditionally accept an update to this module, we'll check if it's + // still a Refresh Boundary later. + module.hot.accept(); + + // This field is set when the previous version of this module was a + // Refresh Boundary, letting us know we need to check for invalidation or + // enqueue an update. + if (prevExports !== null) { + // A boundary can become ineligible if its exports are incompatible + // with the previous exports. + // + // For example, if you add/remove/change exports, we'll want to + // re-execute the importing modules, and force those components to + // re-render. Similarly, if you convert a class component to a + // function, we want to invalidate the boundary. + if ( + helpers.shouldInvalidateReactRefreshBoundary( + prevExports, + currentExports + ) + ) { + module.hot.invalidate(); + } else { + helpers.scheduleUpdate(); + } + } + } else { + // Since we just executed the code for the module, it's possible that the + // new exports made it ineligible for being a boundary. + // We only care about the case when we were _previously_ a boundary, + // because we already accepted this update (accidental side effect). + const isNoLongerABoundary = prevExports !== null; + if (isNoLongerABoundary) { + module.hot.invalidate(); + } + } +} + +/** + * @param {ModuleId[]} dependencyChain + * @returns {string} + */ +function formatDependencyChain(dependencyChain) { + return `Dependency chain: ${dependencyChain.join(" -> ")}`; +} + +/** + * @param {HmrUpdateEntry} factory + * @returns {ModuleFactory} + * @private + */ +function _eval({ code, url, map }) { + code += `\n\n//# sourceURL=${location.origin}${url}`; + if (map) code += `\n//# sourceMappingURL=${map}`; + return eval(code); +} + +/** + * @param {EcmascriptChunkUpdate} update + * @returns {{outdatedModules: Set, newModuleFactories: Map}} + */ +function computeOutdatedModules(update) { + const outdatedModules = new Set(); + const newModuleFactories = new Map(); + + for (const [moduleId, factory] of Object.entries(update.added)) { + newModuleFactories.set(moduleId, _eval(factory)); + } + + for (const [moduleId, factory] of Object.entries(update.modified)) { + const effect = getAffectedModuleEffects(moduleId); + + switch (effect.type) { + case "unaccepted": + throw new Error( + `cannot apply update: unaccepted module. ${formatDependencyChain( + effect.dependencyChain + )}.` + ); + case "self-declined": + throw new Error( + `cannot apply update: self-declined module. ${formatDependencyChain( + effect.dependencyChain + )}.` + ); + case "accepted": + newModuleFactories.set(moduleId, _eval(factory)); + for (const outdatedModuleId of effect.outdatedModules) { + outdatedModules.add(outdatedModuleId); + } + break; + // TODO(alexkirsz) Dependencies: handle dependencies effects. + } + } + + return { outdatedModules, newModuleFactories }; +} + +/** + * @param {Iterable} outdatedModules + * @returns {{ moduleId: ModuleId, errorHandler: true | Function }[]} + */ +function computeOutdatedSelfAcceptedModules(outdatedModules) { + const outdatedSelfAcceptedModules = []; + for (const moduleId of outdatedModules) { + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module); + if (module && hotState.selfAccepted && !hotState.selfInvalidated) { + outdatedSelfAcceptedModules.push({ + moduleId, + errorHandler: hotState.selfAccepted, + }); + } + } + return outdatedSelfAcceptedModules; +} + +/** + * @param {ChunkPath} chunkPath + * @param {Iterable} outdatedModules + * @param {Iterable} deletedModules + */ +function disposePhase(chunkPath, outdatedModules, deletedModules) { + for (const moduleId of outdatedModules) { + const module = moduleCache[moduleId]; + if (!module) { + continue; + } + + const data = disposeModule(module); + + moduleHotData.set(moduleId, data); + } + + for (const moduleId of deletedModules) { + const module = moduleCache[moduleId]; + if (!module) { + continue; + } + + const noRemainingChunks = removeModuleFromChunk(moduleId, chunkPath); + + if (noRemainingChunks) { + disposeModule(module); + + moduleHotData.delete(moduleId); + } + } + + // TODO(alexkirsz) Dependencies: remove outdated dependency from module + // children. +} + +/** + * Disposes of an instance of a module. + * + * Returns the persistent hot data that should be kept for the next module + * instance. + * + * @param {Module} module + * @returns {{}} + */ +function disposeModule(module) { + const hotState = moduleHotState.get(module); + const data = {}; + + // Run the `hot.dispose` handler, if any, passing in the persistent + // `hot.data` object. + for (const disposeHandler of hotState.disposeHandlers) { + disposeHandler(data); + } + + // This used to warn in `getOrInstantiateModuleFromParent` when a disposed + // module is still importing other modules. + module.hot.active = false; + + delete moduleCache[module.id]; + moduleHotState.delete(module); + + // TODO(alexkirsz) Dependencies: delete the module from outdated deps. + + // Remove the disposed module from its children's parents list. + // It will be added back once the module re-instantiates and imports its + // children again. + for (const childId of module.children) { + const child = moduleCache[childId]; + if (!child) { + continue; + } + + const idx = child.parents.indexOf(module.id); + if (idx >= 0) { + child.parents.splice(idx, 1); + } + } + + return data; +} + +/** + * + * @param {ChunkPath} chunkPath + * @param {{ moduleId: ModuleId, errorHandler: true | Function }[]} outdatedSelfAcceptedModules + * @param {Map} newModuleFactories + */ +function applyPhase( + chunkPath, + outdatedSelfAcceptedModules, + newModuleFactories +) { + // Update module factories. + for (const [moduleId, factory] of newModuleFactories.entries()) { + moduleFactories[moduleId] = factory; + addModuleToChunk(moduleId, chunkPath); + } + + // TODO(alexkirsz) Run new runtime entries here. + + // TODO(alexkirsz) Dependencies: call accept handlers for outdated deps. + + // Re-instantiate all outdated self-accepted modules. + for (const { moduleId, errorHandler } of outdatedSelfAcceptedModules) { + try { + instantiateModule(moduleId, SourceType.Update); + } catch (err) { + if (typeof errorHandler === "function") { + try { + errorHandler(err, { moduleId, module: moduleCache[moduleId] }); + } catch (_) { + // Ignore error. + } + } + } + } +} + +/** + * + * @param {ChunkPath} chunkPath + * @param {EcmascriptChunkUpdate} update + */ +function applyUpdate(chunkPath, update) { + const { outdatedModules, newModuleFactories } = + computeOutdatedModules(update); + + const deletedModules = new Set(update.deleted); + + const outdatedSelfAcceptedModules = + computeOutdatedSelfAcceptedModules(outdatedModules); + + disposePhase(chunkPath, outdatedModules, deletedModules); + applyPhase(chunkPath, outdatedSelfAcceptedModules, newModuleFactories); +} + +/** + * + * @param {ModuleId} moduleId + * @returns {ModuleEffect} + */ +function getAffectedModuleEffects(moduleId) { + const outdatedModules = new Set(); + + /** @typedef {{moduleId?: ModuleId, dependencyChain: ModuleId[]}} QueueItem */ + + /** @type {QueueItem[]} */ + const queue = [ + { + moduleId, + dependencyChain: [], + }, + ]; + + while (queue.length > 0) { + const { moduleId, dependencyChain } = + /** @type {QueueItem} */ queue.shift(); + outdatedModules.add(moduleId); + + // We've arrived at the runtime of the chunk, which means that nothing + // else above can accept this update. + if (moduleId === undefined) { + return { + type: "unaccepted", + dependencyChain, + }; + } + + const module = moduleCache[moduleId]; + const hotState = moduleHotState.get(module); + + if ( + // The module is not in the cache. Since this is a "modified" update, + // it means that the module was never instantiated before. + !module || // The module accepted itself without invalidating globalThis. + // TODO is that right? + (hotState.selfAccepted && !hotState.selfInvalidated) + ) { + continue; + } + + if (hotState.selfDeclined) { + return { + type: "self-declined", + dependencyChain, + moduleId, + }; + } + + if (runtimeModules.has(moduleId)) { + queue.push({ + moduleId: undefined, + dependencyChain: [...dependencyChain, moduleId], + }); + continue; + } + + for (const parentId of module.parents) { + const parent = moduleCache[parentId]; + + if (!parent) { + // TODO(alexkirsz) Is this even possible? + continue; + } + + // TODO(alexkirsz) Dependencies: check accepted and declined + // dependencies here. + + queue.push({ + moduleId: parentId, + dependencyChain: [...dependencyChain, moduleId], + }); + } + } + + return { + type: "accepted", + moduleId, + outdatedModules, + }; +} + +/** + * @param {ChunkPath} chunkPath + * @param {import('../types/protocol').ServerMessage} update + */ +function handleApply(chunkPath, update) { + switch (update.type) { + case "partial": + applyUpdate(chunkPath, update.instruction); + break; + case "restart": + BACKEND.restart(); + break; + default: + throw new Error(`Unknown update type: ${update.type}`); + } +} + +/** + * @param {HotData} [hotData] + * @returns {{hotState: HotState, hot: Hot}} + */ +function createModuleHot(hotData) { + /** @type {HotState} */ + const hotState = { + selfAccepted: false, + selfDeclined: false, + selfInvalidated: false, + disposeHandlers: [], + }; + + /** + * TODO(alexkirsz) Support full (dep, callback, errorHandler) form. + * + * @param {string | string[] | AcceptErrorHandler} [dep] + * @param {AcceptCallback} [_callback] + * @param {AcceptErrorHandler} [_errorHandler] + */ + function accept(dep, _callback, _errorHandler) { + if (dep === undefined) { + hotState.selfAccepted = true; + } else if (typeof dep === "function") { + hotState.selfAccepted = dep; + } else { + throw new Error("unsupported `accept` signature"); + } + } + + /** @type {Hot} */ + const hot = { + // TODO(alexkirsz) This is not defined in the HMR API. It was used to + // decide whether to warn whenever an HMR-disposed module required other + // modules. We might want to remove it. + active: true, + + data: hotData ?? {}, + + accept: accept, + + decline: (dep) => { + if (dep === undefined) { + hotState.selfDeclined = true; + } else { + throw new Error("unsupported `decline` signature"); + } + }, + + dispose: (callback) => { + hotState.disposeHandlers.push(callback); + }, + + addDisposeHandler: (callback) => { + hotState.disposeHandlers.push(callback); + }, + + removeDisposeHandler: (callback) => { + const idx = hotState.disposeHandlers.indexOf(callback); + if (idx >= 0) { + hotState.disposeHandlers.splice(idx, 1); + } + }, + + invalidate: () => { + hotState.selfInvalidated = true; + // TODO(alexkirsz) The original HMR code had management-related code + // here. + }, + + // NOTE(alexkirsz) This is part of the management API, which we don't + // implement, but the Next.js React Refresh runtime uses this to decide + // whether to schedule an update. + status: () => "idle", + + // NOTE(alexkirsz) Since we always return "idle" for now, these are no-ops. + addStatusHandler: (_handler) => {}, + removeStatusHandler: (_handler) => {}, + }; + + return { hot, hotState }; +} + +/** + * Adds a module to a chunk. + * + * @param {ModuleId} moduleId + * @param {ChunkPath} chunkPath + */ +function addModuleToChunk(moduleId, chunkPath) { + let moduleChunks = moduleChunksMap.get(moduleId); + if (!moduleChunks) { + moduleChunks = new Set([chunkPath]); + moduleChunksMap.set(moduleId, moduleChunks); + } else { + moduleChunks.add(chunkPath); + } +} + +/** + * Returns the first chunk that included a module. + * + * @type {GetFirstModuleChunk} + */ +function getFirstModuleChunk(moduleId) { + const moduleChunkPaths = moduleChunksMap.get(moduleId); + if (moduleChunkPaths == null) { + return null; + } + + return moduleChunkPaths.values().next().value; +} + +/** + * Removes a module from a chunk. Returns true there are no remaining chunks + * including this module. + * + * @param {ModuleId} moduleId + * @param {ChunkPath} chunkPath + * @returns {boolean} + */ +function removeModuleFromChunk(moduleId, chunkPath) { + const moduleChunks = moduleChunksMap.get(moduleId); + moduleChunks.delete(chunkPath); + + if (moduleChunks.size > 0) { + return false; + } + + moduleChunksMap.delete(moduleId); + return true; +} + +/** + * Instantiates a runtime module. + */ +/** + * + * @param {ModuleId} moduleId + * @returns {Module} + */ +function instantiateRuntimeModule(moduleId) { + return instantiateModule(moduleId, SourceType.Runtime); +} + +/** + * Subscribes to chunk updates from the update server and applies them. + * + * @param {ChunkPath} chunkPath + */ +function subscribeToChunkUpdates(chunkPath) { + // This adds a chunk update listener once the handler code has been loaded + globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS.push([ + chunkPath, + handleApply.bind(null, chunkPath), + ]); +} + +function markChunkAsLoaded(chunkPath) { + const chunkLoader = chunkLoaders.get(chunkPath); + if (!chunkLoader) { + loadedChunks.add(chunkPath); + + // This happens for all initial chunks that are loaded directly from + // the HTML. + return; + } + + // Only chunks that are loaded via `loadChunk` will have a loader. + chunkLoader.onLoad(); +} + +/** @type {Runtime} */ +const runtime = { + loadedChunks, + modules: moduleFactories, + cache: moduleCache, + instantiateRuntimeModule, +}; + +/** + * @param {ChunkRegistration} chunkRegistration + */ +function registerChunk([chunkPath, chunkModules, ...run]) { + markChunkAsLoaded(chunkPath); + subscribeToChunkUpdates(chunkPath); + for (const [moduleId, moduleFactory] of Object.entries(chunkModules)) { + if (!moduleFactories[moduleId]) { + moduleFactories[moduleId] = moduleFactory; + } + addModuleToChunk(moduleId, chunkPath); + } + runnable.push(...run); + runnable = runnable.filter((r) => r(runtime)); +} + +globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = + globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS || []; + +globalThis.TURBOPACK.forEach(registerChunk); +globalThis.TURBOPACK = { + push: registerChunk, +}; +})(); + + +//# sourceMappingURL=crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js.map \ No newline at end of file diff --git a/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js.map b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js.map new file mode 100644 index 0000000000000..c9ca475290907 --- /dev/null +++ b/crates/turbopack-tests/tests/snapshot/comptime/define/output/crates_turbopack-tests_tests_snapshot_comptime_define_input_index_7c0dc7.js.map @@ -0,0 +1,6 @@ +{ + "version": 3, + "sections": [ + {"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":["/crates/turbopack-tests/tests/snapshot/comptime/define/input/index.js"],"sourcesContent":["if (DEFINED_VALUE) {\n console.log('DEFINED_VALUE');\n}\n\nif (DEFINED_TRUE) {\n console.log('DEFINED_VALUE');\n}\n\nif (A.VERY.LONG.DEFINED.VALUE) {\n console.log('A.VERY.LONG.DEFINED.VALUE');\n}\n\nif (process.env.NODE_ENV) {\n console.log('something');\n}\n\nif (process.env.NODE_ENV === 'production') {\n console.log('production');\n}\n\nvar p = process;\n\n// TODO: replacement is not implemented yet\nconsole.log(A.VERY.LONG.DEFINED.VALUE);\nconsole.log(DEFINED_VALUE);\nconsole.log(p.env.NODE_ENV);\n\nif (p.env.NODE_ENV === 'production') {\n console.log('production');\n}\n\n// TODO tenary is not implemented yet\np.env.NODE_ENV == 'production' ? console.log('production') : console.log('development');\n\n// TODO short-circuit is not implemented yet\np.env.NODE_ENV != 'production' && console.log('development');\np.env.NODE_ENV == 'production' && console.log('production');\n"],"names":[],"mappings":"AAAA,IAAI,eAAe;IACjB,QAAQ,GAAG,CAAC;AACd,CAAC;AAED,IAAI,cAAc;IAChB,QAAQ,GAAG,CAAC;AACd,CAAC;AAED,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;IAC7B,QAAQ,GAAG,CAAC;AACd,CAAC;AAED,IAAI,QAAQ,GAAG,CAAC,QAAQ,EAAE;IACxB,QAAQ,GAAG,CAAC;AACd,CAAC;AAED,IAAI,QAAQ,GAAG,CAAC,QAAQ,KAAK,cAAc;IACzC,QAAQ,GAAG,CAAC;AACd,CAAC;AAED,IAAI,IAAI;AAGR,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;AACrC,QAAQ,GAAG,CAAC;AACZ,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ;AAE1B,IAAI,EAAE,GAAG,CAAC,QAAQ,KAAK,cAAc;IACnC,QAAQ,GAAG,CAAC;AACd,CAAC;AAGD,EAAE,GAAG,CAAC,QAAQ,IAAI,eAAe,QAAQ,GAAG,CAAC,gBAAgB,QAAQ,GAAG,CAAC,cAAc;AAGvF,EAAE,GAAG,CAAC,QAAQ,IAAI,gBAAgB,QAAQ,GAAG,CAAC;AAC9C,EAAE,GAAG,CAAC,QAAQ,IAAI,gBAAgB,QAAQ,GAAG,CAAC"}}, + {"offset": {"line": 29, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":"A"}}] +} \ No newline at end of file diff --git a/crates/turbopack/benches/node_file_trace.rs b/crates/turbopack/benches/node_file_trace.rs index c3b9fb21e6be9..d8ab870790c40 100644 --- a/crates/turbopack/benches/node_file_trace.rs +++ b/crates/turbopack/benches/node_file_trace.rs @@ -11,12 +11,14 @@ use turbopack::{ ModuleAssetContextVc, }; use turbopack_core::{ + compile_time_info::CompileTimeInfo, context::AssetContext, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, reference_type::ReferenceType, source_asset::SourceAssetVc, }; +// TODO this should move to the `node-file-trace` crate pub fn benchmark(c: &mut Criterion) { register(); @@ -78,22 +80,25 @@ fn bench_emit(b: &mut Bencher, bench_input: &BenchInput) { let output_dir = output_fs.root(); let source = SourceAssetVc::new(input); - let environment = EnvironmentVc::new( - Value::new(ExecutionEnvironment::NodeJsLambda( - NodeJsEnvironment::default().into(), - )), - Value::new(EnvironmentIntention::ServerRendering), - ); + let compile_time_info = CompileTimeInfo { + environment: EnvironmentVc::new( + Value::new(ExecutionEnvironment::NodeJsLambda( + NodeJsEnvironment::default().into(), + )), + Value::new(EnvironmentIntention::ServerRendering), + ), + } + .cell(); let context = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - environment, + compile_time_info, ModuleOptionsContext { enable_types: true, ..Default::default() } .cell(), ResolveOptionsContext { - emulate_environment: Some(environment), + emulate_environment: Some(compile_time_info.environment().resolve().await?), ..Default::default() } .cell(), diff --git a/crates/turbopack/examples/turbopack.rs b/crates/turbopack/examples/turbopack.rs index 08cd1f06ee9c7..b256fb3addd92 100644 --- a/crates/turbopack/examples/turbopack.rs +++ b/crates/turbopack/examples/turbopack.rs @@ -23,6 +23,7 @@ use turbopack::{ resolve_options_context::ResolveOptionsContext, transition::TransitionsByNameVc, }; use turbopack_core::{ + compile_time_info::CompileTimeInfoVc, context::AssetContext, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, source_asset::SourceAssetVc, @@ -50,12 +51,12 @@ async fn main() -> Result<()> { let source = SourceAssetVc::new(entry); let context = turbopack::ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - EnvironmentVc::new( + CompileTimeInfoVc::new(EnvironmentVc::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment::default().into(), )), Value::new(EnvironmentIntention::ServerRendering), - ), + )), Default::default(), ResolveOptionsContext { enable_typescript: true, diff --git a/crates/turbopack/src/evaluate_context.rs b/crates/turbopack/src/evaluate_context.rs index 9982abdf03ed0..cf37022e67890 100644 --- a/crates/turbopack/src/evaluate_context.rs +++ b/crates/turbopack/src/evaluate_context.rs @@ -1,5 +1,6 @@ use turbo_tasks::Value; use turbopack_core::{ + compile_time_info::CompileTimeInfoVc, context::AssetContextVc, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, resolve::options::ImportMapVc, @@ -14,12 +15,12 @@ use crate::{ pub fn node_evaluate_asset_context(import_map: Option) -> AssetContextVc { ModuleAssetContextVc::new( TransitionsByNameVc::cell(Default::default()), - EnvironmentVc::new( + CompileTimeInfoVc::new(EnvironmentVc::new( Value::new(ExecutionEnvironment::NodeJsBuildTime( NodeJsEnvironment::default().cell(), )), Value::new(EnvironmentIntention::Build), - ), + )), ModuleOptionsContext { enable_typescript_transform: true, ..Default::default() diff --git a/crates/turbopack/src/lib.rs b/crates/turbopack/src/lib.rs index 250eb21131792..70dddd3d97251 100644 --- a/crates/turbopack/src/lib.rs +++ b/crates/turbopack/src/lib.rs @@ -32,8 +32,8 @@ use turbo_tasks::{ use turbo_tasks_fs::FileSystemPathVc; use turbopack_core::{ asset::{Asset, AssetVc}, + compile_time_info::CompileTimeInfoVc, context::{AssetContext, AssetContextVc}, - environment::EnvironmentVc, issue::{unsupported_module::UnsupportedModuleIssue, Issue, IssueVc}, reference::all_referenced_assets, reference_type::ReferenceType, @@ -116,7 +116,7 @@ async fn apply_module_type( context.into(), Value::new(EcmascriptModuleAssetType::Ecmascript), *transforms, - context.environment(), + context.compile_time_info(), ) .into(), ModuleType::Typescript(transforms) => EcmascriptModuleAssetVc::new( @@ -124,7 +124,7 @@ async fn apply_module_type( context.into(), Value::new(EcmascriptModuleAssetType::Typescript), *transforms, - context.environment(), + context.compile_time_info(), ) .into(), ModuleType::TypescriptWithTypes(transforms) => EcmascriptModuleAssetVc::new( @@ -132,7 +132,7 @@ async fn apply_module_type( context.with_types_resolving_enabled().into(), Value::new(EcmascriptModuleAssetType::TypescriptWithTypes), *transforms, - context.environment(), + context.compile_time_info(), ) .into(), ModuleType::TypescriptDeclaration(transforms) => EcmascriptModuleAssetVc::new( @@ -140,7 +140,7 @@ async fn apply_module_type( context.with_types_resolving_enabled().into(), Value::new(EcmascriptModuleAssetType::TypescriptDeclaration), *transforms, - context.environment(), + context.compile_time_info(), ) .into(), ModuleType::Json => JsonModuleAssetVc::new(source).into(), @@ -246,7 +246,7 @@ async fn module( #[turbo_tasks::value] pub struct ModuleAssetContext { transitions: TransitionsByNameVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, module_options_context: ModuleOptionsContextVc, resolve_options_context: ResolveOptionsContextVc, transition: Option, @@ -257,13 +257,13 @@ impl ModuleAssetContextVc { #[turbo_tasks::function] pub fn new( transitions: TransitionsByNameVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, module_options_context: ModuleOptionsContextVc, resolve_options_context: ResolveOptionsContextVc, ) -> Self { Self::cell(ModuleAssetContext { transitions, - environment, + compile_time_info, module_options_context, resolve_options_context, transition: None, @@ -273,14 +273,14 @@ impl ModuleAssetContextVc { #[turbo_tasks::function] pub fn new_transition( transitions: TransitionsByNameVc, - environment: EnvironmentVc, + compile_time_info: CompileTimeInfoVc, module_options_context: ModuleOptionsContextVc, resolve_options_context: ResolveOptionsContextVc, transition: TransitionVc, ) -> Self { Self::cell(ModuleAssetContext { transitions, - environment, + compile_time_info, module_options_context, resolve_options_context, transition: Some(transition), @@ -313,7 +313,7 @@ impl ModuleAssetContextVc { .await?; Ok(ModuleAssetContextVc::new( this.transitions, - this.environment, + this.compile_time_info, this.module_options_context, resolve_options_context, )) @@ -323,8 +323,8 @@ impl ModuleAssetContextVc { #[turbo_tasks::value_impl] impl AssetContext for ModuleAssetContext { #[turbo_tasks::function] - fn environment(&self) -> EnvironmentVc { - self.environment + fn compile_time_info(&self) -> CompileTimeInfoVc { + self.compile_time_info } #[turbo_tasks::function] @@ -392,14 +392,14 @@ impl AssetContext for ModuleAssetContext { let this = self_vc.await?; if let Some(transition) = this.transition { let asset = transition.process_source(asset); - let environment = transition.process_environment(this.environment); + let compile_time_info = transition.process_compile_time_info(this.compile_time_info); let module_options_context = transition.process_module_options_context(this.module_options_context); let resolve_options_context = transition.process_resolve_options_context(this.resolve_options_context); let context = ModuleAssetContextVc::new( this.transitions, - environment, + compile_time_info, module_options_context, resolve_options_context, ); @@ -408,7 +408,7 @@ impl AssetContext for ModuleAssetContext { } else { let context = ModuleAssetContextVc::new( this.transitions, - this.environment, + this.compile_time_info, this.module_options_context, this.resolve_options_context, ); @@ -422,7 +422,7 @@ impl AssetContext for ModuleAssetContext { if let Some(transition) = self.transitions.await?.get(transition) { ModuleAssetContextVc::new_transition( self.transitions, - self.environment, + self.compile_time_info, self.module_options_context, self.resolve_options_context, *transition, @@ -432,7 +432,7 @@ impl AssetContext for ModuleAssetContext { // TODO report issue ModuleAssetContextVc::new( self.transitions, - self.environment, + self.compile_time_info, self.module_options_context, self.resolve_options_context, ) diff --git a/crates/turbopack/src/transition/mod.rs b/crates/turbopack/src/transition/mod.rs index da42b231213b4..09ba9364b3a1c 100644 --- a/crates/turbopack/src/transition/mod.rs +++ b/crates/turbopack/src/transition/mod.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use turbopack_core::{asset::AssetVc, environment::EnvironmentVc}; +use turbopack_core::{asset::AssetVc, compile_time_info::CompileTimeInfoVc}; use crate::{ module_options::ModuleOptionsContextVc, resolve_options_context::ResolveOptionsContextVc, @@ -16,9 +16,9 @@ pub trait Transition { fn process_source(&self, asset: AssetVc) -> AssetVc { asset } - /// Apply modifications to the environment - fn process_environment(&self, environment: EnvironmentVc) -> EnvironmentVc { - environment + /// Apply modifications to the compile-time information + fn process_compile_time_info(&self, compile_time_info: CompileTimeInfoVc) -> CompileTimeInfoVc { + compile_time_info } /// Apply modifications/wrapping to the module options context fn process_module_options_context( diff --git a/crates/turbopack/tests/node-file-trace.rs b/crates/turbopack/tests/node-file-trace.rs index 441496f6304e8..71c8a48c961ca 100644 --- a/crates/turbopack/tests/node-file-trace.rs +++ b/crates/turbopack/tests/node-file-trace.rs @@ -34,6 +34,7 @@ use turbopack::{ #[cfg(not(feature = "bench_against_node_nft"))] use turbopack_core::asset::Asset; use turbopack_core::{ + compile_time_info::CompileTimeInfoVc, context::AssetContext, environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, reference_type::ReferenceType, @@ -403,12 +404,15 @@ fn node_file_trace( let source = SourceAssetVc::new(input); let context = ModuleAssetContextVc::new( TransitionsByNameVc::cell(HashMap::new()), - EnvironmentVc::new( + // TODO It's easy to make a mistake here as this should match the config in the + // binary. TODO These test cases should move into the + // `node-file-trace` crate and use the same config. + CompileTimeInfoVc::new(EnvironmentVc::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment::default().into(), )), Value::new(EnvironmentIntention::ServerRendering), - ), + )), ModuleOptionsContext { enable_types: true, ..Default::default()