mirror of
https://github.com/swc-project/swc.git
synced 2024-12-24 14:16:12 +03:00
parent
f0e4598f41
commit
145d6f39eb
@ -45,7 +45,7 @@ New generation javascript to old-days javascript.
|
|||||||
- [x] computed-properties
|
- [x] computed-properties
|
||||||
- [x] destructuring
|
- [x] destructuring
|
||||||
- [x] duplicate-keys
|
- [x] duplicate-keys
|
||||||
- [ ] for-of
|
- [x] for-of
|
||||||
- [x] function-name
|
- [x] function-name
|
||||||
- [x] instanceof
|
- [x] instanceof
|
||||||
- [x] literals
|
- [x] literals
|
||||||
@ -78,9 +78,11 @@ New generation javascript to old-days javascript.
|
|||||||
The benchmarks were run on Macbook pro, dual core, 2.3GHz Intel Core i5, 16 GB ram
|
The benchmarks were run on Macbook pro, dual core, 2.3GHz Intel Core i5, 16 GB ram
|
||||||
|
|
||||||
| | performance |
|
| | performance |
|
||||||
| --------------------- |:--------------------------------------:|
|
| ------------------------ |:--------------------------------------:|
|
||||||
| swc (ffi) | 1,086 ops/sec ±0.77% (84 runs sampled) |
|
| swc (ffi) | 1,086 ops/sec ±0.77% (84 runs sampled) |
|
||||||
| swc-optimize (ffi) | 1,060 ops/sec ±0.63% (87 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) |
|
| babel | 65.72 ops/sec ±6.45% (62 runs sampled) |
|
||||||
|
|
||||||
|
|
||||||
|
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::{
|
pub use self::{
|
||||||
arrow::arrow, block_scoped_fn::BlockScopedFns, block_scoping::block_scoping, classes::Classes,
|
arrow::arrow, block_scoped_fn::BlockScopedFns, block_scoping::block_scoping, classes::Classes,
|
||||||
computed_props::computed_properties, destructuring::destructuring,
|
computed_props::computed_properties, destructuring::destructuring,
|
||||||
duplicate_keys::duplicate_keys, function_name::function_name, instanceof::InstanceOf,
|
duplicate_keys::duplicate_keys, for_of::for_of, function_name::function_name,
|
||||||
parameters::parameters, shorthand_property::Shorthand, spread::Spread,
|
instanceof::InstanceOf, parameters::parameters, shorthand_property::Shorthand, spread::Spread,
|
||||||
sticky_regex::StickyRegex, template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol,
|
sticky_regex::StickyRegex, template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol,
|
||||||
};
|
};
|
||||||
use super::helpers::Helpers;
|
use super::helpers::Helpers;
|
||||||
@ -17,6 +17,7 @@ mod classes;
|
|||||||
mod computed_props;
|
mod computed_props;
|
||||||
mod destructuring;
|
mod destructuring;
|
||||||
mod duplicate_keys;
|
mod duplicate_keys;
|
||||||
|
mod for_of;
|
||||||
mod function_name;
|
mod function_name;
|
||||||
mod instanceof;
|
mod instanceof;
|
||||||
mod parameters;
|
mod parameters;
|
||||||
@ -66,6 +67,7 @@ pub fn es2015(helpers: &Arc<Helpers>) -> impl Fold<Module> {
|
|||||||
chain_at!(
|
chain_at!(
|
||||||
Module,
|
Module,
|
||||||
stmts(helpers),
|
stmts(helpers),
|
||||||
|
for_of(),
|
||||||
computed_properties(helpers.clone()),
|
computed_properties(helpers.clone()),
|
||||||
destructuring(helpers.clone()),
|
destructuring(helpers.clone()),
|
||||||
block_scoping(),
|
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> {
|
impl<'a, 'b, T: Traverse> Fold<BlockStmt> for ScopeAnalyzer<'a, 'b, T> {
|
||||||
fn fold(&mut self, node: BlockStmt) -> BlockStmt {
|
fn fold(&mut self, node: BlockStmt) -> BlockStmt {
|
||||||
let node = {
|
let node = {
|
||||||
|
Loading…
Reference in New Issue
Block a user