1 package goja
2
3 import (
4 "bytes"
5 "testing"
6 )
7
8 func TestUint16ArrayObject(t *testing.T) {
9 vm := New()
10 buf := vm._newArrayBuffer(vm.global.ArrayBufferPrototype, nil)
11 buf.data = make([]byte, 16)
12 if nativeEndian == littleEndian {
13 buf.data[2] = 0xFE
14 buf.data[3] = 0xCA
15 } else {
16 buf.data[2] = 0xCA
17 buf.data[3] = 0xFE
18 }
19 a := vm.newUint16ArrayObject(buf, 1, 1, nil)
20 v := a.getIdx(valueInt(0), nil)
21 if v != valueInt(0xCAFE) {
22 t.Fatalf("v: %v", v)
23 }
24 }
25
26 func TestArrayBufferGoWrapper(t *testing.T) {
27 vm := New()
28 data := []byte{0xAA, 0xBB}
29 buf := vm.NewArrayBuffer(data)
30 vm.Set("buf", buf)
31 _, err := vm.RunString(`
32 var a = new Uint8Array(buf);
33 if (a.length !== 2 || a[0] !== 0xAA || a[1] !== 0xBB) {
34 throw new Error(a);
35 }
36 `)
37 if err != nil {
38 t.Fatal(err)
39 }
40 ret, err := vm.RunString(`
41 var b = Uint8Array.of(0xCC, 0xDD);
42 b.buffer;
43 `)
44 if err != nil {
45 t.Fatal(err)
46 }
47 buf1 := ret.Export().(ArrayBuffer)
48 data1 := buf1.Bytes()
49 if len(data1) != 2 || data1[0] != 0xCC || data1[1] != 0xDD {
50 t.Fatal(data1)
51 }
52 if buf1.Detached() {
53 t.Fatal("buf1.Detached() returned true")
54 }
55 if !buf1.Detach() {
56 t.Fatal("buf1.Detach() returned false")
57 }
58 if !buf1.Detached() {
59 t.Fatal("buf1.Detached() returned false")
60 }
61 _, err = vm.RunString(`
62 if (b[0] !== undefined) {
63 throw new Error("b[0] !== undefined");
64 }
65 `)
66 if err != nil {
67 t.Fatal(err)
68 }
69 }
70
71 func TestTypedArrayIdx(t *testing.T) {
72 const SCRIPT = `
73 var a = new Uint8Array(1);
74
75 // 32-bit integer overflow, should not panic on 32-bit architectures
76 if (a[4294967297] !== undefined) {
77 throw new Error("4294967297");
78 }
79
80 // Canonical non-integer
81 a["Infinity"] = 8;
82 if (a["Infinity"] !== undefined) {
83 throw new Error("Infinity");
84 }
85 a["NaN"] = 1;
86 if (a["NaN"] !== undefined) {
87 throw new Error("NaN");
88 }
89
90 // Non-canonical integer
91 a["00"] = "00";
92 if (a["00"] !== "00") {
93 throw new Error("00");
94 }
95
96 // Non-canonical non-integer
97 a["1e-3"] = "1e-3";
98 if (a["1e-3"] !== "1e-3") {
99 throw new Error("1e-3");
100 }
101 if (a["0.001"] !== undefined) {
102 throw new Error("0.001");
103 }
104
105 // Negative zero
106 a["-0"] = 88;
107 if (a["-0"] !== undefined) {
108 throw new Error("-0");
109 }
110
111 if (a[0] !== 0) {
112 throw new Error("0");
113 }
114
115 a["9007199254740992"] = 1;
116 if (a["9007199254740992"] !== undefined) {
117 throw new Error("9007199254740992");
118 }
119 a["-9007199254740992"] = 1;
120 if (a["-9007199254740992"] !== undefined) {
121 throw new Error("-9007199254740992");
122 }
123
124 // Safe integer overflow, not canonical (Number("9007199254740993") === 9007199254740992)
125 a["9007199254740993"] = 1;
126 if (a["9007199254740993"] !== 1) {
127 throw new Error("9007199254740993");
128 }
129 a["-9007199254740993"] = 1;
130 if (a["-9007199254740993"] !== 1) {
131 throw new Error("-9007199254740993");
132 }
133
134 // Safe integer overflow, canonical Number("9007199254740994") == 9007199254740994
135 a["9007199254740994"] = 1;
136 if (a["9007199254740994"] !== undefined) {
137 throw new Error("9007199254740994");
138 }
139 a["-9007199254740994"] = 1;
140 if (a["-9007199254740994"] !== undefined) {
141 throw new Error("-9007199254740994");
142 }
143 `
144
145 testScript(SCRIPT, _undefined, t)
146 }
147
148 func TestTypedArraySetDetachedBuffer(t *testing.T) {
149 const SCRIPT = `
150 let sample = new Uint8Array([42]);
151 $DETACHBUFFER(sample.buffer);
152 sample[0] = 1;
153
154 assert.sameValue(sample[0], undefined, 'sample[0] = 1 is undefined');
155 sample['1.1'] = 1;
156 assert.sameValue(sample['1.1'], undefined, 'sample[\'1.1\'] = 1 is undefined');
157 sample['-0'] = 1;
158 assert.sameValue(sample['-0'], undefined, 'sample[\'-0\'] = 1 is undefined');
159 sample['-1'] = 1;
160 assert.sameValue(sample['-1'], undefined, 'sample[\'-1\'] = 1 is undefined');
161 sample['1'] = 1;
162 assert.sameValue(sample['1'], undefined, 'sample[\'1\'] = 1 is undefined');
163 sample['2'] = 1;
164 assert.sameValue(sample['2'], undefined, 'sample[\'2\'] = 1 is undefined');
165 `
166 vm := New()
167 vm.Set("$DETACHBUFFER", func(buf *ArrayBuffer) {
168 buf.Detach()
169 })
170 vm.testScriptWithTestLib(SCRIPT, _undefined, t)
171 }
172
173 func TestTypedArrayDefinePropDetachedBuffer(t *testing.T) {
174 const SCRIPT = `
175 var desc = {
176 value: 0,
177 configurable: false,
178 enumerable: true,
179 writable: true
180 };
181
182 var obj = {
183 valueOf: function() {
184 throw new Error("valueOf() was called");
185 }
186 };
187 let sample = new Uint8Array(42);
188 $DETACHBUFFER(sample.buffer);
189
190 assert.sameValue(
191 Reflect.defineProperty(sample, "0", desc),
192 false,
193 'Reflect.defineProperty(sample, "0", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
194 );
195
196 assert.sameValue(
197 Reflect.defineProperty(sample, "-1", desc),
198 false,
199 'Reflect.defineProperty(sample, "-1", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
200 );
201
202 assert.sameValue(
203 Reflect.defineProperty(sample, "1.1", desc),
204 false,
205 'Reflect.defineProperty(sample, "1.1", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
206 );
207
208 assert.sameValue(
209 Reflect.defineProperty(sample, "-0", desc),
210 false,
211 'Reflect.defineProperty(sample, "-0", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
212 );
213
214 assert.sameValue(
215 Reflect.defineProperty(sample, "2", {
216 configurable: true,
217 enumerable: true,
218 writable: true,
219 value: obj
220 }),
221 false,
222 'Reflect.defineProperty(sample, "2", {configurable: true, enumerable: true, writable: true, value: obj}) must return false'
223 );
224
225 assert.sameValue(
226 Reflect.defineProperty(sample, "3", {
227 configurable: false,
228 enumerable: false,
229 writable: true,
230 value: obj
231 }),
232 false,
233 'Reflect.defineProperty(sample, "3", {configurable: false, enumerable: false, writable: true, value: obj}) must return false'
234 );
235
236 assert.sameValue(
237 Reflect.defineProperty(sample, "4", {
238 writable: false,
239 configurable: false,
240 enumerable: true,
241 value: obj
242 }),
243 false,
244 'Reflect.defineProperty("new TA(42)", "4", {writable: false, configurable: false, enumerable: true, value: obj}) must return false'
245 );
246
247 assert.sameValue(
248 Reflect.defineProperty(sample, "42", desc),
249 false,
250 'Reflect.defineProperty(sample, "42", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
251 );
252
253 assert.sameValue(
254 Reflect.defineProperty(sample, "43", desc),
255 false,
256 'Reflect.defineProperty(sample, "43", {value: 0, configurable: false, enumerable: true, writable: true} ) must return false'
257 );
258
259 assert.sameValue(
260 Reflect.defineProperty(sample, "5", {
261 get: function() {}
262 }),
263 false,
264 'Reflect.defineProperty(sample, "5", {get: function() {}}) must return false'
265 );
266
267 assert.sameValue(
268 Reflect.defineProperty(sample, "6", {
269 configurable: false,
270 enumerable: true,
271 writable: true
272 }),
273 false,
274 'Reflect.defineProperty(sample, "6", {configurable: false, enumerable: true, writable: true}) must return false'
275 );
276 `
277 vm := New()
278 vm.Set("$DETACHBUFFER", func(buf *ArrayBuffer) {
279 buf.Detach()
280 })
281 vm.testScriptWithTestLib(SCRIPT, _undefined, t)
282 }
283
284 func TestTypedArrayDefineProperty(t *testing.T) {
285 const SCRIPT = `
286 var a = new Uint8Array(1);
287
288 assert.throws(TypeError, function() {
289 Object.defineProperty(a, "1", {value: 1});
290 });
291 assert.sameValue(Reflect.defineProperty(a, "1", {value: 1}), false, "1");
292
293 assert.throws(TypeError, function() {
294 Object.defineProperty(a, "Infinity", {value: 8});
295 });
296 assert.sameValue(Reflect.defineProperty(a, "Infinity", {value: 8}), false, "Infinity");
297
298 Object.defineProperty(a, "test", {value: "passed"});
299 assert.sameValue(a.test, "passed", "string property");
300
301 assert.throws(TypeError, function() {
302 Object.defineProperty(a, "0", {value: 1, writable: false});
303 }, "define non-writable");
304
305 assert.throws(TypeError, function() {
306 Object.defineProperty(a, "0", {get() { return 1; }});
307 }, "define accessor");
308
309 var sample = new Uint8Array([42, 42]);
310
311 assert.sameValue(
312 Reflect.defineProperty(sample, "0", {
313 value: 8,
314 configurable: true,
315 enumerable: true,
316 writable: true
317 }),
318 true
319 );
320
321 assert.sameValue(sample[0], 8, "property value was set");
322 let descriptor0 = Object.getOwnPropertyDescriptor(sample, "0");
323 assert.sameValue(descriptor0.value, 8);
324 assert.sameValue(descriptor0.configurable, true, "configurable");
325 assert.sameValue(descriptor0.enumerable, true);
326 assert.sameValue(descriptor0.writable, true);
327 `
328 testScriptWithTestLib(SCRIPT, _undefined, t)
329 }
330
331 func TestTypedArrayGetInvalidIndex(t *testing.T) {
332 const SCRIPT = `
333 var TypedArray = Object.getPrototypeOf(Int8Array);
334 var proto = TypedArray.prototype;
335 Object.defineProperty(proto, "1", {
336 get: function() {
337 throw new Error("OrdinaryGet was called!");
338 }
339 });
340 var a = new Uint8Array(1);
341 assert.sameValue(a[1], undefined);
342 assert.sameValue(a["1"], undefined);
343 `
344 testScriptWithTestLib(SCRIPT, _undefined, t)
345 }
346
347 func TestExportArrayBufferToBytes(t *testing.T) {
348 vm := New()
349 bb := []byte("test")
350 ab := vm.NewArrayBuffer(bb)
351 var b []byte
352 err := vm.ExportTo(vm.ToValue(ab), &b)
353 if err != nil {
354 t.Fatal(err)
355 }
356 if !bytes.Equal(b, bb) {
357 t.Fatal("Not equal")
358 }
359
360 err = vm.ExportTo(vm.ToValue(123), &b)
361 if err == nil {
362 t.Fatal("expected error")
363 }
364 }
365
366 func TestTypedArrayExport(t *testing.T) {
367 vm := New()
368
369 t.Run("uint8", func(t *testing.T) {
370 v, err := vm.RunString("new Uint8Array([1, 2])")
371 if err != nil {
372 t.Fatal(err)
373 }
374 if a, ok := v.Export().([]uint8); ok {
375 if len(a) != 2 || a[0] != 1 || a[1] != 2 {
376 t.Fatal(a)
377 }
378 } else {
379 t.Fatal("Wrong export type")
380 }
381 _, err = vm.RunString(`{
382 let a = new Uint8Array([1, 2]);
383 if (a[0] !== 1 || a[1] !== 2) {
384 throw new Error(a);
385 }
386 }`)
387 if err != nil {
388 t.Fatal(err)
389 }
390 })
391
392 t.Run("uint8-slice", func(t *testing.T) {
393 v, err := vm.RunString(`{
394 const buf = new Uint8Array([1, 2]).buffer;
395 new Uint8Array(buf, 1, 1);
396 }`)
397 if err != nil {
398 t.Fatal(err)
399 }
400 if a, ok := v.Export().([]uint8); ok {
401 if len(a) != 1 || a[0] != 2 {
402 t.Fatal(a)
403 }
404 } else {
405 t.Fatal("Wrong export type")
406 }
407 _, err = vm.RunString(`{
408 let a = new Uint8Array([1, 2]);
409 if (a[0] !== 1 || a[1] !== 2) {
410 throw new Error(a);
411 }
412 }`)
413 if err != nil {
414 t.Fatal(err)
415 }
416 })
417
418 t.Run("int8", func(t *testing.T) {
419 v, err := vm.RunString("new Int8Array([1, -2])")
420 if err != nil {
421 t.Fatal(err)
422 }
423 if a, ok := v.Export().([]int8); ok {
424 if len(a) != 2 || a[0] != 1 || a[1] != -2 {
425 t.Fatal(a)
426 }
427 } else {
428 t.Fatal("Wrong export type")
429 }
430 })
431
432 t.Run("uint16", func(t *testing.T) {
433 v, err := vm.RunString("new Uint16Array([1, 63000])")
434 if err != nil {
435 t.Fatal(err)
436 }
437 if a, ok := v.Export().([]uint16); ok {
438 if len(a) != 2 || a[0] != 1 || a[1] != 63000 {
439 t.Fatal(a)
440 }
441 } else {
442 t.Fatal("Wrong export type")
443 }
444 })
445
446 t.Run("int16", func(t *testing.T) {
447 v, err := vm.RunString("new Int16Array([1, -31000])")
448 if err != nil {
449 t.Fatal(err)
450 }
451 if a, ok := v.Export().([]int16); ok {
452 if len(a) != 2 || a[0] != 1 || a[1] != -31000 {
453 t.Fatal(a)
454 }
455 } else {
456 t.Fatal("Wrong export type")
457 }
458 })
459
460 t.Run("uint32", func(t *testing.T) {
461 v, err := vm.RunString("new Uint32Array([1, 123456])")
462 if err != nil {
463 t.Fatal(err)
464 }
465 if a, ok := v.Export().([]uint32); ok {
466 if len(a) != 2 || a[0] != 1 || a[1] != 123456 {
467 t.Fatal(a)
468 }
469 } else {
470 t.Fatal("Wrong export type")
471 }
472 })
473
474 t.Run("int32", func(t *testing.T) {
475 v, err := vm.RunString("new Int32Array([1, -123456])")
476 if err != nil {
477 t.Fatal(err)
478 }
479 if a, ok := v.Export().([]int32); ok {
480 if len(a) != 2 || a[0] != 1 || a[1] != -123456 {
481 t.Fatal(a)
482 }
483 } else {
484 t.Fatal("Wrong export type")
485 }
486 })
487
488 t.Run("float32", func(t *testing.T) {
489 v, err := vm.RunString("new Float32Array([1, -1.23456])")
490 if err != nil {
491 t.Fatal(err)
492 }
493 if a, ok := v.Export().([]float32); ok {
494 if len(a) != 2 || a[0] != 1 || a[1] != -1.23456 {
495 t.Fatal(a)
496 }
497 } else {
498 t.Fatal("Wrong export type")
499 }
500 })
501
502 t.Run("float64", func(t *testing.T) {
503 v, err := vm.RunString("new Float64Array([1, -1.23456789])")
504 if err != nil {
505 t.Fatal(err)
506 }
507 if a, ok := v.Export().([]float64); ok {
508 if len(a) != 2 || a[0] != 1 || a[1] != -1.23456789 {
509 t.Fatal(a)
510 }
511 } else {
512 t.Fatal("Wrong export type")
513 }
514 })
515
516 }
517
View as plain text