Chromium Code Reviews| Index: runtime/lib/mirrors.cc |
| =================================================================== |
| --- runtime/lib/mirrors.cc (revision 6851) |
| +++ runtime/lib/mirrors.cc (working copy) |
| @@ -6,8 +6,10 @@ |
| #include "vm/dart_entry.h" |
| #include "vm/exceptions.h" |
| +#include "vm/json.h" |
| #include "vm/message.h" |
| #include "vm/port.h" |
| +#include "vm/resolver.h" |
| namespace dart { |
| @@ -55,26 +57,132 @@ |
| } |
| -DEFINE_NATIVE_ENTRY(IsolateMirrorImpl_buildResponse, 1) { |
| - GET_NATIVE_ARGUMENT(Instance, map, arguments->At(0)); |
| - String& key = String::Handle(); |
| - Instance& value = Instance::Handle(); |
| - Object& result = Object::Handle(); |
| +static bool JSONGetLiteral(const char* text, |
| + const char* field_name, |
| + const char** value_chars, |
| + int* value_len) { |
| + JSONReader reader(text); |
| + reader.Seek(field_name); |
| + if (reader.Type() != JSONReader::kLiteral) { |
| + return false; |
| + } |
| + *value_chars = reader.ValueChars(); |
| + *value_len = reader.ValueLen(); |
| + return true; |
| +} |
| - key = String::New("debugName"); |
| - value = String::New(isolate->name()); |
| - result = DartLibraryCalls::MapSetAt(map, key, value); |
| - if (result.IsError()) { |
| - // TODO(turnidge): Prevent mirror operations from crashing other isolates? |
| - Exceptions::PropagateError(result); |
| + |
| +static bool JSONGetString(const char* text, |
| + const char* field_name, |
| + const char** value_chars, |
| + int* value_len) { |
| + JSONReader reader(text); |
| + reader.Seek(field_name); |
| + if (reader.Type() != JSONReader::kString) { |
| + return false; |
| } |
| + *value_chars = reader.ValueChars(); |
| + *value_len = reader.ValueLen(); |
| + return true; |
| +} |
| - key = String::New("ok"); |
| - value = Bool::True(); |
| - result = DartLibraryCalls::MapSetAt(map, key, value); |
| - if (result.IsError()) { |
| - Exceptions::PropagateError(result); |
| + |
| +static bool match(const char* expected, |
| + const char* actual, |
| + int actual_len) { |
| + if (!strncmp(expected, actual, actual_len) == 0) { |
| + return false; |
| } |
| + return expected[actual_len] == '\0'; |
| } |
| + |
| +DEFINE_NATIVE_ENTRY(Mirrors_processResponse, 3) { |
| + GET_NATIVE_ARGUMENT(Instance, port, arguments->At(0)); |
| + GET_NATIVE_ARGUMENT(String, command, arguments->At(1)); |
| + GET_NATIVE_ARGUMENT(String, response, arguments->At(2)); |
| + |
| + const char* json_text = response.ToCString(); |
| + if (command.Equals("isolateMirrorOf")) { |
| + const char* ok; |
| + int ok_len; |
| + const char* debug_name; |
| + int debug_name_len; |
| + if (!JSONGetLiteral(json_text, "ok", &ok, &ok_len) || |
|
hausner
2012/04/23 21:54:17
If you don't throw away the JSONReader object afte
turnidge
2012/04/23 22:14:19
Instead of IsLiteral I added IsTrue(), IsFalse(),
|
| + !match("true", ok, ok_len) || |
| + !JSONGetString(json_text, "debugName", &debug_name, &debug_name_len)) { |
| + // TODO(turnidge): Use an exception class instead of a String. |
| + Exceptions::Throw(Instance::Handle(String::NewFormatted( |
| + "Error while processing mirror request."))); |
| + UNREACHABLE(); |
| + } |
| + |
| + // Create and return a new instance of _IsolateMirrorImpl. |
| + Library& lib = Library::Handle(Library::MirrorsLibrary()); |
| + const String& public_class_name = |
| + String::Handle(String::NewSymbol("_IsolateMirrorImpl")); |
| + const String& class_name = |
| + String::Handle(lib.PrivateName(public_class_name)); |
| + const String& function_name = |
| + String::Handle(String::NewSymbol("_make")); |
| + const int kNumArgs = 2; |
| + const Array& kNoArgNames = Array::Handle(); |
| + const Function& function = Function::Handle( |
| + Resolver::ResolveStatic(lib, |
| + class_name, |
| + function_name, |
| + kNumArgs, |
| + kNoArgNames, |
| + Resolver::kIsQualified)); |
| + |
| + GrowableArray<const Object*> args(kNumArgs); |
| + args.Add(&port); |
| + const String& debug_name_str = String::Handle( |
| + String::NewFormatted("%.*s", debug_name_len, debug_name)); |
| + args.Add(&debug_name_str); |
| + const Object& result = Object::Handle( |
| + DartEntry::InvokeStatic(function, args, kNoArgNames)); |
| + arguments->SetReturn(result); |
| + } |
| +} |
| + |
| + |
| +void HandleMirrorsMessage(Isolate* isolate, |
| + Dart_Port reply_port, |
| + const Instance& message) { |
| + TextBuffer buffer(64); |
| + if (!message.IsString()) { |
| + buffer.Printf( |
| + "{ \"ok\": false, \"error\": \"Malformed mirrors request\" }"); |
| + } else { |
| + String& json_string = String::Handle(); |
| + json_string ^= message.raw(); |
| + const char* json_text = json_string.ToCString(); |
| + |
| + const char* command; |
| + int command_len; |
| + if (JSONGetString(json_text, "command", &command, &command_len)) { |
| + if (match("isolateMirrorOf", command, command_len)) { |
| + buffer.Printf("{ \"ok\": true, \"debugName\": \"%s\" }", |
| + isolate->name()); |
| + } else { |
| + buffer.Printf( |
| + "{ \"ok\": false, \"error\": \"Command '%.*s' not recognized\" }", |
| + command_len, command); |
| + } |
| + } else { |
| + buffer.Printf( |
| + "{ \"ok\": false, \"error\": \"Field 'command' not found\" }"); |
| + } |
| + } |
| + |
| + Dart_CObject reply; |
| + reply.type = Dart_CObject::kString; |
| + reply.value.as_string = buffer.buf(); |
| + if (!Dart_PostCObject(reply_port, &reply)) { |
| + OS::PrintErr("Unable to post mirrors reply"); |
| + return; |
| + } |
| +} |
| + |
| } // namespace dart |