Skip to content
4 changes: 3 additions & 1 deletion webdev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
## 3.7.2-wip
## 3.7.2

- Fixed duplicate app logs on page refresh by preventing multiple stdout listeners for the same appId.
- Adds `--offline` flag [#2483](https://github.com/dart-lang/webdev/pull/2483).
- Support the `--hostname` flag when the `--tls-cert-key` and `--tls-cert-chain` flags are present [#2588](https://github.com/dart-lang/webdev/pull/2588).
- Update `dwds` constraint to `24.3.11`.

## 3.7.1

Expand Down
87 changes: 57 additions & 30 deletions webdev/lib/src/daemon/app_domain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,46 +63,33 @@ class AppDomain extends Domain {

Future<void> _handleAppConnections(WebDevServer server) async {
final dwds = server.dwds!;

// The connection is established right before `main()` is called.
await for (final appConnection in dwds.connectedApps) {
final appId = appConnection.request.appId;

// Check if we already have an active app state for this appId
if (_appStates.containsKey(appId)) {
// Reuse existing connection, just run main again
appConnection.runMain();
continue;
}

final debugConnection = await dwds.debugConnection(appConnection);
final debugUri = debugConnection.ddsUri ?? debugConnection.uri;
final vmService = await vmServiceConnectUri(debugUri);
final appId = appConnection.request.appId;
unawaited(debugConnection.onDone.then((_) {
sendEvent('app.log', {
'appId': appId,
'log': 'Lost connection to device.',
});
sendEvent('app.stop', {
'appId': appId,
});
daemon.shutdown();
}));

sendEvent('app.start', {
'appId': appId,
'directory': Directory.current.path,
'deviceId': 'chrome',
'launchMode': 'run'
});
// TODO(grouma) - limit the catch to the appropriate error.
try {
await vmService.streamCancel('Stdout');
} catch (_) {}
try {
await vmService.streamListen('Stdout');
} catch (_) {}
try {
vmService.onServiceEvent.listen(_onServiceEvent);
await vmService.streamListen('Service');
} catch (_) {}

// Set up VM service listeners for this appId
// ignore: cancel_subscriptions
final stdOutSub = vmService.onStdoutEvent.listen((log) {
sendEvent('app.log', {
'appId': appId,
'log': utf8.decode(base64.decode(log.bytes!)),
});
});
final stdOutSub = await _setupVmServiceListeners(appId, vmService);

sendEvent('app.debugPort', {
'appId': appId,
'port': debugConnection.port,
Expand All @@ -120,9 +107,19 @@ class AppDomain extends Domain {

appConnection.runMain();

// Handle connection termination - send events first, then cleanup
unawaited(debugConnection.onDone.whenComplete(() {
appState.dispose();
_appStates.remove(appId);
sendEvent('app.log', {
'appId': appId,
'log': 'Lost connection to device.',
});
sendEvent('app.stop', {
'appId': appId,
});
daemon.shutdown();

// Clean up app resources
_cleanupAppConnection(appId, appState);
}));
}

Expand Down Expand Up @@ -223,6 +220,36 @@ class AppDomain extends Domain {
return true;
}

/// Sets up VM service listeners for the given appId.
/// Returns the stdout subscription.
Future<StreamSubscription<Event>> _setupVmServiceListeners(
String appId, VmService vmService) async {
try {
vmService.onServiceEvent.listen(_onServiceEvent);
await vmService.streamListen(EventStreams.kService);
} catch (_) {}

// ignore: cancel_subscriptions
final stdoutSubscription = vmService.onStdoutEvent.listen((log) {
sendEvent('app.log', {
'appId': appId,
'log': utf8.decode(base64.decode(log.bytes!)),
});
});

try {
await vmService.streamListen(EventStreams.kStdout);
} catch (_) {}

return stdoutSubscription;
}

/// Cleans up an app connection and its associated listeners.
void _cleanupAppConnection(String appId, _AppState appState) {
appState.dispose();
_appStates.remove(appId);
}

@override
void dispose() {
_isShutdown = true;
Expand Down
2 changes: 1 addition & 1 deletion webdev/lib/src/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions webdev/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: webdev
# Every time this changes you need to run `dart run build_runner build`.
version: 3.7.2-wip
version: 3.7.2
# We should not depend on a dev SDK before publishing.
# publish_to: none
description: >-
Expand All @@ -19,7 +19,7 @@ dependencies:
crypto: ^3.0.2
dds: ^4.1.0
# Pin DWDS to avoid dependency conflicts with vm_service:
dwds: 24.3.5
dwds: 24.3.11
http: ^1.0.0
http_multi_server: ^3.2.0
io: ^1.0.3
Expand Down
Loading