Convert JavaScript uncaught exception stack traces to Dart stacks (#1603)

* Convert JavaScript uncaught exception stack traces to Dart stacks

Fixes https://github.com/dart-lang/webdev/issues/1265
Fixes https://github.com/flutter/flutter/issues/101888

* Built
diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md
index 3fe3115..f5a9ad6 100644
--- a/dwds/CHANGELOG.md
+++ b/dwds/CHANGELOG.md
@@ -1,6 +1,7 @@
 ## 14.0.3-dev
 - Make data types null safe
 - Update `package:vm_service` to 8.3.0.
+- Convert JavaScript stack traces in uncaught exceptions to Dart stack traces.
 
 ## 14.0.2
 - Update the min SDK constraint to 2.17.0.
diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart
index b761879..dd9e024 100644
--- a/dwds/lib/src/debugging/debugger.dart
+++ b/dwds/lib/src/debugging/debugger.dart
@@ -558,8 +558,10 @@
           if (isNativeJsObject(exception)) {
             if (obj.description != null) {
               // Create a string exception object.
-              exception = await inspector.instanceHelper
-                  .instanceRefFor(obj.description);
+              var description =
+                  await inspector.mapExceptionStackTrace(obj.description);
+              exception =
+                  await inspector.instanceHelper.instanceRefFor(description);
             } else {
               exception = null;
             }
diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart
index 44e2b89..24d1972 100644
--- a/dwds/lib/src/debugging/inspector.dart
+++ b/dwds/lib/src/debugging/inspector.dart
@@ -67,6 +67,12 @@
   final String _root;
   final SdkConfiguration _sdkConfiguration;
 
+  /// JavaScript expression that evaluates to the Dart stack trace mapper.
+  static const stackTraceMapperExpression = '\$dartStackTraceUtility.mapper';
+
+  /// Regex used to extract the message from an exception description.
+  static final exceptionMessageRegex = RegExp(r'^.*$', multiLine: true);
+
   AppInspector._(
     this.appConnection,
     this.isolate,
@@ -223,7 +229,7 @@
   /// [evalExpression] should be a JS function definition that can accept
   /// [arguments].
   Future<RemoteObject> _jsCallFunction(
-      String evalExpression, List<RemoteObject> arguments,
+      String evalExpression, List<Object> arguments,
       {bool returnByValue = false}) async {
     var jsArguments = arguments.map(callArgumentFor).toList();
     var result =
@@ -550,4 +556,23 @@
     handleErrorIfPresent(extensionsResult, evalContents: expression);
     return List.from(extensionsResult.result['result']['value'] as List);
   }
+
+  /// Convert a JS exception description into a description containing
+  /// a Dart stack trace.
+  Future<String> mapExceptionStackTrace(String description) async {
+    RemoteObject mapperResult;
+    try {
+      mapperResult = await _jsCallFunction(
+          stackTraceMapperExpression, <Object>[description]);
+    } catch (_) {
+      return description;
+    }
+    var mappedStack = mapperResult?.value?.toString();
+    if (mappedStack == null || mappedStack.isEmpty) {
+      return description;
+    }
+    var message = exceptionMessageRegex.firstMatch(description)?.group(0);
+    message = (message != null) ? '$message\n' : '';
+    return '$message$mappedStack';
+  }
 }
diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js
index 483470f..c7c3faa 100644
--- a/dwds/lib/src/injected/client.js
+++ b/dwds/lib/src/injected/client.js
@@ -1,4 +1,4 @@
-// Generated by dart2js (NullSafetyMode.unsound, csp), the Dart to JavaScript compiler version: 2.18.0-106.0.dev.
+// Generated by dart2js (NullSafetyMode.unsound, csp), the Dart to JavaScript compiler version: 2.18.0-109.0.dev.
 // The code supports the following hooks:
 // dartPrint(message):
 //    if this function is defined it is called instead of the Dart [print]
@@ -4244,30 +4244,6 @@
       this.$function = t1;
       this.$ti = t2;
     },
-    _RunNullaryZoneFunction: function _RunNullaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
-    _RunUnaryZoneFunction: function _RunUnaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
-    _RunBinaryZoneFunction: function _RunBinaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
-    _RegisterNullaryZoneFunction: function _RegisterNullaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
-    _RegisterUnaryZoneFunction: function _RegisterUnaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
-    _RegisterBinaryZoneFunction: function _RegisterBinaryZoneFunction(t0, t1) {
-      this.zone = t0;
-      this.$function = t1;
-    },
     _ZoneSpecification: function _ZoneSpecification(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) {
       var _ = this;
       _.handleUncaughtError = t0;
@@ -12856,12 +12832,6 @@
     }
   };
   A._ZoneFunction.prototype = {};
