Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(es/module): Add export_interop_annotation flag #7330

Merged
merged 3 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions bindings/binding_core_wasm/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,14 @@ export interface BaseModuleConfig {
* ```
*/
importInterop?: "swc" | "babel" | "node" | "none";
/**
* Emits `cjs-module-lexer` annotation
* `cjs-module-lexer` is used in Node.js core for detecting the named exports available when importing a CJS module into ESM.
* swc will emit `cjs-module-lexer` detectable annotation with this option enabled.
*
* Defaults to `true` if import_interop is Node, else `false`
*/
exportInteropAnnotation?: boolean;
/**
* If set to true, dynamic imports will be preserved.
*/
Expand Down
9 changes: 5 additions & 4 deletions crates/swc_ecma_transforms_module/src/common_js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,15 @@ where
is_export_assign: bool,
) -> impl Iterator<Item = Stmt> {
let import_interop = self.config.import_interop();
let export_interop_annotation = self.config.export_interop_annotation();
let is_node = import_interop.is_node();

let mut stmts = Vec::with_capacity(link.len());

let mut export_obj_prop_list = export.into_iter().map(From::from).collect();

let lexer_reexport = if is_node {
self.emit_lexer_ts_reexport(&link)
let lexer_reexport = if export_interop_annotation {
self.emit_lexer_reexport(&link)
} else {
None
};
Expand Down Expand Up @@ -355,7 +356,7 @@ where
let mut features = self.available_features;
let exports = self.exports();

if is_node {
if export_interop_annotation {
if export_obj_prop_list.len() > 1 {
export_stmts.extend(self.emit_lexer_exports_init(&export_obj_prop_list));
} else {
Expand Down Expand Up @@ -507,7 +508,7 @@ where
/// ```javascript
/// 0 && __export(require("foo")) && __export(require("bar"));
/// ```
fn emit_lexer_ts_reexport(&self, link: &Link) -> Option<Stmt> {
fn emit_lexer_reexport(&self, link: &Link) -> Option<Stmt> {
link.iter()
.filter(|(.., LinkItem(.., link_flag))| link_flag.export_star())
.map(|(src, ..)| {
Expand Down
16 changes: 16 additions & 0 deletions crates/swc_ecma_transforms_module/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ pub struct Config {
pub lazy: Lazy,
#[serde(default)]
pub import_interop: Option<ImportInterop>,
/// Emits `cjs-module-lexer` annotation
/// `cjs-module-lexer` is used in Node.js core for detecting the named
/// exports available when importing a CJS module into ESM.
/// swc will emit `cjs-module-lexer` detectable annotation with this option
/// enabled.
///
/// Defaults to `true` if import_interop is Node, else `false`
#[serde(default)]
pub export_interop_annotation: Option<bool>,
#[serde(default)]
/// Note: deprecated
pub no_interop: bool,
Expand All @@ -39,6 +48,7 @@ impl Default for Config {
strict_mode: default_strict_mode(),
lazy: Lazy::default(),
import_interop: None,
export_interop_annotation: None,
no_interop: false,
ignore_dynamic: false,
preserve_import_meta: false,
Expand Down Expand Up @@ -75,6 +85,12 @@ impl Config {
self.import_interop
.unwrap_or_else(|| self.no_interop.into())
}

#[inline(always)]
pub fn export_interop_annotation(&self) -> bool {
self.export_interop_annotation
.unwrap_or_else(|| self.import_interop == Some(ImportInterop::Node))
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function useRouter() {}

export default useRouter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"importInterop": "swc",
"exportInteropAnnotation": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
define([
"require",
"exports"
], function(require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useRouter: function() {
return useRouter;
},
default: function() {
return _default;
}
});
function useRouter() {}
const _default = useRouter;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
useRouter: null,
default: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useRouter: function() {
return useRouter;
},
default: function() {
return _default;
}
});
function useRouter() {}
const _default = useRouter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(function(global, factory) {
if (typeof module === "object" && typeof module.exports === "object") factory(exports);
else if (typeof define === "function" && define.amd) define([
"exports"
], factory);
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {});
})(this, function(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useRouter: function() {
return useRouter;
},
default: function() {
return _default;
}
});
function useRouter() {}
const _default = useRouter;
});
8 changes: 8 additions & 0 deletions node-swc/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,14 @@ export interface BaseModuleConfig {
* ```
*/
importInterop?: "swc" | "babel" | "node" | "none";
/**
* Emits `cjs-module-lexer` annotation
* `cjs-module-lexer` is used in Node.js core for detecting the named exports available when importing a CJS module into ESM.
* swc will emit `cjs-module-lexer` detectable annotation with this option enabled.
*
* Defaults to `true` if import_interop is Node, else `false`
*/
exportInteropAnnotation?: boolean;
/**
* If set to true, dynamic imports will be preserved.
*/
Expand Down