From ba151c56486fd2becc96cbaf085d7cc1565060bd Mon Sep 17 00:00:00 2001 From: zuiwuchang Date: Sat, 18 Mar 2023 00:55:01 +0800 Subject: [PATCH 1/2] int64 uint64 --- builtin_caller.go | 216 ++++++++++++++++++++++++++++++++ runtime.go | 53 ++++++-- runtime_wrapReflectFunc_test.go | 97 ++++++++++++++ 3 files changed, 354 insertions(+), 12 deletions(-) create mode 100644 builtin_caller.go create mode 100644 runtime_wrapReflectFunc_test.go diff --git a/builtin_caller.go b/builtin_caller.go new file mode 100644 index 00000000..80d0cd21 --- /dev/null +++ b/builtin_caller.go @@ -0,0 +1,216 @@ +package goja + +import ( + "hash/maphash" + "reflect" + "strconv" + + "github.com/dop251/goja/unistring" +) + +var ( + reflectTypeGoCaller = reflect.TypeOf(&valueGoCaller{}) + _GoRaw = &valueGoCaller{ + value: 1, + hashValue: randomHash(), + stringValue: asciiString("GoRaw"), + } + _GoNumber = &valueGoCaller{ + value: 2, + hashValue: randomHash(), + stringValue: asciiString("GoNumber"), + } + _GoRawNumber = &valueGoCaller{ + value: 1 | 2, + hashValue: randomHash(), + stringValue: asciiString("GoRawNumber"), + } + + _GoAsync = &valueGoCaller{ + value: 4, + hashValue: randomHash(), + stringValue: asciiString("GoAsync"), + } + _GoAsyncRaw = &valueGoCaller{ + value: 1 | 4, + hashValue: randomHash(), + stringValue: asciiString("GoAsyncRaw"), + } + _GoAsyncNumber = &valueGoCaller{ + value: 2 | 4, + hashValue: randomHash(), + stringValue: asciiString("GoAsyncNumber"), + } + _GoAsyncRawNumber = &valueGoCaller{ + value: 1 | 2 | 4, + hashValue: randomHash(), + stringValue: asciiString("GoAsyncRawNumber"), + } +) + +func (r *Runtime) initCaller() { + o := r.globalObject.self + o._putProp("GoRaw", _GoRaw, false, false, true) + o._putProp("GoNumber", _GoNumber, false, false, true) + o._putProp("GoRawNumber", _GoRawNumber, false, false, true) + + o._putProp("GoAsync", _GoAsync, false, false, true) + o._putProp("GoAsyncRaw", _GoAsyncRaw, false, false, true) + o._putProp("GoAsyncNumber", _GoAsyncNumber, false, false, true) + o._putProp("GoAsyncRawNumber", _GoAsyncRawNumber, false, false, true) +} + +type Int64 int64 +type Uint64 uint64 + +func (v Int64) String() string { + return strconv.FormatInt(int64(v), 10) +} +func (v Uint64) String() string { + return strconv.FormatUint(uint64(v), 10) +} +func (v Int64) Uint64() Uint64 { + return Uint64(v) +} +func (v Uint64) Int64() Int64 { + return Int64(v) +} +func (v Int64) Value() int64 { + return int64(v) +} +func (v Uint64) Value() uint64 { + return uint64(v) +} +func (v Int64) Add(o Int64) Int64 { + return v + o +} +func (v Uint64) Add(o Uint64) Uint64 { + return v + o +} +func (v Int64) Sub(o Int64) Int64 { + return v - o +} +func (v Uint64) Sub(o Uint64) Uint64 { + return v - o +} +func (v Int64) Mul(o Int64) Int64 { + return v * o +} +func (v Uint64) Mul(o Uint64) Uint64 { + return v * o +} +func (v Int64) Div(o Int64) Int64 { + return v / o +} +func (v Uint64) Div(o Uint64) Uint64 { + return v / o +} +func (v Int64) Mod(o Int64) Int64 { + return v % o +} +func (v Uint64) Mod(o Uint64) Uint64 { + return v % o +} +func (v Int64) ABS() Int64 { + if v < 0 { + return -v + } + return v +} +func (v Int64) Neg() Int64 { + return -v +} +func (v Int64) And(o Int64) Int64 { + return v & o +} +func (v Uint64) And(o Uint64) Uint64 { + return v & o +} +func (v Int64) Or(o Int64) Int64 { + return v | o +} +func (v Uint64) Or(o Uint64) Uint64 { + return v | o +} +func (v Int64) Xor(o Int64) Int64 { + return v ^ o +} +func (v Uint64) Xor(o Uint64) Uint64 { + return v ^ o +} +func (v Int64) Not() Int64 { + return ^v +} +func (v Uint64) Not() Uint64 { + return ^v +} +func (v Int64) Lsh(n int) Int64 { + return v << n +} +func (v Uint64) Lsh(n int) Uint64 { + return v << n +} +func (v Int64) Rsh(n int) Int64 { + return v >> n +} +func (v Uint64) Rsh(n int) Uint64 { + return v >> n +} + +type valueGoCaller struct { + value int64 + hashValue uint64 + stringValue asciiString +} + +func (v *valueGoCaller) ToInteger() int64 { + return v.value +} +func (v *valueGoCaller) toString() valueString { + return v.stringValue +} +func (v *valueGoCaller) string() unistring.String { + return v.stringValue.string() +} +func (v *valueGoCaller) ToString() Value { + return v.stringValue +} +func (v *valueGoCaller) String() string { + return string(v.stringValue) +} +func (v *valueGoCaller) ToFloat() float64 { + return float64(v.value) +} +func (v *valueGoCaller) ToNumber() Value { + return valueInt(v.value) +} +func (v *valueGoCaller) ToBoolean() bool { + return true +} +func (v *valueGoCaller) ToObject(r *Runtime) *Object { + r.typeErrorResult(true, "Cannot convert "+string(v.stringValue)+" to object") + return nil +} +func (v *valueGoCaller) SameAs(other Value) bool { + _, same := other.(*valueGoCaller) + return same +} +func (v *valueGoCaller) Equals(other Value) bool { + return v.value == other.ToInteger() +} +func (v *valueGoCaller) StrictEquals(other Value) bool { + o, same := other.(*valueGoCaller) + return same && o.value == v.value +} +func (v *valueGoCaller) Export() interface{} { + return v +} +func (v *valueGoCaller) ExportType() reflect.Type { + return reflectTypeGoCaller +} +func (v *valueGoCaller) baseObject(r *Runtime) *Object { + return nil +} +func (v *valueGoCaller) hash(hasher *maphash.Hash) uint64 { + return v.hashValue +} diff --git a/runtime.go b/runtime.go index 32593dc7..3aee04fd 100644 --- a/runtime.go +++ b/runtime.go @@ -464,6 +464,7 @@ func (r *Runtime) init() { r.initMap() r.initSet() r.initPromise() + r.initCaller() r.global.thrower = r.newNativeFunc(r.builtin_thrower, nil, "", nil, 0) r.global.throwerProperty = &valueProperty{ @@ -2011,6 +2012,11 @@ func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value typ := value.Type() nargs := typ.NumIn() var in []reflect.Value + var style uint64 + if len(call.Arguments) > 0 && call.Arguments[0].ExportType() == reflectTypeGoCaller { + style = uint64(call.Arguments[0].ToInteger()) + call.Arguments = call.Arguments[1:] + } if l := len(call.Arguments); l < nargs { // fill missing arguments with zero values @@ -2053,41 +2059,64 @@ func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value in[i] = v } + if style&4 != 0 { + promise, _, _ := r.NewPromise() + go func() { + value.Call(in) + }() + return r.ToValue(promise) + } out := value.Call(in) if len(out) == 0 { return _undefined } - if last := out[len(out)-1]; last.Type() == reflectTypeError { - if !last.IsNil() { - err := last.Interface().(error) - if _, ok := err.(*Exception); ok { - panic(err) - } - if isUncatchableException(err) { - panic(err) + if style&1 == 0 { + if last := out[len(out)-1]; last.Type() == reflectTypeError { + if !last.IsNil() { + err := last.Interface().(error) + if _, ok := err.(*Exception); ok { + panic(err) + } + if isUncatchableException(err) { + panic(err) + } + panic(r.NewGoError(err)) } - panic(r.NewGoError(err)) + out = out[:len(out)-1] } - out = out[:len(out)-1] } switch len(out) { case 0: return _undefined case 1: + if style&2 != 0 { + return r.toValue64(out[0].Interface()) + } return r.ToValue(out[0].Interface()) default: s := make([]interface{}, len(out)) for i, v := range out { s[i] = v.Interface() } - return r.ToValue(s) } } } - +func (r *Runtime) toValue64(v interface{}) Value { + switch i := v.(type) { + case int64: + return r.ToValue(Int64(i)) + case int: + return r.ToValue(Int64(i)) + case uint64: + return r.ToValue(Uint64(i)) + case uint: + return r.ToValue(Uint64(i)) + } + return r.ToValue(v) +} func (r *Runtime) toReflectValue(v Value, dst reflect.Value, ctx *objectExportCtx) error { typ := dst.Type() diff --git a/runtime_wrapReflectFunc_test.go b/runtime_wrapReflectFunc_test.go new file mode 100644 index 00000000..0025d839 --- /dev/null +++ b/runtime_wrapReflectFunc_test.go @@ -0,0 +1,97 @@ +package goja_test + +import ( + "errors" + "fmt" + "math" + "testing" + + "github.com/dop251/goja" +) + +func TestWrapReflectFunc(t *testing.T) { + vm := goja.New() + vm.Set(`println`, func(vals ...interface{}) { + fmt.Println(vals...) + }) + vm.Set(`newError`, func(str string) error { + return errors.New(str) + }) + vm.Set(`getInt64`, func() int64 { + return math.MaxInt64 + }) + vm.Set(`setInt64`, func(v int64) { + if v != math.MaxInt64 { + t.Errorf(`int64 want %v, but got %v`, int64(math.MaxInt64), v) + t.FailNow() + } + }) + vm.Set(`getUint64`, func() uint64 { + return math.MaxUint64 + }) + vm.Set(`setUint64`, func(v uint64) { + if v != math.MaxUint64 { + t.Errorf(`uint64 want %v, but got %v`, uint64(math.MaxUint64), v) + t.FailNow() + } + }) + vm.Set(`getInt64s`, func() []int64 { + return []int64{1, math.MaxInt64} + }) + vm.Set(`failMessage`, func(args ...interface{}) { + t.Error(args) + t.FailNow() + }) + + vm.RunScript(`test.js`, ` +function abc(){ + setInt64(getInt64(GoNumber)) + if(getInt64(GoNumber) != '`+fmt.Sprint(int64(math.MaxInt64))+`'){ + failMessage('getInt64') + } + + setUint64(getUint64(GoRawNumber)) + if(getUint64(GoNumber).toString() != '`+fmt.Sprint(uint64(math.MaxUint64))+`'){ + failMessage('getUint64 got',getUint64(GoNumber),', but want '+'`+fmt.Sprint(uint64(math.MaxUint64))+`') + } + return 1 +} +function err(){ + return newError(GoRaw,"ok") +} +function asyncErr(){ + const v= newError(GoAsyncRaw,"async") + println(v.then) +}`) + var call goja.Callable + call, _ = goja.AssertFunction(vm.Get(`abc`)) + v, e := call(goja.Undefined()) + if e != nil { + t.Errorf(`js abc() err: %s`, e.Error()) + t.FailNow() + } + val := v.Export().(int64) + if val != 1 { + t.Errorf(`js abc() return %v, but want 1`, val) + t.FailNow() + } + call, _ = goja.AssertFunction(vm.Get(`err`)) + v, e = call(goja.Undefined()) + if e != nil { + t.Errorf(`js err() err: %s`, e.Error()) + t.FailNow() + } + v0 := v.Export().(error) + if v0.Error() != "ok" { + t.Errorf(`js err() want "ok", but got %s`, v0.Error()) + t.FailNow() + } + + // call, _ = goja.AssertFunction(vm.Get(`asyncErr`)) + // _, e = call(goja.Undefined()) + // if e != nil { + // t.Errorf(`js asyncErr() err: %s`, e.Error()) + // t.FailNow() + // } + +} From 8cea683e0320aa20f9269a3395f666718098e799 Mon Sep 17 00:00:00 2001 From: zuiwuchang Date: Sat, 18 Mar 2023 11:57:16 +0800 Subject: [PATCH 2/2] promise for js call gofunc --- builtin_caller.go | 64 +++++++++++++- runtime.go | 111 ++++++++++++++--------- runtime_wrapReflectFunc_test.go | 150 ++++++++++++++++++++++++++++---- 3 files changed, 266 insertions(+), 59 deletions(-) diff --git a/builtin_caller.go b/builtin_caller.go index 80d0cd21..64525dfe 100644 --- a/builtin_caller.go +++ b/builtin_caller.go @@ -4,6 +4,7 @@ import ( "hash/maphash" "reflect" "strconv" + "unsafe" "github.com/dop251/goja/unistring" ) @@ -60,6 +61,51 @@ func (r *Runtime) initCaller() { o._putProp("GoAsyncRawNumber", _GoAsyncRawNumber, false, false, true) } +// Set up the runner so that calling go functions asynchronously can called resolve/reject on the loop +func (r *Runtime) SetRunOnLoop(runner func(f func(*Runtime))) { + r.runOnLoop = runner +} + +// called f on the loop, must call SetRunOnLoop to set the runner before +func (r *Runtime) RunOnLoop(f func(*Runtime)) { + r.runOnLoop(f) +} + +func toValue64(v interface{}) interface{} { + if strconv.IntSize < 64 { + switch i := v.(type) { + case int64: + return Int64(i) + case uint64: + return Uint64(i) + case []int64: + return *(*[]Int64)(unsafe.Pointer(&i)) + case []uint64: + return *(*[]Uint64)(unsafe.Pointer(&i)) + } + } else { + switch i := v.(type) { + case int64: + return Int64(i) + case int: + return Int64(i) + case uint64: + return Uint64(i) + case uint: + return Uint64(i) + case []int64: + return *(*[]Int64)(unsafe.Pointer(&i)) + case []int: + return *(*[]Int64)(unsafe.Pointer(&i)) + case []uint64: + return *(*[]Uint64)(unsafe.Pointer(&i)) + case []uint: + return *(*[]Uint64)(unsafe.Pointer(&i)) + } + } + return v +} + type Int64 int64 type Uint64 uint64 @@ -111,7 +157,7 @@ func (v Int64) Mod(o Int64) Int64 { func (v Uint64) Mod(o Uint64) Uint64 { return v % o } -func (v Int64) ABS() Int64 { +func (v Int64) Abs() Int64 { if v < 0 { return -v } @@ -156,6 +202,22 @@ func (v Int64) Rsh(n int) Int64 { func (v Uint64) Rsh(n int) Uint64 { return v >> n } +func (v Int64) Cmp(o Int64) int { + if v < o { + return -1 + } else if v > o { + return 1 + } + return 0 +} +func (v Uint64) Cmp(o Uint64) int { + if v < o { + return -1 + } else if v > o { + return 1 + } + return 0 +} type valueGoCaller struct { value int64 diff --git a/runtime.go b/runtime.go index 3aee04fd..29442274 100644 --- a/runtime.go +++ b/runtime.go @@ -196,6 +196,7 @@ type Runtime struct { promiseRejectionTracker PromiseRejectionTracker asyncContextTracker AsyncContextTracker + runOnLoop func(func(*Runtime)) } type StackFrame struct { @@ -2060,63 +2061,91 @@ func (r *Runtime) wrapReflectFunc(value reflect.Value) func(FunctionCall) Value } if style&4 != 0 { - promise, _, _ := r.NewPromise() + runner := r.runOnLoop + if runner == nil { + panic(r.NewGoError(errors.New(`runner nil, please call Runtime.SetRunOnLoop to set.`))) + } + promise, resolve, reject := r.NewPromise() go func() { - value.Call(in) + out, err := func() (out []reflect.Value, err interface{}) { + defer func() { + if x := recover(); x != nil { + err = x + } + }() + out = value.Call(in) + return + }() + if err != nil { + reject(err) + return + } + value, err := r.wrapReflectFuncReturn(style, out) + if err == nil { + resolve(value) + } else { + reject(err) + } }() return r.ToValue(promise) } out := value.Call(in) - if len(out) == 0 { - return _undefined + value, err := r.wrapReflectFuncReturn(style, out) + if err != nil { + panic(err) } + return value + } +} +func (r *Runtime) wrapReflectFuncReturn(style uint64, out []reflect.Value) (value Value, e interface{}) { + if len(out) == 0 { + value = _undefined + return + } - if style&1 == 0 { - if last := out[len(out)-1]; last.Type() == reflectTypeError { - if !last.IsNil() { - err := last.Interface().(error) - if _, ok := err.(*Exception); ok { - panic(err) - } - if isUncatchableException(err) { - panic(err) - } - panic(r.NewGoError(err)) + if style&1 == 0 { + if last := out[len(out)-1]; last.Type() == reflectTypeError { + if !last.IsNil() { + err := last.Interface().(error) + if _, ok := err.(*Exception); ok { + e = err + return } - out = out[:len(out)-1] + if isUncatchableException(err) { + e = err + return + } + e = r.NewGoError(err) + return } + out = out[:len(out)-1] } - - switch len(out) { - case 0: - return _undefined - case 1: - if style&2 != 0 { - return r.toValue64(out[0].Interface()) - } - return r.ToValue(out[0].Interface()) - default: - s := make([]interface{}, len(out)) + } + switch len(out) { + case 0: + value = _undefined + case 1: + if style&2 == 0 { + value = r.ToValue(out[0].Interface()) + } else { + value = r.ToValue(toValue64(out[0].Interface())) + } + default: + s := make([]interface{}, len(out)) + if style&2 == 0 { for i, v := range out { s[i] = v.Interface() } - return r.ToValue(s) + } else { + for i, v := range out { + s[i] = toValue64(v.Interface()) + } } + value = r.ToValue(s) } + return } -func (r *Runtime) toValue64(v interface{}) Value { - switch i := v.(type) { - case int64: - return r.ToValue(Int64(i)) - case int: - return r.ToValue(Int64(i)) - case uint64: - return r.ToValue(Uint64(i)) - case uint: - return r.ToValue(Uint64(i)) - } - return r.ToValue(v) -} + func (r *Runtime) toReflectValue(v Value, dst reflect.Value, ctx *objectExportCtx) error { typ := dst.Type() diff --git a/runtime_wrapReflectFunc_test.go b/runtime_wrapReflectFunc_test.go index 0025d839..3f50ce0d 100644 --- a/runtime_wrapReflectFunc_test.go +++ b/runtime_wrapReflectFunc_test.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "math" + "strconv" + "sync" "testing" "github.com/dop251/goja" @@ -11,6 +13,28 @@ import ( func TestWrapReflectFunc(t *testing.T) { vm := goja.New() + done := make(chan struct{}) + ch := make(chan func(*goja.Runtime)) + var wait sync.WaitGroup + wait.Add(1) + go func() { + defer wait.Done() + select { + case <-done: + return + case f := <-ch: + f(vm) + } + }() + vm.SetRunOnLoop(func(f func(vm *goja.Runtime)) { + select { + case <-done: + case ch <- f: + } + }) + vm.Set(`close`, func() { + close(done) + }) vm.Set(`println`, func(vals ...interface{}) { fmt.Println(vals...) }) @@ -20,6 +44,9 @@ func TestWrapReflectFunc(t *testing.T) { vm.Set(`getInt64`, func() int64 { return math.MaxInt64 }) + vm.Set(`getInt64s`, func() []int64 { + return []int64{math.MaxInt64, -100} + }) vm.Set(`setInt64`, func(v int64) { if v != math.MaxInt64 { t.Errorf(`int64 want %v, but got %v`, int64(math.MaxInt64), v) @@ -29,31 +56,115 @@ func TestWrapReflectFunc(t *testing.T) { vm.Set(`getUint64`, func() uint64 { return math.MaxUint64 }) + vm.Set(`getUint64s`, func() []uint64 { + return []uint64{math.MaxUint64, 100} + }) vm.Set(`setUint64`, func(v uint64) { if v != math.MaxUint64 { t.Errorf(`uint64 want %v, but got %v`, uint64(math.MaxUint64), v) t.FailNow() } }) - vm.Set(`getInt64s`, func() []int64 { - return []int64{1, math.MaxInt64} + vm.Set(`get64`, func() (int64, uint64) { + return int64(math.MaxInt64), uint64(math.MaxUint64) }) vm.Set(`failMessage`, func(args ...interface{}) { - t.Error(args) + t.Error(args...) t.FailNow() }) - + vm.Set(`parseInt64`, func(s string) (goja.Int64, error) { + v, e := strconv.ParseInt(s, 10, 64) + if e != nil { + return 0, e + } + return goja.Int64(v), nil + }) + vm.Set(`parseUint64`, func(s string) (goja.Int64, error) { + v, e := strconv.ParseInt(s, 10, 64) + if e != nil { + return 0, e + } + return goja.Int64(v), nil + }) vm.RunScript(`test.js`, ` +const MaxInt64='`+strconv.FormatInt(int64(math.MaxInt64), 10)+`' +const MaxUint64='`+strconv.FormatUint(uint64(math.MaxUint64), 10)+`' +function assertEqual(want,actual,label){ + if(want!=actual){ + failMessage(label,'want',want, ', but get',actual) + } +} + function abc(){ + // int64 setInt64(getInt64(GoNumber)) - if(getInt64(GoNumber) != '`+fmt.Sprint(int64(math.MaxInt64))+`'){ - failMessage('getInt64') - } + assertEqual(MaxInt64,getInt64(GoNumber).toString(),'getInt64') + assertEqual(getInt64(GoNumber),getInt64(GoNumber),'getInt64 ==') + let v = parseInt64(GoNumber,"2") + assertEqual(2,v,'getInt64 ==') + assertEqual(3,v.Add(1),'Int64 add') + assertEqual(1,v.Sub(1),'Int64 sub') + assertEqual(-3,v.Sub(5),'Int64 sub5') + assertEqual(6,v.Mul(3),'Int64 mul') + assertEqual(3,v.Mul(3).Div(2),'Int64 div') + assertEqual(2,v.Mul(5).Div(4),'Int64 mod') + assertEqual(-2,v.Neg(),'Int64 neg') + assertEqual(2,v.Neg().Abs(),'Int64 abs') + assertEqual(2,v.And(3),'Int64 and') + assertEqual(6,v.Or(4),'Int64 or') + assertEqual(4,v.Xor(6),'Int64 xor') + assertEqual(2,v.Not().Not(),'Int64 not') + assertEqual(8,v.Lsh(2),'Int64 left shift') + assertEqual(1,v.Rsh(1),'Int64 right shift') + assertEqual(0,v.Cmp(2),'Int64 cmp 2') + assertEqual(-1,v.Cmp(4),'Int64 cmp 4') + assertEqual(1,v.Cmp(0),'Int64 cmp 0') + + // uint64 setUint64(getUint64(GoRawNumber)) - if(getUint64(GoNumber).toString() != '`+fmt.Sprint(uint64(math.MaxUint64))+`'){ - failMessage('getUint64 got',getUint64(GoNumber),', but want '+'`+fmt.Sprint(uint64(math.MaxUint64))+`') - } + assertEqual(MaxUint64,getUint64(GoNumber).toString(),'getUint64') + assertEqual(getUint64(GoNumber),getUint64(GoNumber),'getUint64 ==') + + v = parseUint64(GoNumber,"2") + assertEqual(2,v,'getInt64 ==') + assertEqual(3,v.Add(1),'Uint64 add') + assertEqual(1,v.Sub(1),'Uint64 sub') + assertEqual(-3,v.Sub(5),'Uint64 sub5') + assertEqual(6,v.Mul(3),'Uint64 mul') + assertEqual(3,v.Mul(3).Div(2),'Uint64 div') + assertEqual(2,v.Mul(5).Div(4),'Uint64 mod') + assertEqual(2,v.And(3),'Uint64 and') + assertEqual(6,v.Or(4),'Uint64 or') + assertEqual(4,v.Xor(6),'Uint64 xor') + assertEqual(2,v.Not().Not(),'Uint64 not') + assertEqual(8,v.Lsh(2),'Uint64 left shift') + assertEqual(1,v.Rsh(1),'Uint64 right shift') + assertEqual(0,v.Cmp(2),'Uint64 cmp 2') + assertEqual(-1,v.Cmp(4),'Uint64 cmp 4') + assertEqual(1,v.Cmp(0),'Uint64 cmp 0') + + // slice 64 + const [i64,u64] = get64(GoRawNumber) + assertEqual(MaxInt64,i64.toString(),'i64') + assertEqual(MaxUint64,u64.toString(),'u64') + + let vals = getInt64s(GoRawNumber) + assertEqual(MaxInt64,vals[0].toString(),'getInt64s') + assertEqual(-100,vals[1],'getInt64s -100') + vals.push(vals[0]) + assertEqual(MaxInt64,vals[0].toString(),'getInt64s') + assertEqual(-100,vals[1],'getInt64s -100') + assertEqual(MaxInt64,vals[2].toString(),'getInt64s 2') + + vals = getUint64s(GoRawNumber) + assertEqual(MaxUint64,vals[0].toString(),'getUint64s') + assertEqual(100,vals[1],'getUint64s 100') + vals.push(vals[0]) + assertEqual(MaxUint64,vals[0].toString(),'getUint64s') + assertEqual(100,vals[1],'getUint64s 100') + assertEqual(MaxUint64,vals[2].toString(),'getUint64s 2') + return 1 } function err(){ @@ -61,8 +172,12 @@ function err(){ } function asyncErr(){ const v= newError(GoAsyncRaw,"async") - println(v.then) + v.then((e)=>{ + assertEqual(e.Error(),"async","then") + close() + }) }`) + var call goja.Callable call, _ = goja.AssertFunction(vm.Get(`abc`)) v, e := call(goja.Undefined()) @@ -87,11 +202,12 @@ function asyncErr(){ t.FailNow() } - // call, _ = goja.AssertFunction(vm.Get(`asyncErr`)) - // _, e = call(goja.Undefined()) - // if e != nil { - // t.Errorf(`js asyncErr() err: %s`, e.Error()) - // t.FailNow() - // } + call, _ = goja.AssertFunction(vm.Get(`asyncErr`)) + _, e = call(goja.Undefined()) + if e != nil { + t.Errorf(`js asyncErr() err: %s`, e.Error()) + t.FailNow() + } + wait.Wait() }