Revert "Make device debuggable if useDwdsWebSocketConnection is true … (#173551)
Reverts #171648 for multiple failing tests
<img width="624" height="347" alt="image"
src="https://github.com/user-attachments/assets/affc7820-bd1a-408a-822c-3bc0df5f985d"
/>
diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
index 9be9111..25173ae 100644
--- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart
@@ -158,17 +158,8 @@
@override
bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;
- /// Device is debuggable if not a WebServer device, or if running with
- /// --start-paused or using DWDS WebSocket connection (WebServer device).
- bool get deviceIsDebuggable =>
- device!.device is! WebServerDevice ||
- debuggingOptions.startPaused ||
- _useDwdsWebSocketConnection;
-
- bool get _useDwdsWebSocketConnection {
- final DevFS? devFS = device?.devFS;
- return devFS is WebDevFS && devFS.useDwdsWebSocketConnection;
- }
+ /// WebServer device is debuggable when running with --start-paused.
+ bool get deviceIsDebuggable => device!.device is! WebServerDevice || debuggingOptions.startPaused;
@override
// Web uses a different plugin registry.
@@ -799,102 +790,86 @@
Uri? websocketUri;
if (supportsServiceProtocol) {
assert(connectDebug != null);
- unawaited(
- connectDebug!.then((connectionResult) async {
- _connectionResult = connectionResult;
- unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
+ _connectionResult = await connectDebug;
+ unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
- void onLogEvent(vmservice.Event event) {
- final String message = processVmServiceMessage(event);
- _logger.printStatus(message);
- }
+ void onLogEvent(vmservice.Event event) {
+ final String message = processVmServiceMessage(event);
+ _logger.printStatus(message);
+ }
- // This flag is needed to manage breakpoints properly.
- if (debuggingOptions.startPaused && debuggingOptions.debuggingEnabled) {
- try {
- final vmservice.Response result = await _vmService.service.setFlag(
- 'pause_isolates_on_start',
- 'true',
- );
- if (result is! vmservice.Success) {
- _logger.printError('setFlag failure: $result');
- }
- } on Exception catch (e) {
- _logger.printError(
- 'Failed to set pause_isolates_on_start=true, proceeding. '
- 'Error: $e',
- );
- }
- }
-
- _stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
- _stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
- _serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
- try {
- await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
- } on vmservice.RPCError {
- // It is safe to ignore this error because we expect an error to be
- // thrown if we're already subscribed.
- }
- try {
- await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
- } on vmservice.RPCError {
- // It is safe to ignore this error because we expect an error to be
- // thrown if we're already subscribed.
- }
- try {
- await _vmService.service.streamListen(vmservice.EventStreams.kService);
- } on vmservice.RPCError {
- // It is safe to ignore this error because we expect an error to be
- // thrown if we're already subscribed.
- }
- try {
- await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
- } on vmservice.RPCError {
- // It is safe to ignore this error because we expect an error to be
- // thrown if we're not already subscribed.
- }
- await setUpVmService(
- reloadSources: (String isolateId, {bool? force, bool? pause}) async {
- await restart(pause: pause);
- },
- device: device!.device,
- flutterProject: flutterProject,
- printStructuredErrorLogMethod: printStructuredErrorLog,
- vmService: _vmService.service,
+ // This flag is needed to manage breakpoints properly.
+ if (debuggingOptions.startPaused && debuggingOptions.debuggingEnabled) {
+ try {
+ final vmservice.Response result = await _vmService.service.setFlag(
+ 'pause_isolates_on_start',
+ 'true',
);
-
- websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
- device!.vmService = _vmService;
-
- // Run main immediately if the app is not started paused or if there
- // is no debugger attached. Otherwise, runMain when a resume event
- // is received.
- if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
- _connectionResult!.appConnection!.runMain();
- } else {
- late StreamSubscription<void> resumeSub;
- resumeSub = _vmService.service.onDebugEvent.listen((vmservice.Event event) {
- if (event.type == vmservice.EventKind.kResume) {
- _connectionResult!.appConnection!.runMain();
- resumeSub.cancel();
- }
- });
+ if (result is! vmservice.Success) {
+ _logger.printError('setFlag failure: $result');
}
+ } on Exception catch (e) {
+ _logger.printError(
+ 'Failed to set pause_isolates_on_start=true, proceeding. '
+ 'Error: $e',
+ );
+ }
+ }
- if (websocketUri != null) {
- if (debuggingOptions.vmserviceOutFile != null) {
- _fileSystem.file(debuggingOptions.vmserviceOutFile)
- ..createSync(recursive: true)
- ..writeAsStringSync(websocketUri.toString());
- }
- _logger.printStatus('Debug service listening on $websocketUri');
- }
- connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));
- }),
+ _stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
+ _stdErrSub = _vmService.service.onStderrEvent.listen(onLogEvent);
+ _serviceSub = _vmService.service.onServiceEvent.listen(_onServiceEvent);
+ try {
+ await _vmService.service.streamListen(vmservice.EventStreams.kStdout);
+ } on vmservice.RPCError {
+ // It is safe to ignore this error because we expect an error to be
+ // thrown if we're already subscribed.
+ }
+ try {
+ await _vmService.service.streamListen(vmservice.EventStreams.kStderr);
+ } on vmservice.RPCError {
+ // It is safe to ignore this error because we expect an error to be
+ // thrown if we're already subscribed.
+ }
+ try {
+ await _vmService.service.streamListen(vmservice.EventStreams.kService);
+ } on vmservice.RPCError {
+ // It is safe to ignore this error because we expect an error to be
+ // thrown if we're already subscribed.
+ }
+ try {
+ await _vmService.service.streamListen(vmservice.EventStreams.kIsolate);
+ } on vmservice.RPCError {
+ // It is safe to ignore this error because we expect an error to be
+ // thrown if we're not already subscribed.
+ }
+ await setUpVmService(
+ reloadSources: (String isolateId, {bool? force, bool? pause}) async {
+ await restart(pause: pause);
+ },
+ device: device!.device,
+ flutterProject: flutterProject,
+ printStructuredErrorLogMethod: printStructuredErrorLog,
+ vmService: _vmService.service,
);
- } else {
- connectionInfoCompleter?.complete(DebugConnectionInfo());
+
+ websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
+ device!.vmService = _vmService;
+
+ // Run main immediately if the app is not started paused or if there
+ // is no debugger attached. Otherwise, runMain when a resume event
+ // is received.
+ if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
+ _connectionResult!.appConnection!.runMain();
+ } else {
+ late StreamSubscription<void> resumeSub;
+ resumeSub = _vmService.service.onDebugEvent.listen((vmservice.Event event) {
+ if (event.type == vmservice.EventKind.kResume) {
+ _connectionResult!.appConnection!.runMain();
+ resumeSub.cancel();
+ }
+ });
+ }
}
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
if (debuggingOptions.enableDevTools) {
@@ -906,8 +881,16 @@
),
);
}
-
+ if (websocketUri != null) {
+ if (debuggingOptions.vmserviceOutFile != null) {
+ _fileSystem.file(debuggingOptions.vmserviceOutFile)
+ ..createSync(recursive: true)
+ ..writeAsStringSync(websocketUri.toString());
+ }
+ _logger.printStatus('Debug service listening on $websocketUri');
+ }
appStartedCompleter?.complete();
+ connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));
if (stayResident) {
await waitForAppToFinish();
} else {
diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml
index 14485a3..fa69ee5 100644
--- a/packages/flutter_tools/pubspec.yaml
+++ b/packages/flutter_tools/pubspec.yaml
@@ -13,7 +13,7 @@
archive: 3.6.1
args: 2.7.0
dds: 5.0.3
- dwds: 24.4.1
+ dwds: 24.4.0
code_builder: 4.10.1
collection: 1.19.1
completion: 1.0.2
@@ -126,4 +126,4 @@
dartdoc:
# Exclude this package from the hosted API docs.
nodoc: true
-# PUBSPEC CHECKSUM: 932agm
+# PUBSPEC CHECKSUM: kav93d
diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
index 00ae682..9895d19 100644
--- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
@@ -1665,9 +1665,7 @@
mainLibName: 'my_app',
packages: <String, String>{'path_provider_linux': '../../path_provider_linux'},
);
- final connectionInfoCompleter = Completer<DebugConnectionInfo>();
- expect(await residentWebRunner.run(connectionInfoCompleter: connectionInfoCompleter), 0);
- await connectionInfoCompleter.future;
+ expect(await residentWebRunner.run(), 0);
final File generatedLocalizationsFile = globals.fs
.directory('lib')
.childDirectory('l10n')
@@ -2058,9 +2056,6 @@
PackageConfig? lastPackageConfig = PackageConfig.empty;
@override
- var useDwdsWebSocketConnection = false;
-
- @override
Future<Uri> create() async {
return baseUri;
}
diff --git a/packages/flutter_tools/test/integration.shard/hot_reload_websocket_test.dart b/packages/flutter_tools/test/integration.shard/hot_reload_websocket_test.dart
deleted file mode 100644
index c28ca83..0000000
--- a/packages/flutter_tools/test/integration.shard/hot_reload_websocket_test.dart
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-@Tags(<String>['flutter-test-driver'])
-library;
-
-import 'dart:async';
-import 'dart:io' as io;
-
-import 'package:file/file.dart';
-import 'package:flutter_tools/src/web/chrome.dart';
-import 'package:flutter_tools/src/web/web_device.dart' show WebServerDevice;
-
-import '../src/common.dart';
-import 'test_data/hot_reload_project.dart';
-import 'test_driver.dart';
-import 'test_utils.dart';
-import 'transition_test_utils.dart';
-
-void main() {
- testAll();
-}
-
-void testAll({List<String> additionalCommandArgs = const <String>[]}) {
- group('WebSocket DWDS connection'
- '${additionalCommandArgs.isEmpty ? '' : ' with args: $additionalCommandArgs'}', () {
- // Test configuration constants
- const debugUrlTimeout = Duration(seconds: 20);
- const appStartTimeout = Duration(seconds: 15);
- const hotReloadTimeout = Duration(seconds: 10);
-
- late Directory tempDir;
- final project = HotReloadProject();
- late FlutterRunTestDriver flutter;
-
- setUp(() async {
- tempDir = createResolvedTempDirectorySync('hot_reload_websocket_test.');
- await project.setUpIn(tempDir);
- flutter = FlutterRunTestDriver(tempDir);
- });
-
- tearDown(() async {
- await flutter.stop();
- tryToDelete(tempDir);
- });
-
- testWithoutContext(
- 'hot reload with headless Chrome WebSocket connection',
- () async {
- debugPrint('Starting WebSocket DWDS test with headless Chrome...');
-
- // Set up listening for app output before starting
- final stdout = StringBuffer();
- final sawDebugUrl = Completer<String>();
- final StreamSubscription<String> subscription = flutter.stdout.listen((String e) {
- stdout.writeln(e);
- // Extract the debug connection URL
- if (e.contains('Waiting for connection from Dart debug extension at http://')) {
- final debugUrlPattern = RegExp(
- r'Waiting for connection from Dart debug extension at (http://[^\s]+)',
- );
- final Match? match = debugUrlPattern.firstMatch(e);
- if (match != null && !sawDebugUrl.isCompleted) {
- sawDebugUrl.complete(match.group(1)!);
- }
- }
- });
-
- io.Process? chromeProcess;
- try {
- // Step 1: Start Flutter app with web-server device (will wait for debug connection)
- debugPrint('Step 1: Starting Flutter app with web-server device...');
- // Start the app but don't wait for it to complete - it won't complete until Chrome connects
- final Future<void> appStartFuture = runFlutterWithWebServerDevice(
- flutter,
- additionalCommandArgs: [...additionalCommandArgs, '--no-web-resources-cdn'],
- );
-
- // Step 2: Wait for DWDS debug URL to be available
- debugPrint('Step 2: Waiting for DWDS debug service URL...');
- final String debugUrl = await sawDebugUrl.future.timeout(
- debugUrlTimeout,
- onTimeout: () {
- throw Exception('DWDS debug URL not found - app may not have started correctly');
- },
- );
- debugPrint('✓ DWDS debug service available at: $debugUrl');
-
- // Step 3: Launch headless Chrome to connect to DWDS
- debugPrint('Step 3: Launching headless Chrome to connect to DWDS...');
- chromeProcess = await _launchHeadlessChrome(debugUrl);
- debugPrint('✓ Headless Chrome launched and connecting to DWDS');
-
- // Step 4: Wait for app to start (Chrome connection established)
- debugPrint('Step 4: Waiting for Flutter app to start after Chrome connection...');
- await appStartFuture.timeout(
- appStartTimeout,
- onTimeout: () {
- throw Exception('App startup did not complete after Chrome connection');
- },
- );
- debugPrint('✓ Flutter app started successfully with WebSocket connection');
-
- // Step 5: Test hot reload functionality
- debugPrint('Step 5: Testing hot reload with WebSocket connection...');
- await flutter.hotReload().timeout(
- hotReloadTimeout,
- onTimeout: () {
- throw Exception('Hot reload timed out');
- },
- );
-
- // Give some time for logs to capture
- await Future<void>.delayed(const Duration(seconds: 2));
-
- final output = stdout.toString();
- expect(output, contains('Reloaded'), reason: 'Hot reload should complete successfully');
- debugPrint('✓ Hot reload completed successfully with WebSocket connection');
-
- // Verify the correct infrastructure was used
- expect(
- output,
- contains('Waiting for connection from Dart debug extension'),
- reason: 'Should wait for debug connection (WebSocket infrastructure)',
- );
- expect(output, contains('web-server'), reason: 'Should use web-server device');
-
- debugPrint('✓ WebSocket DWDS test completed successfully');
- debugPrint('✓ Verified: web-server device + DWDS + WebSocket connection + hot reload');
- } finally {
- await _cleanupResources(chromeProcess, subscription);
- }
- },
- skip: !platform.isMacOS, // Skip on non-macOS platforms where Chrome paths may differ
- );
- });
-}
-
-/// Launches headless Chrome with the given debug URL.
-/// Uses findChromeExecutable to locate Chrome on the current platform.
-Future<io.Process> _launchHeadlessChrome(String debugUrl) async {
- const chromeArgs = [
- '--headless',
- '--disable-gpu',
- '--no-sandbox',
- '--disable-extensions',
- '--disable-dev-shm-usage',
- '--remote-debugging-port=0',
- ];
-
- final String chromePath = findChromeExecutable(platform, fileSystem);
-
- try {
- return await io.Process.start(chromePath, [...chromeArgs, debugUrl]);
- } on Exception catch (e) {
- throw Exception(
- 'Could not launch Chrome at $chromePath: $e. Please ensure Chrome is installed.',
- );
- }
-}
-
-/// Cleans up test resources (Chrome process and stdout subscription).
-Future<void> _cleanupResources(
- io.Process? chromeProcess,
- StreamSubscription<String> subscription,
-) async {
- if (chromeProcess != null) {
- try {
- chromeProcess.kill();
- await chromeProcess.exitCode;
- debugPrint('Chrome process cleaned up');
- } on Exception catch (e) {
- debugPrint('Warning: Failed to clean up Chrome process: $e');
- }
- }
- await subscription.cancel();
-}
-
-// Helper to run flutter with web-server device using WebSocket connection.
-Future<void> runFlutterWithWebServerDevice(
- FlutterRunTestDriver flutter, {
- bool verbose = false,
- bool withDebugger = true, // Enable debugger by default for WebSocket connection
- bool startPaused = false, // Don't start paused for this test
- List<String> additionalCommandArgs = const <String>[],
-}) => flutter.run(
- verbose: verbose,
- withDebugger: withDebugger, // Enable debugger to establish WebSocket connection
- startPaused: startPaused, // Let the app start normally after debugger connects
- device: WebServerDevice.kWebServerDeviceId,
- additionalCommandArgs: additionalCommandArgs,
-);
diff --git a/packages/flutter_tools/test/integration.shard/test_driver.dart b/packages/flutter_tools/test/integration.shard/test_driver.dart
index a6c5887..e173616 100644
--- a/packages/flutter_tools/test/integration.shard/test_driver.dart
+++ b/packages/flutter_tools/test/integration.shard/test_driver.dart
@@ -11,7 +11,7 @@
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:flutter_tools/src/tester/flutter_tester.dart';
-import 'package:flutter_tools/src/web/web_device.dart' show GoogleChromeDevice, WebServerDevice;
+import 'package:flutter_tools/src/web/web_device.dart' show GoogleChromeDevice;
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart';
@@ -568,7 +568,6 @@
],
withDebugger: withDebugger,
startPaused: startPaused,
- waitForDebugPort: device != WebServerDevice.kWebServerDeviceId,
pauseOnExceptions: pauseOnExceptions,
script: script,
verbose: verbose,
@@ -609,7 +608,6 @@
bool withDebugger = false,
bool startPaused = false,
bool pauseOnExceptions = false,
- bool waitForDebugPort = false,
bool verbose = false,
int? attachPort,
}) async {
@@ -650,11 +648,12 @@
event: 'app.started',
timeout: appStartTimeout,
);
- late final Map<String, Object?> debugPort;
- if (waitForDebugPort || withDebugger) {
- debugPort = await _waitFor(event: 'app.debugPort', timeout: appStartTimeout);
- }
+
if (withDebugger) {
+ final Map<String, Object?> debugPort = await _waitFor(
+ event: 'app.debugPort',
+ timeout: appStartTimeout,
+ );
final wsUriString = (debugPort['params']! as Map<String, Object?>)['wsUri']! as String;
_vmServiceWsUri = Uri.parse(wsUriString);
await connectToVmService(pauseOnExceptions: pauseOnExceptions);