Browse Source

Added support for native functions with *Runtime as a parameter. See #243

Dmitry Panov 4 years ago
parent
commit
06e99480d2
2 changed files with 31 additions and 0 deletions
  1. 14 0
      runtime.go
  2. 17 0
      runtime_test.go

+ 14 - 0
runtime.go

@@ -1297,6 +1297,8 @@ func(FunctionCall) Value is treated as a native JavaScript function. This increa
 automatic argument and return value type conversions (which involves reflect). Attempting to use
 the function as a constructor will result in a TypeError.
 
+func(FunctionCall, *Runtime) Value is treated as above, except the *Runtime is also passed as a parameter.
+
 func(ConstructorCall) *Object is treated as a native constructor, allowing to use it with the new
 operator:
 
@@ -1327,6 +1329,8 @@ When a native constructor is called directly (without the new operator) its beha
 this value: if it's an Object, it is passed through, otherwise a new one is created exactly as
 if it was called with the new operator. In either case call.NewTarget will be nil.
 
+func(ConstructorCall, *Runtime) *Object is treated as above, except the *Runtime is also passed as a parameter.
+
 Any other Go function is wrapped so that the arguments are automatically converted into the required Go types and the
 return value is converted to a JavaScript value (using this method).  If conversion is not possible, a TypeError is
 thrown.
@@ -1449,9 +1453,19 @@ func (r *Runtime) ToValue(i interface{}) Value {
 	case func(FunctionCall) Value:
 		name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name())
 		return r.newNativeFunc(i, nil, name, nil, 0)
+	case func(FunctionCall, *Runtime) Value:
+		name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name())
+		return r.newNativeFunc(func(call FunctionCall) Value {
+			return i(call, r)
+		}, nil, name, nil, 0)
 	case func(ConstructorCall) *Object:
 		name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name())
 		return r.newNativeConstructor(i, name, 0)
+	case func(ConstructorCall, *Runtime) *Object:
+		name := unistring.NewFromString(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name())
+		return r.newNativeConstructor(func(call ConstructorCall) *Object {
+			return i(call, r)
+		}, name, 0)
 	case int:
 		return intToValue(int64(i))
 	case int8:

+ 17 - 0
runtime_test.go

@@ -1848,6 +1848,23 @@ func TestRuntime_SetParserOptions_Eval(t *testing.T) {
 	}
 }
 
+func TestNativeCallWithRuntimeParameter(t *testing.T) {
+	vm := New()
+	vm.Set("f", func(_ FunctionCall, r *Runtime) Value {
+		if r == vm {
+			return valueTrue
+		}
+		return valueFalse
+	})
+	ret, err := vm.RunString(`f()`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if ret != valueTrue {
+		t.Fatal(ret)
+	}
+}
+
 /*
 func TestArrayConcatSparse(t *testing.T) {
 function foo(a,b,c)