Browse Source

Reverted to the old behaviour of returning an error when converting non-array values into slices. Fixes #369, closes #370.

Dmitry Panov 3 năm trước cách đây
mục cha
commit
61453c17e2
5 tập tin đã thay đổi với 30 bổ sung6 xóa
  1. 5 1
      object.go
  2. 5 2
      object_test.go
  3. 3 3
      runtime.go
  4. 16 0
      runtime_test.go
  5. 1 0
      value.go

+ 5 - 1
object.go

@@ -1044,7 +1044,11 @@ func genericExportToArrayOrSlice(o *Object, dst reflect.Value, typ reflect.Type,
 		}
 	} else {
 		// array-like
-		l := toIntStrict(toLength(o.self.getStr("length", nil)))
+		lp := o.self.getStr("length", nil)
+		if lp == nil {
+			return fmt.Errorf("cannot convert %v to %v: not an array or iterable", o, typ)
+		}
+		l := toIntStrict(toLength(lp))
 		if dst.Len() != l {
 			if typ.Kind() == reflect.Array {
 				return fmt.Errorf("cannot convert an array-like object into an array, lengths mismatch (have %d, need %d)", l, dst.Len())

+ 5 - 2
object_test.go

@@ -303,12 +303,15 @@ func TestExportToSliceNonIterable(t *testing.T) {
 	o := vm.NewObject()
 	var a []interface{}
 	err := vm.ExportTo(o, &a)
-	if err != nil {
-		t.Fatal(err)
+	if err == nil {
+		t.Fatal("Expected an error")
 	}
 	if len(a) != 0 {
 		t.Fatalf("a: %v", a)
 	}
+	if msg := err.Error(); msg != "cannot convert [object Object] to []interface {}: not an array or iterable" {
+		t.Fatalf("Unexpected error: %v", err)
+	}
 }
 
 func ExampleRuntime_ExportTo_iterableToSlice() {

+ 3 - 3
runtime.go

@@ -1863,7 +1863,7 @@ func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value
 
 			// if this is a variadic Go function, and the caller has supplied
 			// exactly the number of JavaScript arguments required, and this
-			// is the last JavaScript argument, try treating the it as the
+			// is the last JavaScript argument, try treating it as the
 			// actual set of variadic Go arguments. if that succeeds, break
 			// out of the loop.
 			if typ.IsVariadic() && len(call.Arguments) == nargs && i == nargs-1 {
@@ -1877,7 +1877,7 @@ func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value
 			v := reflect.New(t).Elem()
 			err := r.toReflectValue(a, v, &objectExportCtx{})
 			if err != nil {
-				panic(r.newError(r.global.TypeError, "could not convert function call parameter %v to %v", a, t))
+				panic(r.NewTypeError("could not convert function call parameter %d: %v", i, err))
 			}
 			in[i] = v
 		}
@@ -2195,7 +2195,7 @@ func (r *Runtime) wrapJSFunc(fn Callable, typ reflect.Type) func(args []reflect.
 // If an object has a 'length' property it is treated as array-like. The resulting slice will contain
 // obj[0], ... obj[length-1].
 //
-// Any other Object is treated as an array-like object with zero length and results in an empty slice.
+// For any other Object an error is returned.
 //
 // Array types
 //

+ 16 - 0
runtime_test.go

@@ -304,6 +304,22 @@ func TestSetGoFunc(t *testing.T) {
 	}
 }
 
+func TestSetFuncVariadic(t *testing.T) {
+	vm := New()
+	vm.Set("f", func(s string, g ...Value) {
+		something := g[0].ToObject(vm).Get(s).ToInteger()
+		if something != 5 {
+			t.Fatal()
+		}
+	})
+	_, err := vm.RunString(`
+           f("something", {something: 5})
+	`)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
 func TestArgsKeys(t *testing.T) {
 	const SCRIPT = `
 	function testArgs2(x, y, z) {

+ 1 - 0
value.go

@@ -767,6 +767,7 @@ func (o *Object) baseObject(*Runtime) *Object {
 // For an array, returns its items as []interface{}.
 //
 // In all other cases returns own enumerable non-symbol properties as map[string]interface{}.
+//
 // This method will panic with an *Exception if a JavaScript exception is thrown in the process.
 func (o *Object) Export() (ret interface{}) {
 	o.runtime.tryPanic(func() {