Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reland "Fix issue where DevTools would not be immediately available when using --start-paused (#126698)" #129368

Merged
merged 7 commits into from
Jun 27, 2023
52 changes: 40 additions & 12 deletions packages/flutter_tools/lib/src/resident_devtools_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ abstract class ResidentDevtoolsHandler {
Future<void> serveAndAnnounceDevTools({
Uri? devToolsServerAddress,
required List<FlutterDevice?> flutterDevices,
bool isStartPaused = false,
});

bool launchDevToolsInBrowser({required List<FlutterDevice?> flutterDevices});
Expand Down Expand Up @@ -71,6 +72,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
Future<void> serveAndAnnounceDevTools({
Uri? devToolsServerAddress,
required List<FlutterDevice?> flutterDevices,
bool isStartPaused = false,
}) async {
assert(!_readyToAnnounce);
if (!_residentRunner.supportsServiceProtocol || _devToolsLauncher == null) {
Expand All @@ -88,20 +90,10 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
assert(!_readyToAnnounce);
return;
}
final List<FlutterDevice?> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
await _maybeCallDevToolsUriServiceExtension(devicesWithExtension);
await _callConnectedVmServiceUriExtension(devicesWithExtension);

if (_shutdown) {
// If we're shutting down, no point reporting the debugger list.
return;
}
_readyToAnnounce = true;
assert(_devToolsLauncher!.activeDevToolsServer != null);

final Uri? devToolsUrl = _devToolsLauncher!.devToolsUrl;
if (devToolsUrl != null) {
for (final FlutterDevice? device in devicesWithExtension) {
for (final FlutterDevice? device in flutterDevices) {
if (device == null) {
continue;
}
Expand All @@ -111,11 +103,43 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
}
}

Future<void> callServiceExtensions() async {
final List<FlutterDevice?> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
await Future.wait(
<Future<void>>[
_maybeCallDevToolsUriServiceExtension(devicesWithExtension),
_callConnectedVmServiceUriExtension(devicesWithExtension)
]
);
}

// If the application is starting paused, we can't invoke service extensions
// as they're handled on the target app's paused isolate. Since invoking
// service extensions will block in this situation, we should wait to invoke
// them until after we've output the DevTools connection details.
if (!isStartPaused) {
await callServiceExtensions();
}

// This check needs to happen after the possible asynchronous call above,
// otherwise a shutdown event might be missed and the DevTools launcher may
// no longer be initialized.
if (_shutdown) {
// If we're shutting down, no point reporting the debugger list.
return;
}

_readyToAnnounce = true;
assert(_devToolsLauncher!.activeDevToolsServer != null);
if (_residentRunner.reportedDebuggers) {
// Since the DevTools only just became available, we haven't had a chance to
// report their URLs yet. Do so now.
_residentRunner.printDebuggerList(includeVmService: false);
}

if (isStartPaused) {
await callServiceExtensions();
}
}

// This must be guaranteed not to return a Future that fails.
Expand Down Expand Up @@ -295,7 +319,11 @@ class NoOpDevtoolsHandler implements ResidentDevtoolsHandler {
}

@override
Future<void> serveAndAnnounceDevTools({Uri? devToolsServerAddress, List<FlutterDevice?>? flutterDevices}) async {
Future<void> serveAndAnnounceDevTools({
Uri? devToolsServerAddress,
List<FlutterDevice?>? flutterDevices,
bool isStartPaused = false,
}) async {
return;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/flutter_tools/lib/src/run_cold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class ColdRunner extends ResidentRunner {
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
isStartPaused: debuggingOptions.startPaused,
));
}
if (debuggingOptions.serveObservatory) {
Expand Down Expand Up @@ -173,6 +174,7 @@ class ColdRunner extends ResidentRunner {
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
isStartPaused: debuggingOptions.startPaused,
));
}
if (debuggingOptions.serveObservatory) {
Expand Down
1 change: 1 addition & 0 deletions packages/flutter_tools/lib/src/run_hot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ class HotRunner extends ResidentRunner {
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
isStartPaused: debuggingOptions.startPaused,
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ void main() {
},
),
listViews,
listViews,
const FakeVmServiceRequest(
method: 'ext.flutter.activeDevToolsServerAddress',
args: <String, Object>{
'isolateId': '1',
'value': 'http://localhost:8080',
},
),
listViews,
const FakeVmServiceRequest(
method: 'ext.flutter.connectedVmServiceUri',
args: <String, Object>{
Expand Down Expand Up @@ -314,14 +314,14 @@ void main() {
},
),
listViews,
listViews,
const FakeVmServiceRequest(
method: 'ext.flutter.activeDevToolsServerAddress',
args: <String, Object>{
'isolateId': '1',
'value': 'http://localhost:8080',
},
),
listViews,
const FakeVmServiceRequest(
method: 'ext.flutter.connectedVmServiceUri',
args: <String, Object>{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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.

import 'dart:async';

import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/convert.dart';

import '../src/common.dart';
import 'test_data/basic_project.dart';
import 'test_utils.dart';

void main() {
late Directory tempDir;
final BasicProject project = BasicProject();

setUp(() async {
tempDir = createResolvedTempDirectorySync('run_test.');
await project.setUpIn(tempDir);
});

tearDown(() async {
tryToDelete(tempDir);
});

// Regression test for https://github.com/flutter/flutter/issues/126691
testWithoutContext('flutter run --start-paused prints DevTools URI', () async {
final Completer<void> completer = Completer<void>();
final RegExp matcher = RegExp(r'The Flutter DevTools debugger and profiler on');
bkonyi marked this conversation as resolved.
Show resolved Hide resolved

final String flutterBin = fileSystem.path.join(getFlutterRoot(), 'bin', 'flutter');
final Process process = await processManager.start(<String>[
flutterBin,
'run',
'--start-paused',
'-d',
'flutter-tester',
], workingDirectory: tempDir.path);

late final StreamSubscription<String> sub;
sub = process.stdout.transform(utf8.decoder).listen((String message) {
if (message.contains(matcher)) {
completer.complete();
sub.cancel();
bkonyi marked this conversation as resolved.
Show resolved Hide resolved
}
});
await completer.future;
process.kill();
await process.exitCode;
});
}