swc_ecma_parser:
 - add a test to ensure that \r\n is lexed correctly (#316)

swc_ecma_transforms:
 - destructuring pass now handle variable exports correctly (#317)
 - es2017::async_to_generator now handles module items. Fix #319.
 - prevent hygiene pass from de-exporting class and funcrion (#315)
This commit is contained in:
강동윤 2019-03-07 15:48:45 +09:00 committed by GitHub
parent ed100700f1
commit a311f42acf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 257 additions and 31 deletions

View File

@ -1062,6 +1062,17 @@ fn issue_299_03() {
);
}
#[test]
fn issue_316() {
assert_eq!(
lex_tokens(Default::default(), "'Hi\\r\\n..'"),
vec![Token::Str {
value: "Hi\r\n..".into(),
has_escape: true
}]
);
}
#[bench]
fn lex_colors_js(b: &mut Bencher) {
b.bytes = include_str!("../../colors.js").len() as _;

View File

@ -317,3 +317,19 @@ fn iife() {
expr("(function(){})()")
)
}
#[test]
fn issue_319_1() {
assert_eq_ignore_span!(
expr("obj(({ async f() { await g(); } }));"),
box Expr::Call(CallExpr {
span,
callee: ExprOrSuper::Expr(expr("obj")),
args: vec![ExprOrSpread {
spread: None,
expr: expr("({ async f() { await g(); } })"),
}],
type_args: Default::default(),
})
);
}

View File

@ -827,6 +827,15 @@ mod tests {
})
})
}
fn module_item(s: &'static str) -> ModuleItem {
test_parser(s, Syntax::default(), |p| {
p.parse_stmt_like(true, true).map_err(|mut e| {
e.emit();
()
})
})
}
fn expr(s: &'static str) -> Box<Expr> {
test_parser(s, Syntax::default(), |p| {
p.parse_expr().map_err(|mut e| {
@ -1226,4 +1235,16 @@ export default function waitUntil(callback, options = {}) {
},
);
}
#[test]
fn issue_319_2() {
module_item(
"export default obj({
async f() {
await g();
}
});",
);
}
}

View File