-  A._RunNullaryZoneFunction.prototype = {};
-  A._RunUnaryZoneFunction.prototype = {};
-  A._RunBinaryZoneFunction.prototype = {};
-  A._RegisterNullaryZoneFunction.prototype = {};
-  A._RegisterUnaryZoneFunction.prototype = {};
-  A._RegisterBinaryZoneFunction.prototype = {};
   A._ZoneSpecification.prototype = {$isZoneSpecification: 1};
   A._ZoneDelegate.prototype = {$isZoneDelegate: 1};
   A._Zone.prototype = {
@@ -13127,22 +13097,22 @@
   };
   A._RootZone.prototype = {
     get$_run() {
-      return B._RunNullaryZoneFunction__RootZone__rootRun;
+      return B._ZoneFunction__RootZone__rootRun;
     },
     get$_runUnary() {
-      return B._RunUnaryZoneFunction__RootZone__rootRunUnary;
+      return B._ZoneFunction__RootZone__rootRunUnary;
     },
     get$_runBinary() {
-      return B._RunBinaryZoneFunction__RootZone__rootRunBinary;
+      return B._ZoneFunction__RootZone__rootRunBinary;
     },
     get$_registerCallback() {
-      return B._RegisterNullaryZoneFunction__RootZone__rootRegisterCallback;
+      return B._ZoneFunction__RootZone__rootRegisterCallback;
     },
     get$_registerUnaryCallback() {
-      return B._RegisterUnaryZoneFunction_Bqo;
+      return B._ZoneFunction_Eeh;
     },
     get$_registerBinaryCallback() {
-      return B._RegisterBinaryZoneFunction_kGu;
+      return B._ZoneFunction_7G2;
     },
     get$_errorCallback() {
       return B._ZoneFunction__RootZone__rootErrorCallback;
@@ -25394,7 +25364,7 @@
       _inherit = hunkHelpers.inherit,
       _inheritMany = hunkHelpers.inheritMany;
     _inherit(A.Object, null);
-    _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Iterable, A.CastIterator, A.Closure, A.MapMixin, A.Error, A.SentinelValue, A.ListIterator, A.Iterator, A.EmptyIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._ListBase_Object_ListMixin, A.Symbol, A.MapView, A.ConstantMap, A.JSInvocationMirror, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A._Required, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A.Stream, A.StreamSubscription, A.StreamTransformerBase, A._StreamController, A._SyncStreamControllerDispatch, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._StreamIterator, A._ZoneFunction, A._RunNullaryZoneFunction, A._RunUnaryZoneFunction, A._RunBinaryZoneFunction, A._RegisterNullaryZoneFunction, A._RegisterUnaryZoneFunction, A._RegisterBinaryZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.__SetBase_Object_SetMixin, A._HashSetIterator, A._LinkedHashSetCell, A._LinkedHashSetIterator, A.IterableMixin, A.ListMixin, A._UnmodifiableMapMixin, A._ListQueueIterator, A.SetMixin, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A._JsonStringifier, A._Utf8Encoder, A._BigIntImpl, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.IntegerDivisionByZeroException, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.Expando, A.CssStyleDeclarationBase, A.EventStreamProvider, A._Html5NodeValidator, A.ImmutableListMixin, A.NodeValidatorBuilder, A._SimpleNodeValidator, A._SvgNodeValidator, A.FixedSizeListIterator, A._DOMWindowCrossFrame, A._SameOriginUriPolicy, A._ValidatingTreeSanitizer, A._StructuredClone, A._AcceptStructuredClone, A.JsObject, A.NullRejectionException, A._JSRandom, A._Random, A.AsyncMemoizer, A.DelegatingStreamSink, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.CopyOnWriteList, A.BuiltList, A.ListBuilder, A.BuiltListMultimap, A.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, A.BuiltSet, A.SetBuilder, A.BuiltSetMultimap, A.SetMultimapBuilder, A.EnumClass, A.IndentingBuiltValueToStringHelper, A.JsonObject, A.FullType, A.BigIntSerializer, A.BoolSerializer, A.BuiltJsonSerializers, A.BuiltJsonSerializersBuilder, A.BuiltListMultimapSerializer, A.BuiltListSerializer, A.BuiltMapSerializer, A.BuiltSetMultimapSerializer, A.BuiltSetSerializer, A.DateTimeSerializer, A.DoubleSerializer, A.DurationSerializer, A.Int64Serializer, A.IntSerializer, A.JsonObjectSerializer, A.NullSerializer, A.NumSerializer, A.RegExpSerializer, A.StringSerializer, A.UriSerializer, A.DefaultEquality, A.IterableEquality, A.ListEquality, A._UnorderedEquality, A._MapEntry, A.MapEquality, A.DeepCollectionEquality, A._QueueList_Object_ListMixin, A.BuildResult, A._$BuildStatusSerializer, A._$BuildResultSerializer, A.BuildResultBuilder, A.ConnectRequest, A._$ConnectRequestSerializer, A.ConnectRequestBuilder, A.DebugEvent, A.BatchedDebugEvents, A._$DebugEventSerializer, A._$BatchedDebugEventsSerializer, A.DebugEventBuilder, A.BatchedDebugEventsBuilder, A.DevToolsRequest, A.DevToolsResponse, A._$DevToolsRequestSerializer, A._$DevToolsResponseSerializer, A.DevToolsRequestBuilder, A.DevToolsResponseBuilder, A.ErrorResponse, A._$ErrorResponseSerializer, A.ErrorResponseBuilder, A.ExtensionRequest, A.ExtensionResponse, A.ExtensionEvent, A.BatchedEvents, A._$ExtensionRequestSerializer, A._$ExtensionResponseSerializer, A._$ExtensionEventSerializer, A._$BatchedEventsSerializer, A.ExtensionRequestBuilder, A.ExtensionResponseBuilder, A.ExtensionEventBuilder, A.BatchedEventsBuilder, A.IsolateExit, A.IsolateStart, A._$IsolateExitSerializer, A._$IsolateStartSerializer, A.IsolateExitBuilder, A.IsolateStartBuilder, A.RegisterEvent, A._$RegisterEventSerializer, A.RegisterEventBuilder, A.RunRequest, A._$RunRequestSerializer, A.SocketClient, A.Int64, A.Level, A.LogRecord, A.Logger, A.Pool, A.PoolResource, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.Uuid, A.WebSocketChannelException, A.BatchedStreamController, A.LegacyRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]);
+    _inheritMany(A.Object, [A.JS_CONST, J.Interceptor, J.ArrayIterator, A.Iterable, A.CastIterator, A.Closure, A.MapMixin, A.Error, A.SentinelValue, A.ListIterator, A.Iterator, A.EmptyIterator, A.FixedLengthListMixin, A.UnmodifiableListMixin, A._ListBase_Object_ListMixin, A.Symbol, A.MapView, A.ConstantMap, A.JSInvocationMirror, A.TypeErrorDecoder, A.NullThrownFromJavaScriptException, A.ExceptionAndStackTrace, A._StackTrace, A._Required, A.LinkedHashMapCell, A.LinkedHashMapKeyIterator, A.JSSyntaxRegExp, A._MatchImplementation, A._AllMatchesIterator, A.StringMatch, A._StringAllMatchesIterator, A._Cell, A.Rti, A._FunctionParameters, A._Type, A._TimerImpl, A._AsyncAwaitCompleter, A.AsyncError, A._Completer, A._FutureListener, A._Future, A._AsyncCallbackEntry, A.Stream, A.StreamSubscription, A.StreamTransformerBase, A._StreamController, A._SyncStreamControllerDispatch, A._AsyncStreamControllerDispatch, A._BufferingStreamSubscription, A._StreamSinkWrapper, A._DelayedEvent, A._DelayedDone, A._PendingEvents, A._StreamIterator, A._ZoneFunction, A._ZoneSpecification, A._ZoneDelegate, A._Zone, A._HashMapKeyIterator, A.__SetBase_Object_SetMixin, A._HashSetIterator, A._LinkedHashSetCell, A._LinkedHashSetIterator, A.IterableMixin, A.ListMixin, A._UnmodifiableMapMixin, A._ListQueueIterator, A.SetMixin, A._SplayTreeNode, A._SplayTree, A._SplayTreeIterator, A.Codec, A._JsonStringifier, A._Utf8Encoder, A._BigIntImpl, A.DateTime, A.Duration, A.OutOfMemoryError, A.StackOverflowError, A._Exception, A.FormatException, A.IntegerDivisionByZeroException, A.Null, A._StringStackTrace, A.StringBuffer, A._Uri, A.UriData, A._SimpleUri, A.Expando, A.CssStyleDeclarationBase, A.EventStreamProvider, A._Html5NodeValidator, A.ImmutableListMixin, A.NodeValidatorBuilder, A._SimpleNodeValidator, A._SvgNodeValidator, A.FixedSizeListIterator, A._DOMWindowCrossFrame, A._SameOriginUriPolicy, A._ValidatingTreeSanitizer, A._StructuredClone, A._AcceptStructuredClone, A.JsObject, A.NullRejectionException, A._JSRandom, A._Random, A.AsyncMemoizer, A.DelegatingStreamSink, A.ErrorResult, A.ValueResult, A.StreamQueue, A._NextRequest, A._HasNextRequest, A.CopyOnWriteList, A.BuiltList, A.ListBuilder, A.BuiltListMultimap, A.ListMultimapBuilder, A.BuiltMap, A.MapBuilder, A.BuiltSet, A.SetBuilder, A.BuiltSetMultimap, A.SetMultimapBuilder, A.EnumClass, A.IndentingBuiltValueToStringHelper, A.JsonObject, A.FullType, A.BigIntSerializer, A.BoolSerializer, A.BuiltJsonSerializers, A.BuiltJsonSerializersBuilder, A.BuiltListMultimapSerializer, A.BuiltListSerializer, A.BuiltMapSerializer, A.BuiltSetMultimapSerializer, A.BuiltSetSerializer, A.DateTimeSerializer, A.DoubleSerializer, A.DurationSerializer, A.Int64Serializer, A.IntSerializer, A.JsonObjectSerializer, A.NullSerializer, A.NumSerializer, A.RegExpSerializer, A.StringSerializer, A.UriSerializer, A.DefaultEquality, A.IterableEquality, A.ListEquality, A._UnorderedEquality, A._MapEntry, A.MapEquality, A.DeepCollectionEquality, A._QueueList_Object_ListMixin, A.BuildResult, A._$BuildStatusSerializer, A._$BuildResultSerializer, A.BuildResultBuilder, A.ConnectRequest, A._$ConnectRequestSerializer, A.ConnectRequestBuilder, A.DebugEvent, A.BatchedDebugEvents, A._$DebugEventSerializer, A._$BatchedDebugEventsSerializer, A.DebugEventBuilder, A.BatchedDebugEventsBuilder, A.DevToolsRequest, A.DevToolsResponse, A._$DevToolsRequestSerializer, A._$DevToolsResponseSerializer, A.DevToolsRequestBuilder, A.DevToolsResponseBuilder, A.ErrorResponse, A._$ErrorResponseSerializer, A.ErrorResponseBuilder, A.ExtensionRequest, A.ExtensionResponse, A.ExtensionEvent, A.BatchedEvents, A._$ExtensionRequestSerializer, A._$ExtensionResponseSerializer, A._$ExtensionEventSerializer, A._$BatchedEventsSerializer, A.ExtensionRequestBuilder, A.ExtensionResponseBuilder, A.ExtensionEventBuilder, A.BatchedEventsBuilder, A.IsolateExit, A.IsolateStart, A._$IsolateExitSerializer, A._$IsolateStartSerializer, A.IsolateExitBuilder, A.IsolateStartBuilder, A.RegisterEvent, A._$RegisterEventSerializer, A.RegisterEventBuilder, A.RunRequest, A._$RunRequestSerializer, A.SocketClient, A.Int64, A.Level, A.LogRecord, A.Logger, A.Pool, A.PoolResource, A.StreamChannelMixin, A._GuaranteeSink, A.StreamChannelController, A.Uuid, A.WebSocketChannelException, A.BatchedStreamController, A.LegacyRestarter, A.ReloadingManager, A.HotReloadFailedException, A.RequireRestarter]);
     _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSArray, J.JSNumber, J.JSString, A.NativeByteBuffer, A.NativeTypedData]);
     _inheritMany(J.JavaScriptObject, [J.LegacyJavaScriptObject, A.EventTarget, A.AccessibleNodeList, A.Blob, A.Event, A.CssTransformComponent, A.CssRule, A._CssStyleDeclaration_JavaScriptObject_CssStyleDeclarationBase, A.CssStyleValue, A.DataTransferItemList, A.DomException, A.DomImplementation, A._DomRectList_JavaScriptObject_ListMixin, A.DomRectReadOnly, A._DomStringList_JavaScriptObject_ListMixin, A.DomTokenList, A._FileList_JavaScriptObject_ListMixin, A.Gamepad, A.History, A._HtmlCollection_JavaScriptObject_ListMixin, A.ImageData, A.Location, A.MediaList, A._MidiInputMap_JavaScriptObject_MapMixin, A._MidiOutputMap_JavaScriptObject_MapMixin, A.MimeType, A._MimeTypeArray_JavaScriptObject_ListMixin, A._NodeList_JavaScriptObject_ListMixin, A.Plugin, A._PluginArray_JavaScriptObject_ListMixin, A._RtcStatsReport_JavaScriptObject_MapMixin, A.SpeechGrammar, A._SpeechGrammarList_JavaScriptObject_ListMixin, A.SpeechRecognitionResult, A._Storage_JavaScriptObject_MapMixin, A.StyleSheet, A._TextTrackCueList_JavaScriptObject_ListMixin, A.TimeRanges, A.Touch, A._TouchList_JavaScriptObject_ListMixin, A.TrackDefaultList, A.Url, A.__CssRuleList_JavaScriptObject_ListMixin, A.__GamepadList_JavaScriptObject_ListMixin, A.__NamedNodeMap_JavaScriptObject_ListMixin, A.__SpeechRecognitionResultList_JavaScriptObject_ListMixin, A.__StyleSheetList_JavaScriptObject_ListMixin, A.KeyRange, A.Length, A._LengthList_JavaScriptObject_ListMixin, A.Number, A._NumberList_JavaScriptObject_ListMixin, A.PointList, A._StringList_JavaScriptObject_ListMixin, A.Transform, A._TransformList_JavaScriptObject_ListMixin, A.AudioBuffer, A._AudioParamMap_JavaScriptObject_MapMixin]);
     _inheritMany(J.LegacyJavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction, A.Promise, A.RequireLoader, A.JsError, A.JsMap]);
