diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index 1c58ea1b1a5..ca074dc82f7 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -220,7 +220,7 @@ "name": "dart2js_tools", "rootUri": "../pkg/dart2js_tools", "packageUri": "lib/", - "languageVersion": "2.3" + "languageVersion": "2.12" }, { "name": "dart2native", diff --git a/pkg/dart2js_tools/bin/deobfuscate.dart b/pkg/dart2js_tools/bin/deobfuscate.dart index d6ba8370903..009357f65d4 100644 --- a/pkg/dart2js_tools/bin/deobfuscate.dart +++ b/pkg/dart2js_tools/bin/deobfuscate.dart @@ -10,7 +10,7 @@ import 'package:dart2js_tools/src/name_decoder.dart'; import 'package:dart2js_tools/src/util.dart'; import 'package:dart2js_tools/src/trace_decoder.dart'; -/// Script that deobuscates a stack-trace given in a text file. +/// Script that deobfuscates a stack-trace given in a text file. /// /// To run this script you need 3 or more files: /// @@ -47,24 +47,24 @@ main(List args) { var sb = new StringBuffer(); try { String obfuscatedTrace = new File(args[0]).readAsStringSync(); - String error = extractErrorMessage(obfuscatedTrace); + String? error = extractErrorMessage(obfuscatedTrace); var provider = new CachingFileProvider(logger: Logger()); StackDeobfuscationResult result = deobfuscateStack(obfuscatedTrace, provider); Frame firstFrame = result.original.frames.first; - String translatedError = + String? translatedError = translate(error, provider.mappingFor(firstFrame.uri)); if (translatedError == null) translatedError = ''; printPadded(translatedError, error, sb); int longest = - result.deobfuscated.frames.fold(0, (m, f) => max(f.member.length, m)); + result.deobfuscated.frames.fold(0, (m, f) => max(f.member!.length, m)); for (var originalFrame in result.original.frames) { var deobfuscatedFrames = result.frameMap[originalFrame]; if (deobfuscatedFrames == null) { printPadded('no mapping', '${originalFrame.location}', sb); } else { for (var frame in deobfuscatedFrames) { - printPadded('${frame.member.padRight(longest)} ${frame.location}', + printPadded('${frame.member!.padRight(longest)} ${frame.location}', '${originalFrame.location}', sb); } } @@ -77,7 +77,7 @@ main(List args) { final green = stdout.hasTerminal ? '\x1b[32m' : ''; final none = stdout.hasTerminal ? '\x1b[0m' : ''; -printPadded(String mapping, String original, sb) { +printPadded(String mapping, String? original, sb) { var len = mapping.length; var s = mapping.indexOf('\n'); if (s >= 0) len -= s + 1; diff --git a/pkg/dart2js_tools/bin/lookup_name.dart b/pkg/dart2js_tools/bin/lookup_name.dart index f2d5c1b18b1..e14c5039ab9 100644 --- a/pkg/dart2js_tools/bin/lookup_name.dart +++ b/pkg/dart2js_tools/bin/lookup_name.dart @@ -1,7 +1,8 @@ import 'dart:io'; import 'dart:convert'; -import 'package:source_maps/source_maps.dart'; + import 'package:dart2js_tools/src/dart2js_mapping.dart'; +import 'package:dart2js_tools/src/util.dart'; main(List args) { if (args.length < 2) { @@ -16,7 +17,7 @@ main(List args) { exit(1); } var json = jsonDecode(sourcemapFile.readAsStringSync()); - Dart2jsMapping mapping = Dart2jsMapping(parseJson(json), json); + Dart2jsMapping mapping = Dart2jsMapping(parseSingleMapping(json), json); var global = mapping.globalNames[name]; if (global != null) print('$name => $global (a global name)'); var instance = mapping.instanceNames[name]; diff --git a/pkg/dart2js_tools/bin/show_inline_data.dart b/pkg/dart2js_tools/bin/show_inline_data.dart index cc3d5f09900..235e380292d 100644 --- a/pkg/dart2js_tools/bin/show_inline_data.dart +++ b/pkg/dart2js_tools/bin/show_inline_data.dart @@ -22,11 +22,11 @@ main(List args) { var mapping = provider.mappingFor(uri); var starts = functionStarts(provider.sourcesFor(uri)); var file = provider.fileFor(uri); - var frames = mapping.frames; + var frames = mapping!.frames; var offsets = frames.keys.toList()..sort(); var sb = new StringBuffer(); int depth = 0; - int lastFunctionStart = null; + int? lastFunctionStart = null; for (var offset in offsets) { int functionStart = nextFunctionStart(starts, offset, lastFunctionStart); if (lastFunctionStart == null || functionStart > lastFunctionStart) { @@ -43,7 +43,7 @@ main(List args) { var pad = ' ' * offsetPrefix.length; sb.write(offsetPrefix); bool first = true; - for (var frame in frames[offset]) { + for (var frame in frames[offset]!) { if (!first) sb.write('$pad'); sb.write(' $frame\n'); first = false; @@ -75,7 +75,7 @@ List functionStarts(String sources) { return result; } -int nextFunctionStart(List starts, int offset, int last) { +int nextFunctionStart(List starts, int offset, int? last) { int j = last ?? 0; for (; j < starts.length && starts[j] <= offset; j++); return j - 1; diff --git a/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart b/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart index 29a209e088a..4a43b6c19b7 100644 --- a/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart +++ b/pkg/dart2js_tools/lib/deobfuscate_stack_trace.dart @@ -5,7 +5,7 @@ import 'package:dart2js_tools/src/name_decoder.dart'; import 'package:dart2js_tools/src/util.dart'; import 'package:dart2js_tools/src/trace_decoder.dart'; -/// Deobuscates the given [obfuscatedTrace]. +/// Deobfuscates the given [obfuscatedTrace]. /// /// This method assumes a stack trace contains URIs normalized to be file URIs. /// If for example you obtain a stack from a browser, you may need to preprocess @@ -27,7 +27,7 @@ import 'package:dart2js_tools/src/trace_decoder.dart'; /// `//# sourceMappingURL=` line at the end, and load the corresponding /// source-map file. String deobfuscateStackTrace(String obfuscatedTrace) { - String error = extractErrorMessage(obfuscatedTrace); + String? error = extractErrorMessage(obfuscatedTrace); var provider = CachingFileProvider(); StackDeobfuscationResult result = deobfuscateStack(obfuscatedTrace, provider); Frame firstFrame = result.original.frames.first; @@ -38,14 +38,14 @@ String deobfuscateStackTrace(String obfuscatedTrace) { var sb = StringBuffer(); sb.writeln(translatedError); - maxMemberLengthHelper(int m, Frame f) => max(f.member.length, m); + maxMemberLengthHelper(int m, Frame f) => max(f.member!.length, m); int longest = result.deobfuscated.frames.fold(0, maxMemberLengthHelper); longest = result.original.frames.fold(longest, maxMemberLengthHelper); for (var originalFrame in result.original.frames) { var deobfuscatedFrames = result.frameMap[originalFrame]; if (deobfuscatedFrames == null) { var name = originalFrame.member; - sb.writeln(' at ${name.padRight(longest)} ${originalFrame.location}'); + sb.writeln(' at ${name!.padRight(longest)} ${originalFrame.location}'); } else { for (var frame in deobfuscatedFrames) { var name = frame.member; @@ -53,7 +53,7 @@ String deobfuscateStackTrace(String obfuscatedTrace) { // client, we can start encoding the function name and remove this // workaround. if (name == '') name = originalFrame.member; - sb.writeln(' at ${name.padRight(longest)} ${frame.location}'); + sb.writeln(' at ${name!.padRight(longest)} ${frame.location}'); } } } diff --git a/pkg/dart2js_tools/lib/src/dart2js_mapping.dart b/pkg/dart2js_tools/lib/src/dart2js_mapping.dart index ac6b9d718e2..6432aaae311 100644 --- a/pkg/dart2js_tools/lib/src/dart2js_mapping.dart +++ b/pkg/dart2js_tools/lib/src/dart2js_mapping.dart @@ -23,38 +23,32 @@ class Dart2jsMapping { final Map globalNames = {}; final Map instanceNames = {}; final Map> frames = {}; - List _frameIndex; - List get frameIndex { - if (_frameIndex == null) { - _frameIndex = frames.keys.toList()..sort(); - } - return _frameIndex; - } + late final List frameIndex = frames.keys.toList()..sort(); - Dart2jsMapping(this.sourceMap, Map json, {Logger logger}) { + Dart2jsMapping(this.sourceMap, Map json, {Logger? logger}) { var extensions = json['x_org_dartlang_dart2js']; if (extensions == null) return; var minifiedNames = extensions['minified_names']; if (minifiedNames != null) { - _extractMinifedNames( + _extractMinifiedNames( minifiedNames['global'], sourceMap, globalNames, logger); - _extractMinifedNames( + _extractMinifiedNames( minifiedNames['instance'], sourceMap, instanceNames, logger); } - String jsonFrames = extensions['frames']; + String? jsonFrames = extensions['frames']; if (jsonFrames != null) { new _FrameDecoder(jsonFrames).parseFrames(frames, sourceMap); } } - Dart2jsMapping.json(Map json) : this(parseJson(json), json); + Dart2jsMapping.json(Map json) : this(parseSingleMapping(json), json); } class FrameEntry { - final String callUri; - final int callLine; - final int callColumn; - final String inlinedMethodName; + final String? callUri; + final int? callLine; + final int? callColumn; + final String? inlinedMethodName; final bool isEmpty; FrameEntry.push( this.callUri, this.callLine, this.callColumn, this.inlinedMethodName) @@ -76,7 +70,7 @@ class FrameEntry { } const _marker = "\n//# sourceMappingURL="; -Dart2jsMapping parseMappingFor(Uri uri, {Logger logger}) { +Dart2jsMapping? parseMappingFor(Uri uri, {Logger? logger}) { var file = new File.fromUri(uri); if (!file.existsSync()) { logger?.log('Error: no such file: $uri'); @@ -100,7 +94,7 @@ Dart2jsMapping parseMappingFor(Uri uri, {Logger logger}) { return null; } var json = jsonDecode(sourcemapFile.readAsStringSync()); - return new Dart2jsMapping(parseJson(json), json, logger: logger); + return new Dart2jsMapping(parseSingleMapping(json), json, logger: logger); } class _FrameDecoder implements Iterator { @@ -112,8 +106,9 @@ class _FrameDecoder implements Iterator { // Iterator API is used by decodeVlq to consume VLQ entries. bool moveNext() => ++index < _length; - String get current => - (index >= 0 && index < _length) ? _internal[index] : null; + String get current => (index >= 0 && index < _length) + ? _internal[index] + : throw StateError('No current value available.'); bool get hasTokens => index < _length - 1 && _length > 0; @@ -150,8 +145,8 @@ class _FrameDecoder implements Iterator { } } -_extractMinifedNames(String encodedInput, SingleMapping sourceMap, - Map minifiedNames, Logger logger) { +_extractMinifiedNames(String encodedInput, SingleMapping sourceMap, + Map minifiedNames, Logger? logger) { if (encodedInput.isEmpty) return; List input = encodedInput.split(','); if (input.length % 2 != 0) { @@ -159,7 +154,7 @@ _extractMinifedNames(String encodedInput, SingleMapping sourceMap, } for (int i = 0; i < input.length; i += 2) { String minifiedName = input[i]; - int id = int.tryParse(input[i + 1]); + int id = int.parse(input[i + 1]); minifiedNames[minifiedName] = sourceMap.names[id]; } } diff --git a/pkg/dart2js_tools/lib/src/name_decoder.dart b/pkg/dart2js_tools/lib/src/name_decoder.dart index 306beadb3ed..862c7b417d2 100644 --- a/pkg/dart2js_tools/lib/src/name_decoder.dart +++ b/pkg/dart2js_tools/lib/src/name_decoder.dart @@ -9,8 +9,8 @@ import 'package:source_maps/source_maps.dart'; import 'dart2js_mapping.dart'; import 'trace.dart'; -String translate(String error, Dart2jsMapping mapping, - [StackTraceLine line, TargetEntry entry]) { +String? translate(String? error, Dart2jsMapping? mapping, + [StackTraceLine? line, TargetEntry? entry]) { for (var decoder in _errorMapDecoders) { var result = decoder.decode(error, mapping, line, entry); // More than one decoder might be applied on a single error message. This @@ -30,10 +30,10 @@ abstract class ErrorMapDecoder { /// Decode [error] that was reported in [line] and has a corresponding [entry] /// in the source-map file. The provided [mapping] includes additional /// minification data that may be used to decode the error message. - String decode(String error, Dart2jsMapping mapping, StackTraceLine line, - TargetEntry entry) { + String? decode(String? error, Dart2jsMapping? mapping, StackTraceLine? line, + TargetEntry? entry) { if (error == null) return null; - Match lastMatch = null; + Match? lastMatch = null; var result = new StringBuffer(); for (var match in _matcher.allMatches(error)) { var decodedMatch = _decodeInternal(match, mapping, line, entry); @@ -49,8 +49,8 @@ abstract class ErrorMapDecoder { return '$result'; } - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry); + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry); } typedef String ErrorDecoder(Match match, Dart2jsMapping mapping, @@ -59,45 +59,45 @@ typedef String ErrorDecoder(Match match, Dart2jsMapping mapping, class MinifiedNameDecoder extends ErrorMapDecoder { final RegExp _matcher = new RegExp("minified:([a-zA-Z0-9_\$]*)"); - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry) { + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry) { var minifiedName = match.group(1); - return mapping.globalNames[minifiedName]; + return mapping!.globalNames[minifiedName]; } } class CannotReadPropertyDecoder extends ErrorMapDecoder { final RegExp _matcher = new RegExp("Cannot read property '([^']*)' of"); - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry) { + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry) { var minifiedName = match.group(1); - var name = mapping.instanceNames[minifiedName]; + var name = mapping!.instanceNames[minifiedName]; if (name == null) return null; return "Cannot read property '$name' of"; } } abstract class NoSuchMethodDecoderBase extends ErrorMapDecoder { - String _translateMinifiedName(Dart2jsMapping mapping, String minifiedName) { + String? _translateMinifiedName(Dart2jsMapping mapping, String? minifiedName) { var name = mapping.instanceNames[minifiedName]; if (name != null) return "'$name'"; - if (minifiedName.startsWith(new RegExp(r'(call)?\$[0-9]'))) { + if (minifiedName!.startsWith(new RegExp(r'(call)?\$[0-9]'))) { int first$ = minifiedName.indexOf(r'$'); return _expandCallSignature(minifiedName.substring(first$)); } return null; } - String _expandCallSignature(String callSignature) { + String? _expandCallSignature(String callSignature) { // Minified names are one of these forms: // $0 // positional arguments only // $1$2 // type parameters and positional arguments // $3$name // positional and named arguments // $1$3$name // type parameters and positional and named args var signature = callSignature.split(r'$'); - var typeArgs = null; - var totalArgs = null; + int? typeArgs = null; + int? totalArgs = null; var namedArgs = []; for (var arg in signature) { if (arg == "") continue; @@ -115,6 +115,7 @@ abstract class NoSuchMethodDecoderBase extends ErrorMapDecoder { namedArgs.add(arg); } } + if (totalArgs == null) return null; var sb = new StringBuffer(); sb.write("'call'"); sb.write(" (with "); @@ -136,11 +137,11 @@ class NoSuchMethodDecoder1 extends NoSuchMethodDecoderBase { final RegExp _matcher = new RegExp( "NoSuchMethodError: method not found: '([^']*)'( on [^\\(]*)? \\(.*\\)"); - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry) { + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry) { var minifiedName = match.group(1); var suffix = match.group(2) ?? ''; - var name = _translateMinifiedName(mapping, minifiedName); + var name = _translateMinifiedName(mapping!, minifiedName); if (name == null) return null; return "NoSuchMethodError: method not found: $name$suffix"; } @@ -150,10 +151,10 @@ class NoSuchMethodDecoder2 extends NoSuchMethodDecoderBase { final RegExp _matcher = new RegExp("NoSuchMethodError: method not found: '([^']*)'"); - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry) { + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry) { var minifiedName = match.group(1); - var name = _translateMinifiedName(mapping, minifiedName); + var name = _translateMinifiedName(mapping!, minifiedName); if (name == null) return null; return "NoSuchMethodError: method not found: $name"; } @@ -162,10 +163,10 @@ class NoSuchMethodDecoder2 extends NoSuchMethodDecoderBase { class UnhandledNotAFunctionError extends ErrorMapDecoder { final RegExp _matcher = new RegExp("Error: ([^']*) is not a function"); - String _decodeInternal(Match match, Dart2jsMapping mapping, - StackTraceLine line, TargetEntry entry) { + String? _decodeInternal(Match match, Dart2jsMapping? mapping, + StackTraceLine? line, TargetEntry? entry) { var minifiedName = match.group(1); - var name = mapping.instanceNames[minifiedName]; + var name = mapping!.instanceNames[minifiedName]; if (name == null) return null; return "Error: $name is not a function"; } diff --git a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart index 68ffd941a02..cdbf85a92cb 100644 --- a/pkg/dart2js_tools/lib/src/sourcemap_helper.dart +++ b/pkg/dart2js_tools/lib/src/sourcemap_helper.dart @@ -10,11 +10,10 @@ import 'util.dart' show FileProvider; /// Search backwards in [sources] for a function declaration that includes the /// [start] offset. -TargetEntry findEnclosingFunction(FileProvider provider, Uri uri, int start) { +TargetEntry? findEnclosingFunction(FileProvider provider, Uri uri, int start) { String sources = provider.sourcesFor(uri); - if (sources == null) return null; SourceFile file = provider.fileFor(uri); - SingleMapping mapping = provider.mappingFor(uri).sourceMap; + SingleMapping mapping = provider.mappingFor(uri)!.sourceMap; var index = start; while (true) { index = nextDeclarationCandidate(sources, index); @@ -22,7 +21,7 @@ TargetEntry findEnclosingFunction(FileProvider provider, Uri uri, int start) { var line = file.getLine(index); var lineEntry = findLine(mapping, line); var column = file.getColumn(index); - TargetEntry result = findColumn(line, column, lineEntry); + TargetEntry? result = findColumn(line, column, lineEntry); // If the name entry doesn't start exactly at the column corresponding to // `index`, we must be in the middle of a string or code that uses the word // "function", but that doesn't have a corresponding mapping. In those @@ -61,7 +60,7 @@ int nextDeclarationCandidate(String sources, int start) { /// number is lower or equal to [line]. /// /// Copied from [SingleMapping._findLine]. -TargetLineEntry findLine(SingleMapping sourceMap, int line) { +TargetLineEntry? findLine(SingleMapping sourceMap, int line) { int index = binarySearch(sourceMap.lines, (e) => e.line > line); return (index <= 0) ? null : sourceMap.lines[index - 1]; } @@ -73,7 +72,7 @@ TargetLineEntry findLine(SingleMapping sourceMap, int line) { /// 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.length == 0) return null; if (lineEntry.line != line) return lineEntry.entries.last; var entries = lineEntry.entries; diff --git a/pkg/dart2js_tools/lib/src/trace.dart b/pkg/dart2js_tools/lib/src/trace.dart index 846af16de1a..07bdb1e3700 100644 --- a/pkg/dart2js_tools/lib/src/trace.dart +++ b/pkg/dart2js_tools/lib/src/trace.dart @@ -14,10 +14,10 @@ import 'util.dart'; /// Represents a stack trace line. class StackTraceLine { - String methodName; - String fileName; - int lineNo; - int columnNo; + final String? methodName; + final String fileName; + final int? lineNo; + final int columnNo; StackTraceLine(this.methodName, this.fileName, this.lineNo, this.columnNo); @@ -31,11 +31,11 @@ class StackTraceLine { /// at : /// at /// - factory StackTraceLine.fromText(String text, {Logger logger}) { + factory StackTraceLine.fromText(String text, {Logger? logger}) { text = text.trim(); assert(text.startsWith('at ')); text = text.substring('at '.length); - String methodName; + String? methodName; int endParen = text.indexOf(')'); if (endParen > 0) { int nameEnd = text.indexOf('('); @@ -46,16 +46,16 @@ class StackTraceLine { logger?.log('Missing left-paren in: $text'); } } - 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; @@ -84,14 +84,14 @@ class StackTraceLine { if (methodName != null) { sb.write(methodName); sb.write(' ('); - sb.write(fileName ?? '?'); + sb.write(fileName); sb.write(':'); sb.write(lineNo); sb.write(':'); sb.write(columnNo); sb.write(')'); } else { - sb.write(fileName ?? '?'); + sb.write(fileName); sb.write(':'); sb.write(lineNo); sb.write(':'); @@ -103,27 +103,27 @@ class StackTraceLine { String get inlineString { StringBuffer sb = new StringBuffer(); var padding = 20; - if (methodName != null) { - sb.write(methodName); - padding -= (methodName.length); + var lineMethodName = methodName; + if (lineMethodName != null) { + sb.write(lineMethodName); + padding -= (lineMethodName.length); if (padding <= 0) { sb.write('\n'); padding = 20; } } sb.write(' ' * padding); - if (fileName != null) { - sb.write(p.url.basename(fileName)); - sb.write(' '); - sb.write(lineNo); - sb.write(':'); - sb.write(columnNo); - } + sb.write(p.url.basename(fileName)); + sb.write(' '); + sb.write(lineNo); + sb.write(':'); + sb.write(columnNo); + return sb.toString(); } } -List parseStackTrace(String trace, {Logger logger}) { +List parseStackTrace(String trace, {Logger? logger}) { List lines = trace.split(new RegExp(r'(\r|\n|\r\n)')); List jsStackTrace = []; for (String line in lines) { @@ -138,7 +138,7 @@ List parseStackTrace(String trace, {Logger logger}) { /// Returns the portion of the output that corresponds to the error message. /// /// Note: some errors can span multiple lines. -String extractErrorMessage(String trace) { +String? extractErrorMessage(String trace) { var firstStackFrame = trace.indexOf(new RegExp('\n +at')); if (firstStackFrame == -1) return null; var errorMarker = trace.indexOf('^') + 1; diff --git a/pkg/dart2js_tools/lib/src/trace_decoder.dart b/pkg/dart2js_tools/lib/src/trace_decoder.dart index 7ac12aa4e4c..6331bad2a81 100644 --- a/pkg/dart2js_tools/lib/src/trace_decoder.dart +++ b/pkg/dart2js_tools/lib/src/trace_decoder.dart @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Logic to expand and deobuscate stack traces. +/// Logic to expand and deobfuscate stack traces. import 'package:stack_trace/stack_trace.dart'; import 'package:source_span/source_span.dart'; @@ -16,12 +16,12 @@ class StackDeobfuscationResult { /// Representation of the obfuscated stack trace. final Trace original; - /// Representation of the deobfsucated stack trace. + /// Representation of the deobfuscated stack trace. final Trace deobfuscated; /// Details about how one original frame maps to deobfuscated frames. A single /// frame might map to many frames (in the case of inlining), or to a null - /// value (when we were unabled to deobfuscate it). + /// value (when we were unable to deobfuscate it). final Map> frameMap; StackDeobfuscationResult(this.original, this.deobfuscated, this.frameMap); @@ -35,22 +35,23 @@ StackDeobfuscationResult deobfuscateStack( var deobfuscatedFrames = []; var frameMap = >{}; for (var frame in trace.frames) { + var frameLine = frame.line; // If there's no line information, there's no way to translate this frame. // We could return it as-is, but these lines are usually not useful anyways. - if (frame.line == null) { + if (frameLine == null) { continue; } // If there's no column, try using the first column of the line. var column = frame.column ?? 1; - Dart2jsMapping mapping = provider.mappingFor(frame.uri); + Dart2jsMapping? mapping = provider.mappingFor(frame.uri); if (mapping == null) continue; // Subtract 1 because stack traces use 1-indexed lines and columns and // source maps uses 0-indexed. - SourceSpan span = mapping.sourceMap - .spanFor(frame.line - 1, column - 1, uri: frame.uri?.toString()); + SourceSpan? span = mapping.sourceMap + .spanFor(frameLine - 1, column - 1, uri: frame.uri.toString()); // If we can't find a source span, ignore the frame. It's probably something // internal that the user doesn't care about. @@ -59,11 +60,11 @@ StackDeobfuscationResult deobfuscateStack( List mappedFrames = frameMap[frame] = []; SourceFile jsFile = provider.fileFor(frame.uri); - int offset = jsFile.getOffset(frame.line - 1, column - 1); + int offset = jsFile.getOffset(frameLine - 1, column - 1); String nameOf(id) => _normalizeName(id >= 0 ? mapping.sourceMap.names[id] : null); - Uri fileName = span.sourceUrl; + Uri? fileName = span.sourceUrl; int targetLine = span.start.line + 1; int targetColumn = span.start.column + 1; @@ -78,13 +79,13 @@ StackDeobfuscationResult deobfuscateStack( int depth = 0; outer: while (key >= 0) { - for (var frame in frames[index[key]].reversed) { + for (var frame in frames[index[key]]!.reversed) { if (frame.isEmpty) break outer; if (frame.isPush) { if (depth <= 0) { - mappedFrames.add(new Frame(fileName, targetLine, targetColumn, + mappedFrames.add(new Frame(fileName!, targetLine, targetColumn, _normalizeName(frame.inlinedMethodName) + "(inlined)")); - fileName = Uri.parse(frame.callUri); + fileName = Uri.parse(frame.callUri!); targetLine = (frame.callLine ?? 0) + 1; targetColumn = (frame.callColumn ?? 0) + 1; } else { @@ -100,7 +101,8 @@ StackDeobfuscationResult deobfuscateStack( var functionEntry = findEnclosingFunction(provider, frame.uri, offset); String methodName = nameOf(functionEntry?.sourceNameId ?? -1); - mappedFrames.add(new Frame(fileName, targetLine, targetColumn, methodName)); + mappedFrames + .add(new Frame(fileName!, targetLine, targetColumn, methodName)); deobfuscatedFrames.addAll(mappedFrames); } return new StackDeobfuscationResult( @@ -109,6 +111,6 @@ StackDeobfuscationResult deobfuscateStack( /// Ensure we don't use spaces in method names. At this time, they are only /// introduced by ``. -_normalizeName(String methodName) => +String _normalizeName(String? methodName) => methodName?.replaceAll("", "") ?? ''; diff --git a/pkg/dart2js_tools/lib/src/util.dart b/pkg/dart2js_tools/lib/src/util.dart index 433ac5aee46..1a733ac211a 100644 --- a/pkg/dart2js_tools/lib/src/util.dart +++ b/pkg/dart2js_tools/lib/src/util.dart @@ -1,18 +1,19 @@ import 'dart:io'; +import 'package:source_maps/parser.dart'; import 'package:source_span/source_span.dart'; import 'dart2js_mapping.dart'; abstract class FileProvider { String sourcesFor(Uri uri); SourceFile fileFor(Uri uri); - Dart2jsMapping mappingFor(Uri uri); + Dart2jsMapping? mappingFor(Uri uri); } class CachingFileProvider implements FileProvider { final Map _sources = {}; final Map _files = {}; - final Map _mappings = {}; - final Logger logger; + final Map _mappings = {}; + final Logger? logger; CachingFileProvider({this.logger}); @@ -22,7 +23,7 @@ class CachingFileProvider implements FileProvider { SourceFile fileFor(Uri uri) => _files[uri] ??= new SourceFile.fromString(sourcesFor(uri)); - Dart2jsMapping mappingFor(Uri uri) => + Dart2jsMapping? mappingFor(Uri uri) => _mappings[uri] ??= parseMappingFor(uri, logger: logger); } @@ -44,7 +45,7 @@ class DownloadedFileProvider extends CachingFileProvider { SourceFile fileFor(Uri uri) => super.fileFor(_localize(uri)); - Dart2jsMapping mappingFor(Uri uri) => super.mappingFor(_localize(uri)); + Dart2jsMapping? mappingFor(Uri uri) => super.mappingFor(_localize(uri)); } class Logger { @@ -57,3 +58,5 @@ class Logger { } var logger = Logger(); + +SingleMapping parseSingleMapping(Map json) => parseJson(json) as SingleMapping; diff --git a/pkg/dart2js_tools/pubspec.yaml b/pkg/dart2js_tools/pubspec.yaml index a6a46fe0656..392ed5670a3 100644 --- a/pkg/dart2js_tools/pubspec.yaml +++ b/pkg/dart2js_tools/pubspec.yaml @@ -10,4 +10,4 @@ dependencies: source_span: any stack_trace: ^1.9.3 environment: - sdk: '>=2.3.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0'