From ac2ea62348e326758746429c8cc68fb2256188e1 Mon Sep 17 00:00:00 2001 From: Dmitry Panov Date: Fri, 16 Aug 2024 18:18:43 +0100 Subject: [PATCH 1/2] Updated tc39 tests. A number of fixes as a result: - 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(). --- .tc39_test262_checkout.sh | 4 +- builtin_regexp.go | 17 +++--- builtin_typedarrays.go | 34 +++++++---- compiler_test.go | 12 ---- date_parser.go | 4 ++ runtime.go | 3 +- runtime_test.go | 11 ++++ string_ascii.go | 9 ++- tc39_test.go | 35 +++++++++++ vm.go | 121 +++++++++++++++++++++++--------------- 10 files changed, 166 insertions(+), 84 deletions(-) diff --git a/.tc39_test262_checkout.sh b/.tc39_test262_checkout.sh index 65dedfc..1500daa 100755 --- a/.tc39_test262_checkout.sh +++ b/.tc39_test262_checkout.sh @@ -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 diff --git a/builtin_regexp.go b/builtin_regexp.go index 2d02b66..14d875b 100644 --- a/builtin_regexp.go +++ b/builtin_regexp.go @@ -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 { @@ -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 } @@ -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) diff --git a/builtin_typedarrays.go b/builtin_typedarrays.go index 1443134..b927460 100644 --- a/builtin_typedarrays.go +++ b/builtin_typedarrays.go @@ -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) @@ -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) @@ -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] @@ -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{ @@ -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) } @@ -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 @@ -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 { diff --git a/compiler_test.go b/compiler_test.go index 05d82ca..c9ba80e 100644 --- a/compiler_test.go +++ b/compiler_test.go @@ -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 { } diff --git a/date_parser.go b/date_parser.go index f836053..762888c 100644 --- a/date_parser.go +++ b/date_parser.go @@ -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 { diff --git a/runtime.go b/runtime.go index ff7f7e6..ca869f6 100644 --- a/runtime.go +++ b/runtime.go @@ -45,8 +45,7 @@ const ( ) type global struct { - stash stash - varNames map[unistring.String]struct{} + stash stash Object *Object Array *Object diff --git a/runtime_test.go b/runtime_test.go index 708ce7f..f2992d5 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -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) diff --git a/string_ascii.go b/string_ascii.go index 5ff21bf..a74dd63 100644 --- a/string_ascii.go +++ b/string_ascii.go @@ -114,7 +114,7 @@ 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 } @@ -122,7 +122,14 @@ func (s asciiString) _toFloat() (float64, error) { 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 } diff --git a/tc39_test.go b/tc39_test.go index 841feae..16d3a26 100644 --- a/tc39_test.go +++ b/tc39_test.go @@ -185,6 +185,17 @@ 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, @@ -192,6 +203,9 @@ var ( "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 @@ -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{ @@ -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", @@ -222,6 +242,7 @@ var ( "import.meta", "Atomics", "Atomics.waitAsync", + "Atomics.pause", "FinalizationRegistry", "WeakRef", "numeric-separator-literal", @@ -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", } ) diff --git a/vm.go b/vm.go index 30b7933..c09e00d 100644 --- a/vm.go +++ b/vm.go @@ -208,6 +208,48 @@ func (r *stashRefConst) set(v Value) { } type objRef struct { + base *Object + name Value + this Value + strict bool + + nameConverted bool +} + +func (r *objRef) getKey() Value { + if !r.nameConverted { + r.name = toPropertyKey(r.name) + r.nameConverted = true + } + return r.name +} + +func (r *objRef) get() Value { + return r.base.get(r.getKey(), r.this) +} + +func (r *objRef) set(v Value) { + key := r.getKey() + if r.this != nil { + r.base.set(key, v, r.this, r.strict) + } else { + r.base.setOwn(key, v, r.strict) + } +} + +func (r *objRef) init(v Value) { + if r.this != nil { + r.base.set(r.getKey(), v, r.this, r.strict) + } else { + r.base.setOwn(r.getKey(), v, r.strict) + } +} + +func (r *objRef) refname() unistring.String { + return r.getKey().string() +} + +type objStrRef struct { base *Object name unistring.String this Value @@ -215,11 +257,11 @@ type objRef struct { binding bool } -func (r *objRef) get() Value { +func (r *objStrRef) get() Value { return r.base.self.getStr(r.name, r.this) } -func (r *objRef) set(v Value) { +func (r *objStrRef) set(v Value) { if r.strict && r.binding && !r.base.self.hasOwnPropertyStr(r.name) { panic(referenceError(fmt.Sprintf("%s is not defined", r.name))) } @@ -230,7 +272,7 @@ func (r *objRef) set(v Value) { } } -func (r *objRef) init(v Value) { +func (r *objStrRef) init(v Value) { if r.this != nil { r.base.setStr(r.name, v, r.this, r.strict) } else { @@ -238,7 +280,7 @@ func (r *objRef) init(v Value) { } } -func (r *objRef) refname() unistring.String { +func (r *objStrRef) refname() unistring.String { return r.name } @@ -465,7 +507,7 @@ func (s *stash) getByName(name unistring.String) (v Value, exists bool) { func (s *stash) getRefByName(name unistring.String, strict bool) ref { if obj := s.obj; obj != nil { if stashObjHas(obj, name) { - return &objRef{ + return &objStrRef{ base: obj, name: name, strict: strict, @@ -1588,10 +1630,10 @@ var getElemRef _getElemRef func (_getElemRef) exec(vm *vm) { obj := vm.stack[vm.sp-2].ToObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-1]) + propName := vm.stack[vm.sp-1] vm.refStack = append(vm.refStack, &objRef{ base: obj, - name: propName.string(), + name: propName, }) vm.sp -= 2 vm.pc++ @@ -1603,10 +1645,10 @@ var getElemRefRecv _getElemRefRecv func (_getElemRefRecv) exec(vm *vm) { obj := vm.stack[vm.sp-1].ToObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-2]) + propName := vm.stack[vm.sp-2] vm.refStack = append(vm.refStack, &objRef{ base: obj, - name: propName.string(), + name: propName, this: vm.stack[vm.sp-3], }) vm.sp -= 3 @@ -1619,10 +1661,10 @@ var getElemRefStrict _getElemRefStrict func (_getElemRefStrict) exec(vm *vm) { obj := vm.stack[vm.sp-2].ToObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-1]) + propName := vm.stack[vm.sp-1] vm.refStack = append(vm.refStack, &objRef{ base: obj, - name: propName.string(), + name: propName, strict: true, }) vm.sp -= 2 @@ -1635,10 +1677,10 @@ var getElemRefRecvStrict _getElemRefRecvStrict func (_getElemRefRecvStrict) exec(vm *vm) { obj := vm.stack[vm.sp-1].ToObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-2]) + propName := vm.stack[vm.sp-2] vm.refStack = append(vm.refStack, &objRef{ base: obj, - name: propName.string(), + name: propName, this: vm.stack[vm.sp-3], strict: true, }) @@ -1908,7 +1950,7 @@ func (d deletePropStrict) exec(vm *vm) { type getPropRef unistring.String func (p getPropRef) exec(vm *vm) { - vm.refStack = append(vm.refStack, &objRef{ + vm.refStack = append(vm.refStack, &objStrRef{ base: vm.stack[vm.sp-1].ToObject(vm.r), name: unistring.String(p), }) @@ -1919,7 +1961,7 @@ func (p getPropRef) exec(vm *vm) { type getPropRefRecv unistring.String func (p getPropRefRecv) exec(vm *vm) { - vm.refStack = append(vm.refStack, &objRef{ + vm.refStack = append(vm.refStack, &objStrRef{ this: vm.stack[vm.sp-2], base: vm.stack[vm.sp-1].ToObject(vm.r), name: unistring.String(p), @@ -1931,7 +1973,7 @@ func (p getPropRefRecv) exec(vm *vm) { type getPropRefStrict unistring.String func (p getPropRefStrict) exec(vm *vm) { - vm.refStack = append(vm.refStack, &objRef{ + vm.refStack = append(vm.refStack, &objStrRef{ base: vm.stack[vm.sp-1].ToObject(vm.r), name: unistring.String(p), strict: true, @@ -1943,7 +1985,7 @@ func (p getPropRefStrict) exec(vm *vm) { type getPropRefRecvStrict unistring.String func (p getPropRefRecvStrict) exec(vm *vm) { - vm.refStack = append(vm.refStack, &objRef{ + vm.refStack = append(vm.refStack, &objStrRef{ this: vm.stack[vm.sp-2], base: vm.stack[vm.sp-1].ToObject(vm.r), name: unistring.String(p), @@ -2330,11 +2372,11 @@ var getElem _getElem func (_getElem) exec(vm *vm) { v := vm.stack[vm.sp-2] obj := v.baseObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-1]) if obj == nil { - vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String())) + vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", vm.stack[vm.sp-1])) return } + propName := toPropertyKey(vm.stack[vm.sp-1]) vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v)) @@ -2348,13 +2390,13 @@ var getElemRecv _getElemRecv func (_getElemRecv) exec(vm *vm) { recv := vm.stack[vm.sp-3] - propName := toPropertyKey(vm.stack[vm.sp-2]) v := vm.stack[vm.sp-1] obj := v.baseObject(vm.r) if obj == nil { - vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String())) + vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", vm.stack[vm.sp-2])) return } + propName := toPropertyKey(vm.stack[vm.sp-2]) vm.stack[vm.sp-3] = nilSafe(obj.get(propName, recv)) @@ -2388,12 +2430,12 @@ var getElemCallee _getElemCallee func (_getElemCallee) exec(vm *vm) { v := vm.stack[vm.sp-2] obj := v.baseObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-1]) if obj == nil { - vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String())) + vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", vm.stack[vm.sp-1])) return } + propName := toPropertyKey(vm.stack[vm.sp-1]) prop := obj.get(propName, v) if prop == nil { prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}} @@ -2411,12 +2453,12 @@ func (_getElemRecvCallee) exec(vm *vm) { recv := vm.stack[vm.sp-3] v := vm.stack[vm.sp-2] obj := v.baseObject(vm.r) - propName := toPropertyKey(vm.stack[vm.sp-1]) if obj == nil { - vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String())) + vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", vm.stack[vm.sp-1])) return } + propName := toPropertyKey(vm.stack[vm.sp-1]) prop := obj.get(propName, recv) if prop == nil { prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}} @@ -2654,7 +2696,7 @@ func (s resolveVar1) exec(vm *vm) { } } - ref = &objRef{ + ref = &objStrRef{ base: vm.r.globalObject, name: name, binding: true, @@ -2708,9 +2750,6 @@ func (d deleteGlobal) exec(vm *vm) { var ret bool if vm.r.globalObject.self.hasPropertyStr(name) { ret = vm.r.globalObject.self.deleteStr(name, false) - if ret { - delete(vm.r.global.varNames, name) - } } else { ret = true } @@ -2735,7 +2774,7 @@ func (s resolveVar1Strict) exec(vm *vm) { } if vm.r.globalObject.self.hasPropertyStr(name) { - ref = &objRef{ + ref = &objStrRef{ base: vm.r.globalObject, name: name, binding: true, @@ -3876,18 +3915,12 @@ func (vm *vm) checkBindVarsGlobal(names []unistring.String) { } func (vm *vm) createGlobalVarBindings(names []unistring.String, d bool) { - globalVarNames := vm.r.global.varNames - if globalVarNames == nil { - globalVarNames = make(map[unistring.String]struct{}) - vm.r.global.varNames = globalVarNames - } o := vm.r.globalObject.self - if bo, ok := o.(*baseObject); ok { + if bo, ok := o.(*templatedObject); ok { for _, name := range names { if !bo.hasOwnPropertyStr(name) && bo.extensible { bo._putProp(name, _undefined, true, true, d) } - globalVarNames[name] = struct{}{} } } else { var cf Flag @@ -3906,21 +3939,15 @@ func (vm *vm) createGlobalVarBindings(names []unistring.String, d bool) { }, true) o.setOwnStr(name, _undefined, false) } - globalVarNames[name] = struct{}{} } } } func (vm *vm) createGlobalFuncBindings(names []unistring.String, d bool) { - globalVarNames := vm.r.global.varNames - if globalVarNames == nil { - globalVarNames = make(map[unistring.String]struct{}) - vm.r.global.varNames = globalVarNames - } o := vm.r.globalObject.self b := vm.sp - len(names) - var shortcutObj *baseObject - if o, ok := o.(*baseObject); ok { + var shortcutObj *templatedObject + if o, ok := o.(*templatedObject); ok { shortcutObj = o } for i, name := range names { @@ -3948,7 +3975,6 @@ func (vm *vm) createGlobalFuncBindings(names []unistring.String, d bool) { o.setOwnStr(name, desc.Value, false) // not a bug, see https://262.ecma-international.org/#sec-createglobalfunctionbinding } } - globalVarNames[name] = struct{}{} } vm.sp = b } @@ -3978,9 +4004,6 @@ func (vm *vm) checkBindLexGlobal(names []unistring.String) { o := vm.r.globalObject.self s := &vm.r.global.stash for _, name := range names { - if _, exists := vm.r.global.varNames[name]; exists { - goto fail - } if _, exists := s.names[name]; exists { goto fail } From 8130cadc5774d6c30ecbef6e9cb07c406afcdcc5 Mon Sep 17 00:00:00 2001 From: Dmitry Panov Date: Fri, 16 Aug 2024 19:12:38 +0100 Subject: [PATCH 2/2] Skip Unicode 14 and 15 tests for Go versions < 1.21 --- go.mod | 1 + go.sum | 33 ++------------------------------- tc39_test.go | 23 +++++++++++++++++++---- 3 files changed, 22 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 74f938b..103a3f1 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/dop251/goja go 1.20 require ( + github.com/Masterminds/semver/v3 v3.2.1 github.com/dlclark/regexp2 v1.11.4 github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d github.com/go-sourcemap/sourcemap v2.1.3+incompatible diff --git a/go.sum b/go.sum index 0ff74a7..14a87f4 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,7 @@ -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dlclark/regexp2 v1.11.3 h1:tdwMFLz4VxHteujuVYHzG5Bje3M2ORsvv2jvbCTufTA= -github.com/dlclark/regexp2 v1.11.3/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= @@ -17,7 +12,6 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyL github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -28,33 +22,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/tc39_test.go b/tc39_test.go index 16d3a26..a7ff693 100644 --- a/tc39_test.go +++ b/tc39_test.go @@ -6,12 +6,14 @@ import ( "io" "os" "path" + "runtime/debug" "sort" "strings" "sync" "testing" "time" + "github.com/Masterminds/semver/v3" "gopkg.in/yaml.v2" ) @@ -269,7 +271,14 @@ var ( } ) +var goVersion *semver.Version + func init() { + if info, ok := debug.ReadBuildInfo(); ok { + goVersion = semver.MustParse(strings.TrimPrefix(info.GoVersion, "go")) + } else { + panic("Could not read build info") + } skip := func(prefixes ...string) { for _, prefix := range prefixes { @@ -277,11 +286,17 @@ func init() { } } - skip( - // Go 1.16 only supports unicode 13 - "test/language/identifiers/start-unicode-14.", - "test/language/identifiers/part-unicode-14.", + if goVersion.LessThan(semver.MustParse("1.21")) { + skip( + // Go <1.21 only supports Unicode 13 + "test/language/identifiers/start-unicode-14.", + "test/language/identifiers/part-unicode-14.", + "test/language/identifiers/start-unicode-15.", + "test/language/identifiers/part-unicode-15.", + ) + } + skip( // generators and async generators (harness/hidden-constructors.js) "test/built-ins/Async",