@@ -26190,19 +26160,19 @@
     B.Type_Uri_EFX = A.typeLiteral("Uri");
     B.Type_double_K1J = A.typeLiteral("double");
     B.Type_num_cv7 = A.typeLiteral("num");
-    B._RegisterBinaryZoneFunction_kGu = new A._RegisterBinaryZoneFunction(B.C__RootZone, A.async___rootRegisterBinaryCallback$closure());
-    B._RegisterNullaryZoneFunction__RootZone__rootRegisterCallback = new A._RegisterNullaryZoneFunction(B.C__RootZone, A.async___rootRegisterCallback$closure());
-    B._RegisterUnaryZoneFunction_Bqo = new A._RegisterUnaryZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback$closure());
-    B._RunBinaryZoneFunction__RootZone__rootRunBinary = new A._RunBinaryZoneFunction(B.C__RootZone, A.async___rootRunBinary$closure());
-    B._RunNullaryZoneFunction__RootZone__rootRun = new A._RunNullaryZoneFunction(B.C__RootZone, A.async___rootRun$closure());
-    B._RunUnaryZoneFunction__RootZone__rootRunUnary = new A._RunUnaryZoneFunction(B.C__RootZone, A.async___rootRunUnary$closure());
     B._StringStackTrace_3uE = new A._StringStackTrace("");
     B._ZoneFunction_3bB = new A._ZoneFunction(B.C__RootZone, A.async___rootCreatePeriodicTimer$closure(), A.findType("_ZoneFunction<Timer*(Zone*,ZoneDelegate*,Zone*,Duration*,~(Timer*)*)*>"));
