4
4
5
5
import 'dart:async' ;
6
6
7
+ import 'package:dds/dds.dart' ;
8
+ import 'package:dds/dds_launcher.dart' ;
7
9
import 'package:meta/meta.dart' ;
8
10
9
11
import '../artifacts.dart' ;
10
- import '../convert.dart' ;
11
12
import '../device.dart' ;
12
13
import '../globals.dart' as globals;
13
14
import 'io.dart' as io;
14
15
import 'logger.dart' ;
15
16
16
- /// A representation of the current DDS state including:
17
- ///
18
- /// - The process the external DDS instance is running in
19
- /// - The service URI DDS is being served on
20
- /// - The URI DevTools is being served on, if applicable
21
- /// - The URI DTD is being served on, if applicable
22
- typedef DartDevelopmentServiceInstance = ({
23
- io.Process ? process,
24
- Uri ? serviceUri,
25
- Uri ? devToolsUri,
26
- Uri ? dtdUri,
27
- });
28
-
29
- /// The default DDSLauncherCallback used to spawn DDS.
30
- Future <DartDevelopmentServiceInstance > defaultStartDartDevelopmentService (
31
- Uri remoteVmServiceUri, {
32
- required bool enableAuthCodes,
33
- required bool ipv6,
34
- required bool enableDevTools,
35
- required List <String > cachedUserTags,
36
- Uri ? serviceUri,
37
- String ? google3WorkspaceRoot,
38
- Uri ? devToolsServerAddress,
39
- }) async {
40
- final String exe = globals.artifacts! .getArtifactPath (
41
- Artifact .engineDartBinary,
42
- );
43
- final io.Process process = await io.Process .start (
44
- exe,
45
- < String > [
46
- 'development-service' ,
47
- '--vm-service-uri=$remoteVmServiceUri ' ,
48
- if (serviceUri != null ) ...< String > [
49
- '--bind-address=${serviceUri .host }' ,
50
- '--bind-port=${serviceUri .port }' ,
51
- ],
52
- if (! enableAuthCodes) '--disable-service-auth-codes' ,
53
- if (google3WorkspaceRoot != null )
54
- '--google3-workspace-root=$google3WorkspaceRoot ' ,
55
- for (final String tag in cachedUserTags) '--cached-user-tags=$tag ' ,
56
- ],
57
- );
58
- final Completer <DartDevelopmentServiceInstance > completer =
59
- Completer <DartDevelopmentServiceInstance >();
60
- late StreamSubscription <Object ?> stderrSub;
61
- stderrSub = process.stderr
62
- .transform (utf8.decoder)
63
- .transform (json.decoder)
64
- .listen ((Object ? result) {
65
- if (result
66
- case {
67
- 'state' : 'started' ,
68
- 'ddsUri' : final String ddsUriStr,
69
- }) {
70
- final Uri ddsUri = Uri .parse (ddsUriStr);
71
- final String ? devToolsUriStr = result['devToolsUri' ] as String ? ;
72
- final Uri ? devToolsUri =
73
- devToolsUriStr == null ? null : Uri .parse (devToolsUriStr);
74
- final String ? dtdUriStr =
75
- (result['dtd' ] as Map <String , Object ?>? )? ['uri' ] as String ? ;
76
- final Uri ? dtdUri = dtdUriStr == null ? null : Uri .parse (dtdUriStr);
77
-
78
- completer.complete ((
79
- process: process,
80
- serviceUri: ddsUri,
81
- devToolsUri: devToolsUri,
82
- dtdUri: dtdUri,
83
- ));
84
- } else if (result
85
- case {
86
- 'state' : 'error' ,
87
- 'error' : final String error,
88
- }) {
89
- final Map <String , Object ?>? exceptionDetails =
90
- result['ddsExceptionDetails' ] as Map <String , Object ?>? ;
91
- completer.completeError (
92
- exceptionDetails != null
93
- ? DartDevelopmentServiceException .fromJson (exceptionDetails)
94
- : StateError (error),
95
- );
96
- } else {
97
- throw StateError ('Unexpected result from DDS: $result ' );
98
- }
99
- stderrSub.cancel ();
100
- });
101
- return completer.future;
102
- }
17
+ export 'package:dds/dds.dart'
18
+ show
19
+ DartDevelopmentServiceException,
20
+ ExistingDartDevelopmentServiceException;
103
21
104
- typedef DDSLauncherCallback = Future <DartDevelopmentServiceInstance > Function (
105
- Uri remoteVmServiceUri, {
106
- required bool enableAuthCodes,
107
- required bool ipv6,
108
- required bool enableDevTools,
109
- required List <String > cachedUserTags,
22
+ typedef DDSLauncherCallback = Future <DartDevelopmentServiceLauncher > Function ({
23
+ required Uri remoteVmServiceUri,
110
24
Uri ? serviceUri,
111
- String ? google3WorkspaceRoot,
25
+ bool enableAuthCodes,
26
+ bool serveDevTools,
112
27
Uri ? devToolsServerAddress,
28
+ bool enableServicePortFallback,
29
+ List <String > cachedUserTags,
30
+ String ? dartExecutable,
31
+ Uri ? google3WorkspaceRoot,
113
32
});
114
33
115
34
// TODO(fujino): This should be direct injected, rather than mutable global state.
116
35
/// Used by tests to override the DDS spawn behavior for mocking purposes.
117
36
@visibleForTesting
118
- DDSLauncherCallback ddsLauncherCallback = defaultStartDartDevelopmentService;
119
-
120
- /// Thrown by DDS during initialization failures, unexpected connection issues,
121
- /// and when attempting to spawn DDS when an existing DDS instance exists.
122
- class DartDevelopmentServiceException implements Exception {
123
- factory DartDevelopmentServiceException .fromJson (Map <String , Object ?> json) {
124
- if (json
125
- case {
126
- 'error_code' : final int errorCode,
127
- 'message' : final String message,
128
- }) {
129
- return switch (errorCode) {
130
- existingDdsInstanceError =>
131
- DartDevelopmentServiceException .existingDdsInstance (
132
- message,
133
- ddsUri: Uri .parse (json['uri' ]! as String ),
134
- ),
135
- failedToStartError => DartDevelopmentServiceException .failedToStart (),
136
- connectionError =>
137
- DartDevelopmentServiceException .connectionIssue (message),
138
- _ => throw StateError (
139
- 'Invalid DartDevelopmentServiceException error_code: $errorCode ' ,
140
- ),
141
- };
142
- }
143
- throw StateError ('Invalid DartDevelopmentServiceException JSON: $json ' );
144
- }
145
-
146
- /// Thrown when `DartDeveloperService.startDartDevelopmentService` is called
147
- /// and the target VM service already has a Dart Developer Service instance
148
- /// connected.
149
- factory DartDevelopmentServiceException .existingDdsInstance (
150
- String message, {
151
- Uri ? ddsUri,
152
- }) {
153
- return ExistingDartDevelopmentServiceException ._(
154
- message,
155
- ddsUri: ddsUri,
156
- );
157
- }
158
-
159
- /// Thrown when the connection to the remote VM service terminates unexpectedly
160
- /// during Dart Development Service startup.
161
- factory DartDevelopmentServiceException .failedToStart () {
162
- return DartDevelopmentServiceException ._(
163
- failedToStartError,
164
- 'Failed to start Dart Development Service' ,
165
- );
166
- }
167
-
168
- /// Thrown when a connection error has occurred after startup.
169
- factory DartDevelopmentServiceException .connectionIssue (String message) {
170
- return DartDevelopmentServiceException ._(connectionError, message);
171
- }
172
-
173
- DartDevelopmentServiceException ._(this .errorCode, this .message);
174
-
175
- /// Set when `DartDeveloperService.startDartDevelopmentService` is called and
176
- /// the target VM service already has a Dart Developer Service instance
177
- /// connected.
178
- static const int existingDdsInstanceError = 1 ;
179
-
180
- /// Set when the connection to the remote VM service terminates unexpectedly
181
- /// during Dart Development Service startup.
182
- static const int failedToStartError = 2 ;
183
-
184
- /// Set when a connection error has occurred after startup.
185
- static const int connectionError = 3 ;
186
-
187
- @override
188
- String toString () => 'DartDevelopmentServiceException: $message ' ;
189
-
190
- final int errorCode;
191
- final String message;
192
- }
193
-
194
- /// Thrown when attempting to start a new DDS instance when one already exists.
195
- class ExistingDartDevelopmentServiceException
196
- extends DartDevelopmentServiceException {
197
- ExistingDartDevelopmentServiceException ._(
198
- String message, {
199
- this .ddsUri,
200
- }) : super ._(
201
- DartDevelopmentServiceException .existingDdsInstanceError,
202
- message,
203
- );
204
-
205
- /// The URI of the existing DDS instance, if available.
206
- ///
207
- /// This URI is the base HTTP URI such as `http://127.0.0.1:1234/AbcDefg=/` ,
208
- /// not the WebSocket URI (which can be obtained by mapping the scheme to
209
- /// `ws` (or `wss` ) and appending `ws` to the path segments).
210
- final Uri ? ddsUri;
211
- }
37
+ DDSLauncherCallback ddsLauncherCallback = DartDevelopmentServiceLauncher .start;
212
38
213
39
/// Helper class to launch a [dds.DartDevelopmentService] . Allows for us to
214
40
/// mock out this functionality for testing purposes.
215
41
class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin {
216
42
DartDevelopmentService ({required Logger logger}) : _logger = logger;
217
43
218
- DartDevelopmentServiceInstance ? _ddsInstance;
44
+ DartDevelopmentServiceLauncher ? _ddsInstance;
219
45
220
- Uri ? get uri => _ddsInstance? .serviceUri ?? _existingDdsUri;
46
+ Uri ? get uri => _ddsInstance? .uri ?? _existingDdsUri;
221
47
Uri ? _existingDdsUri;
222
48
223
49
Future <void > get done => _completer.future;
@@ -257,25 +83,25 @@ class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin {
257
83
258
84
try {
259
85
_ddsInstance = await ddsLauncherCallback (
260
- vmServiceUri,
86
+ remoteVmServiceUri : vmServiceUri,
261
87
serviceUri: ddsUri,
262
88
enableAuthCodes: disableServiceAuthCodes != true ,
263
- ipv6: ipv6 ?? false ,
264
- enableDevTools: enableDevTools,
265
89
// Enables caching of CPU samples collected during application startup.
266
90
cachedUserTags: cacheStartupProfile
267
91
? const < String > ['AppStartUp' ]
268
92
: const < String > [],
269
- google3WorkspaceRoot: google3WorkspaceRoot,
270
93
devToolsServerAddress: devToolsServerAddress,
94
+ google3WorkspaceRoot: google3WorkspaceRoot != null
95
+ ? Uri .parse (google3WorkspaceRoot)
96
+ : null ,
97
+ dartExecutable: globals.artifacts! .getArtifactPath (
98
+ Artifact .engineDartBinary,
99
+ ),
271
100
);
272
- final io.Process ? process = _ddsInstance? .process;
273
101
274
102
// Complete the future if the DDS process is null, which happens in
275
103
// testing.
276
- if (process != null ) {
277
- unawaited (process.exitCode.whenComplete (completeFuture));
278
- }
104
+ unawaited (_ddsInstance! .done.whenComplete (completeFuture));
279
105
} on DartDevelopmentServiceException catch (e) {
280
106
_logger.printTrace ('Warning: Failed to start DDS: ${e .message }' );
281
107
if (e is ExistingDartDevelopmentServiceException ) {
@@ -294,7 +120,7 @@ class DartDevelopmentService with DartDevelopmentServiceLocalOperationsMixin {
294
120
}
295
121
}
296
122
297
- void shutdown () => _ddsInstance? .process ? . kill ();
123
+ void shutdown () => _ddsInstance? .shutdown ();
298
124
}
299
125
300
126
/// Contains common functionality that can be used with any implementation of
0 commit comments