Skip to content

Commit

Permalink
Updated tc39 tests. A number of fixes as a result:
Browse files Browse the repository at this point in the history
- Fixed panic if target ArrayBuffer gets detached during TypedArray.from().
- Use the "flags" property, rather than "global" and "unicode" in RegExp matcher and replacer.
- Do not throw if ArrayBuffer is detached during TypedArray.sort().
- Do not use species constructor when creating a TypedArray from another TypedArray.
- Allow global lexical bindings override variable bindings created by eval().
- Do not accept -00000 as year in Date.parse().
- Fixed object references with Symbol property names.
- Do not call toPropertyKey prematurely when creating object references and some other cases.
- Make "Infinity" case-sensitive and do not accept "inf" in Number().
  • Loading branch information
dop251 committed Aug 16, 2024
1 parent 7d18bf7 commit ac2ea62
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 84 deletions.
4 changes: 2 additions & 2 deletions .tc39_test262_checkout.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh
#!/bin/sh -e
# this is just the commit it was last tested with
sha=926b0960d737b9f1dfd0ec0c1dfd95d836016d33
sha=cb4a6c8074671c00df8cbc17a620c0f9462b312a

mkdir -p testdata/test262
cd testdata/test262
Expand Down
17 changes: 10 additions & 7 deletions builtin_regexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,7 @@ func (r *Runtime) regExpExec(execFn func(FunctionCall) Value, rxObj *Object, arg
return res
}

