Index: runtime/vm/dart_entry.cc |
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc |
index 9a1ea76cde1e9b59be5b0b1699cae06e24070d08..817b7e9cc911f4db2c4d3a200d2f6cf01e3e067e 100644 |
--- a/runtime/vm/dart_entry.cc |
+++ b/runtime/vm/dart_entry.cc |
@@ -151,7 +151,50 @@ RawObject* DartEntry::InvokeClosure(const Array& arguments, |
return InvokeFunction(function, arguments, arguments_descriptor); |
} |
} |
- // There is no compatible 'call' method, so invoke noSuchMethod. |
+ |
+ // There is no compatible 'call' method, see if there's a getter. |
+ if (instance.IsClosure()) { |
+ // Special case: closures are implemented with a call getter instead of a |
+ // call method. If the arguments didn't match, go to noSuchMethod instead |
+ // of infinitely recursing on the getter. |
+ } else { |
+ const String& getter_name = String::Handle(Symbols::New("get:call")); |
+ Class& cls = Class::Handle(instance.clazz()); |
+ while (!cls.IsNull()) { |
+ function ^= cls.LookupDynamicFunction(getter_name); |
+ if (!function.IsNull()) { |
+ // Getters don't have a stack overflow check, so do one in C++. |
+ |
+ Isolate* isolate = Isolate::Current(); |
+#if defined(USING_SIMULATOR) |
+ uword stack_pos = Simulator::Current()->get_register(SPREG); |
+#else |
+ uword stack_pos = Isolate::GetCurrentStackPointer(); |
+#endif |
+ if (stack_pos < isolate->saved_stack_limit()) { |
+ const Instance& exception = |
+ Instance::Handle(isolate->object_store()->stack_overflow()); |
+ return UnhandledException::New(exception, Stacktrace::Handle()); |
+ } |
+ |
+ const Array& getter_arguments = Array::Handle(Array::New(1)); |
+ getter_arguments.SetAt(0, instance); |
+ const Object& getter_result = |
+ Object::Handle(DartEntry::InvokeFunction(function, |
+ getter_arguments)); |
+ if (getter_result.IsError()) { |
+ return getter_result.raw(); |
+ } |
+ ASSERT(getter_result.IsNull() || getter_result.IsInstance()); |
+ |
+ arguments.SetAt(0, getter_result); |
+ return InvokeClosure(arguments, arguments_descriptor); |
+ } |
+ cls = cls.SuperClass(); |
+ } |
+ } |
+ |
+ // No compatible method or getter so invoke noSuchMethod. |
return InvokeNoSuchMethod(instance, |
Symbols::Call(), |
arguments, |