Unverified Commit 2a2f9731 authored by Ben Konyi's avatar Ben Konyi Committed by GitHub

Update flutter_tools to look for new VM service message (#97683)

* Update flutter_tools to look for new VM service message

The Dart SDK will soon move away from the current Observatory message:

"Observatory listening on ..."

To a new message that no longer references Observatory:

"Dart VM Service listening on ..."

This change updates all tests with mocks to check for the new message
and also adds support for the new message in ProtocolDiscovery.

See https://github.com/dart-lang/sdk/issues/46756

* Fix some parsing locations

* Fix analysis failures

* Update message

* Remove extra comment

* Update message

* Add globals prefix
parent ee0bbf47
...@@ -190,7 +190,7 @@ Future<TaskResult> runTask( ...@@ -190,7 +190,7 @@ Future<TaskResult> runTask(
.transform<String>(const LineSplitter()) .transform<String>(const LineSplitter())
.listen((String line) { .listen((String line) {
if (!uri.isCompleted) { if (!uri.isCompleted) {
final Uri? serviceUri = parseServiceUri(line, prefix: 'Observatory listening on '); final Uri? serviceUri = parseServiceUri(line, prefix: RegExp('(Observatory|Dart VM Service) listening on '));
if (serviceUri != null) if (serviceUri != null)
uri.complete(serviceUri); uri.complete(serviceUri);
} }
......
...@@ -688,7 +688,7 @@ class _WidgetInspectorService = Object with WidgetInspectorService; ...@@ -688,7 +688,7 @@ class _WidgetInspectorService = Object with WidgetInspectorService;
/// ///
/// Calls to this object are typically made from GUI tools such as the [Flutter /// Calls to this object are typically made from GUI tools such as the [Flutter
/// IntelliJ Plugin](https://github.com/flutter/flutter-intellij/blob/master/README.md) /// IntelliJ Plugin](https://github.com/flutter/flutter-intellij/blob/master/README.md)
/// using the [Dart VM Service protocol](https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md). /// using the [Dart VM Service](https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md).
/// This class uses its own object id and manages object lifecycles itself /// This class uses its own object id and manages object lifecycles itself
/// instead of depending on the [object ids](https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#getobject) /// instead of depending on the [object ids](https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#getobject)
/// specified by the VM Service Protocol because the VM Service Protocol ids /// specified by the VM Service Protocol because the VM Service Protocol ids
......
...@@ -281,3 +281,7 @@ PreRunValidator get preRunValidator => context.get<PreRunValidator>() ?? const N ...@@ -281,3 +281,7 @@ PreRunValidator get preRunValidator => context.get<PreRunValidator>() ?? const N
// TODO(fujino): Migrate to 'main' https://github.com/flutter/flutter/issues/95041 // TODO(fujino): Migrate to 'main' https://github.com/flutter/flutter/issues/95041
const String kDefaultFrameworkChannel = 'master'; const String kDefaultFrameworkChannel = 'master';
// Used to build RegExp instances which can detect the VM service message.
const String kServicePrefixRegExp = '(?:Observatory|The Dart VM service is)';
final RegExp kVMServiceMessageRegExp = RegExp(kServicePrefixRegExp + r' listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
...@@ -313,7 +313,7 @@ class IOSDeployDebugger { ...@@ -313,7 +313,7 @@ class IOSDeployDebugger {
// (lldb) run // (lldb) run
// success // success
// 2020-09-15 13:42:25.185474-0700 Runner[477:181141] flutter: Observatory listening on http://127.0.0.1:57782/ // 2020-09-15 13:42:25.185474-0700 Runner[477:181141] flutter: The Dart VM service is listening on http://127.0.0.1:57782/
if (_lldbRun.hasMatch(line)) { if (_lldbRun.hasMatch(line)) {
_logger.printTrace(line); _logger.printTrace(line);
_debuggerState = _IOSDeployDebuggerState.launching; _debuggerState = _IOSDeployDebuggerState.launching;
......
...@@ -757,8 +757,8 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -757,8 +757,8 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
} }
// Match the log prefix (in order to shorten it): // Match the log prefix (in order to shorten it):
// * Xcode 8: Sep 13 15:28:51 cbracken-macpro localhost Runner[37195]: (Flutter) Observatory listening on http://127.0.0.1:57701/ // * Xcode 8: Sep 13 15:28:51 cbracken-macpro localhost Runner[37195]: (Flutter) The Dart VM service is listening on http://127.0.0.1:57701/
// * Xcode 9: 2017-09-13 15:26:57.228948-0700 localhost Runner[37195]: (Flutter) Observatory listening on http://127.0.0.1:57701/ // * Xcode 9: 2017-09-13 15:26:57.228948-0700 localhost Runner[37195]: (Flutter) The Dart VM service is listening on http://127.0.0.1:57701/
static final RegExp _mapRegex = RegExp(r'\S+ +\S+ +(?:\S+) (.+?(?=\[))\[\d+\]\)?: (\(.*?\))? *(.*)$'); static final RegExp _mapRegex = RegExp(r'\S+ +\S+ +(?:\S+) (.+?(?=\[))\[\d+\]\)?: (\(.*?\))? *(.*)$');
// Jan 31 19:23:28 --- last message repeated 1 time --- // Jan 31 19:23:28 --- last message repeated 1 time ---
......
...@@ -8,6 +8,7 @@ import 'base/io.dart'; ...@@ -8,6 +8,7 @@ import 'base/io.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'device.dart'; import 'device.dart';
import 'device_port_forwarder.dart'; import 'device_port_forwarder.dart';
import 'globals.dart' as globals;
/// Discovers a specific service protocol on a device, and forwards the service /// Discovers a specific service protocol on a device, and forwards the service
/// protocol device port to the host. /// protocol device port to the host.
...@@ -104,8 +105,7 @@ class ProtocolDiscovery { ...@@ -104,8 +105,7 @@ class ProtocolDiscovery {
} }
Match? _getPatternMatch(String line) { Match? _getPatternMatch(String line) {
final RegExp r = RegExp(RegExp.escape(serviceName) + r' listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)'); return globals.kVMServiceMessageRegExp.firstMatch(line);
return r.firstMatch(line);
} }
Uri? _getObservatoryUri(String line) { Uri? _getObservatoryUri(String line) {
......
...@@ -367,7 +367,7 @@ class FlutterDevice { ...@@ -367,7 +367,7 @@ class FlutterDevice {
return; return;
} }
_loggingSubscription = logStream.listen((String line) { _loggingSubscription = logStream.listen((String line) {
if (!line.contains('Observatory listening on http')) { if (!line.contains(globals.kVMServiceMessageRegExp)) {
globals.printStatus(line, wrap: false); globals.printStatus(line, wrap: false);
} }
}); });
......
...@@ -20,6 +20,7 @@ import '../base/os.dart'; ...@@ -20,6 +20,7 @@ import '../base/os.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../convert.dart'; import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../vmservice.dart'; import '../vmservice.dart';
...@@ -294,7 +295,6 @@ class FlutterTesterTestDevice extends TestDevice { ...@@ -294,7 +295,6 @@ class FlutterTesterTestDevice extends TestDevice {
@required Process process, @required Process process,
@required Future<void> Function(Uri uri) reportObservatoryUri, @required Future<void> Function(Uri uri) reportObservatoryUri,
}) { }) {
const String observatoryString = 'Observatory listening on ';
for (final Stream<List<int>> stream in <Stream<List<int>>>[ for (final Stream<List<int>> stream in <Stream<List<int>>>[
process.stderr, process.stderr,
process.stdout, process.stdout,
...@@ -306,9 +306,10 @@ class FlutterTesterTestDevice extends TestDevice { ...@@ -306,9 +306,10 @@ class FlutterTesterTestDevice extends TestDevice {
(String line) async { (String line) async {
logger.printTrace('test $id: Shell: $line'); logger.printTrace('test $id: Shell: $line');
if (line.startsWith(observatoryString)) { final Match match = globals.kVMServiceMessageRegExp.firstMatch(line);
if (match != null) {
try { try {
final Uri uri = Uri.parse(line.substring(observatoryString.length)); final Uri uri = Uri.parse(match[1]);
if (reportObservatoryUri != null) { if (reportObservatoryUri != null) {
await reportObservatoryUri(uri); await reportObservatoryUri(uri);
} }
......
...@@ -104,7 +104,7 @@ void main() { ...@@ -104,7 +104,7 @@ void main() {
testUsingContext('finds observatory port and forwards', () async { testUsingContext('finds observatory port and forwards', () async {
device.onGetLogReader = () { device.onGetLogReader = () {
fakeLogReader.addLine('Foo'); fakeLogReader.addLine('Foo');
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
return fakeLogReader; return fakeLogReader;
}; };
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
...@@ -133,7 +133,7 @@ void main() { ...@@ -133,7 +133,7 @@ void main() {
testUsingContext('Fails with tool exit on bad Observatory uri', () async { testUsingContext('Fails with tool exit on bad Observatory uri', () async {
device.onGetLogReader = () { device.onGetLogReader = () {
fakeLogReader.addLine('Foo'); fakeLogReader.addLine('Foo');
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
fakeLogReader.dispose(); fakeLogReader.dispose();
return fakeLogReader; return fakeLogReader;
}; };
...@@ -148,7 +148,7 @@ void main() { ...@@ -148,7 +148,7 @@ void main() {
testUsingContext('accepts filesystem parameters', () async { testUsingContext('accepts filesystem parameters', () async {
device.onGetLogReader = () { device.onGetLogReader = () {
fakeLogReader.addLine('Foo'); fakeLogReader.addLine('Foo');
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
return fakeLogReader; return fakeLogReader;
}; };
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
...@@ -223,7 +223,7 @@ void main() { ...@@ -223,7 +223,7 @@ void main() {
testUsingContext('exits when observatory-port is specified and debug-port is not', () async { testUsingContext('exits when observatory-port is specified and debug-port is not', () async {
device.onGetLogReader = () { device.onGetLogReader = () {
fakeLogReader.addLine('Foo'); fakeLogReader.addLine('Foo');
fakeLogReader.addLine('Observatory listening on http://127.0.0.1:$devicePort'); fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
return fakeLogReader; return fakeLogReader;
}; };
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
......
...@@ -200,7 +200,7 @@ void main() { ...@@ -200,7 +200,7 @@ void main() {
'10', '10',
'app.apk' 'app.apk'
], ],
stdout: '\n\nObservatory listening on http://127.0.0.1:456\n\n', stdout: '\n\nThe Dart VM service is listening on http://127.0.0.1:456\n\n',
)); ));
processManager.addCommand(kShaCommand); processManager.addCommand(kShaCommand);
processManager.addCommand(const FakeCommand( processManager.addCommand(const FakeCommand(
......
...@@ -370,7 +370,7 @@ void main() { ...@@ -370,7 +370,7 @@ void main() {
FakeCommand( FakeCommand(
command: testConfig.runDebugCommand, command: testConfig.runDebugCommand,
completer: runDebugCompleter, completer: runDebugCompleter,
stdout: 'Observatory listening on http://127.0.0.1:12345/abcd/\n', stdout: 'The Dart VM service is listening on http://127.0.0.1:12345/abcd/\n',
), ),
FakeCommand( FakeCommand(
command: testConfig.forwardPortCommand, command: testConfig.forwardPortCommand,
...@@ -411,7 +411,7 @@ void main() { ...@@ -411,7 +411,7 @@ void main() {
FakeCommand( FakeCommand(
command: testConfigNonForwarding.runDebugCommand, command: testConfigNonForwarding.runDebugCommand,
completer: runDebugCompleter, completer: runDebugCompleter,
stdout: 'Observatory listening on http://192.168.178.123:12345/abcd/\n' stdout: 'The Dart VM service is listening on http://192.168.178.123:12345/abcd/\n'
), ),
] ]
); );
...@@ -456,7 +456,7 @@ void main() { ...@@ -456,7 +456,7 @@ void main() {
FakeCommand( FakeCommand(
command: testConfig.runDebugCommand, command: testConfig.runDebugCommand,
completer: runDebugCompleter, completer: runDebugCompleter,
stdout: 'Observatory listening on http://127.0.0.1:12345/abcd/\n', stdout: 'The Dart VM service is listening on http://127.0.0.1:12345/abcd/\n',
), ),
FakeCommand( FakeCommand(
command: testConfig.forwardPortCommand, command: testConfig.forwardPortCommand,
......
...@@ -81,7 +81,7 @@ void main() { ...@@ -81,7 +81,7 @@ void main() {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['debug'], command: const <String>['debug'],
stdout: 'Observatory listening on http://127.0.0.1/0\n', stdout: 'The Dart VM service is listening on http://127.0.0.1/0\n',
completer: completer, completer: completer,
), ),
]); ]);
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['debug'], command: const <String>['debug'],
stdout: 'Observatory listening on http://127.0.0.1/0\n', stdout: 'The Dart VM service is listening on http://127.0.0.1/0\n',
completer: completer, completer: completer,
), ),
]); ]);
...@@ -140,7 +140,7 @@ void main() { ...@@ -140,7 +140,7 @@ void main() {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['debug'], command: const <String>['debug'],
stdout: 'Observatory listening on http://127.0.0.1/0\n', stdout: 'The Dart VM service is listening on http://127.0.0.1/0\n',
completer: completer, completer: completer,
environment: const <String, String>{ environment: const <String, String>{
'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true', 'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true',
...@@ -202,7 +202,7 @@ void main() { ...@@ -202,7 +202,7 @@ void main() {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['debug'], command: const <String>['debug'],
stdout: 'Observatory listening on http://127.0.0.1/0\n', stdout: 'The Dart VM service is listening on http://127.0.0.1/0\n',
completer: completer, completer: completer,
environment: const <String, String>{ environment: const <String, String>{
'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true', 'FLUTTER_ENGINE_SWITCH_1': 'enable-dart-profiling=true',
...@@ -251,7 +251,7 @@ void main() { ...@@ -251,7 +251,7 @@ void main() {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand( FakeCommand(
command: const <String>['debug', 'arg1', 'arg2'], command: const <String>['debug', 'arg1', 'arg2'],
stdout: 'Observatory listening on http://127.0.0.1/0\n', stdout: 'The Dart VM service is listening on http://127.0.0.1/0\n',
completer: completer, completer: completer,
), ),
]); ]);
......
...@@ -247,7 +247,7 @@ void main() { ...@@ -247,7 +247,7 @@ void main() {
'--packages=.dart_tool/package_config.json', '--packages=.dart_tool/package_config.json',
'example.dill' 'example.dill'
], ],
stdout: 'Observatory listening on http://localhost:1234', stdout: 'The Dart VM service is listening on http://localhost:1234',
stderr: 'failure', stderr: 'failure',
) )
]); ]);
......
...@@ -128,7 +128,7 @@ void main() { ...@@ -128,7 +128,7 @@ void main() {
// Start writing messages to the log reader. // Start writing messages to the log reader.
Timer.run(() { Timer.run(() {
deviceLogReader.addLine('Foo'); deviceLogReader.addLine('Foo');
deviceLogReader.addLine('Observatory listening on http://127.0.0.1:456'); deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:456');
}); });
final LaunchResult launchResult = await device.startApp(iosApp, final LaunchResult launchResult = await device.startApp(iosApp,
...@@ -166,7 +166,7 @@ void main() { ...@@ -166,7 +166,7 @@ void main() {
// Start writing messages to the log reader. // Start writing messages to the log reader.
Timer.run(() { Timer.run(() {
deviceLogReader.addLine('Foo'); deviceLogReader.addLine('Foo');
deviceLogReader.addLine('Observatory listening on http://127.0.0.1:456'); deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:456');
}); });
final LaunchResult launchResult = await device.startApp(iosApp, final LaunchResult launchResult = await device.startApp(iosApp,
...@@ -206,7 +206,7 @@ void main() { ...@@ -206,7 +206,7 @@ void main() {
Timer.run(() async { Timer.run(() async {
await Future<void>.delayed(const Duration(milliseconds: 1)); await Future<void>.delayed(const Duration(milliseconds: 1));
deviceLogReader.addLine('Foo'); deviceLogReader.addLine('Foo');
deviceLogReader.addLine('Observatory listening on http://127.0.0.1:456'); deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:456');
}); });
final LaunchResult launchResult = await device.startApp(iosApp, final LaunchResult launchResult = await device.startApp(iosApp,
...@@ -311,7 +311,7 @@ void main() { ...@@ -311,7 +311,7 @@ void main() {
// Start writing messages to the log reader. // Start writing messages to the log reader.
Timer.run(() { Timer.run(() {
deviceLogReader.addLine('Observatory listening on http://127.0.0.1:1234'); deviceLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:1234');
}); });
final LaunchResult launchResult = await device.startApp(iosApp, final LaunchResult launchResult = await device.startApp(iosApp,
......
...@@ -495,7 +495,7 @@ void main() { ...@@ -495,7 +495,7 @@ void main() {
..addCommand(const FakeCommand( ..addCommand(const FakeCommand(
command: <String>['tail', '-n', '0', '-F', 'system.log'], command: <String>['tail', '-n', '0', '-F', 'system.log'],
stdout: ''' stdout: '''
Dec 20 17:04:32 md32-11-vm1 My Super Awesome App[88374]: flutter: Observatory listening on http://127.0.0.1:64213/1Uoeu523990=/ Dec 20 17:04:32 md32-11-vm1 My Super Awesome App[88374]: flutter: The Dart VM service is listening on http://127.0.0.1:64213/1Uoeu523990=/
Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
)) ))
..addCommand(const FakeCommand( ..addCommand(const FakeCommand(
...@@ -514,7 +514,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' ...@@ -514,7 +514,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
final List<String> lines = await logReader.logLines.toList(); final List<String> lines = await logReader.logLines.toList();
expect(lines, <String>[ expect(lines, <String>[
'flutter: Observatory listening on http://127.0.0.1:64213/1Uoeu523990=/', 'flutter: The Dart VM service is listening on http://127.0.0.1:64213/1Uoeu523990=/',
]); ]);
expect(fakeProcessManager.hasRemainingExpectations, isFalse); expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
...@@ -529,7 +529,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' ...@@ -529,7 +529,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
..addCommand(const FakeCommand( ..addCommand(const FakeCommand(
command: <String>['tail', '-n', '0', '-F', 'system.log'], command: <String>['tail', '-n', '0', '-F', 'system.log'],
stdout: ''' stdout: '''
2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) Observatory listening on http://127.0.0.1:57701/ 2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) The Dart VM service is listening on http://127.0.0.1:57701/
2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) )))))))))) 2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) ))))))))))
2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) #0 Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)''' 2017-09-13 15:26:57.228948-0700 localhost My Super Awesome App[37195]: (Flutter) #0 Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)'''
)) ))
...@@ -549,7 +549,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text''' ...@@ -549,7 +549,7 @@ Dec 20 17:04:32 md32-11-vm1 Another App[88374]: Ignore this text'''
final List<String> lines = await logReader.logLines.toList(); final List<String> lines = await logReader.logLines.toList();
expect(lines, <String>[ expect(lines, <String>[
'Observatory listening on http://127.0.0.1:57701/', 'The Dart VM service is listening on http://127.0.0.1:57701/',
'))))))))))', '))))))))))',
'#0 Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)', '#0 Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)',
]); ]);
......
...@@ -61,7 +61,7 @@ void main() { ...@@ -61,7 +61,7 @@ void main() {
command: const <String>[ command: const <String>[
'/.tmp_rand0/flutter_preview.rand0/splash' '/.tmp_rand0/flutter_preview.rand0/splash'
], ],
stdout: 'Observatory listening on http://127.0.0.1:64494/fZ_B2N6JRwY=/\n', stdout: 'The Dart VM service is listening on http://127.0.0.1:64494/fZ_B2N6JRwY=/\n',
completer: completer, completer: completer,
) )
]), ]),
......
...@@ -154,7 +154,7 @@ void main() { ...@@ -154,7 +154,7 @@ void main() {
completer: completer, completer: completer,
stdout: stdout:
''' '''
Observatory listening on $observatoryUri The Dart VM service is listening on $observatoryUri
Hello! Hello!
''', ''',
)); ));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment