Skip to content

Commit 4096331

Browse files
committed
Turbopack: selective reads of defined env vars in module analysis
1 parent 2494303 commit 4096331

6 files changed

Lines changed: 169 additions & 288 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/next-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ rustc-hash = { workspace = true }
3434
serde = { workspace = true }
3535
serde_json = { workspace = true }
3636
serde_path_to_error = { workspace = true }
37+
smallvec = { workspace = true }
3738
swc_sourcemap = { workspace = true }
3839
thiserror = { workspace = true }
3940
tracing = { workspace = true }

crates/next-core/src/raw_ecmascript_module.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::io::Write;
33
use anyhow::{Result, bail};
44
use once_cell::sync::Lazy;
55
use regex::Regex;
6+
use smallvec::smallvec;
67
use tracing::Instrument;
78
use turbo_rcstr::rcstr;
89
use turbo_tasks::{FxIndexMap, FxIndexSet, ResolvedVc, TryJoinIterExt, ValueToString, Vc};
@@ -13,7 +14,8 @@ use turbopack_core::{
1314
chunk::{ChunkItem, ChunkType, ChunkableModule, ChunkingContext},
1415
code_builder::CodeBuilder,
1516
compile_time_info::{
16-
CompileTimeDefineValue, CompileTimeInfo, DefinableNameSegment, FreeVarReference,
17+
CompileTimeDefineValue, CompileTimeInfo, DefinableNameSegmentRef, DefinableNameSegmentRefs,
18+
FreeVarReference,
1719
},
1820
context::AssetContext,
1921
ident::AssetIdent,
@@ -201,12 +203,7 @@ impl EcmascriptChunkItem for RawEcmascriptChunkItem {
201203

202204
let mut code = CodeBuilder::default();
203205
if !env_vars.is_empty() {
204-
let replacements = module
205-
.compile_time_info
206-
.await?
207-
.free_var_references
208-
.individual()
209-
.await?;
206+
let replacements = module.compile_time_info.await?.free_var_references;
210207
code += "var process = {env:\n";
211208
writeln!(
212209
code,
@@ -217,20 +214,14 @@ impl EcmascriptChunkItem for RawEcmascriptChunkItem {
217214
.map(async |name| {
218215
Ok((
219216
name,
220-
if let Some(value) =
221-
replacements.get(&DefinableNameSegment::Name(name.into()))
222-
&& let Some((_, value)) =
223-
value.0.iter().find(|(path, _)| {
224-
matches!(
225-
path.as_slice(),
226-
[
227-
DefinableNameSegment::Name(a),
228-
DefinableNameSegment::Name(b)
229-
] if a == "process" && b == "env"
230-
)
231-
})
217+
if let Some(value) = replacements
218+
.get(&DefinableNameSegmentRefs(smallvec![
219+
DefinableNameSegmentRef::Name("process"),
220+
DefinableNameSegmentRef::Name("env"),
221+
DefinableNameSegmentRef::Name(name),
222+
]))
223+
.await?
232224
{
233-
let value = value.await?;
234225
let value = match &*value {
235226
FreeVarReference::Value(
236227
CompileTimeDefineValue::String(value),

turbopack/crates/turbopack-core/src/compile_time_info.rs

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use anyhow::Result;
22
use bincode::{Decode, Encode};
3+
use indexmap::Equivalent;
4+
use rustc_hash::FxHashSet;
5+
use smallvec::SmallVec;
36
use turbo_rcstr::RcStr;
47
use turbo_tasks::{FxIndexMap, NonLocalValue, ResolvedVc, Vc, trace::TraceRawVcs};
58
use turbo_tasks_fs::FileSystemPath;
@@ -157,6 +160,7 @@ impl From<serde_json::Value> for CompileTimeDefineValue {
157160
#[derive(Debug, Clone, Hash, PartialOrd, Ord)]
158161
pub enum DefinableNameSegment {
159162
Name(RcStr),
163+
Call(RcStr),
160164
TypeOf,
161165
}
162166

@@ -178,20 +182,48 @@ impl From<String> for DefinableNameSegment {
178182
}
179183
}
180184

181-
#[turbo_tasks::value(transparent)]
185+
#[derive(Hash, PartialEq, Eq)]
186+
pub enum DefinableNameSegmentRef<'a> {
187+
Name(&'a str),
188+
Call(&'a str),
189+
TypeOf,
190+
}
191+
192+
impl Equivalent<DefinableNameSegment> for DefinableNameSegmentRef<'_> {
193+
fn equivalent(&self, key: &DefinableNameSegment) -> bool {
194+
match (self, key) {
195+
(DefinableNameSegmentRef::Name(a), DefinableNameSegment::Name(b)) => **a == *b.as_str(),
196+
(DefinableNameSegmentRef::Call(a), DefinableNameSegment::Call(b)) => **a == *b.as_str(),
197+
(DefinableNameSegmentRef::TypeOf, DefinableNameSegment::TypeOf) => true,
198+
_ => false,
199+
}
200+
}
201+
}
202+
203+
#[derive(Hash, PartialEq, Eq)]
204+
pub struct DefinableNameSegmentRefs<'a>(pub SmallVec<[DefinableNameSegmentRef<'a>; 4]>);
205+
206+
impl Equivalent<Vec<DefinableNameSegment>> for DefinableNameSegmentRefs<'_> {
207+
fn equivalent(&self, key: &Vec<DefinableNameSegment>) -> bool {
208+
if self.0.len() != key.len() {
209+
return false;
210+
}
211+
for (a, b) in self.0.iter().zip(key.iter()) {
212+
if !a.equivalent(b) {
213+
return false;
214+
}
215+
}
216+
true
217+
}
218+
}
219+
220+
#[turbo_tasks::value(transparent, cell = "keyed")]
182221
#[derive(Debug, Clone)]
183222
pub struct CompileTimeDefines(
184223
#[bincode(with = "turbo_bincode::indexmap")]
185224
pub FxIndexMap<Vec<DefinableNameSegment>, CompileTimeDefineValue>,
186225
);
187226

188-
#[turbo_tasks::value(transparent)]
189-
#[derive(Debug, Clone)]
190-
pub struct CompileTimeDefinesIndividual(
191-
#[bincode(with = "turbo_bincode::indexmap")]
192-
pub FxIndexMap<Vec<DefinableNameSegment>, ResolvedVc<CompileTimeDefineValue>>,
193-
);
194-
195227
impl IntoIterator for CompileTimeDefines {
196228
type Item = (Vec<DefinableNameSegment>, CompileTimeDefineValue);
197229
type IntoIter = indexmap::map::IntoIter<Vec<DefinableNameSegment>, CompileTimeDefineValue>;
@@ -207,20 +239,6 @@ impl CompileTimeDefines {
207239
pub fn empty() -> Vc<Self> {
208240
Vc::cell(FxIndexMap::default())
209241
}
210-
211-
#[turbo_tasks::function]
212-
pub fn individual(&self) -> Vc<CompileTimeDefinesIndividual> {
213-
let mut map: FxIndexMap<Vec<DefinableNameSegment>, ResolvedVc<CompileTimeDefineValue>> =
214-
self.0
215-
.iter()
216-
.map(|(key, value)| (key.clone(), value.clone().resolved_cell()))
217-
.collect();
218-
219-
// Sort keys to make order as deterministic as possible
220-
map.sort_keys();
221-
222-
Vc::cell(map)
223-
}
224242
}
225243

226244
#[derive(Debug, Clone, Copy, PartialEq, Eq, TraceRawVcs, NonLocalValue, Encode, Decode)]
@@ -275,26 +293,15 @@ impl From<CompileTimeDefineValue> for FreeVarReference {
275293
}
276294
}
277295

278-
#[turbo_tasks::value(transparent)]
296+
#[turbo_tasks::value(transparent, cell = "keyed")]
279297
#[derive(Debug, Clone)]
280298
pub struct FreeVarReferences(
281299
#[bincode(with = "turbo_bincode::indexmap")]
282300
pub FxIndexMap<Vec<DefinableNameSegment>, FreeVarReference>,
283301
);
284302

285-
#[derive(Debug, Default, Clone, PartialEq, Eq, TraceRawVcs, NonLocalValue, Encode, Decode)]
286-
pub struct FreeVarReferenceVcs(
287-
#[bincode(with = "turbo_bincode::indexmap")]
288-
pub FxIndexMap<Vec<DefinableNameSegment>, ResolvedVc<FreeVarReference>>,
289-
);
290-
291-
/// A map from the last element (the member prop) to a map of the rest of the name to the value.
292-
#[turbo_tasks::value(transparent)]
293-
#[derive(Debug, Clone)]
294-
pub struct FreeVarReferencesIndividual(
295-
#[bincode(with = "turbo_bincode::indexmap")]
296-
pub FxIndexMap<DefinableNameSegment, FreeVarReferenceVcs>,
297-
);
303+
#[turbo_tasks::value(transparent, cell = "keyed")]
304+
pub struct FreeVarReferencesMembers(FxHashSet<RcStr>);
298305

299306
#[turbo_tasks::value_impl]
300307
impl FreeVarReferences {
@@ -304,24 +311,17 @@ impl FreeVarReferences {
304311
}
305312

306313
#[turbo_tasks::function]
307-
pub fn individual(&self) -> Vc<FreeVarReferencesIndividual> {
308-
let mut result: FxIndexMap<DefinableNameSegment, FreeVarReferenceVcs> =
309-
FxIndexMap::default();
310-
311-
for (key, value) in &self.0 {
312-
let (last_key, key) = key.split_last().unwrap();
313-
result
314-
.entry(last_key.clone())
315-
.or_default()
316-
.0
317-
.insert(key.to_vec(), value.clone().resolved_cell());
314+
pub fn members(&self) -> Vc<FreeVarReferencesMembers> {
315+
let mut members = FxHashSet::default();
316+
for (key, _) in self.0.iter() {
317+
if let Some(DefinableNameSegment::Name(name)) = key
318+
.iter()
319+
.rfind(|segment| matches!(segment, DefinableNameSegment::Name(_)))
320+
{
321+
members.insert(name.clone());
322+
}
318323
}
319-
320-
// Sort keys to make order as deterministic as possible
321-
result.sort_keys();
322-
result.iter_mut().for_each(|(_, inner)| inner.0.sort_keys());
323-
324-
Vc::cell(result)
324+
Vc::cell(members)
325325
}
326326
}
327327

0 commit comments

Comments
 (0)