| Index: runtime/lib/mirrors.cc
|
| diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
|
| index 1e66b8259c57c4847c5f4ce53eba89c8068718fd..146e02a22a247564dc06e0ad2fc03f06786e22d3 100644
|
| --- a/runtime/lib/mirrors.cc
|
| +++ b/runtime/lib/mirrors.cc
|
| @@ -65,6 +65,7 @@ static void ThrowInvokeError(const Error& error) {
|
| static void ThrowNoSuchMethod(const Instance& receiver,
|
| const String& function_name,
|
| const Function& function,
|
| + const Array& arguments,
|
| const InvocationMirror::Call call,
|
| const InvocationMirror::Type type) {
|
| const Smi& invocation_type = Smi::Handle(Smi::New(
|
| @@ -74,10 +75,8 @@ static void ThrowNoSuchMethod(const Instance& receiver,
|
| args.SetAt(0, receiver);
|
| args.SetAt(1, function_name);
|
| args.SetAt(2, invocation_type);
|
| - // Parameter 3 (actual arguments): We omit this parameter to get the same
|
| - // error message as one would get by invoking the function non-reflectively.
|
| - // Parameter 4 (named arguments): We omit this parameters since we cannot
|
| - // invoke functions with named parameters reflectively (using mirrors).
|
| + args.SetAt(3, arguments);
|
| + // TODO(rmacnak): Argument 4 (attempted argument names).
|
| if (!function.IsNull()) {
|
| const intptr_t total_num_parameters = function.NumParameters();
|
| const Array& array = Array::Handle(Array::New(total_num_parameters));
|
| @@ -677,6 +676,7 @@ static RawInstance* InvokeLibraryGetter(const Library& library,
|
| ThrowNoSuchMethod(Instance::null_instance(),
|
| getter_name,
|
| getter,
|
| + Object::null_array(),
|
| InvocationMirror::kTopLevel,
|
| InvocationMirror::kGetter);
|
| UNREACHABLE();
|
| @@ -714,6 +714,7 @@ static RawInstance* InvokeClassGetter(const Class& klass,
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| getter_name,
|
| getter,
|
| + Object::null_array(),
|
| InvocationMirror::kStatic,
|
| InvocationMirror::kGetter);
|
| UNREACHABLE();
|
| @@ -1443,6 +1444,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) {
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| function_name,
|
| function,
|
| + Object::null_array(),
|
| InvocationMirror::kStatic,
|
| InvocationMirror::kMethod);
|
| UNREACHABLE();
|
| @@ -1481,26 +1483,27 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) {
|
| // Check for real fields and user-defined setters.
|
| const Field& field = Field::Handle(klass.LookupStaticField(setter_name));
|
| Function& setter = Function::Handle();
|
| - if (field.IsNull()) {
|
| - const String& internal_setter_name = String::Handle(
|
| + const String& internal_setter_name = String::Handle(
|
| Field::SetterName(setter_name));
|
|
|
| + if (field.IsNull()) {
|
| setter = klass.LookupStaticFunction(internal_setter_name);
|
|
|
| + const int kNumArgs = 1;
|
| + const Array& args = Array::Handle(Array::New(kNumArgs));
|
| + args.SetAt(0, value);
|
| +
|
| if (setter.IsNull() || !setter.is_visible()) {
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| - setter_name,
|
| + internal_setter_name,
|
| setter,
|
| + args,
|
| InvocationMirror::kStatic,
|
| InvocationMirror::kSetter);
|
| UNREACHABLE();
|
| }
|
|
|
| // Invoke the setter and return the result.
|
| - const int kNumArgs = 1;
|
| - const Array& args = Array::Handle(Array::New(kNumArgs));
|
| - args.SetAt(0, value);
|
| -
|
| Object& result = Object::Handle(
|
| DartEntry::InvokeFunction(setter, args));
|
| if (result.IsError()) {
|
| @@ -1512,8 +1515,9 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) {
|
|
|
| if (field.is_final()) {
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| - setter_name,
|
| + internal_setter_name,
|
| setter,
|
| + Object::null_array(),
|
| InvocationMirror::kStatic,
|
| InvocationMirror::kSetter);
|
| UNREACHABLE();
|
| @@ -1557,6 +1561,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) {
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| internal_constructor_name,
|
| lookup_constructor,
|
| + Object::null_array(),
|
| InvocationMirror::kConstructor,
|
| InvocationMirror::kMethod);
|
| UNREACHABLE();
|
| @@ -1634,6 +1639,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) {
|
| ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
|
| internal_constructor_name,
|
| redirected_constructor,
|
| + Object::null_array(),
|
| InvocationMirror::kConstructor,
|
| InvocationMirror::kMethod);
|
| UNREACHABLE();
|
| @@ -1696,26 +1702,28 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
| if (function.IsNull()) {
|
| // Didn't find a method: try to find a getter and invoke call on its result.
|
| const Instance& getter_result =
|
| - Instance::Handle(InvokeLibraryGetter(library, function_name, true));
|
| - // Make room for the closure (receiver) in arguments.
|
| - intptr_t numArgs = args.Length();
|
| - const Array& call_args = Array::Handle(Array::New(numArgs + 1));
|
| - Object& temp = Object::Handle();
|
| - for (int i = 0; i < numArgs; i++) {
|
| - temp = args.At(i);
|
| - call_args.SetAt(i + 1, temp);
|
| - }
|
| - call_args.SetAt(0, getter_result);
|
| - const Array& call_args_descriptor_array =
|
| - Array::Handle(ArgumentsDescriptor::New(call_args.Length(), arg_names));
|
| - // Call closure.
|
| - const Object& call_result = Object::Handle(
|
| - DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
|
| - if (call_result.IsError()) {
|
| - ThrowInvokeError(Error::Cast(call_result));
|
| - UNREACHABLE();
|
| + Instance::Handle(InvokeLibraryGetter(library, function_name, false));
|
| + if (getter_result.raw() != Object::sentinel().raw()) {
|
| + // Make room for the closure (receiver) in arguments.
|
| + intptr_t numArgs = args.Length();
|
| + const Array& call_args = Array::Handle(Array::New(numArgs + 1));
|
| + Object& temp = Object::Handle();
|
| + for (int i = 0; i < numArgs; i++) {
|
| + temp = args.At(i);
|
| + call_args.SetAt(i + 1, temp);
|
| + }
|
| + call_args.SetAt(0, getter_result);
|
| + const Array& call_args_descriptor_array = Array::Handle(
|
| + ArgumentsDescriptor::New(call_args.Length(), arg_names));
|
| + // Call closure.
|
| + const Object& call_result = Object::Handle(
|
| + DartEntry::InvokeClosure(call_args, call_args_descriptor_array));
|
| + if (call_result.IsError()) {
|
| + ThrowInvokeError(Error::Cast(call_result));
|
| + UNREACHABLE();
|
| + }
|
| + return call_result.raw();
|
| }
|
| - return call_result.raw();
|
| }
|
|
|
| const Array& args_descriptor_array =
|
| @@ -1728,6 +1736,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) {
|
| ThrowNoSuchMethod(Instance::null_instance(),
|
| function_name,
|
| function,
|
| + Object::null_array(),
|
| InvocationMirror::kTopLevel,
|
| InvocationMirror::kMethod);
|
| UNREACHABLE();
|
| @@ -1769,25 +1778,27 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) {
|
| const Field& field = Field::Handle(
|
| library.LookupLocalField(setter_name));
|
| Function& setter = Function::Handle();
|
| + const String& internal_setter_name =
|
| + String::Handle(Field::SetterName(setter_name));
|
|
|
| if (field.IsNull()) {
|
| - const String& internal_setter_name =
|
| - String::Handle(Field::SetterName(setter_name));
|
| -
|
| setter = library.LookupLocalFunction(internal_setter_name);
|
| +
|
| + const int kNumArgs = 1;
|
| + const Array& args = Array::Handle(Array::New(kNumArgs));
|
| + args.SetAt(0, value);
|
| +
|
| if (setter.IsNull() || !setter.is_visible()) {
|
| ThrowNoSuchMethod(Instance::null_instance(),
|
| - setter_name,
|
| + internal_setter_name,
|
| setter,
|
| + args,
|
| InvocationMirror::kTopLevel,
|
| InvocationMirror::kSetter);
|
| UNREACHABLE();
|
| }
|
|
|
| // Invoke the setter and return the result.
|
| - const int kNumArgs = 1;
|
| - const Array& args = Array::Handle(Array::New(kNumArgs));
|
| - args.SetAt(0, value);
|
| const Object& result = Object::Handle(
|
| DartEntry::InvokeFunction(setter, args));
|
| if (result.IsError()) {
|
| @@ -1799,8 +1810,9 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) {
|
|
|
| if (field.is_final()) {
|
| ThrowNoSuchMethod(Instance::null_instance(),
|
| - setter_name,
|
| + internal_setter_name,
|
| setter,
|
| + Object::null_array(),
|
| InvocationMirror::kTopLevel,
|
| InvocationMirror::kSetter);
|
| UNREACHABLE();
|
|
|