Skip to content

Commit

Permalink
Only insert CJS globals if undeclared
Browse files Browse the repository at this point in the history
  • Loading branch information
mischnic committed Sep 25, 2024
1 parent 1f929b6 commit 6ef7bbb
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 32 deletions.
53 changes: 41 additions & 12 deletions turbopack/crates/turbopack-ecmascript/src/chunk/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use turbopack_core::{
};

use crate::{
references::async_module::{AsyncModuleOptions, OptionAsyncModuleOptions},
references::{
async_module::{AsyncModuleOptions, OptionAsyncModuleOptions},
DeclaredCjsGlobals,
},
utils::FormatIter,
EcmascriptModuleContent, EcmascriptOptions,
};
Expand All @@ -35,6 +38,7 @@ impl EcmascriptChunkItemContent {
chunking_context: Vc<Box<dyn ChunkingContext>>,
options: Vc<EcmascriptOptions>,
async_module_options: Vc<OptionAsyncModuleOptions>,
declared_cjs_globals: Vc<DeclaredCjsGlobals>,
) -> Result<Vc<Self>> {
let refresh = options.await?.refresh;
let externals = *chunking_context
Expand All @@ -44,6 +48,7 @@ impl EcmascriptChunkItemContent {

let content = content.await?;
let async_module = async_module_options.await?.clone_value();
let declared_cjs_globals = declared_cjs_globals.await?;

Ok(EcmascriptChunkItemContent {
inner_code: content.inner_code.clone(),
Expand All @@ -54,7 +59,11 @@ impl EcmascriptChunkItemContent {
refresh,
externals,
async_module,
stub_require: true,
require: if declared_cjs_globals.require {
EcmascriptChunkItemRequireType::None
} else {
EcmascriptChunkItemRequireType::Stub
},
..Default::default()
}
} else {
Expand All @@ -65,10 +74,12 @@ impl EcmascriptChunkItemContent {
EcmascriptChunkItemOptions {
refresh,
externals,
// These things are not available in ESM
require: EcmascriptChunkItemRequireType::Real,
// These are not available in ESM
module: true,
exports: true,
this: true,
dirname: true,
..Default::default()
}
},
Expand Down Expand Up @@ -96,8 +107,6 @@ impl EcmascriptChunkItemContent {
"R: __turbopack_resolve_module_id_path__",
"b: __turbopack_worker_blob_url__",
"g: global",
// HACK
"__dirname",
];
if this.options.async_module.is_some() {
args.push("a: __turbopack_async_module__");
Expand All @@ -109,21 +118,26 @@ impl EcmascriptChunkItemContent {
if this.options.refresh {
args.push("k: __turbopack_refresh__");
}
if this.options.dirname {
args.push("__dirname");
}
if this.options.module || this.options.refresh {
args.push("m: module");
}
if this.options.exports {
args.push("e: exports");
}
if this.options.stub_require {
args.push("z: require");
} else {
args.push("t: require");
match this.options.require {
EcmascriptChunkItemRequireType::Real => args.push("t: require"),
EcmascriptChunkItemRequireType::Stub => args.push("z: require"),
EcmascriptChunkItemRequireType::None => {}
}

if this.options.wasm {
args.push("w: __turbopack_wasm__");
args.push("u: __turbopack_wasm_module__");
}

let mut code = CodeBuilder::default();
let args = FormatIter(|| args.iter().copied().intersperse(", "));
if this.options.this {
Expand Down Expand Up @@ -159,6 +173,17 @@ impl EcmascriptChunkItemContent {
}
}

#[derive(PartialEq, Eq, Default, Debug, Clone, Serialize, Deserialize, TraceRawVcs)]
pub enum EcmascriptChunkItemRequireType {
/// No require at all
#[default]
None,
/// A throwing stub (for ESM)
Stub,
/// The real require
Real,
}

#[derive(PartialEq, Eq, Default, Debug, Clone, Serialize, Deserialize, TraceRawVcs)]
pub struct EcmascriptChunkItemOptions {
/// Whether this chunk item should be in "use strict" mode.
Expand All @@ -172,15 +197,19 @@ pub struct EcmascriptChunkItemOptions {
/// Whether this chunk item's module factory should include an `exports`
/// argument.
pub exports: bool,
/// Whether this chunk item's module factory should include an argument for the real `require`,
/// or just a throwing stub (for ESM)
pub stub_require: bool,
/// Whether this chunk item's module factory should include an `__dirname`
/// argument.
pub dirname: bool,
/// What `require` argument this chunk item's module factory should include
/// an argument for the real `require`.
pub require: EcmascriptChunkItemRequireType,
/// Whether this chunk item's module factory should include a
/// `__turbopack_external_require__` argument.
pub externals: bool,
/// Whether this chunk item's module is async (either has a top level await
/// or is importing async modules).
pub async_module: Option<AsyncModuleOptions>,
/// Whether this chunk item accesses the module-global `this` object.
pub this: bool,
/// Whether this chunk item's module factory should include
/// `__turbopack_wasm__` to load WebAssembly.
Expand Down
42 changes: 24 additions & 18 deletions turbopack/crates/turbopack-ecmascript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ use swc_core::{
visit::{VisitMutWith, VisitMutWithAstPath},
},
};
use tracing::Instrument;
pub use transform::{
CustomTransformer, EcmascriptInputTransform, EcmascriptInputTransforms, OptionTransformPlugin,
TransformContext, TransformPlugin, UnsupportedServerActionIssue,
Expand Down Expand Up @@ -685,27 +686,32 @@ impl EcmascriptChunkItem for ModuleChunkItem {
async_module_info: Option<Vc<AsyncModuleInfo>>,
) -> Result<Vc<EcmascriptChunkItemContent>> {
let this = self.await?;
let _span = tracing::info_span!(
async {
let async_module_options = this
.module
.get_async_module()
.module_options(async_module_info);

// TODO check if we need to pass async_module_info at all
let content = this
.module
.module_content(this.chunking_context, async_module_info);

let declared_cjs_globals = this.module.analyze().await?.declared_cjs_globals;

Ok(EcmascriptChunkItemContent::new(
content,
this.chunking_context,
this.module.options(),
async_module_options,
declared_cjs_globals,
))
}
.instrument(tracing::info_span!(
"code generation",
module = self.asset_ident().to_string().await?.to_string()
)
.entered();
let async_module_options = this
.module
.get_async_module()
.module_options(async_module_info);

// TODO check if we need to pass async_module_info at all
let content = this
.module
.module_content(this.chunking_context, async_module_info);

Ok(EcmascriptChunkItemContent::new(
content,
this.chunking_context,
this.module.options(),
async_module_options,
))
.await
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{fmt::Display, io::Write};

use anyhow::Result;
use serde::{Deserialize, Serialize};
use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput, Vc};
use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput, ValueDefault, Vc};
use turbo_tasks_fs::{glob::Glob, rope::RopeBuilder, FileContent, FileSystem, VirtualFileSystem};
use turbopack_core::{
asset::{Asset, AssetContent},
Expand All @@ -12,6 +12,7 @@ use turbopack_core::{
reference::ModuleReferences,
};

use super::DeclaredCjsGlobals;
use crate::{
chunk::{
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable,
Expand Down Expand Up @@ -241,6 +242,7 @@ impl EcmascriptChunkItem for CachedExternalModuleChunkItem {
self.chunking_context,
EcmascriptOptions::default().cell(),
async_module_options,
DeclaredCjsGlobals::value_default(),
))
}
}
Expand Down
33 changes: 32 additions & 1 deletion turbopack/crates/turbopack-ecmascript/src/references/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use swc_core::{
},
};
use tracing::Instrument;
use turbo_tasks::{RcStr, TryJoinIterExt, Upcast, Value, ValueToString, Vc};
use turbo_tasks::{RcStr, TryJoinIterExt, Upcast, Value, ValueDefault, ValueToString, Vc};
use turbo_tasks_fs::FileSystemPath;
use turbopack_core::{
compile_time_info::{
Expand Down Expand Up @@ -143,6 +143,22 @@ use crate::{
TreeShakingMode,
};

#[turbo_tasks::value(shared)]
#[derive(Clone, Debug, Default)]
pub struct DeclaredCjsGlobals {
pub dirname: bool,
pub filename: bool,
pub require: bool,
}

#[turbo_tasks::value_impl]
impl ValueDefault for DeclaredCjsGlobals {
#[turbo_tasks::function]
fn value_default() -> Vc<Self> {
Self::default().cell()
}
}

#[turbo_tasks::value(shared)]
#[derive(Clone)]
pub struct AnalyzeEcmascriptModuleResult {
Expand All @@ -153,6 +169,7 @@ pub struct AnalyzeEcmascriptModuleResult {
pub code_generation: Vc<CodeGenerateables>,
pub exports: Vc<EcmascriptExports>,
pub async_module: Vc<OptionAsyncModule>,
pub declared_cjs_globals: Vc<DeclaredCjsGlobals>,
/// `true` when the analysis was successful.
pub successful: bool,
pub source_map: Vc<OptionSourceMap>,
Expand All @@ -168,6 +185,7 @@ pub struct AnalyzeEcmascriptModuleResultBuilder {
code_gens: Vec<CodeGen>,
exports: EcmascriptExports,
async_module: Vc<OptionAsyncModule>,
declared_cjs_globals: DeclaredCjsGlobals,
successful: bool,
source_map: Option<Vc<OptionSourceMap>>,
bindings: Vec<EsmBinding>,
Expand All @@ -183,6 +201,7 @@ impl AnalyzeEcmascriptModuleResultBuilder {
code_gens: Vec::new(),
exports: EcmascriptExports::None,
async_module: Vc::cell(None),
declared_cjs_globals: Default::default(),
successful: false,
source_map: None,
bindings: Vec::new(),
Expand Down Expand Up @@ -263,6 +282,11 @@ impl AnalyzeEcmascriptModuleResultBuilder {
self.exports = exports;
}

/// Sets the analysis result CJS globals.
pub fn set_declared_cjs_globals(&mut self, globals: DeclaredCjsGlobals) {
self.declared_cjs_globals = globals;
}

/// Sets the analysis result ES export.
pub fn set_async_module(&mut self, async_module: Vc<AsyncModule>) {
self.async_module = Vc::cell(Some(async_module));
Expand Down Expand Up @@ -336,6 +360,7 @@ impl AnalyzeEcmascriptModuleResultBuilder {
code_generation: Vc::cell(self.code_gens),
exports: self.exports.into(),
async_module: self.async_module,
declared_cjs_globals: self.declared_cjs_globals.into(),
successful: self.successful,
source_map,
},
Expand Down Expand Up @@ -627,6 +652,12 @@ pub(crate) async fn analyse_ecmascript_module_internal(
let mut var_graph =
set_handler_and_globals(&handler, globals, || create_graph(program, eval_context));

analysis.set_declared_cjs_globals(DeclaredCjsGlobals {
dirname: var_graph.values.keys().any(|(k, _)| k == "__dirname"),
filename: var_graph.values.keys().any(|(k, _)| k == "__filename"),
require: var_graph.values.keys().any(|(k, _)| k == "require"),
});

let mut evaluation_references = Vec::new();

for (i, r) in eval_context.imports.references().enumerate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl EcmascriptChunkItem for EcmascriptModuleLocalsChunkItem {
self.chunking_context,
original_module.await?.options,
async_module_options,
analyze_result.declared_cjs_globals,
))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem {
this.chunking_context,
module.full_module.await?.options,
async_module_options,
analyze.declared_cjs_globals,
))
}

Expand Down

0 comments on commit 6ef7bbb

Please sign in to comment.