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

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: 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..67c3fa9ae9a33c5d5aac1cf3dbe99beb4bb39b86 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,337 @@ static RawInstance* CreateMirrorSystem() {
}
+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();
+}
siva 2013/09/26 17:05:07 This function should probably be an instance metho
rmacnak 2013/09/26 17:49:39 Please also update the equivalent use in Dart_SetF
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.(including Dart_GetField/_SetField)
+
+
+// Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
+// exceptions. Wrap and propagate any compilation errors.
+static RawInstance* ReflectivelyInvokeDynamicFunction(
rmacnak 2013/09/26 17:49:39 Let's drop the "Reflectively" for parallelism with
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ 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();
+ } else if (result.IsInstance()) {
+ return Instance::Cast(result).raw();
+ }
+ ASSERT(result.IsNull());
+ return Instance::null();
+}
+
+
+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.
siva 2013/09/26 17:05:07 This comment seems to be incomplete....
rmacnak 2013/09/26 17:49:39 To perform a reflective getter invocation, we need
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ 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();
+ }
siva 2013/09/26 17:05:07 I saw some similar code in Ryan's CL maybe it need
rmacnak 2013/09/26 17:49:39 That code was moved here, not duplicated.
Michael Lippautz (Google) 2013/09/26 21:16:01 This is Ryan's code. It just moved here.
+ }
+ } else if (!field.IsNull() && FieldIsUninitialized(field)) {
siva 2013/09/26 17:05:07 At this point we know field.IsNull() is not true w
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ // 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();
+ } else if (result.IsInstance()) {
+ return Instance::Cast(result).raw();
+ }
+ ASSERT(result.IsNull());
+ return Instance::null();
siva 2013/09/26 17:05:07 Maybe you should have a static helper method stati
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ }
+ if (!field.IsNull()) {
+ return field.value();
+ }
siva 2013/09/26 17:05:07 I think the code needs to be restructured as if (f
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ if (throw_nsm_if_absent) {
+ ThrowNoSuchMethod(Instance::null_instance(),
+ getter_name,
+ getter,
+ InvocationMirror::kTopLevel,
+ InvocationMirror::kGetter);
+ UNREACHABLE();
+ }
+ return Instance::null();
+}
+
+
+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() || 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();
+ }
+ }
+ if (throw_nsm_if_absent) {
+ ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
+ getter_name,
+ getter,
+ InvocationMirror::kStatic,
+ InvocationMirror::kGetter);
+ UNREACHABLE();
+ }
+ return Instance::null();
+ }
+
+ // Invoke the getter and return the result.
+ Object& result = Object::Handle(
rmacnak 2013/09/26 17:49:39 const
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ DartEntry::InvokeFunction(getter, Object::empty_array()));
+ if (result.IsError()) {
+ ThrowInvokeError(Error::Cast(result));
+ UNREACHABLE();
+ } else if (result.IsInstance()) {
+ return Instance::Cast(result).raw();
+ }
+ ASSERT(result.IsNull());
+ return Instance::null();
siva 2013/09/26 17:05:07 ditto comment about returnResult
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ }
+ return field.value();
+}
+
+
+
+
+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));
+ Function& function = Function::Handle(
+ Resolver::ResolveDynamicAnyArgsAllowPrivate(klass, internal_getter_name));
+
+ if (!function.IsNull() || (function.IsNull() && throw_nsm_if_absent)) {
siva 2013/09/26 17:05:07 shouldn't this just be if (!function.IsNull() || t
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ 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 Instance::null();
+}
+
+
+RawInstance* LookupFunctionOrFieldInLibraryPrefix(
+ const LibraryPrefix& prefix,
+ const String& lookup_name) {
+ Instance& result = Instance::Handle();
+ const Object& entry = Object::Handle(prefix.LookupObject(lookup_name));
+ if (!entry.IsNull() && 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.IsNull()) {
+ return result.raw();
+ }
siva 2013/09/26 17:05:07 why not just return result.raw();
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ } else if (!entry.IsNull() && entry.IsFunction()) {
siva 2013/09/26 17:05:07 why test of !entry.IsNull() twice? Structure as if
rmacnak 2013/09/26 17:49:39 Could it be a Class?
Michael Lippautz (Google) 2013/09/26 21:16:01 Can be a class. Restructured nonetheless.
+ const Function& func = Function::Cast(entry);
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ return Instance::null();
+}
+
+
+RawInstance* LookupStaticFunctionOrFieldInClass(const Class& klass,
+ const String& lookup_name) {
+ Instance& result = Instance::Handle(
+ InvokeClassGetter(klass, lookup_name, false));
+ if (!result.IsNull()) {
+ return result.raw();
+ }
+
+ Function& func = Function::Handle();
+ Class& kls = Class::Handle(klass.raw());
rmacnak 2013/09/26 17:49:39 Consider 'lookup_class'
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ for (; func.IsNull() && !kls.IsNull(); kls = kls.SuperClass()) {
+ func ^= kls.LookupStaticFunctionAllowPrivate(lookup_name);
+ }
+ if (!func.IsNull()) {
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
siva 2013/09/26 17:05:07 ASSERT(!closure_function.IsNull());
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ return closure_function.ImplicitStaticClosure();
+ }
+
+ return Instance::null();
+}
+
+
+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 internal getter name. If the internal
rmacnak 2013/09/26 17:49:39 implicit getter, not internal
Michael Lippautz (Google) 2013/09/26 21:16:01 Done.
+ // getter does not exist for the function, a method extractor will be
+ // created.
+ const String& internal_getter_name = String::Handle(
+ Field::GetterName(lookup_name));
+ const Class& owner = Class::Handle(func.Owner());
+ const Instance& receiver = Instance::Handle(ctx.At(this_index));
+ const Function& getter = Function::Handle(
+ Resolver::ResolveDynamicAnyArgsAllowPrivate(
+ owner, internal_getter_name));
+ if (!getter.IsNull()) {
+ const int kNumArgs = 1;
+ const Array& args = Array::Handle(Array::New(kNumArgs));
+ args.SetAt(0, receiver);
+ const Array& args_descriptor = Array::Handle(
+ ArgumentsDescriptor::New(args.Length()));
+
+ return ReflectivelyInvokeDynamicFunction(receiver,
+ getter,
+ internal_getter_name,
+ args,
+ args_descriptor);
+ }
+ }
+ return Instance::null();
+}
+
+
+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));
+ if (!result.IsNull()) {
+ return result.raw();
+ }
+ Function& func = Function::Handle(
+ library.LookupFunctionAllowPrivate(lookup_name));
+ if (!func.IsNull()) {
+ const Function& closure_function = Function::Handle(
+ func.ImplicitClosureFunction());
+ return closure_function.ImplicitStaticClosure();
+ }
+ } else {
+ Class& cls = Class::Handle(
+ library.LookupClassAllowPrivate(class_name));
+ if (!cls.IsNull()) {
+ return LookupStaticFunctionOrFieldInClass(cls, lookup_name);
+ }
+ }
+ return Instance::null();
+}
+
+
+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.IsNull()) {
+ 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.IsNull()) {
+ return result.raw();
+ }
+ }
+ return Instance::null();
+}
+
+
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
return CreateMirrorSystem();
}
@@ -506,18 +837,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 +1076,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
@@ -822,23 +1107,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);
}
@@ -909,6 +1179,84 @@ DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 3) {
}
+DEFINE_NATIVE_ENTRY(ClosureMirror_find_in_context, 2) {
+ enum {
+ kNoLookups = 0,
+ kContext = 1,
+ kStatic = 2,
+ kLibraryPrefix = 4,
+ kGlobal = 8
+ };
+
+ 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)));
+
+ unsigned lookups = kNoLookups;
siva 2013/09/26 17:05:07 we don't normally used unsigned like this, why not
Michael Lippautz (Google) 2013/09/26 21:16:01 Not used anymore.
+ String& part_name = String::Handle();
+ Class& owner = Class::Handle(function.Owner());
+ LibraryPrefix& prefix = LibraryPrefix::Handle();
+ Library& this_library = Library::Handle(owner.library());
+
+ 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.
+ lookups = (kContext | kStatic | kGlobal);
+ } 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);
+ lookups = prefix.IsNull() ? kGlobal : kLibraryPrefix;
+ } else if (parts_len == 3) {
+ // Can only be library.class.staticfield.
+ part_name ^= lookup_parts.At(0);
+ prefix ^= this_library.LookupLocalLibraryPrefix(part_name);
+ if (prefix.IsNull()) {
+ return Instance::null();
+ }
+ part_name ^= lookup_parts.At(1);
+ owner ^= prefix.LookupClass(part_name);
+ if (owner.IsNull()) {
+ return Instance::null();
+ }
+ lookups = kStatic;
+ } else {
+ UNREACHABLE();
+ }
+
+ Instance& result = Instance::Handle();
+ if ((lookups & kContext) && result.IsNull()) {
rmacnak 2013/09/26 17:49:39 I'm suspicious of using null to indicate no-result
Michael Lippautz (Google) 2013/09/26 21:16:01 Done (see above).
+ result ^= LookupFunctionOrFieldInFunctionContext(
+ function, Context::Handle(Closure::context(closure)), lookup_name);
+ }
+ if ((lookups & kStatic) && result.IsNull() && !owner.IsTopLevel()) {
+ result ^= LookupStaticFunctionOrFieldInClass(owner, lookup_name);
+ }
+ if ((lookups & kLibraryPrefix) && result.IsNull()) {
+ result ^= LookupFunctionOrFieldInLibraryPrefix(prefix, lookup_name);
+ }
+ if ((lookups & kGlobal) && result.IsNull()) {
+ result ^= LookupFunctionOrFieldInLibrary(this_library,
+ part_name,
+ lookup_name);
+ }
siva 2013/09/26 17:05:07 I am not sure if this 'lookups' stuff is a good id
Michael Lippautz (Google) 2013/09/26 21:16:01 Inlined the lookup calls.
+ if (!result.IsNull()) {
+ return result.raw();
+ }
+ return Instance::null();
siva 2013/09/26 17:05:07 return result.raw(); is sufficient
Michael Lippautz (Google) 2013/09/26 21:16:01 Different now.
+}
+
+
DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
ASSERT(!closure.IsNull());
@@ -968,43 +1316,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 +1543,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