diff --git a/crates/next-core/src/next_client/context.rs b/crates/next-core/src/next_client/context.rs index 8762f1d992ecb..b9dfb28f84917 100644 --- a/crates/next-core/src/next_client/context.rs +++ b/crates/next-core/src/next_client/context.rs @@ -8,7 +8,7 @@ use turbo_tasks_fs::FileSystemPath; use turbopack::{ css::chunk::CssChunkType, module_options::{ - CssOptionsContext, EcmascriptOptionsContext, JsxTransformOptions, ModuleRule, TypeofWindow, + CssOptionsContext, EcmascriptOptionsContext, JsxTransformOptions, ModuleRule, TypescriptTransformOptions, module_options_context::ModuleOptionsContext, }, resolve_options_context::ResolveOptionsContext, @@ -28,7 +28,7 @@ use turbopack_core::{ module_graph::export_usage::OptionExportUsageInfo, resolve::{parse::Request, pattern::Pattern}, }; -use turbopack_ecmascript::chunk::EcmascriptChunkType; +use turbopack_ecmascript::{TypeofWindow, chunk::EcmascriptChunkType}; use turbopack_node::{ execution_context::ExecutionContext, transforms::postcss::{PostCssConfigLocation, PostCssTransformOptions}, diff --git a/crates/next-core/src/next_server/context.rs b/crates/next-core/src/next_server/context.rs index a79da5c3ae305..a5366dc4aea99 100644 --- a/crates/next-core/src/next_server/context.rs +++ b/crates/next-core/src/next_server/context.rs @@ -9,7 +9,7 @@ use turbopack::{ css::chunk::CssChunkType, module_options::{ CssOptionsContext, EcmascriptOptionsContext, ExternalsTracingOptions, JsxTransformOptions, - ModuleOptionsContext, ModuleRule, TypeofWindow, TypescriptTransformOptions, + ModuleOptionsContext, ModuleRule, TypescriptTransformOptions, }, resolve_options_context::ResolveOptionsContext, transition::Transition, @@ -28,7 +28,9 @@ use turbopack_core::{ module_graph::export_usage::OptionExportUsageInfo, target::CompileTarget, }; -use turbopack_ecmascript::{chunk::EcmascriptChunkType, references::esm::UrlRewriteBehavior}; +use turbopack_ecmascript::{ + TypeofWindow, chunk::EcmascriptChunkType, references::esm::UrlRewriteBehavior, +}; use turbopack_ecmascript_plugins::transform::directives::{ client::ClientDirectiveTransformer, client_disallowed::ClientDisallowedDirectiveTransformer, }; diff --git a/turbopack/crates/turbopack-ecmascript/src/lib.rs b/turbopack/crates/turbopack-ecmascript/src/lib.rs index ed804f18e4325..cf38622ed3ac6 100644 --- a/turbopack/crates/turbopack-ecmascript/src/lib.rs +++ b/turbopack/crates/turbopack-ecmascript/src/lib.rs @@ -175,8 +175,27 @@ pub enum TreeShakingMode { #[turbo_tasks::value(transparent)] pub struct OptionTreeShaking(pub Option); +/// The constant to replace `typeof window` with. +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Debug, + Hash, + Serialize, + Deserialize, + TraceRawVcs, + NonLocalValue, + TaskInput, +)] +pub enum TypeofWindow { + Object, + Undefined, +} + #[turbo_tasks::value(shared)] -#[derive(Hash, Debug, Default, Copy, Clone)] +#[derive(Debug, Default, Copy, Clone)] pub struct EcmascriptOptions { /// variant of tree shaking to use pub tree_shaking_mode: Option, @@ -203,6 +222,11 @@ pub struct EcmascriptOptions { /// Whether the modules in this context are never chunked/codegen-ed, but only used for /// tracing. pub is_tracing: bool, + // TODO this should just be handled via CompileTimeInfo FreeVarReferences, but then it + // (currently) wouldn't be possible to have different replacement values in user code vs + // node_modules. + /// Whether to replace `typeof window` with some constant value. + pub enable_typeof_window_inlining: Option, } #[turbo_tasks::value] diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index 8a3f3b6fe3dec..abc9788d630e0 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -67,8 +67,8 @@ use turbo_tasks::{ use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ compile_time_info::{ - CompileTimeDefineValue, CompileTimeInfo, DefinableNameSegment, FreeVarReference, - FreeVarReferences, FreeVarReferencesIndividual, InputRelativeConstant, + CompileTimeDefineValue, CompileTimeDefines, CompileTimeInfo, DefinableNameSegment, + FreeVarReference, FreeVarReferences, FreeVarReferencesIndividual, InputRelativeConstant, }, environment::Rendering, error::PrettyPrintError, @@ -130,7 +130,7 @@ use super::{ pub use crate::references::esm::export::{FollowExportsResult, follow_reexports}; use crate::{ EcmascriptInputTransforms, EcmascriptModuleAsset, EcmascriptParsable, SpecifiedModuleType, - TreeShakingMode, + TreeShakingMode, TypeofWindow, analyzer::{ ConstantNumber, ConstantString, JsValueUrlKind, RequireContextValue, builtin::early_replace_builtin, @@ -617,10 +617,13 @@ pub async fn analyse_ecmascript_module_internal( analysis.set_has_side_effect_free_directive(has_side_effect_free_directive); let is_esm = eval_context.is_esm(specified_type); - let compile_time_info = - compile_time_info_for_module_type(*raw_module.compile_time_info, is_esm) - .to_resolved() - .await?; + let compile_time_info = compile_time_info_for_module_options( + *raw_module.compile_time_info, + is_esm, + options.enable_typeof_window_inlining, + ) + .to_resolved() + .await?; let pos = program.span().lo; if analyze_types { @@ -1471,9 +1474,10 @@ pub async fn analyse_ecmascript_module_internal( } #[turbo_tasks::function] -async fn compile_time_info_for_module_type( +async fn compile_time_info_for_module_options( compile_time_info: Vc, is_esm: bool, + enable_typeof_window_inlining: Option, ) -> Result> { let compile_time_info = compile_time_info.await?; let free_var_references = compile_time_info.free_var_references; @@ -1584,9 +1588,33 @@ async fn compile_time_info_for_module_type( } else { rcstr!("object").into() }); + + let mut defines = compile_time_info.defines; + if let Some(enable_typeof_window_inlining) = enable_typeof_window_inlining { + let value = match enable_typeof_window_inlining { + TypeofWindow::Object => rcstr!("object"), + TypeofWindow::Undefined => rcstr!("undefined"), + }; + let window = rcstr!("window"); + let mut defines_value = defines.owned().await?; + defines_value + .entry(vec![ + DefinableNameSegment::Name(window.clone()), + DefinableNameSegment::TypeOf, + ]) + .or_insert(value.clone().into()); + free_var_references + .entry(vec![ + DefinableNameSegment::Name(window), + DefinableNameSegment::TypeOf, + ]) + .or_insert(value.into()); + defines = CompileTimeDefines(defines_value).resolved_cell() + } + Ok(CompileTimeInfo { environment: compile_time_info.environment, - defines: compile_time_info.defines, + defines, free_var_references: FreeVarReferences(free_var_references).resolved_cell(), } .cell()) diff --git a/turbopack/crates/turbopack-ecmascript/src/transform/mod.rs b/turbopack/crates/turbopack-ecmascript/src/transform/mod.rs index 000fe2b9c194c..4b7e9847b7efc 100644 --- a/turbopack/crates/turbopack-ecmascript/src/transform/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/transform/mod.rs @@ -2,7 +2,6 @@ use std::{fmt::Debug, hash::Hash, sync::Arc}; use anyhow::Result; use async_trait::async_trait; -use rustc_hash::FxHashMap; use swc_core::{ atoms::{Atom, atom}, base::SwcComments, @@ -15,7 +14,6 @@ use swc_core::{ assumptions::Assumptions, helpers::{HELPERS, HelperData, Helpers}, }, - optimization::inline_globals, react::react, }, utils::IsDirective, @@ -44,9 +42,6 @@ pub enum EcmascriptInputTransform { // swc.jsc.transform.react.runtime, runtime: ResolvedVc>, }, - GlobalTypeofs { - window_value: RcStr, - }, // These options are subset of swc_core::ecma::transforms::typescript::Config, but // it doesn't derive `Copy` so repeating values in here TypeScript { @@ -139,22 +134,6 @@ impl EcmascriptInputTransform { } = ctx; Ok(match self { - EcmascriptInputTransform::GlobalTypeofs { window_value } => { - let mut typeofs: FxHashMap = Default::default(); - typeofs.insert(Atom::from("window"), Atom::from(&**window_value)); - - apply_transform( - program, - helpers, - inline_globals( - unresolved_mark, - Default::default(), - Default::default(), - Default::default(), - Arc::new(typeofs), - ), - ) - } EcmascriptInputTransform::React { development, refresh, diff --git a/turbopack/crates/turbopack/src/module_options/mod.rs b/turbopack/crates/turbopack/src/module_options/mod.rs index 0653f05cffd71..4b999d2538d24 100644 --- a/turbopack/crates/turbopack/src/module_options/mod.rs +++ b/turbopack/crates/turbopack/src/module_options/mod.rs @@ -207,7 +207,7 @@ impl ModuleOptions { ignore_dynamic_requests, import_externals, esm_url_rewrite_behavior, - ref enable_typeof_window_inlining, + enable_typeof_window_inlining, source_maps: ecmascript_source_maps, .. }, @@ -282,6 +282,7 @@ impl ModuleOptions { extract_source_map: matches!(ecmascript_source_maps, SourceMapsType::Full), keep_last_successful_parse, is_tracing, + enable_typeof_window_inlining, ..Default::default() }; let ecmascript_options_vc = ecmascript_options.resolved_cell(); @@ -290,15 +291,6 @@ impl ModuleOptions { postprocess.push(EcmascriptInputTransform::PresetEnv(environment)); } - if let Some(enable_typeof_window_inlining) = enable_typeof_window_inlining { - postprocess.push(EcmascriptInputTransform::GlobalTypeofs { - window_value: match enable_typeof_window_inlining { - TypeofWindow::Object => rcstr!("object"), - TypeofWindow::Undefined => rcstr!("undefined"), - }, - }); - } - let ts_transform = if let Some(options) = enable_typescript_transform { let options = options.await?; Some(EcmascriptInputTransform::TypeScript { diff --git a/turbopack/crates/turbopack/src/module_options/module_options_context.rs b/turbopack/crates/turbopack/src/module_options/module_options_context.rs index dca57bcdc9f62..1d6a1fb78c5dd 100644 --- a/turbopack/crates/turbopack/src/module_options/module_options_context.rs +++ b/turbopack/crates/turbopack/src/module_options/module_options_context.rs @@ -9,7 +9,7 @@ use turbopack_core::{ chunk::SourceMapsType, compile_time_info::CompileTimeInfo, condition::ContextCondition, environment::Environment, resolve::options::ImportMapping, }; -use turbopack_ecmascript::{TreeShakingMode, references::esm::UrlRewriteBehavior}; +use turbopack_ecmascript::{TreeShakingMode, TypeofWindow, references::esm::UrlRewriteBehavior}; pub use turbopack_mdx::MdxTransformOptions; use turbopack_node::{ execution_context::ExecutionContext, @@ -108,13 +108,6 @@ pub enum DecoratorsKind { Ecma, } -/// The types when replacing `typeof window` with a constant. -#[derive(Copy, Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize, NonLocalValue)] -pub enum TypeofWindow { - Object, - Undefined, -} - /// Configuration options for the decorators transform. /// /// This is not part of Typescript transform: while there are typescript @@ -223,6 +216,9 @@ pub struct ModuleOptionsContext { #[derive(Clone, Default)] #[serde(default)] pub struct EcmascriptOptionsContext { + // TODO this should just be handled via CompileTimeInfo FreeVarReferences, but then it + // (currently) wouldn't be possible to have different replacement values in user code vs + // node_modules. pub enable_typeof_window_inlining: Option, pub enable_jsx: Option>, /// Follow type references and resolve declaration files in additional to