mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Turbopack: analyzer improvement followups (#92834)
- defer computing the `EsmAssetReference` issue source from the `Span`. means that we have to pass less arguments around as well
- make `mangle("default export")` a "constant" and use that everywhere instead
Some snapshots changed, because the test runner had `source: None`, so now there are some duplicate module references in there because the new always-set `span` field forces it to be a new entry in the `data.references` hashmap.
This commit is contained in:
@@ -66,7 +66,6 @@ pub fn benchmark(c: &mut Criterion) {
|
||||
top_level_mark,
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let var_graph = create_graph(
|
||||
&program,
|
||||
|
||||
@@ -22,8 +22,7 @@ use swc_core::{
|
||||
},
|
||||
};
|
||||
use turbo_rcstr::{RcStr, rcstr};
|
||||
use turbo_tasks::ResolvedVc;
|
||||
use turbopack_core::{resolve::ExportUsage, source::Source};
|
||||
use turbopack_core::resolve::ExportUsage;
|
||||
|
||||
use super::{
|
||||
ConstantValue, ImportMap, JsValue, ObjectPart, WellKnownFunctionKind, is_unresolved_id,
|
||||
@@ -474,14 +473,11 @@ impl EvalContext {
|
||||
top_level_mark: Mark,
|
||||
force_free_values: Arc<FxHashSet<Id>>,
|
||||
comments: Option<&dyn Comments>,
|
||||
source: Option<ResolvedVc<Box<dyn Source>>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
imports: module.map_or(ImportMap::default(), |m| {
|
||||
ImportMap::analyze(m, source, comments)
|
||||
}),
|
||||
imports: module.map_or(ImportMap::default(), |m| ImportMap::analyze(m, comments)),
|
||||
force_free_values,
|
||||
}
|
||||
}
|
||||
@@ -914,14 +910,8 @@ impl EvalContext {
|
||||
let js_value = try_with_handler(cm, Default::default(), |_| {
|
||||
GLOBALS.set(&Default::default(), || {
|
||||
let expr = parse_single_expr_lit(expr_lit);
|
||||
let eval_context = EvalContext::new(
|
||||
None,
|
||||
Mark::new(),
|
||||
Mark::new(),
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let eval_context =
|
||||
EvalContext::new(None, Mark::new(), Mark::new(), Default::default(), None);
|
||||
|
||||
Ok(eval_context.eval(&expr))
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::SmallVec;
|
||||
use swc_core::{
|
||||
atoms::Wtf8Atom,
|
||||
common::{BytePos, Span, Spanned, SyntaxContext, comments::Comments, source_map::SmallPos},
|
||||
common::{BytePos, Span, Spanned, SyntaxContext, comments::Comments},
|
||||
ecma::{
|
||||
ast::*,
|
||||
atoms::{Atom, atom},
|
||||
@@ -17,13 +17,13 @@ use swc_core::{
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_rcstr::{RcStr, rcstr};
|
||||
use turbo_tasks::{FxIndexMap, FxIndexSet, ResolvedVc};
|
||||
use turbopack_core::{issue::IssueSource, loader::WebpackLoaderItem, source::Source};
|
||||
use turbopack_core::loader::WebpackLoaderItem;
|
||||
|
||||
use super::{JsValue, ModuleValue, top_level_await::has_top_level_await};
|
||||
use crate::{
|
||||
SpecifiedModuleType,
|
||||
analyzer::{ConstantValue, ObjectPart, graph::VarGraph},
|
||||
magic_identifier,
|
||||
magic_identifier::{MAGIC_IDENTIFIER_DEFAULT_EXPORT, MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM},
|
||||
references::{
|
||||
esm::{EsmAssetReference, EsmExport, Liveness},
|
||||
util::{SpecifiedChunkingType, parse_chunking_type_annotation},
|
||||
@@ -410,7 +410,7 @@ pub(crate) struct ImportMapReference {
|
||||
pub module_path: Wtf8Atom,
|
||||
pub imported_symbol: ImportedSymbol,
|
||||
pub annotations: Option<Arc<ImportAnnotations>>,
|
||||
pub issue_source: Option<IssueSource>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl ImportMap {
|
||||
@@ -524,15 +524,10 @@ impl ImportMap {
|
||||
}
|
||||
|
||||
/// Analyze ES import
|
||||
pub(super) fn analyze(
|
||||
m: &Program,
|
||||
source: Option<ResolvedVc<Box<dyn Source>>>,
|
||||
comments: Option<&dyn Comments>,
|
||||
) -> Self {
|
||||
pub(super) fn analyze(m: &Program, comments: Option<&dyn Comments>) -> Self {
|
||||
let mut data = ImportMap::default();
|
||||
let mut analyzer = Analyzer {
|
||||
data: &mut data,
|
||||
source,
|
||||
comments,
|
||||
namespace_imports_to_specifier: FxIndexMap::default(),
|
||||
};
|
||||
@@ -650,7 +645,6 @@ impl ImportMap {
|
||||
|
||||
struct Analyzer<'a> {
|
||||
data: &'a mut ImportMap,
|
||||
source: Option<ResolvedVc<Box<dyn Source>>>,
|
||||
comments: Option<&'a dyn Comments>,
|
||||
/// Map from local identifier of namespace imports to module path, used temporarily during
|
||||
/// analysis to detect dynamic accesses to namespace imports.
|
||||
@@ -665,14 +659,10 @@ impl Analyzer<'_> {
|
||||
imported_symbol: ImportedSymbol,
|
||||
annotations: Option<ImportAnnotations>,
|
||||
) -> usize {
|
||||
let issue_source = self
|
||||
.source
|
||||
.map(|s| IssueSource::from_swc_offsets(s, span.lo.to_u32(), span.hi.to_u32()));
|
||||
|
||||
let r = ImportMapReference {
|
||||
module_path,
|
||||
imported_symbol,
|
||||
issue_source,
|
||||
span,
|
||||
annotations: annotations.map(Arc::new),
|
||||
};
|
||||
if let Some(i) = self.data.references.get_index_of(&r) {
|
||||
@@ -858,7 +848,7 @@ impl Visit for Analyzer<'_> {
|
||||
ident.as_ref().map_or_else(
|
||||
|| {
|
||||
(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
SyntaxContext::empty(),
|
||||
)
|
||||
},
|
||||
@@ -868,7 +858,7 @@ impl Visit for Analyzer<'_> {
|
||||
DefaultDecl::TsInterfaceDecl(_) => {
|
||||
// not matching, might happen due to eventual consistency
|
||||
(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
SyntaxContext::empty(),
|
||||
)
|
||||
}
|
||||
@@ -887,13 +877,13 @@ impl Visit for Analyzer<'_> {
|
||||
|
||||
self.data.exports.insert(
|
||||
rcstr!("default"),
|
||||
Export::LocalBinding(magic_identifier::mangle("default export").into(), false),
|
||||
Export::LocalBinding(MAGIC_IDENTIFIER_DEFAULT_EXPORT.clone(), false),
|
||||
);
|
||||
self.data.exports_ids.insert(
|
||||
rcstr!("default"),
|
||||
(
|
||||
// `EsmModuleItem::code_generation` inserts this variable.
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
SyntaxContext::empty(),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -3798,7 +3798,6 @@ mod tests {
|
||||
top_level_mark,
|
||||
Default::default(),
|
||||
Some(&comments),
|
||||
None,
|
||||
);
|
||||
|
||||
let mut var_graph = create_graph(
|
||||
|
||||
@@ -5,6 +5,14 @@ use std::{
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::{Captures, Regex, Replacer};
|
||||
use swc_core::atoms::Atom;
|
||||
use turbo_rcstr::RcStr;
|
||||
|
||||
pub static MAGIC_IDENTIFIER_DEFAULT_EXPORT: Lazy<RcStr> =
|
||||
Lazy::new(|| RcStr::from(mangle("default export")));
|
||||
|
||||
pub static MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM: Lazy<Atom> =
|
||||
Lazy::new(|| Atom::from(mangle("default export")));
|
||||
|
||||
pub fn mangle(content: &str) -> String {
|
||||
let mut r = "__TURBOPACK__".to_string();
|
||||
|
||||
@@ -605,7 +605,6 @@ async fn parse_file_content(
|
||||
top_level_mark,
|
||||
Arc::new(var_with_ts_declare),
|
||||
Some(&comments),
|
||||
Some(source),
|
||||
);
|
||||
|
||||
let (comments, source_mapping_url) =
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{borrow::Cow, collections::BTreeMap, ops::ControlFlow};
|
||||
use std::{collections::BTreeMap, ops::ControlFlow};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use bincode::{Decode, Encode};
|
||||
@@ -31,7 +31,7 @@ use crate::{
|
||||
analyzer::graph::EvalContext,
|
||||
chunk::{EcmascriptChunkPlaceable, EcmascriptExports},
|
||||
code_gen::{CodeGeneration, CodeGenerationHoistedStmt},
|
||||
magic_identifier,
|
||||
magic_identifier::MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM,
|
||||
references::esm::base::ReferencedAsset,
|
||||
runtime_functions::{TURBOPACK_DYNAMIC, TURBOPACK_ESM},
|
||||
tree_shake::part::module::EcmascriptModulePartAsset,
|
||||
@@ -709,7 +709,7 @@ impl EsmExports {
|
||||
let binding = if let Some((local, ctxt)) =
|
||||
eval_context.imports.exports_ids.get(exported)
|
||||
{
|
||||
Some((Cow::Borrowed(local.as_str()), *ctxt))
|
||||
Some((local.clone(), *ctxt))
|
||||
} else {
|
||||
bail!(
|
||||
"Expected export to be in eval context {:?} {:?}",
|
||||
@@ -721,15 +721,15 @@ impl EsmExports {
|
||||
// Fallback, shouldn't happen in practice
|
||||
(
|
||||
if name == "default" {
|
||||
Cow::Owned(magic_identifier::mangle("default export"))
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone()
|
||||
} else {
|
||||
Cow::Borrowed(name.as_str())
|
||||
name.as_str().into()
|
||||
},
|
||||
SyntaxContext::empty(),
|
||||
)
|
||||
});
|
||||
|
||||
let local = Ident::new(local.into(), DUMMY_SP, ctxt);
|
||||
let local = Ident::new(local, DUMMY_SP, ctxt);
|
||||
match (liveness, export_usage_info.is_circuit_breaker) {
|
||||
(Liveness::Constant, false) => ExportBinding::Value(Expr::Ident(local)),
|
||||
// If the value might change or we are a circuit breaker we must bind a
|
||||
|
||||
@@ -15,7 +15,8 @@ use turbopack_core::chunk::ChunkingContext;
|
||||
|
||||
use crate::{
|
||||
code_gen::{CodeGen, CodeGeneration},
|
||||
create_visitor, magic_identifier,
|
||||
create_visitor,
|
||||
magic_identifier::MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM,
|
||||
references::AstPath,
|
||||
};
|
||||
|
||||
@@ -68,7 +69,7 @@ impl EsmModuleItem {
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Ident::new(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
DUMMY_SP,
|
||||
Default::default(),
|
||||
)
|
||||
@@ -86,8 +87,7 @@ impl EsmModuleItem {
|
||||
ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
|
||||
ident: class.ident.unwrap_or_else(|| {
|
||||
Ident::new(
|
||||
magic_identifier::mangle("default export")
|
||||
.into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
DUMMY_SP,
|
||||
Default::default(),
|
||||
)
|
||||
@@ -100,7 +100,7 @@ impl EsmModuleItem {
|
||||
*module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
|
||||
ident: fn_expr.ident.unwrap_or_else(|| {
|
||||
Ident::new(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
DUMMY_SP,
|
||||
Default::default(),
|
||||
)
|
||||
|
||||
@@ -811,8 +811,7 @@ async fn analyze_ecmascript_module_internal(
|
||||
module,
|
||||
ResolvedVc::upcast(module),
|
||||
RcStr::from(&*r.module_path.to_string_lossy()),
|
||||
r.issue_source
|
||||
.unwrap_or_else(|| IssueSource::from_source_only(source)),
|
||||
IssueSource::from_swc_offsets(source, r.span.lo.to_u32(), r.span.hi.to_u32()),
|
||||
r.annotations.as_ref().map(|a| (**a).clone()),
|
||||
match &r.imported_symbol {
|
||||
ImportedSymbol::ModuleEvaluation => {
|
||||
|
||||
@@ -33,7 +33,10 @@ use super::{
|
||||
Vars, collect_top_level_decls, ids_captured_by, ids_used_by, ids_used_by_ignoring_nested,
|
||||
},
|
||||
};
|
||||
use crate::{magic_identifier, tree_shake::optimizations::GraphOptimizer};
|
||||
use crate::{
|
||||
magic_identifier::{self, MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM},
|
||||
tree_shake::optimizations::GraphOptimizer,
|
||||
};
|
||||
|
||||
/// The id of an item
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
@@ -1012,7 +1015,7 @@ impl DepGraph {
|
||||
// bindings if the class/function has an identifier.
|
||||
let default_var = id.unwrap_or_else(|| {
|
||||
Ident::new(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
DUMMY_SP,
|
||||
Default::default(),
|
||||
)
|
||||
@@ -1083,7 +1086,7 @@ impl DepGraph {
|
||||
// Mirror what `EsmModuleItem::code_generation` does, these are live
|
||||
// bindings if the class/function has an identifier.
|
||||
let default_var = Ident::new(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
MAGIC_IDENTIFIER_DEFAULT_EXPORT_ATOM.clone(),
|
||||
DUMMY_SP,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
@@ -492,7 +492,6 @@ pub(super) async fn split_module(asset: Vc<EcmascriptModuleAsset>) -> Result<Vc<
|
||||
}
|
||||
|
||||
let parse_result = parsed.await?;
|
||||
let source = asset.source().to_resolved().await?;
|
||||
|
||||
match &*parse_result {
|
||||
ParseResult::Ok {
|
||||
@@ -570,7 +569,6 @@ pub(super) async fn split_module(asset: Vc<EcmascriptModuleAsset>) -> Result<Vc<
|
||||
eval_context.top_level_mark,
|
||||
eval_context.force_free_values.clone(),
|
||||
None,
|
||||
Some(source),
|
||||
);
|
||||
|
||||
ParseResult::resolved_cell(ParseResult::Ok {
|
||||
@@ -696,7 +694,6 @@ pub(crate) async fn part_of_module(
|
||||
eval_context.top_level_mark,
|
||||
eval_context.force_free_values.clone(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
return Ok(ParseResult::Ok {
|
||||
|
||||
+1
-1
@@ -1268,7 +1268,7 @@
|
||||
export_usage: All,
|
||||
},
|
||||
ImportedBinding {
|
||||
esm_reference_index: 4,
|
||||
esm_reference_index: 5,
|
||||
export: Some(
|
||||
"z",
|
||||
),
|
||||
|
||||
+1
-1
@@ -1122,7 +1122,7 @@
|
||||
span: 486..488,
|
||||
},
|
||||
ImportedBinding {
|
||||
esm_reference_index: 2,
|
||||
esm_reference_index: 3,
|
||||
export: Some(
|
||||
"join",
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user