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
70 changes: 49 additions & 21 deletions webdev/lib/src/daemon/app_domain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class AppDomain extends Domain {

final _appStates = <String, _AppState>{};

// Prevents duplicate stdout listeners for the same appId
final _activeListeners = <String>{};

// Mapping from service name to service method.
final Map<String, String> _registeredMethodsForService = <String, String>{};

Expand Down Expand Up @@ -85,24 +88,11 @@ class AppDomain extends Domain {
'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 (only once per appId to prevent duplicates)
// 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 @@ -121,8 +111,7 @@ class AppDomain extends Domain {
appConnection.runMain();

unawaited(debugConnection.onDone.whenComplete(() {
appState.dispose();
_appStates.remove(appId);
_cleanupAppConnection(appId, appState);
}));
}

Expand Down Expand Up @@ -223,20 +212,59 @@ class AppDomain extends Domain {
return true;
}

/// Sets up VM service listeners for the given appId if not already active.
/// Returns the stdout subscription if created, null otherwise.
Future<StreamSubscription<Event>?> _setupVmServiceListeners(
String appId, VmService vmService) async {
if (_activeListeners.contains(appId)) {
return null; // Already listening for this appId
}

_activeListeners.add(appId);

// 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 (_) {}

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

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

@override
void dispose() {
_isShutdown = true;
for (final state in _appStates.values) {
state.dispose();
}
_appStates.clear();
_activeListeners.clear();
}
}

class _AppState {
final DebugConnection _debugConnection;
final StreamSubscription<BuildResult> _resultSub;
final StreamSubscription<Event> _stdOutSub;
final StreamSubscription<Event>? _stdOutSub;

bool _isDisposed = false;

Expand All @@ -247,7 +275,7 @@ class _AppState {
void dispose() {
if (_isDisposed) return;
_isDisposed = true;
_stdOutSub.cancel();
_stdOutSub?.cancel();
_resultSub.cancel();
_debugConnection.close();
}
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