mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reverts "Reapply "Make device debuggable if useDwdsWebSocketConnection is true … (#173551)" (#173568)" (#173587)
<!-- start_original_pr_link --> Reverts: flutter/flutter#173568 <!-- end_original_pr_link --> <!-- start_initiating_author --> Initiated by: bkonyi <!-- end_initiating_author --> <!-- start_revert_reason --> Reason for reverting: Chrome isn't configured for the test configuration and is causing failures. <!-- end_revert_reason --> <!-- start_original_pr_author --> Original PR Author: bkonyi <!-- end_original_pr_author --> <!-- start_reviewers --> Reviewed By: {jyameo, matanlurey} <!-- end_reviewers --> <!-- start_revert_body --> This change reverts the following previous change: This reverts commit e2a347b14a18729dd24c2cf3240ef22562195e2d. Previously reverted due to `*_chrome_dev_mode` tests failing on all platforms. <!-- end_revert_body --> Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
This commit is contained in:
parent
1fcb4796c4
commit
17c92b7ba6
@ -6,5 +6,5 @@ import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/tasks/web_dev_mode_tests.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createWebDevModeTest());
|
||||
await task(createWebDevModeTest(WebDevice.webServer, false));
|
||||
}
|
||||
|
||||
@ -6,5 +6,5 @@ import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/tasks/web_dev_mode_tests.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createWebDevModeTest());
|
||||
await task(createWebDevModeTest(WebDevice.webServer, false));
|
||||
}
|
||||
|
||||
@ -6,5 +6,5 @@ import 'package:flutter_devicelab/framework/framework.dart';
|
||||
import 'package:flutter_devicelab/tasks/web_dev_mode_tests.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
await task(createWebDevModeTest());
|
||||
await task(createWebDevModeTest(WebDevice.webServer, false));
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@ class ChromeOptions {
|
||||
this.headless,
|
||||
this.debugPort,
|
||||
this.enableWasmGC = false,
|
||||
this.silent = false,
|
||||
});
|
||||
|
||||
/// If not null passed as `--user-data-dir`.
|
||||
@ -58,9 +57,6 @@ class ChromeOptions {
|
||||
|
||||
/// Whether to enable experimental WasmGC flags
|
||||
final bool enableWasmGC;
|
||||
|
||||
/// Disables Chrome stdio outputs.
|
||||
final bool silent;
|
||||
}
|
||||
|
||||
/// A function called when the Chrome process encounters an error.
|
||||
@ -123,7 +119,6 @@ class Chrome {
|
||||
final io.Process chromeProcess = await _spawnChromiumProcess(
|
||||
_findSystemChromeExecutable(),
|
||||
args,
|
||||
silent: options.silent,
|
||||
workingDirectory: workingDirectory,
|
||||
);
|
||||
|
||||
@ -615,7 +610,6 @@ const String _kGlibcError = 'Inconsistency detected by ld.so';
|
||||
Future<io.Process> _spawnChromiumProcess(
|
||||
String executable,
|
||||
List<String> args, {
|
||||
required bool silent,
|
||||
String? workingDirectory,
|
||||
}) async {
|
||||
// Keep attempting to launch the browser until one of:
|
||||
@ -629,9 +623,7 @@ Future<io.Process> _spawnChromiumProcess(
|
||||
);
|
||||
|
||||
process.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen((String line) {
|
||||
if (!silent) {
|
||||
print('[CHROME STDOUT]: $line');
|
||||
}
|
||||
print('[CHROME STDOUT]: $line');
|
||||
});
|
||||
|
||||
// Wait until the DevTools are listening before trying to connect. This is
|
||||
@ -641,9 +633,7 @@ Future<io.Process> _spawnChromiumProcess(
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.map((String line) {
|
||||
if (!silent) {
|
||||
print('[CHROME STDERR]:$line');
|
||||
}
|
||||
print('[CHROME STDERR]:$line');
|
||||
if (line.contains(_kGlibcError)) {
|
||||
hitGlibcBug = true;
|
||||
}
|
||||
|
||||
@ -56,7 +56,6 @@ enum DeviceOperatingSystem {
|
||||
ios,
|
||||
linux,
|
||||
macos,
|
||||
webServer,
|
||||
windows,
|
||||
}
|
||||
|
||||
@ -81,8 +80,6 @@ abstract class DeviceDiscovery {
|
||||
return LinuxDeviceDiscovery();
|
||||
case DeviceOperatingSystem.macos:
|
||||
return MacosDeviceDiscovery();
|
||||
case DeviceOperatingSystem.webServer:
|
||||
return WebServerDeviceDiscovery();
|
||||
case DeviceOperatingSystem.windows:
|
||||
return WindowsDeviceDiscovery();
|
||||
case DeviceOperatingSystem.fake:
|
||||
@ -434,40 +431,6 @@ class MacosDeviceDiscovery implements DeviceDiscovery {
|
||||
Future<Device> get workingDevice async => _device;
|
||||
}
|
||||
|
||||
class WebServerDeviceDiscovery implements DeviceDiscovery {
|
||||
factory WebServerDeviceDiscovery() {
|
||||
return _instance ??= WebServerDeviceDiscovery._();
|
||||
}
|
||||
|
||||
WebServerDeviceDiscovery._();
|
||||
|
||||
static WebServerDeviceDiscovery? _instance;
|
||||
|
||||
static const WebServerDevice _device = WebServerDevice();
|
||||
|
||||
@override
|
||||
Future<Map<String, HealthCheckResult>> checkDevices() async {
|
||||
return <String, HealthCheckResult>{};
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> chooseWorkingDevice() async {}
|
||||
|
||||
@override
|
||||
Future<void> chooseWorkingDeviceById(String deviceId) async {}
|
||||
|
||||
@override
|
||||
Future<List<String>> discoverDevices() async {
|
||||
return <String>['web-server'];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> performPreflightTasks() async {}
|
||||
|
||||
@override
|
||||
Future<Device> get workingDevice async => _device;
|
||||
}
|
||||
|
||||
class WindowsDeviceDiscovery implements DeviceDiscovery {
|
||||
factory WindowsDeviceDiscovery() {
|
||||
return _instance ??= WindowsDeviceDiscovery._();
|
||||
@ -1297,61 +1260,6 @@ class MacosDevice extends Device {
|
||||
Future<void> awaitDevice() async {}
|
||||
}
|
||||
|
||||
class WebServerDevice extends Device {
|
||||
const WebServerDevice();
|
||||
|
||||
@override
|
||||
String get deviceId => 'web-server';
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> getMemoryStats(String packageName) async {
|
||||
return <String, dynamic>{};
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> home() async {}
|
||||
|
||||
@override
|
||||
Future<bool> isAsleep() async {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isAwake() async {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<String> get logcat => const Stream<String>.empty();
|
||||
|
||||
@override
|
||||
Future<void> clearLogs() async {}
|
||||
|
||||
@override
|
||||
Future<void> reboot() async {}
|
||||
|
||||
@override
|
||||
Future<void> sendToSleep() async {}
|
||||
|
||||
@override
|
||||
Future<void> stop(String packageName) async {}
|
||||
|
||||
@override
|
||||
Future<void> tap(int x, int y) async {}
|
||||
|
||||
@override
|
||||
Future<void> togglePower() async {}
|
||||
|
||||
@override
|
||||
Future<void> unlock() async {}
|
||||
|
||||
@override
|
||||
Future<void> wakeUp() async {}
|
||||
|
||||
@override
|
||||
Future<void> awaitDevice() async {}
|
||||
}
|
||||
|
||||
class WindowsDevice extends Device {
|
||||
const WindowsDevice();
|
||||
|
||||
|
||||
@ -1002,8 +1002,6 @@ class StartupTest {
|
||||
);
|
||||
final String buildRoot = path.join(testDirectory, 'build');
|
||||
applicationBinaryPath = _findDarwinAppInBuildDirectory(buildRoot);
|
||||
case DeviceOperatingSystem.webServer:
|
||||
break;
|
||||
case DeviceOperatingSystem.windows:
|
||||
await flutter(
|
||||
'build',
|
||||
@ -1155,7 +1153,6 @@ class DevtoolsStartupTest {
|
||||
case DeviceOperatingSystem.fuchsia:
|
||||
case DeviceOperatingSystem.linux:
|
||||
case DeviceOperatingSystem.macos:
|
||||
case DeviceOperatingSystem.webServer:
|
||||
case DeviceOperatingSystem.windows:
|
||||
break;
|
||||
}
|
||||
@ -1496,7 +1493,6 @@ class PerfTest {
|
||||
case DeviceOperatingSystem.fuchsia:
|
||||
case DeviceOperatingSystem.linux:
|
||||
case DeviceOperatingSystem.macos:
|
||||
case DeviceOperatingSystem.webServer:
|
||||
case DeviceOperatingSystem.windows:
|
||||
recordGPU = false;
|
||||
}
|
||||
@ -2015,8 +2011,6 @@ class CompileTest {
|
||||
throw Exception('Unsupported option for Fuchsia devices');
|
||||
case DeviceOperatingSystem.linux:
|
||||
throw Exception('Unsupported option for Linux devices');
|
||||
case DeviceOperatingSystem.webServer:
|
||||
throw Exception('Unsupported option for Web Server devices');
|
||||
case DeviceOperatingSystem.windows:
|
||||
unawaited(stderr.flush());
|
||||
options.insert(0, 'windows');
|
||||
@ -2084,8 +2078,6 @@ class CompileTest {
|
||||
case DeviceOperatingSystem.macos:
|
||||
unawaited(stderr.flush());
|
||||
options.insert(0, 'macos');
|
||||
case DeviceOperatingSystem.webServer:
|
||||
throw Exception('Unsupported option for Web Server devices');
|
||||
case DeviceOperatingSystem.windows:
|
||||
unawaited(stderr.flush());
|
||||
options.insert(0, 'windows');
|
||||
@ -2118,7 +2110,6 @@ class CompileTest {
|
||||
case DeviceOperatingSystem.fake:
|
||||
case DeviceOperatingSystem.fuchsia:
|
||||
case DeviceOperatingSystem.linux:
|
||||
case DeviceOperatingSystem.webServer:
|
||||
case DeviceOperatingSystem.windows:
|
||||
throw Exception('Called ${CompileTest.getSizesFromDarwinApp} with $operatingSystem.');
|
||||
}
|
||||
|
||||
@ -9,8 +9,6 @@ import 'dart:io';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:yaml_edit/yaml_edit.dart';
|
||||
|
||||
import '../framework/browser.dart';
|
||||
import '../framework/devices.dart';
|
||||
import '../framework/framework.dart';
|
||||
import '../framework/task_result.dart';
|
||||
import '../framework/utils.dart';
|
||||
@ -33,123 +31,25 @@ const String kFirstRecompileTime = 'FirstRecompileTime';
|
||||
const String kSecondStartupTime = 'SecondStartupTime';
|
||||
const String kSecondRestartTime = 'SecondRestartTime';
|
||||
|
||||
const String kWebServerDevice = 'web-server';
|
||||
|
||||
final RegExp servedAtPattern = RegExp('is being served at (.*)');
|
||||
int hotRestartCount = 0;
|
||||
|
||||
Future<List<int>> launch({required bool isFirstRun}) async {
|
||||
final List<String> options = <String>[
|
||||
'--hot',
|
||||
'-d',
|
||||
kWebServerDevice,
|
||||
'--verbose',
|
||||
'--resident',
|
||||
'--target=lib/main.dart',
|
||||
];
|
||||
final Process process = await startFlutter('run', options: options);
|
||||
|
||||
final List<int> measurements = <int>[];
|
||||
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
final Completer<void> stderrDone = Completer<void>();
|
||||
final Completer<void> waitForService = Completer<void>();
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
Chrome? chrome;
|
||||
bool restarted = false;
|
||||
process
|
||||
..stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) async {
|
||||
if (line.contains(servedAtPattern)) {
|
||||
final String url = servedAtPattern.firstMatch(line)!.group(1)!;
|
||||
chrome = await Chrome.launch(
|
||||
ChromeOptions(url: url, headless: true, silent: true, debugPort: 10000),
|
||||
onError: (String e) {},
|
||||
);
|
||||
}
|
||||
if (line.contains('DevHandler: Debug service listening on')) {
|
||||
waitForService.complete();
|
||||
}
|
||||
// non-dwds builds do not know when the browser is loaded so keep trying
|
||||
// until this succeeds.
|
||||
if (line.contains('Ignoring terminal input')) {
|
||||
unawaited(
|
||||
Future<void>.delayed(const Duration(seconds: 1)).then((void _) {
|
||||
process.stdin.write(restarted ? 'q' : 'r');
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (line.contains('Hot restart')) {
|
||||
unawaited(
|
||||
waitForService.future.then((_) {
|
||||
// measure clean start-up time.
|
||||
sw.stop();
|
||||
measurements.add(sw.elapsedMilliseconds);
|
||||
sw
|
||||
..reset()
|
||||
..start();
|
||||
process.stdin.write('r');
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (line.contains('Reloaded application')) {
|
||||
if (hotRestartCount == 0) {
|
||||
assert(isFirstRun);
|
||||
measurements.add(sw.elapsedMilliseconds);
|
||||
// Update the file and reload again.
|
||||
final File appDartSource = file(
|
||||
path.join(_editedFlutterGalleryDir.path, 'lib/gallery/app.dart'),
|
||||
);
|
||||
appDartSource.writeAsStringSync(
|
||||
appDartSource.readAsStringSync().replaceFirst(
|
||||
"'Flutter Gallery'",
|
||||
"'Updated Flutter Gallery'",
|
||||
),
|
||||
);
|
||||
sw
|
||||
..reset()
|
||||
..start();
|
||||
process.stdin.writeln('r');
|
||||
++hotRestartCount;
|
||||
} else {
|
||||
restarted = true;
|
||||
measurements.add(sw.elapsedMilliseconds);
|
||||
// Quit after second hot restart.
|
||||
process.stdin.writeln('q');
|
||||
}
|
||||
}
|
||||
print('stdout: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stdoutDone.complete();
|
||||
},
|
||||
)
|
||||
..stderr
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
print('stderr: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stderrDone.complete();
|
||||
},
|
||||
);
|
||||
|
||||
await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
|
||||
await process.exitCode;
|
||||
chrome?.stop();
|
||||
return measurements;
|
||||
abstract class WebDevice {
|
||||
static const String chrome = 'chrome';
|
||||
static const String webServer = 'web-server';
|
||||
}
|
||||
|
||||
TaskFunction createWebDevModeTest() {
|
||||
deviceOperatingSystem = DeviceOperatingSystem.webServer;
|
||||
TaskFunction createWebDevModeTest(String webDevice, bool enableIncrementalCompiler) {
|
||||
return () async {
|
||||
final List<String> options = <String>[
|
||||
'--hot',
|
||||
'-d',
|
||||
webDevice,
|
||||
'--verbose',
|
||||
'--resident',
|
||||
'--target=lib/main.dart',
|
||||
];
|
||||
int hotRestartCount = 0;
|
||||
final String expectedMessage = webDevice == WebDevice.webServer
|
||||
? 'Recompile complete'
|
||||
: 'Reloaded application';
|
||||
final Map<String, int> measurements = <String, int>{};
|
||||
await inDirectory<void>(flutterDirectory, () async {
|
||||
rmTree(_editedFlutterGalleryDir);
|
||||
@ -166,20 +66,139 @@ TaskFunction createWebDevModeTest() {
|
||||
).writeAsStringSync(yamlEditor.toString());
|
||||
|
||||
await inDirectory<void>(_editedFlutterGalleryDir, () async {
|
||||
await flutter('packages', options: <String>['get']);
|
||||
final List<int> firstMeasurements = await launch(isFirstRun: true);
|
||||
measurements.addAll(<String, int>{
|
||||
kInitialStartupTime: firstMeasurements[0],
|
||||
kFirstRecompileTime: firstMeasurements[1],
|
||||
kFirstRestartTime: firstMeasurements[2],
|
||||
});
|
||||
{
|
||||
await flutter('packages', options: <String>['get']);
|
||||
final Process process = await startFlutter('run', options: options);
|
||||
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
final Completer<void> stderrDone = Completer<void>();
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
bool restarted = false;
|
||||
process.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
// non-dwds builds do not know when the browser is loaded so keep trying
|
||||
// until this succeeds.
|
||||
if (line.contains('Ignoring terminal input')) {
|
||||
Future<void>.delayed(const Duration(seconds: 1)).then((void _) {
|
||||
process.stdin.write(restarted ? 'q' : 'r');
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (line.contains('Hot restart')) {
|
||||
// measure clean start-up time.
|
||||
sw.stop();
|
||||
measurements[kInitialStartupTime] = sw.elapsedMilliseconds;
|
||||
sw
|
||||
..reset()
|
||||
..start();
|
||||
process.stdin.write('r');
|
||||
return;
|
||||
}
|
||||
if (line.contains(expectedMessage)) {
|
||||
if (hotRestartCount == 0) {
|
||||
measurements[kFirstRestartTime] = sw.elapsedMilliseconds;
|
||||
// Update the file and reload again.
|
||||
final File appDartSource = file(
|
||||
path.join(_editedFlutterGalleryDir.path, 'lib/gallery/app.dart'),
|
||||
);
|
||||
appDartSource.writeAsStringSync(
|
||||
appDartSource.readAsStringSync().replaceFirst(
|
||||
"'Flutter Gallery'",
|
||||
"'Updated Flutter Gallery'",
|
||||
),
|
||||
);
|
||||
sw
|
||||
..reset()
|
||||
..start();
|
||||
process.stdin.writeln('r');
|
||||
++hotRestartCount;
|
||||
} else {
|
||||
restarted = true;
|
||||
measurements[kFirstRecompileTime] = sw.elapsedMilliseconds;
|
||||
// Quit after second hot restart.
|
||||
process.stdin.writeln('q');
|
||||
}
|
||||
}
|
||||
print('stdout: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stdoutDone.complete();
|
||||
},
|
||||
);
|
||||
process.stderr
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
print('stderr: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stderrDone.complete();
|
||||
},
|
||||
);
|
||||
|
||||
await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
|
||||
await process.exitCode;
|
||||
}
|
||||
|
||||
// Start `flutter run` again to make sure it loads from the previous
|
||||
// state. dev compilers loads up from previously compiled JavaScript.
|
||||
final List<int> secondMeasurements = await launch(isFirstRun: false);
|
||||
measurements.addAll(<String, int>{
|
||||
kSecondStartupTime: secondMeasurements[0],
|
||||
kSecondRestartTime: secondMeasurements[1],
|
||||
});
|
||||
{
|
||||
final Stopwatch sw = Stopwatch()..start();
|
||||
final Process process = await startFlutter('run', options: options);
|
||||
final Completer<void> stdoutDone = Completer<void>();
|
||||
final Completer<void> stderrDone = Completer<void>();
|
||||
bool restarted = false;
|
||||
process.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
// non-dwds builds do not know when the browser is loaded so keep trying
|
||||
// until this succeeds.
|
||||
if (line.contains('Ignoring terminal input')) {
|
||||
Future<void>.delayed(const Duration(seconds: 1)).then((void _) {
|
||||
process.stdin.write(restarted ? 'q' : 'r');
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (line.contains('Hot restart')) {
|
||||
measurements[kSecondStartupTime] = sw.elapsedMilliseconds;
|
||||
sw
|
||||
..reset()
|
||||
..start();
|
||||
process.stdin.write('r');
|
||||
return;
|
||||
}
|
||||
if (line.contains(expectedMessage)) {
|
||||
restarted = true;
|
||||
measurements[kSecondRestartTime] = sw.elapsedMilliseconds;
|
||||
process.stdin.writeln('q');
|
||||
}
|
||||
print('stdout: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stdoutDone.complete();
|
||||
},
|
||||
);
|
||||
process.stderr
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
print('stderr: $line');
|
||||
},
|
||||
onDone: () {
|
||||
stderrDone.complete();
|
||||
},
|
||||
);
|
||||
|
||||
await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
|
||||
await process.exitCode;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (hotRestartCount != 1) {
|
||||
|
||||
@ -152,22 +152,21 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
|
||||
// Only non-wasm debug builds of the web support the service protocol.
|
||||
@override
|
||||
late final bool supportsServiceProtocol =
|
||||
!debuggingOptions.webUseWasm && isRunningDebug && _deviceIsDebuggable;
|
||||
bool get supportsServiceProtocol =>
|
||||
!debuggingOptions.webUseWasm && isRunningDebug && deviceIsDebuggable;
|
||||
|
||||
/// Device is debuggable if not a WebServer device, or if running with
|
||||
/// --start-paused or using DWDS WebSocket connection (WebServer device).
|
||||
late final bool _deviceIsDebuggable =
|
||||
device!.device is! WebServerDevice ||
|
||||
debuggingOptions.startPaused ||
|
||||
useDwdsWebSocketConnection;
|
||||
@override
|
||||
bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;
|
||||
|
||||
late final useDwdsWebSocketConnection = device!.device is! ChromiumDevice;
|
||||
/// 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.
|
||||
bool get generateDartPluginRegistry => false;
|
||||
|
||||
bool get _enableDwds => debuggingEnabled;
|
||||
|
||||
@override
|
||||
bool get reloadIsRestart =>
|
||||
debuggingOptions.webUseWasm ||
|
||||
@ -287,6 +286,24 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
? WebExpressionCompiler(device!.generator!, fileSystem: _fileSystem)
|
||||
: null;
|
||||
|
||||
// Retrieve connected web devices, excluding the web server device.
|
||||
final List<Device>? devices = await globals.deviceManager?.getAllDevices();
|
||||
final nonWebServerConnectedDeviceIds = <String>{
|
||||
for (final Device d in devices!.where(
|
||||
(Device d) =>
|
||||
d.platformType == PlatformType.web &&
|
||||
d.isConnected &&
|
||||
d.id != WebServerDevice.kWebServerDeviceId,
|
||||
))
|
||||
d.id,
|
||||
};
|
||||
|
||||
// Use Chrome-based connection only if we have a connected ChromiumDevice
|
||||
// Otherwise, use DWDS WebSocket connection
|
||||
final bool useDwdsWebSocketConnection =
|
||||
!(_chromiumLauncher != null &&
|
||||
nonWebServerConnectedDeviceIds.contains(device!.device!.id));
|
||||
|
||||
device!.devFS = WebDevFS(
|
||||
webDevServerConfig: updatedConfig,
|
||||
packagesFilePath: packagesFilePath,
|
||||
@ -295,7 +312,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
useSseForDebugBackend: debuggingOptions.webUseSseForDebugBackend,
|
||||
useSseForInjectedClient: debuggingOptions.webUseSseForInjectedClient,
|
||||
buildInfo: debuggingOptions.buildInfo,
|
||||
enableDwds: supportsServiceProtocol,
|
||||
enableDwds: _enableDwds,
|
||||
enableDds: debuggingOptions.enableDds,
|
||||
entrypoint: _fileSystem.file(target).uri,
|
||||
expressionCompiler: expressionCompiler,
|
||||
@ -489,7 +506,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
Duration? reloadDuration;
|
||||
Duration? reassembleDuration;
|
||||
try {
|
||||
if (!_deviceIsDebuggable) {
|
||||
if (!deviceIsDebuggable) {
|
||||
_logger.printStatus('Recompile complete. Page requires refresh.');
|
||||
} else if (isRunningDebug) {
|
||||
if (fullRestart) {
|
||||
@ -558,7 +575,7 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
}
|
||||
|
||||
// Don't track restart times for dart2js builds or web-server devices.
|
||||
if (debuggingOptions.buildInfo.isDebug && _deviceIsDebuggable) {
|
||||
if (debuggingOptions.buildInfo.isDebug && deviceIsDebuggable) {
|
||||
if (fullRestart) {
|
||||
_analytics.send(
|
||||
Event.timing(
|
||||
@ -773,102 +790,86 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
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) {
|
||||
@ -880,8 +881,16 @@ class ResidentWebRunner extends ResidentRunner {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@ -13,7 +13,7 @@ dependencies:
|
||||
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 @@ dev_dependencies:
|
||||
dartdoc:
|
||||
# Exclude this package from the hosted API docs.
|
||||
nodoc: true
|
||||
# PUBSPEC CHECKSUM: 932agm
|
||||
# PUBSPEC CHECKSUM: kav93d
|
||||
|
||||
@ -147,7 +147,7 @@ name: my_app
|
||||
}
|
||||
|
||||
testUsingContext(
|
||||
'runner with web server device supports debugging without --start-paused',
|
||||
'runner with web server device does not support debugging without --start-paused',
|
||||
() {
|
||||
final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
|
||||
flutterDevice.device = WebServerDevice(logger: BufferLogger.test());
|
||||
@ -165,7 +165,7 @@ name: my_app
|
||||
systemClock: globals.systemClock,
|
||||
);
|
||||
|
||||
expect(profileResidentWebRunner.debuggingEnabled, true);
|
||||
expect(profileResidentWebRunner.debuggingEnabled, false);
|
||||
|
||||
flutterDevice.device = chromeDevice;
|
||||
|
||||
@ -1104,12 +1104,7 @@ name: my_app
|
||||
logger: logger,
|
||||
systemClock: SystemClock.fixed(DateTime(2001)),
|
||||
);
|
||||
fakeVmServiceHost = FakeVmServiceHost(
|
||||
requests: [
|
||||
...kAttachExpectations,
|
||||
const FakeVmServiceRequest(method: 'hotRestart'),
|
||||
],
|
||||
);
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations);
|
||||
setupMocks();
|
||||
flutterDevice.device = webServerDevice;
|
||||
webDevFS.report = UpdateFSReport(success: true);
|
||||
@ -1122,16 +1117,8 @@ name: my_app
|
||||
expect(logger.statusText, contains('Restarted application in'));
|
||||
expect(result.code, 0);
|
||||
|
||||
expect(
|
||||
fakeAnalytics.sentEvents,
|
||||
contains(
|
||||
Event.timing(
|
||||
workflow: 'hot',
|
||||
variableName: 'web-incremental-restart',
|
||||
elapsedMilliseconds: 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
// web-server device does not send restart analytics
|
||||
expect(fakeAnalytics.sentEvents, isEmpty);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
Analytics: () => fakeAnalytics,
|
||||
@ -1594,7 +1581,7 @@ name: my_app
|
||||
'Sends unlaunched app.webLaunchUrl event for Web Server device',
|
||||
() async {
|
||||
final logger = BufferLogger.test();
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations.toList());
|
||||
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
|
||||
setupMocks();
|
||||
flutterDevice.device = WebServerDevice(logger: logger);
|
||||
webDevFS.baseUri = Uri.parse('http://localhost:8765/app/');
|
||||
@ -1678,9 +1665,7 @@ flutter:
|
||||
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')
|
||||
@ -2070,9 +2055,6 @@ class FakeWebDevFS extends Fake implements WebDevFS {
|
||||
@override
|
||||
PackageConfig? lastPackageConfig = PackageConfig.empty;
|
||||
|
||||
@override
|
||||
var useDwdsWebSocketConnection = false;
|
||||
|
||||
@override
|
||||
Future<Uri> create() async {
|
||||
return baseUri;
|
||||
|
||||
@ -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,
|
||||
);
|
||||
@ -11,7 +11,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
|
||||
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 @@ final class FlutterRunTestDriver extends FlutterTestDriver {
|
||||
],
|
||||
withDebugger: withDebugger,
|
||||
startPaused: startPaused,
|
||||
waitForDebugPort: device != WebServerDevice.kWebServerDeviceId,
|
||||
pauseOnExceptions: pauseOnExceptions,
|
||||
script: script,
|
||||
verbose: verbose,
|
||||
@ -609,7 +608,6 @@ final class FlutterRunTestDriver extends FlutterTestDriver {
|
||||
bool withDebugger = false,
|
||||
bool startPaused = false,
|
||||
bool pauseOnExceptions = false,
|
||||
bool waitForDebugPort = false,
|
||||
bool verbose = false,
|
||||
int? attachPort,
|
||||
}) async {
|
||||
@ -650,11 +648,12 @@ final class FlutterRunTestDriver extends FlutterTestDriver {
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user