Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Side by Side Diff: lib/src/isolate.dart

Issue 1670283002: add sendRequest to VMIsolateRef Base URL: git@github.com:yjbanov/vm_service_client.git@master
Patch Set: dartdocs Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/src/scope.dart » ('j') | test/isolate_test.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:collection'; 6 import 'dart:collection';
7 7
8 import 'package:async/async.dart'; 8 import 'package:async/async.dart';
9 import 'package:crypto/crypto.dart'; 9 import 'package:crypto/crypto.dart';
10 import 'package:json_rpc_2/json_rpc_2.dart' as rpc; 10 import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 /// A broadcast stream that emits a [VMPauseEvent] whenever this isolate is 61 /// A broadcast stream that emits a [VMPauseEvent] whenever this isolate is
62 /// paused or resumed. 62 /// paused or resumed.
63 Stream<VMPauseEvent> get onPauseOrResume => _onPauseOrResume; 63 Stream<VMPauseEvent> get onPauseOrResume => _onPauseOrResume;
64 Stream<VMPauseEvent> _onPauseOrResume; 64 Stream<VMPauseEvent> _onPauseOrResume;
65 65
66 /// A broadcast stream that emits a [VMBreakpoint] whenever a breakpoint is 66 /// A broadcast stream that emits a [VMBreakpoint] whenever a breakpoint is
67 /// added. 67 /// added.
68 Stream<VMBreakpoint> get onBreakpointAdded => _onBreakpointAdded; 68 Stream<VMBreakpoint> get onBreakpointAdded => _onBreakpointAdded;
69 Stream<VMBreakpoint> _onBreakpointAdded; 69 Stream<VMBreakpoint> _onBreakpointAdded;
70 70
71 /// A broadcast stream that emits custom events posted via `postEvent` from
72 /// the `dart:developer` package.
73 Stream<VMExtensionEvent> get onExtensionEvent => _onExtensionEvent;
74 Stream<VMExtensionEvent> _onExtensionEvent;
75
76 /// A broadcast stream that emits custom events posted via `postEvent` from
77 /// the `dart:developer` package, limited to specific [kind].
78 ///
79 /// If [prefix] is `true`, then [kind] is matched to the event kind as a
80 /// prefix.
81 Stream<VMExtensionEvent> selectExtensionEvents(String kind,
82 {bool prefix: false}) =>
83 transform(_onExtensionEvent, new _VMExtensionEventSelector(kind, prefix));
nweiz 2016/02/17 21:35:41 I'd rather this just be an anonymous function.
yjbanov 2016/02/17 23:51:43 Done.
84
71 /// A broadcast stream that emits this isolate's standard output. 85 /// A broadcast stream that emits this isolate's standard output.
72 /// 86 ///
73 /// This is only usable for embedders that provide access to `dart:io`. 87 /// This is only usable for embedders that provide access to `dart:io`.
74 /// 88 ///
75 /// Note that as of the VM service version 3.0, this stream doesn't emit 89 /// Note that as of the VM service version 3.0, this stream doesn't emit
76 /// strings passed to the `print()` function unless the host process's 90 /// strings passed to the `print()` function unless the host process's
77 /// standard output is actively being drained (see [sdk#24351][]). 91 /// standard output is actively being drained (see [sdk#24351][]).
78 /// 92 ///
79 /// [sdk#24351]: https://github.com/dart-lang/sdk/issues/24351 93 /// [sdk#24351]: https://github.com/dart-lang/sdk/issues/24351
80 Stream<List<int>> get stdout => _stdout; 94 Stream<List<int>> get stdout => _stdout;
81 Stream<List<int>> _stdout; 95 Stream<List<int>> _stdout;
82 96
83 /// A broadcast stream that emits this isolate's standard error. 97 /// A broadcast stream that emits this isolate's standard error.
84 /// 98 ///
85 /// This is only usable for embedders that provide access to `dart:io`. 99 /// This is only usable for embedders that provide access to `dart:io`.
86 Stream<List<int>> get stderr => _stderr; 100 Stream<List<int>> get stderr => _stderr;
87 Stream<List<int>> _stderr; 101 Stream<List<int>> _stderr;
88 102
103 /// A broadcast stream that emits the name of VM service extensions
104 Stream<String> get onServiceExtensionAdded =>
105 _onServiceExtensionAdded;
106 Stream<String> _onServiceExtensionAdded;
107
89 /// A future that fires when the isolate exits. 108 /// A future that fires when the isolate exits.
90 /// 109 ///
91 /// If the isolate has already exited, this will complete immediately. 110 /// If the isolate has already exited, this will complete immediately.
92 Future get onExit => _onExitMemo.runOnce(() async { 111 Future get onExit => _onExitMemo.runOnce(() async {
93 try { 112 try {
94 await _scope.getInState(_scope.streams.isolate, () async { 113 await _scope.getInState(_scope.streams.isolate, () async {
95 try { 114 try {
96 await load(); 115 await load();
97 return null; 116 return null;
98 } on VMSentinelException catch (_) { 117 } on VMSentinelException catch (_) {
(...skipping 20 matching lines...) Expand all
119 name = json["name"] { 138 name = json["name"] {
120 _onGC = _transform(_scope.streams.gc, (json, sink) { 139 _onGC = _transform(_scope.streams.gc, (json, sink) {
121 if (json["kind"] == "GC") sink.add(null); 140 if (json["kind"] == "GC") sink.add(null);
122 }); 141 });
123 142
124 _onUpdate = _transform(_scope.streams.isolate, (json, sink) { 143 _onUpdate = _transform(_scope.streams.isolate, (json, sink) {
125 if (json["kind"] != "IsolateUpdate") return; 144 if (json["kind"] != "IsolateUpdate") return;
126 sink.add(new VMIsolateRef._(_scope, json["isolate"])); 145 sink.add(new VMIsolateRef._(_scope, json["isolate"]));
127 }); 146 });
128 147
148 _onServiceExtensionAdded = _transform(_scope.streams.isolate, (json, sink) {
149 if (json["kind"] != "ServiceExtensionAdded") return;
150 sink.add(json["extensionRPC"]);
151 });
152
129 _onPauseOrResume = _transform(_scope.streams.debug, (json, sink) { 153 _onPauseOrResume = _transform(_scope.streams.debug, (json, sink) {
130 var event = newVMPauseEvent(_scope, json); 154 var event = newVMPauseEvent(_scope, json);
131 if (event != null) sink.add(event); 155 if (event != null) sink.add(event);
132 }); 156 });
133 157
134 _onBreakpointAdded = _transform(_scope.streams.debug, (json, sink) { 158 _onBreakpointAdded = _transform(_scope.streams.debug, (json, sink) {
135 if (json["kind"] != "BreakpointAdded") return; 159 if (json["kind"] != "BreakpointAdded") return;
136 sink.add(newVMBreakpoint(_scope, json["breakpoint"])); 160 sink.add(newVMBreakpoint(_scope, json["breakpoint"]));
137 }); 161 });
138 162
139 _stdout = _transform(_scope.streams.stdout, (json, sink) { 163 _stdout = _transform(_scope.streams.stdout, (json, sink) {
140 if (json["kind"] != "WriteEvent") return; 164 if (json["kind"] != "WriteEvent") return;
141 var bytes = CryptoUtils.base64StringToBytes(json["bytes"]); 165 var bytes = CryptoUtils.base64StringToBytes(json["bytes"]);
142 sink.add(bytes); 166 sink.add(bytes);
143 }); 167 });
144 168
145 _stderr = _transform(_scope.streams.stderr, (json, sink) { 169 _stderr = _transform(_scope.streams.stderr, (json, sink) {
146 if (json["kind"] != "WriteEvent") return; 170 if (json["kind"] != "WriteEvent") return;
147 sink.add(CryptoUtils.base64StringToBytes(json["bytes"])); 171 sink.add(CryptoUtils.base64StringToBytes(json["bytes"]));
148 }); 172 });
173
174 _onExtensionEvent = _transform(_scope.streams.extension, (json, sink) {
175 sink.add(
176 new VMExtensionEvent._(json['extensionKind'], json['extensionData']));
177 });
149 } 178 }
150 179
151 /// Like [transform], but only calls [handleData] for events related to this 180 /// Like [transform], but only calls [handleData] for events related to this
152 /// isolate. 181 /// isolate.
153 Stream _transform(Stream<Map> stream, handleData(Map json, StreamSink sink)) { 182 Stream _transform(Stream<Map> stream, handleData(Map json, StreamSink sink)) {
154 return transform(stream, (json, sink) { 183 return transform(stream, (json, sink) {
155 if (json["isolate"]["id"] != _scope.isolateId) return; 184 if (json["isolate"]["id"] != _scope.isolateId) return;
156 handleData(json, sink); 185 handleData(json, sink);
157 }); 186 });
158 } 187 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 var response = await _scope.sendRequest( 286 var response = await _scope.sendRequest(
258 "addBreakpointWithScriptUri", params); 287 "addBreakpointWithScriptUri", params);
259 return newVMBreakpoint(_scope, response); 288 return newVMBreakpoint(_scope, response);
260 } on rpc.RpcException catch (error) { 289 } on rpc.RpcException catch (error) {
261 // Error 102 indicates that the breakpoint couldn't be created. 290 // Error 102 indicates that the breakpoint couldn't be created.
262 if (error.code == 102) return null; 291 if (error.code == 102) return null;
263 rethrow; 292 rethrow;
264 } 293 }
265 } 294 }
266 295
296 /// Returns a future that completes once extension with the given [name] is
297 /// available.
298 ///
299 /// This works whether the extension is already registered or has yet to be
300 /// registered.
301 Future waitForExtension(String name) async {
302 return _scope.getInState(_scope.streams.isolate, () async {
303 var extensions = (await load()).extensionRPCs;
304 return extensions.contains(name);
305 }, (Map json) {
306 return json["kind"] == "ServiceExtensionAdded" &&
307 json["extensionRPC"] == name;
308 }).then((_) => null);
309 }
310
311 /// Makes a raw RPC to a VM service extension registered in this isolate
312 /// corresponding to the ID [number].
313 ///
314 /// [method] must correspond to a VM service extension installed on the VM
315 /// isolate and it must begin with prefix "ext.".
316 ///
317 /// [params] are passed to the extension handler and must be serializable to
318 /// a JSON string.
319 Future<Object> invokeExtension(String method, [Map<String, String> params]) {
320 if (!method.startsWith('ext.')) {
321 throw new ArgumentError.value(method, 'method',
322 'must begin with "ext." prefix');
323 }
324 return _scope.sendRequest(method, params);
325 }
326
267 bool operator ==(other) => other is VMIsolateRef && 327 bool operator ==(other) => other is VMIsolateRef &&
268 other._scope.isolateId == _scope.isolateId; 328 other._scope.isolateId == _scope.isolateId;
269 329
270 int get hashCode => _scope.isolateId.hashCode; 330 int get hashCode => _scope.isolateId.hashCode;
271 331
272 String toString() => name; 332 String toString() => name;
273 } 333 }
274 334
275 /// A full isolate on the remote VM. 335 /// A full isolate on the remote VM.
276 class VMIsolate extends VMIsolateRef { 336 class VMIsolate extends VMIsolateRef {
(...skipping 13 matching lines...) Expand all
290 350
291 /// Whether this isolate is paused. 351 /// Whether this isolate is paused.
292 bool get isPaused => pauseEvent is! VMResumeEvent; 352 bool get isPaused => pauseEvent is! VMResumeEvent;
293 353
294 /// The error that's causing the isolate to exit or `null`. 354 /// The error that's causing the isolate to exit or `null`.
295 final VMError error; 355 final VMError error;
296 356
297 /// All breakpoints currently registered for this isolate. 357 /// All breakpoints currently registered for this isolate.
298 final List<VMBreakpoint> breakpoints; 358 final List<VMBreakpoint> breakpoints;
299 359
360 /// The list of service extension RPCs that are registered for this isolate.
361 final List<String> extensionRPCs;
nweiz 2016/02/17 21:35:41 Nit: Following the Dart style guide, this should b
yjbanov 2016/02/17 23:51:43 Done.
362
300 VMIsolate._(Scope scope, Map json) 363 VMIsolate._(Scope scope, Map json)
301 : startTime = new DateTime.fromMillisecondsSinceEpoch( 364 : startTime = new DateTime.fromMillisecondsSinceEpoch(
302 // Prior to v3.0, this was emitted as a double rather than an int. 365 // Prior to v3.0, this was emitted as a double rather than an int.
303 json["startTime"].round()), 366 json["startTime"].round()),
304 livePorts = json["livePorts"], 367 livePorts = json["livePorts"],
305 pauseOnExit = json["pauseOnExit"], 368 pauseOnExit = json["pauseOnExit"],
306 pauseEvent = newVMPauseEvent(scope, json["pauseEvent"]), 369 pauseEvent = newVMPauseEvent(scope, json["pauseEvent"]),
307 error = newVMError(scope, json["error"]), 370 error = newVMError(scope, json["error"]),
308 breakpoints = new UnmodifiableListView(json["breakpoints"] 371 breakpoints = new UnmodifiableListView(json["breakpoints"]
309 .map((breakpoint) => newVMBreakpoint(scope, breakpoint)) 372 .map((breakpoint) => newVMBreakpoint(scope, breakpoint))
310 .toList()), 373 .toList()),
374 extensionRPCs = json["extensionRPCs"] != null
375 ? new UnmodifiableListView(json["extensionRPCs"])
376 : const <String>[], // it's null when no extensions are registered
nweiz 2016/02/17 21:35:41 Hmm, this is not what's documented. I've filed htt
yjbanov 2016/02/17 23:51:43 Done.
311 super._(scope, json); 377 super._(scope, json);
312 } 378 }
313 379
314 /// A full isolate on the remote VM that's ready to run code. 380 /// A full isolate on the remote VM that's ready to run code.
315 /// 381 ///
316 /// The VM service exposes isolates very early, before their contents are 382 /// The VM service exposes isolates very early, before their contents are
317 /// fully-loaded. These in-progress isolates, represented by plain [VMIsolate] 383 /// fully-loaded. These in-progress isolates, represented by plain [VMIsolate]
318 /// instances, have limited amounts of metadata available. Only once they're 384 /// instances, have limited amounts of metadata available. Only once they're
319 /// runnable is the full suite of metadata available. 385 /// runnable is the full suite of metadata available.
320 /// 386 ///
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 424
359 /// The isolate continues until it exits the current function. 425 /// The isolate continues until it exits the current function.
360 static const out = const VMStep._("Out"); 426 static const out = const VMStep._("Out");
361 427
362 /// The string name of the step type. 428 /// The string name of the step type.
363 final String _value; 429 final String _value;
364 430
365 const VMStep._(this._value); 431 const VMStep._(this._value);
366 432
367 String toString() => _value; 433 String toString() => _value;
368 } 434 }
435
436 /// An event posted via `postEvent` from the `dart:developer` package.
437 class VMExtensionEvent {
438 /// Event kind.
439 final String kind;
440
441 /// Event data.
442 final Map data;
443
444 VMExtensionEvent._(this.kind, this.data);
445 }
446
447 /// Stream data handler that picks extension events based on event kind.
448 class _VMExtensionEventSelector {
449 /// The kind of events the subscriber is interested in.
450 final String kind;
451
452 /// Whether [kind] must match as prefix.
453 final bool prefix;
454
455 _VMExtensionEventSelector(this.kind, this.prefix);
456
457 call(VMExtensionEvent event, EventSink<VMExtensionEvent> sink) {
458 if (event.kind == kind || (prefix && event.kind.startsWith(kind))) {
459 sink.add(event);
460 }
461 }
462 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/scope.dart » ('j') | test/isolate_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698