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

Unified Diff: runtime/vm/service.cc

Issue 2872503004: vm-service: Add optional 'scope' parameter to 'evaluate' and 'evaluateInFrame'. (Closed)
Patch Set: review Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/debugger_api_impl.cc ('k') | runtime/vm/service/service_dev.md » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/service.cc
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index f4241bb996cbbb7a1a0eabe689732815c8eeda42..0d134e86371811d3bcae2afc6087014e140ebe10 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -15,12 +15,13 @@
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/isolate.h"
+#include "vm/kernel_isolate.h"
#include "vm/lockers.h"
#include "vm/malloc_hooks.h"
#include "vm/message.h"
#include "vm/message_handler.h"
-#include "vm/native_entry.h"
#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/object_graph.h"
@@ -40,7 +41,6 @@
#include "vm/type_table.h"
#include "vm/unicode.h"
#include "vm/version.h"
-#include "vm/kernel_isolate.h"
namespace dart {
@@ -2221,6 +2221,113 @@ static const MethodParameter* evaluate_params[] = {
};
+static bool IsAlpha(char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+static bool IsAlphaNum(char c) {
+ return (c >= '0' && c <= '9') || IsAlpha(c);
+}
+static bool IsWhitespace(char c) {
+ return c <= ' ';
+}
+static bool IsObjectIdChar(char c) {
+ return IsAlphaNum(c) || c == '/' || c == '-' || c == '@' || c == '%';
+}
+
+
+// TODO(vm-service): Consider whether we should pass structured objects in
+// service messages instead of always flattening them to C strings.
+static bool ParseScope(const char* scope,
+ GrowableArray<const char*>* names,
+ GrowableArray<const char*>* ids) {
+ Zone* zone = Thread::Current()->zone();
+ const char* c = scope;
+ if (*c++ != '{') return false;
+
+ for (;;) {
+ while (IsWhitespace(*c)) {
+ c++;
+ }
+
+ if (*c == '}') return true;
+
+ const char* name = c;
+ if (!IsAlpha(*c)) return false;
+ while (IsAlphaNum(*c)) {
+ c++;
+ }
+ names->Add(zone->MakeCopyOfStringN(name, c - name));
+
+ while (IsWhitespace(*c)) {
+ c++;
+ }
+
+ if (*c++ != ':') return false;
+
+ while (IsWhitespace(*c)) {
+ c++;
+ }
+
+ const char* id = c;
+ if (!IsObjectIdChar(*c)) return false;
+ while (IsObjectIdChar(*c)) {
+ c++;
+ }
+ ids->Add(zone->MakeCopyOfStringN(id, c - id));
+
+ while (IsWhitespace(*c)) {
+ c++;
+ }
+ if (*c == ',') c++;
+ }
+
+ return false;
+}
+
+
+static bool BuildScope(Thread* thread,
+ JSONStream* js,
+ const GrowableObjectArray& names,
+ const GrowableObjectArray& values) {
+ const char* scope = js->LookupParam("scope");
+ GrowableArray<const char*> cnames;
+ GrowableArray<const char*> cids;
+ if (scope != NULL) {
+ if (!ParseScope(scope, &cnames, &cids)) {
+ PrintInvalidParamError(js, "scope");
+ return true;
+ }
+ String& name = String::Handle();
+ Object& obj = Object::Handle();
+ for (intptr_t i = 0; i < cids.length(); i++) {
+ ObjectIdRing::LookupResult lookup_result;
+ obj = LookupHeapObject(thread, cids[i], &lookup_result);
+ if (obj.raw() == Object::sentinel().raw()) {
+ if (lookup_result == ObjectIdRing::kCollected) {
+ PrintSentinel(js, kCollectedSentinel);
+ } else if (lookup_result == ObjectIdRing::kExpired) {
+ PrintSentinel(js, kExpiredSentinel);
+ } else {
+ PrintInvalidParamError(js, "targetId");
+ }
+ return true;
+ }
+ if ((!obj.IsInstance() && !obj.IsNull()) || ContainsNonInstance(obj)) {
+ js->PrintError(kInvalidParams,
+ "%s: invalid scope 'targetId' parameter: "
+ "Cannot evaluate against a VM-internal object",
+ js->method());
+ return true;
+ }
+ name = String::New(cnames[i]);
+ names.Add(name);
+ values.Add(obj);
+ }
+ }
+ return false;
+}
+
+
static bool Evaluate(Thread* thread, JSONStream* js) {
if (!thread->isolate()->compilation_allowed()) {
js->PrintError(kFeatureDisabled,
@@ -2237,7 +2344,18 @@ static bool Evaluate(Thread* thread, JSONStream* js) {
PrintMissingParamError(js, "expression");
return true;
}
+
Zone* zone = thread->zone();
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ const GrowableObjectArray& values =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ if (BuildScope(thread, js, names, values)) {
+ return true;
+ }
+ const Array& names_array = Array::Handle(zone, Array::MakeArray(names));
+ const Array& values_array = Array::Handle(zone, Array::MakeArray(values));
+
const String& expr_str = String::Handle(zone, String::New(expr));
ObjectIdRing::LookupResult lookup_result;
Object& obj =
@@ -2254,17 +2372,15 @@ static bool Evaluate(Thread* thread, JSONStream* js) {
}
if (obj.IsLibrary()) {
const Library& lib = Library::Cast(obj);
- const Object& result = Object::Handle(
- zone,
- lib.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
+ const Object& result =
+ Object::Handle(zone, lib.Evaluate(expr_str, names_array, values_array));
result.PrintJSON(js, true);
return true;
}
if (obj.IsClass()) {
const Class& cls = Class::Cast(obj);
- const Object& result = Object::Handle(
- zone,
- cls.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
+ const Object& result =
+ Object::Handle(zone, cls.Evaluate(expr_str, names_array, values_array));
result.PrintJSON(js, true);
return true;
}
@@ -2274,8 +2390,8 @@ static bool Evaluate(Thread* thread, JSONStream* js) {
instance ^= obj.raw();
const Class& receiver_cls = Class::Handle(zone, instance.clazz());
const Object& result = Object::Handle(
- zone, instance.Evaluate(receiver_cls, expr_str, Array::empty_array(),
- Array::empty_array()));
+ zone,
+ instance.Evaluate(receiver_cls, expr_str, names_array, values_array));
result.PrintJSON(js, true);
return true;
}
@@ -2309,10 +2425,19 @@ static bool EvaluateInFrame(Thread* thread, JSONStream* js) {
ActivationFrame* frame = stack->FrameAt(framePos);
Zone* zone = thread->zone();
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ const GrowableObjectArray& values =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ if (BuildScope(thread, js, names, values)) {
+ return true;
+ }
+
const char* expr = js->LookupParam("expression");
const String& expr_str = String::Handle(zone, String::New(expr));
- const Object& result = Object::Handle(zone, frame->Evaluate(expr_str));
+ const Object& result =
+ Object::Handle(zone, frame->Evaluate(expr_str, names, values));
result.PrintJSON(js, true);
return true;
}
@@ -2929,9 +3054,10 @@ static const char* const timeline_streams_enum_names[] = {
NULL};
static const MethodParameter* set_vm_timeline_flags_params[] = {
- NO_ISOLATE_PARAMETER, new EnumListParameter("recordedStreams",
- false,
- timeline_streams_enum_names),
+ NO_ISOLATE_PARAMETER,
+ new EnumListParameter("recordedStreams",
+ false,
+ timeline_streams_enum_names),
NULL,
};
@@ -3609,8 +3735,9 @@ class PersistentHandleVisitor : public HandleVisitor {
obj.AddProperty("type", "_WeakPersistentHandle");
const Object& object = Object::Handle(weak_persistent_handle->raw());
obj.AddProperty("object", object);
- obj.AddPropertyF("peer", "0x%" Px "", reinterpret_cast<uintptr_t>(
- weak_persistent_handle->peer()));
+ obj.AddPropertyF(
+ "peer", "0x%" Px "",
+ reinterpret_cast<uintptr_t>(weak_persistent_handle->peer()));
obj.AddPropertyF(
"callbackAddress", "0x%" Px "",
reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()));
« no previous file with comments | « runtime/vm/debugger_api_impl.cc ('k') | runtime/vm/service/service_dev.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698