Browse Source

Catch InterruptedError when calling exported functions (fixes #54)

Dmitry Panov 7 years ago
parent
commit
31b7e71a9b
2 changed files with 40 additions and 0 deletions
  1. 11 0
      runtime.go
  2. 29 0
      runtime_test.go

+ 11 - 0
runtime.go

@@ -1370,6 +1370,15 @@ func AssertFunction(v Value) (Callable, bool) {
 	if obj, ok := v.(*Object); ok {
 	if obj, ok := v.(*Object); ok {
 		if f, ok := obj.self.assertCallable(); ok {
 		if f, ok := obj.self.assertCallable(); ok {
 			return func(this Value, args ...Value) (ret Value, err error) {
 			return func(this Value, args ...Value) (ret Value, err error) {
+				defer func() {
+					if x := recover(); x != nil {
+						if ex, ok := x.(*InterruptedError); ok {
+							err = ex
+						} else {
+							panic(x)
+						}
+					}
+				}()
 				ex := obj.runtime.vm.try(func() {
 				ex := obj.runtime.vm.try(func() {
 					ret = f(FunctionCall{
 					ret = f(FunctionCall{
 						This:      this,
 						This:      this,
@@ -1414,6 +1423,8 @@ func tryFunc(f func()) (err error) {
 			switch x := x.(type) {
 			switch x := x.(type) {
 			case *Exception:
 			case *Exception:
 				err = x
 				err = x
+			case *InterruptedError:
+				err = x
 			case Value:
 			case Value:
 				err = &Exception{
 				err = &Exception{
 					val: x,
 					val: x,

+ 29 - 0
runtime_test.go

@@ -1015,6 +1015,35 @@ func TestCreateObject(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestInterruptInWrappedFunction(t *testing.T) {
+	rt := New()
+	v, err := rt.RunString(`
+		var fn = function() {
+			while (true) {}
+		};
+		fn;
+	`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	fn, ok := AssertFunction(v)
+	if !ok {
+		t.Fatal("Not a function")
+	}
+	go func() {
+		<-time.After(10 * time.Millisecond)
+		rt.Interrupt(errors.New("hi"))
+	}()
+
+	v, err = fn(nil)
+	if err == nil {
+		t.Fatal("expected error")
+	}
+	if _, ok := err.(*InterruptedError); !ok {
+		t.Fatalf("Wrong error type: %T", err)
+	}
+}
+
 /*
 /*
 func TestArrayConcatSparse(t *testing.T) {
 func TestArrayConcatSparse(t *testing.T) {
 function foo(a,b,c)
 function foo(a,b,c)