object_dynamic_test.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. package goja
  2. import (
  3. "sync"
  4. "testing"
  5. )
  6. type testDynObject struct {
  7. r *Runtime
  8. m map[string]Value
  9. }
  10. func (t *testDynObject) Get(key string) Value {
  11. return t.m[key]
  12. }
  13. func (t *testDynObject) Set(key string, val Value) bool {
  14. t.m[key] = val
  15. return true
  16. }
  17. func (t *testDynObject) Has(key string) bool {
  18. _, exists := t.m[key]
  19. return exists
  20. }
  21. func (t *testDynObject) Delete(key string) bool {
  22. delete(t.m, key)
  23. return true
  24. }
  25. func (t *testDynObject) Keys() []string {
  26. keys := make([]string, 0, len(t.m))
  27. for k := range t.m {
  28. keys = append(keys, k)
  29. }
  30. return keys
  31. }
  32. type testDynArray struct {
  33. r *Runtime
  34. a []Value
  35. }
  36. func (t *testDynArray) Len() int {
  37. return len(t.a)
  38. }
  39. func (t *testDynArray) Get(idx int) Value {
  40. if idx < 0 {
  41. idx += len(t.a)
  42. }
  43. if idx >= 0 && idx < len(t.a) {
  44. return t.a[idx]
  45. }
  46. return nil
  47. }
  48. func (t *testDynArray) expand(newLen int) {
  49. if newLen > cap(t.a) {
  50. a := make([]Value, newLen)
  51. copy(a, t.a)
  52. t.a = a
  53. } else {
  54. t.a = t.a[:newLen]
  55. }
  56. }
  57. func (t *testDynArray) Set(idx int, val Value) bool {
  58. if idx < 0 {
  59. idx += len(t.a)
  60. }
  61. if idx < 0 {
  62. return false
  63. }
  64. if idx >= len(t.a) {
  65. t.expand(idx + 1)
  66. }
  67. t.a[idx] = val
  68. return true
  69. }
  70. func (t *testDynArray) SetLen(i int) bool {
  71. if i > len(t.a) {
  72. t.expand(i)
  73. return true
  74. }
  75. if i < 0 {
  76. return false
  77. }
  78. if i < len(t.a) {
  79. tail := t.a[i:len(t.a)]
  80. for j := range tail {
  81. tail[j] = nil
  82. }
  83. t.a = t.a[:i]
  84. }
  85. return true
  86. }
  87. func TestDynamicObject(t *testing.T) {
  88. vm := New()
  89. dynObj := &testDynObject{
  90. r: vm,
  91. m: make(map[string]Value),
  92. }
  93. o := vm.NewDynamicObject(dynObj)
  94. vm.Set("o", o)
  95. vm.testScriptWithTestLibX(`
  96. assert(o instanceof Object, "instanceof Object");
  97. assert(o === o, "self equality");
  98. assert(o !== {}, "non-equality");
  99. o.test = 42;
  100. assert("test" in o, "'test' in o");
  101. assert(deepEqual(Object.getOwnPropertyDescriptor(o, "test"), {value: 42, writable: true, enumerable: true, configurable: true}), "prop desc");
  102. assert.throws(TypeError, function() {
  103. "use strict";
  104. Object.defineProperty(o, "test1", {value: 0, writable: false, enumerable: false, configurable: true});
  105. }, "define prop");
  106. var keys = [];
  107. for (var key in o) {
  108. keys.push(key);
  109. }
  110. assert(compareArray(keys, ["test"]), "for-in");
  111. assert(delete o.test, "delete");
  112. assert(!("test" in o), "'test' in o after delete");
  113. assert("__proto__" in o, "__proto__ in o");
  114. assert.sameValue(o.__proto__, Object.prototype, "__proto__");
  115. o.__proto__ = null;
  116. assert(!("__proto__" in o), "__proto__ in o after setting to null");
  117. `, _undefined, t)
  118. }
  119. func TestDynamicObjectCustomProto(t *testing.T) {
  120. vm := New()
  121. m := make(map[string]Value)
  122. dynObj := &testDynObject{
  123. r: vm,
  124. m: m,
  125. }
  126. o := vm.NewDynamicObject(dynObj)
  127. vm.Set("o", o)
  128. vm.testScriptWithTestLib(`
  129. var proto = {
  130. valueOf: function() {
  131. return this.num;
  132. }
  133. };
  134. proto[Symbol.toStringTag] = "GoObject";
  135. Object.setPrototypeOf(o, proto);
  136. o.num = 41;
  137. assert(o instanceof Object, "instanceof");
  138. assert.sameValue(o+1, 42);
  139. assert.sameValue(o.toString(), "[object GoObject]");
  140. `, _undefined, t)
  141. if v := m["num"]; v.Export() != int64(41) {
  142. t.Fatal(v)
  143. }
  144. }
  145. func TestDynamicArray(t *testing.T) {
  146. vm := New()
  147. dynObj := &testDynArray{
  148. r: vm,
  149. }
  150. a := vm.NewDynamicArray(dynObj)
  151. vm.Set("a", a)
  152. vm.testScriptWithTestLibX(`
  153. assert(a instanceof Array, "instanceof Array");
  154. assert(a instanceof Object, "instanceof Object");
  155. assert(a === a, "self equality");
  156. assert(a !== [], "non-equality");
  157. assert(Array.isArray(a), "isArray()");
  158. assert("length" in a, "length in a");
  159. assert.sameValue(a.length, 0, "len == 0");
  160. assert.sameValue(a[0], undefined, "a[0] (1)");
  161. a[0] = 0;
  162. assert.sameValue(a[0], 0, "a[0] (2)");
  163. assert.sameValue(a.length, 1, "length");
  164. assert(deepEqual(Object.getOwnPropertyDescriptor(a, 0), {value: 0, writable: true, enumerable: true, configurable: true}), "prop desc");
  165. assert(deepEqual(Object.getOwnPropertyDescriptor(a, "length"), {value: 1, writable: true, enumerable: false, configurable: false}), "length prop desc");
  166. assert("__proto__" in a, "__proto__ in a");
  167. assert.sameValue(a.__proto__, Array.prototype, "__proto__");
  168. assert(compareArray(Object.keys(a), ["0"]), "Object.keys()");
  169. assert(compareArray(Reflect.ownKeys(a), ["0", "length"]), "Reflect.ownKeys()");
  170. a.length = 2;
  171. assert.sameValue(a.length, 2, "length after grow");
  172. assert.sameValue(a[1], undefined, "a[1]");
  173. a[1] = 1;
  174. assert.sameValue(a[1], 1, "a[1] after set");
  175. a.length = 1;
  176. assert.sameValue(a.length, 1, "length after shrink");
  177. assert.sameValue(a[1], undefined, "a[1] after shrink");
  178. a.length = 2;
  179. assert.sameValue(a.length, 2, "length after shrink and grow");
  180. assert.sameValue(a[1], undefined, "a[1] after grow");
  181. a[0] = 3; a[1] = 1; a[2] = 2;
  182. assert.sameValue(a.length, 3);
  183. var keys = [];
  184. for (var key in a) {
  185. keys.push(key);
  186. }
  187. assert(compareArray(keys, ["0","1","2"]), "for-in");
  188. var vals = [];
  189. for (var val of a) {
  190. vals.push(val);
  191. }
  192. assert(compareArray(vals, [3,1,2]), "for-of");
  193. a.sort();
  194. assert(compareArray(a, [1,2,3]), "sort: "+a);
  195. assert.sameValue(a[-1], 3);
  196. assert.sameValue(a[-4], undefined);
  197. assert.throws(TypeError, function() {
  198. "use strict";
  199. delete a.length;
  200. }, "delete length");
  201. assert.throws(TypeError, function() {
  202. "use strict";
  203. a.test = true;
  204. }, "set string prop");
  205. assert.throws(TypeError, function() {
  206. "use strict";
  207. Object.defineProperty(a, 0, {value: 0, writable: false, enumerable: false, configurable: true});
  208. }, "define prop");
  209. `, _undefined, t)
  210. }
  211. type testSharedDynObject struct {
  212. sync.RWMutex
  213. m map[string]Value
  214. }
  215. func (t *testSharedDynObject) Get(key string) Value {
  216. t.RLock()
  217. val := t.m[key]
  218. t.RUnlock()
  219. return val
  220. }
  221. func (t *testSharedDynObject) Set(key string, val Value) bool {
  222. t.Lock()
  223. t.m[key] = val
  224. t.Unlock()
  225. return true
  226. }
  227. func (t *testSharedDynObject) Has(key string) bool {
  228. t.RLock()
  229. _, exists := t.m[key]
  230. t.RUnlock()
  231. return exists
  232. }
  233. func (t *testSharedDynObject) Delete(key string) bool {
  234. t.Lock()
  235. delete(t.m, key)
  236. t.Unlock()
  237. return true
  238. }
  239. func (t *testSharedDynObject) Keys() []string {
  240. t.RLock()
  241. keys := make([]string, 0, len(t.m))
  242. for k := range t.m {
  243. keys = append(keys, k)
  244. }
  245. t.RUnlock()
  246. return keys
  247. }
  248. func TestSharedDynamicObject(t *testing.T) {
  249. dynObj := &testSharedDynObject{m: make(map[string]Value, 10000)}
  250. o := NewSharedDynamicObject(dynObj)
  251. ch := make(chan error, 1)
  252. go func() {
  253. vm := New()
  254. vm.Set("o", o)
  255. _, err := vm.RunString(`
  256. for (let i = 0; i < 10000; i++) {
  257. o[i] = i;
  258. }
  259. `)
  260. ch <- err
  261. }()
  262. vm := New()
  263. vm.Set("o", o)
  264. _, err := vm.RunString(`
  265. for (let i = 0; i < 10000; i++) {
  266. o[i] = i+1;
  267. }
  268. `)
  269. if err != nil {
  270. t.Fatal(err)
  271. }
  272. err = <-ch
  273. if err != nil {
  274. t.Fatal(err)
  275. }
  276. }
  277. type testSharedDynArray struct {
  278. sync.RWMutex
  279. a []Value
  280. }
  281. func (t *testSharedDynArray) Len() int {
  282. t.RLock()
  283. l := len(t.a)
  284. t.RUnlock()
  285. return l
  286. }
  287. func (t *testSharedDynArray) Get(idx int) Value {
  288. t.RLock()
  289. defer t.RUnlock()
  290. if idx < 0 {
  291. idx += len(t.a)
  292. }
  293. if idx >= 0 && idx < len(t.a) {
  294. return t.a[idx]
  295. }
  296. return nil
  297. }
  298. func (t *testSharedDynArray) expand(newLen int) {
  299. if newLen > cap(t.a) {
  300. a := make([]Value, newLen)
  301. copy(a, t.a)
  302. t.a = a
  303. } else {
  304. t.a = t.a[:newLen]
  305. }
  306. }
  307. func (t *testSharedDynArray) Set(idx int, val Value) bool {
  308. t.Lock()
  309. defer t.Unlock()
  310. if idx < 0 {
  311. idx += len(t.a)
  312. }
  313. if idx < 0 {
  314. return false
  315. }
  316. if idx >= len(t.a) {
  317. t.expand(idx + 1)
  318. }
  319. t.a[idx] = val
  320. return true
  321. }
  322. func (t *testSharedDynArray) SetLen(i int) bool {
  323. t.Lock()
  324. defer t.Unlock()
  325. if i > len(t.a) {
  326. t.expand(i)
  327. return true
  328. }
  329. if i < 0 {
  330. return false
  331. }
  332. if i < len(t.a) {
  333. tail := t.a[i:len(t.a)]
  334. for j := range tail {
  335. tail[j] = nil
  336. }
  337. t.a = t.a[:i]
  338. }
  339. return true
  340. }
  341. func TestSharedDynamicArray(t *testing.T) {
  342. dynObj := &testSharedDynArray{a: make([]Value, 10000)}
  343. o := NewSharedDynamicArray(dynObj)
  344. ch := make(chan error, 1)
  345. go func() {
  346. vm := New()
  347. vm.Set("o", o)
  348. _, err := vm.RunString(`
  349. for (let i = 0; i < 10000; i++) {
  350. o[i] = i;
  351. }
  352. `)
  353. ch <- err
  354. }()
  355. vm := New()
  356. vm.Set("o", o)
  357. _, err := vm.RunString(`
  358. for (let i = 0; i < 10000; i++) {
  359. o[i] = i+1;
  360. }
  361. `)
  362. if err != nil {
  363. t.Fatal(err)
  364. }
  365. err = <-ch
  366. if err != nil {
  367. t.Fatal(err)
  368. }
  369. }