use oxc::allocator::GetAllocator;
use oxc::ast::ast::Str;
use oxc::{
allocator::{Box as ArenaBox, IntoIn, TakeIn},
ast::{
NONE,
ast::{self, ExportDefaultDeclarationKind, Expression, ObjectPropertyKind, Statement},
},
semantic::{IsGlobalReference, Scoping, SymbolId},
span::{SPAN, Span},
};
use rolldown_common::{
ExternalModule, ImportRecordIdx, ImportRecordMeta, IndexModules, Module, ModuleIdx, NormalModule,
};
use rolldown_ecmascript::CJS_REQUIRE_REF_STR;
use rolldown_ecmascript_utils::{AstFactory, ExpressionExt};
use rolldown_utils::{
ecmascript::is_validate_identifier_name,
indexmap::{FxIndexMap, FxIndexSet},
};
use rustc_hash::{FxHashMap, FxHashSet};
use crate::hmr::utils::{HmrAstBuilder, MODULE_EXPORTS_NAME_FOR_ESM};
pub struct HmrAstFinalizer<'me, 'ast> {
pub ast_factory: AstFactory<'ast>,
pub modules: &'me IndexModules,
pub module: &'me NormalModule,
pub affected_module_idx_to_init_fn_name: &'me FxHashMap<ModuleIdx, String>,
pub use_pife_for_module_wrappers: bool,
pub dedup_module_initializer: bool,
pub unique_index: usize,
pub import_bindings: FxHashMap<SymbolId, String>,
pub exports: oxc::allocator::Vec<'ast, ObjectPropertyKind<'ast>>,
pub re_export_all_dependencies: FxIndexSet<ModuleIdx>,
pub dependencies: FxIndexSet<ModuleIdx>,
pub imports: FxHashSet<ModuleIdx>,
pub generated_static_import_infos: FxHashMap<ModuleIdx, String>,
pub generated_static_import_stmts_from_external: FxIndexMap<ModuleIdx, ast::Statement<'ast>>,
pub named_exports: FxHashMap<Str<'ast>, NamedExport>,
}
impl<'ast> HmrAstFinalizer<'_, 'ast> {
#[expect(clippy::too_many_lines)]
pub fn handle_top_level_stmt(
&mut self,
program_body: &mut oxc::allocator::Vec<'ast, ast::Statement<'ast>>,
mut node: ast::Statement<'ast>,
scoping: &Scoping,
) {
match node {
ref mut module_decl @ ast::match_module_declaration!(Statement) => {
let module_decl = module_decl.to_module_declaration_mut();
match module_decl {
ast::ModuleDeclaration::ImportDeclaration(import_decl) => {
let rec_id = self.module.imports[&import_decl.node_id()];
let rec = &self.module.import_records[rec_id];
let Some(importee_idx) = rec.resolved_module else { return };
let importee = &self.modules[importee_idx];
self.dependencies.insert(importee_idx);
let binding_name = self.ensure_static_import_info(importee_idx, rec_id).to_string();
import_decl.specifiers.as_ref().inspect(|specifiers| {
specifiers.iter().for_each(|spec| match spec {
ast::ImportDeclarationSpecifier::ImportSpecifier(import_specifier) => {
self.import_bindings.insert(
import_specifier.local.symbol_id(),
format!("{binding_name}.{}", import_specifier.imported.name()),
);
}
ast::ImportDeclarationSpecifier::ImportDefaultSpecifier(
import_default_specifier,
) => {
self.import_bindings.insert(
import_default_specifier.local.symbol_id(),
format!("{binding_name}.default"),
);
}
ast::ImportDeclarationSpecifier::ImportNamespaceSpecifier(
import_namespace_specifier,
) => {
self
.import_bindings
.insert(import_namespace_specifier.local.symbol_id(), binding_name.clone());
}
});
});
match importee {
Module::Normal(_) => {
if let Some(stmt) =
self.create_load_exports_call_stmt(importee, &binding_name, import_decl.span)
{
program_body.push(stmt);
}
}
Module::External(importee_ext) => {
self.create_static_import_stmt_from_external_module(
importee_ext,
&binding_name,
import_decl.span,
);
}
}
}
ast::ModuleDeclaration::ExportNamedDeclaration(decl) => {
if let Some(_source) = &decl.source {
let rec_id = self.module.imports[&decl.node_id()];
let rec = &self.module.import_records[rec_id];
let Some(importee_idx) = rec.resolved_module else { return };
let importee = &self.modules[importee_idx];
self.dependencies.insert(importee_idx);
let binding_name = self.ensure_static_import_info(importee_idx, rec_id).to_string();
self.exports.extend(decl.specifiers.iter().map(|specifier| {
self.ast_factory.make_lazy_export_property(
&specifier.exported.name(),
match &specifier.local {
ast::ModuleExportName::IdentifierName(ident) => {
Expression::StaticMemberExpression(
ast::StaticMemberExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, &binding_name),
ast::IdentifierName::new(SPAN, ident.name.as_str(), &self.ast_factory),
false,
&self.ast_factory,
),
)
}
ast::ModuleExportName::StringLiteral(str) => {
Expression::ComputedMemberExpression(
ast::ComputedMemberExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, &binding_name),
ast::Expression::new_string_literal(
SPAN, str.value.as_str(), None, &self.ast_factory
),
false,
&self.ast_factory,
),
)
}
ast::ModuleExportName::IdentifierReference(_) => {
unreachable!(
"ModuleExportName IdentifierReference is invalid in ExportNamedDeclaration with source"
)
}
},
matches!(specifier.exported, ast::ModuleExportName::StringLiteral(_))
)
}));
if let Some(stmt) =
self.create_load_exports_call_stmt(importee, &binding_name, decl.span)
{
program_body.push(stmt);
}
} else if let Some(decl) = &mut decl.declaration {
match decl {
ast::Declaration::VariableDeclaration(var_decl) => {
self.exports.extend(var_decl.declarations.iter().flat_map(|decl| {
decl.id.get_binding_identifiers().into_iter().map(|ident| {
self.ast_factory.make_lazy_export_property(
ident.name.as_str(),
self.ast_factory.make_id_ref_expr(SPAN, ident.name.as_str()),
false,
)
})
}));
}
ast::Declaration::FunctionDeclaration(fn_decl) => {
let id = fn_decl.id.as_ref().unwrap().name.as_str();
self.exports.push(self.ast_factory.make_lazy_export_property(
id,
self.ast_factory.make_id_ref_expr(SPAN, id),
false,
));
}
ast::Declaration::ClassDeclaration(cls_decl) => {
let id = cls_decl.id.as_ref().unwrap().name.as_str();
self.exports.push(self.ast_factory.make_lazy_export_property(
id,
self.ast_factory.make_id_ref_expr(SPAN, id),
false,
));
}
_ => unreachable!("doesn't support ts now"),
}
program_body.push(ast::Statement::from(decl.take_in(&self.ast_factory.allocator())));
} else {
decl.specifiers.iter().for_each(|specifier| {
if let Some(symbol_id) = scoping.get_root_binding(specifier.local.name().into()) {
self
.named_exports
.insert(specifier.exported.name(), NamedExport { local_binding: symbol_id });
} else {
}
});
}
}
ast::ModuleDeclaration::ExportDefaultDeclaration(decl) => match &mut decl.declaration {
ast::ExportDefaultDeclarationKind::FunctionDeclaration(function) => {
if let Some(id) = &function.id {
self.exports.push(self.ast_factory.make_lazy_export_property(
"default",
self.ast_factory.make_id_ref_expr(SPAN, &id.name),
false,
));
} else {
function.id = Some(self.ast_factory.make_id(SPAN, "__rolldown_default__"));
self.exports.push(self.ast_factory.make_lazy_export_property(
"default",
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_default__"),
false,
));
}
program_body.push(ast::Statement::FunctionDeclaration(ArenaBox::new_in(
function.as_mut().take_in(&self.ast_factory.allocator()),
&self.ast_factory.allocator(),
)));
}
ast::ExportDefaultDeclarationKind::ClassDeclaration(class) => {
if let Some(id) = &class.id {
self.exports.push(self.ast_factory.make_lazy_export_property(
"default",
self.ast_factory.make_id_ref_expr(SPAN, &id.name),
false,
));
} else {
class.id = Some(self.ast_factory.make_id(SPAN, "__rolldown_default__"));
self.exports.push(self.ast_factory.make_lazy_export_property(
"default",
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_default__"),
false,
));
}
program_body.push(ast::Statement::ClassDeclaration(ArenaBox::new_in(
class.as_mut().take_in(&self.ast_factory.allocator()),
&self.ast_factory.allocator(),
)));
}
expr @ ast::match_expression!(ExportDefaultDeclarationKind) => {
let expr = expr.to_expression_mut();
program_body.push(self.ast_factory.make_var_decl(
"__rolldown_default__",
expr.take_in(&self.ast_factory.allocator()),
));
self.exports.push(self.ast_factory.make_lazy_export_property(
"default",
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_default__"),
false,
));
}
unhandled_kind => {
unreachable!("Unexpected export default declaration kind: {unhandled_kind:#?}");
}
},
ast::ModuleDeclaration::ExportAllDeclaration(export_all_decl) => {
let rec_id = self.module.imports[&export_all_decl.node_id()];
let rec = &self.module.import_records[rec_id];
let Some(importee_idx) = rec.resolved_module else { return };
let importee = &self.modules[importee_idx];
self.dependencies.insert(importee_idx);
let binding_name = self.ensure_static_import_info(importee_idx, rec_id).to_string();
if let Some(stmt) =
self.create_load_exports_call_stmt(importee, &binding_name, export_all_decl.span)
{
program_body.push(stmt);
}
if let Some(stmt) =
self.create_re_export_call_stmt(importee, &binding_name, export_all_decl.span)
{
program_body.push(stmt);
}
}
ast::ModuleDeclaration::TSExportAssignment(_)
| ast::ModuleDeclaration::TSNamespaceExportDeclaration(_) => {
program_body.push(node);
}
}
}
_ => {
program_body.push(node);
}
}
}
pub fn ensure_static_import_info(
&mut self,
importee_idx: ModuleIdx,
rec_id: ImportRecordIdx,
) -> &str {
self.generated_static_import_infos.entry(importee_idx).or_insert_with(|| {
let importee = &self.modules[importee_idx];
format!("import_{}_{}{}", importee.repr_name(), self.unique_index, rec_id.raw())
})
}
pub fn module_exports_name(&self) -> &'static str {
if self.module.exports_kind.is_commonjs() {
"module.exports"
} else {
MODULE_EXPORTS_NAME_FOR_ESM
}
}
pub fn generate_runtime_module_register_for_hmr(
&mut self,
scoping: &Scoping,
) -> Vec<ast::Statement<'ast>> {
let mut ret = vec![];
if self.module.exports_kind == rolldown_common::ExportsKind::Esm {
let binding_name_for_namespace_object_ref = self.module_exports_name();
ret.extend(self.generate_declaration_of_module_namespace_object(
binding_name_for_namespace_object_ref,
scoping,
));
}
ret.push(self.create_register_module_stmt());
ret
}
pub fn rewrite_hot_accept_call_deps(&self, call_expr: &mut ast::CallExpression<'ast>) {
if !call_expr.callee.is_import_meta_hot_accept() {
return;
}
if call_expr.arguments.is_empty() {
return;
}
match &mut call_expr.arguments[0] {
ast::Argument::StringLiteral(string_literal) => {
let import_record = &self.module.import_records
[self.module.hmr_info.module_request_to_import_record_idx[string_literal.value.as_str()]];
let Some(module_idx) = import_record.resolved_module else { return };
string_literal.value =
Str::from_str_in(self.modules[module_idx].stable_id(), &self.ast_factory);
}
ast::Argument::ArrayExpression(array_expression) => {
array_expression.elements.iter_mut().for_each(|element| {
if let ast::ArrayExpressionElement::StringLiteral(string_literal) = element {
let import_record =
&self.module.import_records[self.module.hmr_info.module_request_to_import_record_idx
[string_literal.value.as_str()]];
let Some(module_idx) = import_record.resolved_module else { return };
string_literal.value =
Str::from_str_in(self.modules[module_idx].stable_id(), &self.ast_factory);
}
});
}
_ => {}
}
}
pub fn rewrite_import_meta_hot(&self, expr: &mut ast::Expression<'ast>) {
if expr.is_import_meta_hot() {
let hot_name = format!("hot_{}", self.module.repr_name);
*expr = self.ast_factory.make_id_ref_expr(SPAN, &hot_name);
}
}
fn create_load_exports_call_stmt(
&mut self,
importee: &Module,
binding_name: &str,
span: Span,
) -> Option<Statement<'ast>> {
if self.imports.contains(&importee.idx()) {
return None;
}
self.imports.insert(importee.idx());
let id = importee.stable_id();
let interop = match importee {
Module::Normal(importee) => self.module.interop(importee),
Module::External(_) => None,
};
let call_expr = self.ast_factory.make_call_with_arg(
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "loadExports"),
ast::Expression::new_string_literal(
SPAN,
Str::from_str_in(id, &self.ast_factory),
None,
&self.ast_factory,
),
false,
);
let stmt = Statement::from(ast::Declaration::new_variable_declaration(
span,
ast::VariableDeclarationKind::Var,
oxc::allocator::Vec::from_value_in(
ast::VariableDeclarator::new(
SPAN,
ast::VariableDeclarationKind::Var,
ast::BindingPattern::new_binding_identifier(
SPAN,
Str::from_str_in(binding_name, &self.ast_factory),
&self.ast_factory,
),
NONE,
Some(self.ast_factory.make_to_esm_call_with_interop(
"__rolldown_runtime__.__toESM",
call_expr,
interop,
)),
false,
&self.ast_factory,
),
&self.ast_factory,
),
false,
&self.ast_factory,
));
Some(stmt)
}
fn create_static_import_stmt_from_external_module(
&mut self,
importee: &ExternalModule,
binding_name: &str,
_span: Span,
) {
if self.generated_static_import_stmts_from_external.contains_key(&importee.idx) {
return;
}
let module_request = &importee.id;
let stmt = self.ast_factory.make_import_star_stmt(module_request, binding_name);
self.generated_static_import_stmts_from_external.insert(importee.idx, stmt);
}
fn create_re_export_call_stmt(
&mut self,
importee: &Module,
binding_name: &str,
span: Span,
) -> Option<Statement<'ast>> {
if self.re_export_all_dependencies.contains(&importee.idx()) {
return None;
}
self.re_export_all_dependencies.insert(importee.idx());
let self_exports = self.module_exports_name();
let call_expr = ast::Expression::new_call_expression(
SPAN,
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "__reExport"),
NONE,
oxc::allocator::Vec::from_iter_in(
[
ast::Argument::from(self.ast_factory.make_id_ref_expr(SPAN, self_exports)),
ast::Argument::from(self.ast_factory.make_id_ref_expr(SPAN, binding_name)),
],
&self.ast_factory,
),
false,
&self.ast_factory,
);
Some(ast::Statement::ExpressionStatement(ast::ExpressionStatement::boxed(
span,
call_expr,
&self.ast_factory,
)))
}
fn generate_declaration_of_module_namespace_object(
&mut self,
binding_name_for_namespace_object_ref: &str,
scoping: &Scoping,
) -> Vec<ast::Statement<'ast>> {
let mut arg_obj_expr = ast::ObjectExpression::boxed(
SPAN,
oxc::allocator::Vec::with_capacity_in(self.exports.len(), &self.ast_factory),
&self.ast_factory,
);
arg_obj_expr.properties.extend(self.exports.drain(..));
arg_obj_expr.properties.extend(self.named_exports.iter().map(|(exported, named_export)| {
let expr = if let Some(local_binding) = self.import_bindings.get(&named_export.local_binding)
{
self.ast_factory.make_id_ref_expr(SPAN, local_binding)
} else {
let name = scoping.symbol_name(named_export.local_binding);
self.ast_factory.make_id_ref_expr(SPAN, name)
};
let computed = !is_validate_identifier_name(exported.as_str());
self.ast_factory.make_lazy_export_property(exported, expr, computed)
}));
let export_call_expr = ast::Expression::new_call_expression(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_runtime__.__exportAll"),
NONE,
oxc::allocator::Vec::from_array_in(
[ast::Argument::ObjectExpression(arg_obj_expr.into_in(self.ast_factory.allocator()))],
&self.ast_factory,
),
false,
&self.ast_factory,
);
let decl_stmt =
self.ast_factory.make_var_decl(binding_name_for_namespace_object_ref, export_call_expr);
vec![decl_stmt]
}
pub fn try_rewrite_dynamic_import(&self, it: &mut ast::Expression<'ast>) {
let ast::Expression::ImportExpression(import_expr) = it else {
return;
};
let Some(rec_idx) = self.module.imports.get(&import_expr.node_id()) else {
return;
};
let Some(importee_idx) = self.module.import_records[*rec_idx].resolved_module else {
return;
};
let Module::Normal(importee) = &self.modules[importee_idx] else {
return;
};
if importee.id.contains("?rolldown-lazy=1") {
let encode_call = ast::Expression::CallExpression(ast::CallExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, "encodeURIComponent"),
NONE,
oxc::allocator::Vec::from_value_in(
ast::Argument::StringLiteral(ast::StringLiteral::boxed(
SPAN,
Str::from_str_in(&importee.id, &self.ast_factory),
None,
&self.ast_factory,
)),
&self.ast_factory,
),
false,
&self.ast_factory,
));
let url_expr = {
let quasis = oxc::allocator::Vec::from_iter_in(
[
ast::TemplateElement::new(
SPAN,
ast::TemplateElementValue {
raw: Str::from_str_in("/@vite/lazy?id=", &self.ast_factory),
cooked: None,
},
false,
&self.ast_factory,
),
ast::TemplateElement::new(
SPAN,
ast::TemplateElementValue {
raw: Str::from_str_in("&clientId=", &self.ast_factory),
cooked: None,
},
false,
&self.ast_factory,
),
ast::TemplateElement::new(
SPAN,
ast::TemplateElementValue {
raw: Str::from_str_in("", &self.ast_factory),
cooked: None,
},
true,
&self.ast_factory,
),
],
&self.ast_factory,
);
let expressions = oxc::allocator::Vec::from_iter_in(
[
encode_call,
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "clientId"),
],
&self.ast_factory,
);
ast::Expression::new_template_literal(SPAN, quasis, expressions, &self.ast_factory)
};
let import_expr =
ast::Expression::new_import_expression(SPAN, url_expr, None, None, &self.ast_factory);
let load_exports_call = ast::Expression::CallExpression(ast::CallExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_runtime__.loadExports"),
NONE,
oxc::allocator::Vec::from_value_in(
ast::Argument::StringLiteral(ast::StringLiteral::boxed(
SPAN,
Str::from_str_in(&importee.stable_id, &self.ast_factory),
None,
&self.ast_factory,
)),
&self.ast_factory,
),
false,
&self.ast_factory,
));
let arrow_fn = ast::Expression::new_arrow_function_expression(
SPAN,
true,
false,
NONE,
ast::FormalParameters::new(
SPAN,
ast::FormalParameterKind::ArrowFormalParameters,
oxc::allocator::Vec::new_in(&self.ast_factory),
NONE,
&self.ast_factory,
),
NONE,
ast::FunctionBody::new(
SPAN,
oxc::allocator::Vec::new_in(&self.ast_factory),
oxc::allocator::Vec::from_value_in(
ast::Statement::ExpressionStatement(ast::ExpressionStatement::boxed(
SPAN,
load_exports_call,
&self.ast_factory,
)),
&self.ast_factory,
),
&self.ast_factory,
),
&self.ast_factory,
);
let then_callee = Expression::StaticMemberExpression(ast::StaticMemberExpression::boxed(
SPAN,
import_expr,
ast::IdentifierName::new(SPAN, "then", &self.ast_factory),
false,
&self.ast_factory,
));
*it = ast::Expression::new_call_expression(
SPAN,
then_callee,
NONE,
oxc::allocator::Vec::from_value_in(ast::Argument::from(arrow_fn), &self.ast_factory),
false,
&self.ast_factory,
);
return;
}
let is_importee_cjs = importee.exports_kind == rolldown_common::ExportsKind::CommonJs;
let mut load_exports_call_expr = ast::Expression::CallExpression(ast::CallExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_runtime__.loadExports"),
NONE,
oxc::allocator::Vec::from_value_in(
ast::Argument::StringLiteral(ast::StringLiteral::boxed(
SPAN,
Str::from_str_in(&importee.stable_id, &self.ast_factory),
None,
&self.ast_factory,
)),
&self.ast_factory,
),
false,
&self.ast_factory,
));
if is_importee_cjs {
let is_node_cjs = importee.def_format.is_commonjs();
let mut args = oxc::allocator::Vec::from_value_in(
ast::Argument::from(load_exports_call_expr),
&self.ast_factory,
);
if is_node_cjs {
args.push(ast::Argument::from(ast::Expression::new_numeric_literal(
SPAN,
1.0,
None,
ast::NumberBase::Decimal,
&self.ast_factory,
)));
}
load_exports_call_expr = ast::Expression::new_call_expression(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, "__rolldown_runtime__.__toDynamicImportESM"),
NONE,
args,
false,
&self.ast_factory,
);
}
if let Some(init_fn_name) = self.affected_module_idx_to_init_fn_name.get(&importee_idx) {
let init_fn_call = ast::CallExpression::boxed(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, init_fn_name),
NONE,
oxc::allocator::Vec::new_in(&self.ast_factory),
false,
&self.ast_factory,
);
let promise_resolve_then_load_exports =
self.ast_factory.make_promise_resolve_then(load_exports_call_expr);
let ret_expr = ast::Expression::SequenceExpression(ast::SequenceExpression::boxed(
SPAN,
oxc::allocator::Vec::from_array_in(
[ast::Expression::CallExpression(init_fn_call), promise_resolve_then_load_exports],
&self.ast_factory,
),
&self.ast_factory,
));
*it = ret_expr;
} else {
*it = self.ast_factory.make_promise_resolve_then(load_exports_call_expr);
}
}
pub fn try_rewrite_require(
&self,
it: &mut ast::Expression<'ast>,
ctx: &oxc_traverse::TraverseCtx<'ast, ()>,
) {
let scoping = ctx.scoping();
if let Some(id_ref) = it.as_identifier()
&& id_ref.name == CJS_REQUIRE_REF_STR
&& id_ref.is_global_reference(scoping)
&& !ctx.parent().is_call_expression()
{
*it = self.ast_factory.make_member_access_expr("__rolldown_runtime__", "loadExports");
}
let ast::Expression::CallExpression(call_expr) = it else {
return;
};
if !call_expr
.callee
.as_identifier()
.is_some_and(|id| id.name == CJS_REQUIRE_REF_STR && id.is_global_reference(scoping))
{
return;
}
let Some(rec_idx) = self.module.imports.get(&call_expr.node_id()) else {
return;
};
let rec = &self.module.import_records[*rec_idx];
let Some(importee_idx) = rec.resolved_module else {
return;
};
let Module::Normal(importee) = &self.modules[importee_idx] else {
return;
};
let is_importee_cjs = importee.exports_kind == rolldown_common::ExportsKind::CommonJs;
let load_exports_call = self.ast_factory.make_call_with_arg(
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "loadExports"),
ast::Expression::new_string_literal(
SPAN,
Str::from_str_in(&importee.stable_id, &self.ast_factory),
None,
&self.ast_factory,
),
false,
);
let load_exports_expr = if importee.meta.has_lazy_export() || is_importee_cjs {
load_exports_call
} else if rec.meta.contains(ImportRecordMeta::JsonModule) {
let to_commonjs_call = self.ast_factory.make_call_with_arg(
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "__toCommonJS"),
load_exports_call,
false,
);
Expression::from(ast::MemberExpression::new_static_member_expression(
SPAN,
to_commonjs_call,
self.ast_factory.make_id_name(SPAN, "default"),
false,
&self.ast_factory,
))
} else {
self.ast_factory.make_call_with_arg(
self.ast_factory.make_member_access_expr("__rolldown_runtime__", "__toCommonJS"),
load_exports_call,
false,
)
};
if let Some(init_fn_name) = self.affected_module_idx_to_init_fn_name.get(&importee_idx) {
*it = self.ast_factory.make_seq_in_parens(
ast::Expression::new_call_expression(
SPAN,
self.ast_factory.make_id_ref_expr(SPAN, init_fn_name),
NONE,
oxc::allocator::Vec::new_in(&self.ast_factory),
false,
&self.ast_factory,
),
load_exports_expr,
);
} else {
*it = load_exports_expr;
}
}
}
pub struct NamedExport {
pub local_binding: SymbolId,
}