+    B._ZoneFunction_7G2 = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterBinaryCallback$closure(), A.findType("_ZoneFunction<0^*(1^*,2^*)*(Zone*,ZoneDelegate*,Zone*,0^*(1^*,2^*)*)<Object?Object?Object?>*>"));
+    B._ZoneFunction_Eeh = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback$closure(), A.findType("_ZoneFunction<0^*(1^*)*(Zone*,ZoneDelegate*,Zone*,0^*(1^*)*)<Object?Object?>*>"));
     B._ZoneFunction_NMc = new A._ZoneFunction(B.C__RootZone, A.async___rootHandleUncaughtError$closure(), A.findType("_ZoneFunction<~(Zone*,ZoneDelegate*,Zone*,Object*,StackTrace*)*>"));
     B._ZoneFunction__RootZone__rootCreateTimer = new A._ZoneFunction(B.C__RootZone, A.async___rootCreateTimer$closure(), A.findType("_ZoneFunction<Timer*(Zone*,ZoneDelegate*,Zone*,Duration*,~()*)*>"));
     B._ZoneFunction__RootZone__rootErrorCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootErrorCallback$closure(), A.findType("_ZoneFunction<AsyncError?(Zone*,ZoneDelegate*,Zone*,Object*,StackTrace?)*>"));
     B._ZoneFunction__RootZone__rootFork = new A._ZoneFunction(B.C__RootZone, A.async___rootFork$closure(), A.findType("_ZoneFunction<Zone*(Zone*,ZoneDelegate*,Zone*,ZoneSpecification?,Map<Object?,Object?>?)*>"));
     B._ZoneFunction__RootZone__rootPrint = new A._ZoneFunction(B.C__RootZone, A.async___rootPrint$closure(), A.findType("_ZoneFunction<~(Zone*,ZoneDelegate*,Zone*,String*)*>"));
