func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { if typ.Kind() != Func { panic("reflect: call of MakeFunc with non-Func type") } t := typ.common() ftyp := (*funcType)(unsafe.Pointer(t)) fv := func() js.Object { args := make([]Value, ftyp.NumIn()) for i := range args { argType := ftyp.In(i).common() args[i] = makeValue(argType, js.Arguments[i], 0) } resultsSlice := fn(args) switch ftyp.NumOut() { case 0: return nil case 1: return js.InternalObject(resultsSlice[0].iword()) default: results := js.Global.Get("Array").New(ftyp.NumOut()) for i, r := range resultsSlice { results.SetIndex(i, js.InternalObject(r.iword())) } return results } } return Value{t, unsafe.Pointer(js.InternalObject(fv).Unsafe()), 0, flag(Func) << flagKindShift} }
func (v Value) Slice3(i, j, k int) Value { var ( cap int typ Type s js.Object ) switch kind := v.kind(); kind { case Array: if v.flag&flagAddr == 0 { panic("reflect.Value.Slice: slice of unaddressable array") } tt := (*arrayType)(unsafe.Pointer(v.typ)) cap = int(tt.len) typ = SliceOf(tt.elem) s = jsType(typ).New(js.InternalObject(v.iword())) case Slice: typ = v.typ s = js.InternalObject(v.iword()) cap = s.Get("$capacity").Int() default: panic(&ValueError{"reflect.Value.Slice3", kind}) } if i < 0 || j < i || k < j || k > cap { panic("reflect.Value.Slice3: slice index out of bounds") } return makeValue(typ, js.Global.Call("$subslice", s, i, j, k), v.flag&flagRO) }
func (v Value) object() *js.Object { if v.typ.Kind() == Array || v.typ.Kind() == Struct { return js.InternalObject(v.ptr) } if v.flag&flagIndir != 0 { val := js.InternalObject(v.ptr).Call("$get") if val != js.Global.Get("$ifaceNil") && val.Get("constructor") != jsType(v.typ) { switch v.typ.Kind() { case Uint64, Int64: val = jsType(v.typ).New(val.Get("$high"), val.Get("$low")) case Complex64, Complex128: val = jsType(v.typ).New(val.Get("$real"), val.Get("$imag")) case Slice: if val == val.Get("constructor").Get("nil") { val = jsType(v.typ).Get("nil") break } newVal := jsType(v.typ).New(val.Get("$array")) newVal.Set("$offset", val.Get("$offset")) newVal.Set("$length", val.Get("$length")) newVal.Set("$capacity", val.Get("$capacity")) val = newVal } } return js.InternalObject(val.Unsafe()) } return js.InternalObject(v.ptr) }
func (r *rngReader) Read(b []byte) (n int, err error) { array := js.InternalObject(b).Get("$array") offset := js.InternalObject(b).Get("$offset").Int() // browser crypto := js.Global.Get("crypto") if crypto == js.Undefined { crypto = js.Global.Get("msCrypto") } if crypto != js.Undefined { if crypto.Get("getRandomValues") != js.Undefined { n = len(b) if n > 65536 { // Avoid QuotaExceededError thrown by getRandomValues // when length is more than 65536, as specified in // http://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues n = 65536 } crypto.Call("getRandomValues", array.Call("subarray", offset, offset+n)) return n, nil } } // Node.js if require := js.Global.Get("require"); require != js.Undefined { if randomBytes := require.Invoke("crypto").Get("randomBytes"); randomBytes != js.Undefined { array.Call("set", randomBytes.Invoke(len(b)), offset) return len(b), nil } } return 0, errors.New("crypto/rand not available in this environment") }
func Copy(dst, src Value) int { dk := dst.kind() if dk != Array && dk != Slice { panic(&ValueError{"reflect.Copy", dk}) } if dk == Array { dst.mustBeAssignable() } dst.mustBeExported() sk := src.kind() if sk != Array && sk != Slice { panic(&ValueError{"reflect.Copy", sk}) } src.mustBeExported() typesMustMatch("reflect.Copy", dst.typ.Elem(), src.typ.Elem()) dstVal := js.InternalObject(dst.iword()) if dk == Array { dstVal = jsType(SliceOf(dst.typ.Elem())).New(dstVal) } srcVal := js.InternalObject(src.iword()) if sk == Array { srcVal = jsType(SliceOf(src.typ.Elem())).New(srcVal) } return js.Global.Call("$copySlice", dstVal, srcVal).Int() }
func zeroVal(typ Type) js.Object { switch typ.Kind() { case Bool: return js.InternalObject(false) case Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32, Uintptr, Float32, Float64: return js.InternalObject(0) case Int64, Uint64, Complex64, Complex128: return jsType(typ).New(0, 0) case Array: elemType := typ.Elem() return js.Global.Call("go$makeNativeArray", jsType(elemType).Get("kind"), typ.Len(), func() js.Object { return zeroVal(elemType) }) case Func: return js.Global.Get("go$throwNilPointerError") case Interface: return nil case Map: return js.InternalObject(false) case Chan, Ptr, Slice: return jsType(typ).Get("nil") case String: return js.InternalObject("") case Struct: return jsType(typ).Get("Ptr").New() default: panic(&ValueError{"reflect.Zero", typ.Kind()}) } }
func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer) { k := js.InternalObject(key).Call("$get") if !k.Get("$key").IsUndefined() { k = k.Call("$key") } js.InternalObject(m).Delete(k.Str()) }
func mapaccess(t *rtype, m, key unsafe.Pointer) unsafe.Pointer { k := jsType(t.Key()).Call("keyFor", js.InternalObject(key).Call("$get")).String() entry := js.InternalObject(m).Get(k) if entry == js.Undefined { return nil } return unsafe.Pointer(js.Global.Call("$newDataPointer", entry.Get("v"), jsType(PtrTo(t.Elem()))).Unsafe()) }
func Main2(pkgPath string, dir string, names []string, tests []func(*T)) { flag.Parse() if len(tests) == 0 { fmt.Println("testing: warning: no tests to run") } d, err := os.Open(dir) if err != nil { panic(err) } d.Chdir() ok := true start := time.Now() for i := 0; i < len(tests); i++ { t := &T{ common: common{ start: time.Now(), }, name: names[i], } t.self = t if *chatty { fmt.Printf("=== RUN %s\n", t.name) } err := runTest.Invoke(js.InternalObject(tests[i]), js.InternalObject(t)) js.Global.Set("$jsErr", nil) if err != nil { switch { case !err.Get("$exit").IsUndefined(): // test failed or skipped err = nil case !err.Get("$notSupported").IsUndefined(): t.log(err.Get("message").Str()) t.skip() err = nil default: t.Fail() } } t.common.duration = time.Now().Sub(t.common.start) t.report() if err != nil { throw.Invoke(js.InternalObject(err)) } ok = ok && !t.common.failed } duration := time.Now().Sub(start) status := "ok " exitCode := 0 if !ok { status = "FAIL" exitCode = 1 } fmt.Printf("%s\t%s\t%.3fs\n", status, pkgPath, duration.Seconds()) os.Exit(exitCode) }
func (v *Value) Store(x interface{}) { if x == nil { panic("sync/atomic: store of nil value into Value") } if v.v != nil && js.InternalObject(x).Get("constructor") != js.InternalObject(v.v).Get("constructor") { panic("sync/atomic: store of inconsistently typed value into Value") } v.v = x }
func ValueOf(i interface{}) Value { if i == nil { return Value{} } c := js.InternalObject(i).Get("constructor") if c.Get("kind").IsUndefined() { // js.Object return Value{jsObject(), nil, js.InternalObject(i).Unsafe(), flag(Interface) << flagKindShift} } return makeValue(reflectType(c), js.InternalObject(i).Get("$val"), 0) }
func mapaccess(t *rtype, m, key unsafe.Pointer) unsafe.Pointer { k := js.InternalObject(key) if !k.Get("$key").IsUndefined() { k = k.Call("$key") } entry := js.InternalObject(m).Get(k.Str()) if entry.IsUndefined() { return nil } return makePointer(t.Elem(), entry.Get("v")) }
func mapaccess(t *rtype, m, key unsafe.Pointer) unsafe.Pointer { k := js.InternalObject(key).Call("$get") if !k.Get("$key").IsUndefined() { k = k.Call("$key") } entry := js.InternalObject(m).Get(k.Str()) if entry.IsUndefined() { return nil } return unsafe.Pointer(js.Global.Call("$newDataPointer", entry.Get("v"), jsType(PtrTo(t.Elem()))).Unsafe()) }
func mapaccess(t *rtype, m iword, key iword) (val iword, ok bool) { k := js.InternalObject(key) if !k.Get("go$key").IsUndefined() { k = k.Call("go$key") } entry := js.InternalObject(m).Get(k.Str()) if entry.IsUndefined() { return nil, false } return makeIword(t.Elem(), entry.Get("v")), true }
func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool { comms := [][]interface{}{{js.InternalObject(ch), js.InternalObject(val).Call("$get")}} if nb { comms = append(comms, []interface{}{}) } selectRes := selectHelper(comms) if nb && selectRes.Index(0).Int() == 1 { return false } return true }
func makeMethodValue(op string, v Value) Value { if v.flag&flagMethod == 0 { panic("reflect: internal error: invalid use of makePartialFunc") } _, fn, rcvr := methodReceiver(op, v, int(v.flag)>>flagMethodShift) fv := func() js.Object { return js.InternalObject(fn).Call("apply", rcvr, js.Arguments) } return Value{v.Type().common(), unsafe.Pointer(js.InternalObject(fv).Unsafe()), v.flag&flagRO | flag(Func)<<flagKindShift} }
func DeepEqual(a1, a2 interface{}) bool { i1 := js.InternalObject(a1) i2 := js.InternalObject(a2) if i1 == i2 { return true } if i1 == nil || i2 == nil || i1.Get("constructor") != i2.Get("constructor") { return false } return deepValueEqualJs(ValueOf(a1), ValueOf(a2), nil) }
func (v Value) Len() int { switch k := v.kind(); k { case Array, Slice, String: return js.InternalObject(v.iword()).Length() // case Chan: // return chanlen(v.iword()) case Map: return js.Global.Call("$keys", js.InternalObject(v.iword())).Length() default: panic(&ValueError{"reflect.Value.Len", k}) } }
func (v Value) Index(i int) Value { switch k := v.kind(); k { case Array: tt := (*arrayType)(unsafe.Pointer(v.typ)) if i < 0 || i > int(tt.len) { panic("reflect: array index out of range") } typ := tt.elem fl := v.flag & (flagRO | flagIndir | flagAddr) fl |= flag(typ.Kind()) a := js.InternalObject(v.ptr) if fl&flagIndir != 0 && typ.Kind() != Array && typ.Kind() != Struct { return Value{typ, unsafe.Pointer(jsType(PtrTo(typ)).New( js.InternalObject(func() *js.Object { return wrapJsObject(typ, a.Index(i)) }), js.InternalObject(func(x *js.Object) { a.SetIndex(i, unwrapJsObject(typ, x)) }), ).Unsafe()), fl} } return makeValue(typ, wrapJsObject(typ, a.Index(i)), fl) case Slice: s := v.object() if i < 0 || i >= s.Get("$length").Int() { panic("reflect: slice index out of range") } tt := (*sliceType)(unsafe.Pointer(v.typ)) typ := tt.elem fl := flagAddr | flagIndir | v.flag&flagRO fl |= flag(typ.Kind()) i += s.Get("$offset").Int() a := s.Get("$array") if fl&flagIndir != 0 && typ.Kind() != Array && typ.Kind() != Struct { return Value{typ, unsafe.Pointer(jsType(PtrTo(typ)).New( js.InternalObject(func() *js.Object { return wrapJsObject(typ, a.Index(i)) }), js.InternalObject(func(x *js.Object) { a.SetIndex(i, unwrapJsObject(typ, x)) }), ).Unsafe()), fl} } return makeValue(typ, wrapJsObject(typ, a.Index(i)), fl) case String: str := *(*string)(v.ptr) if i < 0 || i >= len(str) { panic("reflect: string index out of range") } fl := v.flag&flagRO | flag(Uint8) c := str[i] return Value{uint8Type, unsafe.Pointer(&c), fl | flagIndir} default: panic(&ValueError{"reflect.Value.Index", k}) } }
func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool) { comms := [][]interface{}{{js.InternalObject(ch)}} if nb { comms = append(comms, []interface{}{}) } selectRes := selectHelper(comms) if nb && selectRes.Index(0).Int() == 1 { return false, false } recvRes := selectRes.Index(1) js.InternalObject(val).Call("$set", recvRes.Index(0)) return true, recvRes.Index(1).Bool() }
func (v Value) SetCap(n int) { v.mustBeAssignable() v.mustBe(Slice) s := js.InternalObject(v.val).Call("go$get") if n < s.Length() || n > s.Get("capacity").Int() { panic("reflect: slice capacity out of range in SetCap") } newSlice := jsType(v.typ).New(s.Get("array")) newSlice.Set("offset", s.Get("offset")) newSlice.Set("length", s.Get("length")) newSlice.Set("capacity", n) js.InternalObject(v.val).Call("go$set", newSlice) }
func (v Value) SetLen(n int) { v.mustBeAssignable() v.mustBe(Slice) s := js.InternalObject(v.ptr).Call("$get") if n < 0 || n > s.Get("$capacity").Int() { panic("reflect: slice length out of range in SetLen") } newSlice := jsType(v.typ).New(s.Get("$array")) newSlice.Set("$offset", s.Get("$offset")) newSlice.Set("$length", n) newSlice.Set("$capacity", s.Get("$capacity")) js.InternalObject(v.ptr).Call("$set", newSlice) }
// MarshalIndentString is like MarshalIndent, but outputs a string func MarshalIndentString(v interface{}, prefix, indent string) (json string, err error) { defer func() { if e := recover(); e != nil { if er, ok := e.(*js.Error); ok { err = er } } }() str := js.Global.Get("JSON").Call("stringify", js.InternalObject(toObject).Invoke(js.InternalObject(v)), nil, indent) if len(prefix) > 0 { str = str.Call("replace", "\n", "\n"+prefix) } return str.String(), nil }
func mapassign(t *rtype, m, key, val unsafe.Pointer) { kv, k := keyFor(t, key) jsVal := js.InternalObject(val).Call("$get") et := t.Elem() if et.Kind() == Struct { newVal := jsType(et).Call("zero") copyStruct(newVal, jsVal, et) jsVal = newVal } entry := js.Global.Get("Object").New() entry.Set("k", kv) entry.Set("v", jsVal) js.InternalObject(m).Set(k, entry) }
func rselect(rselects []runtimeSelect) (chosen int, recvOK bool) { comms := make([][]*js.Object, len(rselects)) for i, s := range rselects { switch SelectDir(s.dir) { case SelectDefault: comms[i] = []*js.Object{} case SelectRecv: ch := js.Global.Get("$chanNil") if js.InternalObject(s.ch) != js.InternalObject(0) { ch = js.InternalObject(s.ch) } comms[i] = []*js.Object{ch} case SelectSend: ch := js.Global.Get("$chanNil") var val *js.Object if js.InternalObject(s.ch) != js.InternalObject(0) { ch = js.InternalObject(s.ch) val = js.InternalObject(s.val).Call("$get") } comms[i] = []*js.Object{ch, val} } } selectRes := selectHelper(comms) c := selectRes.Index(0).Int() if SelectDir(rselects[c].dir) == SelectRecv { recvRes := selectRes.Index(1) js.InternalObject(rselects[c].val).Call("$set", recvRes.Index(0)) return c, recvRes.Index(1).Bool() } return c, false }
func (v Value) Len() int { switch k := v.kind(); k { case Array, String: return js.InternalObject(v.iword()).Length() case Slice: return js.InternalObject(v.iword()).Get("$length").Int() case Chan: return js.InternalObject(v.iword()).Get("$buffer").Get("length").Int() case Map: return js.Global.Call("$keys", js.InternalObject(v.iword())).Length() default: panic(&ValueError{"reflect.Value.Len", k}) } }
func (v Value) IsNil() bool { switch k := v.kind(); k { case Chan, Ptr, Slice: return v.iword() == iword(jsType(v.typ).Get("nil").Unsafe()) case Func: return v.iword() == iword(js.Global.Get("$throwNilPointerError").Unsafe()) case Map: return v.iword() == iword(js.InternalObject(false).Unsafe()) case Interface: return js.InternalObject(v.iword()).IsNull() default: panic(&ValueError{"reflect.Value.IsNil", k}) } }
func (v Value) Field(i int) Value { if v.kind() != Struct { panic(&ValueError{"reflect.Value.Field", v.kind()}) } tt := (*structType)(unsafe.Pointer(v.typ)) if uint(i) >= uint(len(tt.fields)) { panic("reflect: Field index out of range") } prop := jsType(v.typ).Get("fields").Index(i).Get("prop").String() field := &tt.fields[i] typ := field.typ fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind()) if !field.name.isExported() { if field.name.name() == "" { fl |= flagEmbedRO } else { fl |= flagStickyRO } } if tag := tt.fields[i].name.tag(); tag != "" && i != 0 { if jsTag := getJsTag(tag); jsTag != "" { for { v = v.Field(0) if v.typ == jsObjectPtr { o := v.object().Get("object") return Value{typ, unsafe.Pointer(jsType(PtrTo(typ)).New( js.InternalObject(func() *js.Object { return js.Global.Call("$internalize", o.Get(jsTag), jsType(typ)) }), js.InternalObject(func(x *js.Object) { o.Set(jsTag, js.Global.Call("$externalize", x, jsType(typ))) }), ).Unsafe()), fl} } if v.typ.Kind() == Ptr { v = v.Elem() } } } } s := js.InternalObject(v.ptr) if fl&flagIndir != 0 && typ.Kind() != Array && typ.Kind() != Struct { return Value{typ, unsafe.Pointer(jsType(PtrTo(typ)).New( js.InternalObject(func() *js.Object { return wrapJsObject(typ, s.Get(prop)) }), js.InternalObject(func(x *js.Object) { s.Set(prop, unwrapJsObject(typ, x)) }), ).Unsafe()), fl} } return makeValue(typ, wrapJsObject(typ, s.Get(prop)), fl) }
func makeMethodValue(op string, v Value) Value { if v.flag&flagMethod == 0 { panic("reflect: internal error: invalid use of makePartialFunc") } _, _, fn := methodReceiver(op, v, int(v.flag)>>flagMethodShift) rcvr := v.object() if isWrapped(v.typ) { rcvr = jsType(v.typ).New(rcvr) } fv := js.Global.Call("$makeFunc", js.InternalObject(func(arguments []*js.Object) *js.Object { return js.InternalObject(fn).Call("apply", rcvr, arguments) })) return Value{v.Type().common(), unsafe.Pointer(fv.Unsafe()), v.flag&flagRO | flag(Func)} }
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { if f := syscall("Syscall"); f != nil { r := f.Invoke(trap, a1, a2, a3) return uintptr(r.Index(0).Int()), uintptr(r.Index(1).Int()), Errno(r.Index(2).Int()) } if trap == SYS_WRITE && (a1 == 1 || a1 == 2) { array := js.InternalObject(a2) slice := make([]byte, array.Length()) js.InternalObject(slice).Set("$array", array) printToConsole(slice) return uintptr(array.Length()), 0, 0 } printWarning() return uintptr(minusOne), 0, EACCES }