Skip to content

Commit 769a056

Browse files
authored
[ DWDS ] Serve DevTools from DDS by default (#2681)
In order to reduce the number of ways DevTools is served across the ecosystem, we're working on serving DevTools from DDS by default in all tools that spawn DDS. This change exposes some new DDS related configuration options that allow for specifying whether or not DevTools should be served via DDS and whether or not an existing DevTools server should be used. The `devToolsLauncher` parameter has been marked as deprecated as it will be removed in a future major release, but will continue to act as the default way to launch DevTools if it is provided. Other DDS related properties that have been merged into the new `DartDevelopmentServiceConfiguration` class are also marked as deprecated.
1 parent a7d3d2f commit 769a056

23 files changed

+326
-200
lines changed

dwds/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 25.1.0
2+
3+
- Added `DartDevelopmentServiceConfiguration` to allow for configuring DDS behavior.
4+
- Added support for serving DevTools via DDS. This will become the sole method of serving
5+
DevTools from DWDS in a future major release.
6+
- Deprecated `spawnDds`, `ddsPort`, and `devToolsLauncher` properties in `DebugSettings`.
7+
- Added `ddsConfiguration` to `DebugSettings`.
8+
19
## 25.0.4
210

311
### Bug Fixes:

dwds/lib/dart_web_debug_service.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,20 @@ class Dwds {
115115
}
116116
}
117117

