mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
deps: V8: cherry-pick fe191e8d05cc
Original commit message:
[coverage] optional chaining coverage
Implement coverage tracking for optional chains.
Bug: v8:10060
Change-Id: I4f29eda64b6d859939f5f58f4fabead649905795
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2573013
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Gus Caplan <snek@chromium.org>
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Commit-Queue: Benjamin Coe <bencoe@google.com>
Cr-Commit-Position: refs/heads/master@{#72075}
Refs: fe191e8d05
PR-URL: https://github.com/nodejs/node/pull/36956
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
bd899bc656
commit
afd911c38c
@ -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 #####
|
||||
|
||||
|
19
deps/v8/src/ast/ast-source-ranges.h
vendored
19
deps/v8/src/ast/ast-source-ranges.h
vendored
@ -47,6 +47,7 @@ struct SourceRange {
|
||||
V(Block) \
|
||||
V(CaseClause) \
|
||||
V(Conditional) \
|
||||
V(Expression) \
|
||||
V(FunctionLiteral) \
|
||||
V(IfStatement) \
|
||||
V(IterationStatement) \
|
||||
@ -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)
|
||||
|
@ -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);
|
||||
@ -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
|
||||
@ -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);
|
||||
|
26
deps/v8/src/parsing/parser-base.h
vendored
26
deps/v8/src/parsing/parser-base.h
vendored
@ -3297,6 +3297,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
|
||||
|
||||
bool optional_chaining = false;
|
||||
bool is_optional = false;
|
||||
int optional_link_begin;
|
||||
do {
|
||||
switch (peek()) {
|
||||
case Token::QUESTION_PERIOD: {
|
||||
@ -3304,10 +3305,16 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
|
||||
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 */
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
|
8
deps/v8/src/parsing/parser.h
vendored
8
deps/v8/src/parsing/parser.h
vendored
@ -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;
|
||||
|
39
deps/v8/test/mjsunit/code-coverage-block.js
vendored
39
deps/v8/test/mjsunit/code-coverage-block.js
vendored
@ -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
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user