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

Unified Diff: vm/dart_api_impl.cc

Issue 9616044: Adds new apis Dart_GetField/Dart_SetField. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 9 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
Index: vm/dart_api_impl.cc
===================================================================
--- vm/dart_api_impl.cc (revision 4977)
+++ vm/dart_api_impl.cc (working copy)
@@ -792,8 +792,10 @@
DARTSCOPE(isolate);
Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
ASSERT(!isolate_lib.IsNull());
+ const String& public_class_name =
+ String::Handle(String::New("_SendPortImpl"));
const String& class_name =
- String::Handle(isolate_lib.PrivateName("_SendPortImpl"));
+ String::Handle(isolate_lib.PrivateName(public_class_name));
const String& function_name = String::Handle(String::NewSymbol("_create"));
const int kNumArguments = 1;
const Array& kNoArgumentNames = Array::Handle();
@@ -819,8 +821,10 @@
DARTSCOPE(isolate);
Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
ASSERT(!isolate_lib.IsNull());
+ const String& public_class_name =
+ String::Handle(String::New("_ReceivePortImpl"));
const String& class_name =
- String::Handle(isolate_lib.PrivateName("_ReceivePortImpl"));
+ String::Handle(isolate_lib.PrivateName(public_class_name));
const String& function_name =
String::Handle(String::NewSymbol("_get_or_create"));
const int kNumArguments = 1;
@@ -2114,10 +2118,8 @@
static const bool kSetter = false;
-static bool UseGetterForStaticField(const Field& fld) {
- if (fld.IsNull()) {
- return true;
- }
+static bool FieldIsUninitialized(const Field& fld) {
+ ASSERT(!fld.IsNull());
// Return getter method for uninitialized fields, rather than the
// field object, since the value in the field object will not be
@@ -2144,7 +2146,7 @@
String& fld_name = String::Handle();
fld_name ^= param2.raw();
const Field& fld = Field::Handle(cls.LookupStaticField(fld_name));
- if (is_getter && UseGetterForStaticField(fld)) {
+ if (is_getter && (fld.IsNull() || FieldIsUninitialized(fld))) {
const String& func_name = String::Handle(Field::GetterName(fld_name));
const Function& function =
Function::Handle(cls.LookupStaticFunction(func_name));
@@ -2190,10 +2192,257 @@
}
cls = cls.SuperClass();
}
- return Api::NewError("Unable to find field in the class");
+ return Api::NewError("Unable to find field '%s'.", field_name.ToCString());
}
+DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+
+ const String& field_name = Api::UnwrapStringHandle(name);
+ if (field_name.IsNull()) {
+ RETURN_TYPE_ERROR(name, String);
+ }
+
+ const Object& obj = Object::Handle(Api::UnwrapHandle(container));
+
+ Field& field = Field::Handle();
+ Function& getter = Function::Handle();
+ if (obj.IsNull()) {
+ return Api::NewError("%s expects argument 'container' to be non-null.",
+ CURRENT_FUNC);
+ } else if (obj.IsInstance()) {
+ // Every instance field has a getter Function. Try to find the
+ // getter in any superclass and use that function to access the
+ // field.
+ Instance& instance = Instance::Handle();
+ instance ^= obj.raw();
+ Class& cls = Class::Handle(instance.clazz());
+ while (!cls.IsNull()) {
+ String& getter_name = String::Handle(Field::GetterName(field_name));
+ getter = cls.LookupDynamicFunction(getter_name);
+ if (!getter.IsNull()) {
+ break;
+ }
+ cls = cls.SuperClass();
+ }
+
+ if (getter.IsNull()) {
+ return Api::NewError("%s: did not find instance field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ // Invoke the getter and return the result.
+ GrowableArray<const Object*> args;
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeDynamic(instance, getter, args, kNoArgNames));
+ return Api::NewLocalHandle(result);
+
+ } else if (obj.IsClass()) {
+ // To access a static field we may need to use the Field or the
+ // getter Function.
+ Class& cls = Class::Handle();
+ cls ^= obj.raw();
+ field = cls.LookupStaticField(field_name);
+ if (field.IsNull() || FieldIsUninitialized(field)) {
+ const String& getter_name = String::Handle(Field::GetterName(field_name));
+ getter = cls.LookupStaticFunction(getter_name);
+ }
+
+ if (!getter.IsNull()) {
+ // Invoke the getter and return the result.
+ GrowableArray<const Object*> args;
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeStatic(getter, args, kNoArgNames));
+ return Api::NewLocalHandle(result);
+ } else if (!field.IsNull()) {
+ const Object& result = Object::Handle(field.value());
+ return Api::NewLocalHandle(result);
+ } else {
+ return Api::NewError("%s: did not find static field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ } else if (obj.IsLibrary()) {
+ // To access a top-level we may need to use the Field or the
+ // getter Function. The getter function may either be in the
+ // library or in the field's owner class, depending.
+ Library& lib = Library::Handle();
+ lib ^= obj.raw();
+ field = lib.LookupLocalField(field_name);
+ if (field.IsNull()) {
+ // No field found. Check for a getter in the lib.
+ const String& getter_name = String::Handle(Field::GetterName(field_name));
+ getter = lib.LookupLocalFunction(getter_name);
+ } else if (FieldIsUninitialized(field)) {
+ // A field was found. Check for a getter in the field's owner classs.
+ const Class& cls = Class::Handle(field.owner());
+ const String& getter_name = String::Handle(Field::GetterName(field_name));
+ getter = cls.LookupStaticFunction(getter_name);
+ }
+
+ if (!getter.IsNull()) {
+ // Invoke the getter and return the result.
+ GrowableArray<const Object*> args;
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeStatic(getter, args, kNoArgNames));
+ return Api::NewLocalHandle(result);
+ } else if (!field.IsNull()) {
+ const Object& result = Object::Handle(field.value());
+ return Api::NewLocalHandle(result);
+ } else {
+ return Api::NewError("%s: did not find top-level variable '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ } else {
+ return Api::NewError(
+ "%s expects argument 'container' to be an object, class, or library.",
+ CURRENT_FUNC);
+ }
+}
+
+
+DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
+ Dart_Handle name,
+ Dart_Handle value) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+
+ const String& field_name = Api::UnwrapStringHandle(name);
+ if (field_name.IsNull()) {
+ RETURN_TYPE_ERROR(name, String);
+ }
+ const Instance& value_instance = Api::UnwrapInstanceHandle(value);
+ if (value_instance.IsNull()) {
+ RETURN_TYPE_ERROR(value, Instance);
+ }
+
+ Field& field = Field::Handle();
+ Function& setter = Function::Handle();
+ const Object& obj = Object::Handle(Api::UnwrapHandle(container));
+ if (obj.IsNull()) {
+ return Api::NewError("%s expects argument 'container' to be non-null.",
+ CURRENT_FUNC);
+ } else if (obj.IsInstance()) {
+ // Every instance field has a setter Function. Try to find the
+ // setter in any superclass and use that function to access the
+ // field.
+ Instance& instance = Instance::Handle();
+ instance ^= obj.raw();
+ Class& cls = Class::Handle(instance.clazz());
+ while (!cls.IsNull()) {
+ field = cls.LookupInstanceField(field_name);
+ if (!field.IsNull() && field.is_final()) {
+ return Api::NewError("%s: cannot set final field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+ String& setter_name = String::Handle(Field::SetterName(field_name));
+ setter = cls.LookupDynamicFunction(setter_name);
+ if (!setter.IsNull()) {
+ break;
+ }
+ cls = cls.SuperClass();
+ }
+
+ if (setter.IsNull()) {
+ return Api::NewError("%s: did not find instance field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ // Invoke the setter and return the result.
+ GrowableArray<const Object*> args(1);
+ args.Add(&value_instance);
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeDynamic(instance, setter, args, kNoArgNames));
+ return Api::NewLocalHandle(result);
+
+ } else if (obj.IsClass()) {
+ // To access a static field we may need to use the Field or the
+ // setter Function.
+ Class& cls = Class::Handle();
+ cls ^= obj.raw();
+ field = cls.LookupStaticField(field_name);
+ if (field.IsNull()) {
+ String& setter_name = String::Handle(Field::SetterName(field_name));
+ setter = cls.LookupStaticFunction(setter_name);
+ }
+
+ if (!setter.IsNull()) {
+ // Invoke the setter and return the result.
+ GrowableArray<const Object*> args(1);
+ args.Add(&value_instance);
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeStatic(setter, args, kNoArgNames));
+ if (result.IsError()) {
+ return Api::NewLocalHandle(result);
+ } else {
+ return Api::Success();
+ }
+ } else if (!field.IsNull()) {
+ if (field.is_final()) {
+ return Api::NewError("%s: cannot set final field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ } else {
+ field.set_value(value_instance);
+ return Api::Success();
+ }
+ } else {
+ return Api::NewError("%s: did not find static field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ } else if (obj.IsLibrary()) {
+ // To access a top-level we may need to use the Field or the
+ // setter Function. The setter function may either be in the
+ // library or in the field's owner class, depending.
+ Library& lib = Library::Handle();
+ lib ^= obj.raw();
+ field = lib.LookupLocalField(field_name);
+ if (field.IsNull()) {
+ const String& setter_name = String::Handle(Field::SetterName(field_name));
+ setter ^= lib.LookupLocalFunction(setter_name);
+ }
+
+ if (!setter.IsNull()) {
+ // Invoke the setter and return the result.
+ GrowableArray<const Object*> args(1);
+ args.Add(&value_instance);
+ const Array& kNoArgNames = Array::Handle();
+ const Object& result = Object::Handle(
+ DartEntry::InvokeStatic(setter, args, kNoArgNames));
+ if (result.IsError()) {
+ return Api::NewLocalHandle(result);
+ } else {
+ return Api::Success();
+ }
+ } else if (!field.IsNull()) {
+ if (field.is_final()) {
+ return Api::NewError("%s: cannot set final top-level variable '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ } else {
+ field.set_value(value_instance);
+ return Api::Success();
+ }
+ } else {
+ return Api::NewError("%s: did not find top-level variable '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
+ } else {
+ return Api::NewError(
+ "%s expects argument 'container' to be an object, class, or library.",
+ CURRENT_FUNC);
+ }
+}
+
+
DART_EXPORT Dart_Handle Dart_GetStaticField(Dart_Handle cls,
Dart_Handle name) {
Isolate* isolate = Isolate::Current();

Powered by Google App Engine
This is Rietveld 408576698