func (r *Runtime) getGlobalRegexpMatches(rxObj *Object, s String) []Value {
fullUnicode := nilSafe(rxObj.self.getStr("unicode", nil)).ToBoolean()
func (r *Runtime) getGlobalRegexpMatches(rxObj *Object, s String, fullUnicode bool) []Value {
rxObj.self.setOwnStr("lastIndex", intToValue(0), true)
execFn, ok := r.toObject(rxObj.self.getStr("exec", nil)).self.assertCallable()
if !ok {
Expand All @@ -714,9 +713,10 @@ func (r *Runtime) getGlobalRegexpMatches(rxObj *Object, s String) []Value {

func (r *Runtime) regexpproto_stdMatcherGeneric(rxObj *Object, s String) Value {
rx := rxObj.self
global := rx.getStr("global", nil)
if global != nil && global.ToBoolean() {
a := r.getGlobalRegexpMatches(rxObj, s)
flags := nilSafe(rx.getStr("flags", nil)).String()
global := strings.ContainsRune(flags, 'g')
if global {
a := r.getGlobalRegexpMatches(rxObj, s, strings.ContainsRune(flags, 'u'))
if len(a) == 0 {
return _null
}
Expand Down Expand Up @@ -1092,8 +1092,11 @@ RETURN:

func (r *Runtime) regexpproto_stdReplacerGeneric(rxObj *Object, s, replaceStr String, rcall func(FunctionCall) Value) Value {
var results []Value
if nilSafe(rxObj.self.getStr("global", nil)).ToBoolean() {
results = r.getGlobalRegexpMatches(rxObj, s)
flags := nilSafe(rxObj.self.getStr("flags", nil)).String()
isGlobal := strings.ContainsRune(flags, 'g')
isUnicode := strings.ContainsRune(flags, 'u')
if isGlobal {
results = r.getGlobalRegexpMatches(rxObj, s, isUnicode)
} else {
execFn := toMethod(rxObj.self.getStr("exec", nil)) // must be non-nil
result := r.regExpExec(execFn, rxObj, s)
Expand Down
34 changes: 23 additions & 11 deletions builtin_typedarrays.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@ type typedArraySortCtx struct {
ta *typedArrayObject
compare func(FunctionCall) Value
needValidate bool
detached bool
}

func (ctx *typedArraySortCtx) Len() int {
return ctx.ta.length
}

func (ctx *typedArraySortCtx) Less(i, j int) bool {
if ctx.needValidate {
ctx.ta.viewedArrayBuf.ensureNotDetached(true)
func (ctx *typedArraySortCtx) checkDetached() {
if !ctx.detached && ctx.needValidate {
ctx.detached = !ctx.ta.viewedArrayBuf.ensureNotDetached(false)
ctx.needValidate = false
}
}

func (ctx *typedArraySortCtx) Less(i, j int) bool {
ctx.checkDetached()
if ctx.detached {
return false
}
offset := ctx.ta.offset
if ctx.compare != nil {
x := ctx.ta.typedArray.get(offset + i)
Expand Down Expand Up @@ -54,9 +62,9 @@ func (ctx *typedArraySortCtx) Less(i, j int) bool {
}

func (ctx *typedArraySortCtx) Swap(i, j int) {
if ctx.needValidate {
ctx.ta.viewedArrayBuf.ensureNotDetached(true)
ctx.needValidate = false
ctx.checkDetached()
if ctx.detached {
return
}
offset := ctx.ta.offset
ctx.ta.typedArray.swap(offset+i, offset+j)
Expand Down Expand Up @@ -146,7 +154,6 @@ func (r *Runtime) newDataView(args []Value, newTarget *Object) *Object {
if newTarget == nil {
panic(r.needNew("DataView"))
}
proto := r.getPrototypeFromCtor(newTarget, r.getDataView(), r.getDataViewPrototype())
var bufArg Value
if len(args) > 0 {
bufArg = args[0]
Expand Down Expand Up @@ -177,6 +184,14 @@ func (r *Runtime) newDataView(args []Value, newTarget *Object) *Object {
} else {
byteLen = len(buffer.data) - byteOffset
}
proto := r.getPrototypeFromCtor(newTarget, r.getDataView(), r.getDataViewPrototype())
buffer.ensureNotDetached(true)
if byteOffset > len(buffer.data) {
panic(r.newError(r.getRangeError(), "Start offset %d is outside the bounds of the buffer", byteOffset))
}
if byteOffset+byteLen > len(buffer.data) {
panic(r.newError(r.getRangeError(), "Invalid DataView length %d", byteLen))
}
o := &Object{runtime: r}
b := &dataViewObject{
baseObject: baseObject{
Expand Down Expand Up @@ -1007,7 +1022,6 @@ func (r *Runtime) typedArrayProto_set(call FunctionCall) Value {
}
for i := 0; i < srcLen; i++ {
val := nilSafe(srcObj.self.getIdx(valueInt(i), nil))
ta.viewedArrayBuf.ensureNotDetached(true)
if ta.isValidIntegerIndex(i) {
ta.typedArray.set(targetOffset+i, val)
}
Expand Down Expand Up @@ -1270,7 +1284,7 @@ func (r *Runtime) typedArray_from(call FunctionCall) Value {
for idx, val := range values {
fc.Arguments[0], fc.Arguments[1] = val, intToValue(int64(idx))
val = mapFc(fc)
ta.typedArray.set(idx, val)
ta._putIdx(idx, val)
}
}
return ta.val
Expand Down Expand Up @@ -1417,8 +1431,6 @@ func (r *Runtime) _newTypedArrayFromTypedArray(src *typedArrayObject, newTarget
src.viewedArrayBuf.ensureNotDetached(true)
l := src.length

arrayBuffer := r.getArrayBuffer()
dst.viewedArrayBuf.prototype = r.getPrototypeFromCtor(r.speciesConstructorObj(src.viewedArrayBuf.val, arrayBuffer), arrayBuffer, r.getArrayBufferPrototype())
dst.viewedArrayBuf.data = allocByteSlice(toIntStrict(int64(l) * int64(dst.elemSize)))
src.viewedArrayBuf.ensureNotDetached(true)
if src.defaultCtor == dst.defaultCtor {
Expand Down
12 changes: 0 additions & 12 deletions compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3135,18 +3135,6 @@ func TestDeleteGlobalEval(t *testing.T) {
testScript(SCRIPT, valueTrue, t)
}

func TestGlobalVarNames(t *testing.T) {
vm := New()
_, err := vm.RunString("(0,eval)('var x')")
if err != nil {
t.Fatal(err)
}
_, err = vm.RunString("let x")
if err == nil {
t.Fatal("Expected error")
}
}

func TestTryResultEmpty(t *testing.T) {
const SCRIPT = `
1; try { } finally { }
Expand Down
4 changes: 4 additions & 0 deletions date_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ func parseDate(layout, value string, defaultLocation *time.Location) (time.Time,
p, value = value[1:7], value[7:]
year, err = atoi(p)
if neg {
if year == 0 {
err = errBad
break
}
year = -year
}
} else {
Expand Down
3 changes: 1 addition & 2 deletions runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ const (
)

type global struct {
stash stash
varNames map[unistring.String]struct{}
stash stash

Object *Object
Array *Object
Expand Down
11 changes: 11 additions & 0 deletions runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2968,6 +2968,17 @@ func ExampleRuntime_ForOf() {
// Output: a=1,b=2,
}

func TestDestructAssignToSymbol(t *testing.T) {
const SCRIPT = `
const s = Symbol('s');
const target = {};
({a: target[s]} = {a: 42});
assert.sameValue(target[s], 42);
`
testScriptWithTestLib(SCRIPT, _undefined, t)
}

/*
func TestArrayConcatSparse(t *testing.T) {
function foo(a,b,c)
Expand Down
9 changes: 8 additions & 1 deletion string_ascii.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,22 @@ func isRangeErr(err error) bool {
}

func (s asciiString) _toFloat() (float64, error) {
ss := strings.TrimSpace(string(s))
ss := strings.ToLower(strings.TrimSpace(string(s)))
if ss == "" {
return 0, nil
}
if ss == "-0" {
var f float64
return -f, nil
}

f, err := strconv.ParseFloat(ss, 64)
if err == nil && math.IsInf(f, 0) {
if strings.HasPrefix(ss, "inf") || strings.HasPrefix(ss, "-inf") || strings.HasPrefix(ss, "+inf") {
// We handle "Infinity" separately, prevent from being parsed as Infinity due to strconv.ParseFloat() permissive syntax
return 0, strconv.ErrSyntax
}
}
if isRangeErr(err) {
err = nil
}
Expand Down
35 changes: 35 additions & 0 deletions tc39_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,27 @@ var (
"test/built-ins/TypedArray/prototype/toReversed/this-value-invalid.js": true,
"test/built-ins/TypedArray/prototype/toSorted/comparefn-not-a-function.js": true,
"test/built-ins/TypedArray/prototype/toSorted/this-value-invalid.js": true,
"test/built-ins/RegExp/prototype/sticky/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/source/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/multiline/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/ignoreCase/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/unicode/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/dotAll/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/global/this-val-non-obj.js": true,
"test/built-ins/RegExp/prototype/flags/this-val-non-obj.js": true,
"test/built-ins/Iterator/prototype/Symbol.iterator/return-val.js": true,
"test/built-ins/DataView/prototype/setBigUint64/not-a-constructor.js": true,
"test/built-ins/DataView/prototype/getBigUint64/not-a-constructor.js": true,

// Regexp
"test/language/literals/regexp/invalid-range-negative-lookbehind.js": true,
"test/language/literals/regexp/invalid-range-lookbehind.js": true,
"test/language/literals/regexp/invalid-optional-negative-lookbehind.js": true,
"test/language/literals/regexp/invalid-optional-lookbehind.js": true,

// unicode full case folding
"test/built-ins/RegExp/unicode_full_case_folding.js": true,

// FIXME bugs

// Left-hand side as a CoverParenthesizedExpression
Expand All @@ -203,6 +217,9 @@ var (

// Skip due to regexp named groups
"test/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js": true,

"test/built-ins/RegExp/nullable-quantifier.js": true,
"test/built-ins/RegExp/lookahead-quantifier-match-groups.js": true,
}

featuresBlackList = []string{
Expand All @@ -211,8 +228,11 @@ var (
"BigInt",
"resizable-arraybuffer",
"regexp-named-groups",
"regexp-duplicate-named-groups",
"regexp-unicode-property-escapes",
"regexp-match-indices",
"regexp-modifiers",
"RegExp.escape",
"legacy-regexp",
"tail-call-optimization",
"Temporal",
Expand All @@ -222,6 +242,7 @@ var (
"import.meta",
"Atomics",
"Atomics.waitAsync",
"Atomics.pause",
"FinalizationRegistry",
"WeakRef",
"numeric-separator-literal",
Expand All @@ -231,6 +252,20 @@ var (
"SharedArrayBuffer",
"decorators",
"regexp-v-flag",
"iterator-helpers",
"symbols-as-weakmap-keys",
"uint8array-base64",
"String.prototype.toWellFormed",
"explicit-resource-management",
"set-methods",
"promise-try",
"promise-with-resolvers",
"array-grouping",
"Math.sumPrecise",
"Float16Array",
"arraybuffer-transfer",
"Array.fromAsync",
"String.prototype.isWellFormed",
}
)

Expand Down
Loading

0 comments on commit ac2ea62

Please sign in to comment.