118+
// TODO(bkonyi): only allow for serving DevTools via DDS.
119+
// ignore: deprecated_member_use_from_same_package
118120
final devToolsLauncher = debugSettings.devToolsLauncher;
119-
if (devToolsLauncher != null) {
121+
Uri? launchedDevToolsUri;
122+
if (devToolsLauncher != null &&
123+
// If DDS is configured to serve DevTools, use its instance.
124+
!debugSettings.ddsConfiguration.serveDevTools) {
120125
devTools = await devToolsLauncher(appMetadata.hostname);
121-
final uri = Uri(
126+
launchedDevToolsUri = Uri(
122127
scheme: 'http',
123128
host: devTools.hostname,
124129
port: devTools.port,
125130
);
126-
_logger.info('Serving DevTools at $uri\n');
131+
_logger.info('Serving DevTools at $launchedDevToolsUri\n');
127132
}
128133

129134
final injected = DwdsInjector(extensionUri: extensionUri);
@@ -140,8 +145,17 @@ class Dwds {
140145
debugSettings.useSseForInjectedClient,
141146
debugSettings.expressionCompiler,
142147
injected,
143-
debugSettings.spawnDds,
144-
debugSettings.ddsPort,
148+
DartDevelopmentServiceConfiguration(
149+
// This technically isn't correct, but DartDevelopmentServiceConfiguration.enable
150+
// is true by default, so this won't break unmigrated tools.
151+
// ignore: deprecated_member_use_from_same_package
152+
enable: debugSettings.spawnDds && debugSettings.ddsConfiguration.enable,
153+
// ignore: deprecated_member_use_from_same_package
154+
port: debugSettings.ddsPort ?? debugSettings.ddsConfiguration.port,
155+
devToolsServerAddress:
156+
launchedDevToolsUri ??
157+
debugSettings.ddsConfiguration.devToolsServerAddress,
158+
),
145159
debugSettings.launchDevToolsInNewWindow,
146160
useWebSocketConnection: useDwdsWebSocketConnection,
147161
);

dwds/lib/dwds.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export 'src/config/tool_configuration.dart'
77
show
88
AppMetadata,
99
UrlEncoder,
10+
DartDevelopmentServiceConfiguration,
1011
DevToolsLauncher,
1112
DebugSettings,
1213
ToolConfiguration;

dwds/lib/src/config/tool_configuration.dart

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ typedef UrlEncoder = Future<String> Function(String url);
5151

5252
typedef DevToolsLauncher = Future<DevTools> Function(String hostname);
5353

54+
class DartDevelopmentServiceConfiguration {
55+
const DartDevelopmentServiceConfiguration({
56+
this.enable = true,
57+
this.port,
58+
this.serveDevTools = true,
59+
this.devToolsServerAddress,
60+
});
61+
62+
final bool enable;
63+
final int? port;
64+
final bool serveDevTools;
65+
final Uri? devToolsServerAddress;
66+
}
67+
5468
/// Debug settings for the connected app.
5569
///
5670
/// These are set by the code runner and passed to DWDS on start up.
@@ -60,28 +74,41 @@ class DebugSettings {
6074
final bool useSseForDebugProxy;
6175
final bool useSseForDebugBackend;
6276
final bool useSseForInjectedClient;
77+
78+
@Deprecated('Use ddsConfiguration instead.')
6379
final bool spawnDds;
80+
@Deprecated('Use ddsConfiguration instead.')
6481
final int? ddsPort;
6582
final bool enableDevToolsLaunch;
6683
final bool launchDevToolsInNewWindow;
6784
final bool emitDebugEvents;
85+
@Deprecated(
86+
'Use ddsConfigurationInstead. DevTools will eventually only be '
87+
'served via DDS.',
88+
)
6889
final DevToolsLauncher? devToolsLauncher;
6990
final ExpressionCompiler? expressionCompiler;
7091
final UrlEncoder? urlEncoder;
92+
final DartDevelopmentServiceConfiguration ddsConfiguration;
7193

7294
const DebugSettings({
7395
this.enableDebugging = true,
7496
this.enableDebugExtension = false,
7597
this.useSseForDebugProxy = true,
7698
this.useSseForDebugBackend = true,
7799
this.useSseForInjectedClient = true,
78-
this.spawnDds = true,
79-
this.ddsPort,
100+
@Deprecated('Use ddsConfiguration instead.') this.spawnDds = true,
101+
@Deprecated('Use ddsConfiguration instead.') this.ddsPort,
80102
this.enableDevToolsLaunch = true,
81103
this.launchDevToolsInNewWindow = true,
82104
this.emitDebugEvents = true,
105+
@Deprecated(
106+
'Use ddsConfigurationInstead. DevTools will eventually only be '
107+
'served via DDS.',
108+
)
83109
this.devToolsLauncher,
84110
this.expressionCompiler,
85111
this.urlEncoder,
112+
this.ddsConfiguration = const DartDevelopmentServiceConfiguration(),
86113
});
87114
}

dwds/lib/src/connections/debug_connection.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,12 @@ class DebugConnection {
3535
/// The endpoint of the Dart VM Service.
3636
String get uri => _appDebugServices.debugService.uri;
3737

38-
// The endpoint of the Dart Development Service (DDS).
38+
/// The endpoint of the Dart Development Service (DDS).
3939
String? get ddsUri => _appDebugServices.ddsUri?.toString();
4040

41+
/// The endpoint of the Dart DevTools instance.
42+
String? get devToolsUri => _appDebugServices.devToolsUri?.toString();
43+
4144
/// A client of the Dart VM Service with DWDS specific extensions.
4245
VmService get vmService => _appDebugServices.dwdsVmClient.client;
4346

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import 'dart:async';
66
import 'dart:convert';
77
import 'dart:io';
88

9+
import 'package:collection/collection.dart';
10+
import 'package:dds/dds_launcher.dart';
911
import 'package:dwds/data/build_result.dart';
1012
import 'package:dwds/data/connect_request.dart';
1113
import 'package:dwds/data/debug_event.dart';
@@ -70,8 +72,7 @@ class DevHandler {
7072
final UrlEncoder? _urlEncoder;
7173
final bool _useSseForDebugProxy;
7274
final bool _useSseForInjectedClient;
73-
final bool _spawnDds;
74-
final int? _ddsPort;
75+
final DartDevelopmentServiceConfiguration _ddsConfig;
7576
final bool _launchDevToolsInNewWindow;
7677
final ExpressionCompiler? _expressionCompiler;
7778
final DwdsInjector _injected;
@@ -97,8 +98,8 @@ class DevHandler {
9798
this._useSseForInjectedClient,
9899
this._expressionCompiler,
99100
this._injected,
100-
this._spawnDds,
101-
this._ddsPort,
101+
102+
this._ddsConfig,
102103
this._launchDevToolsInNewWindow, {
103104
this.useWebSocketConnection = false,
104105
}) {
@@ -251,8 +252,7 @@ class DevHandler {
251252
// This will provide a websocket based service.
252253
useSse: false,
253254
expressionCompiler: _expressionCompiler,
254-
spawnDds: _spawnDds,
255-
ddsPort: _ddsPort,
255+
ddsConfig: _ddsConfig,
256256
);
257257
}
258258

@@ -451,7 +451,7 @@ class DevHandler {
451451
AppConnection appConnection,
452452
SocketConnection sseConnection,
453453
) async {
454-
if (_devTools == null) {
454+
if (_devTools == null && !_ddsConfig.serveDevTools) {
455455
sseConnection.sink.add(
456456
jsonEncode(
457457
serializers.serialize(
@@ -548,6 +548,7 @@ class DevHandler {
548548
await _launchDevTools(
549549
chromeProxy.remoteDebugger,
550550
_constructDevToolsUri(
551+
appServices,
551552
appServices.debugService.uri,
552553
ideQueryParam: 'Dwds',
553554
),
@@ -853,21 +854,21 @@ class DevHandler {
853854
ChromeDebugService debugService,
854855
) async {
855856
final dwdsStats = DwdsStats();
856-
Uri? ddsUri;
857-
if (_spawnDds) {
858-
final dds = await debugService.startDartDevelopmentService();
859-
ddsUri = dds.wsUri;
857+
DartDevelopmentServiceLauncher? dds;
858+
if (_ddsConfig.enable) {
859+
dds = await debugService.startDartDevelopmentService();
860860
}
861861
final vmClient = await ChromeDwdsVmClient.create(
862862
debugService,
863863
dwdsStats,
864-
ddsUri,
864+
dds?.wsUri,
865865
);
866866
final appDebugService = ChromeAppDebugServices(
867867
debugService,
868868
vmClient,
869869
dwdsStats,
870-
ddsUri,
870+
dds?.wsUri,
871+
dds?.devToolsUri,
871872
);
872873
final encodedUri = await debugService.encodedUri;
873874
_logger.info('Debug service listening on $encodedUri\n');
@@ -985,8 +986,7 @@ class DevHandler {
985986
},
986987
useSse: _useSseForDebugProxy,
987988
expressionCompiler: _expressionCompiler,
988-
spawnDds: _spawnDds,
989-
ddsPort: _ddsPort,
989+
ddsConfig: _ddsConfig,
990990
);
991991
appServices = await _createAppDebugServices(debugService);
992992
extensionDebugger.sendEvent('dwds.debugUri', debugService.uri);
@@ -1026,27 +1026,17 @@ class DevHandler {
10261026
emitEvent(DwdsEvent.devtoolsLaunch());
10271027
// Send the DevTools URI to the Dart Debug Extension so that it can open it:
10281028
final devToolsUri = _constructDevToolsUri(
1029+
appServices,
10291030
encodedUri,
10301031
ideQueryParam: 'ChromeDevTools',
10311032
);
10321033
return extensionDebugger.sendEvent('dwds.devtoolsUri', devToolsUri);
10331034
}
10341035

1035-
DevTools _ensureDevTools() {
1036-
final devTools = _devTools;
1037-
if (devTools == null) {
1038-
throw StateError('DevHandler: DevTools is not available');
1039-
}
1040-
return devTools;
1041-
}
1042-
10431036
Future<void> _launchDevTools(
10441037
RemoteDebugger remoteDebugger,
10451038
String devToolsUri,
10461039
) async {
1047-
// TODO(annagrin): move checking whether devtools should be started
1048-
// and the creation of the uri logic here so it is easier to follow.
1049-
_ensureDevTools();
10501040
// TODO(grouma) - We may want to log the debugServiceUri if we don't launch
10511041
// DevTools so that users can manually connect.
10521042
emitEvent(DwdsEvent.devtoolsLaunch());
@@ -1057,20 +1047,28 @@ class DevHandler {
10571047
}
10581048

10591049
String _constructDevToolsUri(
1060-
String debugServiceUri, {
1050+
AppDebugServices appDebugServices,
1051+
String serviceUri, {
10611052
String ideQueryParam = '',
10621053
}) {
1063-
final devTools = _ensureDevTools();
1064-
return Uri(
1065-
scheme: 'http',
1066-
host: devTools.hostname,
1067-
port: devTools.port,
1068-
path: 'debugger',
1069-
queryParameters: {
1070-
'uri': debugServiceUri,
1071-
if (ideQueryParam.isNotEmpty) 'ide': ideQueryParam,
1072-
},
1073-
).toString();
1054+
final devToolsUri = _devTools?.uri ?? appDebugServices.devToolsUri;
1055+
if (devToolsUri == null) {
1056+
throw StateError('DevHandler: DevTools is not available');
1057+
}
1058+
return devToolsUri
1059+
.replace(
1060+
pathSegments: [
1061+
// Strips any trailing slashes from the original path
1062+
...devToolsUri.pathSegments.whereNot((e) => e.isEmpty),
1063+
'debugger',
1064+
],
1065+
queryParameters: {
1066+
...devToolsUri.queryParameters,
1067+
'uri': serviceUri,
1068+
if (ideQueryParam.isNotEmpty) 'ide': ideQueryParam,
1069+
},
1070+
)
1071+
.toString();
10741072
}
10751073

10761074
static void _maybeEmitDwdsAttachEvent(DevToolsRequest request) {

dwds/lib/src/injected/client.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dwds/lib/src/servers/devtools.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class DevTools {
1010
final int port;
1111
final HttpServer _server;
1212

13+
Uri get uri => Uri(scheme: 'http', host: hostname, port: port);
14+
1315
/// Null until [close] is called.
1416
///
1517
/// All subsequent calls to [close] will return this future.

dwds/lib/src/services/app_debug_services.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ abstract class AppDebugServices {
1313
DwdsVmClient get dwdsVmClient;
1414
DwdsStats? get dwdsStats;
1515
Uri? get ddsUri;
16+
Uri? get devToolsUri;
1617
String? get connectedInstanceId;
1718
set connectedInstanceId(String? id);
1819
Future<void> close();
@@ -25,6 +26,7 @@ class ChromeAppDebugServices implements AppDebugServices {
2526
final ChromeDwdsVmClient _dwdsVmClient;
2627
final DwdsStats _dwdsStats;
2728
final Uri? _ddsUri;
29+
final Uri? _devToolsUri;
2830
Future<void>? _closed;
2931
String? _connectedInstanceId;
3032

@@ -33,6 +35,7 @@ class ChromeAppDebugServices implements AppDebugServices {
3335
this._dwdsVmClient,
3436
this._dwdsStats,
3537
this._ddsUri,
38+
this._devToolsUri,
3639
);
3740

3841
@override
@@ -47,6 +50,9 @@ class ChromeAppDebugServices implements AppDebugServices {
4750
@override
4851
Uri? get ddsUri => _ddsUri;
4952

53+
@override
54+
Uri? get devToolsUri => _devToolsUri;
55+
5056
@override
5157
String? get connectedInstanceId => _connectedInstanceId;
5258

@@ -81,7 +87,10 @@ class WebSocketAppDebugServices implements AppDebugServices {
8187
@override
8288
DwdsStats? get dwdsStats => null;
8389
@override
90+
// TODO(bkonyi): DDS should still start in WebSocket mode.
8491
Uri? get ddsUri => null;
92+
@override
93+
Uri? get devToolsUri => null;
8594

8695
@override
8796
ProxyService get proxyService => _debugService.webSocketProxyService;

0 commit comments

Comments
 (0)