Bladeren bron

Save return value and restore the stack before running finally. Fixes #553.

Dmitry Panov 1 jaar geleden
bovenliggende
commit
e401ed4502
4 gewijzigde bestanden met toevoegingen van 25 en 2 verwijderingen
  1. 1 1
      compiler_stmt.go
  2. 14 0
      compiler_test.go
  3. 1 1
      runtime_test.go
  4. 9 0
      vm.go

+ 1 - 1
compiler_stmt.go

@@ -739,7 +739,7 @@ func (c *compiler) compileReturnStatement(v *ast.ReturnStatement) {
 	for b := c.block; b != nil; b = b.outer {
 		switch b.typ {
 		case blockTry:
-			c.emit(leaveTry{})
+			c.emit(saveResult, leaveTry{}, loadResult)
 		case blockLoopEnum:
 			c.emit(enumPopClose)
 		}

+ 14 - 0
compiler_test.go

@@ -1117,6 +1117,20 @@ func TestReturnOutOfTryNested(t *testing.T) {
 	testScript(SCRIPT, intToValue(1), t)
 }
 
+func TestReturnOutOfTryWithFinally(t *testing.T) {
+	const SCRIPT = `
+	function test() {
+		try {
+			return 'Hello, world!';
+		} finally {
+			const dummy = 'unexpected';
+		}
+	}
+	test();
+	`
+	testScript(SCRIPT, asciiString("Hello, world!"), t)
+}
+
 func TestContinueLoop(t *testing.T) {
 	const SCRIPT = `
 	function A() {

+ 1 - 1
runtime_test.go

@@ -2331,7 +2331,7 @@ func TestStacktraceLocationThrowFromCatch(t *testing.T) {
 	if frame := stack[0]; frame.funcName != "f2" || frame.pc != 2 {
 		t.Fatalf("Unexpected stack frame 0: %#v", frame)
 	}
-	if frame := stack[1]; frame.funcName != "main" || frame.pc != 15 {
+	if frame := stack[1]; frame.funcName != "main" || frame.pc != 17 {
 		t.Fatalf("Unexpected stack frame 1: %#v", frame)
 	}
 	if frame := stack[2]; frame.funcName != "" || frame.pc != 7 {

+ 9 - 0
vm.go

@@ -932,6 +932,15 @@ func (_saveResult) exec(vm *vm) {
 	vm.pc++
 }
 
+type _loadResult struct{}
+
+var loadResult _loadResult
+
+func (_loadResult) exec(vm *vm) {
+	vm.push(vm.result)
+	vm.pc++
+}
+
 type _clearResult struct{}
 
 var clearResult _clearResult