Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5418e1f

Browse files
authored
feat: support output.exports for IIFE format align with rollup. (#1691)
In PR #1680, support for `output.exports` was only available for the `Cjs` format. This PR extends the support to the `IIFE` format. ### Modifications 1. **Wrapper Function Update:** - In `crates/rolldown/src/ecmascript/format/iife.rs`, the declaration part of the wrapper function has been rewritten. The `exports` argument is now enabled only if `output.exports` is `named`, and the non-name mode issue has been fixed. Similar changes have been made to the ending part of the wrapper function. 2. **Return Value Alignment:** - In `crates/rolldown/src/utils/chunk/render_chunk_exports.rs`, the value is now returned directly instead of assigning it to `exports`, aligning with Rollup’s behavior when `output.exports` is `default` and the `format` is `iife`. 3. **Removal of `__esModule` Property:** - The statement `Object.defineProperty(exports, '__esModule', { value: true });` has been removed when `output.exports` is `default` and the `format` is either `cjs` or `iife`, as it previously caused errors in some cases. 4. **Testing:** - Added tests for the `iife` format to ensure correct handling of `output.exports`. These changes ensure better alignment with Rollup and improve the robustness of the `IIFE` format support in the project.
1 parent edc2c1a commit 5418e1f

16 files changed

Lines changed: 177 additions & 21 deletions

File tree

crates/rolldown/src/ecmascript/format/iife.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use rolldown_sourcemap::{ConcatSource, RawSource};
2-
31
use crate::{
42
ecmascript::ecma_generator::RenderedModuleSources,
53
types::generator::GenerateContext,
6-
utils::chunk::render_chunk_exports::{get_export_items, render_chunk_exports},
4+
utils::chunk::render_chunk_exports::{
5+
determine_export_mode, get_export_items, render_chunk_exports,
6+
},
77
};
8+
use rolldown_common::OutputExports;
9+
use rolldown_sourcemap::{ConcatSource, RawSource};
810

911
pub fn render_iife(
1012
ctx: &GenerateContext<'_>,
@@ -19,14 +21,19 @@ pub fn render_iife(
1921
}
2022
// iife wrapper start
2123
let has_exports = !get_export_items(ctx.chunk, ctx.link_output).is_empty();
22-
if let Some(name) = &ctx.options.name {
23-
concat_source.add_source(Box::new(RawSource::new(format!(
24-
"var {name} = (function({}) {{\n",
25-
if has_exports { "exports" } else { "" }
26-
))));
27-
} else {
28-
concat_source.add_source(Box::new(RawSource::new("(function() {\n".to_string())));
29-
}
24+
// Since before rendering the `determine_export_mode` runs, `unwrap` here won't cause panic.
25+
// FIXME do not call `determine_export_mode` twice
26+
let named_exports = matches!(
27+
determine_export_mode(ctx.chunk, &ctx.options.exports, ctx.link_output).unwrap(),
28+
OutputExports::Named
29+
);
30+
31+
concat_source.add_source(Box::new(RawSource::new(format!(
32+
"{}(function({}) {{\n",
33+
if let Some(name) = &ctx.options.name { format!("var {name} = ") } else { String::new() },
34+
// TODO handle external imports here.
35+
if has_exports && named_exports { "exports" } else { "" }
36+
))));
3037

3138
// TODO iife imports
3239

@@ -45,12 +52,17 @@ pub fn render_iife(
4552
render_chunk_exports(ctx.chunk, &ctx.link_output.runtime, ctx.link_output, ctx.options)
4653
{
4754
concat_source.add_source(Box::new(RawSource::new(exports)));
48-
concat_source.add_source(Box::new(RawSource::new("return exports;".to_string())));
55+
if named_exports {
56+
// We need to add `return exports;` here only if using `named`, because the default value is returned when using `default` in `render_chunk_exports`.
57+
concat_source.add_source(Box::new(RawSource::new("return exports;".to_string())));
58+
}
4959
}
5060

5161
// iife wrapper end
52-
concat_source
53-
.add_source(Box::new(RawSource::new(format!("}})({});", if has_exports { "{}" } else { "" }))));
62+
concat_source.add_source(Box::new(RawSource::new(format!(
63+
"}})({});",
64+
if has_exports && named_exports { "{}" } else { "" }
65+
))));
5466

5567
if let Some(footer) = footer {
5668
concat_source.add_source(Box::new(RawSource::new(footer)));

crates/rolldown/src/utils/chunk/render_chunk_exports.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ pub fn render_chunk_exports(
5353
let module = &graph.module_table.modules[module].as_ecma().unwrap();
5454
if matches!(module.exports_kind, ExportsKind::Esm) {
5555
let export_mode = determine_export_mode(this, &output_options.exports, graph).unwrap();
56-
s.push_str("Object.defineProperty(exports, '__esModule', { value: true });\n");
56+
if matches!(export_mode, OutputExports::Named) {
57+
s.push_str("Object.defineProperty(exports, '__esModule', { value: true });\n");
58+
}
5759
let rendered_items = export_items
5860
.into_iter()
5961
.map(|(exported_name, export_ref)| {
@@ -77,7 +79,11 @@ pub fn render_chunk_exports(
7779
}
7880
}
7981
OutputExports::Default => {
80-
format!("module.exports = {canonical_name};")
82+
if matches!(output_options.format, OutputFormat::Cjs) {
83+
format!("module.exports = {canonical_name};")
84+
} else {
85+
format!("return {canonical_name};")
86+
}
8187
}
8288
OutputExports::None => String::new(),
8389
OutputExports::Auto => unreachable!(),

crates/rolldown/tests/fixtures/export_mode/cjs/auto/default/artifacts.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/rolldown_testing/src/case/case.rs
33
expression: content
4-
input_file: crates/rolldown/tests/fixtures/export_mode/cjs/auto-default
4+
input_file: crates/rolldown/tests/fixtures/export_mode/cjs/auto/default
55
---
66
# Assets
77

@@ -17,6 +17,5 @@ function main_default() {
1717
}
1818
1919
//#endregion
20-
Object.defineProperty(exports, '__esModule', { value: true });
2120
module.exports = main_default;
2221
```

crates/rolldown/tests/fixtures/export_mode/cjs/default/artifacts.snap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,5 @@ function example() {
2020
}
2121
2222
//#endregion
23-
Object.defineProperty(exports, '__esModule', { value: true });
2423
module.exports = default_mod_ns;
2524
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"config": {
3+
"exports": "auto",
4+
"format": "iife",
5+
"name": "MyLibrary"
6+
}
7+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
source: crates/rolldown_testing/src/case/case.rs
3+
expression: content
4+
input_file: crates/rolldown/tests/fixtures/export_mode/iife/auto/none
5+
---
6+
# Assets
7+
8+
## main.mjs
9+
10+
```js
11+
var MyLibrary = (function() {
12+
13+
//#region main.js
14+
console.log("none");
15+
16+
//#endregion
17+
})();
18+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('none')
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"config": {
3+
"exports": "default",
4+
"format": "iife"
5+
}
6+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: crates/rolldown_testing/src/case/case.rs
3+
expression: content
4+
input_file: crates/rolldown/tests/fixtures/export_mode/iife/default
5+
---
6+
# Assets
7+
8+
## main.mjs
9+
10+
```js
11+
(function() {
12+
13+
14+
//#region mod.js
15+
var default_mod_ns = {};
16+
__export(default_mod_ns, {
17+
add: () => add,
18+
subtract: () => subtract
19+
});
20+
function add(a, b) {
21+
return a + b;
22+
}
23+
function subtract(a, b) {
24+
return a - b;
25+
}
26+
27+
//#endregion
28+
return default_mod_ns;
29+
})();
30+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * as default from './mod.js'

0 commit comments

Comments
 (0)