Skip to content

Commit 0f2e021

Browse files
nshahanCommit Bot
authored andcommitted
[ddc] Fix non-null assertion crash
`VariableDeclaration.name` could be null when the variable was synthetically introduced by the compiler. In this case the expression compiler can ignore the variable because it's value doesn't reflect the value of a variable in the original dart source code. Add a regression test for the expression compiler that ensures code that introduces a synthetic variable will not cause a crash when you stop at a breakpoint. Fixes: dart-lang/sdk#49373 Change-Id: Ifc5f72ab4e5733ead17a20889c222bcc46921f6b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250343 Commit-Queue: Nicholas Shahan <nshahan@google.com> Reviewed-by: Anna Gringauze <annagrin@google.com>
1 parent d7df61e commit 0f2e021

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

pkg/dev_compiler/lib/src/kernel/expression_compiler.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,17 @@ class DartScopeBuilder extends Visitor<void> with VisitorVoidMixin {
163163

164164
@override
165165
void visitVariableDeclaration(VariableDeclaration decl) {
166+
var name = decl.name;
166167
// Collect locals and formals appearing before current breakpoint.
167168
// Note that we include variables with no offset because the offset
168169
// is not set in many cases in generated code, so omitting them would
169170
// make expression evaluation fail in too many cases.
170171
// Issue: https://github.com/dart-lang/sdk/issues/43966
171-
if (decl.fileOffset < 0 || decl.fileOffset < _offset) {
172-
_definitions[decl.name!] = decl.type;
172+
//
173+
// A null name signals that the variable was synthetically introduced by the
174+
// compiler so they are skipped.
175+
if ((decl.fileOffset < 0 || decl.fileOffset < _offset) && name != null) {
176+
_definitions[name] = decl.type;
173177
}
174178
super.visitVariableDeclaration(decl);
175179
}

pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,35 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
356356
expectedResult: 'true');
357357
});
358358
});
359+
360+
group('Synthetic variables', () {
361+
var source = r'''
362+
dynamic couldReturnNull() => null;
363+
364+
main() {
365+
var i = couldReturnNull() ?? 10;
366+
// Breakpoint: bp
367+
print(i);
368+
}
369+
''';
370+
371+
setUpAll(() async {
372+
await driver.initSource(setup, source);
373+
});
374+
375+
tearDownAll(() async {
376+
await driver.cleanupTest();
377+
});
378+
379+
test('do not cause a crash the expression compiler', () async {
380+
// The null aware code in the test source causes the compiler to introduce
381+
// a let statement that includes a synthetic variable declaration.
382+
// That variable has no name and was causing a crash in the expression
383+
// compiler https://github.com/dart-lang/sdk/issues/49373.
384+
await driver.check(
385+
breakpointId: 'bp', expression: 'true', expectedResult: 'true');
386+
});
387+
});
359388
}
360389

361390
/// Shared tests that are valid in legacy (before 2.12) and are agnostic to

0 commit comments

Comments
 (0)