+    B._ZoneFunction__RootZone__rootRegisterCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterCallback$closure(), A.findType("_ZoneFunction<0^*()*(Zone*,ZoneDelegate*,Zone*,0^*()*)<Object?>*>"));
+    B._ZoneFunction__RootZone__rootRun = new A._ZoneFunction(B.C__RootZone, A.async___rootRun$closure(), A.findType("_ZoneFunction<0^*(Zone*,ZoneDelegate*,Zone*,0^*()*)<Object?>*>"));
+    B._ZoneFunction__RootZone__rootRunBinary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunBinary$closure(), A.findType("_ZoneFunction<0^*(Zone*,ZoneDelegate*,Zone*,0^*(1^*,2^*)*,1^*,2^*)<Object?Object?Object?>*>"));
+    B._ZoneFunction__RootZone__rootRunUnary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunUnary$closure(), A.findType("_ZoneFunction<0^*(Zone*,ZoneDelegate*,Zone*,0^*(1^*)*,1^*)<Object?Object?>*>"));
     B._ZoneFunction__RootZone__rootScheduleMicrotask = new A._ZoneFunction(B.C__RootZone, A.async___rootScheduleMicrotask$closure(), A.findType("_ZoneFunction<~(Zone*,ZoneDelegate*,Zone*,~()*)*>"));
     B._ZoneSpecification_ALf = new A._ZoneSpecification(null, null, null, null, null, null, null, null, null, null, null, null, null);
   })();
diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart
index 3b396ba..196419e 100644
--- a/dwds/lib/src/services/chrome_proxy_service.dart
+++ b/dwds/lib/src/services/chrome_proxy_service.dart
@@ -842,15 +842,19 @@
           ..timestamp = e.timestamp.toInt());
       });
       if (includeExceptions) {
-        exceptionsSubscription = remoteDebugger.onExceptionThrown.listen((e) {
+        exceptionsSubscription =
+            remoteDebugger.onExceptionThrown.listen((e) async {
           var isolate = _inspector?.isolate;
           if (isolate == null) return;
+          var description = e.exceptionDetails.exception.description;
+          if (description != null) {
+            description = await _inspector.mapExceptionStackTrace(description);
+          }
           controller.add(Event(
               kind: EventKind.kWriteEvent,
               timestamp: DateTime.now().millisecondsSinceEpoch,
               isolate: _inspector.isolateRef)
-            ..bytes = base64.encode(
-                utf8.encode(e.exceptionDetails.exception.description ?? '')));
+            ..bytes = base64.encode(utf8.encode(description ?? '')));
         });
       }
     });
diff --git a/dwds/test/chrome_proxy_service_test.dart b/dwds/test/chrome_proxy_service_test.dart
index 46bebc6..92fe072 100644
--- a/dwds/test/chrome_proxy_service_test.dart
+++ b/dwds/test/chrome_proxy_service_test.dart
@@ -1129,6 +1129,8 @@
         var event = await stream
             .firstWhere((event) => event.kind == EventKind.kPauseException);
         expect(event.exception, isNotNull);
