Skip to content

Commit fdb9812

Browse files
bcoeruyadorno
authored andcommitted
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 <[email protected]> Reviewed-by: Toon Verwaest <[email protected]> Reviewed-by: Gus Caplan <[email protected]> Reviewed-by: Sigurd Schneider <[email protected]> Commit-Queue: Benjamin Coe <[email protected]> Cr-Commit-Position: refs/heads/master@{#72075} Refs: v8/v8@fe191e8 PR-URL: #36956 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Michaël Zasso <[email protected]>
1 parent 68ffe5a commit fdb9812

File tree

5 files changed

+89
-12
lines changed

5 files changed

+89
-12
lines changed

deps/v8/src/ast/ast-source-ranges.h

+19
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct SourceRange {
4747
V(Block) \
4848
V(CaseClause) \
4949
V(Conditional) \
50+
V(Expression) \
5051
V(FunctionLiteral) \
5152
V(IfStatement) \
5253
V(IterationStatement) \
@@ -281,6 +282,24 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges {
281282
ZoneVector<SourceRange> ranges_;
282283
};
283284

285+
class ExpressionSourceRanges final : public AstNodeSourceRanges {
286+
public:
287+
explicit ExpressionSourceRanges(const SourceRange& right_range)
288+
: right_range_(right_range) {}
289+
290+
SourceRange GetRange(SourceRangeKind kind) override {
291+
DCHECK(HasRange(kind));
292+
return right_range_;
293+
}
294+
295+
bool HasRange(SourceRangeKind kind) override {
296+
return kind == SourceRangeKind::kRight;
297+
}
298+
299+
private:
300+
SourceRange right_range_;
301+
};
302+
284303
class SuspendSourceRanges final : public ContinuationSourceRanges {
285304
public:
286305
explicit SuspendSourceRanges(int32_t continuation_position)

deps/v8/src/interpreter/bytecode-generator.cc

+9
Original file line numberDiff line numberDiff line change
@@ -4575,8 +4575,11 @@ void BytecodeGenerator::VisitThrow(Throw* expr) {
45754575
void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
45764576
if (property->is_optional_chain_link()) {
45774577
DCHECK_NOT_NULL(optional_chaining_null_labels_);
4578+
int right_range =
4579+
AllocateBlockCoverageSlotIfEnabled(property, SourceRangeKind::kRight);
45784580
builder()->LoadAccumulatorWithRegister(obj).JumpIfUndefinedOrNull(
45794581
optional_chaining_null_labels_->New());
4582+
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
45804583
}
45814584

45824585
AssignType property_kind = Property::GetAssignType(property);
@@ -4902,8 +4905,11 @@ void BytecodeGenerator::VisitCall(Call* expr) {
49024905

49034906
if (expr->is_optional_chain_link()) {
49044907
DCHECK_NOT_NULL(optional_chaining_null_labels_);
4908+
int right_range =
4909+
AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kRight);
49054910
builder()->LoadAccumulatorWithRegister(callee).JumpIfUndefinedOrNull(
49064911
optional_chaining_null_labels_->New());
4912+
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
49074913
}
49084914

49094915
// Evaluate all arguments to the function call and store in sequential args
@@ -5175,7 +5181,10 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* unary) {
51755181
OptionalChainNullLabelScope label_scope(this);
51765182
VisitForAccumulatorValue(property->obj());
51775183
if (property->is_optional_chain_link()) {
5184+
int right_range = AllocateBlockCoverageSlotIfEnabled(
5185+
property, SourceRangeKind::kRight);
51785186
builder()->JumpIfUndefinedOrNull(label_scope.labels()->New());
5187+
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
51795188
}
51805189
Register object = register_allocator()->NewRegister();
51815190
builder()->StoreAccumulatorInRegister(object);

deps/v8/src/parsing/parser-base.h

+15-11
Original file line numberDiff line numberDiff line change
@@ -3289,17 +3289,24 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
32893289

32903290
bool optional_chaining = false;
32913291
bool is_optional = false;
3292+
int optional_link_begin;
32923293
do {
32933294
switch (peek()) {
32943295
case Token::QUESTION_PERIOD: {
32953296
if (is_optional) {
32963297
ReportUnexpectedToken(peek());
32973298
return impl()->FailureExpression();
32983299
}
3300+
// Include the ?. in the source range position.
3301+
optional_link_begin = scanner()->peek_location().beg_pos;
32993302
Consume(Token::QUESTION_PERIOD);
33003303
is_optional = true;
33013304
optional_chaining = true;
3302-
continue;
3305+
if (Token::IsPropertyOrCall(peek())) continue;
3306+
int pos = position();
3307+
ExpressionT key = ParsePropertyOrPrivatePropertyName();
3308+
result = factory()->NewProperty(result, key, pos, is_optional);
3309+
break;
33033310
}
33043311

33053312
/* Property */
@@ -3379,14 +3386,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
33793386
}
33803387

33813388
default:
3382-
/* Optional Property */
3383-
if (is_optional) {
3384-
DCHECK_EQ(scanner()->current_token(), Token::QUESTION_PERIOD);
3385-
int pos = position();
3386-
ExpressionT key = ParsePropertyOrPrivatePropertyName();
3387-
result = factory()->NewProperty(result, key, pos, is_optional);
3388-
break;
3389-
}
3389+
// Template literals in/after an Optional Chain not supported:
33903390
if (optional_chaining) {
33913391
impl()->ReportMessageAt(scanner()->peek_location(),
33923392
MessageTemplate::kOptionalChainingNoTemplate);
@@ -3397,8 +3397,12 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
33973397
result = ParseTemplateLiteral(result, position(), true);
33983398
break;
33993399
}
3400-
is_optional = false;
3401-
} while (is_optional || Token::IsPropertyOrCall(peek()));
3400+
if (is_optional) {
3401+
SourceRange chain_link_range(optional_link_begin, end_position());
3402+
impl()->RecordExpressionSourceRange(result, chain_link_range);
3403+
is_optional = false;
3404+
}
3405+
} while (Token::IsPropertyOrCall(peek()));
34023406
if (optional_chaining) return factory()->NewOptionalChain(result);
34033407
return result;
34043408
}

deps/v8/src/parsing/parser.h

+8
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
997997
node, zone()->New<IterationStatementSourceRanges>(body_range));
998998
}
999999

