diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 80a5c0623..02378f08d 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -4,6 +4,7 @@ - Do not persist breakpoints across hot restarts or page reloads. - [#2371](https://github.com/dart-lang/webdev/pull/2371) - If `pause_isolates_on_start` is `true`, wait for `resume` to run the app's `main` method. - [#2378](https://github.com/dart-lang/webdev/pull/2378) - Fix bug where setting breakpoints in a project using macros would fail. - [#2403](https://github.com/dart-lang/webdev/pull/2403) +- Make stack trace calculation resilient against one frame throwing an error. - [#2408](https://github.com/dart-lang/webdev/pull/2408) **Breaking changes** diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index 3c4ab7fa2..7e6d41824 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -462,7 +462,13 @@ class Debugger extends Domain { // Don't populate variables for async frames. if (populateVariables) { - dartFrame.vars = await variablesFor(frame); + try { + dartFrame.vars = await variablesFor(frame); + } catch (e) { + logger.warning( + 'Error calculating Dart variables for frame $frameIndex: $e', + ); + } } return dartFrame; diff --git a/dwds/lib/src/debugging/frame_computer.dart b/dwds/lib/src/debugging/frame_computer.dart index 50bd325eb..6626a0f81 100644 --- a/dwds/lib/src/debugging/frame_computer.dart +++ b/dwds/lib/src/debugging/frame_computer.dart @@ -4,10 +4,13 @@ import 'package:dwds/src/debugging/debugger.dart'; import 'package:dwds/src/utilities/synchronized.dart'; +import 'package:logging/logging.dart'; import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; class FrameComputer { + static final logger = Logger('FrameComputer'); + final Debugger debugger; // To ensure that the frames are computed only once, we use an atomic queue @@ -58,12 +61,16 @@ class FrameComputer { Future _collectSyncFrames({int? limit}) async { while (_frameIndex < _callFrames.length) { if (limit != null && _computedFrames.length == limit) return; - - final callFrame = _callFrames[_frameIndex]; - final dartFrame = - await debugger.calculateDartFrameFor(callFrame, _frameIndex++); - if (dartFrame != null) { - _computedFrames.add(dartFrame); + try { + final callFrame = _callFrames[_frameIndex]; + final dartFrame = + await debugger.calculateDartFrameFor(callFrame, _frameIndex++); + if (dartFrame != null) { + _computedFrames.add(dartFrame); + } + } catch (e) { + // If there is an error calculating the frame, then skip it. + logger.warning('Error calculating sync frame: $e'); } } } @@ -93,28 +100,33 @@ class FrameComputer { final asyncFramesToProcess = _asyncFramesToProcess!; // Process a single async frame. if (asyncFramesToProcess.isNotEmpty) { - final callFrame = asyncFramesToProcess.removeAt(0); - final location = WipLocation.fromValues( - callFrame.scriptId, - callFrame.lineNumber, - columnNumber: callFrame.columnNumber, - ); - - final tempWipFrame = WipCallFrame({ - 'url': callFrame.url, - 'functionName': callFrame.functionName, - 'location': location.json, - 'scopeChain': [], - }); - - final frame = await debugger.calculateDartFrameFor( - tempWipFrame, - _frameIndex++, - populateVariables: false, - ); - if (frame != null) { - frame.kind = FrameKind.kAsyncCausal; - _computedFrames.add(frame); + try { + final callFrame = asyncFramesToProcess.removeAt(0); + final location = WipLocation.fromValues( + callFrame.scriptId, + callFrame.lineNumber, + columnNumber: callFrame.columnNumber, + ); + + final tempWipFrame = WipCallFrame({ + 'url': callFrame.url, + 'functionName': callFrame.functionName, + 'location': location.json, + 'scopeChain': [], + }); + + final frame = await debugger.calculateDartFrameFor( + tempWipFrame, + _frameIndex++, + populateVariables: false, + ); + if (frame != null) { + frame.kind = FrameKind.kAsyncCausal; + _computedFrames.add(frame); + } + } catch (e) { + // If there is an error calculating the frame, then skip it. + logger.warning('Error calculating async frame: $e'); } } } diff --git a/dwds/test/debugger_test.dart b/dwds/test/debugger_test.dart index 863697bac..112ee1c53 100644 --- a/dwds/test/debugger_test.dart +++ b/dwds/test/debugger_test.dart @@ -204,7 +204,8 @@ void main() async { Debugger.logger.onRecord, emitsThrough( predicate( - (LogRecord log) => log.message == 'Error calculating Dart frames', + (LogRecord log) => + log.message.contains('Error calculating sync frame'), ), ), );