diff --git a/runtime_test.go b/runtime_test.go index b084a4a3..d51cbbdb 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -2325,15 +2325,32 @@ func TestStacktraceLocationThrowFromCatch(t *testing.T) { t.Fatal("Expected error") } stack := err.(*Exception).stack - if len(stack) != 2 { + if len(stack) != 3 { t.Fatalf("Unexpected stack len: %v", stack) } - if frame := stack[0]; frame.funcName != "main" || frame.pc != 29 { + if frame := stack[0]; frame.funcName != "f2" || frame.pc != 2 { t.Fatalf("Unexpected stack frame 0: %#v", frame) } - if frame := stack[1]; frame.funcName != "" || frame.pc != 7 { + if frame := stack[1]; frame.funcName != "main" || frame.pc != 15 { t.Fatalf("Unexpected stack frame 1: %#v", frame) } + if frame := stack[2]; frame.funcName != "" || frame.pc != 7 { + t.Fatalf("Unexpected stack frame 2: %#v", frame) + } +} + +func TestErrorStackRethrow(t *testing.T) { + const SCRIPT = ` + function f(e) { + throw e; + } + try { + f(new Error()); + } catch(e) { + assertStack(e, [["test.js", "", 6, 5]]); + } + ` + testScriptWithTestLibX(SCRIPT, _undefined, t) } func TestStacktraceLocationThrowFromGo(t *testing.T) { diff --git a/vm.go b/vm.go index dd328444..031870c9 100644 --- a/vm.go +++ b/vm.go @@ -4437,28 +4437,20 @@ var throw _throw func (_throw) exec(vm *vm) { v := vm.stack[vm.sp-1] - var ex *Exception + ex := &Exception{ + val: v, + } + if o, ok := v.(*Object); ok { if e, ok := o.self.(*errorObject); ok { if len(e.stack) > 0 { - frame0 := e.stack[0] - // If the Error was created immediately before throwing it (i.e. 'throw new Error(....)') - // avoid capturing the stack again by the reusing the stack from the Error. - // These stacks would be almost identical and the difference doesn't matter for debugging. - if frame0.prg == vm.prg && vm.pc-frame0.pc == 1 { - ex = &Exception{ - val: v, - stack: e.stack, - } - } + ex.stack = e.stack } } } - if ex == nil { - ex = &Exception{ - val: v, - stack: vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0), - } + + if ex.stack == nil { + ex.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0) } if ex = vm.handleThrow(ex); ex != nil {