github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/typedarrays.go (about) 1 package goja 2 3 import ( 4 "math" 5 "reflect" 6 "strconv" 7 "unsafe" 8 9 "github.com/nuvolaris/goja/unistring" 10 ) 11 12 type byteOrder bool 13 14 const ( 15 bigEndian byteOrder = false 16 littleEndian byteOrder = true 17 ) 18 19 var ( 20 nativeEndian byteOrder 21 22 arrayBufferType = reflect.TypeOf(ArrayBuffer{}) 23 ) 24 25 type typedArrayObjectCtor func(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject 26 27 type arrayBufferObject struct { 28 baseObject 29 detached bool 30 data []byte 31 } 32 33 // ArrayBuffer is a Go wrapper around ECMAScript ArrayBuffer. Calling Runtime.ToValue() on it 34 // returns the underlying ArrayBuffer. Calling Export() on an ECMAScript ArrayBuffer returns a wrapper. 35 // Use Runtime.NewArrayBuffer([]byte) to create one. 36 type ArrayBuffer struct { 37 buf *arrayBufferObject 38 } 39 40 type dataViewObject struct { 41 baseObject 42 viewedArrayBuf *arrayBufferObject 43 byteLen, byteOffset int 44 } 45 46 type typedArray interface { 47 toRaw(Value) uint64 48 get(idx int) Value 49 set(idx int, value Value) 50 getRaw(idx int) uint64 51 setRaw(idx int, raw uint64) 52 less(i, j int) bool 53 swap(i, j int) 54 typeMatch(v Value) bool 55 export(offset int, length int) interface{} 56 exportType() reflect.Type 57 } 58 59 type uint8Array []byte 60 type uint8ClampedArray []byte 61 type int8Array []byte 62 type uint16Array []byte 63 type int16Array []byte 64 type uint32Array []byte 65 type int32Array []byte 66 type float32Array []byte 67 type float64Array []byte 68 69 type typedArrayObject struct { 70 baseObject 71 viewedArrayBuf *arrayBufferObject 72 defaultCtor *Object 73 length, offset int 74 elemSize int 75 typedArray typedArray 76 } 77 78 func (a ArrayBuffer) toValue(r *Runtime) Value { 79 if a.buf == nil { 80 return _null 81 } 82 v := a.buf.val 83 if v.runtime != r { 84 panic(r.NewTypeError("Illegal runtime transition of an ArrayBuffer")) 85 } 86 return v 87 } 88 89 // Bytes returns the underlying []byte for this ArrayBuffer. 90 // For detached ArrayBuffers returns nil. 91 func (a ArrayBuffer) Bytes() []byte { 92 return a.buf.data 93 } 94 95 // Detach the ArrayBuffer. After this, the underlying []byte becomes unreferenced and any attempt 96 // to use this ArrayBuffer results in a TypeError. 97 // Returns false if it was already detached, true otherwise. 98 // Note, this method may only be called from the goroutine that 'owns' the Runtime, it may not 99 // be called concurrently. 100 func (a ArrayBuffer) Detach() bool { 101 if a.buf.detached { 102 return false 103 } 104 a.buf.detach() 105 return true 106 } 107 108 // Detached returns true if the ArrayBuffer is detached. 109 func (a ArrayBuffer) Detached() bool { 110 return a.buf.detached 111 } 112 113 // NewArrayBuffer creates a new instance of ArrayBuffer backed by the provided byte slice. 114 // 115 // Warning: be careful when using unaligned slices (sub-slices that do not start at word boundaries). If later a 116 // typed array of a multibyte type (uint16, uint32, etc.) is created from a buffer backed by an unaligned slice, 117 // using this typed array will result in unaligned access which may cause performance degradation or runtime panics 118 // on some architectures or configurations. 119 func (r *Runtime) NewArrayBuffer(data []byte) ArrayBuffer { 120 buf := r._newArrayBuffer(r.global.ArrayBufferPrototype, nil) 121 buf.data = data 122 return ArrayBuffer{ 123 buf: buf, 124 } 125 } 126 127 func (a *uint8Array) toRaw(v Value) uint64 { 128 return uint64(toUint8(v)) 129 } 130 131 func (a *uint8Array) ptr(idx int) *uint8 { 132 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 133 return (*uint8)(unsafe.Pointer(uintptr(p) + uintptr(idx))) 134 } 135 136 func (a *uint8Array) get(idx int) Value { 137 return intToValue(int64(*(a.ptr(idx)))) 138 } 139 140 func (a *uint8Array) set(idx int, value Value) { 141 *(a.ptr(idx)) = toUint8(value) 142 } 143 144 func (a *uint8Array) getRaw(idx int) uint64 { 145 return uint64(*(a.ptr(idx))) 146 } 147 148 func (a *uint8Array) setRaw(idx int, raw uint64) { 149 *(a.ptr(idx)) = uint8(raw) 150 } 151 152 func (a *uint8Array) less(i, j int) bool { 153 return *(a.ptr(i)) < *(a.ptr(j)) 154 } 155 156 func (a *uint8Array) swap(i, j int) { 157 pi, pj := a.ptr(i), a.ptr(j) 158 *pi, *pj = *pj, *pi 159 } 160 161 func (a *uint8Array) typeMatch(v Value) bool { 162 if i, ok := v.(valueInt); ok { 163 return i >= 0 && i <= 255 164 } 165 return false 166 } 167 168 func (a *uint8Array) export(offset int, length int) interface{} { 169 return ([]uint8)(*a)[offset : offset+length : offset+length] 170 } 171 172 func (a *uint8Array) exportType() reflect.Type { 173 return typeBytes 174 } 175 176 func (a *uint8ClampedArray) toRaw(v Value) uint64 { 177 return uint64(toUint8Clamp(v)) 178 } 179 180 func (a *uint8ClampedArray) ptr(idx int) *uint8 { 181 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 182 return (*uint8)(unsafe.Pointer(uintptr(p) + uintptr(idx))) 183 } 184 185 func (a *uint8ClampedArray) get(idx int) Value { 186 return intToValue(int64(*(a.ptr(idx)))) 187 } 188 189 func (a *uint8ClampedArray) set(idx int, value Value) { 190 *(a.ptr(idx)) = toUint8Clamp(value) 191 } 192 193 func (a *uint8ClampedArray) getRaw(idx int) uint64 { 194 return uint64(*(a.ptr(idx))) 195 } 196 197 func (a *uint8ClampedArray) setRaw(idx int, raw uint64) { 198 *(a.ptr(idx)) = uint8(raw) 199 } 200 201 func (a *uint8ClampedArray) less(i, j int) bool { 202 return *(a.ptr(i)) < *(a.ptr(j)) 203 } 204 205 func (a *uint8ClampedArray) swap(i, j int) { 206 pi, pj := a.ptr(i), a.ptr(j) 207 *pi, *pj = *pj, *pi 208 } 209 210 func (a *uint8ClampedArray) typeMatch(v Value) bool { 211 if i, ok := v.(valueInt); ok { 212 return i >= 0 && i <= 255 213 } 214 return false 215 } 216 217 func (a *uint8ClampedArray) export(offset int, length int) interface{} { 218 return ([]uint8)(*a)[offset : offset+length : offset+length] 219 } 220 221 func (a *uint8ClampedArray) exportType() reflect.Type { 222 return typeBytes 223 } 224 225 func (a *int8Array) ptr(idx int) *int8 { 226 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 227 return (*int8)(unsafe.Pointer(uintptr(p) + uintptr(idx))) 228 } 229 230 func (a *int8Array) get(idx int) Value { 231 return intToValue(int64(*(a.ptr(idx)))) 232 } 233 234 func (a *int8Array) getRaw(idx int) uint64 { 235 return uint64(*(a.ptr(idx))) 236 } 237 238 func (a *int8Array) set(idx int, value Value) { 239 *(a.ptr(idx)) = toInt8(value) 240 } 241 242 func (a *int8Array) toRaw(v Value) uint64 { 243 return uint64(toInt8(v)) 244 } 245 246 func (a *int8Array) setRaw(idx int, v uint64) { 247 *(a.ptr(idx)) = int8(v) 248 } 249 250 func (a *int8Array) less(i, j int) bool { 251 return *(a.ptr(i)) < *(a.ptr(j)) 252 } 253 254 func (a *int8Array) swap(i, j int) { 255 pi, pj := a.ptr(i), a.ptr(j) 256 *pi, *pj = *pj, *pi 257 } 258 259 func (a *int8Array) typeMatch(v Value) bool { 260 if i, ok := v.(valueInt); ok { 261 return i >= math.MinInt8 && i <= math.MaxInt8 262 } 263 return false 264 } 265 266 func (a *int8Array) export(offset int, length int) interface{} { 267 var res []int8 268 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 269 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset) 270 sliceHeader.Len = length 271 sliceHeader.Cap = length 272 return res 273 } 274 275 var typeInt8Array = reflect.TypeOf(([]int8)(nil)) 276 277 func (a *int8Array) exportType() reflect.Type { 278 return typeInt8Array 279 } 280 281 func (a *uint16Array) toRaw(v Value) uint64 { 282 return uint64(toUint16(v)) 283 } 284 285 func (a *uint16Array) ptr(idx int) *uint16 { 286 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 287 return (*uint16)(unsafe.Pointer(uintptr(p) + uintptr(idx)*2)) 288 } 289 290 func (a *uint16Array) get(idx int) Value { 291 return intToValue(int64(*(a.ptr(idx)))) 292 } 293 294 func (a *uint16Array) set(idx int, value Value) { 295 *(a.ptr(idx)) = toUint16(value) 296 } 297 298 func (a *uint16Array) getRaw(idx int) uint64 { 299 return uint64(*(a.ptr(idx))) 300 } 301 302 func (a *uint16Array) setRaw(idx int, raw uint64) { 303 *(a.ptr(idx)) = uint16(raw) 304 } 305 306 func (a *uint16Array) less(i, j int) bool { 307 return *(a.ptr(i)) < *(a.ptr(j)) 308 } 309 310 func (a *uint16Array) swap(i, j int) { 311 pi, pj := a.ptr(i), a.ptr(j) 312 *pi, *pj = *pj, *pi 313 } 314 315 func (a *uint16Array) typeMatch(v Value) bool { 316 if i, ok := v.(valueInt); ok { 317 return i >= 0 && i <= math.MaxUint16 318 } 319 return false 320 } 321 322 var typeUint16Array = reflect.TypeOf(([]uint16)(nil)) 323 324 func (a *uint16Array) export(offset int, length int) interface{} { 325 var res []uint16 326 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 327 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*2 328 sliceHeader.Len = length 329 sliceHeader.Cap = length 330 return res 331 } 332 333 func (a *uint16Array) exportType() reflect.Type { 334 return typeUint16Array 335 } 336 337 func (a *int16Array) ptr(idx int) *int16 { 338 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 339 return (*int16)(unsafe.Pointer(uintptr(p) + uintptr(idx)*2)) 340 } 341 342 func (a *int16Array) get(idx int) Value { 343 return intToValue(int64(*(a.ptr(idx)))) 344 } 345 346 func (a *int16Array) getRaw(idx int) uint64 { 347 return uint64(*(a.ptr(idx))) 348 } 349 350 func (a *int16Array) set(idx int, value Value) { 351 *(a.ptr(idx)) = toInt16(value) 352 } 353 354 func (a *int16Array) toRaw(v Value) uint64 { 355 return uint64(toInt16(v)) 356 } 357 358 func (a *int16Array) setRaw(idx int, v uint64) { 359 *(a.ptr(idx)) = int16(v) 360 } 361 362 func (a *int16Array) less(i, j int) bool { 363 return *(a.ptr(i)) < *(a.ptr(j)) 364 } 365 366 func (a *int16Array) swap(i, j int) { 367 pi, pj := a.ptr(i), a.ptr(j) 368 *pi, *pj = *pj, *pi 369 } 370 371 func (a *int16Array) typeMatch(v Value) bool { 372 if i, ok := v.(valueInt); ok { 373 return i >= math.MinInt16 && i <= math.MaxInt16 374 } 375 return false 376 } 377 378 func (a *int16Array) export(offset int, length int) interface{} { 379 var res []int16 380 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 381 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*2 382 sliceHeader.Len = length 383 sliceHeader.Cap = length 384 return res 385 } 386 387 var typeInt16Array = reflect.TypeOf(([]int16)(nil)) 388 389 func (a *int16Array) exportType() reflect.Type { 390 return typeInt16Array 391 } 392 393 func (a *uint32Array) ptr(idx int) *uint32 { 394 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 395 return (*uint32)(unsafe.Pointer(uintptr(p) + uintptr(idx)*4)) 396 } 397 398 func (a *uint32Array) get(idx int) Value { 399 return intToValue(int64(*(a.ptr(idx)))) 400 } 401 402 func (a *uint32Array) getRaw(idx int) uint64 { 403 return uint64(*(a.ptr(idx))) 404 } 405 406 func (a *uint32Array) set(idx int, value Value) { 407 *(a.ptr(idx)) = toUint32(value) 408 } 409 410 func (a *uint32Array) toRaw(v Value) uint64 { 411 return uint64(toUint32(v)) 412 } 413 414 func (a *uint32Array) setRaw(idx int, v uint64) { 415 *(a.ptr(idx)) = uint32(v) 416 } 417 418 func (a *uint32Array) less(i, j int) bool { 419 return *(a.ptr(i)) < *(a.ptr(j)) 420 } 421 422 func (a *uint32Array) swap(i, j int) { 423 pi, pj := a.ptr(i), a.ptr(j) 424 *pi, *pj = *pj, *pi 425 } 426 427 func (a *uint32Array) typeMatch(v Value) bool { 428 if i, ok := v.(valueInt); ok { 429 return i >= 0 && i <= math.MaxUint32 430 } 431 return false 432 } 433 434 func (a *uint32Array) export(offset int, length int) interface{} { 435 var res []uint32 436 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 437 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*4 438 sliceHeader.Len = length 439 sliceHeader.Cap = length 440 return res 441 } 442 443 var typeUint32Array = reflect.TypeOf(([]uint32)(nil)) 444 445 func (a *uint32Array) exportType() reflect.Type { 446 return typeUint32Array 447 } 448 449 func (a *int32Array) ptr(idx int) *int32 { 450 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 451 return (*int32)(unsafe.Pointer(uintptr(p) + uintptr(idx)*4)) 452 } 453 454 func (a *int32Array) get(idx int) Value { 455 return intToValue(int64(*(a.ptr(idx)))) 456 } 457 458 func (a *int32Array) getRaw(idx int) uint64 { 459 return uint64(*(a.ptr(idx))) 460 } 461 462 func (a *int32Array) set(idx int, value Value) { 463 *(a.ptr(idx)) = toInt32(value) 464 } 465 466 func (a *int32Array) toRaw(v Value) uint64 { 467 return uint64(toInt32(v)) 468 } 469 470 func (a *int32Array) setRaw(idx int, v uint64) { 471 *(a.ptr(idx)) = int32(v) 472 } 473 474 func (a *int32Array) less(i, j int) bool { 475 return *(a.ptr(i)) < *(a.ptr(j)) 476 } 477 478 func (a *int32Array) swap(i, j int) { 479 pi, pj := a.ptr(i), a.ptr(j) 480 *pi, *pj = *pj, *pi 481 } 482 483 func (a *int32Array) typeMatch(v Value) bool { 484 if i, ok := v.(valueInt); ok { 485 return i >= math.MinInt32 && i <= math.MaxInt32 486 } 487 return false 488 } 489 490 func (a *int32Array) export(offset int, length int) interface{} { 491 var res []int32 492 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 493 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*4 494 sliceHeader.Len = length 495 sliceHeader.Cap = length 496 return res 497 } 498 499 var typeInt32Array = reflect.TypeOf(([]int32)(nil)) 500 501 func (a *int32Array) exportType() reflect.Type { 502 return typeInt32Array 503 } 504 505 func (a *float32Array) ptr(idx int) *float32 { 506 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 507 return (*float32)(unsafe.Pointer(uintptr(p) + uintptr(idx)*4)) 508 } 509 510 func (a *float32Array) get(idx int) Value { 511 return floatToValue(float64(*(a.ptr(idx)))) 512 } 513 514 func (a *float32Array) getRaw(idx int) uint64 { 515 return uint64(math.Float32bits(*(a.ptr(idx)))) 516 } 517 518 func (a *float32Array) set(idx int, value Value) { 519 *(a.ptr(idx)) = toFloat32(value) 520 } 521 522 func (a *float32Array) toRaw(v Value) uint64 { 523 return uint64(math.Float32bits(toFloat32(v))) 524 } 525 526 func (a *float32Array) setRaw(idx int, v uint64) { 527 *(a.ptr(idx)) = math.Float32frombits(uint32(v)) 528 } 529 530 func typedFloatLess(x, y float64) bool { 531 xNan := math.IsNaN(x) 532 yNan := math.IsNaN(y) 533 if yNan { 534 return !xNan 535 } else if xNan { 536 return false 537 } 538 if x == 0 && y == 0 { // handle neg zero 539 return math.Signbit(x) 540 } 541 return x < y 542 } 543 544 func (a *float32Array) less(i, j int) bool { 545 return typedFloatLess(float64(*(a.ptr(i))), float64(*(a.ptr(j)))) 546 } 547 548 func (a *float32Array) swap(i, j int) { 549 pi, pj := a.ptr(i), a.ptr(j) 550 *pi, *pj = *pj, *pi 551 } 552 553 func (a *float32Array) typeMatch(v Value) bool { 554 switch v.(type) { 555 case valueInt, valueFloat: 556 return true 557 } 558 return false 559 } 560 561 func (a *float32Array) export(offset int, length int) interface{} { 562 var res []float32 563 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 564 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*4 565 sliceHeader.Len = length 566 sliceHeader.Cap = length 567 return res 568 } 569 570 var typeFloat32Array = reflect.TypeOf(([]float32)(nil)) 571 572 func (a *float32Array) exportType() reflect.Type { 573 return typeFloat32Array 574 } 575 576 func (a *float64Array) ptr(idx int) *float64 { 577 p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) 578 return (*float64)(unsafe.Pointer(uintptr(p) + uintptr(idx)*8)) 579 } 580 581 func (a *float64Array) get(idx int) Value { 582 return floatToValue(*(a.ptr(idx))) 583 } 584 585 func (a *float64Array) getRaw(idx int) uint64 { 586 return math.Float64bits(*(a.ptr(idx))) 587 } 588 589 func (a *float64Array) set(idx int, value Value) { 590 *(a.ptr(idx)) = value.ToFloat() 591 } 592 593 func (a *float64Array) toRaw(v Value) uint64 { 594 return math.Float64bits(v.ToFloat()) 595 } 596 597 func (a *float64Array) setRaw(idx int, v uint64) { 598 *(a.ptr(idx)) = math.Float64frombits(v) 599 } 600 601 func (a *float64Array) less(i, j int) bool { 602 return typedFloatLess(*(a.ptr(i)), *(a.ptr(j))) 603 } 604 605 func (a *float64Array) swap(i, j int) { 606 pi, pj := a.ptr(i), a.ptr(j) 607 *pi, *pj = *pj, *pi 608 } 609 610 func (a *float64Array) typeMatch(v Value) bool { 611 switch v.(type) { 612 case valueInt, valueFloat: 613 return true 614 } 615 return false 616 } 617 618 func (a *float64Array) export(offset int, length int) interface{} { 619 var res []float64 620 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) 621 sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*8 622 sliceHeader.Len = length 623 sliceHeader.Cap = length 624 return res 625 } 626 627 var typeFloat64Array = reflect.TypeOf(([]float64)(nil)) 628 629 func (a *float64Array) exportType() reflect.Type { 630 return typeFloat64Array 631 } 632 633 func (a *typedArrayObject) _getIdx(idx int) Value { 634 if 0 <= idx && idx < a.length { 635 if !a.viewedArrayBuf.ensureNotDetached(false) { 636 return nil 637 } 638 return a.typedArray.get(idx + a.offset) 639 } 640 return nil 641 } 642 643 func (a *typedArrayObject) getOwnPropStr(name unistring.String) Value { 644 idx, ok := strToIntNum(name) 645 if ok { 646 v := a._getIdx(idx) 647 if v != nil { 648 return &valueProperty{ 649 value: v, 650 writable: true, 651 enumerable: true, 652 configurable: true, 653 } 654 } 655 return nil 656 } 657 if idx == 0 { 658 return nil 659 } 660 return a.baseObject.getOwnPropStr(name) 661 } 662 663 func (a *typedArrayObject) getOwnPropIdx(idx valueInt) Value { 664 v := a._getIdx(toIntClamp(int64(idx))) 665 if v != nil { 666 return &valueProperty{ 667 value: v, 668 writable: true, 669 enumerable: true, 670 configurable: true, 671 } 672 } 673 return nil 674 } 675 676 func (a *typedArrayObject) getStr(name unistring.String, receiver Value) Value { 677 idx, ok := strToIntNum(name) 678 if ok { 679 return a._getIdx(idx) 680 } 681 if idx == 0 { 682 return nil 683 } 684 return a.baseObject.getStr(name, receiver) 685 } 686 687 func (a *typedArrayObject) getIdx(idx valueInt, receiver Value) Value { 688 return a._getIdx(toIntClamp(int64(idx))) 689 } 690 691 func (a *typedArrayObject) isValidIntegerIndex(idx int) bool { 692 if a.viewedArrayBuf.ensureNotDetached(false) { 693 if idx >= 0 && idx < a.length { 694 return true 695 } 696 } 697 return false 698 } 699 700 func (a *typedArrayObject) _putIdx(idx int, v Value) { 701 v = v.ToNumber() 702 if a.isValidIntegerIndex(idx) { 703 a.typedArray.set(idx+a.offset, v) 704 } 705 } 706 707 func (a *typedArrayObject) _hasIdx(idx int) bool { 708 return a.isValidIntegerIndex(idx) 709 } 710 711 func (a *typedArrayObject) setOwnStr(p unistring.String, v Value, throw bool) bool { 712 idx, ok := strToIntNum(p) 713 if ok { 714 a._putIdx(idx, v) 715 return true 716 } 717 if idx == 0 { 718 v.ToNumber() // make sure it throws 719 return true 720 } 721 return a.baseObject.setOwnStr(p, v, throw) 722 } 723 724 func (a *typedArrayObject) setOwnIdx(p valueInt, v Value, throw bool) bool { 725 a._putIdx(toIntClamp(int64(p)), v) 726 return true 727 } 728 729 func (a *typedArrayObject) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) { 730 return a._setForeignStr(p, a.getOwnPropStr(p), v, receiver, throw) 731 } 732 733 func (a *typedArrayObject) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) { 734 return a._setForeignIdx(p, trueValIfPresent(a.hasOwnPropertyIdx(p)), v, receiver, throw) 735 } 736 737 func (a *typedArrayObject) hasOwnPropertyStr(name unistring.String) bool { 738 idx, ok := strToIntNum(name) 739 if ok { 740 return a._hasIdx(idx) 741 } 742 if idx == 0 { 743 return false 744 } 745 return a.baseObject.hasOwnPropertyStr(name) 746 } 747 748 func (a *typedArrayObject) hasOwnPropertyIdx(idx valueInt) bool { 749 return a._hasIdx(toIntClamp(int64(idx))) 750 } 751 752 func (a *typedArrayObject) hasPropertyStr(name unistring.String) bool { 753 idx, ok := strToIntNum(name) 754 if ok { 755 return a._hasIdx(idx) 756 } 757 if idx == 0 { 758 return false 759 } 760 return a.baseObject.hasPropertyStr(name) 761 } 762 763 func (a *typedArrayObject) hasPropertyIdx(idx valueInt) bool { 764 return a.hasOwnPropertyIdx(idx) 765 } 766 767 func (a *typedArrayObject) _defineIdxProperty(idx int, desc PropertyDescriptor, throw bool) bool { 768 if desc.Configurable == FLAG_FALSE || desc.Enumerable == FLAG_FALSE || desc.IsAccessor() || desc.Writable == FLAG_FALSE { 769 a.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", idx) 770 return false 771 } 772 _, ok := a._defineOwnProperty(unistring.String(strconv.Itoa(idx)), a.getOwnPropIdx(valueInt(idx)), desc, throw) 773 if ok { 774 if !a.isValidIntegerIndex(idx) { 775 a.val.runtime.typeErrorResult(throw, "Invalid typed array index") 776 return false 777 } 778 a._putIdx(idx, desc.Value) 779 return true 780 } 781 return ok 782 } 783 784 func (a *typedArrayObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool { 785 idx, ok := strToIntNum(name) 786 if ok { 787 return a._defineIdxProperty(idx, desc, throw) 788 } 789 if idx == 0 { 790 a.viewedArrayBuf.ensureNotDetached(throw) 791 a.val.runtime.typeErrorResult(throw, "Invalid typed array index") 792 return false 793 } 794 return a.baseObject.defineOwnPropertyStr(name, desc, throw) 795 } 796 797 func (a *typedArrayObject) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool { 798 return a._defineIdxProperty(toIntClamp(int64(name)), desc, throw) 799 } 800 801 func (a *typedArrayObject) deleteStr(name unistring.String, throw bool) bool { 802 idx, ok := strToIntNum(name) 803 if ok { 804 if a.isValidIntegerIndex(idx) { 805 a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String()) 806 return false 807 } 808 return true 809 } 810 if idx == 0 { 811 return true 812 } 813 return a.baseObject.deleteStr(name, throw) 814 } 815 816 func (a *typedArrayObject) deleteIdx(idx valueInt, throw bool) bool { 817 if a.viewedArrayBuf.ensureNotDetached(false) && idx >= 0 && int64(idx) < int64(a.length) { 818 a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String()) 819 return false 820 } 821 822 return true 823 } 824 825 func (a *typedArrayObject) stringKeys(all bool, accum []Value) []Value { 826 if accum == nil { 827 accum = make([]Value, 0, a.length) 828 } 829 for i := 0; i < a.length; i++ { 830 accum = append(accum, asciiString(strconv.Itoa(i))) 831 } 832 return a.baseObject.stringKeys(all, accum) 833 } 834 835 type typedArrayPropIter struct { 836 a *typedArrayObject 837 idx int 838 } 839 840 func (i *typedArrayPropIter) next() (propIterItem, iterNextFunc) { 841 if i.idx < i.a.length { 842 name := strconv.Itoa(i.idx) 843 prop := i.a._getIdx(i.idx) 844 i.idx++ 845 return propIterItem{name: asciiString(name), value: prop}, i.next 846 } 847 848 return i.a.baseObject.iterateStringKeys()() 849 } 850 851 func (a *typedArrayObject) iterateStringKeys() iterNextFunc { 852 return (&typedArrayPropIter{ 853 a: a, 854 }).next 855 } 856 857 func (a *typedArrayObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error { 858 if typ == typeBytes { 859 dst.Set(reflect.ValueOf(a.viewedArrayBuf.data)) 860 return nil 861 } 862 return a.baseObject.exportToArrayOrSlice(dst, typ, ctx) 863 } 864 865 func (a *typedArrayObject) export(_ *objectExportCtx) interface{} { 866 return a.typedArray.export(a.offset, a.length) 867 } 868 869 func (a *typedArrayObject) exportType() reflect.Type { 870 return a.typedArray.exportType() 871 } 872 873 func (o *dataViewObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error { 874 if typ == typeBytes { 875 dst.Set(reflect.ValueOf(o.viewedArrayBuf.data)) 876 return nil 877 } 878 return o.baseObject.exportToArrayOrSlice(dst, typ, ctx) 879 } 880 881 func (r *Runtime) _newTypedArrayObject(buf *arrayBufferObject, offset, length, elemSize int, defCtor *Object, arr typedArray, proto *Object) *typedArrayObject { 882 o := &Object{runtime: r} 883 a := &typedArrayObject{ 884 baseObject: baseObject{ 885 val: o, 886 class: classObject, 887 prototype: proto, 888 extensible: true, 889 }, 890 viewedArrayBuf: buf, 891 offset: offset, 892 length: length, 893 elemSize: elemSize, 894 defaultCtor: defCtor, 895 typedArray: arr, 896 } 897 o.self = a 898 a.init() 899 return a 900 901 } 902 903 func (r *Runtime) newUint8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 904 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8Array, (*uint8Array)(&buf.data), proto) 905 } 906 907 func (r *Runtime) newUint8ClampedArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 908 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8ClampedArray, (*uint8ClampedArray)(&buf.data), proto) 909 } 910 911 func (r *Runtime) newInt8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 912 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Int8Array, (*int8Array)(&buf.data), proto) 913 } 914 915 func (r *Runtime) newUint16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 916 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Uint16Array, (*uint16Array)(&buf.data), proto) 917 } 918 919 func (r *Runtime) newInt16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 920 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Int16Array, (*int16Array)(&buf.data), proto) 921 } 922 923 func (r *Runtime) newUint32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 924 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Uint32Array, (*uint32Array)(&buf.data), proto) 925 } 926 927 func (r *Runtime) newInt32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 928 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Int32Array, (*int32Array)(&buf.data), proto) 929 } 930 931 func (r *Runtime) newFloat32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 932 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Float32Array, (*float32Array)(&buf.data), proto) 933 } 934 935 func (r *Runtime) newFloat64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 936 return r._newTypedArrayObject(buf, offset, length, 8, r.global.Float64Array, (*float64Array)(&buf.data), proto) 937 } 938 939 func (o *dataViewObject) getIdxAndByteOrder(getIdx int, littleEndianVal Value, size int) (int, byteOrder) { 940 o.viewedArrayBuf.ensureNotDetached(true) 941 if getIdx+size > o.byteLen { 942 panic(o.val.runtime.newError(o.val.runtime.global.RangeError, "Index %d is out of bounds", getIdx)) 943 } 944 getIdx += o.byteOffset 945 var bo byteOrder 946 if littleEndianVal != nil { 947 if littleEndianVal.ToBoolean() { 948 bo = littleEndian 949 } else { 950 bo = bigEndian 951 } 952 } else { 953 bo = nativeEndian 954 } 955 return getIdx, bo 956 } 957 958 func (o *arrayBufferObject) ensureNotDetached(throw bool) bool { 959 if o.detached { 960 o.val.runtime.typeErrorResult(throw, "ArrayBuffer is detached") 961 return false 962 } 963 return true 964 } 965 966 func (o *arrayBufferObject) getFloat32(idx int, byteOrder byteOrder) float32 { 967 return math.Float32frombits(o.getUint32(idx, byteOrder)) 968 } 969 970 func (o *arrayBufferObject) setFloat32(idx int, val float32, byteOrder byteOrder) { 971 o.setUint32(idx, math.Float32bits(val), byteOrder) 972 } 973 974 func (o *arrayBufferObject) getFloat64(idx int, byteOrder byteOrder) float64 { 975 return math.Float64frombits(o.getUint64(idx, byteOrder)) 976 } 977 978 func (o *arrayBufferObject) setFloat64(idx int, val float64, byteOrder byteOrder) { 979 o.setUint64(idx, math.Float64bits(val), byteOrder) 980 } 981 982 func (o *arrayBufferObject) getUint64(idx int, byteOrder byteOrder) uint64 { 983 var b []byte 984 if byteOrder == nativeEndian { 985 b = o.data[idx : idx+8] 986 } else { 987 b = make([]byte, 8) 988 d := o.data[idx : idx+8] 989 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] = d[7], d[6], d[5], d[4], d[3], d[2], d[1], d[0] 990 } 991 return *((*uint64)(unsafe.Pointer(&b[0]))) 992 } 993 994 func (o *arrayBufferObject) setUint64(idx int, val uint64, byteOrder byteOrder) { 995 if byteOrder == nativeEndian { 996 *(*uint64)(unsafe.Pointer(&o.data[idx])) = val 997 } else { 998 b := (*[8]byte)(unsafe.Pointer(&val)) 999 d := o.data[idx : idx+8] 1000 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7] = b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0] 1001 } 1002 } 1003 1004 func (o *arrayBufferObject) getUint32(idx int, byteOrder byteOrder) uint32 { 1005 var b []byte 1006 if byteOrder == nativeEndian { 1007 b = o.data[idx : idx+4] 1008 } else { 1009 b = make([]byte, 4) 1010 d := o.data[idx : idx+4] 1011 b[0], b[1], b[2], b[3] = d[3], d[2], d[1], d[0] 1012 } 1013 return *((*uint32)(unsafe.Pointer(&b[0]))) 1014 } 1015 1016 func (o *arrayBufferObject) setUint32(idx int, val uint32, byteOrder byteOrder) { 1017 o.ensureNotDetached(true) 1018 if byteOrder == nativeEndian { 1019 *(*uint32)(unsafe.Pointer(&o.data[idx])) = val 1020 } else { 1021 b := (*[4]byte)(unsafe.Pointer(&val)) 1022 d := o.data[idx : idx+4] 1023 d[0], d[1], d[2], d[3] = b[3], b[2], b[1], b[0] 1024 } 1025 } 1026 1027 func (o *arrayBufferObject) getUint16(idx int, byteOrder byteOrder) uint16 { 1028 var b []byte 1029 if byteOrder == nativeEndian { 1030 b = o.data[idx : idx+2] 1031 } else { 1032 b = make([]byte, 2) 1033 d := o.data[idx : idx+2] 1034 b[0], b[1] = d[1], d[0] 1035 } 1036 return *((*uint16)(unsafe.Pointer(&b[0]))) 1037 } 1038 1039 func (o *arrayBufferObject) setUint16(idx int, val uint16, byteOrder byteOrder) { 1040 if byteOrder == nativeEndian { 1041 *(*uint16)(unsafe.Pointer(&o.data[idx])) = val 1042 } else { 1043 b := (*[2]byte)(unsafe.Pointer(&val)) 1044 d := o.data[idx : idx+2] 1045 d[0], d[1] = b[1], b[0] 1046 } 1047 } 1048 1049 func (o *arrayBufferObject) getUint8(idx int) uint8 { 1050 return o.data[idx] 1051 } 1052 1053 func (o *arrayBufferObject) setUint8(idx int, val uint8) { 1054 o.data[idx] = val 1055 } 1056 1057 func (o *arrayBufferObject) getInt32(idx int, byteOrder byteOrder) int32 { 1058 return int32(o.getUint32(idx, byteOrder)) 1059 } 1060 1061 func (o *arrayBufferObject) setInt32(idx int, val int32, byteOrder byteOrder) { 1062 o.setUint32(idx, uint32(val), byteOrder) 1063 } 1064 1065 func (o *arrayBufferObject) getInt16(idx int, byteOrder byteOrder) int16 { 1066 return int16(o.getUint16(idx, byteOrder)) 1067 } 1068 1069 func (o *arrayBufferObject) setInt16(idx int, val int16, byteOrder byteOrder) { 1070 o.setUint16(idx, uint16(val), byteOrder) 1071 } 1072 1073 func (o *arrayBufferObject) getInt8(idx int) int8 { 1074 return int8(o.data[idx]) 1075 } 1076 1077 func (o *arrayBufferObject) setInt8(idx int, val int8) { 1078 o.setUint8(idx, uint8(val)) 1079 } 1080 1081 func (o *arrayBufferObject) detach() { 1082 o.data = nil 1083 o.detached = true 1084 } 1085 1086 func (o *arrayBufferObject) exportType() reflect.Type { 1087 return arrayBufferType 1088 } 1089 1090 func (o *arrayBufferObject) export(*objectExportCtx) interface{} { 1091 return ArrayBuffer{ 1092 buf: o, 1093 } 1094 } 1095 1096 func (o *arrayBufferObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error { 1097 if typ == typeBytes { 1098 dst.Set(reflect.ValueOf(o.data)) 1099 return nil 1100 } 1101 return o.baseObject.exportToArrayOrSlice(dst, typ, ctx) 1102 } 1103 1104 func (r *Runtime) _newArrayBuffer(proto *Object, o *Object) *arrayBufferObject { 1105 if o == nil { 1106 o = &Object{runtime: r} 1107 } 1108 b := &arrayBufferObject{ 1109 baseObject: baseObject{ 1110 class: classObject, 1111 val: o, 1112 prototype: proto, 1113 extensible: true, 1114 }, 1115 } 1116 o.self = b 1117 b.init() 1118 return b 1119 } 1120 1121 func init() { 1122 buf := [2]byte{} 1123 *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xCAFE) 1124 1125 switch buf { 1126 case [2]byte{0xFE, 0xCA}: 1127 nativeEndian = littleEndian 1128 case [2]byte{0xCA, 0xFE}: 1129 nativeEndian = bigEndian 1130 default: 1131 panic("Could not determine native endianness.") 1132 } 1133 }