From 3ea53c5dc8eaeecfe5d13dc84f59a8f8f67ce3e7 Mon Sep 17 00:00:00 2001 From: sepehrst Date: Sat, 4 Feb 2023 22:17:11 +0000 Subject: [PATCH] deps: V8: cherry-pick c875e86df1d7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [bigint] Convert BigInt property names to decimal Hexadecimal/octal/binary BigInt property names should be converted to decimal, i.e. the following object literals should all be equivalent: var o = {0xF: 1}, p = {0xFn: 1}, q = {15: 1}, r = {15n: 1}. Test case by yangwenming@bytedance.com, uploaded at https://chromium-review.googlesource.com/c/v8/v8/+/3634937 Fixed: v8:10600 Change-Id: Ie1d8a16e95697cd31cbc0784843779c921ce91fa Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3642302 Reviewed-by: Toon Verwaest Commit-Queue: Jakob Kummerow Cr-Commit-Position: refs/heads/main@{#80490} Refs: v8/v8@c875e86 PR-URL: https://github.com/nodejs/node/pull/46501 Refs: https://github.com/v8/v8/commit/c875e86 Reviewed-By: Michaƫl Zasso Reviewed-By: Jiawen Geng --- common.gypi | 2 +- deps/v8/src/numbers/conversions.cc | 25 +++++++++++++++++++ deps/v8/src/numbers/conversions.h | 2 ++ deps/v8/src/parsing/parser-base.h | 2 +- deps/v8/src/parsing/parser.cc | 10 ++++++++ deps/v8/src/parsing/parser.h | 2 ++ deps/v8/src/parsing/preparser.h | 4 +++ deps/v8/src/parsing/scanner.h | 3 +++ .../mjsunit/harmony/bigint/property-names.js | 23 +++++++++++++++++ 9 files changed, 71 insertions(+), 2 deletions(-) diff --git a/common.gypi b/common.gypi index 5372c8d42de531..47b9453124631f 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.22', + 'v8_embedder_string': '-node.23', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/numbers/conversions.cc b/deps/v8/src/numbers/conversions.cc index 0683402794dbe7..93f5ba7be50a75 100644 --- a/deps/v8/src/numbers/conversions.cc +++ b/deps/v8/src/numbers/conversions.cc @@ -12,6 +12,7 @@ #include "src/base/numbers/dtoa.h" #include "src/base/numbers/strtod.h" #include "src/base/platform/wrappers.h" +#include "src/base/small-vector.h" #include "src/bigint/bigint.h" #include "src/common/assert-scope.h" #include "src/handles/handles.h" @@ -970,6 +971,23 @@ class StringToBigIntHelper : public StringToIntHelper { UNREACHABLE(); } + // Used for converting BigInt literals. The scanner has already checked + // that the literal is valid and not too big, so this always succeeds. + std::unique_ptr DecimalString(bigint::Processor* processor) { + DCHECK_EQ(behavior_, Behavior::kLiteral); + this->ParseInt(); + DCHECK_EQ(this->state(), State::kDone); + int num_digits = accumulator_.ResultLength(); + base::SmallVector digit_storage(num_digits); + bigint::RWDigits digits(digit_storage.data(), num_digits); + processor->FromString(digits, &accumulator_); + int num_chars = bigint::ToStringResultLength(digits, 10, false); + std::unique_ptr out(new char[num_chars + 1]); + processor->ToString(out.get(), &num_chars, digits, 10, false); + out[num_chars] = '\0'; + return out; + } + private: template void ParseInternal(Char start) { @@ -1018,6 +1036,13 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) MaybeHandle BigIntLiteral(LocalIsolate* isolate, const char* string); +std::unique_ptr BigIntLiteralToDecimal( + LocalIsolate* isolate, base::Vector literal) { + StringToBigIntHelper helper(nullptr, literal.begin(), + literal.length()); + return helper.DecimalString(isolate->bigint_processor()); +} + const char* DoubleToCString(double v, base::Vector buffer) { switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) { case FP_NAN: diff --git a/deps/v8/src/numbers/conversions.h b/deps/v8/src/numbers/conversions.h index 9232de93cafe90..fce0d726544527 100644 --- a/deps/v8/src/numbers/conversions.h +++ b/deps/v8/src/numbers/conversions.h @@ -119,6 +119,8 @@ const int kDoubleToCStringMinBufferSize = 100; V8_EXPORT_PRIVATE const char* DoubleToCString(double value, base::Vector buffer); +V8_EXPORT_PRIVATE std::unique_ptr BigIntLiteralToDecimal( + LocalIsolate* isolate, base::Vector literal); // Convert an int to a null-terminated string. The returned string is // located inside the buffer, but not necessarily at the start. V8_EXPORT_PRIVATE const char* IntToCString(int n, base::Vector buffer); diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index df829ff8cac43c..cfa91e446f82e9 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -2288,7 +2288,7 @@ typename ParserBase::ExpressionT ParserBase::ParseProperty( case Token::BIGINT: { Consume(Token::BIGINT); - prop_info->name = impl()->GetSymbol(); + prop_info->name = impl()->GetBigIntAsSymbol(); is_array_index = impl()->IsArrayIndex(prop_info->name, &index); break; } diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 6ee70886a99f8d..9789909456ee5e 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -247,6 +247,16 @@ bool Parser::CollapseNaryExpression(Expression** x, Expression* y, return true; } +const AstRawString* Parser::GetBigIntAsSymbol() { + base::Vector literal = scanner()->BigIntLiteral(); + if (literal[0] != '0' || literal.length() == 1) { + return ast_value_factory()->GetOneByteString(literal); + } + std::unique_ptr decimal = + BigIntLiteralToDecimal(local_isolate_, literal); + return ast_value_factory()->GetOneByteString(decimal.get()); +} + Expression* Parser::BuildUnaryExpression(Expression* expression, Token::Value op, int pos) { DCHECK_NOT_NULL(expression); diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index 1d8fa2515df380..909fc7defdb0cc 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -790,6 +790,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase) { return ast_value_factory()->GetOneByteString(string); } + const AstRawString* GetBigIntAsSymbol(); + class ThisExpression* ThisExpression() { UseThis(); return factory()->ThisExpression(); diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h index ff64f9a5f55bba..9b1d54ed7d6001 100644 --- a/deps/v8/src/parsing/preparser.h +++ b/deps/v8/src/parsing/preparser.h @@ -1522,6 +1522,10 @@ class PreParser : public ParserBase { return PreParserIdentifier::Default(); } + V8_INLINE PreParserIdentifier GetBigIntAsSymbol() const { + return PreParserIdentifier::Default(); + } + V8_INLINE PreParserExpression ThisExpression() { UseThis(); return PreParserExpression::This(); diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h index 0fe907632de4bf..3a38ed243bb1dd 100644 --- a/deps/v8/src/parsing/scanner.h +++ b/deps/v8/src/parsing/scanner.h @@ -336,6 +336,9 @@ class V8_EXPORT_PRIVATE Scanner { AstValueFactory* ast_value_factory) const; double DoubleValue(); + base::Vector BigIntLiteral() const { + return literal_one_byte_string(); + } const char* CurrentLiteralAsCString(Zone* zone) const; diff --git a/deps/v8/test/mjsunit/harmony/bigint/property-names.js b/deps/v8/test/mjsunit/harmony/bigint/property-names.js index ac65e1041d50fa..400b51f51c67a3 100644 --- a/deps/v8/test/mjsunit/harmony/bigint/property-names.js +++ b/deps/v8/test/mjsunit/harmony/bigint/property-names.js @@ -7,3 +7,26 @@ assertEquals(it, 1); var { 999999999999999999n: it } = { 999999999999999999n: 1 }; // greater than max safe integer assertEquals(it, 1); + +var obj = { 0xfffffffffffffffffffffn: 1}; +assertEquals(1, obj["19342813113834066795298815"]); + +var obj2 = {0o777777777777777777777777777n: 1}; +assertEquals(1, obj2["2417851639229258349412351"]); + +var obj3 = { 0x4n: 'hi' }; + +assertEquals('hi', obj3[4]); +assertEquals(undefined, obj3["0x4"]); + +let obj4 = + {12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890n: 1}; +assertEquals( + 1, + obj4["12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"]); + +// 130 hex digits +let obj5 = {0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn: 1}; +assertEquals( + 1, + obj5["3432398830065304857490950399540696608634717650071652704697231729592771591698828026061279820330727277488648155695740429018560993999858321906287014145557528575"]);