github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/typedarrays_test.go (about) 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 }