diff --git a/crates/turbopack-ecmascript/Cargo.toml b/crates/turbopack-ecmascript/Cargo.toml index 105d36b868d8d..8142da8f863bb 100644 --- a/crates/turbopack-ecmascript/Cargo.toml +++ b/crates/turbopack-ecmascript/Cargo.toml @@ -55,6 +55,7 @@ swc_core = { workspace = true, features = [ "ecma_transforms", "ecma_transforms_module", "ecma_transforms_react", + "ecma_transforms_optimization", "ecma_transforms_typescript", "ecma_transforms_proposal", "ecma_quote", diff --git a/crates/turbopack-ecmascript/src/transform/mod.rs b/crates/turbopack-ecmascript/src/transform/mod.rs index 24e325751bb4b..b7383e529d565 100644 --- a/crates/turbopack-ecmascript/src/transform/mod.rs +++ b/crates/turbopack-ecmascript/src/transform/mod.rs @@ -3,13 +3,15 @@ use std::{fmt::Debug, hash::Hash, sync::Arc}; use anyhow::Result; use async_trait::async_trait; use swc_core::{ + atoms::JsWord, base::SwcComments, - common::{chain, comments::Comments, util::take::Take, Mark, SourceMap}, + common::{chain, collections::AHashMap, comments::Comments, util::take::Take, Mark, SourceMap}, ecma::{ ast::{Module, ModuleItem, Program, Script}, preset_env::{self, Targets}, transforms::{ base::{feature::FeatureFlag, helpers::inject_helpers, Assumptions}, + optimization::inline_globals2, react::react, }, visit::{FoldWith, VisitMutWith}, @@ -39,6 +41,9 @@ pub enum EcmascriptInputTransform { // swc.jsc.transform.react.runtime, runtime: Vc>, }, + GlobalTypeofs { + window_value: String, + }, // These options are subset of swc_core::ecma::transforms::typescript::Config, but // it doesn't derive `Copy` so repeating values in here TypeScript { @@ -134,6 +139,17 @@ impl EcmascriptInputTransform { .. } = ctx; match self { + EcmascriptInputTransform::GlobalTypeofs { window_value } => { + let mut typeofs: AHashMap = Default::default(); + typeofs.insert("window".into(), JsWord::from(&**window_value)); + + program.visit_mut_with(&mut inline_globals2( + Default::default(), + Default::default(), + Default::default(), + Arc::new(typeofs), + )); + } EcmascriptInputTransform::React { development, refresh, diff --git a/crates/turbopack/src/module_options/mod.rs b/crates/turbopack/src/module_options/mod.rs index fb01248ae7a2a..f2d7bc83e3b30 100644 --- a/crates/turbopack/src/module_options/mod.rs +++ b/crates/turbopack/src/module_options/mod.rs @@ -81,6 +81,7 @@ impl ModuleOptions { import_externals, ignore_dynamic_requests, use_swc_css, + ref enable_typeof_window_inlining, .. } = *module_options_context.await?; if !rules.is_empty() { @@ -130,6 +131,15 @@ impl ModuleOptions { transforms.push(EcmascriptInputTransform::PresetEnv(env)); } + if let Some(enable_typeof_window_inlining) = enable_typeof_window_inlining { + transforms.push(EcmascriptInputTransform::GlobalTypeofs { + window_value: match enable_typeof_window_inlining { + TypeofWindow::Object => "object".to_string(), + TypeofWindow::Undefined => "undefined".to_string(), + }, + }); + } + let ts_transform = if let Some(options) = enable_typescript_transform { let options = options.await?; Some(EcmascriptInputTransform::TypeScript { diff --git a/crates/turbopack/src/module_options/module_options_context.rs b/crates/turbopack/src/module_options/module_options_context.rs index 1e9dd365c216b..ac068c1496ba7 100644 --- a/crates/turbopack/src/module_options/module_options_context.rs +++ b/crates/turbopack/src/module_options/module_options_context.rs @@ -46,6 +46,13 @@ pub enum DecoratorsKind { Ecma, } +/// The types when replacing `typeof window` with a constant. +#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] +pub enum TypeofWindow { + Object, + Undefined, +} + /// Configuration options for the decorators transform. /// This is not part of Typescript transform: while there are typescript /// specific transforms (legay decorators), there is an ecma decorator transform @@ -105,6 +112,7 @@ pub struct JsxTransformOptions { #[derive(Default, Clone)] #[serde(default)] pub struct ModuleOptionsContext { + pub enable_typeof_window_inlining: Option, pub enable_jsx: Option>, pub enable_postcss_transform: Option>, pub enable_webpack_loaders: Option>,