Skip to content

Commit be9a6dc

Browse files
author
Anna Gringauze
committed
Add ext.dwds.sendEvent service extension to implement DEBUGGER_READY event
1 parent 53c067b commit be9a6dc

File tree

5 files changed

+85
-58
lines changed

5 files changed

+85
-58
lines changed

dwds/lib/src/dwds_vm_client.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ class DwdsVmClient {
4040
await client.dispose();
4141
}();
4242

43-
static Future<DwdsVmClient> create(DebugService debugService) async {
43+
static Future<DwdsVmClient> create(
44+
DebugService debugService, DwdsStats dwdsStats) async {
4445
// Set up hot restart as an extension.
4546
var requestController = StreamController<Map<String, Object>>();
4647
var responseController = StreamController<Map<String, Object>>();
@@ -154,6 +155,20 @@ class DwdsVmClient {
154155
});
155156
await client.registerService('ext.dwds.screenshot', 'DWDS');
156157

158+
client.registerServiceCallback('ext.dwds.sendEvent', (event) async {
159+
var type = event['type'] as String;
160+
switch (type) {
161+
case 'DevtoolsReady':
162+
{
163+
emitEvent(DwdsEvent.debuggerReady(DateTime.now()
164+
.difference(dwdsStats.debuggerStart)
165+
.inMilliseconds));
166+
}
167+
}
168+
return {'result': Success().toJson()};
169+
});
170+
await client.registerService('ext.dwds.sendEvent', 'DWDS');
171+
157172
client.registerServiceCallback('ext.dwds.emitEvent', (event) async {
158173
emitEvent(DwdsEvent(
159174
event['type'] as String, event['payload'] as Map<String, dynamic>));

dwds/lib/src/handlers/dev_handler.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ class DevHandler {
209209
useSse: false,
210210
expressionCompiler: _expressionCompiler,
211211
spawnDds: _spawnDds,
212-
dwdsStats: DwdsStats(DateTime.now()),
213212
);
214213
}
215214

@@ -223,12 +222,13 @@ class DevHandler {
223222
}
224223

225224
Future<AppDebugServices> loadAppServices(AppConnection appConnection) async {
225+
var dwdsStats = DwdsStats(DateTime.now());
226226
var appId = appConnection.request.appId;
227227
if (_servicesByAppId[appId] == null) {
228228
var debugService = await _startLocalDebugService(
229229
await _chromeConnection(), appConnection);
230230
var appServices = await _createAppDebugServices(
231-
appConnection.request.appId, debugService);
231+
appConnection.request.appId, debugService, dwdsStats);
232232
unawaited(appServices.chromeProxyService.remoteDebugger.onClose.first
233233
.whenComplete(() async {
234234
await appServices.close();
@@ -435,8 +435,8 @@ class DevHandler {
435435
}
436436

437437
Future<AppDebugServices> _createAppDebugServices(
438-
String appId, DebugService debugService) async {
439-
var webdevClient = await DwdsVmClient.create(debugService);
438+
String appId, DebugService debugService, DwdsStats dwdsStats) async {
439+
var webdevClient = await DwdsVmClient.create(debugService, dwdsStats);
440440
if (_spawnDds) {
441441
await debugService.startDartDevelopmentService();
442442
}
@@ -464,6 +464,7 @@ class DevHandler {
464464
// Waits for a `DevToolsRequest` to be sent from the extension background
465465
// when the extension is clicked.
466466
extensionDebugger.devToolsRequestStream.listen((devToolsRequest) async {
467+
var dwdsStats = DwdsStats(DateTime.now());
467468
var connection = _appConnectionByAppId[devToolsRequest.appId];
468469
if (connection == null) {
469470
// TODO(grouma) - Ideally we surface this warning to the extension so
@@ -491,10 +492,12 @@ class DevHandler {
491492
useSse: _useSseForDebugProxy,
492493
expressionCompiler: _expressionCompiler,
493494
spawnDds: _spawnDds,
494-
dwdsStats: DwdsStats(DateTime.now()),
495495
);
496-
var appServices =
497-
await _createAppDebugServices(devToolsRequest.appId, debugService);
496+
var appServices = await _createAppDebugServices(
497+
devToolsRequest.appId,
498+
debugService,
499+
dwdsStats,
500+
);
498501
var encodedUri = await debugService.encodedUri;
499502
extensionDebugger.sendEvent('dwds.encodedUri', encodedUri);
500503
unawaited(appServices.chromeProxyService.remoteDebugger.onClose.first

dwds/lib/src/services/chrome_proxy_service.dart

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ class ChromeProxyService implements VmServiceInterface {
9595
final ExpressionCompiler _compiler;
9696
ExpressionEvaluator _expressionEvaluator;
9797

98-
final DwdsStats _dwdsStats;
99-
10098
bool terminatingIsolates = false;
10199

102100
ChromeProxyService._(
@@ -109,7 +107,6 @@ class ChromeProxyService implements VmServiceInterface {
109107
this._skipLists,
110108
this.executionContext,
111109
this._compiler,
112-
this._dwdsStats,
113110
) {
114111
var debugger = Debugger.create(
115112
remoteDebugger,
@@ -123,14 +120,14 @@ class ChromeProxyService implements VmServiceInterface {
123120
}
124121

125122
static Future<ChromeProxyService> create(
126-
RemoteDebugger remoteDebugger,
127-
String tabUrl,
128-
AssetReader assetReader,
129-
LoadStrategy loadStrategy,
130-
AppConnection appConnection,
131-
ExecutionContext executionContext,
132-
ExpressionCompiler expressionCompiler,
133-
DwdsStats dwdsStats) async {
123+
RemoteDebugger remoteDebugger,
124+
String tabUrl,
125+
AssetReader assetReader,
126+
LoadStrategy loadStrategy,
127+
AppConnection appConnection,
128+
ExecutionContext executionContext,
129+
ExpressionCompiler expressionCompiler,
130+
) async {
134131
final vm = VM(
135132
name: 'ChromeDebugProxy',
136133
operatingSystem: Platform.operatingSystem,
@@ -159,7 +156,6 @@ class ChromeProxyService implements VmServiceInterface {
159156
skipLists,
160157
executionContext,
161158
expressionCompiler,
162-
dwdsStats,
163159
);
164160
unawaited(service.createIsolate(appConnection));
165161
return service;
@@ -548,7 +544,7 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension(
548544
int endTokenPos,
549545
bool forceCompile,
550546
bool reportLines}) async {
551-
var result = await _captureElapsedTime(() async {
547+
return await _captureElapsedTime(() async {
552548
await isInitialized;
553549
return await _inspector?.getSourceReport(isolateId, reports,
554550
scriptId: scriptId,
@@ -557,18 +553,6 @@ ${globalLoadStrategy.loadModuleSnippet}("dart_sdk").developer.invokeExtension(
557553
forceCompile: forceCompile,
558554
reportLines: reportLines);
559555
}, (result) => DwdsEvent.getSourceReport());
560-
561-
// This metric is an approximation of the "debugger is ready"
562-
// time when using devtools. It currently has flaws:
563-
// - it does not make sense for other debugger uses
564-
// - is also can be invalidated later.
565-
// Issue: https://github.com/dart-lang/webdev/issues/1406
566-
if (_dwdsStats.isFirstDebuggerReady()) {
567-
emitEvent(DwdsEvent.debuggerReady(
568-
DateTime.now().difference(_dwdsStats.debuggerStart).inMilliseconds));
569-
}
570-
571-
return result;
572556
}
573557

574558
/// Returns the current stack.

dwds/lib/src/services/debug_service.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import 'package:web_socket_channel/web_socket_channel.dart';
2323
import '../../dwds.dart';
2424
import '../debugging/execution_context.dart';
2525
import '../debugging/remote_debugger.dart';
26-
import '../events.dart';
2726
import '../utilities/shared.dart';
2827
import 'chrome_proxy_service.dart';
2928

@@ -214,8 +213,7 @@ class DebugService {
214213
void Function(Map<String, dynamic>) onResponse,
215214
bool spawnDds = true,
216215
bool useSse,
217-
ExpressionCompiler expressionCompiler,
218-
DwdsStats dwdsStats}) async {
216+
ExpressionCompiler expressionCompiler}) async {
219217
useSse ??= false;
220218
var chromeProxyService = await ChromeProxyService.create(
221219
remoteDebugger,
@@ -224,8 +222,7 @@ class DebugService {
224222
loadStrategy,
225223
appConnection,
226224
executionContext,
227-
expressionCompiler,
228-
dwdsStats);
225+
expressionCompiler);
229226
var authToken = _makeAuthToken();
230227
var serviceExtensionRegistry = ServiceExtensionRegistry();
231228
Handler handler;

dwds/test/events_test.dart

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,57 @@ void main() {
5555
await events;
5656
});
5757

58+
test('emits DEBUGGER_READY event', () async {
59+
// The events stream is a broadcast stream so start listening before the
60+
// action.
61+
var events = expectLater(
62+
context.testServer.dwds.events,
63+
emitsThrough(predicate(
64+
(DwdsEvent event) => event.type == DwdsEventKind.debuggerReady)));
65+
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
66+
await events;
67+
},
68+
skip:
69+
'https://github.com/dart-lang/webdev/issues/1406'); // Not implemented yet.
70+
5871
test('events can be listened to multiple times', () async {
5972
context.testServer.dwds.events.listen((_) {});
6073
context.testServer.dwds.events.listen((_) {});
6174
});
6275

76+
test('can emit event through service extension', () async {
77+
var events = expectLater(
78+
context.testServer.dwds.events,
79+
emitsThrough(predicate((DwdsEvent event) =>
80+
event.type == 'foo-event' && event.payload['data'] == 1234)));
81+
82+
var response = await context.debugConnection.vmService
83+
.callServiceExtension('ext.dwds.emitEvent', args: {
84+
'type': 'foo-event',
85+
'payload': {'data': 1234},
86+
});
87+
expect(response.type, 'Success');
88+
await events;
89+
});
90+
91+
test(
92+
'can receive DevtoolsReady event and emit DEBUGGER_READY '
93+
'event through service extension', () async {
94+
var events = expectLater(
95+
context.testServer.dwds.events,
96+
emitsThrough(predicate((DwdsEvent event) =>
97+
event.type == DwdsEventKind.debuggerReady &&
98+
event.payload['elapsedMilliseconds'] != null)));
99+
100+
var response = await context.debugConnection.vmService
101+
.callServiceExtension('ext.dwds.sendEvent', args: {
102+
'type': 'DevtoolsReady',
103+
'payload': {},
104+
});
105+
expect(response.type, 'Success');
106+
await events;
107+
});
108+
63109
group('evaluate', () {
64110
Isolate isolate;
65111
LibraryRef bootstrap;
@@ -75,21 +121,6 @@ void main() {
75121
setCurrentLogWriter();
76122
});
77123

78-
test('can emit event through service extension', () async {
79-
var events = expectLater(
80-
context.testServer.dwds.events,
81-
emitsThrough(predicate((DwdsEvent event) =>
82-
event.type == 'foo-event' && event.payload['data'] == 1234)));
83-
84-
var response = await context.debugConnection.vmService
85-
.callServiceExtension('ext.dwds.emitEvent', args: {
86-
'type': 'foo-event',
87-
'payload': {'data': 1234},
88-
});
89-
expect(response.type, 'Success');
90-
await events;
91-
});
92-
93124
test('emits EVALUATE events on evaluation success', () async {
94125
var expression = "helloString('world')";
95126
var events = expectLater(
@@ -260,14 +291,11 @@ void main() {
260291
test('emits GET_SOURCE_REPORT events', () async {
261292
var events = expectLater(
262293
context.testServer.dwds.events,
263-
emitsInOrder([
294+
emitsThrough(
264295
predicate((DwdsEvent event) =>
265296
event.type == DwdsEventKind.getSourceReport &&
266297
event.payload['elapsedMilliseconds'] != null),
267-
predicate((DwdsEvent event) =>
268-
event.type == DwdsEventKind.debuggerReady &&
269-
event.payload['elapsedMilliseconds'] != null),
270-
]));
298+
));
271299
await service.getSourceReport(
272300
isolateId, [SourceReportKind.kPossibleBreakpoints],
273301
scriptId: mainScript.id);

0 commit comments

Comments
 (0)