Index: runtime/lib/mirrors.cc |
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc |
index a7c11d77a4271ed4296ebc6144239f181a824b5a..3ffbff8ec4ff9389f2e9d54e345ac76e7834afe6 100644 |
--- a/runtime/lib/mirrors.cc |
+++ b/runtime/lib/mirrors.cc |
@@ -47,6 +47,7 @@ static void ThrowNoSuchMethod(const Instance& receiver, |
const String& function_name, |
const Function& function, |
const Array& arguments, |
+ const Array& argument_names, |
const InvocationMirror::Call call, |
const InvocationMirror::Type type) { |
const Smi& invocation_type = Smi::Handle(Smi::New( |
@@ -57,19 +58,26 @@ static void ThrowNoSuchMethod(const Instance& receiver, |
args.SetAt(1, function_name); |
args.SetAt(2, invocation_type); |
args.SetAt(3, arguments); |
- // TODO(rmacnak): Argument 4 (attempted argument names). |
+ if (!argument_names.IsNull() && (argument_names.Length() > 0)) { |
+ // Empty and null are treated differently for some reason. Don't pass empty |
+ // to match the non-reflective error. |
+ args.SetAt(4, argument_names); |
+ } |
if (!function.IsNull()) { |
- const intptr_t total_num_parameters = function.NumParameters(); |
- const Array& array = Array::Handle(Array::New(total_num_parameters)); |
- String& param_name = String::Handle(); |
- for (int i = 0; i < total_num_parameters; i++) { |
- param_name = function.ParameterNameAt(i); |
- array.SetAt(i, param_name); |
- } |
+ const Array& array = Array::Handle(Array::New(1)); |
+ array.SetAt(0, String::Handle(function.UserVisibleFormalParameters())); |
args.SetAt(5, array); |
} |
- Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args); |
+ const Library& libcore = Library::Handle(Library::CoreLibrary()); |
+ const Class& NoSuchMethodError = Class::Handle( |
+ libcore.LookupClass(Symbols::NoSuchMethodError())); |
+ const Function& throwNew = Function::Handle( |
+ NoSuchMethodError.LookupFunctionAllowPrivate(Symbols::ThrowNew())); |
+ const Object& result = Object::Handle( |
+ DartEntry::InvokeFunction(throwNew, args)); |
+ ASSERT(result.IsError()); |
+ Exceptions::PropagateError(Error::Cast(result)); |
UNREACHABLE(); |
} |
@@ -672,6 +680,7 @@ static RawInstance* InvokeLibraryGetter(const Library& library, |
getter_name, |
getter, |
Object::null_array(), |
+ Object::null_array(), |
InvocationMirror::kTopLevel, |
InvocationMirror::kGetter); |
UNREACHABLE(); |
@@ -710,6 +719,7 @@ static RawInstance* InvokeClassGetter(const Class& klass, |
getter_name, |
getter, |
Object::null_array(), |
+ Object::null_array(), |
InvocationMirror::kStatic, |
InvocationMirror::kGetter); |
UNREACHABLE(); |
@@ -1513,7 +1523,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 5) { |
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()), |
function_name, |
function, |
- Object::null_array(), |
+ args, |
+ arg_names, |
InvocationMirror::kStatic, |
InvocationMirror::kMethod); |
UNREACHABLE(); |
@@ -1567,6 +1578,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) { |
internal_setter_name, |
setter, |
args, |
+ Object::null_array(), |
InvocationMirror::kStatic, |
InvocationMirror::kSetter); |
UNREACHABLE(); |
@@ -1587,6 +1599,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) { |
internal_setter_name, |
setter, |
Object::null_array(), |
+ Object::null_array(), |
InvocationMirror::kStatic, |
InvocationMirror::kSetter); |
UNREACHABLE(); |
@@ -1611,11 +1624,13 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) { |
// unnamed constructor for class 'A' is labeled 'A.'. |
// This convention prevents users from explicitly calling constructors. |
const String& klass_name = String::Handle(klass.Name()); |
+ String& external_constructor_name = String::Handle(klass_name.raw()); |
String& internal_constructor_name = |
String::Handle(String::Concat(klass_name, Symbols::Dot())); |
- if (!constructor_name.IsNull()) { |
+ if (!constructor_name.IsNull() && constructor_name.Length() > 0) { |
internal_constructor_name = |
String::Concat(internal_constructor_name, constructor_name); |
+ external_constructor_name = internal_constructor_name.raw(); |
} |
Function& lookup_constructor = Function::Handle( |
@@ -1624,13 +1639,11 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) { |
if (lookup_constructor.IsNull() || |
(lookup_constructor.kind() != RawFunction::kConstructor) || |
!lookup_constructor.is_reflectable()) { |
- // Pretend we didn't find the constructor at all when the arity is wrong |
- // so as to produce the same NoSuchMethodError as the non-reflective case. |
- lookup_constructor = Function::null(); |
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()), |
- internal_constructor_name, |
+ external_constructor_name, |
lookup_constructor, |
- Object::null_array(), |
+ explicit_args, |
+ arg_names, |
InvocationMirror::kConstructor, |
InvocationMirror::kMethod); |
UNREACHABLE(); |
@@ -1702,13 +1715,12 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 5) { |
ArgumentsDescriptor args_descriptor(args_descriptor_array); |
if (!redirected_constructor.AreValidArguments(args_descriptor, NULL) || |
!redirected_constructor.is_reflectable()) { |
- // Pretend we didn't find the constructor at all when the arity is wrong |
- // so as to produce the same NoSuchMethodError as the non-reflective case. |
- redirected_constructor = Function::null(); |
+ external_constructor_name = redirected_constructor.name(); |
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()), |
- internal_constructor_name, |
+ external_constructor_name, |
redirected_constructor, |
- Object::null_array(), |
+ explicit_args, |
+ arg_names, |
InvocationMirror::kConstructor, |
InvocationMirror::kMethod); |
UNREACHABLE(); |
@@ -1805,7 +1817,8 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 5) { |
ThrowNoSuchMethod(Instance::null_instance(), |
function_name, |
function, |
- Object::null_array(), |
+ args, |
+ arg_names, |
InvocationMirror::kTopLevel, |
InvocationMirror::kMethod); |
UNREACHABLE(); |
@@ -1862,6 +1875,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) { |
internal_setter_name, |
setter, |
args, |
+ Object::null_array(), |
InvocationMirror::kTopLevel, |
InvocationMirror::kSetter); |
UNREACHABLE(); |
@@ -1882,6 +1896,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) { |
internal_setter_name, |
setter, |
Object::null_array(), |
+ Object::null_array(), |
InvocationMirror::kTopLevel, |
InvocationMirror::kSetter); |
UNREACHABLE(); |