mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Turbopack: Use FrozenMap for module export information (#92802)
This commit is contained in:
Generated
+1
@@ -10481,6 +10481,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"turbo-bincode",
|
||||
"turbo-esregex",
|
||||
"turbo-frozenmap",
|
||||
"turbo-rcstr",
|
||||
"turbo-tasks",
|
||||
"turbo-tasks-backend",
|
||||
|
||||
@@ -49,6 +49,7 @@ tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
turbo-bincode = { workspace = true }
|
||||
turbo-esregex = { workspace = true }
|
||||
turbo-frozenmap = { workspace = true }
|
||||
turbo-rcstr = { workspace = true }
|
||||
turbo-tasks = { workspace = true }
|
||||
turbo-tasks-fs = { workspace = true }
|
||||
|
||||
@@ -11,6 +11,7 @@ use swc_core::{
|
||||
},
|
||||
quote, quote_expr,
|
||||
};
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_rcstr::{RcStr, rcstr};
|
||||
use turbo_tasks::{
|
||||
FxIndexMap, NonLocalValue, ResolvedVc, TryFlatJoinIterExt, Vc, trace::TraceRawVcs, turbofmt,
|
||||
@@ -529,7 +530,7 @@ async fn emit_star_exports_issue(source_ident: Vc<AssetIdent>, message: RcStr) -
|
||||
#[derive(Hash, Debug)]
|
||||
pub struct EsmExports {
|
||||
/// Explicit exports
|
||||
pub exports: BTreeMap<RcStr, EsmExport>,
|
||||
pub exports: FrozenMap<RcStr, EsmExport>,
|
||||
/// Unexpanded `export * from ...` statements (expanded in `expand_star_exports`)
|
||||
pub star_exports: Vec<ResolvedVc<Box<dyn ModuleReference>>>,
|
||||
}
|
||||
@@ -541,7 +542,7 @@ pub struct EsmExports {
|
||||
#[turbo_tasks::value(shared)]
|
||||
#[derive(Hash, Debug)]
|
||||
pub struct ExpandedExports {
|
||||
pub exports: BTreeMap<RcStr, EsmExport>,
|
||||
pub exports: FrozenMap<RcStr, EsmExport>,
|
||||
/// Modules we couldn't analyze all exports of.
|
||||
pub dynamic_exports: Vec<ResolvedVc<Box<dyn EcmascriptChunkPlaceable>>>,
|
||||
}
|
||||
@@ -559,16 +560,16 @@ impl EsmExports {
|
||||
module_reference: Vc<Box<dyn ModuleReference>>,
|
||||
) -> Result<Vc<EcmascriptExports>> {
|
||||
let module_reference = module_reference.to_resolved().await?;
|
||||
let mut exports = BTreeMap::new();
|
||||
let mut exports = Vec::new();
|
||||
let default = rcstr!("default");
|
||||
exports.insert(
|
||||
exports.push((
|
||||
default.clone(),
|
||||
EsmExport::ImportedBinding(module_reference, default, false),
|
||||
);
|
||||
));
|
||||
|
||||
Ok(EcmascriptExports::EsmExports(
|
||||
EsmExports {
|
||||
exports,
|
||||
exports: FrozenMap::from(exports),
|
||||
star_exports: vec![module_reference],
|
||||
}
|
||||
.resolved_cell(),
|
||||
@@ -581,7 +582,11 @@ impl EsmExports {
|
||||
&self,
|
||||
export_usage_info: Vc<ModuleExportUsageInfo>,
|
||||
) -> Result<Vc<ExpandedExports>> {
|
||||
let mut exports: BTreeMap<RcStr, EsmExport> = self.exports.clone();
|
||||
let mut exports: BTreeMap<_, _> = self
|
||||
.exports
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.collect();
|
||||
let mut dynamic_exports = vec![];
|
||||
let export_usage_info = export_usage_info.await?;
|
||||
|
||||
@@ -608,12 +613,10 @@ impl EsmExports {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !exports.contains_key(export) {
|
||||
exports.insert(
|
||||
export.clone(),
|
||||
EsmExport::ImportedBinding(esm_ref, export.clone(), false),
|
||||
);
|
||||
}
|
||||
// the spec indicates first-one-wins: https://tc39.es/ecma262/#_ref_9060
|
||||
exports
|
||||
.entry(export.clone())
|
||||
.or_insert_with(|| EsmExport::ImportedBinding(esm_ref, export.clone(), false));
|
||||
}
|
||||
|
||||
if !export_info.dynamic_exporting_modules.is_empty() {
|
||||
@@ -622,7 +625,7 @@ impl EsmExports {
|
||||
}
|
||||
|
||||
Ok(ExpandedExports {
|
||||
exports,
|
||||
exports: FrozenMap::from(exports),
|
||||
dynamic_exports,
|
||||
}
|
||||
.cell())
|
||||
|
||||
@@ -22,7 +22,6 @@ pub mod util;
|
||||
pub mod worker;
|
||||
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
future::Future,
|
||||
mem::take,
|
||||
ops::Deref,
|
||||
@@ -62,6 +61,7 @@ use swc_core::{
|
||||
};
|
||||
use tokio::sync::OnceCell;
|
||||
use tracing::Instrument;
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_rcstr::{RcStr, rcstr};
|
||||
use turbo_tasks::{
|
||||
FxIndexMap, FxIndexSet, NonLocalValue, PrettyPrintError, ReadRef, ResolvedVc, TaskInput,
|
||||
@@ -907,21 +907,21 @@ async fn analyze_ecmascript_module_internal(
|
||||
analysis.add_esm_reexport_reference(i);
|
||||
}
|
||||
Reexport::Namespace { exported: n } => {
|
||||
esm_exports.insert(
|
||||
esm_exports.push((
|
||||
n.as_str().into(),
|
||||
EsmExport::ImportedNamespace(ResolvedVc::upcast(reference)),
|
||||
);
|
||||
));
|
||||
analysis.add_esm_reexport_reference(i);
|
||||
}
|
||||
Reexport::Named { imported, exported } => {
|
||||
esm_exports.insert(
|
||||
esm_exports.push((
|
||||
exported.as_str().into(),
|
||||
EsmExport::ImportedBinding(
|
||||
ResolvedVc::upcast(reference),
|
||||
imported.to_string().into(),
|
||||
false,
|
||||
),
|
||||
);
|
||||
));
|
||||
analysis.add_esm_reexport_reference(i);
|
||||
}
|
||||
}
|
||||
@@ -939,7 +939,7 @@ async fn analyze_ecmascript_module_internal(
|
||||
}
|
||||
|
||||
let esm_exports = EsmExports {
|
||||
exports: esm_exports,
|
||||
exports: FrozenMap::from(esm_exports),
|
||||
star_exports: esm_star_exports,
|
||||
}
|
||||
.cell();
|
||||
@@ -4003,7 +4003,7 @@ struct ModuleReferencesVisitor<'a> {
|
||||
old_analyzer: StaticAnalyser,
|
||||
import_references: &'a [ResolvedVc<EsmAssetReference>],
|
||||
analysis: &'a mut AnalyzeEcmascriptModuleResultBuilder,
|
||||
esm_exports: BTreeMap<RcStr, EsmExport>,
|
||||
esm_exports: Vec<(RcStr, EsmExport)>,
|
||||
webpack_runtime: Option<(RcStr, Span)>,
|
||||
webpack_entry: bool,
|
||||
webpack_chunks: Vec<Lit>,
|
||||
@@ -4026,7 +4026,7 @@ impl<'a> ModuleReferencesVisitor<'a> {
|
||||
old_analyzer: StaticAnalyser::default(),
|
||||
import_references,
|
||||
analysis,
|
||||
esm_exports: BTreeMap::new(),
|
||||
esm_exports: Vec::new(),
|
||||
webpack_runtime: None,
|
||||
webpack_entry: false,
|
||||
webpack_chunks: Vec::new(),
|
||||
@@ -4186,7 +4186,7 @@ impl VisitAstPath for ModuleReferencesVisitor<'_> {
|
||||
)
|
||||
}
|
||||
};
|
||||
self.esm_exports.insert(key, export);
|
||||
self.esm_exports.push((key, export));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4212,7 +4212,7 @@ impl VisitAstPath for ModuleReferencesVisitor<'_> {
|
||||
let liveness = self.get_export_ident_liveness((id.clone(), ctx));
|
||||
let name: RcStr = id.as_str().into();
|
||||
self.esm_exports
|
||||
.insert(name.clone(), EsmExport::LocalBinding(name, liveness));
|
||||
.push((name.clone(), EsmExport::LocalBinding(name, liveness)));
|
||||
};
|
||||
match decl {
|
||||
Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => {
|
||||
@@ -4252,14 +4252,14 @@ impl VisitAstPath for ModuleReferencesVisitor<'_> {
|
||||
export: &'ast ExportDefaultExpr,
|
||||
ast_path: &mut AstNodePath<AstParentNodeRef<'r>>,
|
||||
) {
|
||||
self.esm_exports.insert(
|
||||
self.esm_exports.push((
|
||||
rcstr!("default"),
|
||||
EsmExport::LocalBinding(
|
||||
magic_identifier::mangle("default export").into(),
|
||||
// The expression passed to `export default` cannot be mutated
|
||||
Liveness::Constant,
|
||||
),
|
||||
);
|
||||
));
|
||||
if self.analyze_mode.is_code_gen() {
|
||||
self.analysis.add_code_gen(EsmModuleItem::new(
|
||||
as_parent_path(ast_path).into(),
|
||||
@@ -4287,7 +4287,7 @@ impl VisitAstPath for ModuleReferencesVisitor<'_> {
|
||||
Liveness::Constant,
|
||||
),
|
||||
};
|
||||
self.esm_exports.insert(rcstr!("default"), export);
|
||||
self.esm_exports.push((rcstr!("default"), export));
|
||||
}
|
||||
DefaultDecl::TsInterfaceDecl(..) => {
|
||||
// ignore
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_tasks::{ResolvedVc, Vc};
|
||||
use turbo_tasks_fs::{File, FileContent};
|
||||
use turbopack_core::{
|
||||
@@ -208,33 +207,28 @@ impl EcmascriptChunkPlaceable for EcmascriptModuleRenameModule {
|
||||
#[turbo_tasks::function]
|
||||
async fn get_exports(&self) -> Result<Vc<EcmascriptExports>> {
|
||||
let reference = self.module_reference().await?;
|
||||
let mut exports = BTreeMap::new();
|
||||
|
||||
match &self.part {
|
||||
let export = match &self.part {
|
||||
ModulePart::RenamedExport {
|
||||
original_export,
|
||||
export,
|
||||
} => {
|
||||
exports.insert(
|
||||
export.clone(),
|
||||
EsmExport::ImportedBinding(
|
||||
ResolvedVc::upcast(reference),
|
||||
original_export.clone(),
|
||||
false,
|
||||
),
|
||||
);
|
||||
}
|
||||
ModulePart::RenamedNamespace { export } => {
|
||||
exports.insert(
|
||||
export.clone(),
|
||||
EsmExport::ImportedNamespace(ResolvedVc::upcast(reference)),
|
||||
);
|
||||
}
|
||||
} => (
|
||||
export.clone(),
|
||||
EsmExport::ImportedBinding(
|
||||
ResolvedVc::upcast(reference),
|
||||
original_export.clone(),
|
||||
false,
|
||||
),
|
||||
),
|
||||
ModulePart::RenamedNamespace { export } => (
|
||||
export.clone(),
|
||||
EsmExport::ImportedNamespace(ResolvedVc::upcast(reference)),
|
||||
),
|
||||
_ => bail!("Unexpected ModulePart for EcmascriptModuleRenameModule"),
|
||||
}
|
||||
};
|
||||
|
||||
let exports = EsmExports {
|
||||
exports,
|
||||
exports: FrozenMap::from_unique_sorted_box(Box::new([export])),
|
||||
star_exports: Vec::new(),
|
||||
}
|
||||
.resolved_cell();
|
||||
|
||||
+10
-14
@@ -1,6 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_tasks::{ResolvedVc, Vc};
|
||||
use turbopack_core::{
|
||||
chunk::{
|
||||
@@ -189,18 +188,16 @@ impl EcmascriptAnalyzable for EcmascriptModuleFacadeModule {
|
||||
impl EcmascriptChunkPlaceable for EcmascriptModuleFacadeModule {
|
||||
#[turbo_tasks::function]
|
||||
async fn get_exports(&self) -> Result<Vc<EcmascriptExports>> {
|
||||
let mut exports = BTreeMap::new();
|
||||
let mut star_exports = Vec::new();
|
||||
|
||||
let EcmascriptExports::EsmExports(esm_exports) = &*self.module.get_exports().await? else {
|
||||
bail!("EcmascriptModuleFacadeModule must only be used on modules with EsmExports");
|
||||
};
|
||||
let esm_exports = esm_exports.await?;
|
||||
let mut exports = Vec::with_capacity(esm_exports.exports.len());
|
||||
for (name, export) in &esm_exports.exports {
|
||||
let name = name.clone();
|
||||
match export {
|
||||
EsmExport::LocalBinding(_, liveness) => {
|
||||
exports.insert(
|
||||
exports.push((
|
||||
name.clone(),
|
||||
EsmExport::ImportedBinding(
|
||||
ResolvedVc::upcast(
|
||||
@@ -215,27 +212,26 @@ impl EcmascriptChunkPlaceable for EcmascriptModuleFacadeModule {
|
||||
name,
|
||||
*liveness == Liveness::Mutable,
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
EsmExport::ImportedNamespace(reference) => {
|
||||
exports.insert(name, EsmExport::ImportedNamespace(*reference));
|
||||
exports.push((name, EsmExport::ImportedNamespace(*reference)));
|
||||
}
|
||||
EsmExport::ImportedBinding(reference, imported_name, mutable) => {
|
||||
exports.insert(
|
||||
exports.push((
|
||||
name,
|
||||
EsmExport::ImportedBinding(*reference, imported_name.clone(), *mutable),
|
||||
);
|
||||
));
|
||||
}
|
||||
EsmExport::Error => {
|
||||
exports.insert(name, EsmExport::Error);
|
||||
exports.push((name, EsmExport::Error));
|
||||
}
|
||||
}
|
||||
}
|
||||
star_exports.extend(esm_exports.star_exports.iter().copied());
|
||||
|
||||
let exports = EsmExports {
|
||||
exports,
|
||||
star_exports,
|
||||
exports: FrozenMap::from_unique_sorted_box(exports.into_boxed_slice()),
|
||||
star_exports: esm_exports.star_exports.clone(),
|
||||
}
|
||||
.resolved_cell();
|
||||
Ok(EcmascriptExports::EsmExports(exports).cell())
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use turbo_frozenmap::FrozenMap;
|
||||
use turbo_tasks::{ResolvedVc, Vc};
|
||||
use turbopack_core::{
|
||||
chunk::{
|
||||
@@ -142,7 +141,7 @@ impl EcmascriptChunkPlaceable for EcmascriptModuleLocalsModule {
|
||||
bail!("EcmascriptModuleLocalsModule must only be used on modules with EsmExports");
|
||||
};
|
||||
let esm_exports = exports.await?;
|
||||
let mut exports = BTreeMap::new();
|
||||
let mut exports = Vec::new();
|
||||
|
||||
for (name, export) in &esm_exports.exports {
|
||||
match export {
|
||||
@@ -150,19 +149,19 @@ impl EcmascriptChunkPlaceable for EcmascriptModuleLocalsModule {
|
||||
// not included in locals module
|
||||
}
|
||||
EsmExport::LocalBinding(local_name, liveness) => {
|
||||
exports.insert(
|
||||
exports.push((
|
||||
name.clone(),
|
||||
EsmExport::LocalBinding(local_name.clone(), *liveness),
|
||||
);
|
||||
));
|
||||
}
|
||||
EsmExport::Error => {
|
||||
exports.insert(name.clone(), EsmExport::Error);
|
||||
exports.push((name.clone(), EsmExport::Error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let exports = EsmExports {
|
||||
exports,
|
||||
exports: FrozenMap::from_unique_sorted_box(exports.into_boxed_slice()),
|
||||
star_exports: vec![],
|
||||
}
|
||||
.resolved_cell();
|
||||
|
||||
Reference in New Issue
Block a user