mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
parent
f0e4598f41
commit
145d6f39eb
14
README.md
14
README.md
@ -45,7 +45,7 @@ New generation javascript to old-days javascript.
|
||||
- [x] computed-properties
|
||||
- [x] destructuring
|
||||
- [x] duplicate-keys
|
||||
- [ ] for-of
|
||||
- [x] for-of
|
||||
- [x] function-name
|
||||
- [x] instanceof
|
||||
- [x] literals
|
||||
@ -77,11 +77,13 @@ New generation javascript to old-days javascript.
|
||||
|
||||
The benchmarks were run on Macbook pro, dual core, 2.3GHz Intel Core i5, 16 GB ram
|
||||
|
||||
| | performance |
|
||||
| --------------------- |:--------------------------------------:|
|
||||
| swc (ffi) | 1,086 ops/sec ±0.77% (84 runs sampled) |
|
||||
| swc-optimize (ffi) | 1,060 ops/sec ±0.63% (87 runs sampled) |
|
||||
| babel | 65.72 ops/sec ±6.45% (62 runs sampled) |
|
||||
| | performance |
|
||||
| ------------------------ |:--------------------------------------:|
|
||||
| swc (ffi) | 1,086 ops/sec ±0.77% (84 runs sampled) |
|
||||
| swc-optimize (ffi) | 1,060 ops/sec ±0.63% (87 runs sampled) |
|
||||
| swc (ffi, simd) | 1,295 ops/sec ±0.87% (89 runs sampled) |
|
||||
| swc-optimize (ffi, simd) | 1,270 ops/sec ±0.24% (89 runs sampled) |
|
||||
| babel | 65.72 ops/sec ±6.45% (62 runs sampled) |
|
||||
|
||||
|
||||
## Contributing
|
||||
|
432
ecmascript/transforms/src/compat/es2015/for_of/mod.rs
Normal file
432
ecmascript/transforms/src/compat/es2015/for_of/mod.rs
Normal file
@ -0,0 +1,432 @@
|
||||
use crate::util::{ExprFactory, StmtLike};
|
||||
use ast::*;
|
||||
use swc_common::{Fold, FoldWith, Mark, Spanned, DUMMY_SP};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// `@babel/plugin-transform-for-of`
|
||||
///
|
||||
/// ## In
|
||||
///
|
||||
/// ```js
|
||||
/// for (var i of foo) {}
|
||||
/// ```
|
||||
///
|
||||
/// ## Out
|
||||
///
|
||||
/// ```js
|
||||
/// var _iteratorNormalCompletion = true;
|
||||
/// var _didIteratorError = false;
|
||||
/// var _iteratorError = undefined;
|
||||
///
|
||||
/// try {
|
||||
/// for (var _iterator = foo[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
/// var i = _step.value;
|
||||
/// }
|
||||
/// } catch (err) {
|
||||
/// _didIteratorError = true;
|
||||
/// _iteratorError = err;
|
||||
/// } finally {
|
||||
/// try {
|
||||
/// if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
/// _iterator.return();
|
||||
/// }
|
||||
/// } finally {
|
||||
/// if (_didIteratorError) {
|
||||
/// throw _iteratorError;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn for_of() -> impl Fold<Module> {
|
||||
ForOf
|
||||
}
|
||||
|
||||
struct ForOf;
|
||||
|
||||
/// Real folder.
|
||||
#[derive(Default)]
|
||||
struct Actual {
|
||||
///```js
|
||||
/// var _iteratorNormalCompletion = true;
|
||||
/// var _didIteratorError = false;
|
||||
/// var _iteratorError = undefined;
|
||||
/// ```
|
||||
top_level_vars: Vec<VarDeclarator>,
|
||||
}
|
||||
|
||||
impl Actual {
|
||||
fn fold_for_stmt(
|
||||
&mut self,
|
||||
label: Option<Ident>,
|
||||
ForOfStmt {
|
||||
span,
|
||||
await_token,
|
||||
left,
|
||||
right,
|
||||
body,
|
||||
}: ForOfStmt,
|
||||
) -> Stmt {
|
||||
assert!(await_token.is_none());
|
||||
let var_span = left.span().apply_mark(Mark::fresh(Mark::root()));
|
||||
// TODO(kdy): convert to normal for loop if rhs is array
|
||||
// TODO(kdy): Type annotation to determine if rhs is array
|
||||
|
||||
let mut body = match *body {
|
||||
Stmt::Block(block) => block,
|
||||
body => BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![body],
|
||||
},
|
||||
};
|
||||
|
||||
let step = quote_ident!(var_span, "_step");
|
||||
let step_value = box Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr(box Expr::Ident(step.clone())),
|
||||
computed: false,
|
||||
prop: box Expr::Ident(quote_ident!("value")),
|
||||
});
|
||||
body.stmts.insert(
|
||||
0,
|
||||
match left {
|
||||
VarDeclOrPat::VarDecl(mut var) => {
|
||||
assert!(var.decls.len() == 1);
|
||||
Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: var.span,
|
||||
kind: var.kind,
|
||||
decls: vec![VarDeclarator {
|
||||
init: Some(step_value),
|
||||
..var.decls.pop().unwrap()
|
||||
}],
|
||||
}))
|
||||
}
|
||||
VarDeclOrPat::Pat(pat) => Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box pat),
|
||||
op: op!("="),
|
||||
right: step_value,
|
||||
})),
|
||||
},
|
||||
);
|
||||
|
||||
let iterator = quote_ident!(var_span, "_iterator");
|
||||
// `_iterator.return`
|
||||
let iterator_return = box Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr(box Expr::Ident(iterator.clone())),
|
||||
computed: false,
|
||||
prop: box Expr::Ident(quote_ident!("return")),
|
||||
});
|
||||
|
||||
let normal_completion_ident = Ident::new("_iteratorNormalCompletion".into(), var_span);
|
||||
self.top_level_vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(normal_completion_ident.clone()),
|
||||
init: Some(box Expr::Lit(Lit::Bool(Bool {
|
||||
span: DUMMY_SP,
|
||||
value: true,
|
||||
}))),
|
||||
});
|
||||
let error_flag_ident = Ident::new("_didIteratorError".into(), var_span);
|
||||
self.top_level_vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(error_flag_ident.clone()),
|
||||
init: Some(box Expr::Lit(Lit::Bool(Bool {
|
||||
span: DUMMY_SP,
|
||||
value: false,
|
||||
}))),
|
||||
});
|
||||
let error_ident = Ident::new("_iteratorError".into(), var_span);
|
||||
self.top_level_vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(error_ident.clone()),
|
||||
init: Some(box Expr::Ident(Ident::new(js_word!("undefined"), DUMMY_SP))),
|
||||
});
|
||||
|
||||
let for_stmt = ForStmt {
|
||||
span,
|
||||
init: Some(VarDeclOrExpr::VarDecl(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![
|
||||
VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(iterator.clone()),
|
||||
init: Some(box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr(right),
|
||||
computed: true,
|
||||
prop: member_expr!(DUMMY_SP, Symbol.iterator),
|
||||
}
|
||||
.as_callee(),
|
||||
args: vec![],
|
||||
})),
|
||||
},
|
||||
VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(step.clone()),
|
||||
init: None,
|
||||
},
|
||||
],
|
||||
})),
|
||||
// !(_iteratorNormalCompletion = (_step = _iterator.next()).done)
|
||||
test: Some(box Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("!"),
|
||||
arg: box Expr::Paren(ParenExpr {
|
||||
span: DUMMY_SP,
|
||||
expr: box Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(normal_completion_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Paren(ParenExpr {
|
||||
span: DUMMY_SP,
|
||||
expr: box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(step.clone())),
|
||||
op: op!("="),
|
||||
// `_iterator.next()`
|
||||
right: box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
// `_iterator.next`
|
||||
callee: MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
computed: false,
|
||||
obj: ExprOrSuper::Expr(box Expr::Ident(
|
||||
iterator.clone(),
|
||||
)),
|
||||
prop: member_expr!(DUMMY_SP, next),
|
||||
}
|
||||
.as_callee(),
|
||||
args: vec![],
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})),
|
||||
computed: false,
|
||||
prop: box Expr::Ident(quote_ident!("done")),
|
||||
}),
|
||||
}),
|
||||
})),
|
||||
|
||||
// `_iteratorNormalCompletion = true`
|
||||
update: Some(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(normal_completion_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Lit(Lit::Bool(Bool {
|
||||
span: DUMMY_SP,
|
||||
value: true,
|
||||
})),
|
||||
})),
|
||||
body: box Stmt::Block(body),
|
||||
}
|
||||
.into();
|
||||
|
||||
let for_stmt = match label {
|
||||
Some(label) => Stmt::Labeled(LabeledStmt {
|
||||
span,
|
||||
label,
|
||||
body: box for_stmt,
|
||||
}),
|
||||
None => for_stmt,
|
||||
};
|
||||
|
||||
Stmt::Try(TryStmt {
|
||||
span: DUMMY_SP,
|
||||
block: BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![for_stmt],
|
||||
},
|
||||
handler: Some(CatchClause {
|
||||
span: DUMMY_SP,
|
||||
param: Some(Pat::Ident(quote_ident!("err"))),
|
||||
// _didIteratorError = true;
|
||||
// _iteratorError = err;
|
||||
body: BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![
|
||||
// _didIteratorError = true;
|
||||
Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(error_flag_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Lit(Lit::Bool(Bool {
|
||||
span: DUMMY_SP,
|
||||
value: true,
|
||||
})),
|
||||
})),
|
||||
// _iteratorError = err;
|
||||
Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(error_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Ident(quote_ident!("err")),
|
||||
})),
|
||||
],
|
||||
},
|
||||
}),
|
||||
finalizer: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![make_finally_block(
|
||||
iterator_return,
|
||||
&normal_completion_ident,
|
||||
error_flag_ident,
|
||||
error_ident,
|
||||
)],
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Stmt> for Actual {
|
||||
fn fold(&mut self, stmt: Stmt) -> Stmt {
|
||||
match stmt {
|
||||
Stmt::Labeled(LabeledStmt { span, label, body }) => {
|
||||
// Handle label
|
||||
match *body {
|
||||
Stmt::ForOf(
|
||||
stmt @ ForOfStmt {
|
||||
await_token: None, ..
|
||||
},
|
||||
) => self.fold_for_stmt(Some(label), stmt),
|
||||
_ => {
|
||||
return Stmt::Labeled(LabeledStmt {
|
||||
span,
|
||||
label,
|
||||
body: body.fold_children(self),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::ForOf(
|
||||
stmt @ ForOfStmt {
|
||||
await_token: None, ..
|
||||
},
|
||||
) => self.fold_for_stmt(None, stmt),
|
||||
_ => stmt.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ```js
|
||||
///
|
||||
/// try {
|
||||
/// if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
/// _iterator.return();
|
||||
/// }
|
||||
/// } finally {
|
||||
/// if (_didIteratorError) {
|
||||
/// throw _iteratorError;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn make_finally_block(
|
||||
iterator_return: Box<Expr>,
|
||||
normal_completion_ident: &Ident,
|
||||
error_flag_ident: Ident,
|
||||
error_ident: Ident,
|
||||
) -> Stmt {
|
||||
Stmt::Try(TryStmt {
|
||||
span: DUMMY_SP,
|
||||
block: BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![
|
||||
// if (!_iteratorNormalCompletion && _iterator.return !=
|
||||
// null) {
|
||||
// _iterator.return();
|
||||
// }
|
||||
Stmt::If(IfStmt {
|
||||
span: DUMMY_SP,
|
||||
test: box Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: box Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("!"),
|
||||
arg: box Expr::Ident(normal_completion_ident.clone()),
|
||||
}),
|
||||
op: op!("&&"),
|
||||
right: box Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left: iterator_return.clone(),
|
||||
op: op!("!="),
|
||||
right: box Expr::Lit(Lit::Null(Null { span: DUMMY_SP })),
|
||||
}),
|
||||
}),
|
||||
cons: box Stmt::Block(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Stmt::Expr(box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: iterator_return.as_callee(),
|
||||
args: vec![],
|
||||
}))],
|
||||
}),
|
||||
alt: None,
|
||||
}),
|
||||
],
|
||||
},
|
||||
handler: None,
|
||||
finalizer: Some(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
|
||||
stmts: vec![
|
||||
// if (_didIteratorError) {
|
||||
// throw _iteratorError;
|
||||
// }
|
||||
Stmt::If(IfStmt {
|
||||
span: DUMMY_SP,
|
||||
test: box Expr::Ident(error_flag_ident),
|
||||
cons: box Stmt::Block(BlockStmt {
|
||||
span: DUMMY_SP,
|
||||
stmts: vec![Stmt::Throw(ThrowStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: box Expr::Ident(error_ident),
|
||||
})],
|
||||
}),
|
||||
alt: None,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
impl<T: StmtLike> Fold<Vec<T>> for ForOf
|
||||
where
|
||||
Vec<T>: FoldWith<Self>,
|
||||
{
|
||||
fn fold(&mut self, stmts: Vec<T>) -> Vec<T> {
|
||||
let stmts = stmts.fold_children(self);
|
||||
|
||||
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 folder = Actual::default();
|
||||
let stmt = stmt.fold_with(&mut folder);
|
||||
|
||||
// Add variable declaration
|
||||
// e.g. var ref
|
||||
if !folder.top_level_vars.is_empty() {
|
||||
buf.push(T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
decls: folder.top_level_vars,
|
||||
}))));
|
||||
}
|
||||
|
||||
buf.push(T::from_stmt(stmt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
}
|
226
ecmascript/transforms/src/compat/es2015/for_of/tests.rs
Normal file
226
ecmascript/transforms/src/compat/es2015/for_of/tests.rs
Normal file
@ -0,0 +1,226 @@
|
||||
use super::*;
|
||||
|
||||
test!(
|
||||
ForOf,
|
||||
spec_identifier,
|
||||
r#"for (i of arr) {
|
||||
}"#,
|
||||
r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
i = _step.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#,ok_if_code_eq
|
||||
);
|
||||
|
||||
test!(ForOf, spec_ignore_cases, r#"for (var i of foo) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
}"#, r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = foo[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var i = _step.value;
|
||||
|
||||
switch (i) {
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#, ok_if_code_eq);
|
||||
|
||||
test!(ForOf, spec_let, r#"for (let i of arr) {
|
||||
|
||||
}"#, r#"
|
||||
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
let i = _step.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
ok_if_code_eq);
|
||||
|
||||
test!(ForOf, spec_member_expr, r#"for (obj.prop of arr) {
|
||||
|
||||
}"#, r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
obj.prop = _step.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
ok_if_code_eq);
|
||||
|
||||
test!(ForOf, spec_multiple, r#"for (var i of arr) {
|
||||
|
||||
}
|
||||
|
||||
for (var i of numbers) {
|
||||
|
||||
}
|
||||
"#, r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var i = _step.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator1 = numbers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
|
||||
var i = _step1.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError1 = true;
|
||||
_iteratorError1 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
||||
_iterator1.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError1) {
|
||||
throw _iteratorError1;
|
||||
}
|
||||
}
|
||||
}"#, ok_if_code_eq);
|
||||
|
||||
test!(ForOf, spec_nested_label_for_of, r#"b: for (let c of d()) {
|
||||
for (let e of f()) {
|
||||
continue b;
|
||||
}
|
||||
}"#, r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
b: for (var _iterator = d()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
let c = _step.value;
|
||||
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator1 = f()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
|
||||
let e = _step1.value;
|
||||
continue b;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError1 = true;
|
||||
_iteratorError1 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
||||
_iterator1.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError1) {
|
||||
throw _iteratorError1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#, ok_if_code_eq);
|
||||
|
||||
test!(ForOf, spec_var, r#"for (var i of arr) {
|
||||
|
||||
}"#, r#"var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var i = _step.value;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}"#, ok_if_code_eq);
|
@ -1,8 +1,8 @@
|
||||
pub use self::{
|
||||
arrow::arrow, block_scoped_fn::BlockScopedFns, block_scoping::block_scoping, classes::Classes,
|
||||
computed_props::computed_properties, destructuring::destructuring,
|
||||
duplicate_keys::duplicate_keys, function_name::function_name, instanceof::InstanceOf,
|
||||
parameters::parameters, shorthand_property::Shorthand, spread::Spread,
|
||||
duplicate_keys::duplicate_keys, for_of::for_of, function_name::function_name,
|
||||
instanceof::InstanceOf, parameters::parameters, shorthand_property::Shorthand, spread::Spread,
|
||||
sticky_regex::StickyRegex, template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol,
|
||||
};
|
||||
use super::helpers::Helpers;
|
||||
@ -17,6 +17,7 @@ mod classes;
|
||||
mod computed_props;
|
||||
mod destructuring;
|
||||
mod duplicate_keys;
|
||||
mod for_of;
|
||||
mod function_name;
|
||||
mod instanceof;
|
||||
mod parameters;
|
||||
@ -66,6 +67,7 @@ pub fn es2015(helpers: &Arc<Helpers>) -> impl Fold<Module> {
|
||||
chain_at!(
|
||||
Module,
|
||||
stmts(helpers),
|
||||
for_of(),
|
||||
computed_properties(helpers.clone()),
|
||||
destructuring(helpers.clone()),
|
||||
block_scoping(),
|
||||
|
@ -283,4 +283,62 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_loop() {
|
||||
test(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(mark1);
|
||||
let mark3 = Mark::fresh(mark1);
|
||||
|
||||
Ok(vec![
|
||||
tester
|
||||
.parse_stmt("actual1.js", "for(var a=1;;) {}")?
|
||||
.fold_with(&mut marker(&[("a", mark1)])),
|
||||
tester
|
||||
.parse_stmt("actual2.js", "for(var a of foo) {}")?
|
||||
.fold_with(&mut marker(&[("a", mark2)])),
|
||||
tester
|
||||
.parse_stmt("actual3.js", "for(var a=3;;) {}")?
|
||||
.fold_with(&mut marker(&[("a", mark3)])),
|
||||
])
|
||||
},
|
||||
"
|
||||
for(var a=1;;) {}
|
||||
for(var a1 of foo) {}
|
||||
for(var a2 = 3;;) {}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_for_loop() {
|
||||
test(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(mark1);
|
||||
let mark3 = Mark::fresh(mark1);
|
||||
|
||||
Ok(vec![
|
||||
tester
|
||||
.parse_stmt("actual1.js", "try { for(var a=1;;) {} } finally {}")?
|
||||
.fold_with(&mut marker(&[("a", mark1)])),
|
||||
tester
|
||||
.parse_stmt("actual2.js", "for(var a of foo) {}")?
|
||||
.fold_with(&mut marker(&[("a", mark2)])),
|
||||
tester
|
||||
.parse_stmt("actual3.js", "for(var a=3;;) {}")?
|
||||
.fold_with(&mut marker(&[("a", mark3)])),
|
||||
])
|
||||
},
|
||||
"
|
||||
try {
|
||||
for(var a=1;;) {}
|
||||
} finally {
|
||||
}
|
||||
for(var a1 of foo) {}
|
||||
for(var a2 = 3;;) {}
|
||||
",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +148,17 @@ impl<'a, 'b, T: Traverse> Fold<Module> for ScopeAnalyzer<'a, 'b, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: Traverse> Fold<TryStmt> for ScopeAnalyzer<'a, 'b, T> {
|
||||
fn fold(&mut self, node: TryStmt) -> TryStmt {
|
||||
TryStmt {
|
||||
span: node.span,
|
||||
block: node.block.fold_children(self),
|
||||
handler: node.handler.fold_with(self),
|
||||
finalizer: node.finalizer.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: Traverse> Fold<BlockStmt> for ScopeAnalyzer<'a, 'b, T> {
|
||||
fn fold(&mut self, node: BlockStmt) -> BlockStmt {
|
||||
let node = {
|
||||
|
Loading…
Reference in New Issue
Block a user