@@ -9,8 +9,9 @@ import 'package:dwds/src/debugging/remote_debugger.dart';
99import 'package:logging/logging.dart' ;
1010
1111abstract class ExecutionContext {
12- /// Returns the context ID that contains the running Dart application.
13- Future <int > get id;
12+ /// Returns the context ID that contains the running Dart application,
13+ /// if available.
14+ Future <int ?> get id;
1415}
1516
1617/// The execution context in which to do remote evaluations.
@@ -23,12 +24,12 @@ class RemoteDebuggerExecutionContext extends ExecutionContext {
2324 /// Context can be null if an error has occurred and we cannot detect
2425 /// and parse the context ID.
2526 late StreamQueue <int > _contexts;
27+ final _contextController = StreamController <int >();
28+ final _seenContexts = < int > [];
2629
2730 int ? _id;
2831
29- @override
30- Future <int > get id async {
31- if (_id != null ) return _id! ;
32+ Future <int ?> _lookUpId () async {
3233 _logger.fine ('Looking for Dart execution context...' );
3334 const timeoutInMs = 100 ;
3435 while (await _contexts.hasNext.timeout (
@@ -41,6 +42,7 @@ class RemoteDebuggerExecutionContext extends ExecutionContext {
4142 },
4243 )) {
4344 final context = await _contexts.next;
45+ _seenContexts.add (context);
4446 _logger.fine ('Checking context id: $context ' );
4547 try {
4648 final result = await _remoteDebugger.sendCommand (
@@ -51,24 +53,34 @@ class RemoteDebuggerExecutionContext extends ExecutionContext {
5153 },
5254 );
5355 if (result.result? ['result' ]? ['value' ] != null ) {
54- _logger.fine ('Found valid execution context: $context ' );
55- _id = context;
56- break ;
56+ _logger.fine ('Found dart execution context: $context ' );
57+ return context;
5758 }
5859 } catch (_) {
5960 // Errors may be thrown if we attempt to evaluate in a stale a context.
6061 // Ignore and continue.
61- _logger.fine ('Invalid execution context: $context ' );
62+ _logger.fine ('Stale execution context: $context ' );
63+ _seenContexts.remove (context);
6264 }
6365 }
66+ return null ;
67+ }
68+
69+ @override
70+ Future <int ?> get id async {
71+ if (_id != null ) return _id;
72+
73+ _id = await _lookUpId ();
6474 if (_id == null ) {
65- throw StateError ('No context with the running Dart application.' );
75+ // Add seen contexts back to the queue in case the injected
76+ // client is still loading, so the next call to `id` succeeds.
77+ _seenContexts.forEach (_contextController.add);
78+ _seenContexts.clear ();
6679 }
67- return _id! ;
80+ return _id;
6881 }
6982
7083 RemoteDebuggerExecutionContext (this ._id, this ._remoteDebugger) {
71- final contextController = StreamController <int >();
7284 _remoteDebugger
7385 .eventStream ('Runtime.executionContextsCleared' , (e) => e)
7486 .listen ((_) => _id = null );
@@ -86,8 +98,8 @@ class RemoteDebuggerExecutionContext extends ExecutionContext {
8698 }
8799 return parsedId;
88100 }).listen ((e) {
89- if (e != null ) contextController .add (e);
101+ if (e != null ) _contextController .add (e);
90102 });
91- _contexts = StreamQueue (contextController .stream);
103+ _contexts = StreamQueue (_contextController .stream);
92104 }
93105}
0 commit comments