[ VM ] Added Dart_IsolateServiceID() to the embedding API

Allows for the retrieval of an isolate's service protocol ID from a
Dart_Isolate handle.

Change-Id: Ie90cac2f76566040e61427f1255a4ab76792712f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104680
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 7103341..d1e4326 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -913,6 +913,13 @@
 DART_EXPORT Dart_Handle Dart_DebugName();
 
 /**
+ * Returns the ID for an isolate which is used to query the service protocol.
+ *
+ * It is the responsibility of the caller to free the returned ID.
+ */
+DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate);
+
+/**
  * Enters an isolate. After calling this function,
  * the current isolate will be set to the provided isolate.
  *
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 55eb9ba..ca8ce78 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1234,6 +1234,15 @@
                               static_cast<int64_t>(I->main_port()), I->name()));
 }
 
+DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
+  if (isolate == NULL) {
+    FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
+  }
+  Isolate* I = reinterpret_cast<Isolate*>(isolate);
+  int64_t main_port = static_cast<int64_t>(I->main_port());
+  return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
+}
+
 DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
   CHECK_NO_ISOLATE(Isolate::Current());
   // TODO(16615): Validate isolate parameter.
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a8c490b..e500239 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3635,6 +3635,15 @@
   EXPECT(Dart_IsString(debug_name));
 }
 
+TEST_CASE(DartAPI_IsolateServiceID) {
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  const char* id = Dart_IsolateServiceId(isolate);
+  EXPECT(id != NULL);
+  int64_t main_port = Dart_GetMainPortId();
+  EXPECT_STREQ(ZONE_STR("isolates/%" Pd64, main_port), id);
+  free(const_cast<char*>(id));
+}
+
 static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) {}
 
 VM_UNIT_TEST_CASE(DartAPI_SetMessageCallbacks) {