Index: runtime/vm/dart_api_impl.cc |
=================================================================== |
--- runtime/vm/dart_api_impl.cc (revision 28227) |
+++ runtime/vm/dart_api_impl.cc (working copy) |
@@ -2974,6 +2974,32 @@ |
} |
+static Dart_Handle SetupArguments(Isolate* isolate, |
+ int num_args, |
+ Dart_Handle* arguments, |
+ int extra_args, |
+ Array* args) { |
+ // Check for malformed arguments in the arguments list. |
+ *args = Array::New(num_args + extra_args); |
+ Object& arg = Object::Handle(isolate); |
+ for (int i = 0; i < num_args; i++) { |
+ arg = Api::UnwrapHandle(arguments[i]); |
+ if (!arg.IsNull() && !arg.IsInstance()) { |
+ *args = Array::null(); |
+ if (arg.IsError()) { |
+ return Api::NewHandle(isolate, arg.raw()); |
+ } else { |
+ return Api::NewError( |
+ "%s expects arguments[%d] to be an Instance handle.", |
+ "Dart_Invoke", i); |
+ } |
+ } |
+ args->SetAt((i + extra_args), arg); |
+ } |
+ return Api::Success(); |
+} |
+ |
+ |
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, |
Dart_Handle name, |
int number_of_arguments, |
@@ -2995,27 +3021,10 @@ |
if (obj.IsError()) { |
return target; |
} |
+ Dart_Handle result; |
// Check for malformed arguments in the arguments list. |
- 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); |
- for (int i = 0; i < number_of_arguments; i++) { |
- arg = Api::UnwrapHandle(arguments[i]); |
- if (!arg.IsNull() && !arg.IsInstance()) { |
- if (arg.IsError()) { |
- return Api::NewHandle(isolate, arg.raw()); |
- } else { |
- return Api::NewError( |
- "%s expects arguments[%d] to be an Instance handle.", |
- CURRENT_FUNC, i); |
- } |
- } |
- args.SetAt((i + num_receiver), arg); |
- } |
- |
+ Array& args = Array::Handle(isolate); |
if (obj.IsType()) { |
// Finalize all classes. |
Dart_Handle state = Api::CheckIsolateState(isolate); |
@@ -3038,9 +3047,16 @@ |
cls_name.ToCString(), |
function_name.ToCString()); |
} |
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args)); |
- |
+ result = SetupArguments(isolate, number_of_arguments, arguments, 0, &args); |
+ if (!::Dart_IsError(result)) { |
+ result = Api::NewHandle(isolate, |
+ DartEntry::InvokeFunction(function, args)); |
+ } |
+ return result; |
} else if (obj.IsNull() || obj.IsInstance()) { |
+ // Since we have allocated an object it would mean that all classes |
+ // are finalized and hence it is not necessary to call |
+ // Api::CheckIsolateState. |
Instance& instance = Instance::Handle(isolate); |
instance ^= obj.raw(); |
ArgumentsDescriptor args_desc( |
@@ -3048,18 +3064,77 @@ |
const Function& function = Function::Handle( |
isolate, |
Resolver::ResolveDynamic(instance, function_name, args_desc)); |
- 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)); |
+ // See if we are trying to invoke a constructor here. |
regis
2013/10/04 00:03:09
Wouldn't target be a type to call a constructor?
O
siva
2013/10/04 18:32:57
Target is an already allocated instance.
On 2013/
|
+ if (!instance.IsNull()) { |
+ // Constuct name of the constructor to invoke. |
regis
2013/10/04 00:03:09
construct
siva
2013/10/04 18:32:57
Done.
|
+ const Type& type_obj = Type::Handle(isolate, instance.GetType()); |
+ const Class& cls = Class::Handle(isolate, type_obj.type_class()); |
+ const String& class_name = String::Handle(isolate, cls.Name()); |
+ const Array& strings = Array::Handle(Array::New(3)); |
+ strings.SetAt(0, class_name); |
+ strings.SetAt(1, Symbols::Dot()); |
+ strings.SetAt(2, function_name); |
+ const String& dot_name = String::Handle(isolate, |
+ String::ConcatAll(strings)); |
+ const AbstractTypeArguments& type_arguments = |
+ AbstractTypeArguments::Handle(isolate, type_obj.arguments()); |
+ const Function& constructor = |
+ Function::Handle(isolate, cls.LookupFunctionAllowPrivate(dot_name)); |
+ const int extra_args = 2; |
+ if (!constructor.IsNull() && |
+ constructor.IsConstructor() && |
+ constructor.AreValidArgumentCounts(number_of_arguments + extra_args, |
+ 0, |
+ NULL)) { |
+ // Create the argument list. |
+ // Constructors get the uninitialized object and a constructor phase. |
+ if (!type_arguments.IsNull()) { |
+ // The type arguments will be null if the class has no type |
+ // parameters, in which case the following call would fail |
+ // because there is no slot reserved in the object for the |
+ // type vector. |
+ instance.SetTypeArguments(type_arguments); |
+ } |
+ result = SetupArguments(isolate, |
+ number_of_arguments, |
+ arguments, |
+ extra_args, |
+ &args); |
+ if (!::Dart_IsError(result)) { |
+ args.SetAt(0, instance); |
+ args.SetAt(1, Smi::Handle(isolate, |
+ Smi::New(Function::kCtorPhaseAll))); |
+ result = Api::NewHandle( |
+ isolate, DartEntry::InvokeFunction(constructor, args)); |
+ } |
+ return result; |
+ } |
+ } |
+ result = SetupArguments(isolate, |
+ number_of_arguments, |
+ arguments, |
+ 1, |
+ &args); |
+ if (!::Dart_IsError(result)) { |
+ args.SetAt(0, instance); |
+ const Array& args_descriptor = |
+ Array::Handle(ArgumentsDescriptor::New(args.Length())); |
+ result = Api::NewHandle(isolate, |
+ DartEntry::InvokeNoSuchMethod(instance, |
+ function_name, |
+ args, |
+ args_descriptor)); |
+ } |
+ return result; |
} |
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args)); |
- |
+ result = SetupArguments(isolate, number_of_arguments, arguments, 1, &args); |
+ if (!::Dart_IsError(result)) { |
+ args.SetAt(0, instance); |
+ result = Api::NewHandle(isolate, |
+ DartEntry::InvokeFunction(function, args)); |
+ } |
+ return result; |
} else if (obj.IsLibrary()) { |
// Check whether class finalization is needed. |
const Library& lib = Library::Cast(obj); |
@@ -3089,8 +3164,12 @@ |
function_name.ToCString(), |
error_message.ToCString()); |
} |
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args)); |
- |
+ result = SetupArguments(isolate, number_of_arguments, arguments, 0, &args); |
+ if (!::Dart_IsError(result)) { |
+ result = Api::NewHandle(isolate, |
+ DartEntry::InvokeFunction(function, args)); |
+ } |
+ return result; |
} else { |
return Api::NewError( |
"%s expects argument 'target' to be an object, type, or library.", |