Index: runtime/vm/service.cc |
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
index 25330c4e39453563be6b203a8f036a129c98f29f..036126280efa4af59f83088443b30ad213f6fd9f 100644 |
--- a/runtime/vm/service.cc |
+++ b/runtime/vm/service.cc |
@@ -819,12 +819,11 @@ void Service::RunService() { |
typedef bool (*IsolateMessageHandler)(Isolate* isolate, JSONStream* stream); |
struct IsolateMessageHandlerEntry { |
- const char* command; |
+ const char* method; |
IsolateMessageHandler handler; |
}; |
-static IsolateMessageHandler FindIsolateMessageHandler(const char* command); |
-static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command); |
+static IsolateMessageHandler FindIsolateMessageHandler(const char* method); |
// A handler for a root (vm-global) request. |
@@ -836,32 +835,26 @@ static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command); |
typedef bool (*RootMessageHandler)(JSONStream* stream); |
struct RootMessageHandlerEntry { |
- const char* command; |
+ const char* method; |
RootMessageHandler handler; |
}; |
-static RootMessageHandler FindRootMessageHandler(const char* command); |
-static RootMessageHandler FindRootMessageHandlerNew(const char* command); |
+static RootMessageHandler FindRootMessageHandler(const char* method); |
-static void PrintArgumentsAndOptions(const JSONObject& obj, JSONStream* js) { |
+static void PrintRequest(const JSONObject& obj, JSONStream* js) { |
JSONObject jsobj(&obj, "request"); |
+ jsobj.AddProperty("method", js->method()); |
{ |
- JSONArray jsarr(&jsobj, "arguments"); |
- for (intptr_t i = 0; i < js->num_arguments(); i++) { |
- jsarr.AddValue(js->GetArgument(i)); |
+ JSONArray jsarr(&jsobj, "param_keys"); |
+ for (intptr_t i = 0; i < js->num_params(); i++) { |
+ jsarr.AddValue(js->GetParamKey(i)); |
} |
} |
{ |
- JSONArray jsarr(&jsobj, "option_keys"); |
- for (intptr_t i = 0; i < js->num_options(); i++) { |
- jsarr.AddValue(js->GetOptionKey(i)); |
- } |
- } |
- { |
- JSONArray jsarr(&jsobj, "option_values"); |
- for (intptr_t i = 0; i < js->num_options(); i++) { |
- jsarr.AddValue(js->GetOptionValue(i)); |
+ JSONArray jsarr(&jsobj, "param_values"); |
+ for (intptr_t i = 0; i < js->num_params(); i++) { |
+ jsarr.AddValue(js->GetParamValue(i)); |
} |
} |
} |
@@ -885,7 +878,21 @@ static void PrintError(JSONStream* js, |
JSONObject jsobj(js); |
jsobj.AddProperty("type", "Error"); |
jsobj.AddProperty("message", buffer); |
- PrintArgumentsAndOptions(jsobj, js); |
+ PrintRequest(jsobj, js); |
+} |
+ |
+ |
+static void PrintMissingParamError(JSONStream* js, |
+ const char* param) { |
+ PrintError(js, "%s expects the '%s' parameter", |
+ js->method(), param); |
+} |
+ |
+ |
+static void PrintInvalidParamError(JSONStream* js, |
+ const char* param) { |
+ PrintError(js, "%s: invalid '%s' parameter: %s", |
+ js->method(), param, js->LookupParam(param)); |
} |
@@ -910,13 +917,14 @@ static void PrintErrorWithKind(JSONStream* js, |
jsobj.AddProperty("id", ""); |
jsobj.AddProperty("kind", kind); |
jsobj.AddProperty("message", buffer); |
- PrintArgumentsAndOptions(jsobj, js); |
+ PrintRequest(jsobj, js); |
} |
-void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) { |
+void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
ASSERT(isolate != NULL); |
ASSERT(!msg.IsNull()); |
+ ASSERT(msg.Length() == 5); |
{ |
StackZone zone(isolate); |
@@ -941,11 +949,11 @@ void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) { |
} |
IsolateMessageHandler handler = |
- FindIsolateMessageHandlerNew(method.ToCString()); |
+ FindIsolateMessageHandler(method.ToCString()); |
{ |
JSONStream js; |
- js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
- method, param_keys, param_values); |
+ js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
+ method, param_keys, param_values); |
if (handler == NULL) { |
// Check for an embedder handler. |
EmbedderServiceHandler* e_handler = |
@@ -953,8 +961,8 @@ void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) { |
if (e_handler != NULL) { |
EmbedderHandleMessage(e_handler, &js); |
} else { |
- if (FindRootMessageHandlerNew(method.ToCString()) != NULL) { |
- PrintError(&js, "%s expects no 'isolate' parameter\n", |
+ if (FindRootMessageHandler(method.ToCString()) != NULL) { |
+ PrintError(&js, "%s does not expect the 'isolateId' parameter", |
method.ToCString()); |
} else { |
PrintError(&js, "Unrecognized method: %s", method.ToCString()); |
@@ -973,79 +981,6 @@ void Service::HandleIsolateMessageNew(Isolate* isolate, const Array& msg) { |
} |
-void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
- ASSERT(isolate != NULL); |
- ASSERT(!msg.IsNull()); |
- |
- { |
- StackZone zone(isolate); |
- HANDLESCOPE(isolate); |
- |
- // Message is a list with five entries. |
- ASSERT(msg.Length() == 5); |
- |
- Object& tmp = Object::Handle(isolate); |
- tmp = msg.At(2); |
- if (tmp.IsString()) { |
- return Service::HandleIsolateMessageNew(isolate, msg); |
- } |
- |
- Instance& reply_port = Instance::Handle(isolate); |
- GrowableObjectArray& path = GrowableObjectArray::Handle(isolate); |
- Array& option_keys = Array::Handle(isolate); |
- Array& option_values = Array::Handle(isolate); |
- reply_port ^= msg.At(1); |
- path ^= msg.At(2); |
- option_keys ^= msg.At(3); |
- option_values ^= msg.At(4); |
- |
- ASSERT(!path.IsNull()); |
- ASSERT(!option_keys.IsNull()); |
- ASSERT(!option_values.IsNull()); |
- // Same number of option keys as values. |
- ASSERT(option_keys.Length() == option_values.Length()); |
- |
- if (!reply_port.IsSendPort()) { |
- FATAL("SendPort expected."); |
- } |
- |
- String& path_segment = String::Handle(); |
- if (path.Length() > 0) { |
- path_segment ^= path.At(0); |
- } else { |
- path_segment ^= Symbols::Empty().raw(); |
- } |
- ASSERT(!path_segment.IsNull()); |
- const char* path_segment_c = path_segment.ToCString(); |
- |
- IsolateMessageHandler handler = |
- FindIsolateMessageHandler(path_segment_c); |
- { |
- JSONStream js; |
- js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
- path, option_keys, option_values); |
- if (handler == NULL) { |
- // Check for an embedder handler. |
- EmbedderServiceHandler* e_handler = |
- FindIsolateEmbedderHandler(path_segment_c); |
- if (e_handler != NULL) { |
- EmbedderHandleMessage(e_handler, &js); |
- } else { |
- PrintError(&js, "Unrecognized path"); |
- } |
- js.PostReply(); |
- } else { |
- if (handler(isolate, &js)) { |
- // Handler returns true if the reply is ready to be posted. |
- // TODO(johnmccutchan): Support asynchronous replies. |
- js.PostReply(); |
- } |
- } |
- } |
- } |
-} |
- |
- |
static bool HandleIsolate(Isolate* isolate, JSONStream* js) { |
isolate->PrintJSON(js, false); |
return true; |
@@ -1072,8 +1007,8 @@ static bool HandleIsolateGetStack(Isolate* isolate, JSONStream* js) { |
static bool HandleCommonEcho(JSONObject* jsobj, JSONStream* js) { |
jsobj->AddProperty("type", "_EchoResponse"); |
- if (js->HasOption("text")) { |
- jsobj->AddProperty("text", js->LookupOption("text")); |
+ if (js->HasParam("text")) { |
+ jsobj->AddProperty("text", js->LookupParam("text")); |
} |
return true; |
} |
@@ -1098,7 +1033,7 @@ void Service::SendEchoEvent(Isolate* isolate, const char* text) { |
static bool HandleIsolateTriggerEchoEvent(Isolate* isolate, JSONStream* js) { |
- Service::SendEchoEvent(isolate, js->LookupOption("text")); |
+ Service::SendEchoEvent(isolate, js->LookupParam("text")); |
JSONObject jsobj(js); |
return HandleCommonEcho(&jsobj, js); |
} |
@@ -1110,26 +1045,6 @@ static bool HandleIsolateEcho(Isolate* isolate, JSONStream* js) { |
} |
-// Print an error message if there is no ID argument. |
-#define REQUIRE_COLLECTION_ID(collection) \ |
- if (js->num_arguments() == 1) { \ |
- PrintError(js, "Must specify collection object id: /%s/id", collection); \ |
- return true; \ |
- } |
- |
- |
-#define CHECK_COLLECTION_ID_BOUNDS(collection, length, arg, id, js) \ |
- if (!GetIntegerId(arg, &id)) { \ |
- PrintError(js, "Must specify collection object id: %s/id", collection); \ |
- return true; \ |
- } \ |
- if ((id < 0) || (id >= length)) { \ |
- PrintError(js, "%s id (%" Pd ") must be in [0, %" Pd ").", collection, id, \ |
- length); \ |
- return true; \ |
- } |
- |
- |
static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) { |
if ((s == NULL) || (*s == '\0')) { |
// Empty string. |
@@ -1680,19 +1595,19 @@ static bool PrintInboundReferences(Isolate* isolate, |
static bool HandleIsolateGetInboundReferences(Isolate* isolate, |
JSONStream* js) { |
- const char* target_id = js->LookupOption("targetId"); |
+ const char* target_id = js->LookupParam("targetId"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'targetId' option"); |
+ PrintMissingParamError(js, "targetId"); |
return true; |
} |
- const char* limit_cstr = js->LookupOption("limit"); |
+ const char* limit_cstr = js->LookupParam("limit"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'limit' option"); |
+ PrintMissingParamError(js, "limit"); |
return true; |
} |
intptr_t limit; |
- if (!GetIntegerId(js->LookupOption("limit"), &limit)) { |
- PrintError(js, "Invalid 'limit' option: %s", limit_cstr); |
+ if (!GetIntegerId(limit_cstr, &limit)) { |
+ PrintInvalidParamError(js, "limit"); |
return true; |
} |
@@ -1706,18 +1621,15 @@ static bool HandleIsolateGetInboundReferences(Isolate* isolate, |
if (lookup_result == ObjectIdRing::kCollected) { |
PrintErrorWithKind( |
js, "InboundReferencesCollected", |
- "attempt to find a retaining path for a collected object\n", |
- js->num_arguments()); |
+ "attempt to find a retaining path for a collected object\n"); |
return true; |
} else if (lookup_result == ObjectIdRing::kExpired) { |
PrintErrorWithKind( |
js, "InboundReferencesExpired", |
- "attempt to find a retaining path for an expired object\n", |
- js->num_arguments()); |
+ "attempt to find a retaining path for an expired object\n"); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: no object with id '%s'", |
- target_id); |
+ PrintInvalidParamError(js, "targetId"); |
return true; |
} |
return PrintInboundReferences(isolate, &obj, limit, js); |
@@ -1781,19 +1693,19 @@ static bool PrintRetainingPath(Isolate* isolate, |
static bool HandleIsolateGetRetainingPath(Isolate* isolate, |
JSONStream* js) { |
- const char* target_id = js->LookupOption("targetId"); |
+ const char* target_id = js->LookupParam("targetId"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'targetId' option"); |
+ PrintMissingParamError(js, "targetId"); |
return true; |
} |
- const char* limit_cstr = js->LookupOption("limit"); |
+ const char* limit_cstr = js->LookupParam("limit"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'limit' option"); |
+ PrintMissingParamError(js, "limit"); |
return true; |
} |
intptr_t limit; |
- if (!GetIntegerId(js->LookupOption("limit"), &limit)) { |
- PrintError(js, "Invalid 'limit' option: %s", limit_cstr); |
+ if (!GetIntegerId(limit_cstr, &limit)) { |
+ PrintInvalidParamError(js, "limit"); |
return true; |
} |
@@ -1807,18 +1719,15 @@ static bool HandleIsolateGetRetainingPath(Isolate* isolate, |
if (lookup_result == ObjectIdRing::kCollected) { |
PrintErrorWithKind( |
js, "RetainingPathCollected", |
- "attempt to find a retaining path for a collected object\n", |
- js->num_arguments()); |
+ "attempt to find a retaining path for a collected object\n"); |
return true; |
} else if (lookup_result == ObjectIdRing::kExpired) { |
PrintErrorWithKind( |
js, "RetainingPathExpired", |
- "attempt to find a retaining path for an expired object\n", |
- js->num_arguments()); |
+ "attempt to find a retaining path for an expired object\n"); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: no object with id '%s'", |
- target_id); |
+ PrintInvalidParamError(js, "targetId"); |
return true; |
} |
return PrintRetainingPath(isolate, &obj, limit, js); |
@@ -1826,9 +1735,9 @@ static bool HandleIsolateGetRetainingPath(Isolate* isolate, |
static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) { |
- const char* target_id = js->LookupOption("targetId"); |
+ const char* target_id = js->LookupParam("targetId"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'targetId' option"); |
+ PrintMissingParamError(js, "targetId"); |
return true; |
} |
ObjectIdRing::LookupResult lookup_result; |
@@ -1838,18 +1747,15 @@ static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) { |
if (lookup_result == ObjectIdRing::kCollected) { |
PrintErrorWithKind( |
js, "RetainedCollected", |
- "attempt to calculate size retained by a collected object\n", |
- js->num_arguments()); |
+ "attempt to calculate size retained by a collected object\n"); |
return true; |
} else if (lookup_result == ObjectIdRing::kExpired) { |
PrintErrorWithKind( |
js, "RetainedExpired", |
- "attempt to calculate size retained by an expired object\n", |
- js->num_arguments()); |
+ "attempt to calculate size retained by an expired object\n"); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: no object with id '%s'", |
- target_id); |
+ PrintInvalidParamError(js, "targetId"); |
return true; |
} |
if (obj.IsClass()) { |
@@ -1868,43 +1774,22 @@ static bool HandleIsolateGetRetainedSize(Isolate* isolate, JSONStream* js) { |
result.PrintJSON(js, true); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " |
- "library, class, or instance", target_id); |
- return true; |
-} |
- |
- |
-static bool HandleClassesClosures(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- intptr_t id; |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- if (!GetIntegerId(js->GetArgument(3), &id)) { |
- PrintError(js, "Must specify collection object id: closures/id"); |
- return true; |
- } |
- Function& func = Function::Handle(); |
- func ^= cls.ClosureFunctionFromIndex(id); |
- if (func.IsNull()) { |
- PrintError(js, "Closure function %" Pd " not found", id); |
- return true; |
- } |
- func.PrintJSON(js, false); |
+ PrintError(js, "%s: Invalid 'targetId' parameter value: " |
+ "id '%s' does not correspond to a " |
+ "library, class, or instance", js->method(), target_id); |
return true; |
} |
static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) { |
- const char* target_id = js->LookupOption("targetId"); |
+ const char* target_id = js->LookupParam("targetId"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'targetId' option"); |
+ PrintMissingParamError(js, "targetId"); |
return true; |
} |
- const char* expr = js->LookupOption("expression"); |
+ const char* expr = js->LookupParam("expression"); |
if (expr == NULL) { |
- PrintError(js, "Missing 'expression' option"); |
+ PrintMissingParamError(js, "expression"); |
return true; |
} |
const String& expr_str = String::Handle(isolate, String::New(expr)); |
@@ -1917,8 +1802,7 @@ static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) { |
} else if (lookup_result == ObjectIdRing::kExpired) { |
PrintSentinel(js, "objects/expired", "<expired>"); |
} else { |
- PrintError(js, "Invalid 'targetId' value: no object with id '%s'", |
- target_id); |
+ PrintInvalidParamError(js, "targetId"); |
} |
return true; |
} |
@@ -1950,173 +1834,9 @@ static bool HandleIsolateEval(Isolate* isolate, JSONStream* js) { |
result.PrintJSON(js, true); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " |
- "library, class, or instance", target_id); |
- return true; |
-} |
- |
- |
-static bool HandleClassesDispatchers(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- intptr_t id; |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- if (!GetIntegerId(js->GetArgument(3), &id)) { |
- PrintError(js, "Must specify collection object id: dispatchers/id"); |
- return true; |
- } |
- Function& func = Function::Handle(); |
- func ^= cls.InvocationDispatcherFunctionFromIndex(id); |
- if (func.IsNull()) { |
- PrintError(js, "Dispatcher %" Pd " not found", id); |
- return true; |
- } |
- func.PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleFunctionSetSource( |
- Isolate* isolate, const Class& cls, const Function& func, JSONStream* js) { |
- if (js->LookupOption("source") == NULL) { |
- PrintError(js, "set_source expects a 'source' option\n"); |
- return true; |
- } |
- const String& source = |
- String::Handle(String::New(js->LookupOption("source"))); |
- const Object& result = Object::Handle( |
- Parser::ParseFunctionFromSource(cls, source)); |
- if (result.IsError()) { |
- Error::Cast(result).PrintJSON(js, false); |
- return true; |
- } |
- if (!result.IsFunction()) { |
- PrintError(js, "source did not compile to a function.\n"); |
- return true; |
- } |
- |
- // Replace function. |
- cls.RemoveFunction(func); |
- cls.AddFunction(Function::Cast(result)); |
- |
- JSONObject jsobj(js); |
- jsobj.AddProperty("type", "Success"); |
- jsobj.AddProperty("id", ""); |
- return true; |
-} |
- |
- |
-static bool HandleClassesFunctions(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- if (js->num_arguments() != 4 && js->num_arguments() != 5) { |
- PrintError(js, "Command should have 4 or 5 arguments"); |
- return true; |
- } |
- const char* encoded_id = js->GetArgument(3); |
- String& id = String::Handle(isolate, String::New(encoded_id)); |
- id = String::DecodeIRI(id); |
- if (id.IsNull()) { |
- PrintError(js, "Function id %s is malformed", encoded_id); |
- return true; |
- } |
- Function& func = Function::Handle(cls.LookupFunction(id)); |
- if (func.IsNull()) { |
- PrintError(js, "Function %s not found", encoded_id); |
- return true; |
- } |
- if (js->num_arguments() == 4) { |
- func.PrintJSON(js, false); |
- return true; |
- } else { |
- const char* subcommand = js->GetArgument(4); |
- if (strcmp(subcommand, "set_source") == 0) { |
- return HandleFunctionSetSource(isolate, cls, func, js); |
- } else { |
- PrintError(js, "Invalid sub command %s", subcommand); |
- return true; |
- } |
- } |
- UNREACHABLE(); |
- return true; |
-} |
- |
- |
-static bool HandleClassesImplicitClosures(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- intptr_t id; |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- if (!GetIntegerId(js->GetArgument(3), &id)) { |
- PrintError(js, "Must specify collection object id: implicit_closures/id"); |
- return true; |
- } |
- Function& func = Function::Handle(); |
- func ^= cls.ImplicitClosureFunctionFromIndex(id); |
- if (func.IsNull()) { |
- PrintError(js, "Implicit closure function %" Pd " not found", id); |
- return true; |
- } |
- func.PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleClassesFields(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- intptr_t id; |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- if (!GetIntegerId(js->GetArgument(3), &id)) { |
- PrintError(js, "Must specify collection object id: fields/id"); |
- return true; |
- } |
- Field& field = Field::Handle(cls.FieldFromIndex(id)); |
- if (field.IsNull()) { |
- PrintError(js, "Field %" Pd " not found", id); |
- return true; |
- } |
- field.PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleClassesTypes(Isolate* isolate, const Class& cls, |
- JSONStream* js) { |
- if (js->num_arguments() == 3) { |
- JSONObject jsobj(js); |
- jsobj.AddProperty("type", "TypeList"); |
- JSONArray members(&jsobj, "members"); |
- const intptr_t num_types = cls.NumCanonicalTypes(); |
- Type& type = Type::Handle(); |
- for (intptr_t i = 0; i < num_types; i++) { |
- type = cls.CanonicalTypeFromIndex(i); |
- members.AddValue(type); |
- } |
- return true; |
- } |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- ASSERT(js->num_arguments() == 4); |
- intptr_t id; |
- if (!GetIntegerId(js->GetArgument(3), &id)) { |
- PrintError(js, "Must specify collection object id: types/id"); |
- return true; |
- } |
- Type& type = Type::Handle(); |
- type ^= cls.CanonicalTypeFromIndex(id); |
- if (type.IsNull()) { |
- PrintError(js, "Canonical type %" Pd " not found", id); |
- return true; |
- } |
- type.PrintJSON(js, false); |
+ PrintError(js, "%s: Invalid 'targetId' parameter value: " |
+ "id '%s' does not correspond to a " |
+ "library, class, or instance", js->method(), target_id); |
return true; |
} |
@@ -2154,26 +1874,26 @@ class GetInstancesVisitor : public ObjectGraph::Visitor { |
static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) { |
- const char* target_id = js->LookupOption("classId"); |
+ const char* target_id = js->LookupParam("classId"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'classId' option"); |
+ PrintMissingParamError(js, "classId"); |
return true; |
} |
- const char* limit_cstr = js->LookupOption("limit"); |
+ const char* limit_cstr = js->LookupParam("limit"); |
if (target_id == NULL) { |
- PrintError(js, "Missing 'limit' option"); |
+ PrintMissingParamError(js, "limit"); |
return true; |
} |
intptr_t limit; |
- if (!GetIntegerId(js->LookupOption("limit"), &limit)) { |
- PrintError(js, "Invalid 'limit' option: %s", limit_cstr); |
+ if (!GetIntegerId(limit_cstr, &limit)) { |
+ PrintInvalidParamError(js, "limit"); |
return true; |
} |
const Object& obj = |
Object::Handle(LookupHeapObject(isolate, target_id, NULL)); |
if (obj.raw() == Object::sentinel().raw() || |
!obj.IsClass()) { |
- PrintError(js, "Invalid 'classId' value: no class with id '%s'", target_id); |
+ PrintInvalidParamError(js, "classId"); |
return true; |
} |
const Class& cls = Class::Cast(obj); |
@@ -2199,60 +1919,15 @@ static bool HandleIsolateGetInstances(Isolate* isolate, JSONStream* js) { |
} |
-static bool HandleClasses(Isolate* isolate, JSONStream* js) { |
- if (js->num_arguments() == 1) { |
- PrintError(js, "Invalid number of arguments."); |
- return true; |
- } |
- ASSERT(js->num_arguments() >= 2); |
- intptr_t id; |
- if (!GetIntegerId(js->GetArgument(1), &id)) { |
- PrintError(js, "Must specify collection object id: /classes/id"); |
- return true; |
- } |
- ClassTable* table = isolate->class_table(); |
- if (!table->IsValidIndex(id)) { |
- PrintError(js, "%" Pd " is not a valid class id.", id); |
- return true; |
- } |
- Class& cls = Class::Handle(table->At(id)); |
- if (js->num_arguments() == 2) { |
- cls.PrintJSON(js, false); |
- return true; |
- } else if (js->num_arguments() >= 3) { |
- const char* second = js->GetArgument(2); |
- if (strcmp(second, "closures") == 0) { |
- return HandleClassesClosures(isolate, cls, js); |
- } else if (strcmp(second, "fields") == 0) { |
- return HandleClassesFields(isolate, cls, js); |
- } else if (strcmp(second, "functions") == 0) { |
- return HandleClassesFunctions(isolate, cls, js); |
- } else if (strcmp(second, "implicit_closures") == 0) { |
- return HandleClassesImplicitClosures(isolate, cls, js); |
- } else if (strcmp(second, "dispatchers") == 0) { |
- return HandleClassesDispatchers(isolate, cls, js); |
- } else if (strcmp(second, "types") == 0) { |
- return HandleClassesTypes(isolate, cls, js); |
- } else { |
- PrintError(js, "Invalid sub collection %s", second); |
- return true; |
- } |
- } |
- UNREACHABLE(); |
- return true; |
-} |
- |
- |
static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) { |
- if (!js->HasOption("targetId")) { |
+ if (!js->HasParam("targetId")) { |
CodeCoverage::PrintJSON(isolate, js, NULL); |
return true; |
} |
- const char* target_id = js->LookupOption("targetId"); |
+ const char* target_id = js->LookupParam("targetId"); |
Object& obj = Object::Handle(LookupHeapObject(isolate, target_id, NULL)); |
if (obj.raw() == Object::sentinel().raw()) { |
- PrintError(js, "Invalid 'targetId' value: no object with id '%s'", |
- target_id); |
+ PrintInvalidParamError(js, "targetId"); |
return true; |
} |
if (obj.IsScript()) { |
@@ -2275,27 +1950,28 @@ static bool HandleIsolateGetCoverage(Isolate* isolate, JSONStream* js) { |
CodeCoverage::PrintJSON(isolate, js, &ff); |
return true; |
} |
- PrintError(js, "Invalid 'targetId' value: id '%s' does not correspond to a " |
- "script, library, class, or function", target_id); |
+ PrintError(js, "%s: Invalid 'targetId' parameter value: " |
+ "id '%s' does not correspond to a " |
+ "script, library, class, or function", js->method(), target_id); |
return true; |
} |
static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) { |
- if (!js->HasOption("line")) { |
- PrintError(js, "Missing 'line' option"); |
+ if (!js->HasParam("line")) { |
+ PrintMissingParamError(js, "line"); |
return true; |
} |
- const char* line_option = js->LookupOption("line"); |
+ const char* line_param = js->LookupParam("line"); |
intptr_t line = -1; |
- if (!GetIntegerId(line_option, &line)) { |
- PrintError(js, "Invalid 'line' value: %s is not an integer", line_option); |
+ if (!GetIntegerId(line_param, &line)) { |
+ PrintInvalidParamError(js, "line"); |
return true; |
} |
- const char* script_id = js->LookupOption("script"); |
+ const char* script_id = js->LookupParam("script"); |
Object& obj = Object::Handle(LookupHeapObject(isolate, script_id, NULL)); |
if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) { |
- PrintError(js, "Invalid 'script' value: no script with id '%s'", script_id); |
+ PrintInvalidParamError(js, "script"); |
return true; |
} |
const Script& script = Script::Cast(obj); |
@@ -2303,7 +1979,7 @@ static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) { |
SourceBreakpoint* bpt = |
isolate->debugger()->SetBreakpointAtLine(script_url, line); |
if (bpt == NULL) { |
- PrintError(js, "Unable to set breakpoint at line %s", line_option); |
+ PrintError(js, "Unable to set breakpoint at line %s", line_param); |
return true; |
} |
bpt->PrintJSON(js); |
@@ -2312,16 +1988,15 @@ static bool HandleIsolateAddBreakpoint(Isolate* isolate, JSONStream* js) { |
static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) { |
- if (!js->HasOption("breakpointId")) { |
- PrintError(js, "Missing 'breakpointId' option"); |
+ if (!js->HasParam("breakpointId")) { |
+ PrintMissingParamError(js, "breakpointId"); |
return true; |
} |
- const char* bpt_id = js->LookupOption("breakpointId"); |
+ const char* bpt_id = js->LookupParam("breakpointId"); |
SourceBreakpoint* bpt = LookupBreakpoint(isolate, bpt_id); |
if (bpt == NULL) { |
fprintf(stderr, "ERROR1"); |
- PrintError(js, "Invalid 'breakpointId' value: no breakpoint with id '%s'", |
- bpt_id); |
+ PrintInvalidParamError(js, "breakpointId"); |
return true; |
} |
isolate->debugger()->RemoveBreakpoint(bpt->id()); |
@@ -2335,75 +2010,6 @@ static bool HandleIsolateRemoveBreakpoint(Isolate* isolate, JSONStream* js) { |
} |
-static bool HandleLibrariesScripts(Isolate* isolate, |
- const Library& lib, |
- JSONStream* js) { |
- if (js->num_arguments() > 5) { |
- PrintError(js, "Command too long"); |
- return true; |
- } else if (js->num_arguments() < 4) { |
- PrintError(js, "Must specify collection object id: scripts/id"); |
- return true; |
- } |
- const String& id = String::Handle(String::New(js->GetArgument(3))); |
- ASSERT(!id.IsNull()); |
- // The id is the url of the script % encoded, decode it. |
- const String& requested_url = String::Handle(String::DecodeIRI(id)); |
- Script& script = Script::Handle(); |
- String& script_url = String::Handle(); |
- const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); |
- ASSERT(!loaded_scripts.IsNull()); |
- intptr_t i; |
- for (i = 0; i < loaded_scripts.Length(); i++) { |
- script ^= loaded_scripts.At(i); |
- ASSERT(!script.IsNull()); |
- script_url ^= script.url(); |
- if (script_url.Equals(requested_url)) { |
- break; |
- } |
- } |
- if (i == loaded_scripts.Length()) { |
- PrintError(js, "Script %s not found", requested_url.ToCString()); |
- return true; |
- } |
- if (js->num_arguments() > 4) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- script.PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleLibraries(Isolate* isolate, JSONStream* js) { |
- // TODO(johnmccutchan): Support fields and functions on libraries. |
- 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()); |
- if (js->num_arguments() == 2) { |
- lib.PrintJSON(js, false); |
- return true; |
- } else if (js->num_arguments() >= 3) { |
- const char* second = js->GetArgument(2); |
- if (strcmp(second, "scripts") == 0) { |
- return HandleLibrariesScripts(isolate, lib, js); |
- } else { |
- PrintError(js, "Invalid sub collection %s", second); |
- return true; |
- } |
- } |
- UNREACHABLE(); |
- return true; |
-} |
- |
- |
static RawClass* GetMetricsClass(Isolate* isolate) { |
const Library& prof_lib = |
Library::Handle(isolate, Library::ProfilerLibrary()); |
@@ -2500,18 +2106,17 @@ static bool HandleDartMetric(Isolate* isolate, JSONStream* js, const char* id) { |
static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) { |
bool native_metrics = false; |
- if (js->HasOption("type")) { |
- if (js->OptionIs("type", "Native")) { |
+ if (js->HasParam("type")) { |
+ if (js->ParamIs("type", "Native")) { |
native_metrics = true; |
- } else if (js->OptionIs("type", "Dart")) { |
+ } else if (js->ParamIs("type", "Dart")) { |
native_metrics = false; |
} else { |
- PrintError(js, "Invalid 'type' option value: %s\n", |
- js->LookupOption("type")); |
+ PrintInvalidParamError(js, "type"); |
return true; |
} |
} else { |
- PrintError(js, "Expected 'type' option."); |
+ PrintMissingParamError(js, "type"); |
return true; |
} |
if (native_metrics) { |
@@ -2522,9 +2127,9 @@ static bool HandleIsolateGetMetricList(Isolate* isolate, JSONStream* js) { |
static bool HandleIsolateGetMetric(Isolate* isolate, JSONStream* js) { |
- const char* metric_id = js->LookupOption("metricId"); |
+ const char* metric_id = js->LookupParam("metricId"); |
if (metric_id == NULL) { |
- PrintError(js, "Expected 'metricId' option."); |
+ PrintMissingParamError(js, "metricId"); |
return true; |
} |
// Verify id begins with "metrics/". |
@@ -2553,114 +2158,16 @@ static bool HandleVMGetMetricList(JSONStream* js) { |
static bool HandleVMGetMetric(JSONStream* js) { |
- const char* metric_id = js->LookupOption("metricId"); |
+ const char* metric_id = js->LookupParam("metricId"); |
if (metric_id == NULL) { |
- PrintError(js, "Expected 'metricId' option."); |
+ PrintMissingParamError(js, "metricId"); |
} |
return false; |
} |
-static bool HandleObjects(Isolate* isolate, JSONStream* js) { |
- REQUIRE_COLLECTION_ID("objects"); |
- if (js->num_arguments() != 2) { |
- PrintError(js, "expected at least 2 arguments but found %" Pd "\n", |
- js->num_arguments()); |
- return true; |
- } |
- const char* arg = js->GetArgument(1); |
- |
- // Handle special non-objects first. |
- if (strcmp(arg, "optimized-out") == 0) { |
- if (js->num_arguments() > 2) { |
- PrintError(js, "expected at most 2 arguments but found %" Pd "\n", |
- js->num_arguments()); |
- } else { |
- Symbols::OptimizedOut().PrintJSON(js, false); |
- } |
- return true; |
- |
- } else if (strcmp(arg, "collected") == 0) { |
- if (js->num_arguments() > 2) { |
- PrintError(js, "expected at most 2 arguments but found %" Pd "\n", |
- js->num_arguments()); |
- } else { |
- PrintSentinel(js, "objects/collected", "<collected>"); |
- } |
- return true; |
- |
- } else if (strcmp(arg, "expired") == 0) { |
- if (js->num_arguments() > 2) { |
- PrintError(js, "expected at most 2 arguments but found %" Pd "\n", |
- js->num_arguments()); |
- } else { |
- PrintSentinel(js, "objects/expired", "<expired>"); |
- } |
- return true; |
- } |
- |
- // Lookup the object. |
- Object& obj = Object::Handle(isolate); |
- ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid; |
- obj = LookupObjectId(isolate, arg, &kind); |
- if (kind == ObjectIdRing::kInvalid) { |
- PrintError(js, "unrecognized object id '%s'", arg); |
- return true; |
- } |
- |
- // Print. |
- if (kind == ObjectIdRing::kCollected) { |
- // The object has been collected by the gc. |
- PrintSentinel(js, "objects/collected", "<collected>"); |
- return true; |
- } else if (kind == ObjectIdRing::kExpired) { |
- // The object id has expired. |
- PrintSentinel(js, "objects/expired", "<expired>"); |
- return true; |
- } |
- obj.PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleScriptsEnumerate(Isolate* isolate, JSONStream* js) { |
- JSONObject jsobj(js); |
- jsobj.AddProperty("type", "ScriptList"); |
- jsobj.AddProperty("id", "scripts"); |
- JSONArray members(&jsobj, "members"); |
- const GrowableObjectArray& libs = |
- GrowableObjectArray::Handle(isolate->object_store()->libraries()); |
- intptr_t 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); |
- } |
- } |
- return true; |
-} |
- |
- |
-static bool HandleScripts(Isolate* isolate, JSONStream* js) { |
- if (js->num_arguments() == 1) { |
- // Enumerate all scripts. |
- return HandleScriptsEnumerate(isolate, js); |
- } |
- PrintError(js, "Command too long"); |
- return true; |
-} |
- |
- |
static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) { |
- const char* step_option = js->LookupOption("step"); |
+ const char* step_param = js->LookupParam("step"); |
if (isolate->message_handler()->paused_on_start()) { |
isolate->message_handler()->set_pause_on_start(false); |
JSONObject jsobj(js); |
@@ -2676,15 +2183,15 @@ static bool HandleIsolateResume(Isolate* isolate, JSONStream* js) { |
return true; |
} |
if (isolate->debugger()->PauseEvent() != NULL) { |
- if (step_option != NULL) { |
- if (strcmp(step_option, "into") == 0) { |
+ if (step_param != NULL) { |
+ if (strcmp(step_param, "into") == 0) { |
isolate->debugger()->SetSingleStep(); |
- } else if (strcmp(step_option, "over") == 0) { |
+ } else if (strcmp(step_param, "over") == 0) { |
isolate->debugger()->SetStepOver(); |
- } else if (strcmp(step_option, "out") == 0) { |
+ } else if (strcmp(step_param, "out") == 0) { |
isolate->debugger()->SetStepOut(); |
} else { |
- PrintError(js, "Invalid 'step' option: %s", step_option); |
+ PrintInvalidParamError(js, "step"); |
return true; |
} |
} |
@@ -2719,69 +2226,6 @@ static bool HandleIsolatePause(Isolate* isolate, JSONStream* js) { |
} |
-static bool HandleNullCode(uintptr_t pc, JSONStream* js) { |
- // TODO(turnidge): Consider adding/using Object::null_code() for |
- // consistent "type". |
- Object::null_object().PrintJSON(js, false); |
- return true; |
-} |
- |
- |
-static bool HandleCode(Isolate* isolate, JSONStream* js) { |
- REQUIRE_COLLECTION_ID("code"); |
- uword pc; |
- if (js->num_arguments() > 2) { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
- ASSERT(js->num_arguments() == 2); |
- static const char* kCollectedPrefix = "collected-"; |
- static intptr_t kCollectedPrefixLen = strlen(kCollectedPrefix); |
- static const char* kNativePrefix = "native-"; |
- static intptr_t kNativePrefixLen = strlen(kNativePrefix); |
- static const char* kReusedPrefix = "reused-"; |
- static intptr_t kReusedPrefixLen = strlen(kReusedPrefix); |
- const char* command = js->GetArgument(1); |
- if (strncmp(kCollectedPrefix, command, kCollectedPrefixLen) == 0) { |
- if (!GetUnsignedIntegerId(&command[kCollectedPrefixLen], &pc, 16)) { |
- PrintError(js, "Must specify code address: code/%sc0deadd0.", |
- kCollectedPrefix); |
- return true; |
- } |
- return HandleNullCode(pc, js); |
- } |
- if (strncmp(kNativePrefix, command, kNativePrefixLen) == 0) { |
- if (!GetUnsignedIntegerId(&command[kNativePrefixLen], &pc, 16)) { |
- PrintError(js, "Must specify code address: code/%sc0deadd0.", |
- kNativePrefix); |
- return true; |
- } |
- // TODO(johnmccutchan): Support native Code. |
- return HandleNullCode(pc, js); |
- } |
- if (strncmp(kReusedPrefix, command, kReusedPrefixLen) == 0) { |
- if (!GetUnsignedIntegerId(&command[kReusedPrefixLen], &pc, 16)) { |
- PrintError(js, "Must specify code address: code/%sc0deadd0.", |
- kReusedPrefix); |
- return true; |
- } |
- return HandleNullCode(pc, js); |
- } |
- int64_t timestamp = 0; |
- if (!GetCodeId(command, ×tamp, &pc) || (timestamp < 0)) { |
- PrintError(js, "Malformed code id: %s", command); |
- return true; |
- } |
- Code& code = Code::Handle(Code::FindCode(pc, timestamp)); |
- if (!code.IsNull()) { |
- code.PrintJSON(js, false); |
- return true; |
- } |
- PrintError(js, "Could not find code with id: %s", command); |
- return true; |
-} |
- |
- |
static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) { |
JSONObject miniProfile(js); |
miniProfile.AddProperty("type", "TagProfile"); |
@@ -2792,23 +2236,22 @@ static bool HandleIsolateGetTagProfile(Isolate* isolate, JSONStream* js) { |
static bool HandleIsolateGetCpuProfile(Isolate* isolate, JSONStream* js) { |
// A full profile includes disassembly of all Dart code objects. |
- // TODO(johnmccutchan): Add sub command to trigger full code dump. |
+ // TODO(johnmccutchan): Add option to trigger full code dump. |
bool full_profile = false; |
- const char* tags_option = js->LookupOption("tags"); |
Profiler::TagOrder tag_order = Profiler::kUserVM; |
- if (js->HasOption("tags")) { |
- if (js->OptionIs("tags", "None")) { |
+ if (js->HasParam("tags")) { |
+ if (js->ParamIs("tags", "None")) { |
tag_order = Profiler::kNoTags; |
- } else if (js->OptionIs("tags", "UserVM")) { |
+ } else if (js->ParamIs("tags", "UserVM")) { |
tag_order = Profiler::kUserVM; |
- } else if (js->OptionIs("tags", "UserOnly")) { |
+ } else if (js->ParamIs("tags", "UserOnly")) { |
tag_order = Profiler::kUser; |
- } else if (js->OptionIs("tags", "VMUser")) { |
+ } else if (js->ParamIs("tags", "VMUser")) { |
tag_order = Profiler::kVMUser; |
- } else if (js->OptionIs("tags", "VMOnly")) { |
+ } else if (js->ParamIs("tags", "VMOnly")) { |
tag_order = Profiler::kVM; |
} else { |
- PrintError(js, "Invalid tags option value: %s\n", tags_option); |
+ PrintInvalidParamError(js, "tags"); |
return true; |
} |
} |
@@ -2821,20 +2264,19 @@ static bool HandleIsolateGetAllocationProfile(Isolate* isolate, |
JSONStream* js) { |
bool should_reset_accumulator = false; |
bool should_collect = false; |
- if (js->HasOption("reset")) { |
- if (js->OptionIs("reset", "true")) { |
+ if (js->HasParam("reset")) { |
+ if (js->ParamIs("reset", "true")) { |
should_reset_accumulator = true; |
} else { |
- PrintError(js, "Unrecognized reset option '%s'", |
- js->LookupOption("reset")); |
+ PrintInvalidParamError(js, "reset"); |
return true; |
} |
} |
- if (js->HasOption("gc")) { |
- if (js->OptionIs("gc", "full")) { |
+ if (js->HasParam("gc")) { |
+ if (js->ParamIs("gc", "full")) { |
should_collect = true; |
} else { |
- PrintError(js, "Unrecognized gc option '%s'", js->LookupOption("gc")); |
+ PrintInvalidParamError(js, "gc"); |
return true; |
} |
} |
@@ -2907,15 +2349,20 @@ class ContainsAddressVisitor : public FindObjectVisitor { |
}; |
-static bool HandleAddress(Isolate* isolate, JSONStream* js) { |
+static bool HandleIsolateGetObjectByAddress(Isolate* isolate, JSONStream* js) { |
+ const char* addr_str = js->LookupParam("address"); |
+ if (addr_str == NULL) { |
+ PrintMissingParamError(js, "address"); |
+ return true; |
+ } |
+ |
+ // Handle heap objects. |
uword addr = 0; |
- if (js->num_arguments() != 2 || |
- !GetUnsignedIntegerId(js->GetArgument(1), &addr, 16)) { |
- static const uword kExampleAddr = static_cast<uword>(kIntptrMax / 7); |
- PrintError(js, "Must specify address: address/" Px ".", kExampleAddr); |
+ if (!GetUnsignedIntegerId(addr_str, &addr, 16)) { |
+ PrintInvalidParamError(js, "address"); |
return true; |
} |
- bool ref = js->HasOption("ref") && js->OptionIs("ref", "true"); |
+ bool ref = js->HasParam("ref") && js->ParamIs("ref", "true"); |
Object& object = Object::Handle(isolate); |
{ |
NoGCScope no_gc; |
@@ -2949,39 +2396,10 @@ static bool HandleIsolateRespondWithMalformedObject(Isolate* isolate, |
} |
-static IsolateMessageHandlerEntry isolate_handlers[] = { |
- { "", HandleIsolate }, // getObject |
- { "address", HandleAddress }, // to do |
- { "classes", HandleClasses }, // getObject |
- { "code", HandleCode }, // getObject |
- { "libraries", HandleLibraries }, // getObject |
- { "objects", HandleObjects }, // getObject |
- { "scripts", HandleScripts }, // getObject |
-}; |
- |
- |
-static IsolateMessageHandler FindIsolateMessageHandler(const char* command) { |
- intptr_t num_message_handlers = sizeof(isolate_handlers) / |
- sizeof(isolate_handlers[0]); |
- for (intptr_t i = 0; i < num_message_handlers; i++) { |
- const IsolateMessageHandlerEntry& entry = isolate_handlers[i]; |
- if (strcmp(command, entry.command) == 0) { |
- return entry.handler; |
- } |
- } |
- if (FLAG_trace_service) { |
- OS::Print("vm-service: No isolate message handler for <%s>.\n", command); |
- } |
- return NULL; |
-} |
- |
- |
static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) { |
- const char* id = js->LookupOption("objectId"); |
+ const char* id = js->LookupParam("objectId"); |
if (id == NULL) { |
- // TODO(turnidge): Print the isolate here instead. |
- PrintError(js, "GetObject expects an 'objectId' parameter\n", |
- js->num_arguments()); |
+ PrintMissingParamError(js, "objectId"); |
return true; |
} |
@@ -2995,8 +2413,10 @@ static bool HandleIsolateGetObject(Isolate* isolate, JSONStream* js) { |
return true; |
} else if (lookup_result == ObjectIdRing::kCollected) { |
PrintSentinel(js, "objects/collected", "<collected>"); |
+ return true; |
} else if (lookup_result == ObjectIdRing::kExpired) { |
PrintSentinel(js, "objects/expired", "<expired>"); |
+ return true; |
} |
// Handle non-heap objects. |
@@ -3022,7 +2442,7 @@ static bool HandleIsolateGetClassList(Isolate* isolate, JSONStream* js) { |
static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate, |
JSONStream* js) { |
bool only_with_instantiations = false; |
- if (js->OptionIs("onlyWithInstantiations", "true")) { |
+ if (js->ParamIs("onlyWithInstantiations", "true")) { |
only_with_instantiations = true; |
} |
ObjectStore* object_store = isolate->object_store(); |
@@ -3051,6 +2471,7 @@ static bool HandleIsolateGetTypeArgumentsList(Isolate* isolate, |
static IsolateMessageHandlerEntry isolate_handlers_new[] = { |
{ "getIsolate", HandleIsolate }, |
{ "getObject", HandleIsolateGetObject }, |
+ { "getObjectByAddress", HandleIsolateGetObjectByAddress }, |
{ "getBreakpoints", HandleIsolateGetBreakpoints }, |
{ "pause", HandleIsolatePause }, |
{ "resume", HandleIsolateResume }, |
@@ -3079,33 +2500,33 @@ static IsolateMessageHandlerEntry isolate_handlers_new[] = { |
}; |
-static IsolateMessageHandler FindIsolateMessageHandlerNew(const char* command) { |
+static IsolateMessageHandler FindIsolateMessageHandler(const char* method) { |
intptr_t num_message_handlers = sizeof(isolate_handlers_new) / |
sizeof(isolate_handlers_new[0]); |
for (intptr_t i = 0; i < num_message_handlers; i++) { |
const IsolateMessageHandlerEntry& entry = isolate_handlers_new[i]; |
- if (strcmp(command, entry.command) == 0) { |
+ if (strcmp(method, entry.method) == 0) { |
return entry.handler; |
} |
} |
if (FLAG_trace_service) { |
- OS::Print("Service has no isolate message handler for <%s>\n", command); |
+ OS::Print("Service has no isolate message handler for <%s>\n", method); |
} |
return NULL; |
} |
-void Service::HandleRootMessageNew(const Array& msg) { |
+void Service::HandleRootMessage(const Instance& msg_instance) { |
Isolate* isolate = Isolate::Current(); |
- ASSERT(!msg.IsNull()); |
+ ASSERT(!msg_instance.IsNull()); |
+ ASSERT(msg_instance.IsArray()); |
{ |
StackZone zone(isolate); |
HANDLESCOPE(isolate); |
- const Array& message = Array::Cast(msg); |
- // Message is a list with five entries. |
- ASSERT(message.Length() == 5); |
+ const Array& msg = Array::Cast(msg_instance); |
+ ASSERT(msg.Length() == 5); |
Instance& reply_port = Instance::Handle(isolate); |
String& method = String::Handle(isolate); |
@@ -3126,11 +2547,11 @@ void Service::HandleRootMessageNew(const Array& msg) { |
} |
RootMessageHandler handler = |
- FindRootMessageHandlerNew(method.ToCString()); |
+ FindRootMessageHandler(method.ToCString()); |
{ |
JSONStream js; |
- js.SetupNew(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
- method, param_keys, param_values); |
+ js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
+ method, param_keys, param_values); |
if (handler == NULL) { |
// Check for an embedder handler. |
EmbedderServiceHandler* e_handler = |
@@ -3138,9 +2559,8 @@ void Service::HandleRootMessageNew(const Array& msg) { |
if (e_handler != NULL) { |
EmbedderHandleMessage(e_handler, &js); |
} else { |
- if (FindIsolateMessageHandlerNew(method.ToCString()) != NULL) { |
- PrintError(&js, "%s expects an 'isolate' parameter\n", |
- method.ToCString()); |
+ if (FindIsolateMessageHandler(method.ToCString()) != NULL) { |
+ PrintMissingParamError(&js, "isolateId"); |
} else { |
PrintError(&js, "Unrecognized method: %s", method.ToCString()); |
} |
@@ -3158,84 +2578,6 @@ void Service::HandleRootMessageNew(const Array& msg) { |
} |
-void Service::HandleRootMessage(const Instance& msg) { |
- Isolate* isolate = Isolate::Current(); |
- ASSERT(!msg.IsNull()); |
- ASSERT(msg.IsArray()); |
- |
- { |
- StackZone zone(isolate); |
- HANDLESCOPE(isolate); |
- |
- const Array& message = Array::Cast(msg); |
- // Message is a list with five entries. |
- ASSERT(message.Length() == 5); |
- |
- Object& tmp = Object::Handle(isolate); |
- tmp = message.At(2); |
- if (tmp.IsString()) { |
- return Service::HandleRootMessageNew(message); |
- } |
- |
- Instance& reply_port = Instance::Handle(isolate); |
- GrowableObjectArray& path = GrowableObjectArray::Handle(isolate); |
- Array& option_keys = Array::Handle(isolate); |
- Array& option_values = Array::Handle(isolate); |
- |
- reply_port ^= message.At(1); |
- path ^= message.At(2); |
- option_keys ^= message.At(3); |
- option_values ^= message.At(4); |
- |
- ASSERT(!path.IsNull()); |
- ASSERT(!option_keys.IsNull()); |
- ASSERT(!option_values.IsNull()); |
- // Path always has at least one entry in it. |
- ASSERT(path.Length() > 0); |
- // Same number of option keys as values. |
- ASSERT(option_keys.Length() == option_values.Length()); |
- |
- if (!reply_port.IsSendPort()) { |
- FATAL("SendPort expected."); |
- } |
- |
- String& path_segment = String::Handle(); |
- if (path.Length() > 0) { |
- path_segment ^= path.At(0); |
- } else { |
- path_segment ^= Symbols::Empty().raw(); |
- } |
- ASSERT(!path_segment.IsNull()); |
- const char* path_segment_c = path_segment.ToCString(); |
- |
- RootMessageHandler handler = |
- FindRootMessageHandler(path_segment_c); |
- { |
- JSONStream js; |
- js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
- path, option_keys, option_values); |
- if (handler == NULL) { |
- // Check for an embedder handler. |
- EmbedderServiceHandler* e_handler = |
- FindRootEmbedderHandler(path_segment_c); |
- if (e_handler != NULL) { |
- EmbedderHandleMessage(e_handler, &js); |
- } else { |
- PrintError(&js, "Unrecognized path"); |
- } |
- js.PostReply(); |
- } else { |
- if (handler(&js)) { |
- // Handler returns true if the reply is ready to be posted. |
- // TODO(johnmccutchan): Support asynchronous replies. |
- js.PostReply(); |
- } |
- } |
- } |
- } |
-} |
- |
- |
static bool HandleRootEcho(JSONStream* js) { |
JSONObject jsobj(js); |
return HandleCommonEcho(&jsobj, js); |
@@ -3293,83 +2635,59 @@ static bool HandleVM(JSONStream* js) { |
} |
-static bool HandleFlags(JSONStream* js) { |
- if (js->num_arguments() == 1) { |
- Flags::PrintJSON(js); |
- return true; |
- } else if (js->num_arguments() == 2) { |
- const char* arg = js->GetArgument(1); |
- if (strcmp(arg, "set") == 0) { |
- if (js->num_arguments() > 2) { |
- PrintError(js, "expected at most 2 arguments but found %" Pd "\n", |
- js->num_arguments()); |
- } else { |
- if (js->HasOption("name") && js->HasOption("value")) { |
- JSONObject jsobj(js); |
- const char* flag_name = js->LookupOption("name"); |
- const char* flag_value = js->LookupOption("value"); |
- const char* error = NULL; |
- if (Flags::SetFlag(flag_name, flag_value, &error)) { |
- jsobj.AddProperty("type", "Success"); |
- jsobj.AddProperty("id", ""); |
- } else { |
- jsobj.AddProperty("type", "Failure"); |
- jsobj.AddProperty("id", ""); |
- jsobj.AddProperty("message", error); |
- } |
- } else { |
- PrintError(js, "expected to find 'name' and 'value' options"); |
- } |
- } |
- } |
- return true; |
- } else { |
- PrintError(js, "Command too long"); |
- return true; |
- } |
+static bool HandleVMFlagList(JSONStream* js) { |
+ Flags::PrintJSON(js); |
+ return true; |
} |
-static RootMessageHandlerEntry root_handlers[] = { |
- { "vm", HandleVM }, |
- { "flags", HandleFlags }, |
-}; |
- |
-static RootMessageHandler FindRootMessageHandler(const char* command) { |
- intptr_t num_message_handlers = sizeof(root_handlers) / |
- sizeof(root_handlers[0]); |
- for (intptr_t i = 0; i < num_message_handlers; i++) { |
- const RootMessageHandlerEntry& entry = root_handlers[i]; |
- if (strcmp(command, entry.command) == 0) { |
- return entry.handler; |
- } |
+static bool HandleVMSetFlag(JSONStream* js) { |
+ const char* flag_name = js->LookupParam("name"); |
+ if (flag_name == NULL) { |
+ PrintMissingParamError(js, "name"); |
+ return true; |
} |
- if (FLAG_trace_service) { |
- OS::Print("vm-service: No root message handler for <%s>.\n", command); |
+ const char* flag_value = js->LookupParam("value"); |
+ if (flag_value == NULL) { |
+ PrintMissingParamError(js, "value"); |
+ return true; |
+ } |
+ JSONObject jsobj(js); |
+ const char* error = NULL; |
+ if (Flags::SetFlag(flag_name, flag_value, &error)) { |
+ jsobj.AddProperty("type", "Success"); |
+ jsobj.AddProperty("id", ""); |
+ return true; |
+ } else { |
+ jsobj.AddProperty("type", "Failure"); |
+ jsobj.AddProperty("id", ""); |
+ jsobj.AddProperty("message", error); |
+ return true; |
} |
- return NULL; |
} |
static RootMessageHandlerEntry root_handlers_new[] = { |
{ "getVM", HandleVM }, |
+ { "getFlagList", HandleVMFlagList }, |
+ { "setFlag", HandleVMSetFlag }, |
{ "getVMMetricList", HandleVMGetMetricList }, |
{ "getVMMetric", HandleVMGetMetric }, |
{ "_echo", HandleRootEcho }, |
}; |
-static RootMessageHandler FindRootMessageHandlerNew(const char* command) { |
+static RootMessageHandler FindRootMessageHandler(const char* method) { |
intptr_t num_message_handlers = sizeof(root_handlers_new) / |
sizeof(root_handlers_new[0]); |
for (intptr_t i = 0; i < num_message_handlers; i++) { |
const RootMessageHandlerEntry& entry = root_handlers_new[i]; |
- if (strcmp(command, entry.command) == 0) { |
+ if (strcmp(method, entry.method) == 0) { |
return entry.handler; |
} |
} |
if (FLAG_trace_service) { |
- OS::Print("vm-service: No root message handler for <%s>.\n", command); |
+ OS::Print("vm-service: No root message handler for <%s>.\n", method); |
} |
return NULL; |
} |
@@ -3456,12 +2774,10 @@ void Service::EmbedderHandleMessage(EmbedderServiceHandler* handler, |
Dart_ServiceRequestCallback callback = handler->callback(); |
ASSERT(callback != NULL); |
const char* r = NULL; |
- const char* name = js->command(); |
- const char** arguments = js->arguments(); |
- const char** keys = js->option_keys(); |
- const char** values = js->option_values(); |
- r = callback(name, arguments, js->num_arguments(), keys, values, |
- js->num_options(), handler->user_data()); |
+ const char* name = js->method(); |
+ const char** keys = js->param_keys(); |
+ const char** values = js->param_values(); |
+ r = callback(name, keys, values, js->num_params(), handler->user_data()); |
ASSERT(r != NULL); |
// TODO(johnmccutchan): Allow for NULL returns? |
TextBuffer* buffer = js->buffer(); |