--- js.go.dist 2021-01-23 15:50:00.931644132 -0800 +++ js.go 2021-01-26 10:27:12.735267010 -0800 @@ -27,12 +27,6 @@ // nanHead are the upper 32 bits of a ref which are set if the value is not encoded as an IEEE 754 number (see above). const nanHead = 0x7FF80000 -// Wrapper is implemented by types that are backed by a JavaScript value. -type Wrapper interface { - // JSValue returns a JavaScript value associated with an object. - JSValue() Value -} - // Value represents a JavaScript value. The zero value is the JavaScript value "undefined". // Values can be checked for equality with the Equal method. type Value struct { @@ -50,11 +44,6 @@ typeFlagFunction ) -// JSValue implements Wrapper interface. -func (v Value) JSValue() Value { - return v -} - func makeValue(r ref) Value { var gcPtr *ref typeFlag := (r >> 32) & 7 @@ -161,10 +150,10 @@ // Panics if x is not one of the expected types. func ValueOf(x interface{}) Value { switch x := x.(type) { - case Value: // should precede Wrapper to avoid a loop + case Value: return x - case Wrapper: - return x.JSValue() + case Func: + return x.Value case nil: return valueNull case bool: @@ -220,6 +209,7 @@ } } +//go:noescape func stringVal(x string) ref // Type represents the JavaScript type of a Value. @@ -303,6 +293,7 @@ return r } +//go:noescape func valueGet(v ref, p string) ref // Set sets the JavaScript property p of value v to ValueOf(x). @@ -317,6 +308,7 @@ runtime.KeepAlive(xv) } +//go:noescape func valueSet(v ref, p string, x ref) // Delete deletes the JavaScript property p of value v. @@ -329,6 +321,7 @@ runtime.KeepAlive(v) } +//go:noescape func valueDelete(v ref, p string) // Index returns JavaScript index i of value v. @@ -358,9 +351,21 @@ func valueSetIndex(v ref, i int, x ref) -func makeArgs(args []interface{}) ([]Value, []ref) { - argVals := make([]Value, len(args)) - argRefs := make([]ref, len(args)) +var ( + argValsSlice []Value + argRefsSlice []ref +) + +func makeArgs(args []interface{}) (argVals []Value, argRefs []ref) { + for i, _ := range argValsSlice { + argValsSlice[i] = Value{} + } + if len(args) > cap(argValsSlice) { + argValsSlice = make([]Value, 0, len(args)) + argRefsSlice = make([]ref, 0, len(args)) + } + argVals = argValsSlice[:len(args)] + argRefs = argRefsSlice[:len(args)] for i, arg := range args { v := ValueOf(arg) argVals[i] = v @@ -402,6 +407,7 @@ return makeValue(res) } +//go:noescape func valueCall(v ref, m string, args []ref) (ref, bool) // Invoke does a JavaScript call of the value v with the given arguments. @@ -421,6 +427,7 @@ return makeValue(res) } +//go:noescape func valueInvoke(v ref, args []ref) (ref, bool) // New uses JavaScript's "new" operator with value v as constructor and the given arguments. @@ -440,6 +447,7 @@ return makeValue(res) } +//go:noescape func valueNew(v ref, args []ref) (ref, bool) func (v Value) isNumber() bool { @@ -541,6 +549,7 @@ func valuePrepareString(v ref) (ref, int) +//go:noescape func valueLoadString(v ref, b []byte) // InstanceOf reports whether v is an instance of type t according to JavaScript's instanceof operator. @@ -577,6 +586,7 @@ return n } +//go:noescape func copyBytesToGo(dst []byte, src ref) (int, bool) // CopyBytesToJS copies bytes from src to dst. @@ -591,4 +601,5 @@ return n } +//go:noescape func copyBytesToJS(dst ref, src []byte) (int, bool)