Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: V8: cherry-pick fe191e8d05cc #36956

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -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 #####

Expand Down
19 changes: 19 additions & 0 deletions deps/v8/src/ast/ast-source-ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct SourceRange {
V(Block) \
V(CaseClause) \
V(Conditional) \
V(Expression) \
V(FunctionLiteral) \
V(IfStatement) \
V(IterationStatement) \
Expand Down Expand Up @@ -281,6 +282,24 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges {
ZoneVector<SourceRange> ranges_;
};

class ExpressionSourceRanges final : public AstNodeSourceRanges {
public:
explicit ExpressionSourceRanges(const SourceRange& right_range)
: right_range_(right_range) {}

SourceRange GetRange(SourceRangeKind kind) override {
DCHECK(HasRange(kind));
return right_range_;
}

bool HasRange(SourceRangeKind kind) override {
return kind == SourceRangeKind::kRight;
}

private:
SourceRange right_range_;
};

class SuspendSourceRanges final : public ContinuationSourceRanges {
public:
explicit SuspendSourceRanges(int32_t continuation_position)
Expand Down
9 changes: 9 additions & 0 deletions deps/v8/src/interpreter/bytecode-generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4590,8 +4590,11 @@ void BytecodeGenerator::VisitThrow(Throw* expr) {
void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
if (property->is_optional_chain_link()) {
DCHECK_NOT_NULL(optional_chaining_null_labels_);
int right_range =
AllocateBlockCoverageSlotIfEnabled(property, SourceRangeKind::kRight);
builder()->LoadAccumulatorWithRegister(obj).JumpIfUndefinedOrNull(
optional_chaining_null_labels_->New());
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
}

AssignType property_kind = Property::GetAssignType(property);
Expand Down Expand Up @@ -4931,8 +4934,11 @@ void BytecodeGenerator::VisitCall(Call* expr) {

if (expr->is_optional_chain_link()) {
DCHECK_NOT_NULL(optional_chaining_null_labels_);
int right_range =
AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kRight);
builder()->LoadAccumulatorWithRegister(callee).JumpIfUndefinedOrNull(
optional_chaining_null_labels_->New());
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
}

// Evaluate all arguments to the function call and store in sequential args
Expand Down Expand Up @@ -5204,7 +5210,10 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* unary) {
OptionalChainNullLabelScope label_scope(this);
VisitForAccumulatorValue(property->obj());
if (property->is_optional_chain_link()) {
int right_range = AllocateBlockCoverageSlotIfEnabled(
property, SourceRangeKind::kRight);
builder()->JumpIfUndefinedOrNull(label_scope.labels()->New());
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
}
Register object = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(object);
Expand Down
26 changes: 15 additions & 11 deletions deps/v8/src/parsing/parser-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -3297,17 +3297,24 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {

bool optional_chaining = false;
bool is_optional = false;
int optional_link_begin;
do {
switch (peek()) {
case Token::QUESTION_PERIOD: {
if (is_optional) {
ReportUnexpectedToken(peek());
return impl()->FailureExpression();
}
// Include the ?. in the source range position.
optional_link_begin = scanner()->peek_location().beg_pos;
Consume(Token::QUESTION_PERIOD);
is_optional = true;
optional_chaining = true;
continue;
if (Token::IsPropertyOrCall(peek())) continue;
int pos = position();
ExpressionT key = ParsePropertyOrPrivatePropertyName();
result = factory()->NewProperty(result, key, pos, is_optional);
break;
}

/* Property */
Expand Down Expand Up @@ -3387,14 +3394,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
}

default:
/* Optional Property */
if (is_optional) {
DCHECK_EQ(scanner()->current_token(), Token::QUESTION_PERIOD);
int pos = position();
ExpressionT key = ParsePropertyOrPrivatePropertyName();
result = factory()->NewProperty(result, key, pos, is_optional);
break;
}
// Template literals in/after an Optional Chain not supported:
if (optional_chaining) {
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kOptionalChainingNoTemplate);
Expand All @@ -3405,8 +3405,12 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
result = ParseTemplateLiteral(result, position(), true);
break;
}
is_optional = false;
} while (is_optional || Token::IsPropertyOrCall(peek()));
if (is_optional) {
SourceRange chain_link_range(optional_link_begin, end_position());
impl()->RecordExpressionSourceRange(result, chain_link_range);
is_optional = false;
}
} while (Token::IsPropertyOrCall(peek()));
if (optional_chaining) return factory()->NewOptionalChain(result);
return result;
}
Expand Down
8 changes: 8 additions & 0 deletions deps/v8/src/parsing/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
node, zone()->New<IterationStatementSourceRanges>(body_range));
}

// Used to record source ranges of expressions associated with optional chain:
V8_INLINE void RecordExpressionSourceRange(Expression* node,
const SourceRange& right_range) {
if (source_range_map_ == nullptr) return;
source_range_map_->Insert(node,
zone()->New<ExpressionSourceRanges>(right_range));
}

V8_INLINE void RecordSuspendSourceRange(Expression* node,
int32_t continuation_position) {
if (source_range_map_ == nullptr) return;
Expand Down
39 changes: 38 additions & 1 deletion deps/v8/test/mjsunit/code-coverage-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ a(true); // 0500
{"start":0,"end":401,"count":2},
{"start":154,"end":254,"count":0}]);

TestCoverage(
TestCoverage(
"https://crbug.com/v8/11231 - nullish coalescing",
`
const a = true // 0000
Expand All @@ -1195,4 +1195,41 @@ const i = c ?? b ?? 'hello' // 0400
{"start":262,"end":274,"count":0},
{"start":417,"end":427,"count":0}]);

TestCoverage(
"Optional Chaining",
`
const a = undefined || null // 0000
const b = a?.b // 0050
const c = a?.['b'] // 0100
const d = { // 0150
e: {f: 99, g: () => {return undefined}} // 0200
} // 0250
const e = d?.e?.f // 0300
const f = d?.e?.['f'] // 0350
const g = d?.e?.f?.g // 0400
const h = d?.e?.f?.g?.h // 0450
const i = d?.['d']?.['e']?.['h'] // 0500
const k = a?.('b') // 0550
const l = d?.e?.g?.() // 0600
const m = d?.e?.g?.()?.a?.b // 0650
delete a?.b // 0700
const n = d?.[d?.x?.f] // 0750
if (a?.[d?.x?.f]) { const p = 99 } else {}// 0800
const p = d?.[d?.x?.f]?.x // 0850
`,
[{"start":0,"end":899,"count":1},
{"start":61,"end":64,"count":0},
{"start":111,"end":118,"count":0},
{"start":470,"end":473,"count":0},
{"start":518,"end":532,"count":0},
{"start":561,"end":568,"count":0},
{"start":671,"end":677,"count":0},
{"start":708,"end":711,"count":0},
{"start":768,"end":771,"count":0},
{"start":805,"end":816,"count":0},
{"start":818,"end":834,"count":0},
{"start":868,"end":871,"count":0},
{"start":872,"end":875,"count":0},
{"start":216,"end":240,"count":2}]);

%DebugToggleBlockCoverage(false);