@ -271,9 +271,9 @@ fn is_complex(props: &[PropOrSpread]) -> bool {
visitor.found
}
impl<T: StmtLike + VisitWith<ShouldWork>> Fold<Vec<T>> for ComputedProps
impl<T> Fold<Vec<T>> for ComputedProps
where
T: FoldWith<Self> + FoldWith<ObjectLitFolder>,
T: StmtLike + VisitWith<ShouldWork> + FoldWith<Self> + FoldWith<ObjectLitFolder>,
{
fn fold(&mut self, stmts: Vec<T>) -> Vec<T> {
// Fast path when there's no computed properties.
@ -281,11 +281,15 @@ where
return stmts;
}
let stmts = stmts.fold_children(self);
// let stmts = stmts.fold_children(self);
let mut buf = Vec::with_capacity(stmts.len());
for stmt in stmts {
if !contains_computed_expr(&stmt) {
buf.push(stmt);
continue;
}
let mut folder = ObjectLitFolder::default();
let stmt = stmt.fold_with(&mut folder);

View File

@ -203,3 +203,107 @@ test!(
};"#,
r#"var foo = _defineProperty({}, bar, "foobar");"#
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| ComputedProps,
issue_315_1,
"
({
foo: {
bar: null,
[baz]: null
},
[bon]: {
flab: null
}
});
export function corge() {}
",
"
var _obj, _obj1;
_obj1 = {
}, _defineProperty(_obj1, 'foo', (_obj = {
}, _defineProperty(_obj, 'bar', null), _defineProperty(_obj, baz, null), _obj)), \
_defineProperty(_obj1, bon, {
flab: null
}), _obj1;
export function corge() {}
"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| ComputedProps,
issue_315_2,
"
export function corge() {}
",
"
export function corge() {}
"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| ComputedProps,
issue_315_3,
"
export function corge() {}
({
foo: {
bar: null,
[baz]: null
},
[bon]: {
flab: null
}
});
",
"
export function corge() {}
var _obj, _obj1;
_obj1 = {
}, _defineProperty(_obj1, 'foo', (_obj = {
}, _defineProperty(_obj, 'bar', null), _defineProperty(_obj, baz, null), _obj)), \
_defineProperty(_obj1, bon, {
flab: null
}), _obj1;
"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| ComputedProps,
issue_315_4,
"
export class Foo {}
({
foo: {
bar: null,
[baz]: null
},
[bon]: {
flab: null
}
});
",
"
export class Foo {}
var _obj, _obj1;
_obj1 = {
}, _defineProperty(_obj1, 'foo', (_obj = {
}, _defineProperty(_obj, 'bar', null), _defineProperty(_obj, baz, null), _obj)), \
_defineProperty(_obj1, bon, {
flab: null
}), _obj1;
"
);

View File

@ -117,7 +117,7 @@ fn make_ref_ident_for_for_stmt() -> Ident {
private_ident!("ref")
}
impl Fold<Vec<VarDeclarator>> for Destructuring {
impl Fold<Vec<VarDeclarator>> for AssignFolder {
fn fold(&mut self, declarators: Vec<VarDeclarator>) -> Vec<VarDeclarator> {
let declarators = declarators.fold_children(self);
@ -140,7 +140,14 @@ impl Fold<Vec<VarDeclarator>> for Destructuring {
);
// Make ref var if required
let ref_ident = make_ref_ident(&mut decls, decl.init);
let ref_ident = make_ref_ident(
if self.exporting {
&mut self.vars
} else {
&mut decls
},
decl.init,
);
for (i, elem) in elems.into_iter().enumerate() {
let elem: Pat = match elem {
@ -381,9 +388,20 @@ impl Destructuring {
#[derive(Default)]
struct AssignFolder {
exporting: bool,
vars: Vec<VarDeclarator>,
}
impl Fold<ExportDecl> for AssignFolder {
fn fold(&mut self, decl: ExportDecl) -> ExportDecl {
let old = self.exporting;
self.exporting = true;
let decl = decl.fold_children(self);
self.exporting = old;
decl
}
}
impl Fold<Expr> for AssignFolder {
fn fold(&mut self, expr: Expr) -> Expr {
let expr = match expr {

View File

@ -513,3 +513,25 @@ const ref = bar ? bar : _throw(new TypeError(\"Cannot destructure 'undefined' or
_ref$Foo = ref[Foo], ref1 = _ref$Foo ? _ref$Foo : _throw(new TypeError(\"Cannot destructure \
'undefined' or 'null'\")), qux = ref1.qux;"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
issue_317,
"export const [
A,
B,
C
] = [1,2,3];
export const [
E,
D,
F
] = [4,5,6];",
"
var ref = [1, 2, 3];
export const A = ref[0], B = ref[1], C = ref[2];
var ref1 = [4, 5, 6];
export const E = ref[0], D = ref[1], F = ref[2];"
);

View File

@ -39,8 +39,9 @@ struct Actual {
extra_stmts: Vec<Stmt>,
}
impl<T: StmtLike + VisitWith<AsyncVisitor>> Fold<Vec<T>> for AsyncToGenerator
impl<T> Fold<Vec<T>> for AsyncToGenerator
where
T: StmtLike + VisitWith<AsyncVisitor> + FoldWith<Actual>,
Vec<T>: FoldWith<Self>,
{
fn fold(&mut self, stmts: Vec<T>) -> Vec<T> {
@ -53,18 +54,18 @@ where
let mut buf = Vec::with_capacity(stmts.len());
for stmt in stmts {
match stmt.try_into_stmt() {
Err(module_item) => buf.push(module_item),
Ok(stmt) => {
let mut actual = Actual {
extra_stmts: vec![],
};
let stmt = stmt.fold_with(&mut actual);
buf.extend(actual.extra_stmts.into_iter().map(T::from_stmt));
buf.push(T::from_stmt(stmt));
}
if !contains_async(&stmt) {
buf.push(stmt);
continue;
}
let mut actual = Actual {
extra_stmts: vec![],
};
let stmt = stmt.fold_with(&mut actual);
buf.extend(actual.extra_stmts.into_iter().map(T::from_stmt));
buf.push(stmt);
}
buf
@ -74,6 +75,7 @@ where
impl Fold<MethodProp> for Actual {
fn fold(&mut self, prop: MethodProp) -> MethodProp {
let prop = prop.fold_children(self);
if !prop.function.is_async {
return prop;
}
@ -592,7 +594,8 @@ fn make_fn_ref(mut expr: FnExpr) -> Expr {
}
};
}
noop!(Function);
noop!(FnDecl);
noop!(FnExpr);
noop!(Constructor);
noop!(ArrowExpr);

View File

@ -696,3 +696,22 @@ function foo() {
}
"#
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
issue_319,
"export default obj({
async f() {
await g();
}
});",
"export default obj({
f () {
return _asyncToGenerator(function*() {
yield g();
})();
}
});
"
);

View File

@ -37,13 +37,13 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
match item {
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span,
decl:
Decl::Class(ClassDecl {
ident,
class,
declare,
}),
..
})) => {
let orig_ident = ident.clone();
match self.rename_ident(ident) {
@ -56,22 +56,25 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
export!(orig_ident, ident);
}
Err(ident) => {
stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
ident,
class,
declare,
}))))
stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span,
decl: Decl::Class(ClassDecl {
ident,
class,
declare,
}),
})))
}
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span,
decl:
Decl::Fn(FnDecl {
ident,
function,
declare,
}),
..
})) => {
let orig_ident = ident.clone();
match self.rename_ident(ident) {
@ -83,11 +86,16 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
}))));
export!(orig_ident, ident);
}
Err(ident) => stmts.push(ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
ident,
function,
declare,
})))),
Err(ident) => {
stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span,
decl: Decl::Fn(FnDecl {
ident,
function,
declare,
}),
})))
}
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {