Skip to content

Commit

Permalink
Merge branch 'master' into feat/lints-4-0
Browse files Browse the repository at this point in the history
  • Loading branch information
parlough authored May 30, 2024
2 parents 30d68f2 + a97c2a1 commit cd80335
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 17 deletions.
2 changes: 2 additions & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Fix bug where debugging clients are not aware of service extensions when connecting to a new web app. - [#2388](https://github.com/dart-lang/webdev/pull/2388)
- Respect the value of `pause_isolates_on_start` during page-refreshes. - [#2431](https://github.com/dart-lang/webdev/pull/2431)
- Fix issue where DAP clients wouldn't resume after a restart. - [#2441](https://github.com/dart-lang/webdev/pull/2441)
- Add implementation for the VM Service's `getFlagList` API. - [#2438](https://github.com/dart-lang/webdev/pull/2438)

## 24.0.0

Expand Down
26 changes: 24 additions & 2 deletions dwds/lib/src/dwds_vm_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ typedef VmResponse = Map<String, Object?>;

enum _NamespacedServiceExtension {
extDwdsEmitEvent(method: 'ext.dwds.emitEvent'),
extDwdsReload(method: 'ext.dwds.reload'),
extDwdsRestart(method: 'ext.dwds.restart'),
extDwdsScreenshot(method: 'ext.dwds.screenshot'),
extDwdsSendEvent(method: 'ext.dwds.sendEvent'),
Expand Down Expand Up @@ -77,6 +78,8 @@ class DwdsVmClient {
final requestSink = requestController.sink;
final requestStream = requestController.stream;

final clientCompleter = Completer<VmService>();

_setUpVmServerConnection(
chromeProxyService: chromeProxyService,
debugService: debugService,
Expand All @@ -85,6 +88,7 @@ class DwdsVmClient {
requestStream: requestStream,
requestSink: requestSink,
dwdsStats: dwdsStats,
clientFuture: clientCompleter.future,
);

final client = ddsUri == null
Expand All @@ -97,6 +101,10 @@ class DwdsVmClient {
ddsUri: ddsUri,
);

if (!clientCompleter.isCompleted) {
clientCompleter.complete(client);
}

final dwdsVmClient =
DwdsVmClient(client, requestController, responseController);

Expand Down Expand Up @@ -158,12 +166,14 @@ class DwdsVmClient {
required StreamSink<VmResponse> responseSink,
required Stream<VmRequest> requestStream,
required StreamSink<VmRequest> requestSink,
required Future<VmService> clientFuture,
}) {
responseStream.listen((request) async {
final response = await _maybeHandleServiceExtensionRequest(
request,
chromeProxyService: chromeProxyService,
dwdsStats: dwdsStats,
clientFuture: clientFuture,
);
if (response != null) {
requestSink.add(response);
Expand All @@ -187,15 +197,19 @@ class DwdsVmClient {
VmResponse request, {
required ChromeProxyService chromeProxyService,
required DwdsStats dwdsStats,
required Future<VmService> clientFuture,
}) async {
VmRequest? response;
final method = request['method'];
if (method == _NamespacedServiceExtension.flutterListViews.method) {
response = await _flutterListViewsHandler(chromeProxyService);
} else if (method == _NamespacedServiceExtension.extDwdsEmitEvent.method) {
response = _extDwdsEmitEventHandler(request);
} else if (method == _NamespacedServiceExtension.extDwdsReload.method) {
response = await _extDwdsReloadHandler(chromeProxyService);
} else if (method == _NamespacedServiceExtension.extDwdsRestart.method) {
response = await _extDwdsRestartHandler(chromeProxyService);
final client = await clientFuture;
response = await _extDwdsRestartHandler(chromeProxyService, client);
} else if (method == _NamespacedServiceExtension.extDwdsSendEvent.method) {
response = await _extDwdsSendEventHandler(request, dwdsStats);
} else if (method == _NamespacedServiceExtension.extDwdsScreenshot.method) {
Expand Down Expand Up @@ -265,13 +279,21 @@ class DwdsVmClient {
return {'result': Success().toJson()};
}

static Future<Map<String, Object>> _extDwdsRestartHandler(
static Future<Map<String, Object>> _extDwdsReloadHandler(
ChromeProxyService chromeProxyService,
) async {
await _fullReload(chromeProxyService);
return {'result': Success().toJson()};
}

static Future<Map<String, Object>> _extDwdsRestartHandler(
ChromeProxyService chromeProxyService,
VmService client,
) async {
await _hotRestart(chromeProxyService, client);
return {'result': Success().toJson()};
}

static Future<void> _registerServiceExtensions({
required VmService client,
required ChromeProxyService chromeProxyService,
Expand Down
58 changes: 43 additions & 15 deletions dwds/lib/src/services/chrome_proxy_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,20 @@ class ChromeProxyService implements VmServiceInterface {

StreamSubscription<ConsoleAPIEvent>? _consoleSubscription;

bool _pauseIsolatesOnStart = false;
/// The flags that can be set at runtime via [setFlag] and their respective
/// values.
final Map<String, bool> _currentVmServiceFlags = {
_pauseIsolatesOnStartFlag: false,
};

/// The value of the [_pauseIsolatesOnStartFlag].
///
/// This value can be updated at runtime via [setFlag].
bool get pauseIsolatesOnStart => _pauseIsolatesOnStart;
bool get pauseIsolatesOnStart =>
_currentVmServiceFlags[_pauseIsolatesOnStartFlag] ?? false;

/// Whether or not the connected app has a pending restart.
bool get hasPendingRestart => _resumeAfterRestartEventsController.hasListener;

final _resumeAfterRestartEventsController =
StreamController<String>.broadcast();
Expand Down Expand Up @@ -353,6 +361,20 @@ class ChromeProxyService implements VmServiceInterface {
);
}

// If the new isolate was created as part of a restart, send a
// kPausePostRequest event to notify client that the app is paused so that
// it can resume:
if (hasPendingRestart) {
_streamNotify(
'Debug',
Event(
kind: EventKind.kPausePostRequest,
timestamp: timestamp,
isolate: isolateRef,
),
);
}

// The service is considered initialized when the first isolate is created.
if (!_initializedCompleter.isCompleted) _initializedCompleter.complete();
}
Expand Down Expand Up @@ -758,9 +780,22 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
}

@override
Future<FlagList> getFlagList() async {
// VM flags do not apply to web apps.
return FlagList(flags: []);
Future<FlagList> getFlagList() {
return wrapInErrorHandlerAsync(
'getFlagList',
_getFlagList,
);
}

Future<FlagList> _getFlagList() {
final flags = _currentVmServiceFlags.entries.map<Flag>(
(entry) => Flag(
name: entry.key,
valueAsString: '${entry.value}',
),
);

return Future.value(FlagList(flags: flags.toList()));
}

@override
Expand Down Expand Up @@ -1214,14 +1249,12 @@ ${globalToolConfiguration.loadStrategy.loadModuleSnippet}("dart_sdk").developer.
);

Future<Success> _setFlag(String name, String value) async {
if (!_supportedVmServiceFlags.contains(name)) {
if (!_currentVmServiceFlags.containsKey(name)) {
return _rpcNotSupportedFuture('setFlag');
}

if (name == _pauseIsolatesOnStartFlag) {
assert(value == 'true' || value == 'false');
_pauseIsolatesOnStart = value == 'true';
}
assert(value == 'true' || value == 'false');
_currentVmServiceFlags[name] = value == 'true';

return Success();
}
Expand Down Expand Up @@ -1699,8 +1732,3 @@ const _stderrTypes = ['error'];
const _stdoutTypes = ['log', 'info', 'warning'];

const _pauseIsolatesOnStartFlag = 'pause_isolates_on_start';

/// The flags that can be set at runtime via [setFlag].
const _supportedVmServiceFlags = {
_pauseIsolatesOnStartFlag,
};
32 changes: 32 additions & 0 deletions dwds/test/chrome_proxy_service_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,38 @@ void main() {
});
});

group('getFlagList', () {
List<String> stringifyFlags(FlagList flagList) {
return flagList.flags
?.map((flag) => '${flag.name} -> ${flag.valueAsString}')
.toList() ??
[];
}

test('returns expected default values', () async {
final service = context.service;
final flagList = await service.getFlagList();
expect(
stringifyFlags(flagList),
containsAll([
'pause_isolates_on_start -> false',
]),
);
});

test('returns any modified flag values', () async {
final service = context.service;
await service.setFlag('pause_isolates_on_start', 'true');
final flagList = await service.getFlagList();
expect(
stringifyFlags(flagList),
containsAll([
'pause_isolates_on_start -> true',
]),
);
});
});

group('streamListen/onEvent', () {
late ChromeProxyService service;

Expand Down

0 comments on commit cd80335

Please sign in to comment.