Skip to content

Commit

Permalink
regenerator: allow nested finally block (#601)
Browse files Browse the repository at this point in the history
Previously, 

```js
function *foo() {
    try {
    } finally {
        try {
        } finally {
             throw new Error('foo');
        }
    }
}

```

make swc panic

Closes #600.
  • Loading branch information
kdy1 committed Jan 23, 2020
1 parent ec98516 commit 20e37ea
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: Bug report
about: Create a report to help us improve
about: Use this when swc breaks something
title: ''
labels: C-bug
assignees: ''
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: Crash report
about: Create a report to help us improve
about: Use this when swc panics
title: 'panic: '
labels: C-bug
assignees: ''
Expand Down
15 changes: 15 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: Feature request
about: Use this when you want a new feature
title: ''
labels: ''
assignees: ''

---

**Describe the feature**

**Babel plugin or link to the feature description**

**Additional context**
Add any other context about the problem here.
10 changes: 10 additions & 0 deletions .github/ISSUE_TEMPLATE/question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: Question
about: Use this when you have a question
title: ''
labels: ''
assignees: ''

---

**Question**
26 changes: 18 additions & 8 deletions ecmascript/transforms/src/compat/es2015/regenerator/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ impl<'a> CaseHandler<'a> {
}

impl CaseHandler<'_> {
fn with_entry<F, Ret>(&mut self, entry: Entry, op: F) -> Ret
fn with_entry<F>(&mut self, entry: Entry, op: F)
where
F: FnOnce(&mut Self) -> Ret,
F: FnOnce(&mut Self),
{
self.leaps.push(entry);
let ret = op(self);
Expand All @@ -92,15 +92,20 @@ impl CaseHandler<'_> {
return None;
}

let mut last_loc_value = 0;
// let mut last_loc_value = 0;
Some(ArrayLit {
span: DUMMY_SP,
elems: replace(&mut self.try_entries, Default::default())
.into_iter()
.map(|entry: TryEntry| {
let this_loc_value = entry.first_loc;
assert!(this_loc_value.stmt_index >= last_loc_value);
last_loc_value = this_loc_value.stmt_index;
// let this_loc_value = entry.first_loc;
// assert!(
// this_loc_value.stmt_index >= last_loc_value,
// "this_loc_value = {:?}; last_loc_value = {};",
// this_loc_value,
// last_loc_value
// );
// last_loc_value = this_loc_value.stmt_index;

let ce = entry.catch_entry;
let fe = entry.finally_entry;
Expand Down Expand Up @@ -1091,7 +1096,7 @@ impl CaseHandler<'_> {
};

self.update_ctx_prev_loc(Some(&mut try_entry.first_loc));

// TODO: Track unmarked entries in a separate field,
self.with_entry(Entry::TryEntry(try_entry.clone()), |folder| {
//
folder.explode_stmts(block.stmts);
Expand Down Expand Up @@ -1343,7 +1348,12 @@ impl CaseHandler<'_> {
self.mark(after);
}

Stmt::Decl(_) | Stmt::ForOf(_) => self.emit(s),
Stmt::ForOf(s) => unreachable!(
"for-of statement should be removed by es2015::for_of pass\n{:?}",
s
),

Stmt::Decl(_) => self.emit(s),
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions ecmascript/transforms/src/compat/es2015/regenerator/hoist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,9 @@ impl Fold<VarDecl> for Hoister {

impl Fold<VarDeclOrExpr> for Hoister {
fn fold(&mut self, var: VarDeclOrExpr) -> VarDeclOrExpr {
let var = var.fold_children(self);

match var {
VarDeclOrExpr::VarDecl(var) => VarDeclOrExpr::Expr(box self.var_decl_to_expr(var)),
_ => var,
_ => var.fold_children(self),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions ecmascript/transforms/src/compat/es2015/regenerator/leap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ impl LeapManager {
pub fn push(&mut self, entry: Entry) {
self.stack.push(entry);
}
pub fn pop(&mut self) {
self.stack.pop();
pub fn pop(&mut self) -> Option<Entry> {
self.stack.pop()
}

pub fn find_leap_loc<F>(&self, mut pred: F, label: Option<&JsWord>) -> Option<Loc>
Expand Down
55 changes: 54 additions & 1 deletion ecmascript/transforms/tests/es2015_regenerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
use swc_common::chain;
use swc_ecma_parser::Syntax;
use swc_ecma_transforms::{
compat::es2015::regenerator, modules::common_js::common_js, pass::Pass, resolver,
compat::{es2015, es2015::regenerator, es2016, es2017, es2017::async_to_generator},
modules::common_js::common_js,
pass::Pass,
resolver,
};

#[macro_use]
Expand Down Expand Up @@ -965,3 +968,53 @@ expect(v.next()).toEqual({ value: 4, done: false });
expect(v.next()).toEqual({ done: true });
"
);

test_exec!(
syntax(),
|_| chain!(es2017(), es2016(), es2015(Default::default()),),
issue_600_full,
"async function foo(b) {
for (let a of b) {
await a
}
}"
);

test_exec!(
syntax(),
|_| chain!(
async_to_generator(),
es2015::for_of(Default::default()),
es2015::regenerator(),
),
issue_600_exact_passes,
"async function foo(b) {
for (let a of b) {
await a
}
}"
);

test_exec!(
syntax(),
|_| es2015::regenerator(),
issue_600_min,
"function* foo() {
try {
yield 1;
throw new Error('1')
} finally{
try {
yield 2;
} finally{
throw new Error('2');
}
}
}
var v = foo();
expect(v.next()).toEqual({ value: 1, done: false });
expect(v.next()).toEqual({ value: 2, done: false });
expect(() => v.next()).toThrow('2')
"
);
23 changes: 23 additions & 0 deletions ecmascript/transforms/tests/es2017_async_to_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2105,3 +2105,26 @@ async function foo() {}
"#
);

// async_to_generator_parameters
test!(
syntax(),
|_| async_to_generator(),
issue_600,
r#"
async function foo() {
for (let a of b) {
}
}
"#,
"function _foo() {
_foo = _asyncToGenerator(function*() {
for (let a of b){
}
});
return _foo.apply(this, arguments);
}
function foo() {
return _foo.apply(this, arguments);
}"
);

0 comments on commit 20e37ea

Please sign in to comment.