diff --git a/go.mod b/go.mod index 1bb607c88b6..d7acc2227b3 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/google/pprof v0.0.0-20230728192033-2ba5b33183c6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3 + github.com/grafana/sobek v0.0.0-20240823144814-3c582bfdac82 github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect diff --git a/go.sum b/go.sum index 17c0fbba1ca..e81f55f2503 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v0.0.0-20180330214955-e67964b4021a h1:zpQSzEApXM0qkXcpdjeJ4OpnBWhD/X8zT/iT1wYLiVU= github.com/DataDog/datadog-go v0.0.0-20180330214955-e67964b4021a/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +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/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5 h1:k+1+doEm31k0rRjCjLnGG3YRkuO9ljaEyS2ajZd6GK8= @@ -87,8 +89,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3 h1:mJ1DN6EDA5MlRtcspUjVTsfINUVJMd4Yw70RdFoKN8E= -github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3/go.mod h1:14YTHWUwjApKs5kzRn+4akwbvPMRsXEmjfozc5OmT0I= +github.com/grafana/sobek v0.0.0-20240823144814-3c582bfdac82 h1:bOg9X3uXuOSjQmIhxefNpClq0pA8C4T+bzHpE6DuaOk= +github.com/grafana/sobek v0.0.0-20240823144814-3c582bfdac82/go.mod h1:FmcutBFPLiGgroH42I4/HBahv7GxVjODcVWFTw1ISes= github.com/grafana/xk6-browser v1.7.1 h1:RKCcoFyKT97iGgbnK76WwxcXnkB23ijlO1LghqjHQ0E= github.com/grafana/xk6-browser v1.7.1/go.mod h1:sZO7cT7/XQf2mz+rXkp6poswhOCA0JKA8isj3fQrfaU= github.com/grafana/xk6-dashboard v0.7.5 h1:TcILyffT/Ea/XD7xG1jMA5lwtusOPRbEQsQDHmO30Mk= diff --git a/js/bundle_test.go b/js/bundle_test.go index 2d193ddc46b..8aa2df1da1c 100644 --- a/js/bundle_test.go +++ b/js/bundle_test.go @@ -189,13 +189,6 @@ func TestNewBundle(t *testing.T) { "InvalidCompat", "es1", `export default function() {};`, `invalid compatibility mode "es1". Use: "extended", "base", "experimental_enhanced"`, }, - // BigInt is not supported - { - "BigInt", "base", - `module.exports.default = function() {}; -BigInt(1231412444)`, - "ReferenceError: BigInt is not defined\n\tat file:///script.js:2:7(7)\n", - }, } for _, tc := range testCases { diff --git a/js/modules/k6/crypto/x509/x509_test.go b/js/modules/k6/crypto/x509/x509_test.go index e5ef0ec7670..280b7e0b04a 100644 --- a/js/modules/k6/crypto/x509/x509_test.go +++ b/js/modules/k6/crypto/x509/x509_test.go @@ -577,7 +577,7 @@ func TestParse(t *testing.T) { value.algorithm === "RSA" && typeof value.key === "object" && typeof value.key.e === "number" && - typeof value.key.n === "object" + typeof value.key.n === "bigint" )) { throw new Error("Bad RSA public key"); }`, material.rsaCertificate)) @@ -607,29 +607,10 @@ func TestParse(t *testing.T) { _, err := rt.RunString(fmt.Sprintf(` var pem = %q; var cert = x509.parse(pem); - var value = cert.publicKey ? cert.publicKey.key.n.bytes() : null; - var expected = [ - 223, 249, 234, 71, 180, 36, 28, 62, 84, 141, 177, 118, 53, 2, 175, - 45, 167, 89, 155, 216, 103, 86, 32, 216, 42, 92, 84, 125, 183, 102, - 217, 40, 255, 129, 38, 203, 175, 98, 209, 147, 151, 106, 250, 12, - 123, 236, 135, 45, 80, 80, 76, 253, 148, 141, 13, 36, 76, 47, 182, - 58, 100, 153, 114, 13, 141, 96, 12, 109, 126, 74, 68, 119, 88, 15, - 52, 107, 80, 117, 190, 163, 230, 120, 26, 44, 139, 245, 222, 188, - 210, 237, 123, 83, 91, 98, 160, 218, 229, 244, 128, 31, 24, 139, - 125, 25, 184, 108, 180, 23, 149, 136, 47, 140, 168, 51, 159, 35, - 65, 150, 7, 51, 134, 138, 188, 225, 105, 92, 9, 91, 72, 133, 70, - 195, 131, 105, 184, 191, 198, 177, 130, 191, 70, 6, 37, 159, 255, - 244, 109, 238, 128, 138, 0, 201, 41, 87, 67, 87, 165, 118, 4, 253, - 209, 31, 177, 1, 1, 116, 64, 14, 17, 19, 217, 6, 117, 75, 24, 174, - 236, 129, 134, 115, 245, 226, 203, 222, 17, 113, 197, 215, 138, - 241, 99, 169, 68, 77, 243, 36, 116, 69, 143, 150, 60, 245, 75, 200, - 30, 207, 141, 139, 136, 35, 125, 184, 255, 174, 26, 6, 148, 56, - 253, 124, 249, 158, 249, 117, 3, 126, 124, 89, 27, 96, 209, 0, 207, - 152, 233, 166, 81, 7, 253, 155, 165, 96, 29, 72, 28, 172, 24, 104, - 70, 229, 201, 107, 200, 169, 220, 35 - ] - if (value.join(":") !== expected.join(":")) { - throw new Error("Bad RSA public key modulus: " + value.join(":")); + var value = cert.publicKey ? cert.publicKey.key.n.toString(16) : null; + var expected = "dff9ea47b4241c3e548db1763502af2da7599bd8675620d82a5c547db766d928ff8126cbaf62d193976afa0c7bec872d50504cfd948d0d244c2fb63a6499720d8d600c6d7e4a4477580f346b5075bea3e6781a2c8bf5debcd2ed7b535b62a0dae5f4801f188b7d19b86cb41795882f8ca8339f2341960733868abce1695c095b488546c38369b8bfc6b182bf4606259ffff46dee808a00c929574357a57604fdd11fb1010174400e1113d906754b18aeec818673f5e2cbde1171c5d78af163a9444df32474458f963cf54bc81ecf8d8b88237db8ffae1a069438fd7cf99ef975037e7c591b60d100cf98e9a65107fd9ba5601d481cac186846e5c96bc8a9dc23"; + if (value !== expected) { + throw new Error("Bad RSA public key modulus: " + value); }`, material.rsaCertificate)) assert.NoError(t, err) }) @@ -648,7 +629,7 @@ func TestParse(t *testing.T) { typeof value === "object" && value.algorithm === "DSA" && typeof value.key.parameters === "object" && - typeof value.key.y === "object" + typeof value.key.y === "bigint" )) { throw new Error("Bad DSA public key"); }`, material.dsaCertificate)) @@ -669,8 +650,8 @@ func TestParse(t *testing.T) { typeof value === "object" && value.algorithm === "ECDSA" && typeof value.key.curve === "object" && - typeof value.key.x === "object" && - typeof value.key.y === "object" + typeof value.key.x === "bigint" && + typeof value.key.y === "bigint" )) { throw new Error("Bad ECDSA public key"); }`, material.ecdsaCertificate)) diff --git a/js/tc39/breaking_test_errors-experimental_enhanced.json b/js/tc39/breaking_test_errors-experimental_enhanced.json index 88528f6ad21..9ffc8b15732 100644 --- a/js/tc39/breaking_test_errors-experimental_enhanced.json +++ b/js/tc39/breaking_test_errors-experimental_enhanced.json @@ -9,15 +9,13 @@ "test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js-strict:true": "test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js: Test262Error: Code unit: d800 Expected SameValue(«\\\\\\ud800», «\\�») to be true ", "test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js-strict:true": "test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js: Test262Error: Code unit: d800 Expected SameValue(«a\\\\\\ud800», «a\\�») to be true ", "test/annexB/built-ins/RegExp/prototype/compile/pattern-string-invalid-u.js-strict:true": "test/annexB/built-ins/RegExp/prototype/compile/pattern-string-invalid-u.js: Test262Error: invalid pattern: { Expected a SyntaxError to be thrown but no exception was thrown at all ", - "test/built-ins/AsyncArrowFunction/is-a-constructor.js-strict:true": "test/built-ins/AsyncArrowFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", "test/built-ins/AsyncFunction/AsyncFunction-is-subclass.js-strict:true": "test/built-ins/AsyncFunction/AsyncFunction-is-subclass.js: Test262Error: Prototype of constructor is Function Expected SameValue(«function () { [native code] }», «function Function() { [native code] }») to be true ", - "test/built-ins/AsyncFunction/is-a-constructor.js-strict:true": "test/built-ins/AsyncFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", "test/built-ins/Date/UTC/fp-evaluation-order.js-strict:true": "test/built-ins/Date/UTC/fp-evaluation-order.js: Test262Error: order of operations / precision in MakeTime Expected SameValue(«29256», «29312») to be true ", "test/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js-strict:true": "test/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all ", - "test/built-ins/GeneratorFunction/is-a-constructor.js-strict:true": "test/built-ins/GeneratorFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", - "test/built-ins/Object/seal/seal-bigint64array.js-strict:true": "test/built-ins/Object/seal/seal-bigint64array.js: ReferenceError: BigInt64Array is not defined ", - "test/built-ins/Object/seal/seal-biguint64array.js-strict:true": "test/built-ins/Object/seal/seal-biguint64array.js: ReferenceError: BigUint64Array is not defined ", + "test/built-ins/RegExp/lookahead-quantifier-match-groups.js-strict:true": "test/built-ins/RegExp/lookahead-quantifier-match-groups.js: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier ", + "test/built-ins/RegExp/nullable-quantifier.js-strict:true": "test/built-ins/RegExp/nullable-quantifier.js: Test262Error: The regex is expected to match the whole string Expected SameValue(«a», «ab») to be true ", "test/built-ins/RegExp/quantifier-integer-limit.js-strict:true": "test/built-ins/RegExp/quantifier-integer-limit.js: SyntaxError: Invalid regular expression (re2): b{9007199254740991} (error parsing regexp: invalid repeat count: `{9007199254740991}`) ", + "test/built-ins/RegExp/unicode_full_case_folding.js-strict:true": "test/built-ins/RegExp/unicode_full_case_folding.js: Test262Error: \\u0390 does not match \\u1fd3 ", "test/built-ins/RegExp/unicode_restricted_brackets.js-strict:true": "test/built-ins/RegExp/unicode_restricted_brackets.js: Test262Error: RegExp(\"]\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_character_class_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_character_class_escape.js: Test262Error: RegExp(\"[\\d-a]\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_identity_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_identity_escape.js: Test262Error: Invalid IdentityEscape in AtomEscape: '\\\u0000' Expected a SyntaxError to be thrown but no exception was thrown at all ", @@ -28,12 +26,11 @@ "test/built-ins/RegExp/unicode_restricted_incomplete_quantifier.js-strict:true": "test/built-ins/RegExp/unicode_restricted_incomplete_quantifier.js: Test262Error: RegExp(\"a{\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_octal_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_octal_escape.js: Test262Error: RegExp(\"\\1\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js-strict:true": "test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js: Test262Error: RegExp(\"(?=.)*\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", - "test/built-ins/TypedArrayConstructors/BigUint64Array/is-a-constructor.js-strict:true": "test/built-ins/TypedArrayConstructors/BigUint64Array/is-a-constructor.js: ReferenceError: BigUint64Array is not defined ", "test/language/comments/hashbang/function-constructor.js-strict:true": "test/language/comments/hashbang/function-constructor.js: SyntaxError: Async generators are not supported yet ", "test/language/comments/hashbang/module.js-strict:false": "test/language/comments/hashbang/module.js: file:///TestTC39/test262/test/language/comments/hashbang/module.js: Line 1:28 Unexpected token ILLEGAL (and 2 more errors)", "test/language/destructuring/binding/syntax/destructuring-array-parameters-function-arguments-length.js-strict:true": "test/language/destructuring/binding/syntax/destructuring-array-parameters-function-arguments-length.js: SyntaxError: Async generators are not supported yet ", "test/language/destructuring/binding/syntax/destructuring-object-parameters-function-arguments-length.js-strict:true": "test/language/destructuring/binding/syntax/destructuring-object-parameters-function-arguments-length.js: SyntaxError: Async generators are not supported yet ", - "test/language/expressions/assignment/fn-name-lhs-cover.js-strict:true": "test/language/expressions/assignment/fn-name-lhs-cover.js: Test262Error: descriptor value should be ", + "test/language/expressions/assignment/fn-name-lhs-cover.js-strict:true": "test/language/expressions/assignment/fn-name-lhs-cover.js: Test262Error: descriptor value should be ; object value should be ", "test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js-strict:true": "test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js: test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js: Line 9:5 Unexpected token await (and 1 more errors)", "test/language/expressions/await/await-BindingIdentifier-in-global.js-strict:true": "test/language/expressions/await/await-BindingIdentifier-in-global.js: test/language/expressions/await/await-BindingIdentifier-in-global.js: Line 12:16 Unexpected token await (and 2 more errors)", "test/language/expressions/await/await-in-global.js-strict:true": "test/language/expressions/await/await-in-global.js: test/language/expressions/await/await-in-global.js: Line 12:5 Unexpected token await (and 1 more errors)", @@ -63,7 +60,7 @@ "test/language/expressions/object/method-definition/static-init-await-reference-accessor.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-accessor.js: test/language/expressions/object/method-definition/static-init-await-reference-accessor.js: Line 15:5 Unexpected token await (and 1 more errors)", "test/language/expressions/object/method-definition/static-init-await-reference-generator.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-generator.js: test/language/expressions/object/method-definition/static-init-await-reference-generator.js: Line 15:5 Unexpected token await (and 1 more errors)", "test/language/expressions/object/method-definition/static-init-await-reference-normal.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-normal.js: test/language/expressions/object/method-definition/static-init-await-reference-normal.js: Line 15:5 Unexpected token await (and 1 more errors)", - "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js-strict:true": "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: Line 31:7 Unexpected token await (and 9 more errors)", + "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js-strict:true": "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: Line 32:7 Unexpected token await (and 9 more errors)", "test/language/expressions/optional-chaining/member-expression.js-strict:true": "test/language/expressions/optional-chaining/member-expression.js: SyntaxError: Async generators are not supported yet ", "test/language/global-code/import.js-strict:true": "test/language/global-code/import.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/literals/numeric/non-octal-decimal-integer.js-strict:false": "test/language/literals/numeric/non-octal-decimal-integer.js: test/language/literals/numeric/non-octal-decimal-integer.js: Line 28:18 Unexpected token ILLEGAL (and 1 more errors)", @@ -100,12 +97,12 @@ "test/language/module-code/export-expname-from-as-unpaired-surrogate.js-strict:true": "test/language/module-code/export-expname-from-as-unpaired-surrogate.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/export-expname-string-binding.js-strict:true": "test/language/module-code/export-expname-string-binding.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/export-expname-unpaired-surrogate.js-strict:true": "test/language/module-code/export-expname-unpaired-surrogate.js: error is not an object (Test262: This statement should not be evaluated.)", - "test/language/module-code/instn-iee-err-not-found-as.js-strict:true": "test/language/module-code/instn-iee-err-not-found-as.js: Expected error: ", - "test/language/module-code/instn-iee-err-not-found.js-strict:true": "test/language/module-code/instn-iee-err-not-found.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found-as.js-strict:true": "test/language/module-code/instn-named-err-not-found-as.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found-dflt.js-strict:true": "test/language/module-code/instn-named-err-not-found-dflt.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found.js-strict:true": "test/language/module-code/instn-named-err-not-found.js: Expected error: ", - "test/language/module-code/instn-star-err-not-found.js-strict:true": "test/language/module-code/instn-star-err-not-found.js: Expected error: ", + "test/language/module-code/instn-iee-err-not-found-as.js-strict:true": "test/language/module-code/instn-iee-err-not-found-as.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-iee-err-not-found.js-strict:true": "test/language/module-code/instn-iee-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found-as.js-strict:true": "test/language/module-code/instn-named-err-not-found-as.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found-dflt.js-strict:true": "test/language/module-code/instn-named-err-not-found-dflt.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found.js-strict:true": "test/language/module-code/instn-named-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-star-err-not-found.js-strict:true": "test/language/module-code/instn-star-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/parse-err-hoist-lex-fun.js-strict:true": "test/language/module-code/parse-err-hoist-lex-fun.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/parse-err-return.js-strict:true": "test/language/module-code/parse-err-return.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/reserved-words/await-module.js-strict:true": "test/language/reserved-words/await-module.js: error is not an object (Test262: This statement should not be evaluated.)", diff --git a/js/tc39/breaking_test_errors-extended.json b/js/tc39/breaking_test_errors-extended.json index 88528f6ad21..9ffc8b15732 100644 --- a/js/tc39/breaking_test_errors-extended.json +++ b/js/tc39/breaking_test_errors-extended.json @@ -9,15 +9,13 @@ "test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js-strict:true": "test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js: Test262Error: Code unit: d800 Expected SameValue(«\\\\\\ud800», «\\�») to be true ", "test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js-strict:true": "test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js: Test262Error: Code unit: d800 Expected SameValue(«a\\\\\\ud800», «a\\�») to be true ", "test/annexB/built-ins/RegExp/prototype/compile/pattern-string-invalid-u.js-strict:true": "test/annexB/built-ins/RegExp/prototype/compile/pattern-string-invalid-u.js: Test262Error: invalid pattern: { Expected a SyntaxError to be thrown but no exception was thrown at all ", - "test/built-ins/AsyncArrowFunction/is-a-constructor.js-strict:true": "test/built-ins/AsyncArrowFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", "test/built-ins/AsyncFunction/AsyncFunction-is-subclass.js-strict:true": "test/built-ins/AsyncFunction/AsyncFunction-is-subclass.js: Test262Error: Prototype of constructor is Function Expected SameValue(«function () { [native code] }», «function Function() { [native code] }») to be true ", - "test/built-ins/AsyncFunction/is-a-constructor.js-strict:true": "test/built-ins/AsyncFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", "test/built-ins/Date/UTC/fp-evaluation-order.js-strict:true": "test/built-ins/Date/UTC/fp-evaluation-order.js: Test262Error: order of operations / precision in MakeTime Expected SameValue(«29256», «29312») to be true ", "test/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js-strict:true": "test/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all ", - "test/built-ins/GeneratorFunction/is-a-constructor.js-strict:true": "test/built-ins/GeneratorFunction/is-a-constructor.js: SyntaxError: Async generators are not supported yet ", - "test/built-ins/Object/seal/seal-bigint64array.js-strict:true": "test/built-ins/Object/seal/seal-bigint64array.js: ReferenceError: BigInt64Array is not defined ", - "test/built-ins/Object/seal/seal-biguint64array.js-strict:true": "test/built-ins/Object/seal/seal-biguint64array.js: ReferenceError: BigUint64Array is not defined ", + "test/built-ins/RegExp/lookahead-quantifier-match-groups.js-strict:true": "test/built-ins/RegExp/lookahead-quantifier-match-groups.js: Test262Error: Expected [a, abc] and [a, undefined] to have the same contents. ? quantifier ", + "test/built-ins/RegExp/nullable-quantifier.js-strict:true": "test/built-ins/RegExp/nullable-quantifier.js: Test262Error: The regex is expected to match the whole string Expected SameValue(«a», «ab») to be true ", "test/built-ins/RegExp/quantifier-integer-limit.js-strict:true": "test/built-ins/RegExp/quantifier-integer-limit.js: SyntaxError: Invalid regular expression (re2): b{9007199254740991} (error parsing regexp: invalid repeat count: `{9007199254740991}`) ", + "test/built-ins/RegExp/unicode_full_case_folding.js-strict:true": "test/built-ins/RegExp/unicode_full_case_folding.js: Test262Error: \\u0390 does not match \\u1fd3 ", "test/built-ins/RegExp/unicode_restricted_brackets.js-strict:true": "test/built-ins/RegExp/unicode_restricted_brackets.js: Test262Error: RegExp(\"]\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_character_class_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_character_class_escape.js: Test262Error: RegExp(\"[\\d-a]\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_identity_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_identity_escape.js: Test262Error: Invalid IdentityEscape in AtomEscape: '\\\u0000' Expected a SyntaxError to be thrown but no exception was thrown at all ", @@ -28,12 +26,11 @@ "test/built-ins/RegExp/unicode_restricted_incomplete_quantifier.js-strict:true": "test/built-ins/RegExp/unicode_restricted_incomplete_quantifier.js: Test262Error: RegExp(\"a{\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_octal_escape.js-strict:true": "test/built-ins/RegExp/unicode_restricted_octal_escape.js: Test262Error: RegExp(\"\\1\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", "test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js-strict:true": "test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js: Test262Error: RegExp(\"(?=.)*\", \"u\"): Expected a SyntaxError to be thrown but no exception was thrown at all ", - "test/built-ins/TypedArrayConstructors/BigUint64Array/is-a-constructor.js-strict:true": "test/built-ins/TypedArrayConstructors/BigUint64Array/is-a-constructor.js: ReferenceError: BigUint64Array is not defined ", "test/language/comments/hashbang/function-constructor.js-strict:true": "test/language/comments/hashbang/function-constructor.js: SyntaxError: Async generators are not supported yet ", "test/language/comments/hashbang/module.js-strict:false": "test/language/comments/hashbang/module.js: file:///TestTC39/test262/test/language/comments/hashbang/module.js: Line 1:28 Unexpected token ILLEGAL (and 2 more errors)", "test/language/destructuring/binding/syntax/destructuring-array-parameters-function-arguments-length.js-strict:true": "test/language/destructuring/binding/syntax/destructuring-array-parameters-function-arguments-length.js: SyntaxError: Async generators are not supported yet ", "test/language/destructuring/binding/syntax/destructuring-object-parameters-function-arguments-length.js-strict:true": "test/language/destructuring/binding/syntax/destructuring-object-parameters-function-arguments-length.js: SyntaxError: Async generators are not supported yet ", - "test/language/expressions/assignment/fn-name-lhs-cover.js-strict:true": "test/language/expressions/assignment/fn-name-lhs-cover.js: Test262Error: descriptor value should be ", + "test/language/expressions/assignment/fn-name-lhs-cover.js-strict:true": "test/language/expressions/assignment/fn-name-lhs-cover.js: Test262Error: descriptor value should be ; object value should be ", "test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js-strict:true": "test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js: test/language/expressions/assignmenttargettype/simple-basic-identifierreference-await.js: Line 9:5 Unexpected token await (and 1 more errors)", "test/language/expressions/await/await-BindingIdentifier-in-global.js-strict:true": "test/language/expressions/await/await-BindingIdentifier-in-global.js: test/language/expressions/await/await-BindingIdentifier-in-global.js: Line 12:16 Unexpected token await (and 2 more errors)", "test/language/expressions/await/await-in-global.js-strict:true": "test/language/expressions/await/await-in-global.js: test/language/expressions/await/await-in-global.js: Line 12:5 Unexpected token await (and 1 more errors)", @@ -63,7 +60,7 @@ "test/language/expressions/object/method-definition/static-init-await-reference-accessor.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-accessor.js: test/language/expressions/object/method-definition/static-init-await-reference-accessor.js: Line 15:5 Unexpected token await (and 1 more errors)", "test/language/expressions/object/method-definition/static-init-await-reference-generator.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-generator.js: test/language/expressions/object/method-definition/static-init-await-reference-generator.js: Line 15:5 Unexpected token await (and 1 more errors)", "test/language/expressions/object/method-definition/static-init-await-reference-normal.js-strict:true": "test/language/expressions/object/method-definition/static-init-await-reference-normal.js: test/language/expressions/object/method-definition/static-init-await-reference-normal.js: Line 15:5 Unexpected token await (and 1 more errors)", - "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js-strict:true": "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: Line 31:7 Unexpected token await (and 9 more errors)", + "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js-strict:true": "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: test/language/expressions/optional-chaining/iteration-statement-for-await-of.js: Line 32:7 Unexpected token await (and 9 more errors)", "test/language/expressions/optional-chaining/member-expression.js-strict:true": "test/language/expressions/optional-chaining/member-expression.js: SyntaxError: Async generators are not supported yet ", "test/language/global-code/import.js-strict:true": "test/language/global-code/import.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/literals/numeric/non-octal-decimal-integer.js-strict:false": "test/language/literals/numeric/non-octal-decimal-integer.js: test/language/literals/numeric/non-octal-decimal-integer.js: Line 28:18 Unexpected token ILLEGAL (and 1 more errors)", @@ -100,12 +97,12 @@ "test/language/module-code/export-expname-from-as-unpaired-surrogate.js-strict:true": "test/language/module-code/export-expname-from-as-unpaired-surrogate.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/export-expname-string-binding.js-strict:true": "test/language/module-code/export-expname-string-binding.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/export-expname-unpaired-surrogate.js-strict:true": "test/language/module-code/export-expname-unpaired-surrogate.js: error is not an object (Test262: This statement should not be evaluated.)", - "test/language/module-code/instn-iee-err-not-found-as.js-strict:true": "test/language/module-code/instn-iee-err-not-found-as.js: Expected error: ", - "test/language/module-code/instn-iee-err-not-found.js-strict:true": "test/language/module-code/instn-iee-err-not-found.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found-as.js-strict:true": "test/language/module-code/instn-named-err-not-found-as.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found-dflt.js-strict:true": "test/language/module-code/instn-named-err-not-found-dflt.js: Expected error: ", - "test/language/module-code/instn-named-err-not-found.js-strict:true": "test/language/module-code/instn-named-err-not-found.js: Expected error: ", - "test/language/module-code/instn-star-err-not-found.js-strict:true": "test/language/module-code/instn-star-err-not-found.js: Expected error: ", + "test/language/module-code/instn-iee-err-not-found-as.js-strict:true": "test/language/module-code/instn-iee-err-not-found-as.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-iee-err-not-found.js-strict:true": "test/language/module-code/instn-iee-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found-as.js-strict:true": "test/language/module-code/instn-named-err-not-found-as.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found-dflt.js-strict:true": "test/language/module-code/instn-named-err-not-found-dflt.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-named-err-not-found.js-strict:true": "test/language/module-code/instn-named-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", + "test/language/module-code/instn-star-err-not-found.js-strict:true": "test/language/module-code/instn-star-err-not-found.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/parse-err-hoist-lex-fun.js-strict:true": "test/language/module-code/parse-err-hoist-lex-fun.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/module-code/parse-err-return.js-strict:true": "test/language/module-code/parse-err-return.js: error is not an object (Test262: This statement should not be evaluated.)", "test/language/reserved-words/await-module.js-strict:true": "test/language/reserved-words/await-module.js: error is not an object (Test262: This statement should not be evaluated.)", diff --git a/js/tc39/checkout.sh b/js/tc39/checkout.sh index 26b9de55b98..5408e223649 100755 --- a/js/tc39/checkout.sh +++ b/js/tc39/checkout.sh @@ -1,5 +1,5 @@ -#!/bin/sh -sha=926b0960d737b9f1dfd0ec0c1dfd95d836016d33 # this is just the commit it was last tested with +#!/bin/sh -e +sha=cb4a6c8074671c00df8cbc17a620c0f9462b312a # this is just the commit it was last tested with mkdir -p ./TestTC39/test262 cd ./TestTC39/test262 git init diff --git a/js/tc39/tc39_test.go b/js/tc39/tc39_test.go index 1db4d4a4c2e..3e179b8a727 100644 --- a/js/tc39/tc39_test.go +++ b/js/tc39/tc39_test.go @@ -52,7 +52,6 @@ var ( false) featuresBlockList = []string{ - "BigInt", // not supported at all "IsHTMLDDA", // not supported at all "async-iteration", // not supported at all "top-level-await", // not supported at all @@ -60,11 +59,13 @@ var ( // from Sobek "Symbol.asyncIterator", + "resizable-arraybuffer", "regexp-named-groups", - "regexp-dotall", - "regexp-unicode-property-escapes", + "regexp-duplicate-named-groups", "regexp-unicode-property-escapes", "regexp-match-indices", + "regexp-modifiers", + "RegExp.escape", "legacy-regexp", "tail-call-optimization", "Temporal", @@ -72,6 +73,7 @@ var ( "logical-assignment-operators", "Atomics", "Atomics.waitAsync", + "Atomics.pause", "FinalizationRegistry", "WeakRef", "numeric-separator-literal", @@ -79,10 +81,27 @@ var ( "__setter__", "ShadowRealm", "SharedArrayBuffer", - "error-cause", - "resizable-arraybuffer", // stage 3 as of 2021 https://github.com/tc39/proposal-resizablearraybuffer - - "array-find-from-last", // stage 3 as of 2021 https://github.com/tc39/proposal-array-find-from-last + "decorators", + + "regexp-duplicate-named-groups", + "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", + + "source-phase-imports", + "import-attributes", } skipWords = []string{} skipList = map[string]bool{ diff --git a/vendor/github.com/grafana/sobek/.tc39_test262_checkout.sh b/vendor/github.com/grafana/sobek/.tc39_test262_checkout.sh index a72fc156322..1500daa976a 100644 --- a/vendor/github.com/grafana/sobek/.tc39_test262_checkout.sh +++ b/vendor/github.com/grafana/sobek/.tc39_test262_checkout.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/sh -e # this is just the commit it was last tested with -sha=634933a489f1bb8cf074a2a9b8616ade5f2f5cac +sha=cb4a6c8074671c00df8cbc17a620c0f9462b312a mkdir -p testdata/test262 cd testdata/test262 diff --git a/vendor/github.com/grafana/sobek/builtin_bigint.go b/vendor/github.com/grafana/sobek/builtin_bigint.go new file mode 100644 index 00000000000..3c393e60dd2 --- /dev/null +++ b/vendor/github.com/grafana/sobek/builtin_bigint.go @@ -0,0 +1,373 @@ +package sobek + +import ( + "fmt" + "hash/maphash" + "math" + "math/big" + "reflect" + "strconv" + "sync" + + "github.com/grafana/sobek/unistring" +) + +type valueBigInt big.Int + +func (v *valueBigInt) ToInteger() int64 { + v.ToNumber() + return 0 +} + +func (v *valueBigInt) toString() String { + return asciiString((*big.Int)(v).String()) +} + +func (v *valueBigInt) string() unistring.String { + return unistring.String(v.String()) +} + +func (v *valueBigInt) ToString() Value { + return v +} + +func (v *valueBigInt) String() string { + return (*big.Int)(v).String() +} + +func (v *valueBigInt) ToFloat() float64 { + v.ToNumber() + return 0 +} + +func (v *valueBigInt) ToNumber() Value { + panic(typeError("Cannot convert a BigInt value to a number")) +} + +func (v *valueBigInt) ToBoolean() bool { + return (*big.Int)(v).Sign() != 0 +} + +func (v *valueBigInt) ToObject(r *Runtime) *Object { + return r.newPrimitiveObject(v, r.getBigIntPrototype(), classObject) +} + +func (v *valueBigInt) SameAs(other Value) bool { + if o, ok := other.(*valueBigInt); ok { + return (*big.Int)(v).Cmp((*big.Int)(o)) == 0 + } + return false +} + +func (v *valueBigInt) Equals(other Value) bool { + switch o := other.(type) { + case *valueBigInt: + return (*big.Int)(v).Cmp((*big.Int)(o)) == 0 + case valueInt: + return (*big.Int)(v).Cmp(big.NewInt(int64(o))) == 0 + case valueFloat: + if IsInfinity(o) || math.IsNaN(float64(o)) { + return false + } + if f := big.NewFloat(float64(o)); f.IsInt() { + i, _ := f.Int(nil) + return (*big.Int)(v).Cmp(i) == 0 + } + return false + case String: + bigInt, err := stringToBigInt(o.toTrimmedUTF8()) + if err != nil { + return false + } + return bigInt.Cmp((*big.Int)(v)) == 0 + case valueBool: + return (*big.Int)(v).Int64() == o.ToInteger() + case *Object: + return v.Equals(o.toPrimitiveNumber()) + } + return false +} + +func (v *valueBigInt) StrictEquals(other Value) bool { + o, ok := other.(*valueBigInt) + if ok { + return (*big.Int)(v).Cmp((*big.Int)(o)) == 0 + } + return false +} + +func (v *valueBigInt) Export() interface{} { + return new(big.Int).Set((*big.Int)(v)) +} + +func (v *valueBigInt) ExportType() reflect.Type { + return typeBigInt +} + +func (v *valueBigInt) baseObject(rt *Runtime) *Object { + return rt.getBigIntPrototype() +} + +func (v *valueBigInt) hash(hash *maphash.Hash) uint64 { + var sign byte + if (*big.Int)(v).Sign() < 0 { + sign = 0x01 + } else { + sign = 0x00 + } + _ = hash.WriteByte(sign) + _, _ = hash.Write((*big.Int)(v).Bytes()) + h := hash.Sum64() + hash.Reset() + return h +} + +func toBigInt(value Value) *valueBigInt { + // Undefined Throw a TypeError exception. + // Null Throw a TypeError exception. + // Boolean Return 1n if prim is true and 0n if prim is false. + // BigInt Return prim. + // Number Throw a TypeError exception. + // String 1. Let n be StringToBigInt(prim). + // 2. If n is undefined, throw a SyntaxError exception. + // 3. Return n. + // Symbol Throw a TypeError exception. + switch prim := value.(type) { + case *valueBigInt: + return prim + case String: + bigInt, err := stringToBigInt(prim.toTrimmedUTF8()) + if err != nil { + panic(syntaxError(fmt.Sprintf("Cannot convert %s to a BigInt", prim))) + } + return (*valueBigInt)(bigInt) + case valueBool: + return (*valueBigInt)(big.NewInt(prim.ToInteger())) + case *Symbol: + panic(typeError("Cannot convert Symbol to a BigInt")) + case *Object: + return toBigInt(prim.toPrimitiveNumber()) + default: + panic(typeError(fmt.Sprintf("Cannot convert %s to a BigInt", prim))) + } +} + +func numberToBigInt(v Value) *valueBigInt { + switch v := toNumeric(v).(type) { + case *valueBigInt: + return v + case valueInt: + return (*valueBigInt)(big.NewInt(v.ToInteger())) + case valueFloat: + if IsInfinity(v) || math.IsNaN(float64(v)) { + panic(rangeError(fmt.Sprintf("Cannot convert %s to a BigInt", v))) + } + if f := big.NewFloat(float64(v)); f.IsInt() { + n, _ := f.Int(nil) + return (*valueBigInt)(n) + } + panic(rangeError(fmt.Sprintf("Cannot convert %s to a BigInt", v))) + case *Object: + prim := v.toPrimitiveNumber() + switch prim.(type) { + case valueInt, valueFloat: + return numberToBigInt(prim) + default: + return toBigInt(prim) + } + default: + panic(newTypeError("Cannot convert %s to a BigInt", v)) + } +} + +func stringToBigInt(str string) (*big.Int, error) { + var bigint big.Int + n, err := stringToInt(str) + if err != nil { + switch { + case isRangeErr(err): + bigint.SetString(str, 0) + case err == strconv.ErrSyntax: + default: + return nil, strconv.ErrSyntax + } + } else { + bigint.SetInt64(n) + } + return &bigint, nil +} + +func (r *Runtime) thisBigIntValue(value Value) Value { + switch t := value.(type) { + case *valueBigInt: + return t + case *Object: + switch t := t.self.(type) { + case *primitiveValueObject: + return r.thisBigIntValue(t.pValue) + case *objectGoReflect: + if t.exportType() == typeBigInt && t.valueOf != nil { + return t.valueOf() + } + } + } + panic(r.NewTypeError("requires that 'this' be a BigInt")) +} + +func (r *Runtime) bigintproto_valueOf(call FunctionCall) Value { + return r.thisBigIntValue(call.This) +} + +func (r *Runtime) bigintproto_toString(call FunctionCall) Value { + x := (*big.Int)(r.thisBigIntValue(call.This).(*valueBigInt)) + radix := call.Argument(0) + var radixMV int + + if radix == _undefined { + radixMV = 10 + } else { + radixMV = int(radix.ToInteger()) + if radixMV < 2 || radixMV > 36 { + panic(r.newError(r.getRangeError(), "radix must be an integer between 2 and 36")) + } + } + + return asciiString(x.Text(radixMV)) +} + +func (r *Runtime) bigint_asIntN(call FunctionCall) Value { + if len(call.Arguments) < 2 { + panic(r.NewTypeError("Cannot convert undefined to a BigInt")) + } + bits := r.toIndex(call.Argument(0).ToNumber()) + if bits < 0 { + panic(r.NewTypeError("Invalid value: not (convertible to) a safe integer")) + } + bigint := toBigInt(call.Argument(1)) + + twoToBits := new(big.Int).Lsh(big.NewInt(1), uint(bits)) + mod := new(big.Int).Mod((*big.Int)(bigint), twoToBits) + if bits > 0 && mod.Cmp(new(big.Int).Lsh(big.NewInt(1), uint(bits-1))) >= 0 { + return (*valueBigInt)(mod.Sub(mod, twoToBits)) + } else { + return (*valueBigInt)(mod) + } +} + +func (r *Runtime) bigint_asUintN(call FunctionCall) Value { + if len(call.Arguments) < 2 { + panic(r.NewTypeError("Cannot convert undefined to a BigInt")) + } + bits := r.toIndex(call.Argument(0).ToNumber()) + if bits < 0 { + panic(r.NewTypeError("Invalid value: not (convertible to) a safe integer")) + } + bigint := (*big.Int)(toBigInt(call.Argument(1))) + ret := new(big.Int).Mod(bigint, new(big.Int).Lsh(big.NewInt(1), uint(bits))) + return (*valueBigInt)(ret) +} + +var ( + bigintTemplate *objectTemplate + bigintTemplateOnce sync.Once +) + +func getBigIntTemplate() *objectTemplate { + bigintTemplateOnce.Do(func() { + bigintTemplate = createBigIntTemplate() + }) + return bigintTemplate +} + +func createBigIntTemplate() *objectTemplate { + t := newObjectTemplate() + t.protoFactory = func(r *Runtime) *Object { + return r.getFunctionPrototype() + } + + t.putStr("name", func(r *Runtime) Value { return valueProp(asciiString("BigInt"), false, false, true) }) + t.putStr("length", func(r *Runtime) Value { return valueProp(intToValue(1), false, false, true) }) + t.putStr("prototype", func(r *Runtime) Value { return valueProp(r.getBigIntPrototype(), false, false, false) }) + + t.putStr("asIntN", func(r *Runtime) Value { return r.methodProp(r.bigint_asIntN, "asIntN", 2) }) + t.putStr("asUintN", func(r *Runtime) Value { return r.methodProp(r.bigint_asUintN, "asUintN", 2) }) + + return t +} + +func (r *Runtime) builtin_BigInt(call FunctionCall) Value { + if len(call.Arguments) > 0 { + switch v := call.Argument(0).(type) { + case *valueBigInt, valueInt, valueFloat, *Object: + return numberToBigInt(v) + default: + return toBigInt(v) + } + } + return (*valueBigInt)(big.NewInt(0)) +} + +func (r *Runtime) builtin_newBigInt(args []Value, newTarget *Object) *Object { + if newTarget != nil { + panic(r.NewTypeError("BigInt is not a constructor")) + } + var v Value + if len(args) > 0 { + v = numberToBigInt(args[0]) + } else { + v = (*valueBigInt)(big.NewInt(0)) + } + return r.newPrimitiveObject(v, newTarget, classObject) +} + +func (r *Runtime) getBigInt() *Object { + ret := r.global.BigInt + if ret == nil { + ret = &Object{runtime: r} + r.global.BigInt = ret + r.newTemplatedFuncObject(getBigIntTemplate(), ret, r.builtin_BigInt, + r.wrapNativeConstruct(r.builtin_newBigInt, ret, r.getBigIntPrototype())) + } + return ret +} + +func createBigIntProtoTemplate() *objectTemplate { + t := newObjectTemplate() + t.protoFactory = func(r *Runtime) *Object { + return r.global.ObjectPrototype + } + + t.putStr("length", func(r *Runtime) Value { return valueProp(intToValue(0), false, false, true) }) + t.putStr("name", func(r *Runtime) Value { return valueProp(asciiString("BigInt"), false, false, true) }) + t.putStr("constructor", func(r *Runtime) Value { return valueProp(r.getBigInt(), true, false, true) }) + + t.putStr("toLocaleString", func(r *Runtime) Value { return r.methodProp(r.bigintproto_toString, "toLocaleString", 0) }) + t.putStr("toString", func(r *Runtime) Value { return r.methodProp(r.bigintproto_toString, "toString", 0) }) + t.putStr("valueOf", func(r *Runtime) Value { return r.methodProp(r.bigintproto_valueOf, "valueOf", 0) }) + t.putSym(SymToStringTag, func(r *Runtime) Value { return valueProp(asciiString("BigInt"), false, false, true) }) + + return t +} + +var ( + bigintProtoTemplate *objectTemplate + bigintProtoTemplateOnce sync.Once +) + +func getBigIntProtoTemplate() *objectTemplate { + bigintProtoTemplateOnce.Do(func() { + bigintProtoTemplate = createBigIntProtoTemplate() + }) + return bigintProtoTemplate +} + +func (r *Runtime) getBigIntPrototype() *Object { + ret := r.global.BigIntPrototype + if ret == nil { + ret = &Object{runtime: r} + r.global.BigIntPrototype = ret + o := r.newTemplatedObject(getBigIntProtoTemplate(), ret) + o.class = classObject + } + return ret +} diff --git a/vendor/github.com/grafana/sobek/builtin_global.go b/vendor/github.com/grafana/sobek/builtin_global.go index d7ba9b457b5..f22521a3c07 100644 --- a/vendor/github.com/grafana/sobek/builtin_global.go +++ b/vendor/github.com/grafana/sobek/builtin_global.go @@ -2,7 +2,6 @@ package sobek import ( "errors" - "github.com/grafana/sobek/unistring" "io" "math" "regexp" @@ -10,13 +9,13 @@ import ( "strings" "sync" "unicode/utf8" + + "github.com/grafana/sobek/unistring" ) const hexUpper = "0123456789ABCDEF" -var ( - parseFloatRegexp = regexp.MustCompile(`^([+-]?(?:Infinity|[0-9]*\.?[0-9]*(?:[eE][+-]?[0-9]+)?))`) -) +var parseFloatRegexp = regexp.MustCompile(`^([+-]?(?:Infinity|[0-9]*\.?[0-9]*(?:[eE][+-]?[0-9]+)?))`) func (r *Runtime) builtin_isNaN(call FunctionCall) Value { if math.IsNaN(call.Argument(0).ToFloat()) { @@ -339,6 +338,7 @@ func createGlobalObjectTemplate() *objectTemplate { t.putStr("Array", func(r *Runtime) Value { return valueProp(r.getArray(), true, false, true) }) t.putStr("String", func(r *Runtime) Value { return valueProp(r.getString(), true, false, true) }) t.putStr("Number", func(r *Runtime) Value { return valueProp(r.getNumber(), true, false, true) }) + t.putStr("BigInt", func(r *Runtime) Value { return valueProp(r.getBigInt(), true, false, true) }) t.putStr("RegExp", func(r *Runtime) Value { return valueProp(r.getRegExp(), true, false, true) }) t.putStr("Date", func(r *Runtime) Value { return valueProp(r.getDate(), true, false, true) }) t.putStr("Boolean", func(r *Runtime) Value { return valueProp(r.getBoolean(), true, false, true) }) @@ -389,8 +389,10 @@ func createGlobalObjectTemplate() *objectTemplate { return t } -var globalObjectTemplate *objectTemplate -var globalObjectTemplateOnce sync.Once +var ( + globalObjectTemplate *objectTemplate + globalObjectTemplateOnce sync.Once +) func getGlobalObjectTemplate() *objectTemplate { globalObjectTemplateOnce.Do(func() { diff --git a/vendor/github.com/grafana/sobek/builtin_json.go b/vendor/github.com/grafana/sobek/builtin_json.go index 57f7ccd798c..e3fbbd7b46a 100644 --- a/vendor/github.com/grafana/sobek/builtin_json.go +++ b/vendor/github.com/grafana/sobek/builtin_json.go @@ -281,8 +281,9 @@ func (ctx *_builtinJSON_stringifyContext) do(v Value) bool { func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool { value := nilSafe(holder.get(key, nil)) - if object, ok := value.(*Object); ok { - if toJSON, ok := object.self.getStr("toJSON", nil).(*Object); ok { + switch value.(type) { + case *Object, *valueBigInt: + if toJSON, ok := ctx.r.getVStr(value, "toJSON").(*Object); ok { if c, ok := toJSON.self.assertCallable(); ok { value = c(FunctionCall{ This: value, @@ -334,6 +335,9 @@ func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool { value = valueFalse } } + if o1.exportType() == typeBigInt { + value = o1.val.ordinaryToPrimitiveNumber() + } } } } @@ -357,6 +361,8 @@ func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool { } case valueNull: ctx.buf.WriteString("null") + case *valueBigInt: + ctx.r.typeErrorResult(true, "Do not know how to serialize a BigInt") case *Object: for _, object := range ctx.stack { if value1.SameAs(object) { diff --git a/vendor/github.com/grafana/sobek/builtin_regexp.go b/vendor/github.com/grafana/sobek/builtin_regexp.go index 5b4ce71cfde..d0be2decf27 100644 --- a/vendor/github.com/grafana/sobek/builtin_regexp.go +++ b/vendor/github.com/grafana/sobek/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/vendor/github.com/grafana/sobek/builtin_string.go b/vendor/github.com/grafana/sobek/builtin_string.go index 5091c08d1f3..8e82697bb74 100644 --- a/vendor/github.com/grafana/sobek/builtin_string.go +++ b/vendor/github.com/grafana/sobek/builtin_string.go @@ -1,7 +1,6 @@ package sobek import ( - "github.com/grafana/sobek/unistring" "math" "strings" "sync" @@ -9,6 +8,8 @@ import ( "unicode/utf8" "github.com/grafana/sobek/parser" + "github.com/grafana/sobek/unistring" + "golang.org/x/text/collate" "golang.org/x/text/language" "golang.org/x/text/unicode/norm" @@ -332,7 +333,7 @@ func (r *Runtime) stringproto_indexOf(call FunctionCall) Value { r.checkObjectCoercible(call.This) value := call.This.toString() target := call.Argument(0).toString() - pos := call.Argument(1).ToInteger() + pos := call.Argument(1).ToNumber().ToInteger() if pos < 0 { pos = 0 @@ -1089,8 +1090,10 @@ func (r *Runtime) getString() *Object { return ret } -var stringProtoTemplate *objectTemplate -var stringProtoTemplateOnce sync.Once +var ( + stringProtoTemplate *objectTemplate + stringProtoTemplateOnce sync.Once +) func getStringProtoTemplate() *objectTemplate { stringProtoTemplateOnce.Do(func() { diff --git a/vendor/github.com/grafana/sobek/builtin_typedarrays.go b/vendor/github.com/grafana/sobek/builtin_typedarrays.go index 1cdb838c0e8..d350f120871 100644 --- a/vendor/github.com/grafana/sobek/builtin_typedarrays.go +++ b/vendor/github.com/grafana/sobek/builtin_typedarrays.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "sort" + "strings" "sync" "unsafe" @@ -14,17 +15,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 +63,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 +155,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 +185,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{ @@ -275,6 +291,20 @@ func (r *Runtime) dataViewProto_getUint32(call FunctionCall) Value { panic(r.NewTypeError("Method DataView.prototype.getUint32 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) } +func (r *Runtime) dataViewProto_getBigInt64(call FunctionCall) Value { + if dv, ok := r.toObject(call.This).self.(*dataViewObject); ok { + return (*valueBigInt)(dv.viewedArrayBuf.getBigInt64(dv.getIdxAndByteOrder(r.toIndex(call.Argument(0).ToNumber()), call.Argument(1), 8))) + } + panic(r.NewTypeError("Method DataView.prototype.getBigInt64 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) +} + +func (r *Runtime) dataViewProto_getBigUint64(call FunctionCall) Value { + if dv, ok := r.toObject(call.This).self.(*dataViewObject); ok { + return (*valueBigInt)(dv.viewedArrayBuf.getBigUint64(dv.getIdxAndByteOrder(r.toIndex(call.Argument(0).ToNumber()), call.Argument(1), 8))) + } + panic(r.NewTypeError("Method DataView.prototype.getBigUint64 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) +} + func (r *Runtime) dataViewProto_setFloat32(call FunctionCall) Value { if dv, ok := r.toObject(call.This).self.(*dataViewObject); ok { idxVal := r.toIndex(call.Argument(0)) @@ -363,6 +393,28 @@ func (r *Runtime) dataViewProto_setUint32(call FunctionCall) Value { panic(r.NewTypeError("Method DataView.prototype.setUint32 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) } +func (r *Runtime) dataViewProto_setBigInt64(call FunctionCall) Value { + if dv, ok := r.toObject(call.This).self.(*dataViewObject); ok { + idxVal := r.toIndex(call.Argument(0)) + val := toBigInt64(call.Argument(1)) + idx, bo := dv.getIdxAndByteOrder(idxVal, call.Argument(2), 8) + dv.viewedArrayBuf.setBigInt64(idx, val, bo) + return _undefined + } + panic(r.NewTypeError("Method DataView.prototype.setBigInt64 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) +} + +func (r *Runtime) dataViewProto_setBigUint64(call FunctionCall) Value { + if dv, ok := r.toObject(call.This).self.(*dataViewObject); ok { + idxVal := r.toIndex(call.Argument(0)) + val := toBigUint64(call.Argument(1)) + idx, bo := dv.getIdxAndByteOrder(idxVal, call.Argument(2), 8) + dv.viewedArrayBuf.setBigUint64(idx, val, bo) + return _undefined + } + panic(r.NewTypeError("Method DataView.prototype.setBigUint64 called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This}))) +} + func (r *Runtime) typedArrayProto_getBuffer(call FunctionCall) Value { if ta, ok := r.toObject(call.This).self.(*typedArrayObject); ok { return ta.viewedArrayBuf.val @@ -960,6 +1012,7 @@ func (r *Runtime) typedArrayProto_set(call FunctionCall) Value { copy(ta.viewedArrayBuf.data[(ta.offset+targetOffset)*ta.elemSize:], src.viewedArrayBuf.data[src.offset*src.elemSize:(src.offset+srcLen)*src.elemSize]) } else { + checkTypedArrayMixBigInt(src.defaultCtor, ta.defaultCtor) curSrc := uintptr(unsafe.Pointer(&src.viewedArrayBuf.data[src.offset*src.elemSize])) endSrc := curSrc + uintptr(srcLen*src.elemSize) curDst := uintptr(unsafe.Pointer(&ta.viewedArrayBuf.data[(ta.offset+targetOffset)*ta.elemSize])) @@ -1007,7 +1060,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) } @@ -1159,6 +1211,7 @@ func (r *Runtime) typedArrayProto_with(call FunctionCall) Value { if !ok { panic(r.NewTypeError("%s is not a valid TypedArray", r.objectproto_toString(FunctionCall{This: call.This}))) } + ta.viewedArrayBuf.ensureNotDetached(true) length := ta.length relativeIndex := call.Argument(0).ToInteger() var actualIndex int @@ -1172,10 +1225,13 @@ func (r *Runtime) typedArrayProto_with(call FunctionCall) Value { panic(r.newError(r.getRangeError(), "Invalid typed array index")) } - // TODO BigInt - // 7. If O.[[ContentType]] is BIGINT, let numericValue be ? ToBigInt(value). - // 8. Else, let numericValue be ? ToNumber(value). - numericValue := call.Argument(1).ToNumber() + var numericValue Value + switch ta.typedArray.(type) { + case *bigInt64Array, *bigUint64Array: + numericValue = toBigInt(call.Argument(1)) + default: + numericValue = call.Argument(1).ToNumber() + } a := r.typedArrayCreate(ta.defaultCtor, intToValue(int64(length))) for k := 0; k < length; k++ { @@ -1196,6 +1252,7 @@ func (r *Runtime) typedArrayProto_toReversed(call FunctionCall) Value { if !ok { panic(r.NewTypeError("%s is not a valid TypedArray", r.objectproto_toString(FunctionCall{This: call.This}))) } + ta.viewedArrayBuf.ensureNotDetached(true) length := ta.length a := r.typedArrayCreate(ta.defaultCtor, intToValue(int64(length))) @@ -1215,6 +1272,7 @@ func (r *Runtime) typedArrayProto_toSorted(call FunctionCall) Value { if !ok { panic(r.NewTypeError("%s is not a valid TypedArray", r.objectproto_toString(FunctionCall{This: call.This}))) } + ta.viewedArrayBuf.ensureNotDetached(true) var compareFn func(FunctionCall) Value arg := call.Argument(0) @@ -1270,7 +1328,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 @@ -1412,19 +1470,28 @@ func (r *Runtime) _newTypedArrayFromArrayBuffer(ab *arrayBufferObject, args []Va return ta.val } +func checkTypedArrayMixBigInt(src, dst *Object) { + srcType := src.self.getStr("name", nil).String() + if strings.HasPrefix(srcType, "Big") { + if !strings.HasPrefix(dst.self.getStr("name", nil).String(), "Big") { + panic(errMixBigIntType) + } + } +} + func (r *Runtime) _newTypedArrayFromTypedArray(src *typedArrayObject, newTarget *Object, taCtor typedArrayObjectCtor, proto *Object) *Object { dst := r.allocateTypedArray(newTarget, 0, taCtor, proto) 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 { copy(dst.viewedArrayBuf.data, src.viewedArrayBuf.data[src.offset*src.elemSize:]) dst.length = src.length return dst.val + } else { + checkTypedArrayMixBigInt(src.defaultCtor, newTarget) } dst.length = l for i := 0; i < l; i++ { @@ -1494,6 +1561,14 @@ func (r *Runtime) newFloat64Array(args []Value, newTarget, proto *Object) *Objec return r._newTypedArray(args, newTarget, r.newFloat64ArrayObject, proto) } +func (r *Runtime) newBigInt64Array(args []Value, newTarget, proto *Object) *Object { + return r._newTypedArray(args, newTarget, r.newBigInt64ArrayObject, proto) +} + +func (r *Runtime) newBigUint64Array(args []Value, newTarget, proto *Object) *Object { + return r._newTypedArray(args, newTarget, r.newBigUint64ArrayObject, proto) +} + func (r *Runtime) createArrayBufferProto(val *Object) objectImpl { b := newBaseObjectObj(val, r.global.ObjectPrototype, classObject) byteLengthProp := &valueProperty{ @@ -1566,6 +1641,8 @@ func addTypedArrays(t *objectTemplate) { t.putStr("Int32Array", func(r *Runtime) Value { return valueProp(r.getInt32Array(), true, false, true) }) t.putStr("Float32Array", func(r *Runtime) Value { return valueProp(r.getFloat32Array(), true, false, true) }) t.putStr("Float64Array", func(r *Runtime) Value { return valueProp(r.getFloat64Array(), true, false, true) }) + t.putStr("BigInt64Array", func(r *Runtime) Value { return valueProp(r.getBigInt64Array(), true, false, true) }) + t.putStr("BigUint64Array", func(r *Runtime) Value { return valueProp(r.getBigUint64Array(), true, false, true) }) } func createTypedArrayProtoTemplate() *objectTemplate { @@ -1769,6 +1846,26 @@ func (r *Runtime) getFloat64Array() *Object { return ret } +func (r *Runtime) getBigInt64Array() *Object { + ret := r.global.BigInt64Array + if ret == nil { + ret = &Object{runtime: r} + r.global.BigInt64Array = ret + r.createTypedArrayCtor(ret, r.newBigInt64Array, "BigInt64Array", 8) + } + return ret +} + +func (r *Runtime) getBigUint64Array() *Object { + ret := r.global.BigUint64Array + if ret == nil { + ret = &Object{runtime: r} + r.global.BigUint64Array = ret + r.createTypedArrayCtor(ret, r.newBigUint64Array, "BigUint64Array", 8) + } + return ret +} + func createDataViewProtoTemplate() *objectTemplate { t := newObjectTemplate() t.protoFactory = func(r *Runtime) *Object { @@ -1807,6 +1904,8 @@ func createDataViewProtoTemplate() *objectTemplate { t.putStr("getUint8", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_getUint8, "getUint8", 1) }) t.putStr("getUint16", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_getUint16, "getUint16", 1) }) t.putStr("getUint32", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_getUint32, "getUint32", 1) }) + t.putStr("getBigInt64", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_getBigInt64, "getBigInt64", 1) }) + t.putStr("getBigUint64", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_getBigUint64, "getBigUint64", 1) }) t.putStr("setFloat32", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setFloat32, "setFloat32", 2) }) t.putStr("setFloat64", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setFloat64, "setFloat64", 2) }) t.putStr("setInt8", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setInt8, "setInt8", 2) }) @@ -1815,6 +1914,8 @@ func createDataViewProtoTemplate() *objectTemplate { t.putStr("setUint8", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setUint8, "setUint8", 2) }) t.putStr("setUint16", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setUint16, "setUint16", 2) }) t.putStr("setUint32", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setUint32, "setUint32", 2) }) + t.putStr("setBigInt64", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setBigInt64, "setBigInt64", 2) }) + t.putStr("setBigUint64", func(r *Runtime) Value { return r.methodProp(r.dataViewProto_setBigUint64, "setBigUint64", 2) }) t.putSym(SymToStringTag, func(r *Runtime) Value { return valueProp(asciiString("DataView"), false, false, true) }) diff --git a/vendor/github.com/grafana/sobek/compiler_expr.go b/vendor/github.com/grafana/sobek/compiler_expr.go index 357400090f9..d9fa8fe9985 100644 --- a/vendor/github.com/grafana/sobek/compiler_expr.go +++ b/vendor/github.com/grafana/sobek/compiler_expr.go @@ -1,6 +1,8 @@ package sobek import ( + "math/big" + "github.com/grafana/sobek/ast" "github.com/grafana/sobek/file" "github.com/grafana/sobek/token" @@ -2472,7 +2474,7 @@ func (c *compiler) emitThrow(v Value) { if o, ok := v.(*Object); ok { t := nilSafe(o.self.getStr("name", nil)).toString().String() switch t { - case "TypeError": + case "TypeError", "RangeError": c.emit(loadDynamic(t)) msg := o.self.getStr("message", nil) if msg != nil { @@ -3257,6 +3259,8 @@ func (c *compiler) compileNumberLiteral(v *ast.NumberLiteral) compiledExpr { val = intToValue(num) case float64: val = floatToValue(num) + case *big.Int: + val = (*valueBigInt)(num) default: c.assert(false, int(v.Idx)-1, "Unsupported number literal type: %T", v.Value) panic("unreachable") diff --git a/vendor/github.com/grafana/sobek/date_parser.go b/vendor/github.com/grafana/sobek/date_parser.go index a956426d3d7..bda8c985824 100644 --- a/vendor/github.com/grafana/sobek/date_parser.go +++ b/vendor/github.com/grafana/sobek/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/vendor/github.com/grafana/sobek/parser/lexer.go b/vendor/github.com/grafana/sobek/parser/lexer.go index 234d5b963bb..1d7de1becfd 100644 --- a/vendor/github.com/grafana/sobek/parser/lexer.go +++ b/vendor/github.com/grafana/sobek/parser/lexer.go @@ -3,6 +3,7 @@ package parser import ( "errors" "fmt" + "math/big" "strconv" "strings" "unicode" @@ -911,7 +912,9 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { err = parseIntErr if err.(*strconv.NumError).Err == strconv.ErrRange { - if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') { + if len(literal) > 2 && + literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') && + literal[len(literal)-1] != 'n' { // Could just be a very large number (e.g. 0x8000000000000000) var value float64 literal = literal[2:] @@ -926,6 +929,21 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { } } + if len(literal) > 1 && literal[len(literal)-1] == 'n' { + if literal[0] == '0' { + if len(literal) > 2 && isDecimalDigit(rune(literal[1])) { + goto error + } + } + // Parse as big.Int + bigInt := new(big.Int) + _, ok := bigInt.SetString(literal[:len(literal)-1], 0) + if !ok { + goto error + } + return bigInt, nil + } + error: return nil, errors.New("Illegal numeric literal") } @@ -1171,6 +1189,10 @@ func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) } } end: + if self.chr == 'n' || self.chr == 'N' { + self.read() + return tkn, self.str[offset:self.chrOffset] + } if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) { return token.ILLEGAL, self.str[offset:self.chrOffset] } diff --git a/vendor/github.com/grafana/sobek/runtime.go b/vendor/github.com/grafana/sobek/runtime.go index a4506ed30cd..68922b57c38 100644 --- a/vendor/github.com/grafana/sobek/runtime.go +++ b/vendor/github.com/grafana/sobek/runtime.go @@ -7,6 +7,7 @@ import ( "go/ast" "hash/maphash" "math" + "math/big" "math/bits" "math/rand" "reflect" @@ -33,6 +34,7 @@ var ( typeValue = reflect.TypeOf((*Value)(nil)).Elem() typeObject = reflect.TypeOf((*Object)(nil)) typeTime = reflect.TypeOf(time.Time{}) + typeBigInt = reflect.TypeOf((*big.Int)(nil)) typeBytes = reflect.TypeOf(([]byte)(nil)) ) @@ -45,14 +47,14 @@ const ( ) type global struct { - stash stash - varNames map[unistring.String]struct{} + stash stash Object *Object Array *Object Function *Object String *Object Number *Object + BigInt *Object Boolean *Object RegExp *Object Date *Object @@ -77,6 +79,8 @@ type global struct { Int32Array *Object Float32Array *Object Float64Array *Object + BigInt64Array *Object + BigUint64Array *Object WeakSet *Object WeakMap *Object @@ -97,6 +101,7 @@ type global struct { ObjectPrototype *Object ArrayPrototype *Object NumberPrototype *Object + BigIntPrototype *Object StringPrototype *Object BooleanPrototype *Object FunctionPrototype *Object @@ -839,7 +844,18 @@ func (r *Runtime) newPrimitiveObject(value Value, proto *Object, class string) * func (r *Runtime) builtin_Number(call FunctionCall) Value { if len(call.Arguments) > 0 { - return call.Arguments[0].ToNumber() + switch t := call.Arguments[0].(type) { + case *Object: + primValue := t.toPrimitiveNumber() + if bigint, ok := primValue.(*valueBigInt); ok { + return intToValue((*big.Int)(bigint).Int64()) + } + return primValue.ToNumber() + case *valueBigInt: + return intToValue((*big.Int)(t).Int64()) + default: + return t.ToNumber() + } } else { return valueInt(0) } @@ -848,7 +864,19 @@ func (r *Runtime) builtin_Number(call FunctionCall) Value { func (r *Runtime) builtin_newNumber(args []Value, proto *Object) *Object { var v Value if len(args) > 0 { - v = args[0].ToNumber() + switch t := args[0].(type) { + case *Object: + primValue := t.toPrimitiveNumber() + if bigint, ok := primValue.(*valueBigInt); ok { + v = intToValue((*big.Int)(bigint).Int64()) + } else { + v = primValue.ToNumber() + } + case *valueBigInt: + v = intToValue((*big.Int)(t).Int64()) + default: + v = t.ToNumber() + } } else { v = intToValue(0) } @@ -1841,6 +1869,8 @@ func (r *Runtime) toValue(i interface{}, origValue reflect.Value) Value { return floatToValue(float64(i)) case float64: return floatToValue(i) + case *big.Int: + return (*valueBigInt)(new(big.Int).Set(i)) case map[string]interface{}: if i == nil { return _null diff --git a/vendor/github.com/grafana/sobek/string.go b/vendor/github.com/grafana/sobek/string.go index 833bc3aa448..f824c0340b3 100644 --- a/vendor/github.com/grafana/sobek/string.go +++ b/vendor/github.com/grafana/sobek/string.go @@ -24,6 +24,7 @@ var ( stringString String = asciiString("string") stringSymbol String = asciiString("symbol") stringNumber String = asciiString("number") + stringBigInt String = asciiString("bigint") stringNaN String = asciiString("NaN") stringInfinity = asciiString("Infinity") stringNegInfinity = asciiString("-Infinity") diff --git a/vendor/github.com/grafana/sobek/string_ascii.go b/vendor/github.com/grafana/sobek/string_ascii.go index df622f41c3a..f83b3d58421 100644 --- a/vendor/github.com/grafana/sobek/string_ascii.go +++ b/vendor/github.com/grafana/sobek/string_ascii.go @@ -4,6 +4,7 @@ import ( "hash/maphash" "io" "math" + "math/big" "reflect" "strconv" "strings" @@ -114,7 +115,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 +123,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 } @@ -239,6 +247,14 @@ func (s asciiString) Equals(other Value) bool { return false } + if o, ok := other.(*valueBigInt); ok { + bigInt, err := stringToBigInt(s.toTrimmedUTF8()) + if err != nil { + return false + } + return bigInt.Cmp((*big.Int)(o)) == 0 + } + if o, ok := other.(*Object); ok { return s.Equals(o.toPrimitive()) } diff --git a/vendor/github.com/grafana/sobek/typedarrays.go b/vendor/github.com/grafana/sobek/typedarrays.go index cfe19bc66d3..213da9fc7fb 100644 --- a/vendor/github.com/grafana/sobek/typedarrays.go +++ b/vendor/github.com/grafana/sobek/typedarrays.go @@ -2,6 +2,7 @@ package sobek import ( "math" + "math/big" "reflect" "strconv" "unsafe" @@ -65,6 +66,8 @@ type uint32Array []byte type int32Array []byte type float32Array []byte type float64Array []byte +type bigInt64Array []byte +type bigUint64Array []byte type typedArrayObject struct { baseObject @@ -630,6 +633,136 @@ func (a *float64Array) exportType() reflect.Type { return typeFloat64Array } +func (a *bigInt64Array) toRaw(value Value) uint64 { + return toBigInt64(value).Uint64() +} + +func (a *bigInt64Array) ptr(idx int) *int64 { + p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) + return (*int64)(unsafe.Pointer(uintptr(p) + uintptr(idx)*8)) +} + +func (a *bigInt64Array) get(idx int) Value { + return (*valueBigInt)(big.NewInt(*a.ptr(idx))) +} + +func toBigInt64(v Value) *big.Int { + n := (*big.Int)(toBigInt(v)) + + twoTo64 := new(big.Int).Lsh(big.NewInt(1), 64) + twoTo63 := new(big.Int).Lsh(big.NewInt(1), 63) + + int64bit := new(big.Int).Mod(n, twoTo64) + if int64bit.Cmp(twoTo63) >= 0 { + return int64bit.Sub(int64bit, twoTo64) + } + return int64bit +} + +func (a *bigInt64Array) set(idx int, value Value) { + *(a.ptr(idx)) = toBigInt64(value).Int64() +} + +func (a *bigInt64Array) getRaw(idx int) uint64 { + return uint64(*a.ptr(idx)) +} + +func (a *bigInt64Array) setRaw(idx int, raw uint64) { + *(a.ptr(idx)) = int64(raw) +} + +func (a *bigInt64Array) less(i, j int) bool { + return *(a.ptr(i)) < *(a.ptr(j)) +} + +func (a *bigInt64Array) swap(i, j int) { + pi, pj := a.ptr(i), a.ptr(j) + *pi, *pj = *pj, *pi +} + +func (a *bigInt64Array) typeMatch(v Value) bool { + if _, ok := v.(*valueBigInt); ok { + return true + } + return false +} + +func (a *bigInt64Array) export(offset int, length int) interface{} { + var res []int64 + sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) + sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*8 + sliceHeader.Len = length + sliceHeader.Cap = length + return res +} + +var typeBigInt64Array = reflect.TypeOf(([]int64)(nil)) + +func (a *bigInt64Array) exportType() reflect.Type { + return typeBigInt64Array +} + +func (a *bigUint64Array) toRaw(value Value) uint64 { + return toBigUint64(value).Uint64() +} + +func (a *bigUint64Array) ptr(idx int) *uint64 { + p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(a)).Data) + return (*uint64)(unsafe.Pointer(uintptr(p) + uintptr(idx)*8)) +} + +func (a *bigUint64Array) get(idx int) Value { + return (*valueBigInt)(new(big.Int).SetUint64(*a.ptr(idx))) +} + +func toBigUint64(v Value) *big.Int { + n := (*big.Int)(toBigInt(v)) + return new(big.Int).Mod(n, new(big.Int).Lsh(big.NewInt(1), 64)) +} + +func (a *bigUint64Array) set(idx int, value Value) { + *(a.ptr(idx)) = toBigUint64(value).Uint64() +} + +func (a *bigUint64Array) getRaw(idx int) uint64 { + return *a.ptr(idx) +} + +func (a *bigUint64Array) setRaw(idx int, raw uint64) { + *(a.ptr(idx)) = raw +} + +func (a *bigUint64Array) less(i, j int) bool { + return *(a.ptr(i)) < *(a.ptr(j)) +} + +func (a *bigUint64Array) swap(i, j int) { + pi, pj := a.ptr(i), a.ptr(j) + *pi, *pj = *pj, *pi +} + +func (a *bigUint64Array) typeMatch(v Value) bool { + if _, ok := v.(*valueBigInt); ok { + return true + } + return false +} + +func (a *bigUint64Array) export(offset int, length int) interface{} { + var res []uint64 + sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&res)) + sliceHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(a)).Data + uintptr(offset)*8 + sliceHeader.Len = length + sliceHeader.Cap = length + return res +} + +var typeBigUint64Array = reflect.TypeOf(([]uint64)(nil)) + +func (a *bigUint64Array) exportType() reflect.Type { + return typeBigUint64Array +} + func (a *typedArrayObject) _getIdx(idx int) Value { if 0 <= idx && idx < a.length { if !a.viewedArrayBuf.ensureNotDetached(false) { @@ -698,7 +831,12 @@ func (a *typedArrayObject) isValidIntegerIndex(idx int) bool { } func (a *typedArrayObject) _putIdx(idx int, v Value) { - v = v.ToNumber() + switch a.typedArray.(type) { + case *bigInt64Array, *bigUint64Array: + v = toBigInt(v) + default: + v = v.ToNumber() + } if a.isValidIntegerIndex(idx) { a.typedArray.set(idx+a.offset, v) } @@ -715,7 +853,7 @@ func (a *typedArrayObject) setOwnStr(p unistring.String, v Value, throw bool) bo return true } if idx == 0 { - v.ToNumber() // make sure it throws + toNumeric(v) // make sure it throws return true } return a.baseObject.setOwnStr(p, v, throw) @@ -938,6 +1076,14 @@ func (r *Runtime) newFloat64ArrayObject(buf *arrayBufferObject, offset, length i return r._newTypedArrayObject(buf, offset, length, 8, r.global.Float64Array, (*float64Array)(&buf.data), proto) } +func (r *Runtime) newBigInt64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { + return r._newTypedArrayObject(buf, offset, length, 8, r.global.BigInt64Array, (*bigInt64Array)(&buf.data), proto) +} + +func (r *Runtime) newBigUint64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject { + return r._newTypedArrayObject(buf, offset, length, 8, r.global.BigUint64Array, (*bigUint64Array)(&buf.data), proto) +} + func (o *dataViewObject) getIdxAndByteOrder(getIdx int, littleEndianVal Value, size int) (int, byteOrder) { o.viewedArrayBuf.ensureNotDetached(true) if getIdx+size > o.byteLen { @@ -1026,6 +1172,52 @@ func (o *arrayBufferObject) setUint32(idx int, val uint32, byteOrder byteOrder) } } +func (o *arrayBufferObject) getBigInt64(idx int, byteOrder byteOrder) *big.Int { + var b []byte + if byteOrder == nativeEndian { + b = o.data[idx : idx+8] + } else { + b = make([]byte, 8) + d := o.data[idx : idx+8] + 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] + } + return big.NewInt(*((*int64)(unsafe.Pointer(&b[0])))) +} + +func (o *arrayBufferObject) getBigUint64(idx int, byteOrder byteOrder) *big.Int { + var b []byte + if byteOrder == nativeEndian { + b = o.data[idx : idx+8] + } else { + b = make([]byte, 8) + d := o.data[idx : idx+8] + 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] + } + return new(big.Int).SetUint64(*((*uint64)(unsafe.Pointer(&b[0])))) +} + +func (o *arrayBufferObject) setBigInt64(idx int, val *big.Int, byteOrder byteOrder) { + if byteOrder == nativeEndian { + *(*int64)(unsafe.Pointer(&o.data[idx])) = val.Int64() + } else { + n := val.Int64() + b := (*[8]byte)(unsafe.Pointer(&n)) + d := o.data[idx : idx+8] + 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] + } +} + +func (o *arrayBufferObject) setBigUint64(idx int, val *big.Int, byteOrder byteOrder) { + if byteOrder == nativeEndian { + *(*uint64)(unsafe.Pointer(&o.data[idx])) = val.Uint64() + } else { + n := val.Uint64() + b := (*[8]byte)(unsafe.Pointer(&n)) + d := o.data[idx : idx+8] + 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] + } +} + func (o *arrayBufferObject) getUint16(idx int, byteOrder byteOrder) uint16 { var b []byte if byteOrder == nativeEndian { diff --git a/vendor/github.com/grafana/sobek/value.go b/vendor/github.com/grafana/sobek/value.go index bb130092a28..58b89c9c09b 100644 --- a/vendor/github.com/grafana/sobek/value.go +++ b/vendor/github.com/grafana/sobek/value.go @@ -4,6 +4,7 @@ import ( "fmt" "hash/maphash" "math" + "math/big" "reflect" "strconv" "unsafe" @@ -141,6 +142,7 @@ type valueProperty struct { var ( errAccessBeforeInit = referenceError("Cannot access a variable before initialization") errAssignToConst = typeError("Assignment to constant variable.") + errMixBigIntType = typeError("Cannot mix BigInt and other types, use explicit conversions") ) func propGetter(o Value, v Value, r *Runtime) *Object { @@ -218,6 +220,8 @@ func (i valueInt) Equals(other Value) bool { switch o := other.(type) { case valueInt: return i == o + case *valueBigInt: + return (*big.Int)(o).Cmp(big.NewInt(int64(i))) == 0 case valueFloat: return float64(i) == float64(o) case String: @@ -643,6 +647,15 @@ func (f valueFloat) Equals(other Value) bool { return f == o case valueInt: return float64(f) == float64(o) + case *valueBigInt: + if IsInfinity(f) || math.IsNaN(float64(f)) { + return false + } + if f := big.NewFloat(float64(f)); f.IsInt() { + i, _ := f.Int(nil) + return (*big.Int)(o).Cmp(i) == 0 + } + return false case String, valueBool: return float64(f) == o.ToFloat() case *Object: @@ -728,7 +741,7 @@ func (o *Object) Equals(other Value) bool { } switch o1 := other.(type) { - case valueInt, valueFloat, String, *Symbol: + case valueInt, valueFloat, *valueBigInt, String, *Symbol: return o.toPrimitive().Equals(other) case valueBool: return o.Equals(o1.ToNumber()) diff --git a/vendor/github.com/grafana/sobek/vm.go b/vendor/github.com/grafana/sobek/vm.go index 6830913ccb7..a0c5cb4549a 100644 --- a/vendor/github.com/grafana/sobek/vm.go +++ b/vendor/github.com/grafana/sobek/vm.go @@ -3,6 +3,7 @@ package sobek import ( "fmt" "math" + "math/big" "reflect" "strconv" "strings" @@ -210,6 +211,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 @@ -217,11 +260,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))) } @@ -232,7 +275,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 { @@ -240,7 +283,7 @@ func (r *objRef) init(v Value) { } } -func (r *objRef) refname() unistring.String { +func (r *objStrRef) refname() unistring.String { return r.name } @@ -375,17 +418,20 @@ func floatToValue(f float64) (result Value) { return valueFloat(f) } -func assertInt64(v Value) (int64, bool) { - num := v.ToNumber() - if i, ok := num.(valueInt); ok { - return int64(i), true - } - if f, ok := num.(valueFloat); ok { - if i, ok := floatToInt(float64(f)); ok { - return i, true +func toNumeric(value Value) Value { + switch v := value.(type) { + case valueInt, *valueBigInt: + return v + case valueFloat: + return floatToValue(float64(v)) + case *Object: + primValue := v.toPrimitiveNumber() + if bigint, ok := primValue.(*valueBigInt); ok { + return bigint } + return primValue.ToNumber() } - return 0, false + return value.ToNumber() } func (s *valueStack) expand(idx int) { @@ -471,7 +517,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, @@ -1258,7 +1304,7 @@ type _toNumber struct{} var toNumber _toNumber func (_toNumber) exec(vm *vm) { - vm.stack[vm.sp-1] = vm.stack[vm.sp-1].ToNumber() + vm.stack[vm.sp-1] = toNumeric(vm.stack[vm.sp-1]) vm.pc++ } @@ -1292,13 +1338,26 @@ func (_add) exec(vm *vm) { } ret = leftString.Concat(rightString) } else { - if leftInt, ok := left.(valueInt); ok { - if rightInt, ok := right.(valueInt); ok { - ret = intToValue(int64(leftInt) + int64(rightInt)) + switch left := left.(type) { + case valueInt: + switch right := right.(type) { + case valueInt: + ret = intToValue(int64(left) + int64(right)) + case *valueBigInt: + panic(errMixBigIntType) + default: + ret = floatToValue(float64(left) + right.ToFloat()) + } + case *valueBigInt: + if right, ok := right.(*valueBigInt); ok { + ret = (*valueBigInt)(new(big.Int).Add((*big.Int)(left), (*big.Int)(right))) } else { - ret = floatToValue(float64(leftInt) + right.ToFloat()) + panic(errMixBigIntType) + } + default: + if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) } - } else { ret = floatToValue(left.ToFloat() + right.ToFloat()) } } @@ -1316,13 +1375,30 @@ func (_sub) exec(vm *vm) { right := vm.stack[vm.sp-1] left := vm.stack[vm.sp-2] + left = toNumeric(left) + right = toNumeric(right) + var result Value - if left, ok := left.(valueInt); ok { - if right, ok := right.(valueInt); ok { + switch left := left.(type) { + case valueInt: + switch right := right.(type) { + case valueInt: result = intToValue(int64(left) - int64(right)) goto end + case *valueBigInt: + panic(errMixBigIntType) + } + case valueFloat: + if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) } + case *valueBigInt: + if right, ok := right.(*valueBigInt); ok { + result = (*valueBigInt)(new(big.Int).Sub((*big.Int)(left), (*big.Int)(right))) + goto end + } + panic(errMixBigIntType) } result = floatToValue(left.ToFloat() - right.ToFloat()) @@ -1337,13 +1413,15 @@ type _mul struct{} var mul _mul func (_mul) exec(vm *vm) { - left := vm.stack[vm.sp-2] - right := vm.stack[vm.sp-1] + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) var result Value - if left, ok := assertInt64(left); ok { - if right, ok := assertInt64(right); ok { + switch left := left.(type) { + case valueInt: + switch right := right.(type) { + case valueInt: if left == 0 && right == -1 || left == -1 && right == 0 { result = _negativeZero goto end @@ -1351,11 +1429,22 @@ func (_mul) exec(vm *vm) { res := left * right // check for overflow if left == 0 || right == 0 || res/left == right { - result = intToValue(res) + result = intToValue(int64(res)) goto end } - + case *valueBigInt: + panic(errMixBigIntType) } + case valueFloat: + if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + case *valueBigInt: + if right, ok := right.(*valueBigInt); ok { + result = (*valueBigInt)(new(big.Int).Mul((*big.Int)(left), (*big.Int)(right))) + goto end + } + panic(errMixBigIntType) } result = floatToValue(left.ToFloat() * right.ToFloat()) @@ -1372,7 +1461,29 @@ var exp _exp func (_exp) exec(vm *vm) { vm.sp-- - vm.stack[vm.sp-1] = pow(vm.stack[vm.sp-1], vm.stack[vm.sp]) + x := vm.stack[vm.sp-1] + y := vm.stack[vm.sp] + + x = toNumeric(x) + y = toNumeric(y) + + var result Value + if x, ok := x.(*valueBigInt); ok { + if y, ok := y.(*valueBigInt); ok { + if (*big.Int)(y).Cmp(big.NewInt(0)) < 0 { + panic(vm.r.newError(vm.r.getRangeError(), "exponent must be positive")) + } + result = (*valueBigInt)(new(big.Int).Exp((*big.Int)(x), (*big.Int)(y), nil)) + goto end + } + panic(errMixBigIntType) + } else if _, ok := y.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = pow(x, y) +end: + vm.stack[vm.sp-1] = result vm.pc++ } @@ -1381,10 +1492,32 @@ type _div struct{} var div _div func (_div) exec(vm *vm) { - left := vm.stack[vm.sp-2].ToFloat() - right := vm.stack[vm.sp-1].ToFloat() - - var result Value + leftValue := toNumeric(vm.stack[vm.sp-2]) + rightValue := toNumeric(vm.stack[vm.sp-1]) + + var ( + result Value + left, right float64 + ) + + if left, ok := leftValue.(*valueBigInt); ok { + if right, ok := rightValue.(*valueBigInt); ok { + if (*big.Int)(right).Cmp(big.NewInt(0)) == 0 { + panic(vm.r.newError(vm.r.getRangeError(), "Division by zero")) + } + if (*big.Int)(left).CmpAbs((*big.Int)(right)) < 0 { + result = (*valueBigInt)(big.NewInt(0)) + } else { + i, _ := new(big.Int).QuoRem((*big.Int)(left), (*big.Int)(right), big.NewInt(0)) + result = (*valueBigInt)(i) + } + goto end + } + panic(errMixBigIntType) + } else if _, ok := rightValue.(*valueBigInt); ok { + panic(errMixBigIntType) + } + left, right = leftValue.ToFloat(), rightValue.ToFloat() if math.IsNaN(left) || math.IsNaN(right) { result = _NaN @@ -1440,25 +1573,48 @@ type _mod struct{} var mod _mod func (_mod) exec(vm *vm) { - left := vm.stack[vm.sp-2] - right := vm.stack[vm.sp-1] + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) var result Value - if leftInt, ok := assertInt64(left); ok { - if rightInt, ok := assertInt64(right); ok { - if rightInt == 0 { + switch left := left.(type) { + case valueInt: + switch right := right.(type) { + case valueInt: + if right == 0 { result = _NaN goto end } - r := leftInt % rightInt - if r == 0 && leftInt < 0 { + r := left % right + if r == 0 && left < 0 { result = _negativeZero } else { - result = intToValue(leftInt % rightInt) + result = intToValue(int64(left % right)) + } + goto end + case *valueBigInt: + panic(errMixBigIntType) + } + case valueFloat: + if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + case *valueBigInt: + if right, ok := right.(*valueBigInt); ok { + switch { + case (*big.Int)(right).Cmp(big.NewInt(0)) == 0: + panic(vm.r.newError(vm.r.getRangeError(), "Division by zero")) + case (*big.Int)(left).Cmp(big.NewInt(0)) < 0: + abs := new(big.Int).Abs((*big.Int)(left)) + v := new(big.Int).Mod(abs, (*big.Int)(right)) + result = (*valueBigInt)(v.Neg(v)) + default: + result = (*valueBigInt)(new(big.Int).Mod((*big.Int)(left), (*big.Int)(right))) } goto end } + panic(errMixBigIntType) } result = floatToValue(math.Mod(left.ToFloat(), right.ToFloat())) @@ -1477,13 +1633,16 @@ func (_neg) exec(vm *vm) { var result Value - if i, ok := assertInt64(operand); ok { - if i == 0 { + switch n := toNumeric(operand).(type) { + case *valueBigInt: + result = (*valueBigInt)(new(big.Int).Neg((*big.Int)(n))) + case valueInt: + if n == 0 { result = _negativeZero } else { - result = valueInt(-i) + result = -n } - } else { + default: f := operand.ToFloat() if !math.IsNaN(f) { f = -f @@ -1511,14 +1670,15 @@ var inc _inc func (_inc) exec(vm *vm) { v := vm.stack[vm.sp-1] - if i, ok := assertInt64(v); ok { - v = intToValue(i + 1) - goto end + switch n := v.(type) { + case *valueBigInt: + v = (*valueBigInt)(new(big.Int).Add((*big.Int)(n), big.NewInt(1))) + case valueInt: + v = intToValue(int64(n + 1)) + default: + v = valueFloat(n.ToFloat() + 1) } - v = valueFloat(v.ToFloat() + 1) - -end: vm.stack[vm.sp-1] = v vm.pc++ } @@ -1530,14 +1690,15 @@ var dec _dec func (_dec) exec(vm *vm) { v := vm.stack[vm.sp-1] - if i, ok := assertInt64(v); ok { - v = intToValue(i - 1) - goto end + switch n := v.(type) { + case *valueBigInt: + v = (*valueBigInt)(new(big.Int).Sub((*big.Int)(n), big.NewInt(1))) + case valueInt: + v = intToValue(int64(n - 1)) + default: + v = valueFloat(n.ToFloat() - 1) } - v = valueFloat(v.ToFloat() - 1) - -end: vm.stack[vm.sp-1] = v vm.pc++ } @@ -1547,9 +1708,23 @@ type _and struct{} var and _and func (_and) exec(vm *vm) { - left := toInt32(vm.stack[vm.sp-2]) - right := toInt32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left & right)) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + var result Value + + if left, ok := left.(*valueBigInt); ok { + if right, ok := right.(*valueBigInt); ok { + result = (*valueBigInt)(new(big.Int).And((*big.Int)(left), (*big.Int)(right))) + goto end + } + panic(errMixBigIntType) + } else if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = intToValue(int64(toInt32(left) & toInt32(right))) +end: + vm.stack[vm.sp-2] = result vm.sp-- vm.pc++ } @@ -1559,9 +1734,23 @@ type _or struct{} var or _or func (_or) exec(vm *vm) { - left := toInt32(vm.stack[vm.sp-2]) - right := toInt32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left | right)) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + var result Value + + if left, ok := left.(*valueBigInt); ok { + if right, ok := right.(*valueBigInt); ok { + result = (*valueBigInt)(new(big.Int).Or((*big.Int)(left), (*big.Int)(right))) + goto end + } + panic(errMixBigIntType) + } else if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = intToValue(int64(toInt32(left) | toInt32(right))) +end: + vm.stack[vm.sp-2] = result vm.sp-- vm.pc++ } @@ -1571,9 +1760,23 @@ type _xor struct{} var xor _xor func (_xor) exec(vm *vm) { - left := toInt32(vm.stack[vm.sp-2]) - right := toInt32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left ^ right)) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + var result Value + + if left, ok := left.(*valueBigInt); ok { + if right, ok := right.(*valueBigInt); ok { + result = (*valueBigInt)(new(big.Int).Xor((*big.Int)(left), (*big.Int)(right))) + goto end + } + panic(errMixBigIntType) + } else if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = intToValue(int64(toInt32(left) ^ toInt32(right))) +end: + vm.stack[vm.sp-2] = result vm.sp-- vm.pc++ } @@ -1583,8 +1786,14 @@ type _bnot struct{} var bnot _bnot func (_bnot) exec(vm *vm) { - op := toInt32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-1] = intToValue(int64(^op)) + v := vm.stack[vm.sp-1] + switch n := toNumeric(v).(type) { + case *valueBigInt: + v = (*valueBigInt)(new(big.Int).Not((*big.Int)(n))) + default: + v = intToValue(int64(^toInt32(n))) + } + vm.stack[vm.sp-1] = v vm.pc++ } @@ -1593,9 +1802,28 @@ type _sal struct{} var sal _sal func (_sal) exec(vm *vm) { - left := toInt32(vm.stack[vm.sp-2]) - right := toUint32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left << (right & 0x1F))) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + var result Value + + if left, ok := left.(*valueBigInt); ok { + if right, ok := right.(*valueBigInt); ok { + n := uint((*big.Int)(right).Uint64()) + if (*big.Int)(right).Sign() < 0 { + result = (*valueBigInt)(new(big.Int).Rsh((*big.Int)(left), n)) + } else { + result = (*valueBigInt)(new(big.Int).Lsh((*big.Int)(left), n)) + } + goto end + } + panic(errMixBigIntType) + } else if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = intToValue(int64(toInt32(left) << (toUint32(right) & 0x1F))) +end: + vm.stack[vm.sp-2] = result vm.sp-- vm.pc++ } @@ -1605,9 +1833,28 @@ type _sar struct{} var sar _sar func (_sar) exec(vm *vm) { - left := toInt32(vm.stack[vm.sp-2]) - right := toUint32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F))) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + var result Value + + if left, ok := left.(*valueBigInt); ok { + if right, ok := right.(*valueBigInt); ok { + n := uint((*big.Int)(right).Uint64()) + if (*big.Int)(right).Sign() < 0 { + result = (*valueBigInt)(new(big.Int).Lsh((*big.Int)(left), n)) + } else { + result = (*valueBigInt)(new(big.Int).Rsh((*big.Int)(left), n)) + } + goto end + } + panic(errMixBigIntType) + } else if _, ok := right.(*valueBigInt); ok { + panic(errMixBigIntType) + } + + result = intToValue(int64(toInt32(left) >> (toUint32(right) & 0x1F))) +end: + vm.stack[vm.sp-2] = result vm.sp-- vm.pc++ } @@ -1617,9 +1864,17 @@ type _shr struct{} var shr _shr func (_shr) exec(vm *vm) { - left := toUint32(vm.stack[vm.sp-2]) - right := toUint32(vm.stack[vm.sp-1]) - vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F))) + left := toNumeric(vm.stack[vm.sp-2]) + right := toNumeric(vm.stack[vm.sp-1]) + + if _, ok := left.(*valueBigInt); ok { + _ = toNumeric(right) + panic(vm.r.NewTypeError("BigInts have no unsigned right shift, use >> instead")) + } else if _, ok := right.(*valueBigInt); ok { + panic(vm.r.NewTypeError("BigInts have no unsigned right shift, use >> instead")) + } + + vm.stack[vm.sp-2] = intToValue(int64(toUint32(left) >> (toUint32(right) & 0x1F))) vm.sp-- vm.pc++ } @@ -1652,10 +1907,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++ @@ -1667,10 +1922,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 @@ -1683,10 +1938,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 @@ -1699,10 +1954,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, }) @@ -1972,7 +2227,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), }) @@ -1983,7 +2238,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), @@ -1995,7 +2250,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, @@ -2007,7 +2262,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), @@ -2394,11 +2649,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)) @@ -2412,13 +2667,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)) @@ -2452,12 +2707,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()}} @@ -2475,12 +2730,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()}} @@ -2734,7 +2989,7 @@ func (s resolveVar1) exec(vm *vm) { } } - ref = &objRef{ + ref = &objStrRef{ base: vm.r.globalObject, name: name, binding: true, @@ -2788,9 +3043,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 } @@ -2815,7 +3067,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, @@ -4010,18 +4262,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 @@ -4040,21 +4286,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 { @@ -4082,7 +4322,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 } @@ -4112,9 +4351,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 } @@ -4314,31 +4550,94 @@ func toPrimitive(v Value) Value { func cmp(px, py Value) Value { var ret bool - var nx, ny float64 + xs, isPxString := px.(String) + ys, isPyString := py.(String) - if xs, ok := px.(String); ok { - if ys, ok := py.(String); ok { - ret = xs.CompareTo(ys) < 0 + if isPxString && isPyString { + ret = xs.CompareTo(ys) < 0 + goto end + } else { + if px, ok := px.(*valueBigInt); ok && isPyString { + ny, err := stringToBigInt(ys.toTrimmedUTF8()) + if err != nil { + return _undefined + } + ret = (*big.Int)(px).Cmp(ny) < 0 + goto end + } + if py, ok := py.(*valueBigInt); ok && isPxString { + nx, err := stringToBigInt(xs.toTrimmedUTF8()) + if err != nil { + return _undefined + } + ret = nx.Cmp((*big.Int)(py)) < 0 goto end } } - if xi, ok := px.(valueInt); ok { - if yi, ok := py.(valueInt); ok { - ret = xi < yi + px = toNumeric(px) + py = toNumeric(py) + + switch nx := px.(type) { + case valueInt: + switch ny := py.(type) { + case valueInt: + ret = nx < ny + goto end + case *valueBigInt: + ret = big.NewInt(int64(nx)).Cmp((*big.Int)(ny)) < 0 + goto end + } + case valueFloat: + switch ny := py.(type) { + case *valueBigInt: + switch { + case math.IsNaN(float64(nx)): + return _undefined + case nx == _negativeInf: + ret = true + goto end + } + if nx := big.NewFloat(float64(nx)); nx.IsInt() { + nx, _ := nx.Int(nil) + ret = nx.Cmp((*big.Int)(ny)) < 0 + } else { + ret = nx.Cmp(new(big.Float).SetInt((*big.Int)(ny))) < 0 + } + goto end + } + case *valueBigInt: + switch ny := py.(type) { + case valueInt: + ret = (*big.Int)(nx).Cmp(big.NewInt(int64(ny))) < 0 + goto end + case valueFloat: + switch { + case math.IsNaN(float64(ny)): + return _undefined + case ny == _positiveInf: + ret = true + goto end + } + if ny := big.NewFloat(float64(ny)); ny.IsInt() { + ny, _ := ny.Int(nil) + ret = (*big.Int)(nx).Cmp(ny) < 0 + } else { + ret = new(big.Float).SetInt((*big.Int)(nx)).Cmp(ny) < 0 + } + goto end + case *valueBigInt: + ret = (*big.Int)(nx).Cmp((*big.Int)(ny)) < 0 goto end } } - nx = px.ToFloat() - ny = py.ToFloat() - - if math.IsNaN(nx) || math.IsNaN(ny) { + if nx, ny := px.ToFloat(), py.ToFloat(); math.IsNaN(nx) || math.IsNaN(ny) { return _undefined + } else { + ret = nx < ny } - ret = nx < ny - end: if ret { return valueTrue @@ -4751,6 +5050,8 @@ func (_typeof) exec(vm *vm) { r = stringString case valueInt, valueFloat: r = stringNumber + case *valueBigInt: + r = stringBigInt case *Symbol: r = stringSymbol default: diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b1383a76ef..d4e22a51aa0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -163,7 +163,7 @@ github.com/google/uuid # github.com/gorilla/websocket v1.5.1 ## explicit; go 1.20 github.com/gorilla/websocket -# github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3 +# github.com/grafana/sobek v0.0.0-20240823144814-3c582bfdac82 ## explicit; go 1.20 github.com/grafana/sobek github.com/grafana/sobek/ast