123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- package goja
- import (
- "sync"
- "testing"
- )
- type testDynObject struct {
- r *Runtime
- m map[string]Value
- }
- func (t *testDynObject) Get(key string) Value {
- return t.m[key]
- }
- func (t *testDynObject) Set(key string, val Value) bool {
- t.m[key] = val
- return true
- }
- func (t *testDynObject) Has(key string) bool {
- _, exists := t.m[key]
- return exists
- }
- func (t *testDynObject) Delete(key string) bool {
- delete(t.m, key)
- return true
- }
- func (t *testDynObject) Keys() []string {
- keys := make([]string, 0, len(t.m))
- for k := range t.m {
- keys = append(keys, k)
- }
- return keys
- }
- type testDynArray struct {
- r *Runtime
- a []Value
- }
- func (t *testDynArray) Len() int {
- return len(t.a)
- }
- func (t *testDynArray) Get(idx int) Value {
- if idx < 0 {
- idx += len(t.a)
- }
- if idx >= 0 && idx < len(t.a) {
- return t.a[idx]
- }
- return nil
- }
- func (t *testDynArray) expand(newLen int) {
- if newLen > cap(t.a) {
- a := make([]Value, newLen)
- copy(a, t.a)
- t.a = a
- } else {
- t.a = t.a[:newLen]
- }
- }
- func (t *testDynArray) Set(idx int, val Value) bool {
- if idx < 0 {
- idx += len(t.a)
- }
- if idx < 0 {
- return false
- }
- if idx >= len(t.a) {
- t.expand(idx + 1)
- }
- t.a[idx] = val
- return true
- }
- func (t *testDynArray) SetLen(i int) bool {
- if i > len(t.a) {
- t.expand(i)
- return true
- }
- if i < 0 {
- return false
- }
- if i < len(t.a) {
- tail := t.a[i:len(t.a)]
- for j := range tail {
- tail[j] = nil
- }
- t.a = t.a[:i]
- }
- return true
- }
- func TestDynamicObject(t *testing.T) {
- vm := New()
- dynObj := &testDynObject{
- r: vm,
- m: make(map[string]Value),
- }
- o := vm.NewDynamicObject(dynObj)
- vm.Set("o", o)
- vm.testScriptWithTestLibX(`
- assert(o instanceof Object, "instanceof Object");
- assert(o === o, "self equality");
- assert(o !== {}, "non-equality");
- o.test = 42;
- assert("test" in o, "'test' in o");
- assert(deepEqual(Object.getOwnPropertyDescriptor(o, "test"), {value: 42, writable: true, enumerable: true, configurable: true}), "prop desc");
- assert.throws(TypeError, function() {
- "use strict";
- Object.defineProperty(o, "test1", {value: 0, writable: false, enumerable: false, configurable: true});
- }, "define prop");
- var keys = [];
- for (var key in o) {
- keys.push(key);
- }
- assert(compareArray(keys, ["test"]), "for-in");
- assert(delete o.test, "delete");
- assert(!("test" in o), "'test' in o after delete");
- assert("__proto__" in o, "__proto__ in o");
- assert.sameValue(o.__proto__, Object.prototype, "__proto__");
- o.__proto__ = null;
- assert(!("__proto__" in o), "__proto__ in o after setting to null");
- `, _undefined, t)
- }
- func TestDynamicObjectCustomProto(t *testing.T) {
- vm := New()
- m := make(map[string]Value)
- dynObj := &testDynObject{
- r: vm,
- m: m,
- }
- o := vm.NewDynamicObject(dynObj)
- vm.Set("o", o)
- vm.testScriptWithTestLib(`
- var proto = {
- valueOf: function() {
- return this.num;
- }
- };
- proto[Symbol.toStringTag] = "GoObject";
- Object.setPrototypeOf(o, proto);
- o.num = 41;
- assert(o instanceof Object, "instanceof");
- assert.sameValue(o+1, 42);
- assert.sameValue(o.toString(), "[object GoObject]");
- `, _undefined, t)
- if v := m["num"]; v.Export() != int64(41) {
- t.Fatal(v)
- }
- }
- func TestDynamicArray(t *testing.T) {
- vm := New()
- dynObj := &testDynArray{
- r: vm,
- }
- a := vm.NewDynamicArray(dynObj)
- vm.Set("a", a)
- vm.testScriptWithTestLibX(`
- assert(a instanceof Array, "instanceof Array");
- assert(a instanceof Object, "instanceof Object");
- assert(a === a, "self equality");
- assert(a !== [], "non-equality");
- assert(Array.isArray(a), "isArray()");
- assert("length" in a, "length in a");
- assert.sameValue(a.length, 0, "len == 0");
- assert.sameValue(a[0], undefined, "a[0] (1)");
- a[0] = 0;
- assert.sameValue(a[0], 0, "a[0] (2)");
- assert.sameValue(a.length, 1, "length");
- assert(deepEqual(Object.getOwnPropertyDescriptor(a, 0), {value: 0, writable: true, enumerable: true, configurable: true}), "prop desc");
- assert(deepEqual(Object.getOwnPropertyDescriptor(a, "length"), {value: 1, writable: true, enumerable: false, configurable: false}), "length prop desc");
- assert("__proto__" in a, "__proto__ in a");
- assert.sameValue(a.__proto__, Array.prototype, "__proto__");
- assert(compareArray(Object.keys(a), ["0"]), "Object.keys()");
- assert(compareArray(Reflect.ownKeys(a), ["0", "length"]), "Reflect.ownKeys()");
- a.length = 2;
- assert.sameValue(a.length, 2, "length after grow");
- assert.sameValue(a[1], undefined, "a[1]");
- a[1] = 1;
- assert.sameValue(a[1], 1, "a[1] after set");
- a.length = 1;
- assert.sameValue(a.length, 1, "length after shrink");
- assert.sameValue(a[1], undefined, "a[1] after shrink");
- a.length = 2;
- assert.sameValue(a.length, 2, "length after shrink and grow");
- assert.sameValue(a[1], undefined, "a[1] after grow");
- a[0] = 3; a[1] = 1; a[2] = 2;
- assert.sameValue(a.length, 3);
- var keys = [];
- for (var key in a) {
- keys.push(key);
- }
- assert(compareArray(keys, ["0","1","2"]), "for-in");
- var vals = [];
- for (var val of a) {
- vals.push(val);
- }
- assert(compareArray(vals, [3,1,2]), "for-of");
- a.sort();
- assert(compareArray(a, [1,2,3]), "sort: "+a);
- assert.sameValue(a[-1], 3);
- assert.sameValue(a[-4], undefined);
- assert.throws(TypeError, function() {
- "use strict";
- delete a.length;
- }, "delete length");
- assert.throws(TypeError, function() {
- "use strict";
- a.test = true;
- }, "set string prop");
- assert.throws(TypeError, function() {
- "use strict";
- Object.defineProperty(a, 0, {value: 0, writable: false, enumerable: false, configurable: true});
- }, "define prop");
- `, _undefined, t)
- }
- type testSharedDynObject struct {
- sync.RWMutex
- m map[string]Value
- }
- func (t *testSharedDynObject) Get(key string) Value {
- t.RLock()
- val := t.m[key]
- t.RUnlock()
- return val
- }
- func (t *testSharedDynObject) Set(key string, val Value) bool {
- t.Lock()
- t.m[key] = val
- t.Unlock()
- return true
- }
- func (t *testSharedDynObject) Has(key string) bool {
- t.RLock()
- _, exists := t.m[key]
- t.RUnlock()
- return exists
- }
- func (t *testSharedDynObject) Delete(key string) bool {
- t.Lock()
- delete(t.m, key)
- t.Unlock()
- return true
- }
- func (t *testSharedDynObject) Keys() []string {
- t.RLock()
- keys := make([]string, 0, len(t.m))
- for k := range t.m {
- keys = append(keys, k)
- }
- t.RUnlock()
- return keys
- }
- func TestSharedDynamicObject(t *testing.T) {
- dynObj := &testSharedDynObject{m: make(map[string]Value, 10000)}
- o := NewSharedDynamicObject(dynObj)
- ch := make(chan error, 1)
- go func() {
- vm := New()
- vm.Set("o", o)
- _, err := vm.RunString(`
- for (let i = 0; i < 10000; i++) {
- o[i] = i;
- }
- `)
- ch <- err
- }()
- vm := New()
- vm.Set("o", o)
- _, err := vm.RunString(`
- for (let i = 0; i < 10000; i++) {
- o[i] = i+1;
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- err = <-ch
- if err != nil {
- t.Fatal(err)
- }
- }
- type testSharedDynArray struct {
- sync.RWMutex
- a []Value
- }
- func (t *testSharedDynArray) Len() int {
- t.RLock()
- l := len(t.a)
- t.RUnlock()
- return l
- }
- func (t *testSharedDynArray) Get(idx int) Value {
- t.RLock()
- defer t.RUnlock()
- if idx < 0 {
- idx += len(t.a)
- }
- if idx >= 0 && idx < len(t.a) {
- return t.a[idx]
- }
- return nil
- }
- func (t *testSharedDynArray) expand(newLen int) {
- if newLen > cap(t.a) {
- a := make([]Value, newLen)
- copy(a, t.a)
- t.a = a
- } else {
- t.a = t.a[:newLen]
- }
- }
- func (t *testSharedDynArray) Set(idx int, val Value) bool {
- t.Lock()
- defer t.Unlock()
- if idx < 0 {
- idx += len(t.a)
- }
- if idx < 0 {
- return false
- }
- if idx >= len(t.a) {
- t.expand(idx + 1)
- }
- t.a[idx] = val
- return true
- }
- func (t *testSharedDynArray) SetLen(i int) bool {
- t.Lock()
- defer t.Unlock()
- if i > len(t.a) {
- t.expand(i)
- return true
- }
- if i < 0 {
- return false
- }
- if i < len(t.a) {
- tail := t.a[i:len(t.a)]
- for j := range tail {
- tail[j] = nil
- }
- t.a = t.a[:i]
- }
- return true
- }
- func TestSharedDynamicArray(t *testing.T) {
- dynObj := &testSharedDynArray{a: make([]Value, 10000)}
- o := NewSharedDynamicArray(dynObj)
- ch := make(chan error, 1)
- go func() {
- vm := New()
- vm.Set("o", o)
- _, err := vm.RunString(`
- for (let i = 0; i < 10000; i++) {
- o[i] = i;
- }
- `)
- ch <- err
- }()
- vm := New()
- vm.Set("o", o)
- _, err := vm.RunString(`
- for (let i = 0; i < 10000; i++) {
- o[i] = i+1;
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- err = <-ch
- if err != nil {
- t.Fatal(err)
- }
- }
|