diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc index 5d6027b8f9f..e2f5a1ba12e 100644 --- a/runtime/lib/developer.cc +++ b/runtime/lib/developer.cc @@ -172,4 +172,16 @@ DEFINE_NATIVE_ENTRY(Developer_webServerControl, 2) { #endif } + +DEFINE_NATIVE_ENTRY(Developer_getIsolateIDFromSendPort, 1) { +#if defined(PRODUCT) + return Object::null(); +#else + GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); + int64_t port_id = port.Id(); + return String::NewFormatted(ISOLATE_SERVICE_ID_FORMAT_STRING, port_id); +#endif +} + + } // namespace dart diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart index e9b90b92ded..78c1d6d53b2 100644 --- a/runtime/lib/developer.dart +++ b/runtime/lib/developer.dart @@ -154,7 +154,10 @@ _postResponse(SendPort replyPort, @patch int _getServiceMinorVersion() native "Developer_getServiceMinorVersion"; -@patch void _getServerInfo(SendPort sp) native "Developer_getServerInfo"; +@patch void _getServerInfo(SendPort sendPort) native "Developer_getServerInfo"; -@patch void _webServerControl(SendPort sp, bool enable) - native "Developer_webServerControl"; \ No newline at end of file +@patch void _webServerControl(SendPort sendPort, bool enable) + native "Developer_webServerControl"; + +@patch String _getIsolateIDFromSendPort(SendPort sendPort) + native "Developer_getIsolateIDFromSendPort"; diff --git a/runtime/observatory/tests/service/developer_service_get_isolate_id_test.dart b/runtime/observatory/tests/service/developer_service_get_isolate_id_test.dart new file mode 100644 index 00000000000..f3a24b07b5d --- /dev/null +++ b/runtime/observatory/tests/service/developer_service_get_isolate_id_test.dart @@ -0,0 +1,90 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// VMOptions=--error_on_bad_type --error_on_bad_override + +import 'dart:async'; +import 'dart:developer' as dev; +import 'dart:isolate' as Core; + +import 'package:observatory/service_io.dart' as Service; +import 'package:unittest/unittest.dart'; +import 'service_test_common.dart'; +import 'test_helper.dart'; + + +// testee state. +String selfId; +Core.Isolate childIsolate; +String childId; + +void spawnEntry(int i) { + dev.debugger(); +} + +Future testeeMain() async { + dev.debugger(); + // Spawn an isolate. + childIsolate = await Core.Isolate.spawn(spawnEntry, 0); + // Assign the id for this isolate and it's child to strings so they can + // be read by the tester. + selfId = dev.Service.getIsolateID(Core.Isolate.current); + childId = dev.Service.getIsolateID(childIsolate); + dev.debugger(); +} + +// tester state: +Service.Isolate initialIsolate; +Service.Isolate localChildIsolate; + +var tests = [ + (Service.VM vm) async { + // Sanity check. + expect(vm.isolates.length, 1); + initialIsolate = vm.isolates[0]; + await hasStoppedAtBreakpoint(initialIsolate); + // Resume. + await initialIsolate.resume(); + }, + (Service.VM vm) async { + // Initial isolate has paused at second debugger call. + await hasStoppedAtBreakpoint(initialIsolate); + }, + (Service.VM vm) async { + // Reload the VM. + await vm.reload(); + + // Grab the child isolate. + localChildIsolate = + vm.isolates.firstWhere( + (Service.Isolate i) => i != initialIsolate); + expect(localChildIsolate, isNotNull); + + // Reload the initial isolate. + await initialIsolate.reload(); + + // Grab the root library. + Service.Library rootLbirary = await initialIsolate.rootLibrary.load(); + + // Grab self id. + Service.Instance localSelfId = + await initialIsolate.eval(rootLbirary, 'selfId'); + + // Check that the id reported from dart:developer matches the id reported + // from the service protocol. + expect(localSelfId.isString, true); + expect(initialIsolate.id, equals(localSelfId.valueAsString)); + + // Grab the child isolate's id. + Service.Instance localChildId = + await initialIsolate.eval(rootLbirary, 'childId'); + + // Check that the id reported from dart:developer matches the id reported + // from the service protocol. + expect(localChildId.isString, true); + expect(localChildIsolate.id, equals(localChildId.valueAsString)); + } +]; + +main(args) async => runVMTests(args, tests, + testeeConcurrent: testeeMain); diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart index 2a68a528c6b..bf1d013c5d8 100644 --- a/runtime/observatory/tests/service/service_test_common.dart +++ b/runtime/observatory/tests/service/service_test_common.dart @@ -157,7 +157,7 @@ Future hasPausedFor(Isolate isolate, String kind) { isolate.vm.getEventStream(VM.kDebugStream).then((stream) { var subscription; subscription = stream.listen((ServiceEvent event) { - if (event.kind == kind) { + if ((isolate == event.isolate) && (event.kind == kind)) { if (completer != null) { // Reload to update isolate.pauseEvent. print('Paused with $kind'); diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index 536299c65f9..20861868410 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -71,6 +71,7 @@ namespace dart { V(Bigint_getDigits, 1) \ V(Bigint_allocate, 4) \ V(Developer_debugger, 2) \ + V(Developer_getIsolateIDFromSendPort, 1) \ V(Developer_getServerInfo, 1) \ V(Developer_getServiceMajorVersion, 0) \ V(Developer_getServiceMinorVersion, 0) \ diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index e4cbfaf89dc..aa851bfed42 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -1974,7 +1974,7 @@ void Isolate::PrintJSON(JSONStream* stream, bool ref) { } JSONObject jsobj(stream); jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate")); - jsobj.AddFixedServiceId("isolates/%" Pd64 "", + jsobj.AddFixedServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING, static_cast(main_port())); jsobj.AddProperty("name", debugger_name()); diff --git a/runtime/vm/service.h b/runtime/vm/service.h index 8ee0c007077..a1ee159c3e4 100644 --- a/runtime/vm/service.h +++ b/runtime/vm/service.h @@ -41,6 +41,7 @@ class ServiceIdZone { private: }; +#define ISOLATE_SERVICE_ID_FORMAT_STRING "isolates/%" Pd64 "" class RingServiceIdZone : public ServiceIdZone { public: diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart index b9e35b2773f..541658b1289 100644 --- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart @@ -117,11 +117,16 @@ int _getServiceMinorVersion() { } @patch -void _getServerInfo(SendPort sp) { - sp.send(null); +void _getServerInfo(SendPort sendPort) { + sendPort.send(null); } @patch -void _webServerControl(SendPort sp, bool enable) { - sp.send(null); +void _webServerControl(SendPort sendPort, bool enable) { + sendPort.send(null); } + +@patch +String _getIsolateIDFromSendPort(SendPort sendPort) { + return null; +} \ No newline at end of file diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart index 47ea5babfcf..aab137c3b49 100644 --- a/sdk/lib/developer/developer.dart +++ b/sdk/lib/developer/developer.dart @@ -17,7 +17,7 @@ library dart.developer; import 'dart:async'; import 'dart:convert'; -import 'dart:isolate' show RawReceivePort, SendPort; +import 'dart:isolate' show Isolate, RawReceivePort, SendPort; part 'extension.dart'; part 'profiler.dart'; diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart index 9ccf0dccc26..bbe954def25 100644 --- a/sdk/lib/developer/service.dart +++ b/sdk/lib/developer/service.dart @@ -73,13 +73,26 @@ class Service { receivePort.close(); return new ServiceProtocolInfo(uri); } + + /// Returns a [String] token representing the ID of [isolate]. + /// + /// Returns null if the running Dart environment does not support the service + /// protocol. + static String getIsolateID(Isolate isolate) { + if (isolate is! Isolate) { + throw new ArgumentError.value(isolate, + 'isolate', + 'Must be an Isolate'); + } + return _getIsolateIDFromSendPort(isolate.controlPort); + } } -/// [sp] will receive a Uri or null. -external void _getServerInfo(SendPort sp); +/// [sendPort] will receive a Uri or null. +external void _getServerInfo(SendPort sendPort); -/// [sp] will receive a Uri or null. -external void _webServerControl(SendPort sp, bool enable); +/// [sendPort] will receive a Uri or null. +external void _webServerControl(SendPort sendPort, bool enable); /// Returns the major version of the service protocol. external int _getServiceMajorVersion(); @@ -87,3 +100,5 @@ external int _getServiceMajorVersion(); /// Returns the minor version of the service protocol. external int _getServiceMinorVersion(); +/// Returns the service id for the isolate that owns [sendPort]. +external String _getIsolateIDFromSendPort(SendPort sendPort); \ No newline at end of file