fix(es/transforms/cjs): Allow using multiple export * (#2598)

swc_ecma_transforms_module:
 - Preserve order of imports for reexports. (#2594)
This commit is contained in:
OJ Kwon 2021-11-01 21:59:33 -07:00 committed by GitHub
parent f8c7d36ac9
commit 5b141ee80a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 215 additions and 201 deletions

View File

@ -516,7 +516,10 @@ where
};
for export in export_alls {
stmts.push(scope.handle_export_all(
let export = scope
.import_to_export(&export.src, true)
.expect("Export should exists");
stmts.push(Scope::handle_export_all(
exports_ident.clone(),
exported_names.clone(),
export,

View File

@ -9,8 +9,8 @@ use std::{
cell::{Ref, RefCell, RefMut},
rc::Rc,
};
use swc_atoms::js_word;
use swc_common::{FileName, Mark, Span, DUMMY_SP};
use swc_atoms::{js_word, JsWord};
use swc_common::{collections::AHashMap, FileName, Mark, Span, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::helper;
use swc_ecma_utils::{
@ -84,7 +84,10 @@ where
let mut exports = vec![];
let mut initialized = IndexSet::default();
let mut export_alls = vec![];
let mut export_alls: AHashMap<JsWord, Ident> = Default::default();
// Used only if export * exists
let mut exported_names: Option<Ident> = None;
for item in items {
self.in_top_level = true;
@ -174,6 +177,7 @@ where
}
drop(scope);
drop(scope_ref_mut);
match item {
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export)) => {
self.scope
@ -181,7 +185,61 @@ where
.lazy_blacklist
.insert(export.src.value.clone());
export_alls.push(export);
let mut scope_ref_mut = self.scope.borrow_mut();
let scope = &mut *scope_ref_mut;
if exported_names.is_none()
&& (export_alls.len() >= 1 || !exports.is_empty())
{
let exported_names_ident = private_ident!("_exportNames");
stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(exported_names_ident.clone().into()),
init: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: exports
.clone()
.into_iter()
.filter_map(|export| {
if export == js_word!("default") {
return None;
}
Some(PropOrSpread::Prop(Box::new(
Prop::KeyValue(KeyValueProp {
key: PropName::Ident(Ident::new(
export, DUMMY_SP,
)),
value: Box::new(Expr::Lit(Lit::Bool(
Bool {
span: DUMMY_SP,
value: true,
},
))),
}),
)))
})
.collect(),
}))),
definite: false,
}],
declare: false,
}))));
exported_names = Some(exported_names_ident);
}
export_alls.entry(export.src.value.clone()).or_insert(
scope
.import_to_export(&export.src, true)
.expect("Export should exists"),
);
drop(scope);
drop(scope_ref_mut);
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: decl @ Decl::Class(..),
@ -521,61 +579,8 @@ where
}
}
let has_export = !exports.is_empty();
let mut scope_ref_mut = self.scope.borrow_mut();
let scope = &mut *scope_ref_mut;
// Used only if export * exists
let exported_names = {
if (!export_alls.is_empty() && has_export) || export_alls.len() >= 2 {
let exported_names = private_ident!("_exportNames");
stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(exported_names.clone().into()),
init: Some(Box::new(Expr::Object(ObjectLit {
span: DUMMY_SP,
props: exports
.into_iter()
.filter_map(|export| {
if export == js_word!("default") {
return None;
}
Some(PropOrSpread::Prop(Box::new(Prop::KeyValue(
KeyValueProp {
key: PropName::Ident(Ident::new(export, DUMMY_SP)),
value: Box::new(Expr::Lit(Lit::Bool(Bool {
span: DUMMY_SP,
value: true,
}))),
},
))))
})
.collect(),
}))),
definite: false,
}],
declare: false,
}))));
Some(exported_names)
} else {
None
}
};
for export in export_alls {
// We use extra_stmts because it should be placed *after* import
// statements.
extra_stmts.push(ModuleItem::Stmt(scope.handle_export_all(
quote_ident!("exports"),
exported_names.clone(),
export,
)));
}
if !initialized.is_empty() {
stmts.push(
@ -699,6 +704,15 @@ where
stmts.push(require.into_stmt().into());
}
}
let exported = export_alls.remove(&src);
if let Some(export) = exported {
stmts.push(ModuleItem::Stmt(Scope::handle_export_all(
quote_ident!("exports"),
exported_names.clone(),
export,
)));
}
}
stmts.append(&mut extra_stmts);

View File

