| Index: runtime/vm/dart_api_impl.cc
|
| ===================================================================
|
| --- runtime/vm/dart_api_impl.cc (revision 24158)
|
| +++ runtime/vm/dart_api_impl.cc (working copy)
|
| @@ -1241,22 +1241,16 @@
|
| }
|
|
|
|
|
| -DART_EXPORT bool Dart_IsClass(Dart_Handle handle) {
|
| - Isolate* isolate = Isolate::Current();
|
| - DARTSCOPE(isolate);
|
| - const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
| - return obj.IsClass();
|
| +DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
|
| + return Api::ClassId(handle) == kTypeCid;
|
| }
|
|
|
|
|
| -DART_EXPORT bool Dart_IsAbstractClass(Dart_Handle handle) {
|
| +DART_EXPORT bool Dart_IsClass(Dart_Handle handle) {
|
| Isolate* isolate = Isolate::Current();
|
| DARTSCOPE(isolate);
|
| const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
|
| - if (obj.IsClass()) {
|
| - return Class::Cast(obj).is_abstract();
|
| - }
|
| - return false;
|
| + return obj.IsClass();
|
| }
|
|
|
|
|
| @@ -1287,7 +1281,21 @@
|
|
|
| // --- Instances ----
|
|
|
| -// TODO(turnidge): Technically, null has a class. Should we allow it?
|
| +DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
|
| + Isolate* isolate = Isolate::Current();
|
| + DARTSCOPE(isolate);
|
| + const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(instance));
|
| + if (obj.IsNull()) {
|
| + return Api::NewHandle(isolate, isolate->object_store()->null_type());
|
| + }
|
| + if (!obj.IsInstance()) {
|
| + RETURN_TYPE_ERROR(isolate, instance, Instance);
|
| + }
|
| + const Type& type = Type::Handle(Instance::Cast(obj).GetType());
|
| + return Api::NewHandle(isolate, type.Canonicalize());
|
| +}
|
| +
|
| +// TODO(asiva): Deprecate this method.
|
| DART_EXPORT Dart_Handle Dart_InstanceGetClass(Dart_Handle instance) {
|
| Isolate* isolate = Isolate::Current();
|
| DARTSCOPE(isolate);
|
| @@ -2714,7 +2722,7 @@
|
| }
|
|
|
|
|
| -DART_EXPORT Dart_Handle Dart_New(Dart_Handle clazz,
|
| +DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
|
| Dart_Handle constructor_name,
|
| int number_of_arguments,
|
| Dart_Handle* arguments) {
|
| @@ -2730,23 +2738,32 @@
|
| }
|
|
|
| // Get the class to instantiate.
|
| - Class& cls =
|
| - Class::Handle(isolate, Api::UnwrapClassHandle(isolate, clazz).raw());
|
| - if (cls.IsNull()) {
|
| - RETURN_TYPE_ERROR(isolate, clazz, Class);
|
| + result = Api::UnwrapHandle(type);
|
| + if (result.IsNull()) {
|
| + RETURN_TYPE_ERROR(isolate, type, Type);
|
| }
|
| + Class& cls = Class::Handle(isolate);
|
| + if (result.IsType()) {
|
| + cls = Type::Cast(result).type_class();
|
| + } else if (result.IsClass()) {
|
| + // For backwards compatibility we allow class objects to be passed in
|
| + // for now. This needs to be removed once all code that uses class
|
| + // objects to invoke Dart_New is removed.
|
| + cls ^= result.raw();
|
| + } else {
|
| + RETURN_TYPE_ERROR(isolate, type, Type);
|
| + }
|
|
|
| String& base_constructor_name = String::Handle();
|
| base_constructor_name = cls.Name();
|
|
|
| // And get the name of the constructor to invoke.
|
| String& dot_name = String::Handle(isolate);
|
| - const Object& name_obj =
|
| - Object::Handle(isolate, Api::UnwrapHandle(constructor_name));
|
| - if (name_obj.IsNull()) {
|
| + result = Api::UnwrapHandle(constructor_name);
|
| + if (result.IsNull()) {
|
| dot_name = Symbols::Dot().raw();
|
| - } else if (name_obj.IsString()) {
|
| - dot_name = String::Concat(Symbols::Dot(), String::Cast(name_obj));
|
| + } else if (result.IsString()) {
|
| + dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
|
| } else {
|
| RETURN_TYPE_ERROR(isolate, constructor_name, String);
|
| }
|
| @@ -2848,7 +2865,8 @@
|
| }
|
|
|
| // Check for malformed arguments in the arguments list.
|
| - intptr_t num_receiver = (obj.IsNull() || obj.IsInstance()) ? 1 : 0;
|
| + intptr_t num_receiver =
|
| + (obj.IsNull() || (obj.IsInstance() && !obj.IsType())) ? 1 : 0;
|
| const Array& args =
|
| Array::Handle(isolate, Array::New(number_of_arguments + num_receiver));
|
| Object& arg = Object::Handle(isolate);
|
| @@ -2866,35 +2884,22 @@
|
| args.SetAt((i + num_receiver), arg);
|
| }
|
|
|
| - if (obj.IsNull() || obj.IsInstance()) {
|
| - Instance& instance = Instance::Handle(isolate);
|
| - instance ^= obj.raw();
|
| - const Function& function = Function::Handle(
|
| - isolate,
|
| - Resolver::ResolveDynamic(instance,
|
| - function_name,
|
| - (number_of_arguments + 1),
|
| - Resolver::kIsQualified));
|
| - args.SetAt(0, instance);
|
| - if (function.IsNull()) {
|
| - const Array& args_descriptor =
|
| - Array::Handle(ArgumentsDescriptor::New(args.Length()));
|
| - return Api::NewHandle(isolate,
|
| - DartEntry::InvokeNoSuchMethod(instance,
|
| - function_name,
|
| - args,
|
| - args_descriptor));
|
| - }
|
| - return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
|
| -
|
| - } else if (obj.IsClass()) {
|
| + if (obj.IsType() || obj.IsClass()) {
|
| // Finalize all classes.
|
| Dart_Handle state = Api::CheckIsolateState(isolate);
|
| if (::Dart_IsError(state)) {
|
| return state;
|
| }
|
|
|
| - const Class& cls = Class::Cast(obj);
|
| + // For backwards compatibility we allow class objects to be passed in
|
| + // for now. This needs to be removed once all code that uses class
|
| + // objects to invoke Dart_Invoke is removed.
|
| + Class& cls = Class::Handle();
|
| + if (obj.IsType()) {
|
| + cls = Type::Cast(obj).type_class();
|
| + } else {
|
| + cls = Class::Cast(obj).raw();
|
| + }
|
| const Function& function = Function::Handle(
|
| isolate,
|
| Resolver::ResolveStatic(cls,
|
| @@ -2911,6 +2916,27 @@
|
| }
|
| return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
|
|
|
| + } else if (obj.IsNull() || obj.IsInstance()) {
|
| + Instance& instance = Instance::Handle(isolate);
|
| + instance ^= obj.raw();
|
| + const Function& function = Function::Handle(
|
| + isolate,
|
| + Resolver::ResolveDynamic(instance,
|
| + function_name,
|
| + (number_of_arguments + 1),
|
| + Resolver::kIsQualified));
|
| + args.SetAt(0, instance);
|
| + if (function.IsNull()) {
|
| + const Array& args_descriptor =
|
| + Array::Handle(ArgumentsDescriptor::New(args.Length()));
|
| + return Api::NewHandle(isolate,
|
| + DartEntry::InvokeNoSuchMethod(instance,
|
| + function_name,
|
| + args,
|
| + args_descriptor));
|
| + }
|
| + return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
|
| +
|
| } else if (obj.IsLibrary()) {
|
| // Check whether class finalization is needed.
|
| bool finalize_classes = true;
|
| @@ -2954,7 +2980,7 @@
|
|
|
| } else {
|
| return Api::NewError(
|
| - "%s expects argument 'target' to be an object, class, or library.",
|
| + "%s expects argument 'target' to be an object, type, or library.",
|
| CURRENT_FUNC);
|
| }
|
| }
|
| @@ -3027,6 +3053,36 @@
|
| if (obj.IsNull()) {
|
| return Api::NewError("%s expects argument 'container' to be non-null.",
|
| CURRENT_FUNC);
|
| + } else if (obj.IsType() || obj.IsClass()) {
|
| + // To access a static field we may need to use the Field or the
|
| + // getter Function.
|
| + // For backwards compatibility we allow class objects to be passed in
|
| + // for now. This needs to be removed once all code that uses class
|
| + // objects to invoke Dart_GetField is removed.
|
| + Class& cls = Class::Handle();
|
| + if (obj.IsType()) {
|
| + cls = Type::Cast(obj).type_class();
|
| + } else {
|
| + cls = Class::Cast(obj).raw();
|
| + }
|
| + field = cls.LookupStaticField(field_name);
|
| + if (field.IsNull() || FieldIsUninitialized(isolate, field)) {
|
| + const String& getter_name =
|
| + String::Handle(isolate, Field::GetterName(field_name));
|
| + getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
|
| + }
|
| +
|
| + if (!getter.IsNull()) {
|
| + // Invoke the getter and return the result.
|
| + return Api::NewHandle(
|
| + isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
|
| + } else if (!field.IsNull()) {
|
| + return Api::NewHandle(isolate, field.value());
|
| + } else {
|
| + return Api::NewError("%s: did not find static field '%s'.",
|
| + CURRENT_FUNC, field_name.ToCString());
|
| + }
|
| +
|
| } 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
|
| @@ -3058,28 +3114,6 @@
|
| }
|
| return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
|
|
|
| - } else if (obj.IsClass()) {
|
| - // To access a static field we may need to use the Field or the
|
| - // getter Function.
|
| - const Class& cls = Class::Cast(obj);
|
| - field = cls.LookupStaticField(field_name);
|
| - if (field.IsNull() || FieldIsUninitialized(isolate, field)) {
|
| - const String& getter_name =
|
| - String::Handle(isolate, Field::GetterName(field_name));
|
| - getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
|
| - }
|
| -
|
| - if (!getter.IsNull()) {
|
| - // Invoke the getter and return the result.
|
| - return Api::NewHandle(
|
| - isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
|
| - } else if (!field.IsNull()) {
|
| - return Api::NewHandle(isolate, field.value());
|
| - } 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
|
| @@ -3114,7 +3148,7 @@
|
| return container;
|
| } else {
|
| return Api::NewError(
|
| - "%s expects argument 'container' to be an object, class, or library.",
|
| + "%s expects argument 'container' to be an object, type, or library.",
|
| CURRENT_FUNC);
|
| }
|
| }
|
| @@ -3151,6 +3185,50 @@
|
| if (obj.IsNull()) {
|
| return Api::NewError("%s expects argument 'container' to be non-null.",
|
| CURRENT_FUNC);
|
| + } else if (obj.IsType() || obj.IsClass()) {
|
| + // To access a static field we may need to use the Field or the
|
| + // setter Function.
|
| + // For backwards compatibility we allow class objects to be passed in
|
| + // for now. This needs to be removed once all code that uses class
|
| + // objects to invoke Dart_SetField is removed.
|
| + Class& cls = Class::Handle();
|
| + if (obj.IsType()) {
|
| + cls = Type::Cast(obj).type_class();
|
| + } else {
|
| + cls = Class::Cast(obj).raw();
|
| + }
|
| + field = cls.LookupStaticField(field_name);
|
| + if (field.IsNull()) {
|
| + String& setter_name =
|
| + String::Handle(isolate, Field::SetterName(field_name));
|
| + setter = cls.LookupStaticFunctionAllowPrivate(setter_name);
|
| + }
|
| +
|
| + if (!setter.IsNull()) {
|
| + // Invoke the setter and return the result.
|
| + const int kNumArgs = 1;
|
| + const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
|
| + args.SetAt(0, value_instance);
|
| + const Object& result =
|
| + Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
|
| + if (result.IsError()) {
|
| + return Api::NewHandle(isolate, result.raw());
|
| + } 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.IsInstance()) {
|
| // Every instance field has a setter Function. Try to find the
|
| // setter in any superclass and use that function to access the
|
| @@ -3188,42 +3266,6 @@
|
| }
|
| return Api::NewHandle(isolate, DartEntry::InvokeFunction(setter, args));
|
|
|
| - } else if (obj.IsClass()) {
|
| - // To access a static field we may need to use the Field or the
|
| - // setter Function.
|
| - const Class& cls = Class::Cast(obj);
|
| - field = cls.LookupStaticField(field_name);
|
| - if (field.IsNull()) {
|
| - String& setter_name =
|
| - String::Handle(isolate, Field::SetterName(field_name));
|
| - setter = cls.LookupStaticFunctionAllowPrivate(setter_name);
|
| - }
|
| -
|
| - if (!setter.IsNull()) {
|
| - // Invoke the setter and return the result.
|
| - const int kNumArgs = 1;
|
| - const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
|
| - args.SetAt(0, value_instance);
|
| - const Object& result =
|
| - Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
|
| - if (result.IsError()) {
|
| - return Api::NewHandle(isolate, result.raw());
|
| - } 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
|
| @@ -3265,7 +3307,7 @@
|
| return container;
|
| } else {
|
| return Api::NewError(
|
| - "%s expects argument 'container' to be an object, class, or library.",
|
| + "%s expects argument 'container' to be an object, type, or library.",
|
| CURRENT_FUNC);
|
| }
|
| }
|
|
|