Skip to content

Commit

Permalink
feat: support export star commonjs (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin committed Oct 20, 2023
1 parent 3c11c38 commit 07b8c03
Show file tree
Hide file tree
Showing 58 changed files with 259 additions and 85 deletions.
19 changes: 16 additions & 3 deletions crates/rolldown/src/bundler/graph/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ impl<'graph> Linker<'graph> {
}

pub fn link(&mut self) {
self.wrap_modules_if_needed();

self.mark_module_wrapped();
// propagate star exports
for id in &self.graph.sorted_modules {
let importer = &self.graph.modules[*id];
Expand All @@ -47,7 +46,8 @@ impl<'graph> Linker<'graph> {
});
}

fn wrap_modules_if_needed(&mut self) {
#[allow(clippy::too_many_lines)]
fn mark_module_wrapped(&mut self) {
// Detect module need wrapped, here has two cases:
// - Commonjs module, because cjs symbols can't static binding, it need to be wrapped and lazy evaluated.
// - Import esm module at commonjs module.
Expand Down Expand Up @@ -98,6 +98,7 @@ impl<'graph> Linker<'graph> {
// Generate symbol for import warp module
// Case esm import commonjs, eg var commonjs_ns = __toESM(require_a())
// Case commonjs require esm, eg (init_esm(), __toCommonJS(esm_ns))
// Case esm export star commonjs, eg __reExport(esm_ns, __toESM(require_a())
let mut imported_symbols = vec![];

for module in &self.graph.modules {
Expand Down Expand Up @@ -125,6 +126,18 @@ impl<'graph> Linker<'graph> {
}
}
});
importer.star_exports.iter().for_each(|record_id| {
let rec = &importer.import_records[*record_id];
match &self.graph.modules[rec.resolved_module] {
Module::Normal(importee) => {
if importee.exports_kind == ExportsKind::CommonJs {
imported_symbols
.push((importer.id, self.graph.runtime.resolve_symbol(&"__reExport".into())));
}
}
Module::External(_) => {}
}
});
}
Module::External(_) => {}
}
Expand Down
7 changes: 3 additions & 4 deletions crates/rolldown/src/bundler/visitors/esm_source_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ impl<'ast> EsmSourceRender<'ast> {

pub fn apply(&mut self) {
let module = self.ctx.module;
let program = module.ast.program();
self.visit_program(program);

if let Some(namespace_name) = self.ctx.namespace_symbol_name {
let exports: String = module
.resolved_exports
Expand All @@ -29,8 +26,10 @@ impl<'ast> EsmSourceRender<'ast> {
})
.collect::<Vec<_>>()
.join(",\n");
self.ctx.source.append(format!("\nvar {namespace_name} = {{\n{exports}\n}};\n",));
self.ctx.source.prepend(format!("\nvar {namespace_name} = {{\n{exports}\n}};\n",));
}
let program = module.ast.program();
self.visit_program(program);
}
}

Expand Down
20 changes: 20 additions & 0 deletions crates/rolldown/src/bundler/visitors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,26 @@ impl<'ast> RendererContext<'ast> {
&mut self,
decl: &'ast oxc::ast::ast::ExportAllDeclaration<'ast>,
) {
let rec = &self.module.import_records[self.module.imports.get(&decl.span).copied().unwrap()];
if let Module::Normal(importee) = &self.modules[rec.resolved_module] {
if importee.exports_kind == ExportsKind::CommonJs {
// __reExport(a_exports, __toESM(require_c()));
let namespace_name = self.namespace_symbol_name.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());
let re_export_runtime_symbol_name =
self.get_runtime_symbol_final_name(&"__reExport".into());
self.source.update(
decl.span.start,
decl.span.end,
format!(
"{re_export_runtime_symbol_name}({namespace_name}, {to_esm_runtime_symbol_name}({wrap_symbol_name}(){}));",
if self.module.module_type.is_esm() { ", 1" } else { "" }
),
);
return;
}
}
self.remove_node(decl.span);
}

Expand Down
1 change: 1 addition & 0 deletions crates/rolldown/src/bundler/visitors/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl<'a> Scanner<'a> {
// export * from '...'
self.result.star_exports.push(id);
}
self.result.imports.insert(decl.span, id);
}

fn scan_export_named_decl(&mut self, decl: &ExportNamedDeclaration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/default/export_forms_es6

```js
// b.js
const xyz = null
var b_ns = {
get xyz() { return xyz }
};
const xyz = null
// a.js
const abc = undefined
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_import_star_capture

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_import_star_no_capt

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_self_and_import_sel
```js
// main.js
const foo = 123
console.log(main_ns)
var main_ns = {
get foo() { return foo }
};
const foo = 123
console.log(main_ns)
export { foo };
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_self_as_namespace_c

```js
// main.js
const foo = 123
var main_ns = {
get ns() { return main_ns },
get foo() { return foo }
};
const foo = 123
export { foo, main_ns as ns };
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_self_as_namespace_e

```js
// main.js
const foo = 123
var main_ns = {
get ns() { return main_ns },
get foo() { return foo }
};
const foo = 123
export { foo, main_ns as ns };
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_star_as_capture

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
// main.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_star_as_no_capture

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
// main.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/export_star_as_unused

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
// main.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/import_default_namespace_c

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// bar.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ input_file: crates/rolldown/tests/esbuild/import_star/import_export_self_as_name

```js
// main.js
const foo = 123
var main_ns = {
get ns() { return main_ns },
get foo() { return foo }
};
const foo = 123
export { foo, main_ns as ns };
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ const x = 1
const y = 2
// common.js
var common_ns = {
get z() { return z },
get x() { return x }
};
// main.js
console.log(common_ns.x, common_ns.y, common_ns.z)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
source: crates/rolldown/tests/common/case.rs
expression: content
input_file: crates/rolldown/tests/esbuild/import_star/import_star_and_common_js
---
# main.js

```js
// foo.js
var foo;
var foo_ns = {
get foo() { return foo }
};
var init_foo = __esm({
'foo.js'() {
foo = 123
}
});
// entry.js
init_foo();
const ns2 = (init_foo(), __toCommonJS(foo_ns))
console.log(foo_ns.foo, ns2.foo)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"input": {
"input": [
{
"name": "main",
"import": "./entry.js"
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ input_file: crates/rolldown/tests/esbuild/import_star/import_star_capture

```js
// foo.js
const foo$1 = 123
var foo_ns = {
get foo() { return foo$1 }
};
const foo$1 = 123
// main.js
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: crates/rolldown/tests/common/case.rs
expression: content
input_file: crates/rolldown/tests/esbuild/import_star/import_star_common_js_capture
---
# main.js

```js
// foo.js
var require_foo = __commonJS({
'foo.js'(exports, module) {
exports.foo = 123
}
});
// entry.js
var foo_ns = __toESM(require_foo());
let foo = 234
console.log(foo_ns, foo_ns.foo, foo)
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"input": {
"input": [
{
"name": "main",
"import": "./entry.js"
}
]
}
}

0 comments on commit 07b8c03

Please sign in to comment.