Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(649)

Unified Diff: runtime/lib/mirrors.cc

Issue 23633002: Implementation for ClosureMirror.findInContext. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed comments Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/mirrors.cc
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index cc278b2ebd795c39e106810d01c78d14e57d9182..6952df3a4d56153221ed370b6426901a1fa0e268 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -54,7 +54,7 @@ static void ThrowInvokeError(const Error& error) {
// Conventions:
// * For throwing a NSM in a class klass we use its runtime type as receiver,
-// i.e., RawTypeOfClass(klass).
+// i.e., klass.RareType().
// * For throwing a NSM in a library, we just pass the null instance as
// receiver.
static void ThrowNoSuchMethod(const Instance& receiver,
@@ -399,6 +399,336 @@ static RawInstance* CreateMirrorSystem() {
}
+static RawInstance* ReturnResult(const Object& result) {
+ if (result.IsError()) {
+ ThrowInvokeError(Error::Cast(result));
+ UNREACHABLE();
+ } else if (result.IsInstance()) {
siva 2013/09/27 00:21:01 if (result.IsInstance()) { ... ... } The else
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ return Instance::Cast(result).raw();
+ }
+ ASSERT(result.IsNull());
+ return Instance::null();
+}
+
+
+// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
+// exceptions. Wrap and propagate any compilation errors.
+static RawInstance* InvokeDynamicFunction(
+ const Instance& receiver,
+ const Function& function,
+ const String& target_name,
+ const Array& args,
+ const Array& args_descriptor_array) {
+ // Note "args" is already the internal arguments with the receiver as the
+ // first element.
+ Object& result = Object::Handle();
+
siva 2013/09/27 00:21:01 blank line not needed
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ ArgumentsDescriptor args_descriptor(args_descriptor_array);
+ if (function.IsNull() ||
+ !function.is_visible() ||
+ !function.AreValidArguments(args_descriptor, NULL)) {
+ result = DartEntry::InvokeNoSuchMethod(receiver,
+ target_name,
+ args,
+ args_descriptor_array);
+ } else {
+ result = DartEntry::InvokeFunction(function,
+ args,
+ args_descriptor_array);
+ }
+ return ReturnResult(result);
+}
+
+
+static RawInstance* InvokeLibraryGetter(const Library& library,
+ const String& getter_name,
+ const bool throw_nsm_if_absent) {
+ // 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 on whether it was an actual getter, or an uninitialized
+ // field.
+ const Field& field = Field::Handle(
+ library.LookupFieldAllowPrivate(getter_name));
+ Function& getter = Function::Handle();
+ if (field.IsNull()) {
+ // No field found. Check for a getter in the lib.
+ const String& internal_getter_name =
+ String::Handle(Field::GetterName(getter_name));
+ getter = library.LookupFunctionAllowPrivate(internal_getter_name);
+ if (getter.IsNull()) {
+ getter = library.LookupFunctionAllowPrivate(getter_name);
+ if (!getter.IsNull()) {
+ // Looking for a getter but found a regular method: closurize.
siva 2013/09/27 00:21:01 closurize it.
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ const Function& closure_function =
+ Function::Handle(getter.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ }
+ } else {
+ if (field.IsUninitialized()) {
+ // A field was found. Check for a getter in the field's owner classs.
siva 2013/09/27 00:21:01 An uninitialized field was found.
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ const Class& klass = Class::Handle(field.owner());
+ const String& internal_getter_name =
+ String::Handle(Field::GetterName(getter_name));
+ getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name);
+ } else {
+ return field.value();
+ }
siva 2013/09/27 00:21:01 will read better if you wrote it as if (!field.IsU
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ }
+
+ if (!getter.IsNull() && getter.is_visible()) {
+ // Invoke the getter and return the result.
+ const Object& result = Object::Handle(
+ DartEntry::InvokeFunction(getter, Object::empty_array()));
+ return ReturnResult(result);
+ }
+
+ if (throw_nsm_if_absent) {
+ ThrowNoSuchMethod(Instance::null_instance(),
+ getter_name,
+ getter,
+ InvocationMirror::kTopLevel,
+ InvocationMirror::kGetter);
+ UNREACHABLE();
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
siva 2013/09/27 00:21:01 How do you ensure that it does not leak into Dart
Michael Lippautz (Google) 2013/09/27 01:29:29 Adjusted the comment. As clarified offline: All t
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* InvokeClassGetter(const Class& klass,
+ const String& getter_name,
+ const bool throw_nsm_if_absent) {
+ // Note static fields do not have implicit getters.
+ const Field& field = Field::Handle(klass.LookupStaticField(getter_name));
+ if (field.IsNull() || field.IsUninitialized()) {
+ const String& internal_getter_name = String::Handle(
+ Field::GetterName(getter_name));
+ Function& getter = Function::Handle(
+ klass.LookupStaticFunctionAllowPrivate(internal_getter_name));
+
+ if (getter.IsNull() || !getter.is_visible()) {
+ if (getter.IsNull()) {
+ getter = klass.LookupStaticFunctionAllowPrivate(getter_name);
+ if (!getter.IsNull()) {
+ // Looking for a getter but found a regular method: closurize.
siva 2013/09/27 00:21:01 closurize it.
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ const Function& closure_function =
+ Function::Handle(getter.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ }
+ if (throw_nsm_if_absent) {
+ ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
+ getter_name,
+ getter,
+ InvocationMirror::kStatic,
+ InvocationMirror::kGetter);
+ UNREACHABLE();
+ }
+ // Fall through case: Indicate that we didn't find any function or field
+ // using a special null instance. This is different from a field being
+ // null and must not leak into Dartland.
+ return Object::sentinel().raw();
+ }
+
+ // Invoke the getter and return the result.
+ const Object& result = Object::Handle(
+ DartEntry::InvokeFunction(getter, Object::empty_array()));
+ return ReturnResult(result);
+ }
+ return field.value();
+}
+
+
+
+
+static RawInstance* InvokeInstanceGetter(const Class& klass,
+ const Instance& reflectee,
+ const String& getter_name,
+ const bool throw_nsm_if_absent) {
+ String& internal_getter_name = String::Handle(Field::GetterName(getter_name));
siva 2013/09/27 00:21:01 const String&
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ Function& function = Function::Handle(
+ Resolver::ResolveDynamicAnyArgsAllowPrivate(klass, internal_getter_name));
siva 2013/09/27 00:21:01 const Function& function
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+
+ if (!function.IsNull() || throw_nsm_if_absent) {
+ const int kNumArgs = 1;
+ const Array& args = Array::Handle(Array::New(kNumArgs));
+ args.SetAt(0, reflectee);
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(args.Length()));
+
siva 2013/09/27 00:21:01 Add a comment here that InvokeDynamicFunction invo
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ return InvokeDynamicFunction(reflectee,
+ function,
+ internal_getter_name,
+ args,
+ args_descriptor);
+ }
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* LookupFunctionOrFieldInLibraryPrefix(
+ const LibraryPrefix& prefix,
+ const String& lookup_name) {
+ Instance& result = Instance::Handle();
siva 2013/09/27 00:21:01 This declaration can be moved inside the if (...)
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ const Object& entry = Object::Handle(prefix.LookupObject(lookup_name));
+ if (!entry.IsNull()) {
+ if (entry.IsField()) {
+ const Field& field = Field::Cast(entry);
+ const Class& field_owner = Class::Handle(field.owner());
+ const Library& field_library = Library::Handle(field_owner.library());
+ result ^= InvokeLibraryGetter(field_library, lookup_name, false);
+ if (result.raw() != Object::sentinel().raw()) {
+ return result.raw();
+ }
+ } else if (entry.IsFunction()) {
+ const Function& func = Function::Cast(entry);
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* LookupStaticFunctionOrFieldInClass(
+ const Class& klass,
+ const String& lookup_name) {
+ Instance& result = Instance::Handle(
+ InvokeClassGetter(klass, lookup_name, false));
+ if (result.raw() != Object::sentinel().raw()) {
+ return result.raw();
+ }
+
+ Function& func = Function::Handle();
+ Class& lookup_class = Class::Handle(klass.raw());
+ while (func.IsNull() && !lookup_class.IsNull()) {
+ func ^= lookup_class.LookupStaticFunctionAllowPrivate(lookup_name);
+ lookup_class = lookup_class.SuperClass();
+ }
+ if (!func.IsNull()) {
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
+ ASSERT(!closure_function.IsNull());
+ return closure_function.ImplicitStaticClosure();
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* LookupFunctionOrFieldInFunctionContext(
+ const Function& func,
+ const Context& ctx,
+ const String& lookup_name) {
+ const ContextScope& ctx_scope = ContextScope::Handle(func.context_scope());
+ intptr_t this_index = -1;
+
+ // Search local context.
+ String& name = String::Handle();
+ for (intptr_t i = 0; i < ctx_scope.num_variables(); i++) {
+ name ^= ctx_scope.NameAt(i);
+ if (name.Equals(lookup_name)) {
+ return ctx.At(i);
+ } else if (name.Equals(Symbols::This())) {
+ // Record instance index to search for the field in the instance
+ // afterwards.
+ this_index = i;
+ }
+ }
+
+ // Search the instance this function is attached to.
+ if (this_index >= 0) {
+ // Since we want the closurized version of a function, we can access, both,
+ // functions and fields through their implicit getter name. If the implicit
+ // getter does not exist for the function, a method extractor will be
+ // created.
+ const Class& owner = Class::Handle(func.Owner());
+ const Instance& receiver = Instance::Handle(ctx.At(this_index));
+ return InvokeInstanceGetter(owner, receiver, lookup_name, false);
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* LookupFunctionOrFieldInLibraryHelper(
+ const Library& library,
+ const String& class_name,
+ const String& lookup_name) {
+ if (class_name.IsNull()) {
+ Instance& result = Instance::Handle(
+ InvokeLibraryGetter(library, lookup_name, false));
siva 2013/09/27 00:21:01 const Instance& result
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ if (result.raw() != Object::sentinel().raw()) {
+ return result.raw();
+ }
+ Function& func = Function::Handle(
siva 2013/09/27 00:21:01 const Function
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ library.LookupFunctionAllowPrivate(lookup_name));
+ if (!func.IsNull()) {
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ } else {
+ Class& cls = Class::Handle(
siva 2013/09/27 00:21:01 const Class
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ library.LookupClassAllowPrivate(class_name));
+ if (!cls.IsNull()) {
+ return LookupStaticFunctionOrFieldInClass(cls, lookup_name);
+ }
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
+static RawInstance* LookupFunctionOrFieldInLibrary(const Library& library,
+ const String& class_name,
+ const String& lookup_name) {
+ Instance& result = Instance::Handle();
+ // Check current library.
+ result ^= LookupFunctionOrFieldInLibraryHelper(
+ library, class_name, lookup_name);
+ if (result.raw() != Object::sentinel().raw()) {
+ return result.raw();
+ }
+ // Check all imports.
+ Library& lib_it = Library::Handle();
+ for (intptr_t i = 0; i < library.num_imports(); i++) {
+ lib_it ^= library.ImportLibraryAt(i);
+ result ^= LookupFunctionOrFieldInLibraryHelper(
+ lib_it, class_name, lookup_name);
+ if (result.raw() != Object::sentinel().raw()) {
+ return result.raw();
+ }
+ }
+
+ // Fall through case: Indicate that we didn't find any function or field using
+ // a special null instance. This is different from a field being null and must
+ // not leak into Dartland.
+ return Object::sentinel().raw();
+}
+
+
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
return CreateMirrorSystem();
}
@@ -506,18 +836,6 @@ DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 1) {
}
-static bool FieldIsUninitialized(const Field& field) {
- ASSERT(!field.IsNull());
-
- // Return getter method for uninitialized fields, rather than the
- // field object, since the value in the field object will not be
- // initialized until the first time the getter is invoked.
- const Instance& value = Instance::Handle(field.value());
- ASSERT(value.raw() != Object::transition_sentinel().raw());
- return value.raw() == Object::sentinel().raw();
-}
-
-
DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
const Class& klass = Class::Handle(ref.GetClassReferent());
@@ -757,40 +1075,6 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_identityHash, 1) {
}
-// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
-// exceptions. Wrap and propagate any compilation errors.
-static RawObject* ReflectivelyInvokeDynamicFunction(
- const Instance& receiver,
- const Function& function,
- const String& target_name,
- const Array& args,
- const Array& args_descriptor_array) {
- // Note "args" is already the internal arguments with the receiver as the
- // first element.
- Object& result = Object::Handle();
-
- ArgumentsDescriptor args_descriptor(args_descriptor_array);
- if (function.IsNull() ||
- !function.is_visible() ||
- !function.AreValidArguments(args_descriptor, NULL)) {
- result = DartEntry::InvokeNoSuchMethod(receiver,
- target_name,
- args,
- args_descriptor_array);
- } else {
- result = DartEntry::InvokeFunction(function,
- args,
- args_descriptor_array);
- }
-
- if (result.IsError()) {
- ThrowInvokeError(Error::Cast(result));
- UNREACHABLE();
- }
- return result.raw();
-}
-
-
DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
// Argument 0 is the mirror, which is unused by the native. It exists
// because this native is an instance method in order to be polymorphic
@@ -808,11 +1092,11 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 5) {
const Array& args_descriptor =
Array::Handle(ArgumentsDescriptor::New(args.Length(), arg_names));
- return ReflectivelyInvokeDynamicFunction(reflectee,
- function,
- function_name,
- args,
- args_descriptor);
+ return InvokeDynamicFunction(reflectee,
+ function,
+ function_name,
+ args,
+ args_descriptor);
}
@@ -822,23 +1106,8 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) {
// with its cousins.
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
-
Class& klass = Class::Handle(reflectee.clazz());
- String& internal_getter_name = String::Handle(Field::GetterName(getter_name));
- Function& function = Function::Handle(
- Resolver::ResolveDynamicAnyArgsAllowPrivate(klass, internal_getter_name));
-
- const int kNumArgs = 1;
- const Array& args = Array::Handle(Array::New(kNumArgs));
- args.SetAt(0, reflectee);
- const Array& args_descriptor =
- Array::Handle(ArgumentsDescriptor::New(args.Length()));
-
- return ReflectivelyInvokeDynamicFunction(reflectee,
- function,
- internal_getter_name,
- args,
- args_descriptor);
+ return InvokeInstanceGetter(klass, reflectee, getter_name, true);
}
@@ -882,11 +1151,11 @@ DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) {
const Array& args_descriptor =
Array::Handle(ArgumentsDescriptor::New(args.Length()));
- return ReflectivelyInvokeDynamicFunction(reflectee,
- setter,
- internal_setter_name,
- args,
- args_descriptor);
+ return InvokeDynamicFunction(reflectee,
+ setter,
+ internal_setter_name,
+ args,
+ args_descriptor);
}
@@ -909,6 +1178,81 @@ DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) {
}
+DEFINE_NATIVE_ENTRY(ClosureMirror_find_in_context, 2) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Array, lookup_parts, arguments->NativeArgAt(1));
+ ASSERT(lookup_parts.Length() >= 1 && lookup_parts.Length() <= 3);
+
+ Function& function = Function::Handle();
+ const bool callable = closure.IsCallable(&function, NULL);
+ ASSERT(callable);
+
+ const int parts_len = lookup_parts.Length();
+ // Lookup name is always the last part.
+ const String& lookup_name = String::Handle(String::RawCast(
+ lookup_parts.At(parts_len - 1)));
+
+ String& part_name = String::Handle();
+ Class& owner = Class::Handle(function.Owner());
+ LibraryPrefix& prefix = LibraryPrefix::Handle();
+ Library& this_library = Library::Handle(owner.library());
+ Instance& result = Instance::Handle(Object::sentinel().raw());
+ if (parts_len == 1) {
+ // Could be either a field in context, an instance or static field of the
+ // enclosing class, or a field in the current library or any imported
+ // library.
+ result ^= LookupFunctionOrFieldInFunctionContext(
+ function, Context::Handle(Closure::context(closure)), lookup_name);
+ if (result.raw() == Object::sentinel().raw()) {
+ result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name);
+ }
+ if (result.raw() == Object::sentinel().raw()) {
+ result ^= LookupFunctionOrFieldInLibrary(this_library,
+ part_name,
+ lookup_name);
+ }
+ } else if (parts_len == 2) {
+ // Could be either library.field or class.staticfield.
+ part_name ^= lookup_parts.At(0);
+ prefix ^= this_library.LookupLocalLibraryPrefix(part_name);
+ if (prefix.IsNull()) {
+ result ^= LookupFunctionOrFieldInLibrary(this_library,
+ part_name,
+ lookup_name);
+ } else {
+ result ^= LookupFunctionOrFieldInLibraryPrefix(prefix, lookup_name);
+ }
+ } else if (parts_len == 3) {
siva 2013/09/27 00:21:01 this can just be: else { ASSERT(parts_len == 3)
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ // Can only be library.class.staticfield.
+ part_name ^= lookup_parts.At(0);
+ prefix ^= this_library.LookupLocalLibraryPrefix(part_name);
+ if (!prefix.IsNull()) {
+ part_name ^= lookup_parts.At(1);
+ owner ^= prefix.LookupClass(part_name);
+ if (!owner.IsNull()) {
+ result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name);
+ }
+ }
+ } else {
+ UNREACHABLE();
+ }
+
+ // We return a tuple (list) where the first slot indicates whether we found a
siva 2013/09/27 00:21:01 first slot is a boolean that indicates
Michael Lippautz (Google) 2013/09/27 01:29:29 Done.
+ // field or function and the second slot contains the result. This is needed
+ // to distinguish between not finding a field and a field containing null as
+ // value.
+ const Array& result_tuple = Array::Handle(Array::New(2));
+ if (result.raw() == Object::sentinel().raw()) {
+ result_tuple.SetAt(0, Bool::False());
+ // No need to set the value.
+ } else {
+ result_tuple.SetAt(0, Bool::True());
+ result_tuple.SetAt(1, result);
+ }
+ return result_tuple.raw();
+}
+
+
DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
ASSERT(!closure.IsNull());
@@ -968,43 +1312,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Class& klass = Class::Handle(ref.GetClassReferent());
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
-
- // Note static fields do not have implicit getters.
- const Field& field = Field::Handle(klass.LookupStaticField(getter_name));
- if (field.IsNull() || FieldIsUninitialized(field)) {
- const String& internal_getter_name = String::Handle(
- Field::GetterName(getter_name));
- Function& getter = Function::Handle(
- klass.LookupStaticFunctionAllowPrivate(internal_getter_name));
-
- if (getter.IsNull() || !getter.is_visible()) {
- if (getter.IsNull()) {
- getter = klass.LookupStaticFunctionAllowPrivate(getter_name);
- if (!getter.IsNull()) {
- // Looking for a getter but found a regular method: closurize.
- const Function& closure_function =
- Function::Handle(getter.ImplicitClosureFunction());
- return closure_function.ImplicitStaticClosure();
- }
- }
- ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
- getter_name,
- getter,
- InvocationMirror::kStatic,
- InvocationMirror::kGetter);
- UNREACHABLE();
- }
-
- // Invoke the getter and return the result.
- Object& result = Object::Handle(
- DartEntry::InvokeFunction(getter, Object::empty_array()));
- if (result.IsError()) {
- ThrowInvokeError(Error::Cast(result));
- UNREACHABLE();
- }
- return result.raw();
- }
- return field.value();
+ return InvokeClassGetter(klass, getter_name, true);
}
@@ -1231,55 +1539,7 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& library = Library::Handle(ref.GetLibraryReferent());
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
-
- // 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.
- const Field& field = Field::Handle(
- library.LookupFieldAllowPrivate(getter_name));
- Function& getter = Function::Handle();
- if (field.IsNull()) {
- // No field found and no ambiguity error. Check for a getter in the lib.
- const String& internal_getter_name =
- String::Handle(Field::GetterName(getter_name));
- getter = library.LookupFunctionAllowPrivate(internal_getter_name);
- if (getter.IsNull()) {
- getter = library.LookupFunctionAllowPrivate(getter_name);
- if (!getter.IsNull()) {
- // Looking for a getter but found a regular method: closurize.
- const Function& closure_function =
- Function::Handle(getter.ImplicitClosureFunction());
- return closure_function.ImplicitStaticClosure();
- }
- }
- } else if (!field.IsNull() && FieldIsUninitialized(field)) {
- // A field was found. Check for a getter in the field's owner classs.
- const Class& klass = Class::Handle(field.owner());
- const String& internal_getter_name =
- String::Handle(Field::GetterName(getter_name));
- getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name);
- }
-
- if (!getter.IsNull() && getter.is_visible()) {
- // Invoke the getter and return the result.
- const Object& result = Object::Handle(
- DartEntry::InvokeFunction(getter, Object::empty_array()));
- if (result.IsError()) {
- ThrowInvokeError(Error::Cast(result));
- UNREACHABLE();
- }
- return result.raw();
- }
- if (!field.IsNull()) {
- return field.value();
- }
- ThrowNoSuchMethod(Instance::null_instance(),
- getter_name,
- getter,
- InvocationMirror::kTopLevel,
- InvocationMirror::kGetter);
- UNREACHABLE();
- return Instance::null();
+ return InvokeLibraryGetter(library, getter_name, true);
}
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698