1 package goja
2
3 import (
4 "math"
5 "reflect"
6 "strconv"
7 "unsafe"
8
9 "github.com/dop251/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
34
35
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
90
91 func (a ArrayBuffer) Bytes() []byte {
92 return a.buf.data
93 }
94
95
96
97
98
99
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
109 func (a ArrayBuffer) Detached() bool {
110 return a.buf.detached
111 }
112
113
114
115
116
117
118
119 func (r *Runtime) NewArrayBuffer(data []byte) ArrayBuffer {
120 buf := r._newArrayBuffer(r.getArrayBufferPrototype(), 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 {
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()
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
905
906 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8Array, (*uint8Array)(&buf.data), proto)
907 }
908
909 func (r *Runtime) newUint8ClampedArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
910 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8ClampedArray, (*uint8ClampedArray)(&buf.data), proto)
911 }
912
913 func (r *Runtime) newInt8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
914 return r._newTypedArrayObject(buf, offset, length, 1, r.global.Int8Array, (*int8Array)(&buf.data), proto)
915 }
916
917 func (r *Runtime) newUint16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
918 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Uint16Array, (*uint16Array)(&buf.data), proto)
919 }
920
921 func (r *Runtime) newInt16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
922 return r._newTypedArrayObject(buf, offset, length, 2, r.global.Int16Array, (*int16Array)(&buf.data), proto)
923 }
924
925 func (r *Runtime) newUint32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
926 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Uint32Array, (*uint32Array)(&buf.data), proto)
927 }
928
929 func (r *Runtime) newInt32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
930 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Int32Array, (*int32Array)(&buf.data), proto)
931 }
932
933 func (r *Runtime) newFloat32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
934 return r._newTypedArrayObject(buf, offset, length, 4, r.global.Float32Array, (*float32Array)(&buf.data), proto)
935 }
936
937 func (r *Runtime) newFloat64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
938 return r._newTypedArrayObject(buf, offset, length, 8, r.global.Float64Array, (*float64Array)(&buf.data), proto)
939 }
940
941 func (o *dataViewObject) getIdxAndByteOrder(getIdx int, littleEndianVal Value, size int) (int, byteOrder) {
942 o.viewedArrayBuf.ensureNotDetached(true)
943 if getIdx+size > o.byteLen {
944 panic(o.val.runtime.newError(o.val.runtime.getRangeError(), "Index %d is out of bounds", getIdx))
945 }
946 getIdx += o.byteOffset
947 var bo byteOrder
948 if littleEndianVal != nil {
949 if littleEndianVal.ToBoolean() {
950 bo = littleEndian
951 } else {
952 bo = bigEndian
953 }
954 } else {
955 bo = nativeEndian
956 }
957 return getIdx, bo
958 }
959
960 func (o *arrayBufferObject) ensureNotDetached(throw bool) bool {
961 if o.detached {
962 o.val.runtime.typeErrorResult(throw, "ArrayBuffer is detached")
963 return false
964 }
965 return true
966 }
967
968 func (o *arrayBufferObject) getFloat32(idx int, byteOrder byteOrder) float32 {
969 return math.Float32frombits(o.getUint32(idx, byteOrder))
970 }
971
972 func (o *arrayBufferObject) setFloat32(idx int, val float32, byteOrder byteOrder) {
973 o.setUint32(idx, math.Float32bits(val), byteOrder)
974 }
975
976 func (o *arrayBufferObject) getFloat64(idx int, byteOrder byteOrder) float64 {
977 return math.Float64frombits(o.getUint64(idx, byteOrder))
978 }
979
980 func (o *arrayBufferObject) setFloat64(idx int, val float64, byteOrder byteOrder) {
981 o.setUint64(idx, math.Float64bits(val), byteOrder)
982 }
983
984 func (o *arrayBufferObject) getUint64(idx int, byteOrder byteOrder) uint64 {
985 var b []byte
986 if byteOrder == nativeEndian {
987 b = o.data[idx : idx+8]
988 } else {
989 b = make([]byte, 8)
990 d := o.data[idx : idx+8]
991 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]
992 }
993 return *((*uint64)(unsafe.Pointer(&b[0])))
994 }
995
996 func (o *arrayBufferObject) setUint64(idx int, val uint64, byteOrder byteOrder) {
997 if byteOrder == nativeEndian {
998 *(*uint64)(unsafe.Pointer(&o.data[idx])) = val
999 } else {
1000 b := (*[8]byte)(unsafe.Pointer(&val))
1001 d := o.data[idx : idx+8]
1002 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]
1003 }
1004 }
1005
1006 func (o *arrayBufferObject) getUint32(idx int, byteOrder byteOrder) uint32 {
1007 var b []byte
1008 if byteOrder == nativeEndian {
1009 b = o.data[idx : idx+4]
1010 } else {
1011 b = make([]byte, 4)
1012 d := o.data[idx : idx+4]
1013 b[0], b[1], b[2], b[3] = d[3], d[2], d[1], d[0]
1014 }
1015 return *((*uint32)(unsafe.Pointer(&b[0])))
1016 }
1017
1018 func (o *arrayBufferObject) setUint32(idx int, val uint32, byteOrder byteOrder) {
1019 o.ensureNotDetached(true)
1020 if byteOrder == nativeEndian {
1021 *(*uint32)(unsafe.Pointer(&o.data[idx])) = val
1022 } else {
1023 b := (*[4]byte)(unsafe.Pointer(&val))
1024 d := o.data[idx : idx+4]
1025 d[0], d[1], d[2], d[3] = b[3], b[2], b[1], b[0]
1026 }
1027 }
1028
1029 func (o *arrayBufferObject) getUint16(idx int, byteOrder byteOrder) uint16 {
1030 var b []byte
1031 if byteOrder == nativeEndian {
1032 b = o.data[idx : idx+2]
1033 } else {
1034 b = make([]byte, 2)
1035 d := o.data[idx : idx+2]
1036 b[0], b[1] = d[1], d[0]
1037 }
1038 return *((*uint16)(unsafe.Pointer(&b[0])))
1039 }
1040
1041 func (o *arrayBufferObject) setUint16(idx int, val uint16, byteOrder byteOrder) {
1042 if byteOrder == nativeEndian {
1043 *(*uint16)(unsafe.Pointer(&o.data[idx])) = val
1044 } else {
1045 b := (*[2]byte)(unsafe.Pointer(&val))
1046 d := o.data[idx : idx+2]
1047 d[0], d[1] = b[1], b[0]
1048 }
1049 }
1050
1051 func (o *arrayBufferObject) getUint8(idx int) uint8 {
1052 return o.data[idx]
1053 }
1054
1055 func (o *arrayBufferObject) setUint8(idx int, val uint8) {
1056 o.data[idx] = val
1057 }
1058
1059 func (o *arrayBufferObject) getInt32(idx int, byteOrder byteOrder) int32 {
1060 return int32(o.getUint32(idx, byteOrder))
1061 }
1062
1063 func (o *arrayBufferObject) setInt32(idx int, val int32, byteOrder byteOrder) {
1064 o.setUint32(idx, uint32(val), byteOrder)
1065 }
1066
1067 func (o *arrayBufferObject) getInt16(idx int, byteOrder byteOrder) int16 {
1068 return int16(o.getUint16(idx, byteOrder))
1069 }
1070
1071 func (o *arrayBufferObject) setInt16(idx int, val int16, byteOrder byteOrder) {
1072 o.setUint16(idx, uint16(val), byteOrder)
1073 }
1074
1075 func (o *arrayBufferObject) getInt8(idx int) int8 {
1076 return int8(o.data[idx])
1077 }
1078
1079 func (o *arrayBufferObject) setInt8(idx int, val int8) {
1080 o.setUint8(idx, uint8(val))
1081 }
1082
1083 func (o *arrayBufferObject) detach() {
1084 o.data = nil
1085 o.detached = true
1086 }
1087
1088 func (o *arrayBufferObject) exportType() reflect.Type {
1089 return arrayBufferType
1090 }
1091
1092 func (o *arrayBufferObject) export(*objectExportCtx) interface{} {
1093 return ArrayBuffer{
1094 buf: o,
1095 }
1096 }
1097
1098 func (o *arrayBufferObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
1099 if typ == typeBytes {
1100 dst.Set(reflect.ValueOf(o.data))
1101 return nil
1102 }
1103 return o.baseObject.exportToArrayOrSlice(dst, typ, ctx)
1104 }
1105
1106 func (r *Runtime) _newArrayBuffer(proto *Object, o *Object) *arrayBufferObject {
1107 if o == nil {
1108 o = &Object{runtime: r}
1109 }
1110 b := &arrayBufferObject{
1111 baseObject: baseObject{
1112 class: classObject,
1113 val: o,
1114 prototype: proto,
1115 extensible: true,
1116 },
1117 }
1118 o.self = b
1119 b.init()
1120 return b
1121 }
1122
1123 func init() {
1124 buf := [2]byte{}
1125 *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xCAFE)
1126
1127 switch buf {
1128 case [2]byte{0xFE, 0xCA}:
1129 nativeEndian = littleEndian
1130 case [2]byte{0xCA, 0xFE}:
1131 nativeEndian = bigEndian
1132 default:
1133 panic("Could not determine native endianness.")
1134 }
1135 }
1136
View as plain text