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  }