[web] Migrate sourcemap_testing to null safety
Change-Id: Id89be7e1327d7e9016fcd7d2864d124bc04d865a
Issue: https://github.com/dart-lang/sdk/issues/46617
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243701
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
index 195b25c..43c9fa9 100644
--- a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
+++ b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
@@ -8,6 +8,7 @@
import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
import 'package:dart2js_tools/src/dart2js_mapping.dart';
+import 'package:dart2js_tools/src/util.dart';
import 'package:expect/expect.dart';
import 'package:source_maps/source_maps.dart';
import 'package:source_maps/src/utils.dart';
@@ -58,10 +59,10 @@
}
}
- List<StackTraceLine> expectedLines = <StackTraceLine>[];
+ List<StackTraceLine> expectedLines = [];
for (int stackTraceIndex
in (stackTraceMap.keys.toList()..sort()).reversed) {
- expectedLines.add(stackTraceMap[stackTraceIndex]);
+ expectedLines.add(stackTraceMap[stackTraceIndex]!);
}
expectationMap[config] = Expectations(expectedLines, unexpectedLines);
});
@@ -75,7 +76,7 @@
typedef CompileFunc = Future<bool> Function(String, String);
List<String> emptyPreamble(input, output) => const <String>[];
-String identityConverter(String name) => name;
+String? identityConverter(String? name) => name;
/// Tests the stack trace of [test] using the expectations for [config].
///
@@ -105,8 +106,8 @@
List<LineException> beforeExceptions = const <LineException>[],
List<LineException> afterExceptions = const <LineException>[],
bool useJsMethodNamesOnAbsence = false,
- String Function(String name) jsNameConverter = identityConverter,
- Directory forcedTmpDir,
+ String? Function(String? name) jsNameConverter = identityConverter,
+ Directory? forcedTmpDir,
int stackTraceLimit = 10,
expandDart2jsInliningData = false}) async {
Expect.isTrue(test.expectationMap.keys.contains(config),
@@ -124,7 +125,7 @@
Expect.isTrue(
sourceMapFile.existsSync(), 'Source map not generated for $input');
String sourceMapText = sourceMapFile.readAsStringSync();
- SingleMapping sourceMap = parse(sourceMapText);
+ SingleMapping sourceMap = parseSingleMapping(jsonDecode(sourceMapText));
String jsOutput = File(output).readAsStringSync();
if (printJs) {
@@ -160,21 +161,18 @@
List<StackTraceLine> dartStackTrace = <StackTraceLine>[];
for (StackTraceLine line in jsStackTrace) {
- TargetEntry targetEntry = _findColumn(
- line.lineNo - 1, line.columnNo - 1, _findLine(sourceMap, line));
+ TargetEntry? targetEntry = _findColumn(
+ line.lineNo! - 1, line.columnNo! - 1, _findLine(sourceMap, line));
if (targetEntry == null || targetEntry.sourceUrlId == null) {
dartStackTrace.add(line);
} else {
- String fileName;
- if (targetEntry.sourceUrlId != null) {
- fileName = sourceMap.urls[targetEntry.sourceUrlId];
- }
- int targetLine = targetEntry.sourceLine + 1;
- int targetColumn = targetEntry.sourceColumn + 1;
+ String fileName = sourceMap.urls[targetEntry.sourceUrlId!];
+ int targetLine = targetEntry.sourceLine! + 1;
+ int targetColumn = targetEntry.sourceColumn! + 1;
if (expandDart2jsInliningData) {
SourceFile file = SourceFile.fromString(jsOutput);
- int offset = file.getOffset(line.lineNo - 1, line.columnNo - 1);
+ int offset = file.getOffset(line.lineNo! - 1, line.columnNo! - 1);
Map<int, List<FrameEntry>> frames =
_loadInlinedFrameData(sourceMap, sourceMapText);
List<int> indices = frames.keys.toList()..sort();
@@ -182,7 +180,7 @@
int depth = 0;
outer:
while (key >= 0) {
- for (var frame in frames[indices[key]].reversed) {
+ for (var frame in frames[indices[key]]!.reversed) {
if (frame.isEmpty) break outer;
if (frame.isPush) {
if (depth <= 0) {
@@ -192,9 +190,9 @@
targetLine,
targetColumn,
isMapped: true));
- fileName = frame.callUri;
- targetLine = frame.callLine + 1;
- targetColumn = frame.callColumn + 1;
+ fileName = frame.callUri!;
+ targetLine = frame.callLine! + 1;
+ targetColumn = frame.callColumn! + 1;
} else {
depth--;
}
@@ -208,9 +206,9 @@
targetEntry = findEnclosingFunction(jsOutput, file, offset, sourceMap);
}
- String methodName;
- if (targetEntry.sourceNameId != null) {
- methodName = sourceMap.names[targetEntry.sourceNameId];
+ String? methodName;
+ if (targetEntry!.sourceNameId != null) {
+ methodName = sourceMap.names[targetEntry.sourceNameId!];
} else if (useJsMethodNamesOnAbsence) {
methodName = jsNameConverter(line.methodName);
}
@@ -221,7 +219,7 @@
}
}
- Expectations expectations = test.expectationMap[config];
+ Expectations expectations = test.expectationMap[config]!;
int expectedIndex = 0;
List<StackTraceLine> unexpectedLines = <StackTraceLine>[];
@@ -251,7 +249,7 @@
for (LineException exception in exceptions) {
String fileName = exception.fileName;
if (line.methodName == exception.methodName &&
- line.fileName.endsWith(fileName)) {
+ line.fileName!.endsWith(fileName)) {
found = true;
}
}
@@ -295,10 +293,10 @@
}
class StackTraceLine {
- String methodName;
- String fileName;
- int lineNo;
- int columnNo;
+ String? methodName;
+ String? fileName;
+ int? lineNo;
+ int? columnNo;
bool isMapped;
StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo,
@@ -318,22 +316,22 @@
text = text.trim();
assert(text.startsWith('at '));
text = text.substring('at '.length);
- String methodName;
+ String? methodName;
if (text.endsWith(')')) {
int nameEnd = text.indexOf(' (');
methodName = text.substring(0, nameEnd);
text = text.substring(nameEnd + 2, text.length - 1);
}
- int lineNo;
- int columnNo;
+ int? lineNo;
+ int? columnNo;
String fileName;
int lastColon = text.lastIndexOf(':');
if (lastColon != -1) {
- int lastValue = int.tryParse(text.substring(lastColon + 1));
+ int? lastValue = int.tryParse(text.substring(lastColon + 1));
if (lastValue != null) {
int secondToLastColon = text.lastIndexOf(':', lastColon - 1);
if (secondToLastColon != -1) {
- int secondToLastValue =
+ int? secondToLastValue =
int.tryParse(text.substring(secondToLastColon + 1, lastColon));
if (secondToLastValue != null) {
lineNo = secondToLastValue;
@@ -385,14 +383,14 @@
/// number is lower or equal to [line].
///
/// Copied from [SingleMapping._findLine].
-TargetLineEntry _findLine(SingleMapping sourceMap, StackTraceLine stLine) {
- String filename = stLine.fileName
- .substring(stLine.fileName.lastIndexOf(RegExp('[\\/]')) + 1);
+TargetLineEntry? _findLine(SingleMapping sourceMap, StackTraceLine stLine) {
+ String filename = stLine.fileName!
+ .substring(stLine.fileName!.lastIndexOf(RegExp('[\\/]')) + 1);
if (sourceMap.targetUrl != filename) return null;
- return _findLineInternal(sourceMap, stLine.lineNo - 1);
+ return _findLineInternal(sourceMap, stLine.lineNo! - 1);
}
-TargetLineEntry _findLineInternal(SingleMapping sourceMap, int line) {
+TargetLineEntry? _findLineInternal(SingleMapping sourceMap, int line) {
int index = binarySearch(sourceMap.lines, (e) => e.line > line);
return (index <= 0) ? null : sourceMap.lines[index - 1];
}
@@ -404,7 +402,7 @@
/// the very last entry on that line.
///
/// Copied from [SingleMapping._findColumn].
-TargetEntry _findColumn(int line, int column, TargetLineEntry lineEntry) {
+TargetEntry? _findColumn(int line, int column, TargetLineEntry? lineEntry) {
if (lineEntry == null || lineEntry.entries.isEmpty) return null;
if (lineEntry.line != line) return lineEntry.entries.last;
var entries = lineEntry.entries;
@@ -434,9 +432,8 @@
/// Search backwards in [sources] for a function declaration that includes the
/// [start] offset.
-TargetEntry findEnclosingFunction(
+TargetEntry? findEnclosingFunction(
String sources, SourceFile file, int start, SingleMapping mapping) {
- if (sources == null) return null;
var index = start;
while (true) {
index = nextDeclarationCandidate(sources, index);
diff --git a/pkg/sourcemap_testing/lib/src/stepping_helper.dart b/pkg/sourcemap_testing/lib/src/stepping_helper.dart
index 9833d8a..9392f77 100644
--- a/pkg/sourcemap_testing/lib/src/stepping_helper.dart
+++ b/pkg/sourcemap_testing/lib/src/stepping_helper.dart
@@ -1,6 +1,9 @@
+import 'dart:convert' show jsonDecode;
import 'dart:io';
import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
+import 'package:collection/collection.dart' show IterableNullableExtension;
+import 'package:dart2js_tools/src/util.dart';
import 'package:expect/minitest.dart';
import 'package:path/path.dart' as path;
import 'package:source_maps/source_maps.dart';
@@ -14,11 +17,12 @@
ProcessResult runD8AndStep(String outputPath, String testFileName,
AnnotatedCode code, List<String> scriptD8Command) {
var outputFile = path.join(outputPath, 'js.js');
- SingleMapping sourceMap = parse(File('$outputFile.map').readAsStringSync());
+ var sourcemapText = File('$outputFile.map').readAsStringSync();
+ SingleMapping sourceMap = parseSingleMapping(jsonDecode(sourcemapText));
- Set<int> mappedToLines = sourceMap.lines
+ Set<int?> mappedToLines = sourceMap.lines
.map((entry) => entry.entries.map((entry) => entry.sourceLine).toSet())
- .fold(<int>{}, (prev, e) => prev..addAll(e));
+ .fold(<int?>{}, (prev, e) => prev..addAll(e));
for (Annotation annotation
in code.annotations.where((a) => a.text.trim() == 'nm')) {
@@ -30,7 +34,7 @@
}
}
- List<String> breakpoints = [];
+ List<String?> breakpoints = [];
// Annotations are 1-based, js breakpoints are 0-based.
for (Annotation breakAt
in code.annotations.where((a) => a.text.trim() == 'bl')) {
@@ -44,7 +48,7 @@
}
File inspectorFile = File.fromUri(
- sdkRoot.uri.resolve('pkg/sourcemap_testing/lib/src/js/inspector.js'));
+ sdkRoot!.uri.resolve('pkg/sourcemap_testing/lib/src/js/inspector.js'));
if (!inspectorFile.existsSync()) throw "Couldn't find 'inspector.js'";
var outInspectorPath = path.join(outputPath, 'inspector.js');
inspectorFile.copySync(outInspectorPath);
@@ -65,7 +69,8 @@
{bool debug = false}) {
var outputFilename = 'js.js';
var outputFile = path.join(outputPath, outputFilename);
- SingleMapping sourceMap = parse(File('$outputFile.map').readAsStringSync());
+ var sourcemapText = File('$outputFile.map').readAsStringSync();
+ SingleMapping sourceMap = parseSingleMapping(jsonDecode(sourcemapText));
List<List<_DartStackTraceDataEntry>> result =
_extractStackTraces(d8Output, sourceMap, outputFilename);
@@ -100,8 +105,8 @@
}
}
- List<List<String>> noBreaksStart = [];
- List<List<String>> noBreaksEnd = [];
+ List<List<String>?> noBreaksStart = [];
+ List<List<String>?> noBreaksEnd = [];
for (Annotation annotation in code.annotations
.where((annotation) => annotation.text.trim().startsWith('nbb:'))) {
String text = annotation.text.trim();
@@ -109,12 +114,9 @@
int stopNum1 = int.parse(split[1]);
int stopNum2 = int.parse(split[2]);
if (noBreaksStart.length <= stopNum1) noBreaksStart.length = stopNum1 + 1;
- noBreaksStart[stopNum1] ??= [];
+ (noBreaksStart[stopNum1] ??= []).add('test.dart:${annotation.lineNo}:');
if (noBreaksEnd.length <= stopNum2) noBreaksEnd.length = stopNum2 + 1;
- noBreaksEnd[stopNum2] ??= [];
-
- noBreaksStart[stopNum1].add('test.dart:${annotation.lineNo}:');
- noBreaksEnd[stopNum2].add('test.dart:${annotation.lineNo}:');
+ (noBreaksEnd[stopNum2] ??= []).add('test.dart:${annotation.lineNo}:');
}
_checkRecordedStops(
@@ -147,8 +149,8 @@
void _checkRecordedStops(
List<String> recordStops,
List<String> expectedStops,
- List<List<String>> noBreaksStart,
- List<List<String>> noBreaksEnd,
+ List<List<String>?> noBreaksStart,
+ List<List<String>?> noBreaksEnd,
bool debug) {
// We want to find all expected lines in recorded lines in order, but allow
// more in between in the recorded lines.
@@ -158,7 +160,7 @@
int expectedIndex = 0;
Set<String> aliveNoBreaks = {};
if (noBreaksStart.isNotEmpty && noBreaksStart[0] != null) {
- aliveNoBreaks.addAll(noBreaksStart[0]);
+ aliveNoBreaks.addAll(noBreaksStart[0]!);
}
int stopNumber = 0;
for (String recorded in recordStops) {
@@ -168,11 +170,11 @@
++expectedIndex;
if (noBreaksStart.length > expectedIndex &&
noBreaksStart[expectedIndex] != null) {
- aliveNoBreaks.addAll(noBreaksStart[expectedIndex]);
+ aliveNoBreaks.addAll(noBreaksStart[expectedIndex]!);
}
if (noBreaksEnd.length > expectedIndex &&
noBreaksEnd[expectedIndex] != null) {
- aliveNoBreaks.removeAll(noBreaksEnd[expectedIndex]);
+ aliveNoBreaks.removeAll(noBreaksEnd[expectedIndex]!);
}
} else {
if (debug) {
@@ -241,7 +243,7 @@
}
List<String> sideBySide(List<String> a, List<String> b, int columns) {
- List<String> result = List<String>.filled(a.length, null);
+ List<String> result = List<String>.filled(a.length, '');
for (int i = 0; i < a.length; ++i) {
String left = a[i].padRight(columns).substring(0, columns);
String right = b[i].padRight(columns).substring(0, columns);
@@ -267,7 +269,7 @@
}
List<List<_DartStackTraceDataEntry>> _extractStackTraces(
- lines, SingleMapping sourceMap, String outputFilename) {
+ List<String> lines, SingleMapping sourceMap, String outputFilename) {
List<List<_DartStackTraceDataEntry>> result = [];
bool inStackTrace = false;
List<String> currentStackTrace = <String>[];
@@ -301,24 +303,24 @@
continue;
}
Match m = ms.first;
- int l = int.parse(m.group(1));
- int c = int.parse(m.group(2));
- SourceMapSpan span = _getColumnOrPredecessor(sourceMap, l, c);
+ int l = int.parse(m.group(1)!);
+ int c = int.parse(m.group(2)!);
+ SourceMapSpan? span = _getColumnOrPredecessor(sourceMap, l, c);
if (span?.start == null) {
result.add(_DartStackTraceDataEntry.errorWithJsPosition(
"Source map not found for '$line'", l, c));
continue;
}
- var file = span.sourceUrl?.pathSegments?.last ?? '(unknown file)';
+ var file = span!.sourceUrl?.pathSegments.last ?? '(unknown file)';
result.add(_DartStackTraceDataEntry(
file, span.start.line + 1, span.start.column + 1, l, c));
}
return result;
}
-SourceMapSpan _getColumnOrPredecessor(
+SourceMapSpan? _getColumnOrPredecessor(
SingleMapping sourceMap, int line, int column) {
- SourceMapSpan span = sourceMap.spanFor(line, column);
+ SourceMapSpan? span = sourceMap.spanFor(line, column);
if (span == null && line > 0) {
span = sourceMap.spanFor(line - 1, 999999);
}
@@ -326,10 +328,10 @@
}
class _DartStackTraceDataEntry {
- final String file;
+ final String? file;
final int line;
final int column;
- final String errorString;
+ final String? errorString;
final int jsLine;
final int jsColumn;
@@ -351,7 +353,7 @@
bool get isError => errorString != null;
@override
- String toString() => isError ? errorString : '$file:$line:$column';
+ String toString() => isError ? errorString! : '$file:$line:$column';
}
class _PointMapping {
@@ -367,18 +369,21 @@
///
/// The "magic 4" below is taken from
/// https://github.com/ChromeDevTools/devtools-frontend/blob/fa18d70a995f06cb73365b2e5b8ae974cf60bd3a/front_end/sources/JavaScriptSourceFrame.js#L1520-L1523
-String _getJsBreakpointLine(
+String? _getJsBreakpointLine(
String testFileName, SingleMapping sourceMap, int breakOnLine) {
List<_PointMapping> mappingsOnLines = [];
for (var line in sourceMap.lines) {
for (var entry in line.entries) {
- if (entry.sourceLine == null) continue;
- if (entry.sourceLine >= breakOnLine &&
- entry.sourceLine < breakOnLine + 4 &&
- entry.sourceUrlId != null &&
- sourceMap.urls[entry.sourceUrlId] == testFileName) {
- mappingsOnLines.add(_PointMapping(
- entry.sourceLine, entry.sourceColumn, line.line, entry.column));
+ final sourceLine = entry.sourceLine;
+ if (sourceLine == null) continue;
+ final sourceColumn = entry.sourceColumn!;
+ final sourceUrlId = entry.sourceUrlId;
+ if (sourceLine >= breakOnLine &&
+ sourceLine < breakOnLine + 4 &&
+ sourceUrlId != null &&
+ sourceMap.urls[sourceUrlId] == testFileName) {
+ mappingsOnLines.add(
+ _PointMapping(sourceLine, sourceColumn, line.line, entry.column));
}
}
}
@@ -399,14 +404,14 @@
}
/// Input and output is expected to be 0-based.
-String _getJsBreakpointLineAndColumn(String testFileName,
+String? _getJsBreakpointLineAndColumn(String testFileName,
SingleMapping sourceMap, int breakOnLine, int breakOnColumn) {
for (var line in sourceMap.lines) {
for (var entry in line.entries) {
if (entry.sourceLine == breakOnLine &&
entry.sourceColumn == breakOnColumn &&
entry.sourceUrlId != null &&
- sourceMap.urls[entry.sourceUrlId] == testFileName) {
+ sourceMap.urls[entry.sourceUrlId!] == testFileName) {
return '${line.line}:${entry.column}';
}
}
@@ -415,7 +420,7 @@
}
ProcessResult _runD8(String outInspectorPath, List<String> scriptD8Command,
- String debugAction, List<String> breakpoints) {
+ String debugAction, List<String?> breakpoints) {
var outInspectorPathRelative = path.relative(outInspectorPath);
ProcessResult runResult = Process.runSync(d8Executable, [
'--enable-inspector',
@@ -423,7 +428,7 @@
...scriptD8Command,
'--',
debugAction,
- ...breakpoints.where((s) => s != null)
+ ...breakpoints.whereNotNull()
]);
if (runResult.exitCode != 0) {
print(runResult.stderr);
@@ -433,8 +438,8 @@
return runResult;
}
-File _cachedD8File;
-Directory _cachedSdkRoot;
+File? _cachedD8File;
+Directory? _cachedSdkRoot;
File getD8File() {
File attemptFileFromDir(Directory dir) {
if (Platform.isWindows) {
@@ -472,7 +477,7 @@
return _cachedD8File ??= search();
}
-Directory get sdkRoot {
+Directory? get sdkRoot {
getD8File();
return _cachedSdkRoot;
}
diff --git a/pkg/sourcemap_testing/pubspec.yaml b/pkg/sourcemap_testing/pubspec.yaml
index 88a7600..fdeb960 100644
--- a/pkg/sourcemap_testing/pubspec.yaml
+++ b/pkg/sourcemap_testing/pubspec.yaml
@@ -4,10 +4,11 @@
publish_to: none
environment:
- sdk: '>=2.11.0 <3.0.0'
+ sdk: '>=2.16.0 <3.0.0'
dependencies:
_fe_analyzer_shared: any
+ collection: any
dart2js_tools: any
expect: any
path: any