diff --git a/func.go b/func.go index a7866ae4..0b563c8f 100644 --- a/func.go +++ b/func.go @@ -702,12 +702,16 @@ func (g *generator) step() (res Value, resultType resultType, ex *Exception) { return } -func (g *generator) next(v Value) (Value, resultType, *Exception) { +func (g *generator) enterNext() { g.vm.pushCtx() g.vm.pushTryFrame(tryPanicMarker, -1) g.vm.callStack = append(g.vm.callStack, context{pc: -2}) // extra frame so that vm.run() halts after ret g.storeLengths() g.vm.resume(&g.ctx) +} + +func (g *generator) next(v Value) (Value, resultType, *Exception) { + g.enterNext() if v != nil { g.vm.push(v) } @@ -718,8 +722,7 @@ func (g *generator) next(v Value) (Value, resultType, *Exception) { } func (g *generator) nextThrow(v Value) (Value, resultType, *Exception) { - g.enter() - g.vm.resume(&g.ctx) + g.enterNext() ex := g.vm.handleThrow(v) if ex != nil { g.vm.popTryFrame() diff --git a/parser/expression.go b/parser/expression.go index 9adb26c0..82afbf93 100644 --- a/parser/expression.go +++ b/parser/expression.go @@ -1270,9 +1270,7 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { self.scope.allowAwait = false }() } - if c, ok := left.(*ast.CallExpression); ok && len(self.errors) == 0 { - paramList = self.reinterpretSequenceAsArrowFuncParams(c.ArgumentList) - } else { + if _, ok := left.(*ast.CallExpression); ok { self.restore(&state) self.next() // skip "async" paramList = self.parseFunctionParameterList() diff --git a/runtime_test.go b/runtime_test.go index 425d857f..017acfd7 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -2522,6 +2522,43 @@ func TestPanicPassthrough(t *testing.T) { t.Fatal("Should not reach here") } +func TestSuspendResumeRelStackLen(t *testing.T) { + const SCRIPT = ` + let result; + + async function f2() { + throw new Error("test"); + } + + async function f1() { + let a = [1]; + for (let i of a) { + try { + await f2(); + } catch { + return true; + } + } + } + + async function f() { + let a = [1]; + for (let i of a) { + return await f1(); + } + } + f().then(v => {result = v}); + ` + vm := New() + _, err := vm.RunString(SCRIPT) + if err != nil { + t.Fatal(err) + } + if result := vm.Get("result").Export(); result != true { + t.Fatal(result) + } +} + /* func TestArrayConcatSparse(t *testing.T) { function foo(a,b,c) diff --git a/tc39_test.go b/tc39_test.go index 49151f38..312cf52b 100644 --- a/tc39_test.go +++ b/tc39_test.go @@ -158,7 +158,6 @@ var ( "test/language/statements/class/elements/private-generator-method-name.js": true, "test/language/expressions/in/private-field-rhs-yield-present.js": true, "test/language/expressions/class/elements/private-static-generator-method-name.js": true, - "test/language/expressions/class/elements/private-static-async-generator-method-name.js": true, "test/language/computed-property-names/class/static/generator-prototype.js": true, "test/language/computed-property-names/class/method/constructor-can-be-generator.js": true, "test/language/computed-property-names/class/static/generator-constructor.js": true, @@ -188,6 +187,7 @@ var ( "test/language/expressions/object/method-definition/static-init-await-binding-generator.js": true, "test/language/expressions/class/elements/private-async-generator-method-name.js": true, "test/language/comments/hashbang/function-constructor.js": true, + "test/language/expressions/async-generator/name.js": true, // async iterator "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js": true, @@ -273,31 +273,35 @@ func init() { "test/language/identifiers/start-unicode-14.", "test/language/identifiers/part-unicode-14.", - // async - "test/language/eval-code/direct/async-", - "test/language/expressions/async-", - "test/language/expressions/await/", - "test/language/statements/async-function/", + // generators and async generators (harness/hidden-constructors.js) "test/built-ins/Async", - "test/language/statements/class/elements/private-static-async-", - "test/language/statements/class/elements/wrapped-in-sc-rs-static-async-", - "test/language/expressions/class/elements/wrapped-in-sc-rs-static-async-", - "test/language/statements/class/elements/after-same-line-static-method-rs-static-async-", - "test/language/expressions/class/elements/after-same-line-static-method-rs-static-async-", - "test/language/statements/class/elements/after-same-line-method-rs-static-async-", - "test/language/expressions/class/elements/after-same-line-method-rs-static-async-", - "test/language/statements/class/elements/new-sc-line-method-rs-static-async-", - "test/language/expressions/class/elements/new-sc-line-method-rs-static-async-", - "test/language/statements/class/elements/new-no-sc-line-method-rs-static-async-", - "test/language/expressions/class/elements/new-no-sc-line-method-rs-static-async-", - "test/language/statements/class/elements/same-line-method-rs-static-async-", - "test/language/expressions/class/elements/same-line-method-rs-static-async-", - "test/language/statements/class/elements/regular-definitions-rs-static-async-", - "test/language/expressions/class/elements/regular-definitions-rs-static-async-", - "test/language/statements/class/elements/multiple-stacked-definitions-rs-static-async-", - "test/language/expressions/class/elements/multiple-stacked-definitions-rs-static-async-", - "test/language/statements/class/elements/multiple-definitions-rs-static-async-", - "test/language/expressions/class/elements/multiple-definitions-rs-static-async-", + + // async generators + "test/language/statements/class/elements/wrapped-in-sc-rs-static-async-generator-", + "test/language/statements/class/elements/same-line-method-rs-static-async-generator-", + "test/language/statements/class/elements/regular-definitions-rs-static-async-generator-", + "test/language/statements/class/elements/private-static-async-generator-", + "test/language/statements/class/elements/new-sc-line-method-rs-static-async-generator-", + "test/language/statements/class/elements/multiple-stacked-definitions-rs-static-async-generator-", + "test/language/statements/class/elements/new-no-sc-line-method-rs-static-async-generator-", + "test/language/statements/class/elements/multiple-definitions-rs-static-async-generator-", + "test/language/statements/class/elements/after-same-line-static-method-rs-static-async-generator-", + "test/language/statements/class/elements/after-same-line-method-rs-static-async-generator-", + "test/language/statements/class/elements/after-same-line-static-method-rs-static-async-generator-", + + "test/language/expressions/class/elements/wrapped-in-sc-rs-static-async-generator-", + "test/language/expressions/class/elements/same-line-method-rs-static-async-generator-", + "test/language/expressions/class/elements/regular-definitions-rs-static-async-generator-", + "test/language/expressions/class/elements/private-static-async-generator-", + "test/language/expressions/class/elements/new-sc-line-method-rs-static-async-generator-", + "test/language/expressions/class/elements/multiple-stacked-definitions-rs-static-async-generator-", + "test/language/expressions/class/elements/new-no-sc-line-method-rs-static-async-generator-", + "test/language/expressions/class/elements/multiple-definitions-rs-static-async-generator-", + "test/language/expressions/class/elements/after-same-line-static-method-rs-static-async-generator-", + "test/language/expressions/class/elements/after-same-line-method-rs-static-async-generator-", + "test/language/expressions/class/elements/after-same-line-static-method-rs-static-async-generator-", + + "test/language/eval-code/direct/async-gen-", // generators "test/language/eval-code/direct/gen-", diff --git a/vm.go b/vm.go index 836535d0..3f96ec58 100644 --- a/vm.go +++ b/vm.go @@ -71,6 +71,11 @@ func (vm *vm) suspend(ectx *execCtx, tryStackLen, iterStackLen, refStackLen uint l := len(vm.tryStack) - int(tryStackLen) ectx.tryStack = append(ectx.tryStack[:0], vm.tryStack[l:]...) vm.tryStack = vm.tryStack[:l] + for i := range ectx.tryStack { + tf := &ectx.tryStack[i] + tf.iterLen -= iterStackLen + tf.refLen -= refStackLen + } } if iterStackLen > 0 { l := len(vm.iterStack) - int(iterStackLen) @@ -90,6 +95,12 @@ func (vm *vm) resume(ctx *execCtx) { vm.stack.expand(vm.sp + len(ctx.stack)) copy(vm.stack[vm.sp:], ctx.stack) vm.sp += len(ctx.stack) + for i := range ctx.tryStack { + tf := &ctx.tryStack[i] + tf.callStackLen = uint32(len(vm.callStack)) + tf.iterLen += uint32(len(vm.iterStack)) + tf.refLen += uint32(len(vm.refStack)) + } vm.tryStack = append(vm.tryStack, ctx.tryStack...) vm.iterStack = append(vm.iterStack, ctx.iterStack...) vm.refStack = append(vm.refStack, ctx.refStack...)