diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index ff9e196cd..40704f224 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,5 +1,6 @@ ## 14.0.3-dev - 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 b761879cb..dd9e02426 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -558,8 +558,10 @@ class Debugger extends Domain { 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 44e2b8951..24d19724c 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -67,6 +67,12 @@ class AppInspector extends Domain { 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 @@ class AppInspector extends Domain { /// [evalExpression] should be a JS function definition that can accept /// [arguments]. Future _jsCallFunction( - String evalExpression, List arguments, + String evalExpression, List arguments, {bool returnByValue = false}) async { var jsArguments = arguments.map(callArgumentFor).toList(); var result = @@ -550,4 +556,23 @@ function($argsString) { 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 mapExceptionStackTrace(String description) async { + RemoteObject mapperResult; + try { + mapperResult = await _jsCallFunction( + stackTraceMapperExpression, [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 7e79d6cb2..96851a765 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; @@ -12847,12 +12823,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 = { @@ -13118,22 +13088,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; @@ -25313,7 +25283,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]); @@ -26110,19 +26080,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")); + 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^*)*)*>")); + B._ZoneFunction_Eeh = new A._ZoneFunction(B.C__RootZone, A.async___rootRegisterUnaryCallback$closure(), A.findType("_ZoneFunction<0^*(1^*)*(Zone*,ZoneDelegate*,Zone*,0^*(1^*)*)*>")); 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")); B._ZoneFunction__RootZone__rootErrorCallback = new A._ZoneFunction(B.C__RootZone, A.async___rootErrorCallback$closure(), A.findType("_ZoneFunction")); B._ZoneFunction__RootZone__rootFork = new A._ZoneFunction(B.C__RootZone, A.async___rootFork$closure(), A.findType("_ZoneFunction?)*>")); 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^*()*)*>")); + B._ZoneFunction__RootZone__rootRun = new A._ZoneFunction(B.C__RootZone, A.async___rootRun$closure(), A.findType("_ZoneFunction<0^*(Zone*,ZoneDelegate*,Zone*,0^*()*)*>")); + 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^*)*>")); + B._ZoneFunction__RootZone__rootRunUnary = new A._ZoneFunction(B.C__RootZone, A.async___rootRunUnary$closure(), A.findType("_ZoneFunction<0^*(Zone*,ZoneDelegate*,Zone*,0^*(1^*)*,1^*)*>")); 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 3b396ba4b..196419e3d 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -842,15 +842,19 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( ..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 46bebc624..92fe072a6 100644 --- a/dwds/test/chrome_proxy_service_test.dart +++ b/dwds/test/chrome_proxy_service_test.dart @@ -1129,6 +1129,8 @@ void main() { 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 @@ void main() { 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 da0bd5a9d..f36903c71 100644 --- a/fixtures/_test/example/hello_world/main.dart +++ b/fixtures/_test/example/hello_world/main.dart @@ -55,6 +55,10 @@ void main() async { 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 6618118af..d21af3f9d 100644 --- a/fixtures/_testSound/example/hello_world/main.dart +++ b/fixtures/_testSound/example/hello_world/main.dart @@ -55,6 +55,10 @@ void main() async { log(message, name: 'testLogCategory'); }; + context['throwUncaughtException'] = () { + scheduleMicrotask(() => throw Exception('UncaughtException')); + }; + Timer.periodic(const Duration(seconds: 1), (_) { printCount(); // Breakpoint: callPrintCount });