Skip to content

Commit 7621ed4

Browse files
committed
Convert JavaScript uncaught exception stack traces to Dart stacks
See #1265 See flutter/flutter#101888
1 parent 47dd82c commit 7621ed4

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

dwds/lib/src/debugging/inspector.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ class AppInspector extends Domain {
222222
///
223223
/// [evalExpression] should be a JS function definition that can accept
224224
/// [arguments].
225-
Future<RemoteObject> _jsCallFunction(
226-
String evalExpression, List<RemoteObject> arguments,
225+
Future<RemoteObject> jsCallFunction(
226+
String evalExpression, List<Object> arguments,
227227
{bool returnByValue = false}) async {
228228
var jsArguments = arguments.map(callArgumentFor).toList();
229229
var result =
@@ -346,7 +346,7 @@ function($argsString) {
346346
Future<RemoteObject> callFunction(
347347
String function, Iterable<String> argumentIds) async {
348348
var arguments = argumentIds.map(remoteObjectFor).toList();
349-
return _jsCallFunction(function, arguments);
349+
return jsCallFunction(function, arguments);
350350
}
351351

352352
Future<Library> getLibrary(String isolateId, String objectId) async {

dwds/lib/src/services/chrome_proxy_service.dart

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ typedef StreamNotify = void Function(String streamId, Event event);
3939
/// This may be null during a hot restart or page refresh.
4040
typedef AppInspectorProvider = AppInspector Function();
4141

42+
/// JavaScript expression that evaluates to the Dart stack trace mapper.
43+
const stackTraceMapperExpression = '\$dartStackTraceUtility.mapper';
44+
45+
/// Regex used to extract the message from an exception description.
46+
final exceptionMessageRegex = RegExp(r'^.*$', multiLine: true);
47+
4248
/// A proxy from the chrome debug protocol to the dart vm service protocol.
4349
class ChromeProxyService implements VmServiceInterface {
4450
/// Cache of all existing StreamControllers.
@@ -834,15 +840,30 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension(
834840
..timestamp = e.timestamp.toInt());
835841
});
836842
if (includeExceptions) {
837-
exceptionsSubscription = remoteDebugger.onExceptionThrown.listen((e) {
843+
exceptionsSubscription =
844+
remoteDebugger.onExceptionThrown.listen((e) async {
838845
var isolate = _inspector?.isolate;
839846
if (isolate == null) return;
847+
var description = e.exceptionDetails.exception.description;
848+
if (description != null) {
849+
// Map the exception stack trace to a Dart stack.
850+
RemoteObject mapperResult;
851+
try {
852+
mapperResult = await _inspector.jsCallFunction(
853+
stackTraceMapperExpression, <Object>[description]);
854+
} catch (_) {}
855+
var mappedStack = mapperResult?.value?.toString();
856+
if (mappedStack != null && mappedStack.isNotEmpty) {
857+
var message =
858+
exceptionMessageRegex.firstMatch(description)?.group(0) ?? '';
859+
description = '${e.exceptionDetails.text} $message\n$mappedStack';
860+
}
861+
}
840862
controller.add(Event(
841863
kind: EventKind.kWriteEvent,
842864
timestamp: DateTime.now().millisecondsSinceEpoch,
843865
isolate: _inspector.isolateRef)
844-
..bytes = base64.encode(
845-
utf8.encode(e.exceptionDetails.exception.description ?? '')));
866+
..bytes = base64.encode(utf8.encode(description ?? '')));
846867
});
847868
}
848869
});

0 commit comments

Comments
 (0)