Skip to content

Commit

Permalink
fix: hoisted import declaration (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin authored Oct 19, 2023
1 parent ee9a682 commit 569409d
Show file tree
Hide file tree
Showing 15 changed files with 90 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ impl<'ast> Visit<'ast> for CommonJsSourceRender<'ast> {
fn visit_import_declaration(&mut self, decl: &'ast oxc::ast::ast::ImportDeclaration<'ast>) {
self.ctx.visit_import_declaration(decl);
}

fn visit_statement(&mut self, stmt: &'ast oxc::ast::ast::Statement<'ast>) {
self.ctx.visit_statement(stmt);
self.visit_statement_match(stmt);
}
}
5 changes: 5 additions & 0 deletions crates/rolldown/src/bundler/visitors/esm_source_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,9 @@ impl<'ast> Visit<'ast> for EsmSourceRender<'ast> {
}
self.visit_expression(&expr.callee);
}

fn visit_statement(&mut self, stmt: &'ast oxc::ast::ast::Statement<'ast>) {
self.ctx.visit_statement(stmt);
self.visit_statement_match(stmt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,9 @@ impl<'ast> Visit<'ast> for EsmWrapSourceRender<'ast> {
}
self.visit_expression(&expr.callee);
}

fn visit_statement(&mut self, stmt: &'ast oxc::ast::ast::Statement<'ast>) {
self.ctx.visit_statement(stmt);
self.visit_statement_match(stmt);
}
}
28 changes: 17 additions & 11 deletions crates/rolldown/src/bundler/visitors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod scanner;
use index_vec::IndexVec;
use oxc::{
semantic::ReferenceId,
span::{Atom, Span},
span::{Atom, GetSpan, Span},
};
use rolldown_common::{ExportsKind, ModuleId, SymbolRef};
use rustc_hash::FxHashMap;
Expand All @@ -30,6 +30,8 @@ pub struct RendererContext<'ast> {
namespace_symbol_name: Option<&'ast Atom>,
default_symbol_name: Option<&'ast Atom>,
runtime: &'ast Runtime,
// Used to hoisted import declaration before the first statement
first_stmt_start: Option<u32>,
}

impl<'ast> RendererContext<'ast> {
Expand Down Expand Up @@ -66,6 +68,7 @@ impl<'ast> RendererContext<'ast> {
namespace_symbol_name,
default_symbol_name,
runtime,
first_stmt_start: None,
}
}

Expand Down Expand Up @@ -153,6 +156,7 @@ impl<'ast> RendererContext<'ast> {
self.remove_node(decl.span);
let rec = &self.module.import_records[self.module.imports.get(&decl.span).copied().unwrap()];
let importee = &self.modules[rec.resolved_module];
let start = self.first_stmt_start.unwrap_or(decl.span.start);
if let Module::Normal(importee) = importee {
if importee.exports_kind == ExportsKind::CommonJs {
// add import cjs symbol binding
Expand All @@ -161,8 +165,8 @@ impl<'ast> RendererContext<'ast> {
.unwrap();
let wrap_symbol_name = self.get_symbol_final_name(importee.wrap_symbol.unwrap()).unwrap();
let to_esm_runtime_symbol_name = self.get_runtime_symbol_final_name(&"__toESM".into());
self.source.prepend_left(
decl.span.start,
self.source.append_right(
start,
format!(
"var {namespace_name} = {to_esm_runtime_symbol_name}({wrap_symbol_name}(){});\n",
if self.module.module_type.is_esm() { ", 1" } else { "" }
Expand All @@ -173,27 +177,22 @@ impl<'ast> RendererContext<'ast> {
if let Some(name) = self.get_symbol_final_name(
(importee.id, importee.cjs_symbols[spec.imported.name()].symbol).into(),
) {
self
.source
.prepend_right(decl.span.start, format!("var {name} = {namespace_name}.{name};\n"));
self.source.append_right(start, format!("var {name} = {namespace_name}.{name};\n"));
}
}
oxc::ast::ast::ImportDeclarationSpecifier::ImportDefaultSpecifier(_) => {
if let Some(name) = self.get_symbol_final_name(
(importee.id, importee.cjs_symbols[&Atom::new_inline("default")].symbol).into(),
) {
self.source.prepend_right(
decl.span.start,
format!("var {name} = {namespace_name}.default;\n"),
);
self.source.append_right(start, format!("var {name} = {namespace_name}.default;\n"));
}
}
oxc::ast::ast::ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => {}
});
} else if let Some(wrap_symbol) = importee.wrap_symbol {
let wrap_symbol_name = self.get_symbol_final_name(wrap_symbol).unwrap();
// init wrapped esm module
self.source.prepend_left(decl.span.start, format!("{wrap_symbol_name}();\n"));
self.source.append_right(start, format!("{wrap_symbol_name}();\n"));
}
}
}
Expand Down Expand Up @@ -226,4 +225,11 @@ impl<'ast> RendererContext<'ast> {
}
}
}

fn visit_statement(&mut self, stmt: &'ast oxc::ast::ast::Statement<'ast>) {
if !matches!(stmt, oxc::ast::ast::Statement::Declaration(_)) && self.first_stmt_start.is_none()
{
self.first_stmt_start = Some(stmt.span().start);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
source: crates/rolldown/tests/common/case.rs
expression: content
input_file: crates/rolldown/tests/esbuild/default/es6_from_common_js
---
# main.js

```js
// bar.js
var require_bar = __commonJS({
'bar.js'(exports, module) {
exports.bar = function() {
return 'bar'
}
}
});
// foo.js
var require_foo = __commonJS({
'foo.js'(exports, module) {
exports.foo = function() {
return 'foo'
}
}
});
// main.js
var foo_ns = __toESM(require_foo());
var foo = foo_ns.foo;
var bar_ns = __toESM(require_bar());
var bar = bar_ns.bar;

console.log(foo(), bar())
// This should be hoisted
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/rolldown/tests/common/case.rs
expression: content
input_file: crates/rolldown/tests/esbuild/default/nested_es6_from_common_js
---
# main.js

```js
// foo.js
var require_foo = __commonJS({
'foo.js'(exports, module) {
exports.fn = function() {
return 123
}
}
});
// main.js
var foo_ns = __toESM(require_foo());
var fn = foo_ns.fn;

(() => {
console.log(fn())
})()
```
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ module.exports = value;
// main.js
var commonjs_ns = __toESM(require_commonjs$1());
var _default = commonjs_ns.default;

init_esm();


console.log(_default, esm_default_fn, esm_named_var, esm_named_fn, esm_named_class)
// test commonjs warp symbol deconflict
const require_commonjs = () => {}
Expand Down
2 changes: 0 additions & 2 deletions crates/rolldown/tests/fixtures/mix-cjs-esm/artifacts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,5 @@ const value$1 = 1;
module.exports = 1;
const value = 1;
// main.js


var esm_import_cjs_export_ns = __toESM(require_esm_import_cjs_export());
```

0 comments on commit 569409d

Please sign in to comment.