Skip to content

Commit

Permalink
Standard compliance and other fixes for ArrayBuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
dop251 committed Apr 26, 2020
1 parent 99a706f commit 1edec86
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
41 changes: 26 additions & 15 deletions builtin_typedarrays.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package goja

import (
"fmt"
"math"
"sort"
"strings"
Expand Down Expand Up @@ -61,23 +62,34 @@ func (ctx *typedArraySortCtx) Swap(i, j int) {
ctx.ta.typedArray.swap(offset+i, offset+j)
}

func allocByteSlice(size int) (b []byte) {
defer func() {
if x := recover(); x != nil {
panic(rangeError(fmt.Sprintf("Buffer size is too large: %d", size)))
}
}()
if size < 0 {
panic(rangeError(fmt.Sprintf("Invalid buffer size: %d", size)))
}
b = make([]byte, size)
return
}

func (r *Runtime) builtin_newArrayBuffer(args []Value, newTarget *Object) *Object {
if newTarget == nil {
panic(r.needNew("ArrayBuffer"))
}
b := r._newArrayBuffer(r.getPrototypeFromCtor(newTarget, r.global.ArrayBuffer, r.global.ArrayBufferPrototype), nil)
if len(args) > 0 {
b.data = make([]byte, toLength(args[0]))
b.data = allocByteSlice(r.toIndex(args[0]))
}
return b.val
}

func (r *Runtime) arrayBufferProto_getByteLength(call FunctionCall) Value {
o := r.toObject(call.This)
if b, ok := o.self.(*arrayBufferObject); ok {
if b.data == nil {
panic(r.NewTypeError("ArrayBuffer is detached"))
}
b.ensureNotDetached()
return intToValue(int64(len(b.data)))
}
panic(r.NewTypeError("Object is not ArrayBuffer: %s", o))
Expand All @@ -87,29 +99,25 @@ func (r *Runtime) arrayBufferProto_slice(call FunctionCall) Value {
o := r.toObject(call.This)
if b, ok := o.self.(*arrayBufferObject); ok {
l := int64(len(b.data))
start := relToIdx(toLength(call.Argument(0)), l)
start := relToIdx(call.Argument(0).ToInteger(), l)
var stop int64
if arg := call.Argument(1); arg != _undefined {
stop = toLength(arg)
stop = arg.ToInteger()
} else {
stop = l
}
stop = relToIdx(stop, l)
newLen := max(stop-start, 0)
ret := r.speciesConstructor(o, r.global.ArrayBuffer)([]Value{intToValue(newLen)}, nil)
if ab, ok := ret.self.(*arrayBufferObject); ok {
if ab.data == nil {
panic(r.NewTypeError("Species constructor returned a detached ArrayBuffer"))
}
ab.ensureNotDetached()
if ret == o {
panic(r.NewTypeError("Species constructor returned the same ArrayBuffer"))
}
if int64(len(ab.data)) < newLen {
panic(r.NewTypeError("Species constructor returned an ArrayBuffer that is too small: %d", len(ab.data)))
}
if b.data == nil {
panic(r.NewTypeError("Species constructor has detached the current ArrayBuffer"))
}
b.ensureNotDetached()

if stop > start {
copy(ab.data, b.data[start:stop])
Expand All @@ -122,10 +130,13 @@ func (r *Runtime) arrayBufferProto_slice(call FunctionCall) Value {
}

func (r *Runtime) arrayBuffer_isView(call FunctionCall) Value {
if o, ok := call.This.(*Object); ok {
if o, ok := call.Argument(0).(*Object); ok {
if _, ok := o.self.(*dataViewObject); ok {
return valueTrue
}
if _, ok := o.self.(*typedArrayObject); ok {
return valueTrue
}
}
return valueFalse
}
Expand Down Expand Up @@ -1047,7 +1058,7 @@ func (r *Runtime) allocateTypedArray(newTarget *Object, length int, taCtor typed
buf := r._newArrayBuffer(r.global.ArrayBufferPrototype, nil)
ta := taCtor(buf, 0, length, r.getPrototypeFromCtor(newTarget, nil, r.global.TypedArrayPrototype))
if length > 0 {
buf.data = make([]byte, length*ta.elemSize)
buf.data = allocByteSlice(length * ta.elemSize)
}
return ta.val
}
Expand Down Expand Up @@ -1157,7 +1168,7 @@ func (r *Runtime) _newTypedArrayFromTypedArray(src *typedArrayObject, newTarget
src.viewedArrayBuf.ensureNotDetached()
l := src.length
dst.viewedArrayBuf.prototype = r.getPrototypeFromCtor(r.toObject(src.viewedArrayBuf.getStr("constructor", nil)), r.global.ArrayBuffer, r.global.ArrayBufferPrototype)
dst.viewedArrayBuf.data = make([]byte, int64(l)*int64(dst.elemSize))
dst.viewedArrayBuf.data = allocByteSlice(toInt(int64(l) * int64(dst.elemSize)))
if src.defaultCtor == dst.defaultCtor {
copy(dst.viewedArrayBuf.data, src.viewedArrayBuf.data[src.offset*src.elemSize:])
dst.length = src.length
Expand Down
10 changes: 10 additions & 0 deletions tc39_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ var (
"test/built-ins/Date/prototype/toISOString/15.9.5.43-0-10.js": true, // timezone
"test/annexB/built-ins/escape/escape-above-astral.js": true, // \u{xxxxx}

// SharedArrayBuffer
"test/built-ins/ArrayBuffer/prototype/slice/this-is-sharedarraybuffer.js": true,

// class
"test/language/statements/class/subclass/builtin-objects/Symbol/symbol-valid-as-extends-value.js": true,
"test/language/statements/class/subclass/builtin-objects/Symbol/new-symbol-with-super-throws.js": true,
Expand Down Expand Up @@ -96,6 +99,10 @@ var (
"test/language/statements/class/subclass/builtin-objects/Array/regular-subclassing.js": true,
"test/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-single-argument.js": true,
"test/language/statements/class/subclass/builtin-objects/Array/contructor-calls-super-multiple-arguments.js": true,
"test/language/statements/class/subclass/builtin-objects/ArrayBuffer/super-must-be-called.js": true,
"test/language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing.js": true,
"test/built-ins/ArrayBuffer/isView/arg-is-typedarray-subclass-instance.js": true,
"test/built-ins/ArrayBuffer/isView/arg-is-dataview-subclass-instance.js": true,

// full unicode regexp flag
"test/built-ins/RegExp/prototype/Symbol.match/u-advance-after-empty.js": true,
Expand Down Expand Up @@ -155,6 +162,7 @@ var (
"23.2",
"23.3",
"23.4",
"24.1",
"24.2",
"25.1.2",
"26.1",
Expand All @@ -170,6 +178,8 @@ var (
"sec-date",
"sec-number",
"sec-math",
"sec-arraybuffer-length",
"sec-arraybuffer",
}
)

Expand Down

0 comments on commit 1edec86

Please sign in to comment.