go.ketch.com/lib/goja@v0.0.1/typedarrays.go (about) 1 package goja 2 3 import ( 4 "math" 5 "reflect" 6 "strconv" 7 "unsafe" 8 9 "go.ketch.com/lib/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 } 56 57 type uint8Array []uint8 58 type uint8ClampedArray []uint8 59 type int8Array []int8 60 type uint16Array []uint16 61 type int16Array []int16 62 type uint32Array []uint32 63 type int32Array []int32 64 type float32Array []float32 65 type float64Array []float64 66 67 type typedArrayObject struct { 68 baseObject 69 viewedArrayBuf *arrayBufferObject 70 defaultCtor *Object 71 length, offset int 72 elemSize int 73 typedArray typedArray 74 } 75 76 func (a ArrayBuffer) toValue(r *Runtime) Value { 77 if a.buf == nil { 78 return _null 79 } 80 v := a.buf.val 81 if v.runtime != r { 82 panic(r.NewTypeError("Illegal runtime transition of an ArrayBuffer")) 83 } 84 return v 85 } 86 87 // Bytes returns the underlying []byte for this ArrayBuffer. 88 // For detached ArrayBuffers returns nil. 89 func (a ArrayBuffer) Bytes() []byte { 90 return a.buf.data 91 } 92 93 // Detach the ArrayBuffer. After this, the underlying []byte becomes unreferenced and any attempt 94 // to use this ArrayBuffer results in a TypeError. 95 // Returns false if it was already detached, true otherwise. 96 // Note, this method may only be called from the goroutine that 'owns' the Runtime, it may not 97 // be called concurrently. 98 func (a ArrayBuffer) Detach() bool { 99 if a.buf.detached { 100 return false 101 } 102 a.buf.detach() 103 return true 104 } 105 106 // Detached returns true if the ArrayBuffer is detached. 107 func (a ArrayBuffer) Detached() bool { 108 return a.buf.detached 109 } 110 111 func (r *Runtime) NewArrayBuffer(data []byte) ArrayBuffer { 112 buf := r._newArrayBuffer(r.global.ArrayBufferPrototype, nil) 113 buf.data = data 114 return ArrayBuffer{ 115 buf: buf, 116 } 117 } 118 119 func (a *uint8Array) get(idx int) Value { 120 return intToValue(int64((*a)[idx])) 121 } 122 123 func (a *uint8Array) getRaw(idx int) uint64 { 124 return uint64((*a)[idx]) 125 } 126 127 func (a *uint8Array) set(idx int, value Value) { 128 (*a)[idx] = toUint8(value) 129 } 130 131 func (a *uint8Array) toRaw(v Value) uint64 { 132 return uint64(toUint8(v)) 133 } 134 135 func (a *uint8Array) setRaw(idx int, v uint64) { 136 (*a)[idx] = uint8(v) 137 } 138 139 func (a *uint8Array) less(i, j int) bool { 140 return (*a)[i] < (*a)[j] 141 } 142 143 func (a *uint8Array) swap(i, j int) { 144 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 145 } 146 147 func (a *uint8Array) typeMatch(v Value) bool { 148 if i, ok := v.(valueInt); ok { 149 return i >= 0 && i <= 255 150 } 151 return false 152 } 153 154 func (a *uint8ClampedArray) get(idx int) Value { 155 return intToValue(int64((*a)[idx])) 156 } 157 158 func (a *uint8ClampedArray) getRaw(idx int) uint64 { 159 return uint64((*a)[idx]) 160 } 161 162 func (a *uint8ClampedArray) set(idx int, value Value) { 163 (*a)[idx] = toUint8Clamp(value) 164 } 165 166 func (a *uint8ClampedArray) toRaw(v Value) uint64 { 167 return uint64(toUint8Clamp(v)) 168 } 169 170 func (a *uint8ClampedArray) setRaw(idx int, v uint64) { 171 (*a)[idx] = uint8(v) 172 } 173 174 func (a *uint8ClampedArray) less(i, j int) bool { 175 return (*a)[i] < (*a)[j] 176 } 177 178 func (a *uint8ClampedArray) swap(i, j int) { 179 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 180 } 181 182 func (a *uint8ClampedArray) typeMatch(v Value) bool { 183 if i, ok := v.(valueInt); ok { 184 return i >= 0 && i <= 255 185 } 186 return false 187 } 188 189 func (a *int8Array) get(idx int) Value { 190 return intToValue(int64((*a)[idx])) 191 } 192 193 func (a *int8Array) getRaw(idx int) uint64 { 194 return uint64((*a)[idx]) 195 } 196 197 func (a *int8Array) set(idx int, value Value) { 198 (*a)[idx] = toInt8(value) 199 } 200 201 func (a *int8Array) toRaw(v Value) uint64 { 202 return uint64(toInt8(v)) 203 } 204 205 func (a *int8Array) setRaw(idx int, v uint64) { 206 (*a)[idx] = int8(v) 207 } 208 209 func (a *int8Array) less(i, j int) bool { 210 return (*a)[i] < (*a)[j] 211 } 212 213 func (a *int8Array) swap(i, j int) { 214 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 215 } 216 217 func (a *int8Array) typeMatch(v Value) bool { 218 if i, ok := v.(valueInt); ok { 219 return i >= math.MinInt8 && i <= math.MaxInt8 220 } 221 return false 222 } 223 224 func (a *uint16Array) get(idx int) Value { 225 return intToValue(int64((*a)[idx])) 226 } 227 228 func (a *uint16Array) getRaw(idx int) uint64 { 229 return uint64((*a)[idx]) 230 } 231 232 func (a *uint16Array) set(idx int, value Value) { 233 (*a)[idx] = toUint16(value) 234 } 235 236 func (a *uint16Array) toRaw(v Value) uint64 { 237 return uint64(toUint16(v)) 238 } 239 240 func (a *uint16Array) setRaw(idx int, v uint64) { 241 (*a)[idx] = uint16(v) 242 } 243 244 func (a *uint16Array) less(i, j int) bool { 245 return (*a)[i] < (*a)[j] 246 } 247 248 func (a *uint16Array) swap(i, j int) { 249 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 250 } 251 252 func (a *uint16Array) typeMatch(v Value) bool { 253 if i, ok := v.(valueInt); ok { 254 return i >= 0 && i <= math.MaxUint16 255 } 256 return false 257 } 258 259 func (a *int16Array) get(idx int) Value { 260 return intToValue(int64((*a)[idx])) 261 } 262 263 func (a *int16Array) getRaw(idx int) uint64 { 264 return uint64((*a)[idx]) 265 } 266 267 func (a *int16Array) set(idx int, value Value) { 268 (*a)[idx] = toInt16(value) 269 } 270 271 func (a *int16Array) toRaw(v Value) uint64 { 272 return uint64(toInt16(v)) 273 } 274 275 func (a *int16Array) setRaw(idx int, v uint64) { 276 (*a)[idx] = int16(v) 277 } 278 279 func (a *int16Array) less(i, j int) bool { 280 return (*a)[i] < (*a)[j] 281 } 282 283 func (a *int16Array) swap(i, j int) { 284 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 285 } 286 287 func (a *int16Array) typeMatch(v Value) bool { 288 if i, ok := v.(valueInt); ok { 289 return i >= math.MinInt16 && i <= math.MaxInt16 290 } 291 return false 292 } 293 294 func (a *uint32Array) get(idx int) Value { 295 return intToValue(int64((*a)[idx])) 296 } 297 298 func (a *uint32Array) getRaw(idx int) uint64 { 299 return uint64((*a)[idx]) 300 } 301 302 func (a *uint32Array) set(idx int, value Value) { 303 (*a)[idx] = toUint32(value) 304 } 305 306 func (a *uint32Array) toRaw(v Value) uint64 { 307 return uint64(toUint32(v)) 308 } 309 310 func (a *uint32Array) setRaw(idx int, v uint64) { 311 (*a)[idx] = uint32(v) 312 } 313 314 func (a *uint32Array) less(i, j int) bool { 315 return (*a)[i] < (*a)[j] 316 } 317 318 func (a *uint32Array) swap(i, j int) { 319 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 320 } 321 322 func (a *uint32Array) typeMatch(v Value) bool { 323 if i, ok := v.(valueInt); ok { 324 return i >= 0 && i <= math.MaxUint32 325 } 326 return false 327 } 328 329 func (a *int32Array) get(idx int) Value { 330 return intToValue(int64((*a)[idx])) 331 } 332 333 func (a *int32Array) getRaw(idx int) uint64 { 334 return uint64((*a)[idx]) 335 } 336 337 func (a *int32Array) set(idx int, value Value) { 338 (*a)[idx] = toInt32(value) 339 } 340 341 func (a *int32Array) toRaw(v Value) uint64 { 342 return uint64(toInt32(v)) 343 } 344 345 func (a *int32Array) setRaw(idx int, v uint64) { 346 (*a)[idx] = int32(v) 347 } 348 349 func (a *int32Array) less(i, j int) bool { 350 return (*a)[i] < (*a)[j] 351 } 352 353 func (a *int32Array) swap(i, j int) { 354 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 355 } 356 357 func (a *int32Array) typeMatch(v Value) bool { 358 if i, ok := v.(valueInt); ok { 359 return i >= math.MinInt32 && i <= math.MaxInt32 360 } 361 return false 362 } 363 364 func (a *float32Array) get(idx int) Value { 365 return floatToValue(float64((*a)[idx])) 366 } 367 368 func (a *float32Array) getRaw(idx int) uint64 { 369 return uint64(math.Float32bits((*a)[idx])) 370 } 371 372 func (a *float32Array) set(idx int, value Value) { 373 (*a)[idx] = toFloat32(value) 374 } 375 376 func (a *float32Array) toRaw(v Value) uint64 { 377 return uint64(math.Float32bits(toFloat32(v))) 378 } 379 380 func (a *float32Array) setRaw(idx int, v uint64) { 381 (*a)[idx] = math.Float32frombits(uint32(v)) 382 } 383 384 func typedFloatLess(x, y float64) bool { 385 xNan := math.IsNaN(x) 386 yNan := math.IsNaN(y) 387 if yNan { 388 return !xNan 389 } else if xNan { 390 return false 391 } 392 if x == 0 && y == 0 { // handle neg zero 393 return math.Signbit(x) 394 } 395 return x < y 396 } 397 398 func (a *float32Array) less(i, j int) bool { 399 return typedFloatLess(float64((*a)[i]), float64((*a)[j])) 400 } 401 402 func (a *float32Array) swap(i, j int) { 403 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 404 } 405 406 func (a *float32Array) typeMatch(v Value) bool { 407 switch v.(type) { 408 case valueInt, valueFloat: 409 return true 410 } 411 return false 412 } 413 414 func (a *float64Array) get(idx int) Value { 415 return floatToValue((*a)[idx]) 416 } 417 418 func (a *float64Array) getRaw(idx int) uint64 { 419 return math.Float64bits((*a)[idx]) 420 } 421 422 func (a *float64Array) set(idx int, value Value) { 423 (*a)[idx] = value.ToFloat() 424 } 425 426 func (a *float64Array) toRaw(v Value) uint64 { 427 return math.Float64bits(v.ToFloat()) 428 } 429 430 func (a *float64Array) setRaw(idx int, v uint64) { 431 (*a)[idx] = math.Float64frombits(v) 432 } 433 434 func (a *float64Array) less(i, j int) bool { 435 return typedFloatLess((*a)[i], (*a)[j]) 436 } 437 438 func (a *float64Array) swap(i, j int) { 439 (*a)[i], (*a)[j] = (*a)[j], (*a)[i] 440 } 441 442 func (a *float64Array) typeMatch(v Value) bool { 443 switch v.(type) { 444 case valueInt, valueFloat: 445 return true 446 } 447 return false 448 } 449 450 func (a *typedArrayObject) _getIdx(idx int) Value { 451 if 0 <= idx && idx < a.length { 452 if !a.viewedArrayBuf.ensureNotDetached(false) { 453 return nil 454 } 455 return a.typedArray.get(idx + a.offset) 456 } 457 return nil 458 } 459 460 func (a *typedArrayObject) getOwnPropStr(name unistring.String) Value { 461 idx, ok := strToIntNum(name) 462 if ok { 463 v := a._getIdx(idx) 464 if v != nil { 465 return &valueProperty{ 466 value: v, 467 writable: true, 468 enumerable: true, 469 configurable: true, 470 } 471 } 472 return nil 473 } 474 if idx == 0 { 475 return nil 476 } 477 return a.baseObject.getOwnPropStr(name) 478 } 479 480 func (a *typedArrayObject) getOwnPropIdx(idx valueInt) Value { 481 v := a._getIdx(toIntClamp(int64(idx))) 482 if v != nil { 483 return &valueProperty{ 484 value: v, 485 writable: true, 486 enumerable: true, 487 configurable: true, 488 } 489 } 490 return nil 491 } 492 493 func (a *typedArrayObject) getStr(name unistring.String, receiver Value) Value { 494 idx, ok := strToIntNum(name) 495 if ok { 496 return a._getIdx(idx) 497 } 498 if idx == 0 { 499 return nil 500 } 501 return a.baseObject.getStr(name, receiver) 502 } 503 504 func (a *typedArrayObject) getIdx(idx valueInt, receiver Value) Value { 505 return a._getIdx(toIntClamp(int64(idx))) 506 } 507 508 func (a *typedArrayObject) isValidIntegerIndex(idx int) bool { 509 if a.viewedArrayBuf.ensureNotDetached(false) { 510 if idx >= 0 && idx < a.length { 511 return true 512 } 513 } 514 return false 515 } 516 517 func (a *typedArrayObject) _putIdx(idx int, v Value) { 518 v = v.ToNumber() 519 if a.isValidIntegerIndex(idx) { 520 a.typedArray.set(idx+a.offset, v) 521 } 522 } 523 524 func (a *typedArrayObject) _hasIdx(idx int) bool { 525 return a.isValidIntegerIndex(idx) 526 } 527 528 func (a *typedArrayObject) setOwnStr(p unistring.String, v Value, throw bool) bool { 529 idx, ok := strToIntNum(p) 530 if ok { 531 a._putIdx(idx, v) 532 return true 533 } 534 if idx == 0 { 535 v.ToNumber() // make sure it throws 536 return true 537 } 538 return a.baseObject.setOwnStr(p, v, throw) 539 } 540 541 func (a *typedArrayObject) setOwnIdx(p valueInt, v Value, throw bool) bool { 542 a._putIdx(toIntClamp(int64(p)), v) 543 return true 544 } 545 546 func (a *typedArrayObject) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) { 547 return a._setForeignStr(p, a.getOwnPropStr(p), v, receiver, throw) 548 } 549 550 func (a *typedArrayObject) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) { 551 return a._setForeignIdx(p, trueValIfPresent(a.hasOwnPropertyIdx(p)), v, receiver, throw) 552 } 553 554 func (a *typedArrayObject) hasOwnPropertyStr(name unistring.String) bool { 555 idx, ok := strToIntNum(name) 556 if ok { 557 return a._hasIdx(idx) 558 } 559 if idx == 0 { 560 return false 561 } 562 return a.baseObject.hasOwnPropertyStr(name) 563 } 564 565 func (a *typedArrayObject) hasOwnPropertyIdx(idx valueInt) bool { 566 return a._hasIdx(toIntClamp(int64(idx))) 567 } 568 569 func (a *typedArrayObject) hasPropertyStr(name unistring.String) bool { 570 idx, ok := strToIntNum(name) 571 if ok { 572 return a._hasIdx(idx) 573 } 574 if idx == 0 { 575 return false 576 } 577 return a.baseObject.hasPropertyStr(name) 578 } 579 580 func (a *typedArrayObject) hasPropertyIdx(idx valueInt) bool { 581 return a.hasOwnPropertyIdx(idx) 582 } 583 584 func (a *typedArrayObject) _defineIdxProperty(idx int, desc PropertyDescriptor, throw bool) bool { 585 if desc.Configurable == FLAG_FALSE || desc.Enumerable == FLAG_FALSE || desc.IsAccessor() || desc.Writable == FLAG_FALSE { 586 a.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", idx) 587 return false 588 } 589 _, ok := a._defineOwnProperty(unistring.String(strconv.Itoa(idx)), a.getOwnPropIdx(valueInt(idx)), desc, throw) 590 if ok { 591 if !a.isValidIntegerIndex(idx) { 592 a.val.runtime.typeErrorResult(throw, "Invalid typed array index") 593 return false 594 } 595 a._putIdx(idx, desc.Value) 596 return true 597 } 598 return ok 599 } 600 601 func (a *typedArrayObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool { 602 idx, ok := strToIntNum(name) 603 if ok { 604 return a._defineIdxProperty(idx, desc, throw) 605 } 606 if idx == 0 { 607 a.viewedArrayBuf.ensureNotDetached(throw) 608 a.val.runtime.typeErrorResult(throw, "Invalid typed array index") 609 return false 610 } 611 return a.baseObject.defineOwnPropertyStr(name, desc, throw) 612 } 613 614 func (a *typedArrayObject) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool { 615 return a._defineIdxProperty(toIntClamp(int64(name)), desc, throw) 616 } 617 618 func (a *typedArrayObject) deleteStr(name unistring.String, throw bool) bool { 619 idx, ok := strToIntNum(name) 620 if ok { 621 if a.isValidIntegerIndex(idx) { 622 a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String()) 623 return false 624 } 625 return true 626 } 627 if idx == 0 { 628 return true 629 } 630 return a.baseObject.deleteStr(name, throw) 631 } 632 633 func (a *typedArrayObject) deleteIdx(idx valueInt, throw bool) bool { 634 if a.viewedArrayBuf.ensureNotDetached(false) && idx >= 0 && int64(idx) < int64(a.length) { 635 a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String()) 636 return false 637 } 638 639 return true 640 } 641 642 func (a *typedArrayObject) stringKeys(all bool, accum []Value) []Value { 643 if accum == nil { 644 accum = make([]Value, 0, a.length) 645 } 646 for i := 0; i < a.length; i++ { 647 accum = append(accum, asciiString(strconv.Itoa(i))) 648 } 649 return a.baseObject.stringKeys(all, accum) 650 } 651 652 type typedArrayPropIter struct { 653 a *typedArrayObject 654 idx int 655 } 656 657 func (i *typedArrayPropIter) next() (propIterItem, iterNextFunc) { 658 if i.idx < i.a.length { 659 name := strconv.Itoa(i.idx) 660 prop := i.a._getIdx(i.idx) 661 i.idx++ 662 return propIterItem{name: asciiString(name), value: prop}, i.next 663 } 664 665 return i.a.baseObject.iterateStringKeys()() 666 } 667 668 func (a *typedArrayObject) iterateStringKeys() iterNextFunc { 669 return (&typedArrayPropIter{ 670 a: a, 671 }).next 672 } 673 674 func (r *Runtime) _newTypedArrayObject(buf *arrayBufferObject, offset, length, elemSize int, defCtor *Object, arr typedArray, proto *Object) *typedArrayObject { 675 o := &Object{runtime: r} 676 a := &typedArrayObject{ 677 baseObject: baseObject{ 678 val: o, 679 class: classObject, 680 prototype: proto, 681 extensible: true, 682 }, 683 viewedArrayBuf: buf, 684 offset: offset, 685 length: length, 686 elemSize: elemSize, 687 defaultCtor: defCtor, 688 typedArray: arr, 689 } 690 o.self = a 691 a.init() 692 return a 693 694 } 695 696 func (r *Runtime) newUint8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 697 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8Array, (*uint8Array)(&buf.data), proto) 698 } 699 700 func (r *Runtime) newUint8ClampedArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 701 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8ClampedArray, (*uint8ClampedArray)(&buf.data), proto) 702 } 703 704 func (r *Runtime) newInt8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 705 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Int8Array, (*int8Array)(unsafe.Pointer(&buf.data)), proto) 706 } 707 708 func (r *Runtime) newUint16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 709 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Uint16Array, (*uint16Array)(unsafe.Pointer(&buf.data)), proto) 710 } 711 712 func (r *Runtime) newInt16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 713 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Int16Array, (*int16Array)(unsafe.Pointer(&buf.data)), proto) 714 } 715 716 func (r *Runtime) newUint32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 717 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Uint32Array, (*uint32Array)(unsafe.Pointer(&buf.data)), proto) 718 } 719 720 func (r *Runtime) newInt32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 721 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Int32Array, (*int32Array)(unsafe.Pointer(&buf.data)), proto) 722 } 723 724 func (r *Runtime) newFloat32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 725 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Float32Array, (*float32Array)(unsafe.Pointer(&buf.data)), proto) 726 } 727 728 func (r *Runtime) newFloat64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { 729 return r._newTypedArrayObject(buf, offset, length, 8, r.global.Float64Array, (*float64Array)(unsafe.Pointer(&buf.data)), proto) 730 } 731 732 func (o *dataViewObject) getIdxAndByteOrder(getIdx int, littleEndianVal Value, size int) (int, byteOrder) { 733 o.viewedArrayBuf.ensureNotDetached(true) 734 if getIdx+size > o.byteLen { 735 panic(o.val.runtime.newError(o.val.runtime.global.RangeError, "Index %d is out of bounds", getIdx)) 736 } 737 getIdx += o.byteOffset 738 var bo byteOrder 739 if littleEndianVal != nil { 740 if littleEndianVal.ToBoolean() { 741 bo = littleEndian 742 } else { 743 bo = bigEndian 744 } 745 } else { 746 bo = nativeEndian 747 } 748 return getIdx, bo 749 } 750 751 func (o *arrayBufferObject) ensureNotDetached(throw bool) bool { 752 if o.detached { 753 o.val.runtime.typeErrorResult(throw, "ArrayBuffer is detached") 754 return false 755 } 756 return true 757 } 758 759 func (o *arrayBufferObject) getFloat32(idx int, byteOrder byteOrder) float32 { 760 return math.Float32frombits(o.getUint32(idx, byteOrder)) 761 } 762 763 func (o *arrayBufferObject) setFloat32(idx int, val float32, byteOrder byteOrder) { 764 o.setUint32(idx, math.Float32bits(val), byteOrder) 765 } 766 767 func (o *arrayBufferObject) getFloat64(idx int, byteOrder byteOrder) float64 { 768 return math.Float64frombits(o.getUint64(idx, byteOrder)) 769 } 770 771 func (o *arrayBufferObject) setFloat64(idx int, val float64, byteOrder byteOrder) { 772 o.setUint64(idx, math.Float64bits(val), byteOrder) 773 } 774 775 func (o *arrayBufferObject) getUint64(idx int, byteOrder byteOrder) uint64 { 776 var b []byte 777 if byteOrder == nativeEndian { 778 b = o.data[idx : idx+8] 779 } else { 780 b = make([]byte, 8) 781 d := o.data[idx : idx+8] 782 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] 783 } 784 return *((*uint64)(unsafe.Pointer(&b[0]))) 785 } 786 787 func (o *arrayBufferObject) setUint64(idx int, val uint64, byteOrder byteOrder) { 788 if byteOrder == nativeEndian { 789 *(*uint64)(unsafe.Pointer(&o.data[idx])) = val 790 } else { 791 b := (*[8]byte)(unsafe.Pointer(&val)) 792 d := o.data[idx : idx+8] 793 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] 794 } 795 } 796 797 func (o *arrayBufferObject) getUint32(idx int, byteOrder byteOrder) uint32 { 798 var b []byte 799 if byteOrder == nativeEndian { 800 b = o.data[idx : idx+4] 801 } else { 802 b = make([]byte, 4) 803 d := o.data[idx : idx+4] 804 b[0], b[1], b[2], b[3] = d[3], d[2], d[1], d[0] 805 } 806 return *((*uint32)(unsafe.Pointer(&b[0]))) 807 } 808 809 func (o *arrayBufferObject) setUint32(idx int, val uint32, byteOrder byteOrder) { 810 o.ensureNotDetached(true) 811 if byteOrder == nativeEndian { 812 *(*uint32)(unsafe.Pointer(&o.data[idx])) = val 813 } else { 814 b := (*[4]byte)(unsafe.Pointer(&val)) 815 d := o.data[idx : idx+4] 816 d[0], d[1], d[2], d[3] = b[3], b[2], b[1], b[0] 817 } 818 } 819 820 func (o *arrayBufferObject) getUint16(idx int, byteOrder byteOrder) uint16 { 821 var b []byte 822 if byteOrder == nativeEndian { 823 b = o.data[idx : idx+2] 824 } else { 825 b = make([]byte, 2) 826 d := o.data[idx : idx+2] 827 b[0], b[1] = d[1], d[0] 828 } 829 return *((*uint16)(unsafe.Pointer(&b[0]))) 830 } 831 832 func (o *arrayBufferObject) setUint16(idx int, val uint16, byteOrder byteOrder) { 833 if byteOrder == nativeEndian { 834 *(*uint16)(unsafe.Pointer(&o.data[idx])) = val 835 } else { 836 b := (*[2]byte)(unsafe.Pointer(&val)) 837 d := o.data[idx : idx+2] 838 d[0], d[1] = b[1], b[0] 839 } 840 } 841 842 func (o *arrayBufferObject) getUint8(idx int) uint8 { 843 return o.data[idx] 844 } 845 846 func (o *arrayBufferObject) setUint8(idx int, val uint8) { 847 o.data[idx] = val 848 } 849 850 func (o *arrayBufferObject) getInt32(idx int, byteOrder byteOrder) int32 { 851 return int32(o.getUint32(idx, byteOrder)) 852 } 853 854 func (o *arrayBufferObject) setInt32(idx int, val int32, byteOrder byteOrder) { 855 o.setUint32(idx, uint32(val), byteOrder) 856 } 857 858 func (o *arrayBufferObject) getInt16(idx int, byteOrder byteOrder) int16 { 859 return int16(o.getUint16(idx, byteOrder)) 860 } 861 862 func (o *arrayBufferObject) setInt16(idx int, val int16, byteOrder byteOrder) { 863 o.setUint16(idx, uint16(val), byteOrder) 864 } 865 866 func (o *arrayBufferObject) getInt8(idx int) int8 { 867 return int8(o.data[idx]) 868 } 869 870 func (o *arrayBufferObject) setInt8(idx int, val int8) { 871 o.setUint8(idx, uint8(val)) 872 } 873 874 func (o *arrayBufferObject) detach() { 875 o.data = nil 876 o.detached = true 877 } 878 879 func (o *arrayBufferObject) exportType() reflect.Type { 880 return arrayBufferType 881 } 882 883 func (o *arrayBufferObject) export(*objectExportCtx) interface{} { 884 return ArrayBuffer{ 885 buf: o, 886 } 887 } 888 889 func (r *Runtime) _newArrayBuffer(proto *Object, o *Object) *arrayBufferObject { 890 if o == nil { 891 o = &Object{runtime: r} 892 } 893 b := &arrayBufferObject{ 894 baseObject: baseObject{ 895 class: classObject, 896 val: o, 897 prototype: proto, 898 extensible: true, 899 }, 900 } 901 o.self = b 902 b.init() 903 return b 904 } 905 906 func init() { 907 buf := [2]byte{} 908 *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xCAFE) 909 910 switch buf { 911 case [2]byte{0xFE, 0xCA}: 912 nativeEndian = littleEndian 913 case [2]byte{0xCA, 0xFE}: 914 nativeEndian = bigEndian 915 default: 916 panic("Could not determine native endianness.") 917 } 918 }