+        // Check that the exception stack trace has been mapped to Dart source files.
+        expect(event.exception.valueAsString, contains('main.dart'));
 
         var stack = await service.getStack(isolateId);
         expect(stack, isNotNull);
@@ -1660,6 +1662,18 @@
         await tabConnection.runtime.evaluate('console.error("Error");');
       });
 
+      test('exception stack trace mapper', () async {
+        expect(service.streamListen('Stderr'), completion(_isSuccess));
+        var stderrStream = service.onEvent('Stderr');
+        expect(
+            stderrStream,
+            emitsThrough(predicate((Event event) =>
+                event.kind == EventKind.kWriteEvent &&
+                String.fromCharCodes(base64.decode(event.bytes))
+                    .contains('main.dart'))));
+        await tabConnection.runtime.evaluate('throwUncaughtException();');
+      });
+
       test('VM', () async {
         var status = await service.streamListen('VM');
         expect(status, _isSuccess);
diff --git a/fixtures/_test/example/hello_world/main.dart b/fixtures/_test/example/hello_world/main.dart
index da0bd5a..f36903c 100644
--- a/fixtures/_test/example/hello_world/main.dart
+++ b/fixtures/_test/example/hello_world/main.dart
@@ -55,6 +55,10 @@
     log(message, name: 'testLogCategory');
   };
 
+  context['throwUncaughtException'] = () {
+    scheduleMicrotask(() => throw Exception('UncaughtException'));
+  };
+
   Timer.periodic(const Duration(seconds: 1), (_) {
     printCount(); // Breakpoint: callPrintCount
   });
diff --git a/fixtures/_testSound/example/hello_world/main.dart b/fixtures/_testSound/example/hello_world/main.dart
index 6618118..d21af3f 100644
--- a/fixtures/_testSound/example/hello_world/main.dart
+++ b/fixtures/_testSound/example/hello_world/main.dart
@@ -55,6 +55,10 @@
     log(message, name: 'testLogCategory');
   };
 
+  context['throwUncaughtException'] = () {
+    scheduleMicrotask(() => throw Exception('UncaughtException'));
+  };
+
   Timer.periodic(const Duration(seconds: 1), (_) {
     printCount(); // Breakpoint: callPrintCount
   });