diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 11b6df61f..431822994 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -5,9 +5,11 @@ evaluation using a compiler in all scenarios. - Fix a bug where evaluation would fail with more than one parameter in the scope. -- Remove showing uncaptured values from the stack during evaluation. +- Remove showing un-captured values from the stack during evaluation. - Refactor code to break most circular dependencies between files. - Migrate `package:dwds` to null safety. +- Make `ChromeProxyService.getStack` wait for the debugger to perform initial + resume operation. This avoids race conditions on isolate start. **Breaking changes** - Remove no longer used `ExpressionCompilerService.handler`. diff --git a/dwds/lib/src/debugging/debugger.dart b/dwds/lib/src/debugging/debugger.dart index e9f3f32bc..05540f7aa 100644 --- a/dwds/lib/src/debugging/debugger.dart +++ b/dwds/lib/src/debugging/debugger.dart @@ -150,7 +150,7 @@ class Debugger extends Domain { /// Returns the current Dart stack for the paused debugger. /// - /// Returns null if the debugger is not paused. + /// Throws RPCError if the debugger is not paused. /// /// The returned stack will contain up to [limit] frames if provided. Future getStack({int? limit}) async { diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 63ba70d1b..2d3a89e1f 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -46,6 +46,10 @@ class ChromeProxyService implements VmServiceInterface { Future get isInitialized => _initializedCompleter.future; Completer _initializedCompleter = Completer(); + /// Signals when isolate starts. + Future get isStarted => _startedCompleter.future; + Completer _startedCompleter = Completer(); + /// Signals when expression compiler is ready to evaluate. Future get isCompilerInitialized => _compilerCompleter.future; Completer _compilerCompleter = Completer(); @@ -252,6 +256,7 @@ class ChromeProxyService implements VmServiceInterface { unawaited(appConnection.onStart.then((_) async { await debugger.resumeFromStart(); + _startedCompleter.complete(); })); final isolateRef = inspector.isolateRef; @@ -301,6 +306,7 @@ class ChromeProxyService implements VmServiceInterface { final isolateRef = inspector.isolateRef; _initializedCompleter = Completer(); + _startedCompleter = Completer(); _compilerCompleter = Completer(); _streamNotify( 'Isolate', @@ -573,12 +579,13 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( /// Returns the current stack. /// - /// Returns null if the corresponding isolate is not paused. + /// Throws RPCError the corresponding isolate is not paused. /// /// The returned stack will contain up to [limit] frames if provided. @override Future getStack(String isolateId, {int? limit}) async { await isInitialized; + await isStarted; _checkIsolate('getStack', isolateId); return (await debuggerFuture).getStack(limit: limit); } @@ -718,6 +725,7 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension( if (inspector.appConnection.isStarted) { return captureElapsedTime(() async { await isInitialized; + await isStarted; _checkIsolate('resume', isolateId); return await (await debuggerFuture) .resume(step: step, frameIndex: frameIndex);