mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
syscall/js: improve import functions
1. Make import functions not use the js.Value type directly, but only the ref field. This gives more flexibility on the Go side for the js.Value type, which is a preparation for adding garbage collection of js.Value. 2. Turn import functions which are methods of js.Value into package-level functions. This is necessary to make vet happy. Change-Id: I69959bf1fbea0a0b99a552a1112ffcd0c024e9b8 Reviewed-on: https://go-review.googlesource.com/118656 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
f70d1e76cc
commit
2809b339b5
|
@ -173,48 +173,48 @@
|
|||
crypto.getRandomValues(loadSlice(sp + 8));
|
||||
},
|
||||
|
||||
// func boolVal(value bool) Value
|
||||
// func boolVal(value bool) ref
|
||||
"syscall/js.boolVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getUint8(sp + 8) !== 0);
|
||||
},
|
||||
|
||||
// func intVal(value int) Value
|
||||
// func intVal(value int) ref
|
||||
"syscall/js.intVal": (sp) => {
|
||||
storeValue(sp + 16, getInt64(sp + 8));
|
||||
},
|
||||
|
||||
// func floatVal(value float64) Value
|
||||
// func floatVal(value float64) ref
|
||||
"syscall/js.floatVal": (sp) => {
|
||||
storeValue(sp + 16, mem().getFloat64(sp + 8, true));
|
||||
},
|
||||
|
||||
// func stringVal(value string) Value
|
||||
// func stringVal(value string) ref
|
||||
"syscall/js.stringVal": (sp) => {
|
||||
storeValue(sp + 24, loadString(sp + 8));
|
||||
},
|
||||
|
||||
// func (v Value) Get(key string) Value
|
||||
"syscall/js.Value.Get": (sp) => {
|
||||
// func valueGet(v ref, p string) ref
|
||||
"syscall/js.valueGet": (sp) => {
|
||||
storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16)));
|
||||
},
|
||||
|
||||
// func (v Value) set(key string, value Value)
|
||||
"syscall/js.Value.set": (sp) => {
|
||||
// func valueSet(v ref, p string, x ref)
|
||||
"syscall/js.valueSet": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
||||
},
|
||||
|
||||
// func (v Value) Index(i int) Value
|
||||
"syscall/js.Value.Index": (sp) => {
|
||||
// func valueIndex(v ref, i int) ref
|
||||
"syscall/js.valueIndex": (sp) => {
|
||||
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
||||
},
|
||||
|
||||
// func (v Value) setIndex(i int, value Value)
|
||||
"syscall/js.Value.setIndex": (sp) => {
|
||||
// valueSetIndex(v ref, i int, x ref)
|
||||
"syscall/js.valueSetIndex": (sp) => {
|
||||
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
||||
},
|
||||
|
||||
// func (v Value) call(name string, args []Value) (Value, bool)
|
||||
"syscall/js.Value.call": (sp) => {
|
||||
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||
"syscall/js.valueCall": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const m = Reflect.get(v, loadString(sp + 16));
|
||||
|
@ -227,8 +227,8 @@
|
|||
}
|
||||
},
|
||||
|
||||
// func (v Value) invoke(args []Value) (Value, bool)
|
||||
"syscall/js.Value.invoke": (sp) => {
|
||||
// func valueInvoke(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueInvoke": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
|
@ -240,8 +240,8 @@
|
|||
}
|
||||
},
|
||||
|
||||
// func (v Value) new(args []Value) (Value, bool)
|
||||
"syscall/js.Value.new": (sp) => {
|
||||
// func valueNew(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueNew": (sp) => {
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
|
@ -253,35 +253,35 @@
|
|||
}
|
||||
},
|
||||
|
||||
// func (v Value) Float() float64
|
||||
"syscall/js.Value.Float": (sp) => {
|
||||
// func valueFloat(v ref) float64
|
||||
"syscall/js.valueFloat": (sp) => {
|
||||
mem().setFloat64(sp + 16, parseFloat(loadValue(sp + 8)), true);
|
||||
},
|
||||
|
||||
// func (v Value) Int() int
|
||||
"syscall/js.Value.Int": (sp) => {
|
||||
// func valueInt(v ref) int
|
||||
"syscall/js.valueInt": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8)));
|
||||
},
|
||||
|
||||
// func (v Value) Bool() bool
|
||||
"syscall/js.Value.Bool": (sp) => {
|
||||
// func valueBool(v ref) bool
|
||||
"syscall/js.valueBool": (sp) => {
|
||||
mem().setUint8(sp + 16, !!loadValue(sp + 8));
|
||||
},
|
||||
|
||||
// func (v Value) Length() int
|
||||
"syscall/js.Value.Length": (sp) => {
|
||||
// func valueLength(v ref) int
|
||||
"syscall/js.valueLength": (sp) => {
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
||||
},
|
||||
|
||||
// func (v Value) prepareString() (Value, int)
|
||||
"syscall/js.Value.prepareString": (sp) => {
|
||||
// valuePrepareString(v ref) (ref, int)
|
||||
"syscall/js.valuePrepareString": (sp) => {
|
||||
const str = encoder.encode(String(loadValue(sp + 8)));
|
||||
storeValue(sp + 16, str);
|
||||
setInt64(sp + 24, str.length);
|
||||
},
|
||||
|
||||
// func (v Value) loadString(b []byte)
|
||||
"syscall/js.Value.loadString": (sp) => {
|
||||
// valueLoadString(v ref, b []byte)
|
||||
"syscall/js.valueLoadString": (sp) => {
|
||||
const str = loadValue(sp + 8);
|
||||
loadSlice(sp + 16).set(str);
|
||||
},
|
||||
|
|
|
@ -11,11 +11,20 @@
|
|||
// comprehensive API for users. It is exempt from the Go compatibility promise.
|
||||
package js
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ref is used to identify a JavaScript value, since the value itself can not be passed to WebAssembly itself.
|
||||
type ref uint32
|
||||
|
||||
// Value represents a JavaScript value.
|
||||
type Value struct {
|
||||
ref uint32
|
||||
ref ref
|
||||
}
|
||||
|
||||
func makeValue(v ref) Value {
|
||||
return Value{ref: v}
|
||||
}
|
||||
|
||||
// Error wraps a JavaScript error.
|
||||
|
@ -31,19 +40,19 @@ func (e Error) Error() string {
|
|||
|
||||
var (
|
||||
// Undefined is the JavaScript value "undefined". The zero Value equals to Undefined.
|
||||
Undefined = Value{0}
|
||||
Undefined = makeValue(0)
|
||||
|
||||
// Null is the JavaScript value "null".
|
||||
Null = Value{1}
|
||||
Null = makeValue(1)
|
||||
|
||||
// Global is the JavaScript global object, usually "window" or "global".
|
||||
Global = Value{2}
|
||||
Global = makeValue(2)
|
||||
|
||||
// memory is the WebAssembly linear memory.
|
||||
memory = Value{3}
|
||||
memory = makeValue(3)
|
||||
|
||||
// resolveCallbackPromise is a function that the callback helper uses to resume the execution of Go's WebAssembly code.
|
||||
resolveCallbackPromise = Value{4}
|
||||
resolveCallbackPromise = makeValue(4)
|
||||
)
|
||||
|
||||
var uint8Array = Global.Get("Uint8Array")
|
||||
|
@ -58,37 +67,37 @@ func ValueOf(x interface{}) Value {
|
|||
case nil:
|
||||
return Null
|
||||
case bool:
|
||||
return boolVal(x)
|
||||
return makeValue(boolVal(x))
|
||||
case int:
|
||||
return intVal(x)
|
||||
return makeValue(intVal(x))
|
||||
case int8:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case int16:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case int32:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case int64:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uint:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uint8:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uint16:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uint32:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uint64:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case uintptr:
|
||||
return intVal(int(x))
|
||||
return makeValue(intVal(int(x)))
|
||||
case unsafe.Pointer:
|
||||
return intVal(int(uintptr(x)))
|
||||
return makeValue(intVal(int(uintptr(x))))
|
||||
case float32:
|
||||
return floatVal(float64(x))
|
||||
return makeValue(floatVal(float64(x)))
|
||||
case float64:
|
||||
return floatVal(x)
|
||||
return makeValue(floatVal(x))
|
||||
case string:
|
||||
return stringVal(x)
|
||||
return makeValue(stringVal(x))
|
||||
case []byte:
|
||||
if len(x) == 0 {
|
||||
return uint8Array.New(memory.Get("buffer"), 0, 0)
|
||||
|
@ -99,98 +108,122 @@ func ValueOf(x interface{}) Value {
|
|||
}
|
||||
}
|
||||
|
||||
func boolVal(x bool) Value
|
||||
func boolVal(x bool) ref
|
||||
|
||||
func intVal(x int) Value
|
||||
func intVal(x int) ref
|
||||
|
||||
func floatVal(x float64) Value
|
||||
func floatVal(x float64) ref
|
||||
|
||||
func stringVal(x string) Value
|
||||
func stringVal(x string) ref
|
||||
|
||||
// Get returns the JavaScript property p of value v.
|
||||
func (v Value) Get(p string) Value
|
||||
func (v Value) Get(p string) Value {
|
||||
return makeValue(valueGet(v.ref, p))
|
||||
}
|
||||
|
||||
func valueGet(v ref, p string) ref
|
||||
|
||||
// Set sets the JavaScript property p of value v to x.
|
||||
func (v Value) Set(p string, x interface{}) {
|
||||
v.set(p, ValueOf(x))
|
||||
valueSet(v.ref, p, ValueOf(x).ref)
|
||||
}
|
||||
|
||||
func (v Value) set(p string, x Value)
|
||||
func valueSet(v ref, p string, x ref)
|
||||
|
||||
// Index returns JavaScript index i of value v.
|
||||
func (v Value) Index(i int) Value
|
||||
func (v Value) Index(i int) Value {
|
||||
return makeValue(valueIndex(v.ref, i))
|
||||
}
|
||||
|
||||
func valueIndex(v ref, i int) ref
|
||||
|
||||
// SetIndex sets the JavaScript index i of value v to x.
|
||||
func (v Value) SetIndex(i int, x interface{}) {
|
||||
v.setIndex(i, ValueOf(x))
|
||||
valueSetIndex(v.ref, i, ValueOf(x).ref)
|
||||
}
|
||||
|
||||
func (v Value) setIndex(i int, x Value)
|
||||
func valueSetIndex(v ref, i int, x ref)
|
||||
|
||||
func makeArgs(args []interface{}) []Value {
|
||||
argVals := make([]Value, len(args))
|
||||
func makeArgs(args []interface{}) []ref {
|
||||
argVals := make([]ref, len(args))
|
||||
for i, arg := range args {
|
||||
argVals[i] = ValueOf(arg)
|
||||
argVals[i] = ValueOf(arg).ref
|
||||
}
|
||||
return argVals
|
||||
}
|
||||
|
||||
// Length returns the JavaScript property "length" of v.
|
||||
func (v Value) Length() int
|
||||
func (v Value) Length() int {
|
||||
return valueLength(v.ref)
|
||||
}
|
||||
|
||||
func valueLength(v ref) int
|
||||
|
||||
// Call does a JavaScript call to the method m of value v with the given arguments.
|
||||
// It panics if v has no method m.
|
||||
func (v Value) Call(m string, args ...interface{}) Value {
|
||||
res, ok := v.call(m, makeArgs(args))
|
||||
res, ok := valueCall(v.ref, m, makeArgs(args))
|
||||
if !ok {
|
||||
panic(Error{res})
|
||||
panic(Error{makeValue(res)})
|
||||
}
|
||||
return res
|
||||
return makeValue(res)
|
||||
}
|
||||
|
||||
func (v Value) call(m string, args []Value) (Value, bool)
|
||||
func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||
|
||||
// Invoke does a JavaScript call of the value v with the given arguments.
|
||||
// It panics if v is not a function.
|
||||
func (v Value) Invoke(args ...interface{}) Value {
|
||||
res, ok := v.invoke(makeArgs(args))
|
||||
res, ok := valueInvoke(v.ref, makeArgs(args))
|
||||
if !ok {
|
||||
panic(Error{res})
|
||||
panic(Error{makeValue(res)})
|
||||
}
|
||||
return res
|
||||
return makeValue(res)
|
||||
}
|
||||
|
||||
func (v Value) invoke(args []Value) (Value, bool)
|
||||
func valueInvoke(v ref, args []ref) (ref, bool)
|
||||
|
||||
// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
|
||||
// It panics if v is not a function.
|
||||
func (v Value) New(args ...interface{}) Value {
|
||||
res, ok := v.new(makeArgs(args))
|
||||
res, ok := valueNew(v.ref, makeArgs(args))
|
||||
if !ok {
|
||||
panic(Error{res})
|
||||
panic(Error{makeValue(res)})
|
||||
}
|
||||
return res
|
||||
return makeValue(res)
|
||||
}
|
||||
|
||||
func (v Value) new(args []Value) (Value, bool)
|
||||
func valueNew(v ref, args []ref) (ref, bool)
|
||||
|
||||
// Float returns the value v converted to float64 according to JavaScript type conversions (parseFloat).
|
||||
func (v Value) Float() float64
|
||||
func (v Value) Float() float64 {
|
||||
return valueFloat(v.ref)
|
||||
}
|
||||
|
||||
func valueFloat(v ref) float64
|
||||
|
||||
// Int returns the value v converted to int according to JavaScript type conversions (parseInt).
|
||||
func (v Value) Int() int
|
||||
func (v Value) Int() int {
|
||||
return valueInt(v.ref)
|
||||
}
|
||||
|
||||
func valueInt(v ref) int
|
||||
|
||||
// Bool returns the value v converted to bool according to JavaScript type conversions.
|
||||
func (v Value) Bool() bool
|
||||
func (v Value) Bool() bool {
|
||||
return valueBool(v.ref)
|
||||
}
|
||||
|
||||
func valueBool(v ref) bool
|
||||
|
||||
// String returns the value v converted to string according to JavaScript type conversions.
|
||||
func (v Value) String() string {
|
||||
str, length := v.prepareString()
|
||||
str, length := valuePrepareString(v.ref)
|
||||
b := make([]byte, length)
|
||||
str.loadString(b)
|
||||
valueLoadString(str, b)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (v Value) prepareString() (Value, int)
|
||||
func valuePrepareString(v ref) (ref, int)
|
||||
|
||||
func (v Value) loadString(b []byte)
|
||||
func valueLoadString(v ref, b []byte)
|
||||
|
|
|
@ -20,54 +20,54 @@ TEXT ·stringVal(SB), NOSPLIT, $0
|
|||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Get(SB), NOSPLIT, $0
|
||||
TEXT ·valueGet(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·set(SB), NOSPLIT, $0
|
||||
TEXT ·valueSet(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Index(SB), NOSPLIT, $0
|
||||
TEXT ·valueIndex(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·setIndex(SB), NOSPLIT, $0
|
||||
TEXT ·valueSetIndex(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·call(SB), NOSPLIT, $0
|
||||
TEXT ·valueCall(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·invoke(SB), NOSPLIT, $0
|
||||
TEXT ·valueInvoke(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·new(SB), NOSPLIT, $0
|
||||
TEXT ·valueNew(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Float(SB), NOSPLIT, $0
|
||||
TEXT ·valueFloat(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Int(SB), NOSPLIT, $0
|
||||
TEXT ·valueInt(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Bool(SB), NOSPLIT, $0
|
||||
TEXT ·valueBool(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·Length(SB), NOSPLIT, $0
|
||||
TEXT ·valueLength(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·prepareString(SB), NOSPLIT, $0
|
||||
TEXT ·valuePrepareString(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
||||
TEXT ·Value·loadString(SB), NOSPLIT, $0
|
||||
TEXT ·valueLoadString(SB), NOSPLIT, $0
|
||||
CallImport
|
||||
RET
|
||||
|
|
Loading…
Reference in a new issue