33e174084a
Use `hasScheme` in place of comparing against the empty string, and `isScheme` to compare against all other schemes. TEST=No behavior changes. Change-Id: Ifc9fd13c6cf37933ebd4a754c4b500dedbcb291b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231185 Reviewed-by: Kevin Moore <kevmoo@google.com> Commit-Queue: Nate Bosch <nbosch@google.com>
62 lines
2.6 KiB
Dart
62 lines
2.6 KiB
Dart
import 'dart:math' show max;
|
|
import 'package:stack_trace/stack_trace.dart';
|
|
import 'package:dart2js_tools/src/trace.dart';
|
|
import 'package:dart2js_tools/src/name_decoder.dart';
|
|
import 'package:dart2js_tools/src/util.dart';
|
|
import 'package:dart2js_tools/src/trace_decoder.dart';
|
|
|
|
/// 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
|
|
/// the stack to map the URI of the JavaScript files to URIs in the local file
|
|
/// system.
|
|
///
|
|
/// For example, a valid input to this method would be:
|
|
///
|
|
/// Error: no such method
|
|
/// at aB.a20 (/usr/local/foo/main.dart.js:71969:32)
|
|
/// at aNk.goV (/usr/local/foo/main.dart.js:72040:52)
|
|
/// at aNk.gfK (/usr/local/foo/main.dart.js:72038:27)
|
|
/// at FE.gtn (/usr/local/foo/main.dart.js:72640:24)
|
|
/// at aBZ.ghN (/usr/local/foo/main.dart.js:72642:24)
|
|
/// at inheritance (/usr/local/foo/main.dart.js:105334:0)
|
|
/// at FE (/usr/local/foo/main.dart.js:5037:18)
|
|
///
|
|
/// Internally this method will read those JavaScript files, search for the
|
|
/// `//# sourceMappingURL=` line at the end, and load the corresponding
|
|
/// source-map file.
|
|
String deobfuscateStackTrace(String obfuscatedTrace) {
|
|
String? error = extractErrorMessage(obfuscatedTrace);
|
|
var provider = CachingFileProvider();
|
|
StackDeobfuscationResult result = deobfuscateStack(obfuscatedTrace, provider);
|
|
Frame firstFrame = result.original.frames.first;
|
|
String translatedError = (firstFrame.uri.isScheme('error')
|
|
? null
|
|
: translate(error, provider.mappingFor(firstFrame.uri))) ??
|
|
'<no error message found>';
|
|
|
|
var sb = StringBuffer();
|
|
sb.writeln(translatedError);
|
|
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}');
|
|
} else {
|
|
for (var frame in deobfuscatedFrames) {
|
|
var name = frame.member;
|
|
// TODO(sigmund): eventually when ddc stops shipping source-maps to the
|
|
// client, we can start encoding the function name and remove this
|
|
// workaround.
|
|
if (name == '<unknown>') name = originalFrame.member;
|
|
sb.writeln(' at ${name!.padRight(longest)} ${frame.location}');
|
|
}
|
|
}
|
|
}
|
|
return '$sb';
|
|
}
|