1000+
// Used to record source ranges of expressions associated with optional chain:
1001+
V8_INLINE void RecordExpressionSourceRange(Expression* node,
1002+
const SourceRange& right_range) {
1003+
if (source_range_map_ == nullptr) return;
1004+
source_range_map_->Insert(node,
1005+
zone()->New<ExpressionSourceRanges>(right_range));
1006+
}
1007+
10001008
V8_INLINE void RecordSuspendSourceRange(Expression* node,
10011009
int32_t continuation_position) {
10021010
if (source_range_map_ == nullptr) return;

deps/v8/test/mjsunit/code-coverage-block.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,7 @@ a(true); // 0500
11771177
{"start":0,"end":401,"count":2},
11781178
{"start":154,"end":254,"count":0}]);
11791179

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

1198+
TestCoverage(
1199+
"Optional Chaining",
1200+
`
1201+
const a = undefined || null // 0000
1202+
const b = a?.b // 0050
1203+
const c = a?.['b'] // 0100
1204+
const d = { // 0150
1205+
e: {f: 99, g: () => {return undefined}} // 0200
1206+
} // 0250
1207+
const e = d?.e?.f // 0300
1208+
const f = d?.e?.['f'] // 0350
1209+
const g = d?.e?.f?.g // 0400
1210+
const h = d?.e?.f?.g?.h // 0450
1211+
const i = d?.['d']?.['e']?.['h'] // 0500
1212+
const k = a?.('b') // 0550
1213+
const l = d?.e?.g?.() // 0600
1214+
const m = d?.e?.g?.()?.a?.b // 0650
1215+
delete a?.b // 0700
1216+
const n = d?.[d?.x?.f] // 0750
1217+
if (a?.[d?.x?.f]) { const p = 99 } else {}// 0800
1218+
const p = d?.[d?.x?.f]?.x // 0850
1219+
`,
1220+
[{"start":0,"end":899,"count":1},
1221+
{"start":61,"end":64,"count":0},
1222+
{"start":111,"end":118,"count":0},
1223+
{"start":470,"end":473,"count":0},
1224+
{"start":518,"end":532,"count":0},
1225+
{"start":561,"end":568,"count":0},
1226+
{"start":671,"end":677,"count":0},
1227+
{"start":708,"end":711,"count":0},
1228+
{"start":768,"end":771,"count":0},
1229+
{"start":805,"end":816,"count":0},
1230+
{"start":818,"end":834,"count":0},
1231+
{"start":868,"end":871,"count":0},
1232+
{"start":872,"end":875,"count":0},
1233+
{"start":216,"end":240,"count":2}]);
1234+
11981235
%DebugToggleBlockCoverage(false);

0 commit comments

Comments
 (0)