| Index: vm/dart_api_impl.cc
|
| ===================================================================
|
| --- vm/dart_api_impl.cc (revision 5108)
|
| +++ 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;
|
| @@ -2121,10 +2125,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
|
| @@ -2151,7 +2153,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));
|
| @@ -2197,10 +2199,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();
|
|
|