Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
48518888
Unverified
Commit
48518888
authored
Apr 08, 2020
by
Jonah Williams
Committed by
GitHub
Apr 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] Migrate to package:vm_service 4: trigonometric boogaloo (#54132)
parent
fc06d3fe
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
474 additions
and
551 deletions
+474
-551
devfs.dart
packages/flutter_tools/lib/src/devfs.dart
+2
-2
fuchsia_device.dart
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
+2
-2
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+14
-12
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+1
-1
run_hot.dart
packages/flutter_tools/lib/src/run_hot.dart
+20
-18
coverage_collector.dart
packages/flutter_tools/lib/src/test/coverage_collector.dart
+2
-2
tracing.dart
packages/flutter_tools/lib/src/tracing.dart
+3
-1
vmservice.dart
packages/flutter_tools/lib/src/vmservice.dart
+201
-177
pubspec.yaml
packages/flutter_tools/pubspec.yaml
+3
-4
devfs_test.dart
packages/flutter_tools/test/general.shard/devfs_test.dart
+2
-2
fuchsia_device_test.dart
...tools/test/general.shard/fuchsia/fuchsia_device_test.dart
+1
-1
ios_device_logger_test.dart
..._tools/test/general.shard/ios/ios_device_logger_test.dart
+38
-0
resident_runner_test.dart
...lutter_tools/test/general.shard/resident_runner_test.dart
+3
-3
vmservice_test.dart
...ages/flutter_tools/test/general.shard/vmservice_test.dart
+182
-326
No files found.
packages/flutter_tools/lib/src/devfs.dart
View file @
48518888
...
...
@@ -4,8 +4,8 @@
import
'dart:async'
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:meta/meta.dart'
;
import
'package:vm_service/vm_service.dart'
as
vmservice
;
import
'asset.dart'
;
import
'base/context.dart'
;
...
...
@@ -439,7 +439,7 @@ class DevFS {
globals
.
printTrace
(
'DevFS: Creating new filesystem on the device (
$_baseUri
)'
);
try
{
_baseUri
=
await
_operations
.
create
(
fsName
);
}
on
rpc
.
RpcException
catch
(
rpcException
)
{
}
on
vmservice
.
RPCError
catch
(
rpcException
)
{
// 1001 is kFileSystemAlreadyExists in //dart/runtime/vm/json_stream.h
if
(
rpcException
.
code
!=
1001
)
{
rethrow
;
...
...
packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
View file @
48518888
...
...
@@ -620,7 +620,7 @@ class FuchsiaDevice extends Device {
// loopback (::1).
final
Uri
uri
=
Uri
.
parse
(
'http://[
$_ipv6Loopback
]:
$port
'
);
final
VMService
vmService
=
await
VMService
.
connect
(
uri
);
await
vmService
.
getVM
();
await
vmService
.
getVM
Old
();
await
vmService
.
refreshViews
();
for
(
final
FlutterView
flutterView
in
vmService
.
vm
.
views
)
{
if
(
flutterView
.
uiIsolate
==
null
)
{
...
...
@@ -717,7 +717,7 @@ class FuchsiaIsolateDiscoveryProtocol {
continue
;
}
}
await
service
.
getVM
();
await
service
.
getVM
Old
();
await
service
.
refreshViews
();
for
(
final
FlutterView
flutterView
in
service
.
vm
.
views
)
{
if
(
flutterView
.
uiIsolate
==
null
)
{
...
...
packages/flutter_tools/lib/src/ios/devices.dart
View file @
48518888
...
...
@@ -7,11 +7,11 @@ import 'dart:math' as math;
import
'package:meta/meta.dart'
;
import
'package:platform/platform.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:process/process.dart'
;
import
'../application_package.dart'
;
import
'../artifacts.dart'
;
import
'../base/common.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/logger.dart'
;
...
...
@@ -514,7 +514,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
// and "Flutter". The regex tries to strike a balance between not producing
// false positives and not producing false negatives.
_anyLineRegex
=
RegExp
(
r'\w+(\([^)]*\))?\[\d+\] <[A-Za-z]+>: '
);
_loggingSubscriptions
=
<
StreamSubscription
<
ServiceEvent
>>[];
_loggingSubscriptions
=
<
StreamSubscription
<
void
>>[];
}
/// Create a new [IOSDeviceLogReader].
...
...
@@ -554,7 +554,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
RegExp
_anyLineRegex
;
StreamController
<
String
>
_linesController
;
List
<
StreamSubscription
<
ServiceEvent
>>
_loggingSubscriptions
;
List
<
StreamSubscription
<
void
>>
_loggingSubscriptions
;
@override
Stream
<
String
>
get
logLines
=>
_linesController
.
stream
;
...
...
@@ -575,18 +575,20 @@ class IOSDeviceLogReader extends DeviceLogReader {
if
(
_majorSdkVersion
<
_minimumUniversalLoggingSdkVersion
)
{
return
;
}
// The VM service will not publish logging events unless the debug stream is being listened to.
// onDebugEvent listens to this stream as a side effect.
unawaited
(
connectedVmService
.
onDebugEvent
);
_loggingSubscriptions
.
add
((
await
connectedVmService
.
onStdoutEvent
).
listen
((
ServiceEvent
event
)
{
final
String
logMessage
=
event
.
message
;
if
(
logMessage
.
isNotEmpty
)
{
_linesController
.
add
(
logMessage
);
try
{
await
connectedVmService
.
streamListen
(
'Stdout'
);
}
on
vm_service
.
RPCError
{
// Do nothing, since the tool is already subscribed.
}
_loggingSubscriptions
.
add
(
connectedVmService
.
onStdoutEvent
.
listen
((
vm_service
.
Event
event
)
{
final
String
message
=
utf8
.
decode
(
base64
.
decode
(
event
.
bytes
));
if
(
message
.
isNotEmpty
)
{
_linesController
.
add
(
message
);
}
}));
}
void
_listenToSysLog
()
{
void
_listenToSysLog
()
{
// syslog is not written on iOS 13+.
if
(
_majorSdkVersion
>=
_minimumUniversalLoggingSdkVersion
)
{
return
;
...
...
@@ -641,7 +643,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
@override
void
dispose
()
{
for
(
final
StreamSubscription
<
ServiceEvent
>
loggingSubscription
in
_loggingSubscriptions
)
{
for
(
final
StreamSubscription
<
void
>
loggingSubscription
in
_loggingSubscriptions
)
{
loggingSubscription
.
cancel
();
}
_idevicesyslogProcess
?.
kill
();
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
48518888
...
...
@@ -234,7 +234,7 @@ class FlutterDevice {
:
vmService
.
vm
.
views
).
toList
();
}
Future
<
void
>
getVMs
()
=>
vmService
.
getVM
();
Future
<
void
>
getVMs
()
=>
vmService
.
getVM
Old
();
Future
<
void
>
exitApps
()
async
{
if
(!
device
.
supportsFlutterExit
)
{
...
...
packages/flutter_tools/lib/src/run_hot.dart
View file @
48518888
...
...
@@ -3,10 +3,8 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:platform/platform.dart'
;
import
'package:json_rpc_2/error_code.dart'
as
rpc_error_code
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:meta/meta.dart'
;
import
'package:pool/pool.dart'
;
import
'base/async_guard.dart'
;
...
...
@@ -110,9 +108,10 @@ class HotRunner extends ResidentRunner {
// TODO(cbernaschina): check that isolateId is the id of the UI isolate.
final
OperationResult
result
=
await
restart
(
pause:
pause
);
if
(!
result
.
isOk
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
INTERNAL_ERROR
,
throw
vm_service
.
RPCError
(
'Unable to reload sources'
,
RPCErrorCodes
.
kInternalError
,
''
,
);
}
}
...
...
@@ -121,9 +120,10 @@ class HotRunner extends ResidentRunner {
final
OperationResult
result
=
await
restart
(
fullRestart:
true
,
pause:
pause
);
if
(!
result
.
isOk
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
INTERNAL_ERROR
,
throw
vm_service
.
RPCError
(
'Unable to restart'
,
RPCErrorCodes
.
kInternalError
,
''
,
);
}
}
...
...
@@ -564,16 +564,15 @@ class HotRunner extends ResidentRunner {
if
(
benchmarkMode
)
{
final
List
<
Future
<
void
>>
isolateNotifications
=
<
Future
<
void
>>[];
for
(
final
FlutterDevice
device
in
flutterDevices
)
{
try
{
await
device
.
vmService
.
streamListen
(
'Isolate'
);
}
on
vm_service
.
RPCError
{
// Do nothing, we're already subcribed.
}
for
(
final
FlutterView
view
in
device
.
views
)
{
isolateNotifications
.
add
(
view
.
owner
.
vm
.
vmService
.
onIsolateEvent
.
then
((
Stream
<
ServiceEvent
>
serviceEvents
)
async
{
await
for
(
final
ServiceEvent
serviceEvent
in
serviceEvents
)
{
if
(
serviceEvent
.
owner
.
name
.
contains
(
'_spawn'
)
&&
serviceEvent
.
kind
==
ServiceEvent
.
kIsolateExit
)
{
return
;
}
}
view
.
owner
.
vm
.
vmService
.
onIsolateEvent
.
firstWhere
((
vm_service
.
Event
event
)
{
return
event
.
kind
==
vm_service
.
EventKind
.
kServiceExtensionAdded
;
}),
);
}
...
...
@@ -720,9 +719,12 @@ class HotRunner extends ResidentRunner {
if
(!
result
.
isOk
)
{
restartEvent
=
'restart-failed'
;
}
}
on
rpc
.
RpcException
{
}
on
vm_service
.
SentinelException
catch
(
err
,
st
)
{
restartEvent
=
'exception'
;
return
OperationResult
(
1
,
'hot restart failed to complete:
$err
\n
$st
'
,
fatal:
true
);
}
on
vm_service
.
RPCError
catch
(
err
,
st
)
{
restartEvent
=
'exception'
;
return
OperationResult
(
1
,
'hot restart failed to complete'
,
fatal:
true
);
return
OperationResult
(
1
,
'hot restart failed to complete
:
$err
\n
$st
'
,
fatal:
true
);
}
finally
{
HotEvent
(
restartEvent
,
targetPlatform:
targetPlatform
,
...
...
@@ -764,7 +766,7 @@ class HotRunner extends ResidentRunner {
);
},
);
}
on
rpc
.
RpcException
{
}
on
vm_service
.
RPCError
{
HotEvent
(
'exception'
,
targetPlatform:
targetPlatform
,
sdkName:
sdkName
,
...
...
packages/flutter_tools/lib/src/test/coverage_collector.dart
View file @
48518888
...
...
@@ -189,7 +189,7 @@ Future<Map<String, dynamic>> collect(Uri serviceUri, bool Function(String) libra
Future
<
VMService
>
Function
(
Uri
)
connector
=
_defaultConnect
,
})
async
{
final
VMService
vmService
=
await
connector
(
serviceUri
);
await
vmService
.
getVM
();
await
vmService
.
getVM
Old
();
final
Map
<
String
,
dynamic
>
result
=
await
_getAllCoverage
(
vmService
,
libraryPredicate
);
await
vmService
.
close
();
...
...
@@ -197,7 +197,7 @@ Future<Map<String, dynamic>> collect(Uri serviceUri, bool Function(String) libra
}
Future
<
Map
<
String
,
dynamic
>>
_getAllCoverage
(
VMService
service
,
bool
Function
(
String
)
libraryPredicate
)
async
{
await
service
.
getVM
();
await
service
.
getVM
Old
();
final
List
<
Map
<
String
,
dynamic
>>
coverage
=
<
Map
<
String
,
dynamic
>>[];
for
(
final
Isolate
isolateRef
in
service
.
vm
.
isolates
)
{
await
isolateRef
.
load
();
...
...
packages/flutter_tools/lib/src/tracing.dart
View file @
48518888
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'base/file_system.dart'
;
import
'base/logger.dart'
;
...
...
@@ -45,7 +46,8 @@ class Tracing {
);
try
{
final
Completer
<
void
>
whenFirstFrameRendered
=
Completer
<
void
>();
(
await
vmService
.
onExtensionEvent
).
listen
((
ServiceEvent
event
)
{
await
vmService
.
streamListen
(
'Extension'
);
vmService
.
onExtensionEvent
.
listen
((
vm_service
.
Event
event
)
{
if
(
event
.
extensionKind
==
'Flutter.FirstFrame'
)
{
whenFirstFrameRendered
.
complete
();
}
...
...
packages/flutter_tools/lib/src/vmservice.dart
View file @
48518888
...
...
@@ -5,18 +5,14 @@
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'package:json_rpc_2/error_code.dart'
as
rpc_error_code
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:meta/meta.dart'
show
required
;
import
'package:stream_channel/stream_channel.dart'
;
import
'package:web_socket_channel/io.dart'
;
import
'package:web_socket_channel/web_socket_channel.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'base/common.dart'
;
import
'base/context.dart'
;
import
'base/io.dart'
as
io
;
import
'base/utils.dart'
;
import
'convert.dart'
show
base64
,
utf8
;
import
'convert.dart'
show
base64
,
json
,
utf8
;
import
'device.dart'
;
import
'globals.dart'
as
globals
;
import
'version.dart'
;
...
...
@@ -25,10 +21,24 @@ import 'version.dart';
/// for [WebSocket]s (used by tests).
typedef
WebSocketConnector
=
Future
<
io
.
WebSocket
>
Function
(
String
url
,
{
io
.
CompressionOptions
compression
});
/// A function that opens a two-way communication channel to the specified [uri].
typedef
_OpenChannel
=
Future
<
StreamChannel
<
String
>>
Function
(
Uri
uri
,
{
io
.
CompressionOptions
compression
});
WebSocketConnector
_openChannel
=
_defaultOpenChannel
;
_OpenChannel
_openChannel
=
_defaultOpenChannel
;
/// The error codes for the JSON-RPC standard.
///
/// See also: https://www.jsonrpc.org/specification#error_object
abstract
class
RPCErrorCodes
{
/// The method does not exist or is not available.
static
const
int
kMethodNotFound
=
-
32601
;
/// Invalid method parameter(s), such as a mismatched type.
static
const
int
kInvalidParams
=
-
32602
;
/// Internal JSON-RPC error.
static
const
int
kInternalError
=
-
32603
;
/// Application specific error codes.s
static
const
int
kServerError
=
-
32000
;
}
/// A function that reacts to the invocation of the 'reloadSources' service.
///
...
...
@@ -64,7 +74,9 @@ typedef ReloadMethod = Future<void> Function({
String
libraryId
,
});
Future
<
StreamChannel
<
String
>>
_defaultOpenChannel
(
Uri
uri
,
{
io
.
CompressionOptions
compression
=
io
.
CompressionOptions
.
compressionDefault
})
async
{
Future
<
io
.
WebSocket
>
_defaultOpenChannel
(
String
url
,
{
io
.
CompressionOptions
compression
=
io
.
CompressionOptions
.
compressionDefault
})
async
{
Duration
delay
=
const
Duration
(
milliseconds:
100
);
int
attempts
=
0
;
io
.
WebSocket
socket
;
...
...
@@ -90,14 +102,14 @@ Future<StreamChannel<String>> _defaultOpenChannel(Uri uri, {io.CompressionOption
while
(
socket
==
null
)
{
attempts
+=
1
;
try
{
socket
=
await
constructor
(
ur
i
.
toString
()
,
compression:
compression
);
socket
=
await
constructor
(
ur
l
,
compression:
compression
);
}
on
io
.
WebSocketException
catch
(
e
)
{
await
handleError
(
e
);
}
on
io
.
SocketException
catch
(
e
)
{
await
handleError
(
e
);
}
}
return
IOWebSocketChannel
(
socket
).
cast
<
String
>()
;
return
socket
;
}
/// Override `VMServiceConnector` in [context] to return a different VMService
...
...
@@ -112,10 +124,10 @@ typedef VMServiceConnector = Future<VMService> Function(Uri httpUri, {
});
/// A connection to the Dart VM Service.
// TODO(mklim): Test this, https://github.com/flutter/flutter/issues/23031
class
VMService
{
///
/// This also implements the package:vm_service API to enable a gradual migration.
class
VMService
implements
vm_service
.
VmService
{
VMService
(
this
.
_peer
,
this
.
httpAddress
,
this
.
wsAddress
,
ReloadSources
reloadSources
,
...
...
@@ -123,38 +135,49 @@ class VMService {
CompileExpression
compileExpression
,
Device
device
,
ReloadMethod
reloadMethod
,
this
.
_delegateService
,
this
.
streamClosedCompleter
,
Stream
<
dynamic
>
secondary
,
)
{
_vm
=
VM
.
_empty
(
this
);
_peer
.
listen
().
catchError
(
_connectionError
.
completeError
);
_peer
.
registerMethod
(
'streamNotify'
,
(
rpc
.
Parameters
event
)
{
_handleStreamNotify
(
event
.
asMap
.
cast
<
String
,
dynamic
>());
// TODO(jonahwilliams): this is temporary to support the current vm_service
// semantics of update-in-place.
secondary
.
listen
((
dynamic
rawData
)
{
final
String
message
=
rawData
as
String
;
final
dynamic
map
=
json
.
decode
(
message
);
if
(
map
!=
null
&&
map
[
'method'
]
==
'streamNotify'
)
{
_handleStreamNotify
(
map
[
'params'
]
as
Map
<
String
,
dynamic
>);
}
});
if
(
reloadSources
!=
null
)
{
_
peer
.
registerMethod
(
'reloadSources'
,
(
rpc
.
Parameters
params
)
async
{
_
delegateService
.
registerServiceCallback
(
'reloadSources'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
String
isolateId
=
params
[
'isolateId'
].
value
as
String
;
final
bool
force
=
params
.
asMap
[
'force'
]
as
bool
??
false
;
final
bool
pause
=
params
.
asMap
[
'pause'
]
as
bool
??
false
;
final
bool
force
=
params
[
'force'
]
as
bool
??
false
;
final
bool
pause
=
params
[
'pause'
]
as
bool
??
false
;
if
(
isolateId
.
isEmpty
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'isolateId':
$isolateId
"
);
throw
vm_service
.
RPCError
(
"Invalid 'isolateId':
$isolateId
"
,
RPCErrorCodes
.
kInvalidParams
,
''
,
);
}
try
{
await
reloadSources
(
isolateId
,
force:
force
,
pause:
pause
);
return
<
String
,
String
>{
'type'
:
'Success'
};
}
on
rpc
.
RpcException
{
}
on
vm_service
.
RPCError
{
rethrow
;
}
on
Exception
catch
(
e
,
st
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
SERVER_ERROR
,
'Error during Sources Reload:
$e
\n
$st
'
);
throw
vm_service
.
RPCError
(
'Error during Sources Reload:
$e
\n
$st
'
,
RPCErrorCodes
.
kServerError
,
''
,
);
}
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'reloadSources'
,
'alias'
:
'Flutter Tools'
,
});
_delegateService
.
registerService
(
'reloadSources'
,
'Flutter Tools'
);
}
...
...
@@ -168,15 +191,23 @@ class VMService {
// if the build method of a StatelessWidget is updated, this is the name of class.
// If the build method of a StatefulWidget is updated, then this is the name
// of the Widget class that created the State object.
_
peer
.
registerMethod
(
'reloadMethod'
,
(
rpc
.
Parameters
params
)
async
{
final
String
libraryId
=
params
[
'library'
]
.
value
as
String
;
final
String
classId
=
params
[
'class'
]
.
value
as
String
;
_
delegateService
.
registerServiceCallback
(
'reloadMethod'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
String
libraryId
=
params
[
'library'
]
as
String
;
final
String
classId
=
params
[
'class'
]
as
String
;
if
(
libraryId
.
isEmpty
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'libraryId':
$libraryId
"
);
throw
vm_service
.
RPCError
(
"Invalid 'libraryId':
$libraryId
"
,
RPCErrorCodes
.
kInvalidParams
,
''
,
);
}
if
(
classId
.
isEmpty
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'classId':
$classId
"
);
throw
vm_service
.
RPCError
(
"Invalid 'classId':
$classId
"
,
RPCErrorCodes
.
kInvalidParams
,
''
,
);
}
globals
.
printTrace
(
'reloadMethod not yet supported, falling back to hot reload'
);
...
...
@@ -187,111 +218,95 @@ class VMService {
classId:
classId
,
);
return
<
String
,
String
>{
'type'
:
'Success'
};
}
on
rpc
.
RpcException
{
}
on
vm_service
.
RPCError
{
rethrow
;
}
on
Exception
catch
(
e
,
st
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
SERVER_ERROR
,
'Error during Sources Reload:
$e
\n
$st
'
);
throw
vm_service
.
RPCError
(
'Error during Sources Reload:
$e
\n
$st
'
,
-
32000
,
''
);
}
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'reloadMethod'
,
'alias'
:
'Flutter Tools'
,
});
_delegateService
.
registerService
(
'reloadMethod'
,
'Flutter Tools'
);
}
if
(
restart
!=
null
)
{
_peer
.
registerMethod
(
'hotRestart'
,
(
rpc
.
Parameters
params
)
async
{
final
bool
pause
=
params
.
asMap
[
'pause'
]
as
bool
??
false
;
if
(
pause
is
!
bool
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'pause':
$pause
"
);
}
_delegateService
.
registerServiceCallback
(
'hotRestart'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
bool
pause
=
params
[
'pause'
]
as
bool
??
false
;
try
{
await
restart
(
pause:
pause
);
return
<
String
,
String
>{
'type'
:
'Success'
};
}
on
rpc
.
RpcException
{
}
on
vm_service
.
RPCError
{
rethrow
;
}
on
Exception
catch
(
e
,
st
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
SERVER_ERROR
,
'Error during Hot Restart:
$e
\n
$st
'
);
throw
vm_service
.
RPCError
(
'Error during Hot Restart:
$e
\n
$st
'
,
RPCErrorCodes
.
kServerError
,
''
,
);
}
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'hotRestart'
,
'alias'
:
'Flutter Tools'
,
});
_delegateService
.
registerService
(
'hotRestart'
,
'Flutter Tools'
);
}
_
peer
.
registerMethod
(
'flutterVersion'
,
(
rpc
.
Parameters
params
)
async
{
_
delegateService
.
registerServiceCallback
(
'flutterVersion'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
FlutterVersion
version
=
context
.
get
<
FlutterVersion
>()
??
FlutterVersion
();
final
Map
<
String
,
Object
>
versionJson
=
version
.
toJson
();
versionJson
[
'frameworkRevisionShort'
]
=
version
.
frameworkRevisionShort
;
versionJson
[
'engineRevisionShort'
]
=
version
.
engineRevisionShort
;
return
versionJson
;
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'flutterVersion'
,
'alias'
:
'Flutter Tools'
,
});
_delegateService
.
registerService
(
'flutterVersion'
,
'Flutter Tools'
);
if
(
compileExpression
!=
null
)
{
_
peer
.
registerMethod
(
'compileExpression'
,
(
rpc
.
Parameters
params
)
async
{
final
String
isolateId
=
params
[
'isolateId'
]
.
as
String
;
_
delegateService
.
registerServiceCallback
(
'compileExpression'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
String
isolateId
=
params
[
'isolateId'
]
as
String
;
if
(
isolateId
is
!
String
||
isolateId
.
isEmpty
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'isolateId':
$isolateId
"
);
throw
throw
vm_service
.
RPCError
(
"Invalid 'isolateId':
$isolateId
"
,
RPCErrorCodes
.
kInvalidParams
,
''
,
);
}
final
String
expression
=
params
[
'expression'
]
.
as
String
;
final
String
expression
=
params
[
'expression'
]
as
String
;
if
(
expression
is
!
String
||
expression
.
isEmpty
)
{
throw
rpc
.
RpcException
.
invalidParams
(
"Invalid 'expression':
$expression
"
);
throw
throw
vm_service
.
RPCError
(
"Invalid 'expression':
$expression
"
,
RPCErrorCodes
.
kInvalidParams
,
''
,
);
}
final
List
<
String
>
definitions
=
List
<
String
>.
from
(
params
[
'definitions'
].
asList
);
final
List
<
String
>
typeDefinitions
=
List
<
String
>.
from
(
params
[
'typeDefinitions'
].
asList
);
final
String
libraryUri
=
params
[
'libraryUri'
].
asString
;
final
String
klass
=
params
[
'klass'
].
exists
?
params
[
'klass'
].
asString
:
null
;
final
bool
isStatic
=
params
[
'isStatic'
].
asBoolOr
(
false
);
final
List
<
String
>
definitions
=
List
<
String
>.
from
(
params
[
'definitions'
]
as
List
<
dynamic
>);
final
List
<
String
>
typeDefinitions
=
List
<
String
>.
from
(
params
[
'typeDefinitions'
]
as
List
<
dynamic
>);
final
String
libraryUri
=
params
[
'libraryUri'
]
as
String
;
final
String
klass
=
params
[
'klass'
]
as
String
;
final
bool
isStatic
=
params
[
'isStatic'
]
as
bool
??
false
;
try
{
final
String
kernelBytesBase64
=
await
compileExpression
(
isolateId
,
expression
,
definitions
,
typeDefinitions
,
libraryUri
,
klass
,
isStatic
);
return
<
String
,
dynamic
>{
'type'
:
'Success'
,
'result'
:
<
String
,
dynamic
>
{
'kernelBytes'
:
kernelBytesBase64
}};
}
on
rpc
.
RpcException
{
return
<
String
,
dynamic
>{
'type'
:
'Success'
,
'result'
:
<
String
,
dynamic
>{
'result'
:
<
String
,
dynamic
>{
'kernelBytes'
:
kernelBytesBase64
},
},
};
}
on
vm_service
.
RPCError
{
rethrow
;
}
on
Exception
catch
(
e
,
st
)
{
throw
rpc
.
RpcException
(
rpc_error_code
.
SERVER_ERROR
,
'Error during expression compilation:
$e
\n
$st
'
);
throw
vm_service
.
RPCError
(
'Error during expression compilation:
$e
\n
$st
'
,
RPCErrorCodes
.
kServerError
,
''
,
);
}
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'compileExpression'
,
'alias'
:
'Flutter Tools'
,
});
_delegateService
.
registerService
(
'compileExpression'
,
'Flutter Tools'
);
}
if
(
device
!=
null
)
{
_
peer
.
registerMethod
(
'flutterMemoryInfo'
,
(
rpc
.
Parameters
params
)
async
{
_
delegateService
.
registerServiceCallback
(
'flutterMemoryInfo'
,
(
Map
<
String
,
dynamic
>
params
)
async
{
final
MemoryInfo
result
=
await
device
.
queryMemoryInfo
();
return
result
.
toJson
();
});
_peer
.
sendNotification
(
'registerService'
,
<
String
,
String
>{
'service'
:
'flutterMemoryInfo'
,
'alias'
:
'Flutter Tools'
,
});
}
_delegateService
.
registerService
(
'flutterMemoryInfo'
,
'Flutter Tools'
);
}
static
void
_unhandledError
(
dynamic
error
,
dynamic
stack
)
{
globals
.
logger
.
printTrace
(
'Error in internal implementation of JSON RPC.
\n
$error
\n
$stack
'
);
assert
(
false
);
}
/// Connect to a Dart VM Service at [httpUri].
...
...
@@ -332,10 +347,38 @@ class VMService {
Device
device
,
})
async
{
final
Uri
wsUri
=
httpUri
.
replace
(
scheme:
'ws'
,
path:
globals
.
fs
.
path
.
join
(
httpUri
.
path
,
'ws'
));
final
StreamChannel
<
String
>
channel
=
await
_openChannel
(
wsUri
,
compression:
compression
);
final
rpc
.
Peer
peer
=
rpc
.
Peer
.
withoutJson
(
jsonDocument
.
bind
(
channel
),
onUnhandledError:
_unhandledError
);
final
io
.
WebSocket
channel
=
await
_openChannel
(
wsUri
.
toString
(),
compression:
compression
);
final
StreamController
<
dynamic
>
primary
=
StreamController
<
dynamic
>();
final
StreamController
<
dynamic
>
secondary
=
StreamController
<
dynamic
>();
channel
.
listen
((
dynamic
data
)
{
primary
.
add
(
data
);
secondary
.
add
(
data
);
},
onDone:
()
{
primary
.
close
();
secondary
.
close
();
},
onError:
(
dynamic
error
,
StackTrace
stackTrace
)
{
primary
.
addError
(
error
,
stackTrace
);
secondary
.
addError
(
error
,
stackTrace
);
});
// Create an instance of the package:vm_service API in addition to the flutter
// tool's to allow gradual migration.
final
Completer
<
void
>
streamClosedCompleter
=
Completer
<
void
>();
final
vm_service
.
VmService
delegateService
=
vm_service
.
VmService
(
primary
.
stream
,
channel
.
add
,
log:
null
,
disposeHandler:
()
async
{
if
(!
streamClosedCompleter
.
isCompleted
)
{
streamClosedCompleter
.
complete
();
}
await
channel
.
close
();
},
);
final
VMService
service
=
VMService
(
peer
,
httpUri
,
wsUri
,
reloadSources
,
...
...
@@ -343,17 +386,21 @@ class VMService {
compileExpression
,
device
,
reloadMethod
,
delegateService
,
streamClosedCompleter
,
secondary
.
stream
,
);
// This call is to ensure we are able to establish a connection instead of
// keeping on trucking and failing farther down the process.
await
service
.
_sendRequest
(
'getVersion'
,
const
<
String
,
dynamic
>{}
);
await
delegateService
.
getVersion
(
);
return
service
;
}
final
vm_service
.
VmService
_delegateService
;
final
Uri
httpAddress
;
final
Uri
wsAddress
;
final
rpc
.
Peer
_peer
;
final
Completer
<
Map
<
String
,
dynamic
>>
_connectionError
=
Completer
<
Map
<
String
,
dynamic
>>();
final
Completer
<
void
>
streamClosedCompleter
;
VM
_vm
;
/// The singleton [VM] object. Owns [Isolate] and [FlutterView] objects.
...
...
@@ -362,46 +409,36 @@ class VMService {
final
Map
<
String
,
StreamController
<
ServiceEvent
>>
_eventControllers
=
<
String
,
StreamController
<
ServiceEvent
>>{};
final
Set
<
String
>
_listeningFor
=
<
String
>{};
/// Whether our connection to the VM service has been closed;
bool
get
isClosed
=>
_peer
.
isClos
ed
;
bool
get
isClosed
=>
streamClosedCompleter
.
isComplet
ed
;
Future
<
void
>
get
done
async
{
await
_peer
.
don
e
;
return
streamClosedCompleter
.
futur
e
;
}
// Events
Future
<
Stream
<
ServiceEvent
>>
get
onDebugEvent
=>
onEvent
(
'Debug'
);
Future
<
Stream
<
ServiceEvent
>>
get
onExtensionEvent
=>
onEvent
(
'Extension'
);
// IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, ServiceExtensionAdded
Future
<
Stream
<
ServiceEvent
>>
get
onIsolateEvent
=>
onEvent
(
'Isolate'
);
Future
<
Stream
<
ServiceEvent
>>
get
onTimelineEvent
=>
onEvent
(
'Timeline'
);
Future
<
Stream
<
ServiceEvent
>>
get
onStdoutEvent
=>
onEvent
(
'Stdout'
);
// WriteEvent
@override
Stream
<
vm_service
.
Event
>
get
onDebugEvent
=>
onEvent
(
'Debug'
);
// TODO(johnmccutchan): Add FlutterView events.
@override
Stream
<
vm_service
.
Event
>
get
onExtensionEvent
=>
onEvent
(
'Extension'
);
/// Returns a stream of VM service events.
///
/// This purposely returns a `Future<Stream<T>>` rather than a `Stream<T>`
/// because it first registers with the VM to receive events on the stream,
/// and only once the VM has acknowledged that the stream has started will
/// we return the associated stream. Any attempt to streamline this API into
/// returning `Stream<T>` should take that into account to avoid race
/// conditions.
Future
<
Stream
<
ServiceEvent
>>
onEvent
(
String
streamId
)
async
{
await
_streamListen
(
streamId
);
return
_getEventController
(
streamId
).
stream
;
}
Future
<
Map
<
String
,
dynamic
>>
_sendRequest
(
String
method
,
Map
<
String
,
dynamic
>
params
,
)
{
return
Future
.
any
<
Map
<
String
,
dynamic
>>(<
Future
<
Map
<
String
,
dynamic
>>>[
_peer
.
sendRequest
(
method
,
params
).
then
<
Map
<
String
,
dynamic
>>(
castStringKeyedMap
),
_connectionError
.
future
,
]);
@override
Stream
<
vm_service
.
Event
>
get
onIsolateEvent
=>
onEvent
(
'Isolate'
);
@override
Stream
<
vm_service
.
Event
>
get
onTimelineEvent
=>
onEvent
(
'Timeline'
);
@override
Stream
<
vm_service
.
Event
>
get
onStdoutEvent
=>
onEvent
(
'Stdout'
);
@override
Future
<
vm_service
.
Success
>
streamListen
(
String
streamId
)
{
return
_delegateService
.
streamListen
(
streamId
);
}
@override
Stream
<
vm_service
.
Event
>
onEvent
(
String
streamId
)
{
return
_delegateService
.
onEvent
(
streamId
);
}
StreamController
<
ServiceEvent
>
_getEventController
(
String
eventName
)
{
...
...
@@ -441,19 +478,20 @@ class VMService {
_getEventController
(
streamId
).
add
(
event
);
}
Future
<
void
>
_streamListen
(
String
streamId
)
async
{
if
(!
_listeningFor
.
contains
(
streamId
))
{
_listeningFor
.
add
(
streamId
);
await
_sendRequest
(
'streamListen'
,
<
String
,
dynamic
>{
'streamId'
:
streamId
});
}
}
/// Reloads the VM.
Future
<
void
>
getVM
()
async
=>
await
vm
.
reload
();
Future
<
void
>
getVM
Old
()
async
=>
await
vm
.
reload
();
Future
<
void
>
refreshViews
({
bool
waitForViews
=
false
})
=>
vm
.
refreshViews
(
waitForViews:
waitForViews
);
Future
<
void
>
close
()
async
=>
await
_peer
.
close
();
Future
<
void
>
close
()
async
{
_delegateService
?.
dispose
();
}
// To enable a gradual migration to package:vm_service
@override
dynamic
noSuchMethod
(
Invocation
invocation
)
{
throw
UnsupportedError
(
'
${invocation.memberName}
is not currently supported'
);
}
}
/// An error that is thrown when constructing/updating a service object.
...
...
@@ -936,36 +974,15 @@ class VM extends ServiceObjectOwner {
return
Future
<
Isolate
>.
value
(
_isolateCache
[
isolateId
]);
}
static
String
_truncate
(
String
message
,
int
width
,
String
ellipsis
)
{
assert
(
ellipsis
.
length
<
width
);
if
(
message
.
length
<=
width
)
{
return
message
;
}
return
message
.
substring
(
0
,
width
-
ellipsis
.
length
)
+
ellipsis
;
}
/// Invoke the RPC and return the raw response.
Future
<
Map
<
String
,
dynamic
>>
invokeRpcRaw
(
String
method
,
{
Map
<
String
,
dynamic
>
params
=
const
<
String
,
dynamic
>{},
bool
truncateLogs
=
true
,
})
async
{
globals
.
printTrace
(
'Sending to VM service:
$method
(
$params
)'
);
assert
(
params
!=
null
);
try
{
final
Map
<
String
,
dynamic
>
result
=
await
_vmService
.
_sendRequest
(
method
,
params
);
final
String
resultString
=
truncateLogs
?
_truncate
(
result
.
toString
(),
250
,
'...'
)
:
result
.
toString
();
globals
.
printTrace
(
'Result:
$resultString
'
);
return
result
;
}
on
WebSocketChannelException
catch
(
error
)
{
throwToolExit
(
'Error connecting to observatory:
$error
'
);
return
null
;
}
on
rpc
.
RpcException
catch
(
error
)
{
globals
.
printError
(
'Error
${error.code}
received from application:
${error.message}
'
);
globals
.
printTrace
(
'
${error.data}
'
);
rethrow
;
}
final
vm_service
.
Response
response
=
await
_vmService
.
_delegateService
.
callServiceExtension
(
method
,
args:
params
);
return
response
.
json
;
}
/// Invoke the RPC and return a [ServiceObject] response.
...
...
@@ -1264,13 +1281,17 @@ class Isolate extends ServiceObjectOwner {
}
final
Map
<
String
,
dynamic
>
response
=
await
invokeRpcRaw
(
'_reloadSources'
,
params:
arguments
);
return
response
;
}
on
rpc
.
RpcException
catch
(
e
)
{
}
on
vm_service
.
RPCError
catch
(
e
)
{
return
Future
<
Map
<
String
,
dynamic
>>.
value
(<
String
,
dynamic
>{
'code'
:
e
.
code
,
'message'
:
e
.
message
,
'data'
:
e
.
data
,
});
}
on
vm_service
.
SentinelException
catch
(
e
)
{
throwToolExit
(
'Unexpected Sentinel while reloading sources:
$e
'
);
}
assert
(
false
);
return
null
;
}
Future
<
Map
<
String
,
dynamic
>>
getObject
(
Map
<
String
,
dynamic
>
objectRef
)
{
...
...
@@ -1293,9 +1314,9 @@ class Isolate extends ServiceObjectOwner {
})
async
{
try
{
return
await
invokeRpcRaw
(
method
,
params:
params
);
}
on
rpc
.
RpcException
catch
(
e
)
{
}
on
vm_service
.
RPCError
catch
(
err
)
{
// If an application is not using the framework
if
(
e
.
code
==
rpc_error_code
.
METHOD_NOT_FOUND
)
{
if
(
e
rr
.
code
==
RPCErrorCodes
.
kMethodNotFound
)
{
return
null
;
}
rethrow
;
...
...
@@ -1491,10 +1512,13 @@ class FlutterView extends ServiceObject {
final
String
viewId
=
id
;
// When this completer completes the isolate is running.
final
Completer
<
void
>
completer
=
Completer
<
void
>();
final
StreamSubscription
<
ServiceEvent
>
subscription
=
(
await
owner
.
vm
.
vmService
.
onIsolateEvent
).
listen
((
ServiceEvent
event
)
{
// TODO(johnmccutchan): Listen to the debug stream and catch initial
// launch errors.
try
{
await
owner
.
vm
.
vmService
.
streamListen
(
'Isolate'
);
}
on
vm_service
.
RPCError
{
// Do nothing, since the tool is already subscribed.
}
final
StreamSubscription
<
vm_service
.
Event
>
subscription
=
owner
.
vm
.
vmService
.
onIsolateEvent
.
listen
((
vm_service
.
Event
event
)
{
if
(
event
.
kind
==
ServiceEvent
.
kIsolateRunnable
)
{
globals
.
printTrace
(
'Isolate is runnable.'
);
if
(!
completer
.
isCompleted
)
{
...
...
packages/flutter_tools/pubspec.yaml
View file @
48518888
...
...
@@ -19,7 +19,6 @@ dependencies:
flutter_template_images
:
1.0.1
http
:
0.12.0+4
intl
:
0.16.1
json_rpc_2
:
2.1.0
meta
:
1.1.8
multicast_dns
:
0.2.2
mustache_template
:
1.0.0+1
...
...
@@ -28,10 +27,8 @@ dependencies:
process
:
3.0.12
quiver
:
2.1.3
stack_trace
:
1.9.3
stream_channel
:
2.0.0
usage
:
3.4.1
webdriver
:
2.1.2
web_socket_channel
:
1.1.0
webkit_inspection_protocol
:
0.5.0+1
xml
:
3.7.0
yaml
:
2.2.0
...
...
@@ -88,6 +85,7 @@ dependencies:
source_maps
:
0.10.9
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
source_span
:
1.7.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
sse
:
3.2.2
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stream_channel
:
2.0.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
stream_transform
:
1.2.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
string_scanner
:
1.0.5
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
sync_http
:
0.2.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
...
...
@@ -95,6 +93,7 @@ dependencies:
typed_data
:
1.1.6
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
uuid
:
2.0.4
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
watcher
:
0.9.7+14
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
web_socket_channel
:
1.1.0
# THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
dev_dependencies
:
collection
:
1.14.12
...
...
@@ -112,4 +111,4 @@ dartdoc:
# Exclude this package from the hosted API docs.
nodoc
:
true
# PUBSPEC CHECKSUM:
8ac6
# PUBSPEC CHECKSUM:
7689
packages/flutter_tools/test/general.shard/devfs_test.dart
View file @
48518888
...
...
@@ -15,8 +15,8 @@ import 'package:flutter_tools/src/base/os.dart';
import
'package:flutter_tools/src/compile.dart'
;
import
'package:flutter_tools/src/devfs.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:mockito/mockito.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
...
...
@@ -403,7 +403,7 @@ class MockVM implements VM {
Future
<
Map
<
String
,
dynamic
>>
createDevFS
(
String
fsName
)
async
{
_service
.
messages
.
add
(
'create
$fsName
'
);
if
(
_devFSExists
)
{
throw
rpc
.
RpcException
(
kFileSystemAlreadyExists
,
'File system already exists
'
);
throw
vm_service
.
RPCError
(
'File system already exists'
,
kFileSystemAlreadyExists
,
'
'
);
}
_devFSExists
=
true
;
return
<
String
,
dynamic
>{
'uri'
:
'
$_baseUri
'
};
...
...
packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
View file @
48518888
...
...
@@ -596,7 +596,7 @@ void main() {
.
thenAnswer
((
Invocation
invocation
)
async
=>
<
int
>[
1
]);
when
(
portForwarder
.
forward
(
1
))
.
thenAnswer
((
Invocation
invocation
)
async
=>
2
);
when
(
vmService
.
getVM
())
when
(
vmService
.
getVM
Old
())
.
thenAnswer
((
Invocation
invocation
)
=>
Future
<
void
>.
value
(
null
));
when
(
vmService
.
refreshViews
())
.
thenAnswer
((
Invocation
invocation
)
=>
Future
<
void
>.
value
(
null
));
...
...
packages/flutter_tools/test/general.shard/ios/ios_device_logger_test.dart
View file @
48518888
...
...
@@ -2,13 +2,18 @@
// 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/artifacts.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/convert.dart'
;
import
'package:flutter_tools/src/device.dart'
;
import
'package:flutter_tools/src/ios/devices.dart'
;
import
'package:flutter_tools/src/ios/mac.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:vm_service/vm_service.dart'
;
import
'../../src/common.dart'
;
import
'../../src/context.dart'
;
...
...
@@ -137,6 +142,39 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
' with a non-Flutter log message following it.'
,
]);
});
testWithoutContext
(
'IOSDeviceLogReader can listen to VM Service logs'
,
()
async
{
final
MockVmService
vmService
=
MockVmService
();
final
DeviceLogReader
logReader
=
IOSDeviceLogReader
.
test
(
useSyslog:
false
,
iMobileDevice:
IMobileDevice
(
artifacts:
artifacts
,
processManager:
processManager
,
cache:
fakeCache
,
logger:
logger
,
),
);
final
StreamController
<
Event
>
controller
=
StreamController
<
Event
>();
final
Completer
<
Success
>
stdoutCompleter
=
Completer
<
Success
>();
when
(
vmService
.
streamListen
(
'Stdout'
)).
thenAnswer
((
Invocation
invocation
)
{
return
stdoutCompleter
.
future
;
});
when
(
vmService
.
onStdoutEvent
).
thenAnswer
((
Invocation
invocation
)
{
return
controller
.
stream
;
});
logReader
.
connectedVMService
=
vmService
;
stdoutCompleter
.
complete
(
Success
());
controller
.
add
(
Event
(
kind:
'Stdout'
,
timestamp:
0
,
bytes:
base64
.
encode
(
utf8
.
encode
(
' This is a message '
)),
));
// Wait for stream listeners to fire.
await
expectLater
(
logReader
.
logLines
,
emits
(
' This is a message '
));
});
}
class
MockArtifacts
extends
Mock
implements
Artifacts
{}
class
MockVmService
extends
Mock
implements
VMService
,
VmService
{}
packages/flutter_tools/test/general.shard/resident_runner_test.dart
View file @
48518888
...
...
@@ -24,8 +24,8 @@ import 'package:flutter_tools/src/resident_runner.dart';
import
'package:flutter_tools/src/run_cold.dart'
;
import
'package:flutter_tools/src/run_hot.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:json_rpc_2/json_rpc_2.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
...
...
@@ -224,7 +224,7 @@ void main() {
pathToReload:
anyNamed
(
'pathToReload'
),
invalidatedFiles:
anyNamed
(
'invalidatedFiles'
),
dillOutputPath:
anyNamed
(
'dillOutputPath'
),
)).
thenThrow
(
RpcException
(
666
,
'something bad happened
'
));
)).
thenThrow
(
vm_service
.
RPCError
(
'something bad happened'
,
666
,
'
'
));
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
fatal
,
true
);
...
...
@@ -329,7 +329,7 @@ void main() {
pathToReload:
anyNamed
(
'pathToReload'
),
invalidatedFiles:
anyNamed
(
'invalidatedFiles'
),
dillOutputPath:
anyNamed
(
'dillOutputPath'
),
)).
thenThrow
(
RpcException
(
666
,
'something bad happened
'
));
)).
thenThrow
(
vm_service
.
RPCError
(
'something bad happened'
,
666
,
'
'
));
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
true
);
expect
(
result
.
fatal
,
true
);
...
...
packages/flutter_tools/test/general.shard/vmservice_test.dart
View file @
48518888
...
...
@@ -3,95 +3,18 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:io'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:mockito/mockito.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
import
'package:flutter_tools/src/base/terminal.dart'
;
import
'package:flutter_tools/src/device.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
import
'package:flutter_tools/src/version.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:mockito/mockito.dart'
;
import
'package:platform/platform.dart'
;
import
'package:quiver/testing/async.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
import
'../src/mocks.dart'
;
class
MockPeer
implements
rpc
.
Peer
{
Function
_versionFn
=
(
dynamic
_
)
=>
null
;
@override
rpc
.
ErrorCallback
get
onUnhandledError
=>
null
;
@override
Future
<
dynamic
>
get
done
async
{
throw
'unexpected call to done'
;
}
@override
bool
get
isClosed
=>
_isClosed
;
@override
Future
<
dynamic
>
close
()
async
{
_isClosed
=
true
;
}
@override
Future
<
dynamic
>
listen
()
async
{
// this does get called
}
@override
void
registerFallback
(
dynamic
callback
(
rpc
.
Parameters
parameters
))
{
throw
'unexpected call to registerFallback'
;
}
@override
void
registerMethod
(
String
name
,
Function
callback
)
{
registeredMethods
.
add
(
name
);
if
(
name
==
'flutterVersion'
)
{
_versionFn
=
callback
;
}
}
@override
void
sendNotification
(
String
method
,
[
dynamic
parameters
])
{
// this does get called
sentNotifications
.
putIfAbsent
(
method
,
()
=>
<
dynamic
>[]).
add
(
parameters
);
}
Map
<
String
,
List
<
dynamic
>>
sentNotifications
=
<
String
,
List
<
dynamic
>>{};
List
<
String
>
registeredMethods
=
<
String
>[];
bool
isolatesEnabled
=
false
;
bool
_isClosed
=
false
;
Future
<
void
>
_getVMLatch
;
Completer
<
void
>
_currentGetVMLatchCompleter
;
void
tripGetVMLatch
()
{
final
Completer
<
void
>
lastCompleter
=
_currentGetVMLatchCompleter
;
_currentGetVMLatchCompleter
=
Completer
<
void
>();
_getVMLatch
=
_currentGetVMLatchCompleter
.
future
;
lastCompleter
?.
complete
();
}
int
returnedFromSendRequest
=
0
;
@override
Future
<
dynamic
>
sendRequest
(
String
method
,
[
dynamic
parameters
])
async
{
if
(
method
==
'getVM'
)
{
await
_getVMLatch
;
}
await
Future
<
void
>.
delayed
(
Duration
.
zero
);
returnedFromSendRequest
+=
1
;
if
(
method
==
'getVM'
)
{
return
<
String
,
dynamic
>{
final
Map
<
String
,
Object
>
vm
=
<
String
,
dynamic
>{
'type'
:
'VM'
,
'name'
:
'vm'
,
'architectureBits'
:
64
,
...
...
@@ -105,7 +28,7 @@ class MockPeer implements rpc.Peer {
'_embedder'
:
'Flutter'
,
'_maxRSS'
:
312614912
,
'_currentRSS'
:
33091584
,
'isolates'
:
isolatesEnabled
?
<
dynamic
>[
'isolates'
:
<
dynamic
>[
<
String
,
dynamic
>{
'type'
:
'@Isolate'
,
'fixedId'
:
true
,
...
...
@@ -113,11 +36,11 @@ class MockPeer implements rpc.Peer {
'name'
:
'main.dart:main()'
,
'number'
:
242098474
,
},
]
:
<
dynamic
>[
],
};
}
if
(
method
==
'getIsolate'
)
{
return
<
String
,
dynamic
>{
],
};
final
vm_service
.
Isolate
isolate
=
vm_service
.
Isolate
.
parse
(
<
String
,
dynamic
>{
'type'
:
'Isolate'
,
'fixedId'
:
true
,
'id'
:
'isolates/242098474'
,
...
...
@@ -143,12 +66,12 @@ class MockPeer implements rpc.Peer {
'avgCollectionPeriodMillis'
:
0.0
,
},
},
};
}
if
(
method
==
'_flutter.listViews'
)
{
return
<
String
,
dynamic
>{
);
final
Map
<
String
,
Object
>
listViews
=
<
String
,
dynamic
>{
'type'
:
'FlutterViewList'
,
'views'
:
isolatesEnabled
?
<
dynamic
>[
'views'
:
<
dynamic
>[
<
String
,
dynamic
>{
'type'
:
'FlutterView'
,
'id'
:
'_flutterView/0x4a4c1f8'
,
...
...
@@ -160,205 +83,138 @@ class MockPeer implements rpc.Peer {
'number'
:
242098474
,
},
},
]
:
<
dynamic
>[],
};
}
if
(
method
==
'flutterVersion'
)
{
return
_versionFn
(
parameters
);
}
return
null
;
}
]
};
@override
dynamic
withBatch
(
dynamic
callback
())
{
throw
'unexpected call to withBatch'
;
}
}
typedef
ServiceCallback
=
Future
<
Map
<
String
,
dynamic
>>
Function
(
Map
<
String
,
Object
>);
void
main
(
)
{
MockStdio
mockStdio
;
final
MockFlutterVersion
mockVersion
=
MockFlutterVersion
();
group
(
'VMService'
,
()
{
setUp
(()
{
mockStdio
=
MockStdio
();
testUsingContext
(
'VMService can refreshViews'
,
()
async
{
final
MockVMService
mockVmService
=
MockVMService
();
final
VMService
vmService
=
VMService
(
null
,
null
,
null
,
null
,
null
,
null
,
null
,
mockVmService
,
Completer
<
void
>(),
const
Stream
<
dynamic
>.
empty
(),
);
verify
(
mockVmService
.
registerService
(
'flutterVersion'
,
'Flutter Tools'
)).
called
(
1
);
when
(
mockVmService
.
callServiceExtension
(
'getVM'
,
args:
anyNamed
(
'args'
),
// Empty
isolateId:
null
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Response
.
parse
(
vm
);
});
await
vmService
.
getVMOld
();
testUsingContext
(
'fails connection eagerly in the connect() method'
,
()
async
{
FakeAsync
().
run
((
FakeAsync
time
)
{
bool
failed
=
false
;
final
Future
<
VMService
>
future
=
VMService
.
connect
(
Uri
.
parse
(
'http://host.invalid:9999/'
));
future
.
whenComplete
(()
{
failed
=
true
;
});
time
.
elapse
(
const
Duration
(
seconds:
5
));
expect
(
failed
,
isFalse
);
expect
(
mockStdio
.
writtenToStdout
.
join
(
''
),
''
);
expect
(
mockStdio
.
writtenToStderr
.
join
(
''
),
''
);
time
.
elapse
(
const
Duration
(
seconds:
5
));
expect
(
failed
,
isFalse
);
expect
(
mockStdio
.
writtenToStdout
.
join
(
''
),
'This is taking longer than expected...
\n
'
);
expect
(
mockStdio
.
writtenToStderr
.
join
(
''
),
''
);
});
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
StdoutLogger
(
outputPreferences:
OutputPreferences
.
test
(),
stdio:
mockStdio
,
terminal:
AnsiTerminal
(
stdio:
mockStdio
,
platform:
const
LocalPlatform
(),
),
timeoutConfiguration:
const
TimeoutConfiguration
(),
),
WebSocketConnector:
()
=>
(
String
url
,
{
CompressionOptions
compression
})
async
=>
throw
const
SocketException
(
'test'
),
});
testUsingContext
(
'closing VMService closes Peer'
,
()
async
{
final
MockPeer
mockPeer
=
MockPeer
();
final
VMService
vmService
=
VMService
(
mockPeer
,
null
,
null
,
null
,
null
,
null
,
MockDevice
(),
null
);
expect
(
mockPeer
.
isClosed
,
equals
(
false
));
await
vmService
.
close
();
expect
(
mockPeer
.
isClosed
,
equals
(
true
));
when
(
mockVmService
.
callServiceExtension
(
'_flutter.listViews'
,
args:
anyNamed
(
'args'
),
isolateId:
anyNamed
(
'isolateId'
)
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Response
.
parse
(
listViews
);
});
await
vmService
.
refreshViews
(
waitForViews:
true
);
testUsingContext
(
'refreshViews'
,
()
{
FakeAsync
().
run
((
FakeAsync
time
)
{
bool
done
=
false
;
final
MockPeer
mockPeer
=
MockPeer
();
expect
(
mockPeer
.
returnedFromSendRequest
,
0
);
final
VMService
vmService
=
VMService
(
mockPeer
,
null
,
null
,
null
,
null
,
null
,
null
,
null
);
expect
(
mockPeer
.
sentNotifications
,
contains
(
'registerService'
));
final
List
<
String
>
registeredServices
=
mockPeer
.
sentNotifications
[
'registerService'
]
.
map
((
dynamic
service
)
=>
(
service
as
Map
<
String
,
String
>)[
'service'
])
.
toList
();
expect
(
registeredServices
,
contains
(
'flutterVersion'
));
vmService
.
getVM
().
then
((
void
value
)
{
done
=
true
;
});
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
0
);
time
.
elapse
(
Duration
.
zero
);
expect
(
done
,
isTrue
);
expect
(
mockPeer
.
returnedFromSendRequest
,
1
);
done
=
false
;
mockPeer
.
tripGetVMLatch
();
// this blocks the upcoming getVM call
final
Future
<
void
>
ready
=
vmService
.
refreshViews
(
waitForViews:
true
);
ready
.
then
((
void
value
)
{
done
=
true
;
});
expect
(
mockPeer
.
returnedFromSendRequest
,
1
);
time
.
elapse
(
Duration
.
zero
);
// this unblocks the listViews call which returns nothing
expect
(
mockPeer
.
returnedFromSendRequest
,
2
);
time
.
elapse
(
const
Duration
(
milliseconds:
50
));
// the last listViews had no views, so it waits 50ms, then calls getVM
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
2
);
mockPeer
.
tripGetVMLatch
();
// this unblocks the getVM call
expect
(
mockPeer
.
returnedFromSendRequest
,
2
);
time
.
elapse
(
Duration
.
zero
);
// here getVM returns with no isolates and listViews returns no views
expect
(
mockPeer
.
returnedFromSendRequest
,
4
);
time
.
elapse
(
const
Duration
(
milliseconds:
50
));
// so refreshViews waits another 50ms
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
4
);
mockPeer
.
tripGetVMLatch
();
// this unblocks the getVM call
expect
(
mockPeer
.
returnedFromSendRequest
,
4
);
time
.
elapse
(
Duration
.
zero
);
// here getVM returns with no isolates and listViews returns no views
expect
(
mockPeer
.
returnedFromSendRequest
,
6
);
time
.
elapse
(
const
Duration
(
milliseconds:
50
));
// so refreshViews waits another 50ms
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
6
);
mockPeer
.
tripGetVMLatch
();
// this unblocks the getVM call
expect
(
mockPeer
.
returnedFromSendRequest
,
6
);
time
.
elapse
(
Duration
.
zero
);
// here getVM returns with no isolates and listViews returns no views
expect
(
mockPeer
.
returnedFromSendRequest
,
8
);
time
.
elapse
(
const
Duration
(
milliseconds:
50
));
// so refreshViews waits another 50ms
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
8
);
mockPeer
.
tripGetVMLatch
();
// this unblocks the getVM call
expect
(
mockPeer
.
returnedFromSendRequest
,
8
);
time
.
elapse
(
Duration
.
zero
);
// here getVM returns with no isolates and listViews returns no views
expect
(
mockPeer
.
returnedFromSendRequest
,
10
);
const
String
message
=
'Flutter is taking longer than expected to report its views. Still trying...
\n
'
;
expect
(
mockStdio
.
writtenToStdout
.
join
(
''
),
message
);
expect
(
mockStdio
.
writtenToStderr
.
join
(
''
),
''
);
time
.
elapse
(
const
Duration
(
milliseconds:
50
));
// so refreshViews waits another 50ms
expect
(
done
,
isFalse
);
expect
(
mockPeer
.
returnedFromSendRequest
,
10
);
mockPeer
.
isolatesEnabled
=
true
;
mockPeer
.
tripGetVMLatch
();
// this unblocks the getVM call
expect
(
mockPeer
.
returnedFromSendRequest
,
10
);
time
.
elapse
(
Duration
.
zero
);
// now it returns an isolate and the listViews call returns views
expect
(
mockPeer
.
returnedFromSendRequest
,
13
);
expect
(
done
,
isTrue
);
expect
(
mockStdio
.
writtenToStdout
.
join
(
''
),
message
);
expect
(
mockStdio
.
writtenToStderr
.
join
(
''
),
''
);
});
expect
(
vmService
.
vm
.
name
,
'vm'
);
expect
(
vmService
.
vm
.
views
.
single
.
id
,
'_flutterView/0x4a4c1f8'
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
StdoutLogger
(
outputPreferences:
globals
.
outputPreferences
,
terminal:
AnsiTerminal
(
stdio:
mockStdio
,
platform:
const
LocalPlatform
(),
),
stdio:
mockStdio
,
timeoutConfiguration:
const
TimeoutConfiguration
(),
),
Logger:
()
=>
BufferLogger
.
test
()
});
testUsingContext
(
'registers hot UI method'
,
()
{
FakeAsync
().
run
((
FakeAsync
time
)
{
final
MockPeer
mockPeer
=
MockPeer
();
Future
<
void
>
reloadMethod
({
String
classId
,
String
libraryId
})
async
{}
VMService
(
mockPeer
,
null
,
null
,
null
,
null
,
null
,
null
,
reloadMethod
);
expect
(
mockPeer
.
registeredMethods
,
contains
(
'reloadMethod'
));
testUsingContext
(
'VmService registers reloadSources'
,
()
{
Future
<
void
>
reloadSources
(
String
isolateId
,
{
bool
pause
,
bool
force
})
async
{}
final
MockVMService
mockVMService
=
MockVMService
();
VMService
(
null
,
null
,
reloadSources
,
null
,
null
,
null
,
null
,
mockVMService
,
Completer
<
void
>(),
const
Stream
<
dynamic
>.
empty
(),
);
verify
(
mockVMService
.
registerService
(
'reloadSources'
,
'Flutter Tools'
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
BufferLogger
.
test
()
});
testUsingContext
(
'VmService registers reloadMethod'
,
()
{
Future
<
void
>
reloadMethod
({
String
classId
,
String
libraryId
,})
async
{}
final
MockVMService
mockVMService
=
MockVMService
();
VMService
(
null
,
null
,
null
,
null
,
null
,
null
,
reloadMethod
,
mockVMService
,
Completer
<
void
>(),
const
Stream
<
dynamic
>.
empty
(),
);
verify
(
mockVMService
.
registerService
(
'reloadMethod'
,
'Flutter Tools'
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
StdoutLogger
(
outputPreferences:
globals
.
outputPreferences
,
terminal:
AnsiTerminal
(
stdio:
mockStdio
,
platform:
const
LocalPlatform
(),
),
stdio:
mockStdio
,
timeoutConfiguration:
const
TimeoutConfiguration
(),
),
Logger:
()
=>
BufferLogger
.
test
()
});
testUsingContext
(
'registers flutterMemoryInfo service'
,
()
{
FakeAsync
().
run
((
FakeAsync
time
)
{
testUsingContext
(
'VmService registers flutterMemoryInfo service'
,
()
{
final
MockDevice
mockDevice
=
MockDevice
();
final
MockPeer
mockPeer
=
MockPeer
();
Future
<
void
>
reloadSources
(
String
isolateId
,
{
bool
pause
,
bool
force
})
async
{}
VMService
(
mockPeer
,
null
,
null
,
reloadSources
,
null
,
null
,
mockDevice
,
null
);
expect
(
mockPeer
.
registeredMethods
,
contains
(
'flutterMemoryInfo'
));
});
final
MockVMService
mockVMService
=
MockVMService
();
VMService
(
null
,
null
,
null
,
null
,
null
,
mockDevice
,
null
,
mockVMService
,
Completer
<
void
>(),
const
Stream
<
dynamic
>.
empty
(),
);
verify
(
mockVMService
.
registerService
(
'flutterMemoryInfo'
,
'Flutter Tools'
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
StdoutLogger
(
outputPreferences:
globals
.
outputPreferences
,
terminal:
AnsiTerminal
(
stdio:
mockStdio
,
platform:
const
LocalPlatform
(),
),
stdio:
mockStdio
,
timeoutConfiguration:
const
TimeoutConfiguration
(),
),
Logger:
()
=>
BufferLogger
.
test
()
});
testUsingContext
(
'returns correct FlutterVersion'
,
()
{
FakeAsync
().
run
((
FakeAsync
time
)
async
{
final
MockPeer
mockPeer
=
MockPeer
();
VMService
(
mockPeer
,
null
,
null
,
null
,
null
,
null
,
MockDevice
(),
null
);
expect
(
mockPeer
.
registeredMethods
,
contains
(
'flutterVersion'
));
expect
(
await
mockPeer
.
sendRequest
(
'flutterVersion'
),
equals
(
mockVersion
.
toJson
()));
});
testUsingContext
(
'VMService returns correct FlutterVersion'
,
()
async
{
final
MockVMService
mockVMService
=
MockVMService
();
VMService
(
null
,
null
,
null
,
null
,
null
,
null
,
null
,
mockVMService
,
Completer
<
void
>(),
const
Stream
<
dynamic
>.
empty
(),
);
verify
(
mockVMService
.
registerService
(
'flutterVersion'
,
'Flutter Tools'
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
FlutterVersion:
()
=>
mockVersion
,
});
FlutterVersion:
()
=>
MockFlutterVersion
(),
});
}
class
MockDevice
extends
Mock
implements
Device
{}
class
MockVMService
extends
Mock
implements
vm_service
.
VmService
{}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{
@override
Map
<
String
,
Object
>
toJson
()
=>
const
<
String
,
Object
>{
'Mock'
:
'Version'
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment