swc_ecma_transforms:
  - block_scoped_fn: don't fold self-modifing functions. (#288).
  - fixer: fix assignment in conditional expression (#293)
  - make resolver work with self modifying function (#292)
This commit is contained in:
강동윤 2019-02-28 23:07:31 +09:00 committed by GitHub
parent f49fbea2af
commit 21f3f792d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 168 additions and 66 deletions

View File

@ -1,3 +1,4 @@
use crate::util::UsageFinder;
use ast::*;
use swc_common::{Fold, FoldWith, Spanned, DUMMY_SP};
@ -15,20 +16,26 @@ impl Fold<Vec<Stmt>> for BlockScopedFns {
extra_stmts.push(stmt)
} else {
match stmt {
Stmt::Decl(Decl::Fn(decl)) => stmts.push(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Let,
decls: vec![VarDeclarator {
Stmt::Decl(Decl::Fn(decl)) => {
if UsageFinder::find(&decl.ident, &decl.function) {
extra_stmts.push(Stmt::Decl(Decl::Fn(decl)));
continue;
}
stmts.push(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
name: Pat::Ident(decl.ident.clone()),
init: Some(box Expr::Fn(FnExpr {
ident: Some(decl.ident),
function: decl.function,
})),
definite: false,
}],
declare: false,
}))),
kind: VarDeclKind::Let,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(decl.ident.clone()),
init: Some(box Expr::Fn(FnExpr {
ident: Some(decl.ident),
function: decl.function,
})),
definite: false,
}],
declare: false,
})))
}
_ => extra_stmts.push(stmt.fold_children(self)),
}
}
@ -109,6 +116,68 @@ function foo(scope) {
};
scope.startOperation = startOperation;
}
"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| BlockScopedFns,
issue_288_1,
"function components_Link_extends() { components_Link_extends = Object.assign || function \
(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for \
(var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { \
target[key] = source[key]; } } } return target; }; return \
components_Link_extends.apply(this, arguments); }
",
"function components_Link_extends() { components_Link_extends = Object.assign || function \
(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for \
(var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { \
target[key] = source[key]; } } } return target; }; return \
components_Link_extends.apply(this, arguments); }
"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| BlockScopedFns,
issue_288_2,
"function _extends() {
module.exports = _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
",
"function _extends() {
module.exports = _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
"
);

View File

@ -1,5 +1,6 @@
use crate::util::UsageFinder;
use ast::*;
use swc_common::{Fold, FoldWith, Visit, VisitWith};
use swc_common::{Fold, FoldWith};
#[cfg(test)]
mod tests;
@ -74,33 +75,6 @@ impl Fold<AssignExpr> for FnName {
}
}
struct UsageFinder<'a> {
ident: &'a Ident,
found: bool,
}
impl<'a> Visit<Ident> for UsageFinder<'a> {
fn visit(&mut self, i: &Ident) {
if i.span.ctxt() == self.ident.span.ctxt() && i.sym == self.ident.sym {
self.found = true;
}
}
}
impl<'a> UsageFinder<'a> {
fn find<N>(ident: &'a Ident, node: &N) -> bool
where
N: VisitWith<Self>,
{
let mut v = UsageFinder {
ident,
found: false,
};
node.visit_with(&mut v);
v.found
}
}
macro_rules! impl_for {
($T:tt) => {
impl Fold<$T> for Renamer {

View File

@ -227,31 +227,8 @@ impl<'a> Fold<VarDeclarator> for Resolver<'a> {
_ => None,
};
let is_class_like = match decl.init {
Some(box Expr::Fn(FnExpr { ref ident, .. }))
if cur_name.is_some()
&& ident.as_ref().map(|v| &v.sym) == cur_name.as_ref().map(|v| &v.0) =>
{
true
}
Some(box Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(box Expr::Fn(FnExpr { ident: None, .. })),
..
}))
| Some(box Expr::Call(CallExpr {
callee:
ExprOrSuper::Expr(box Expr::Paren(ParenExpr {
expr: box Expr::Fn(FnExpr { ident: None, .. }),
..
})),
..
})) => true,
_ => false,
};
let old_def = self.cur_defining.take();
self.cur_defining = if is_class_like { cur_name } else { None }.into();
self.cur_defining = cur_name;
let init = decl.init.fold_children(self);

View File

@ -632,3 +632,35 @@ identical!(
}
}"
);
identical!(
issue_292_1,
"var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};"
);
identical!(
issue_292_2,
"__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
__assign.apply(this, arguments);"
);

View File

@ -346,7 +346,7 @@ impl Fold<Expr> for Fixer {
Expr::Cond(expr) => {
let test = match *expr.test {
e @ Expr::Seq(..) => box e.wrap_with_paren(),
e @ Expr::Seq(..) | e @ Expr::Assign(..) => box e.wrap_with_paren(),
_ => expr.test,
};
@ -686,4 +686,16 @@ var store = global[SHARED] || (global[SHARED] = {});
copyright: '© 2018 Denis Pushkarev (zloirock.ru)'
});"
);
identical!(
issue_293_1,
"for (var e in a) a.hasOwnProperty(e) && ((b = a[e]) ? this[e] = b(c) : 'target' === e ? \
this.target = d : this[e] = c[e]);"
);
identical!(
issue_293_2,
"(a = rb ? zb(a, c) : Ab(a, c)) ? (b = nb.getPooled(ub.beforeInput, b, c, d), b.data = a, \
Ra(b)) : b = null;"
);
}

View File

@ -977,6 +977,44 @@ impl Fold<Span> for DropSpan {
}
}
/// Finds usage of `ident`
pub(crate) struct UsageFinder<'a> {
ident: &'a Ident,
found: bool,
}
impl<'a> Visit<MemberExpr> for UsageFinder<'a> {
fn visit(&mut self, e: &MemberExpr) {
e.obj.visit_with(self);
if e.computed {
e.prop.visit_with(self);
}
}
}
impl<'a> Visit<Ident> for UsageFinder<'a> {
fn visit(&mut self, i: &Ident) {
if i.span.ctxt() == self.ident.span.ctxt() && i.sym == self.ident.sym {
self.found = true;
}
}
}
impl<'a> UsageFinder<'a> {
pub(crate) fn find<N>(ident: &'a Ident, node: &N) -> bool
where
N: VisitWith<Self>,
{
let mut v = UsageFinder {
ident,
found: false,
};
node.visit_with(&mut v);
v.found
}
}
lazy_static! {
pub(crate) static ref CM: Arc<SourceMap> =
{ Arc::new(SourceMap::new(FilePathMapping::empty())) };