diff --git a/lib/core/parser/eval_access.dart b/lib/core/parser/eval_access.dart index 0cdcd663b..54c7cf64c 100644 --- a/lib/core/parser/eval_access.dart +++ b/lib/core/parser/eval_access.dart @@ -117,7 +117,7 @@ abstract class AccessReflective { _assignToNonExisting(scope, value) => null; static Function createInvokeClosure(InstanceMirror mirror, Symbol symbol) { - if (!hasMember(mirror, symbol)) return null; + if (!hasMethod(mirror, symbol)) return null; return relaxFnArgs(([a0, a1, a2, a3, a4, a5]) { var arguments = stripTrailingNulls([a0, a1, a2, a3, a4, a5]); return mirror.invoke(symbol, arguments).reflectee; @@ -131,17 +131,22 @@ abstract class AccessReflective { return list; } - static bool hasMember(InstanceMirror mirror, Symbol symbol) { + static bool hasMethod(InstanceMirror mirror, Symbol symbol) { return hasMethodHelper(mirror.type, symbol); } + static final objectClassMirror = reflectClass(Object); + static final Set objectClassInstanceMethods = + new Set.from([#toString, #noSuchMethod]); + static final Function hasMethodHelper = (() { - var objectType = reflect(Object).type; try { // Use ClassMirror.instanceMembers if available. It contains local // as well as inherited members. - objectType.instanceMembers; - return (type, symbol) => type.instanceMembers[symbol] is MethodMirror; + objectClassMirror.instanceMembers; + // For SDK 1.2 we have to use a somewhat complicated helper for this + // to work around bugs in the dart2js implementation. + return hasInstanceMethod; } on NoSuchMethodError catch (e) { // For SDK 1.0 we fall back to just using the local members. return (type, symbol) => type.members[symbol] is MethodMirror; @@ -151,6 +156,27 @@ abstract class AccessReflective { } return null; })(); + + static bool hasInstanceMethod(type, symbol) { + // Always allow instance methods found in the Object class. This makes + // it easier to work around a few bugs in the dart2js implementation. + if (objectClassInstanceMethods.contains(symbol)) return true; + // Work around http://dartbug.com/16309 which causes access to the + // instance members of certain builtin types to throw exceptions + // while traversing the superclass chain. + var mirror; + try { + mirror = type.instanceMembers[symbol]; + } on UnsupportedError catch (e) { + mirror = type.declarations[symbol]; + } + // Work around http://dartbug.com/15760 which causes noSuchMethod + // forwarding stubs to be treated as members of all classes. We have + // already checked for the real instance methods in Object, so if the + // owner of this method is Object we simply filter it out. + if (mirror is !MethodMirror) return false; + return mirror.owner != objectClassMirror; + } } /**