GeezerVison is showing github.com — deps: V8: cherry-pick fe191e8d05cc · nodejs/node@fdb9812
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/ast/ast-source-ranges.h +19Lines changed: 19 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -47,6 +47,7 @@ struct SourceRange { | 47 | 47 | V(Block) \ | 48 | 48 | V(CaseClause) \ | 49 | 49 | V(Conditional) \ | | 50 | + V(Expression) \ | 50 | 51 | V(FunctionLiteral) \ | 51 | 52 | V(IfStatement) \ | 52 | 53 | V(IterationStatement) \ | @@ -281,6 +282,24 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges { | 281 | 282 | ZoneVector<SourceRange> ranges_; | 282 | 283 | }; | 283 | 284 |
| | 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 | + | 284 | 303 | class SuspendSourceRanges final : public ContinuationSourceRanges { | 285 | 304 | public: | 286 | 305 | explicit SuspendSourceRanges(int32_t continuation_position) | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/interpreter/bytecode-generator.cc +9Lines changed: 9 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -4575,8 +4575,11 @@ void BytecodeGenerator::VisitThrow(Throw* expr) { | 4575 | 4575 | void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) { | 4576 | 4576 | if (property->is_optional_chain_link()) { | 4577 | 4577 | DCHECK_NOT_NULL(optional_chaining_null_labels_); | | 4578 | + int right_range = | | 4579 | + AllocateBlockCoverageSlotIfEnabled(property, SourceRangeKind::kRight); | 4578 | 4580 | builder()->LoadAccumulatorWithRegister(obj).JumpIfUndefinedOrNull( | 4579 | 4581 | optional_chaining_null_labels_->New()); | | 4582 | + BuildIncrementBlockCoverageCounterIfEnabled(right_range); | 4580 | 4583 | } | 4581 | 4584 |
| 4582 | 4585 | AssignType property_kind = Property::GetAssignType(property); | @@ -4902,8 +4905,11 @@ void BytecodeGenerator::VisitCall(Call* expr) { | 4902 | 4905 |
| 4903 | 4906 | if (expr->is_optional_chain_link()) { | 4904 | 4907 | DCHECK_NOT_NULL(optional_chaining_null_labels_); | | 4908 | + int right_range = | | 4909 | + AllocateBlockCoverageSlotIfEnabled(expr, SourceRangeKind::kRight); | 4905 | 4910 | builder()->LoadAccumulatorWithRegister(callee).JumpIfUndefinedOrNull( | 4906 | 4911 | optional_chaining_null_labels_->New()); | | 4912 | + BuildIncrementBlockCoverageCounterIfEnabled(right_range); | 4907 | 4913 | } | 4908 | 4914 |
| 4909 | 4915 | // Evaluate all arguments to the function call and store in sequential args | @@ -5175,7 +5181,10 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* unary) { | 5175 | 5181 | OptionalChainNullLabelScope label_scope(this); | 5176 | 5182 | VisitForAccumulatorValue(property->obj()); | 5177 | 5183 | if (property->is_optional_chain_link()) { | | 5184 | + int right_range = AllocateBlockCoverageSlotIfEnabled( | | 5185 | + property, SourceRangeKind::kRight); | 5178 | 5186 | builder()->JumpIfUndefinedOrNull(label_scope.labels()->New()); | | 5187 | + BuildIncrementBlockCoverageCounterIfEnabled(right_range); | 5179 | 5188 | } | 5180 | 5189 | Register object = register_allocator()->NewRegister(); | 5181 | 5190 | builder()->StoreAccumulatorInRegister(object); | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/parsing/parser-base.h +15-11Lines changed: 15 additions & 11 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3289,17 +3289,24 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { | 3289 | 3289 |
| 3290 | 3290 | bool optional_chaining = false; | 3291 | 3291 | bool is_optional = false; | | 3292 | + int optional_link_begin; | 3292 | 3293 | do { | 3293 | 3294 | switch (peek()) { | 3294 | 3295 | case Token::QUESTION_PERIOD: { | 3295 | 3296 | if (is_optional) { | 3296 | 3297 | ReportUnexpectedToken(peek()); | 3297 | 3298 | return impl()->FailureExpression(); | 3298 | 3299 | } | | 3300 | + // Include the ?. in the source range position. | | 3301 | + optional_link_begin = scanner()->peek_location().beg_pos; | 3299 | 3302 | Consume(Token::QUESTION_PERIOD); | 3300 | 3303 | is_optional = true; | 3301 | 3304 | 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; | 3303 | 3310 | } | 3304 | 3311 |
| 3305 | 3312 | /* Property */ | @@ -3379,14 +3386,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { | 3379 | 3386 | } | 3380 | 3387 |
| 3381 | 3388 | 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: | 3390 | 3390 | if (optional_chaining) { | 3391 | 3391 | impl()->ReportMessageAt(scanner()->peek_location(), | 3392 | 3392 | MessageTemplate::kOptionalChainingNoTemplate); | @@ -3397,8 +3397,12 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) { | 3397 | 3397 | result = ParseTemplateLiteral(result, position(), true); | 3398 | 3398 | break; | 3399 | 3399 | } | 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())); | 3402 | 3406 | if (optional_chaining) return factory()->NewOptionalChain(result); | 3403 | 3407 | return result; | 3404 | 3408 | } | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/src/parsing/parser.h +8Lines changed: 8 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -997,6 +997,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { | 997 | 997 | node, zone()->New<IterationStatementSourceRanges>(body_range)); | 998 | 998 | } | 999 | 999 |
| | 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 | + | 1000 | 1008 | V8_INLINE void RecordSuspendSourceRange(Expression* node, | 1001 | 1009 | int32_t continuation_position) { | 1002 | 1010 | if (source_range_map_ == nullptr) return; | |
Collapse file Copy file name to clipboardExpand all lines: deps/v8/test/mjsunit/code-coverage-block.js +38-1Lines changed: 38 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -1177,7 +1177,7 @@ a(true); // 0500 | 1177 | 1177 | {"start":0,"end":401,"count":2}, | 1178 | 1178 | {"start":154,"end":254,"count":0}]); | 1179 | 1179 |
| 1180 | | - TestCoverage( | | 1180 | +TestCoverage( | 1181 | 1181 | "https://crbug.com/v8/11231 - nullish coalescing", | 1182 | 1182 | ` | 1183 | 1183 | const a = true // 0000 | @@ -1195,4 +1195,41 @@ const i = c ?? b ?? 'hello' // 0400 | 1195 | 1195 | {"start":262,"end":274,"count":0}, | 1196 | 1196 | {"start":417,"end":427,"count":0}]); | 1197 | 1197 |
| | 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 | + | 1198 | 1235 | %DebugToggleBlockCoverage(false); |
|