fix(es/transforms/cjs): Allow reassignment to exported functions (#2569)

swc_ecma_transforms_module:
 - `common_js`: Reassign exports for the functions. (#2549)
This commit is contained in:
OJ Kwon 2021-10-29 00:03:02 -07:00 committed by GitHub
parent a6af0ab30f
commit 7cc51beb45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 149 additions and 33 deletions

View File

@ -220,7 +220,7 @@ where
for ident in found.drain(..) {
scope
.exported_vars
.exported_bindings
.entry((ident.sym.clone(), ident.span.ctxt()))
.or_default()
.push((ident.sym.clone(), ident.span.ctxt()));
@ -361,14 +361,18 @@ where
let key = (orig.sym.clone(), orig.span.ctxt());
if scope.declared_vars.contains(&key) {
scope.exported_vars.entry(key.clone()).or_default().push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
scope
.exported_bindings
.entry(key.clone())
.or_default()
.push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
}
if let Some(ref src) = export.src {

View File

@ -184,9 +184,19 @@ where
_ => unreachable!(),
};
//
extra_stmts.push(ModuleItem::Stmt(Stmt::Decl(decl.fold_with(self))));
if !is_class {
let mut scope = self.scope.borrow_mut();
scope
.exported_bindings
.entry((ident.sym.clone(), ident.span.ctxt()))
.or_default()
.push((ident.sym.clone(), ident.span.ctxt()));
drop(scope);
}
let append_to: &mut Vec<_> = if is_class {
&mut extra_stmts
} else {
@ -230,7 +240,7 @@ where
for ident in found.drain(..) {
scope
.exported_vars
.exported_bindings
.entry((ident.sym.clone(), ident.span.ctxt()))
.or_default()
.push((ident.sym.clone(), ident.span.ctxt()));
@ -379,14 +389,18 @@ where
let key = orig.to_id();
if scope.declared_vars.contains(&key) {
scope.exported_vars.entry(key.clone()).or_default().push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
scope
.exported_bindings
.entry(key.clone())
.or_default()
.push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
}
if let Some(ref src) = export.src {

View File

@ -230,7 +230,7 @@ where
for ident in found.drain(..) {
scope
.exported_vars
.exported_bindings
.entry((ident.sym.clone(), ident.span.ctxt()))
.or_default()
.push((ident.sym.clone(), ident.span.ctxt()));
@ -365,14 +365,18 @@ where
let mut scope_ref_mut = self.scope.borrow_mut();
let scope = &mut *scope_ref_mut;
if scope.declared_vars.contains(&key) {
scope.exported_vars.entry(key.clone()).or_default().push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
scope
.exported_bindings
.entry(key.clone())
.or_default()
.push(
exported
.clone()
.map(|i| (i.sym.clone(), i.span.ctxt()))
.unwrap_or_else(|| {
(orig.sym.clone(), orig.span.ctxt())
}),
);
}
if let Some(ref src) = export.src {

View File

@ -121,7 +121,7 @@ pub struct Scope {
/// Declared variables except const.
pub(crate) declared_vars: Vec<Id>,
/// Maps of exported variables.
/// Maps of exported bindings.
///
///
/// e.g.
@ -130,7 +130,7 @@ pub struct Scope {
///
/// - `export { a as b }`
/// -> `{ a: [b] }`
pub(crate) exported_vars: AHashMap<Id, Vec<Id>>,
pub(crate) exported_bindings: AHashMap<Id, Vec<Id>>,
/// This is required to handle
/// `export * from 'foo';`
@ -604,7 +604,7 @@ impl Scope {
let arg = arg.ident().unwrap();
let mut scope = folder.scope_mut();
let entry = scope
.exported_vars
.exported_bindings
.entry((arg.sym.clone(), arg.span.ctxt()));
match entry {
@ -744,7 +744,7 @@ impl Scope {
let i = pat.ident().unwrap();
let mut scope = folder.scope_mut();
let entry = scope
.exported_vars
.exported_bindings
.entry((i.id.sym.clone(), i.id.span.ctxt()));
match entry {
@ -772,7 +772,7 @@ impl Scope {
.filter_map(|i| {
let mut scope = folder.scope_mut();
let entry = match scope
.exported_vars
.exported_bindings
.entry((i.sym.clone(), i.span.ctxt()))
{
Entry::Occupied(entry) => entry,

View File

@ -0,0 +1,43 @@
function log() {
console.log('unexported');
}
export function noassign() {
console.log('stub');
}
export function warn() {
throw new Error('this should not be called');
}
export const errors = {
a: 1
};
export const addOne = (x) => `${x + 1}`;
export const someFunc = (x) => `The answer is : ${addOne(x)}`;
export const test = {};
Object.defineProperty(test, 'log', {
get: function get() {
return log;
},
set: function set(v) {
log = v;
}
});
Object.defineProperty(test, 'warn', {
get: () => warn,
set: (v) => {
warn = v;
},
});
Object.defineProperty(test, 'errors', {
get: () => errors,
set: (v) => {
errors = v;
},
});

View File

@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.noassign = noassign;
exports.warn = warn;
exports.test = exports.someFunc = exports.addOne = exports.errors = void 0;
function log() {
console.log("unexported");
}
function noassign() {
console.log("stub");
}
function warn() {
throw new Error("this should not be called");
}
const errors = {
a: 1
};
exports.errors = errors;
const addOne = (x)=>`${x + 1}`
;
exports.addOne = addOne;
const someFunc = (x)=>`The answer is : ${addOne(x)}`
;
exports.someFunc = someFunc;
const test = {
};
exports.test = test;
Object.defineProperty(test, "log", {
get: function get() {
return log;
},
set: function set(v) {
log = v;
}
});
Object.defineProperty(test, "warn", {
get: ()=>warn
,
set: (v)=>{
exports.warn = warn = v;
}
});
Object.defineProperty(test, "errors", {
get: ()=>errors
,
set: (v)=>{
exports.errors = errors = v;
}
});