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

Unified Diff: runtime/vm/service.cc

Issue 98253009: Refactor VM service IDs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/service.cc
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 087c933d0c3b0832dd98a4b8a9ba76dcb1c51a37..52078cc06dc65b46ed968a66212a11d2ac73a886 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -153,6 +153,26 @@ static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) {
}
+static void PrintCollectionErrorResponse(const char* collection_name,
+ JSONStream* js) {
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "Error");
+ jsobj.AddPropertyF("text", "Must specify collection object id: %s/id",
+ collection_name);
+}
+
+
+static void PrintCollectionRangeErrorResponse(const char* collection_name,
+ JSONStream* js,
+ intptr_t id,
+ intptr_t length) {
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "Error");
+ jsobj.AddPropertyF("text", "%s id (%" Pd ") must be in [0, %" Pd ").",
+ collection_name, id, length);
+}
+
+
static void PrintGenericError(JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "Error");
@@ -238,6 +258,78 @@ static void HandleEcho(Isolate* isolate, JSONStream* js) {
return; \
}
+#define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \
+ if (!GetIntegerId(arg, &id)) { \
+ PrintCollectionErrorResponse(collection, js); \
turnidge 2013/12/19 20:39:29 Why not just use PrintError (accepts format string
Cutch 2013/12/19 21:53:58 Done.
+ return; \
+ } \
+ if ((id < 0) || (id >= length)) { \
+ PrintCollectionRangeErrorResponse(collection, js, id, length); \
+ }
+
+
+static bool GetIntegerId(const char* s, intptr_t* id) {
+ if ((s == NULL) || (*s == '\0')) {
+ // Empty string.
+ return false;
+ }
+ if (id == NULL) {
+ // No id pointer.
+ return false;
+ }
+ intptr_t r = 0;
+ char* end_ptr = NULL;
+ r = strtol(s, &end_ptr, 10);
+ if (end_ptr == s) {
+ // String was not advanced at all, cannot be valid.
+ return false;
+ }
+ *id = r;
+ return true;
+}
+
+
+static void HandleClassesClosures(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ const GrowableObjectArray& closures =
+ GrowableObjectArray::Handle(cls.closures());
+ intptr_t id;
+ CHECK_COLLECTION_ID_BOUNDS("closures", closures.Length(), js->GetArgument(3),
+ id, js);
+ Function& function = Function::Handle();
+ function ^= closures.At(id);
+ ASSERT(!function.IsNull());
+ function.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesFunctions(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ const Array& functions =
+ Array::Handle(cls.functions());
+ intptr_t id;
+ CHECK_COLLECTION_ID_BOUNDS("functions", functions.Length(),
+ js->GetArgument(3), id, js);
+ Function& function = Function::Handle();
+ function ^= functions.At(id);
+ ASSERT(!function.IsNull());
+ function.PrintToJSONStream(js, false);
+}
+
+
+static void HandleClassesFields(Isolate* isolate, const Class& cls,
+ JSONStream* js) {
+ const Array& fields =
+ Array::Handle(cls.fields());
+ intptr_t id;
+ CHECK_COLLECTION_ID_BOUNDS("fields", fields.Length(), js->GetArgument(3),
+ id, js);
+ Field& field = Field::Handle();
+ field ^= fields.At(id);
+ ASSERT(!field.IsNull());
+ field.PrintToJSONStream(js, false);
+}
+
static void HandleClasses(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
@@ -246,13 +338,33 @@ static void HandleClasses(Isolate* isolate, JSONStream* js) {
return;
}
ASSERT(js->num_arguments() >= 2);
- intptr_t id = atoi(js->GetArgument(1));
+ intptr_t id;
+ if (!GetIntegerId(js->GetArgument(1), &id)) {
+ PrintGenericError(js);
turnidge 2013/12/19 20:39:29 Use PrintError and give a nice message here.
Cutch 2013/12/19 21:53:58 Done.
+ return;
+ }
ClassTable* table = isolate->class_table();
if (!table->IsValidIndex(id)) {
Object::null_object().PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 So null is what we give for an invalid reference?
Cutch 2013/12/19 21:53:58 Legacy code, returning Error now.
- } else {
- Class& cls = Class::Handle(table->At(id));
+ return;
+ }
+ Class& cls = Class::Handle(table->At(id));
+ if (js->num_arguments() == 2) {
cls.PrintToJSONStream(js, false);
+ return;
+ } else if (js->num_arguments() == 4) {
turnidge 2013/12/19 20:39:29 Maybe just check that num_arguments is >= 3 and le
Cutch 2013/12/19 21:53:58 Done.
+ const char* second = js->GetArgument(2);
+ if (!strcmp(second, "closures")) {
+ HandleClassesClosures(isolate, cls, js);
+ } else if (!strcmp(second, "fields")) {
+ HandleClassesFields(isolate, cls, js);
+ } else if (!strcmp(second, "functions")) {
+ HandleClassesFunctions(isolate, cls, js);
+ } else {
+ PrintError(js, "Invalid sub collection %s", second);
+ }
+ } else {
+ PrintGenericError(js);
turnidge 2013/12/19 20:39:29 This goes away if you let helpers handle sub-error
Cutch 2013/12/19 21:53:58 Done.
}
}
turnidge 2013/12/19 20:39:29 Here and below... You should have my changes now
Cutch 2013/12/19 21:53:58 Done.
@@ -268,17 +380,108 @@ static void HandleLibrary(Isolate* isolate, JSONStream* js) {
}
+static void HandleLibraries(Isolate* isolate, JSONStream* js) {
+ REQUIRE_COLLECTION_ID("libraries");
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ ASSERT(!libs.IsNull());
+ intptr_t id = 0;
+ CHECK_COLLECTION_ID_BOUNDS("libraries", libs.Length(), js->GetArgument(1),
+ id, js);
+ Library& lib = Library::Handle();
+ lib ^= libs.At(id);
+ ASSERT(!lib.IsNull());
+ lib.PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 So do we not yet support Fields/Functions for libr
Cutch 2013/12/19 21:53:58 Good point! TODO added.
+}
+
+
static void HandleObjects(Isolate* isolate, JSONStream* js) {
REQUIRE_COLLECTION_ID("objects");
ASSERT(js->num_arguments() >= 2);
ObjectIdRing* ring = isolate->object_id_ring();
ASSERT(ring != NULL);
- intptr_t id = atoi(js->GetArgument(1));
+ intptr_t id = -1;
+ if (!GetIntegerId(js->GetArgument(1), &id)) {
+ Object::null_object().PrintToJSONStream(js, false);
turnidge 2013/12/19 20:39:29 Again, null object seems ambiguous. I might prefe
+ return;
+ }
Object& obj = Object::Handle(ring->GetObjectForId(id));
obj.PrintToJSONStream(js, false);
}
+
+static void HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) {
+ JSONObject jsobj(js);
+ jsobj.AddProperty("type", "ScriptList");
+ {
+ JSONArray members(&jsobj, "members");
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ int num_libs = libs.Length();
+ Library &lib = Library::Handle();
+ Script& script = Script::Handle();
+ for (intptr_t i = 0; i < num_libs; i++) {
+ lib ^= libs.At(i);
+ ASSERT(!lib.IsNull());
+ ASSERT(Smi::IsValid(lib.index()));
+ const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
+ ASSERT(!loaded_scripts.IsNull());
+ intptr_t num_scripts = loaded_scripts.Length();
+ for (intptr_t i = 0; i < num_scripts; i++) {
+ script ^= loaded_scripts.At(i);
+ members.AddValue(script);
+ }
+ }
+ }
+}
+
+
+static void HandleScriptsFetch(Isolate* isolate, JSONStream* js) {
+ const GrowableObjectArray& libs =
+ GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ int num_libs = libs.Length();
+ Library &lib = Library::Handle();
+ Script& script = Script::Handle();
+ String& url = String::Handle();
+ const String& id = String::Handle(String::New(js->GetArgument(1)));
+ ASSERT(!id.IsNull());
+ // The id is the url of the script % encoded, decode it.
+ String& requested_url = String::Handle(String::DecodeURI(id));
+ for (intptr_t i = 0; i < num_libs; i++) {
+ lib ^= libs.At(i);
+ ASSERT(!lib.IsNull());
+ ASSERT(Smi::IsValid(lib.index()));
+ const Array& loaded_scripts = Array::Handle(lib.LoadedScripts());
+ ASSERT(!loaded_scripts.IsNull());
+ intptr_t num_scripts = loaded_scripts.Length();
+ for (intptr_t i = 0; i < num_scripts; i++) {
+ script ^= loaded_scripts.At(i);
+ ASSERT(!script.IsNull());
+ url ^= script.url();
+ if (url.Equals(requested_url)) {
+ script.PrintToJSONStream(js, false);
+ return;
+ }
+ }
+ }
+ PrintError(js, "Cannot find script %s\n", requested_url.ToCString());
+}
+
+
+static void HandleScripts(Isolate* isolate, JSONStream* js) {
+ if (js->num_arguments() == 1) {
+ // Enumerate all scripts.
+ HandleScriptsEnumerate(isolate, js);
+ } else if (js->num_arguments() == 2) {
+ // Fetch specific script.
+ HandleScriptsFetch(isolate, js);
+ } else {
+ PrintError(js, "Command too long");
+ }
+}
+
+
static void HandleDebug(Isolate* isolate, JSONStream* js) {
if (js->num_arguments() == 1) {
PrintError(js, "Must specify a subcommand");
@@ -324,10 +527,12 @@ static ServiceMessageHandlerEntry __message_handlers[] = {
{ "classes", HandleClasses },
{ "cpu", HandleCpu },
{ "debug", HandleDebug },
+ { "libraries", HandleLibraries },
{ "library", HandleLibrary },
turnidge 2013/12/19 20:39:29 Is the plan to have both library and libraries? I
Cutch 2013/12/19 21:53:58 library is how you get to the root library. librar
{ "name", HandleName },
{ "objecthistogram", HandleObjectHistogram},
{ "objects", HandleObjects },
+ { "scripts", HandleScripts },
{ "stacktrace", HandleStackTrace },
};

Powered by Google App Engine
This is Rietveld 408576698