@ -525,7 +525,10 @@ where
};
for export in export_alls {
stmts.push(scope.handle_export_all(
let export = scope
.import_to_export(&export.src, true)
.expect("Export should exists");
stmts.push(Scope::handle_export_all(
exports_ident.clone(),
exported_names.clone(),
export,

View File

@ -155,13 +155,10 @@ impl Scope {
/// # Parameters
/// - `exported_names` Ident of the object literal.
pub fn handle_export_all(
&mut self,
exports: Ident,
exported_names: Option<Ident>,
export: ExportAll,
imported: Ident,
) -> Stmt {
let imported = self.import_to_export(&export.src, true).unwrap();
let key_ident = private_ident!("key");
let function = Function {

View File

@ -1251,7 +1251,6 @@ var _exportNames = {
};
var _white = require("white");
var _black = require("black");
Object.keys(_white).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
@ -1265,6 +1264,8 @@ Object.keys(_white).forEach(function (key) {
});
});
var _black = require("black");
Object.keys(_black).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@ -3785,18 +3786,12 @@ export * from 'react';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {};
var _exportNames = {
};
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
// The fact that this exports both a normal default, and all of the names via
// re-export is an edge case that is important not to miss. See
// https://github.com/babel/babel/issues/8306 as an example.
var _default = _react.default;
exports.default = _default;
Object.keys(_react).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@ -3809,6 +3804,12 @@ Object.keys(_react).forEach(function (key) {
});
});
// The fact that this exports both a normal default, and all of the names via
// re-export is an edge case that is important not to miss. See
// https://github.com/babel/babel/issues/8306 as an example.
var _default = _react.default;
exports.default = _default;
"#
);
@ -4093,19 +4094,19 @@ test!(
issue_962,
"import root from './_root.js';
import stubFalse from './stubFalse.js';
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && \
module;
var moduleExports = freeModule && freeModule.exports === freeExports;
var Buffer = moduleExports ? root.Buffer : undefined;
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;
var isBuffer = nativeIsBuffer || stubFalse;
export default isBuffer",
r#"
"use strict";
@ -4166,14 +4167,9 @@ Object.defineProperty(exports, "Scope", {
return _interfaces.Scope;
}
});
var _exportNames = {
Scope: true
};
var _http = require("./http");
var _interfaces = require("./interfaces");
Object.keys(_http).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _http[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
@ -4182,6 +4178,7 @@ Object.keys(_http).forEach(function(key) {
}
});
});
var _interfaces = require("./interfaces");
"#
);
@ -4214,8 +4211,6 @@ export * from './pipes';
};
require("reflect-metadata");
var _http = require("./http");
var _interfaces = require("./interfaces");
var _pipes = require("./pipes");
Object.keys(_http).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@ -4227,6 +4222,8 @@ export * from './pipes';
}
});
});
var _interfaces = require("./interfaces");
var _pipes = require("./pipes");
Object.keys(_pipes).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@ -4544,7 +4541,7 @@ test!(
console.log(foo);
}
}
export default class NotOK {
constructor() {
console.log(foo);
@ -4557,9 +4554,9 @@ test!(
value: true
});
exports.default = void 0;
var _foo = _interopRequireDefault(require('foo'));
class OK {
constructor() {
console.log(_foo.default);
@ -4685,11 +4682,11 @@ test!(
});
exports.get = get;
exports.default = void 0;
function get(key) {
console.log(key);
}
var _default = a;
exports.default = _default;
"
@ -4756,20 +4753,18 @@ test!(
};
exports.BIZ = void 0;
var _file1 = require('./File1');
var _file2 = require('./File2');
const BIZ = 'biz';
exports.BIZ = BIZ;
Object.keys(_file1).forEach(function(key) {
if (key === 'default' || key === '__esModule') return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _file1[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _file1[key];
}
});
if (key === 'default' || key === '__esModule') return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _file1[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _file1[key];
}
});
});
var _file2 = require('./File2');
Object.keys(_file2).forEach(function(key) {
if (key === 'default' || key === '__esModule') return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@ -4781,6 +4776,8 @@ test!(
}
});
});
const BIZ = 'biz';
exports.BIZ = BIZ;
"
);
@ -4922,7 +4919,7 @@ test!(
ignore_dynamic_1,
"
import foo from 'foo';
function foo() {
await import('foo');

View File

@ -10,6 +10,16 @@ Object.defineProperty(exports, "render", {
});
var _customRender = require("./customRender");
var _react = _interopRequireWildcard(require("@testing-library/react"));
Object.keys(_react).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _react[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _react[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -33,13 +43,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_react).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _react[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _react[key];
}
});
});

View File

@ -5,7 +5,29 @@ Object.defineProperty(exports, "__esModule", {
var _exportNames = {
};
var _appConfig = _interopRequireWildcard(require("./app.config"));
Object.keys(_appConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _appConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _appConfig[key];
}
});
});
var _databaseConfig = _interopRequireWildcard(require("./database.config"));
Object.keys(_databaseConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _databaseConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _databaseConfig[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -29,25 +51,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_appConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _appConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _appConfig[key];
}
});
});
Object.keys(_databaseConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _databaseConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _databaseConfig[key];
}
});
});

View File

@ -5,7 +5,29 @@ Object.defineProperty(exports, "__esModule", {
var _exportNames = {
};
var _appConfig = _interopRequireWildcard(require("./app.config"));
Object.keys(_appConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _appConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _appConfig[key];
}
});
});
var _databaseConfig = _interopRequireWildcard(require("./database.config"));
Object.keys(_databaseConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _databaseConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _databaseConfig[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -29,25 +51,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_appConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _appConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _appConfig[key];
}
});
});
Object.keys(_databaseConfig).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _databaseConfig[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _databaseConfig[key];
}
});
});

View File

@ -5,7 +5,29 @@ Object.defineProperty(exports, "__esModule", {
var _exportNames = {
};
var _foo = _interopRequireWildcard(require("./foo"));
Object.keys(_foo).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _foo[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _foo[key];
}
});
});
var _bar = _interopRequireWildcard(require("./bar"));
Object.keys(_bar).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _bar[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _bar[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -29,25 +51,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_foo).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _foo[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _foo[key];
}
});
});
Object.keys(_bar).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _bar[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _bar[key];
}
});
});

View File

@ -12,6 +12,17 @@ var _exportNames = {
X: true
};
var _z = _interopRequireWildcard(require("./Z"));
Object.keys(_z).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _z[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _z[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -35,14 +46,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_z).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _z[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _z[key];
}
});
});

View File

@ -26,6 +26,17 @@ var _exportNames = {
X2: true
};
var _z = _interopRequireWildcard(require("./Z"));
Object.keys(_z).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _z[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _z[key];
}
});
});
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
@ -49,14 +60,3 @@ function _interopRequireWildcard(obj) {
return newObj;
}
}
Object.keys(_z).forEach(function(key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _z[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function() {
return _z[key];
}
});
});