[kernel/DDC] DDC shouldn't crash when trying to translate line/column to offset for expresion compilation

Follow-up to https://dart-review.googlesource.com/c/sdk/+/446042.

Change-Id: Icfbaa763a6d6089a74f62088602c07c478520741
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/446420
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Jens Johansen
2025-08-24 23:50:07 -07:00
committed by Commit Queue
parent 33697720bf
commit abfa152cfc
3 changed files with 126 additions and 2 deletions
@@ -353,7 +353,14 @@ class ExpressionCompiler {
// TODO(jensj): Eventually make the scriptUri required.
if (scriptFileUri != null) {
final offset = _component.getOffset(scriptFileUri, line, column);
final offset = _component.getOffsetNoThrow(scriptFileUri, line, column);
if (offset < 0) {
_log(
'Got offset negative offset ($offset) for '
'$scriptFileUri:$line:$column',
);
return DartScope(library, null, null, null, null, {}, []);
}
final scope = DartScopeBuilder2.findScopeFromOffset(
library,
scriptFileUri,
@@ -388,11 +395,19 @@ class ExpressionCompiler {
final foundScopes = <DartScope>[];
for (final fileUri in fileUris) {
final offset = _component.getOffset(fileUri, line, column);
final offset = _component.getOffsetNoThrow(fileUri, line, column);
if (offset < 0) continue;
foundScopes.add(
DartScopeBuilder2.findScopeFromOffset(library, fileUri, offset),
);
}
if (foundScopes.isEmpty) {
_log(
'Got only negative offsets for library/parts ${library.fileUri} '
'at $line:$column.',
);
return DartScope(library, null, null, null, null, {}, []);
}
if (foundScopes.length == 1) {
return foundScopes[0];
}
@@ -217,6 +217,88 @@ void runExpressionCompilationTests(ExpressionCompilerWorkerTestDriver driver) {
);
});
test('does not crash on line 0 in a library', () {
driver.requestController.add({
'command': 'UpdateDeps',
'inputs': driver.inputs,
});
driver.requestController.add({
'command': 'CompileExpression',
'expression': '1 + 1',
'line': 0,
'column': 0,
'jsModules': {},
'jsScope': {},
'libraryUri': driver.config.getModule('testModule').libraryUris.first,
'moduleName': driver.config.getModule('testModule').moduleName,
});
expect(
driver.responseController.stream,
emitsInOrder([
equals({'succeeded': true}),
equals({
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
'infos': isEmpty,
'compiledProcedure': contains('1 + 1;'),
}),
]),
);
});
test('does not crash on line thats too high in a library', () {
driver.requestController.add({
'command': 'UpdateDeps',
'inputs': driver.inputs,
});
driver.requestController.add({
'command': 'CompileExpression',
'expression': '1 + 1',
'line': 10000000,
'column': 1,
'jsModules': {},
'jsScope': {},
'libraryUri': driver.config.getModule('testModule').libraryUris.first,
'moduleName': driver.config.getModule('testModule').moduleName,
});
driver.requestController.add({
'command': 'CompileExpression',
'expression': '2 + 2',
'line': 1,
'column': 10000000,
'jsModules': {},
'jsScope': {},
'libraryUri': driver.config.getModule('testModule').libraryUris.first,
'moduleName': driver.config.getModule('testModule').moduleName,
});
expect(
driver.responseController.stream,
emitsInOrder([
equals({'succeeded': true}),
equals({
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
'infos': isEmpty,
'compiledProcedure': contains('1 + 1;'),
}),
equals({
'succeeded': true,
'errors': isEmpty,
'warnings': isEmpty,
'infos': isEmpty,
'compiledProcedure': contains('2 + 2;'),
}),
]),
);
});
test('can compile expressions in a library', () {
driver.requestController.add({
'command': 'UpdateDeps',