[macruby-changes] [3157] MacRuby/trunk/dispatcher.cpp
source_changes at macosforge.org
source_changes at macosforge.org
Tue Dec 22 18:09:34 PST 2009
Revision: 3157
http://trac.macosforge.org/projects/ruby/changeset/3157
Author: lsansonetti at apple.com
Date: 2009-12-22 18:09:33 -0800 (Tue, 22 Dec 2009)
Log Message:
-----------
fixed #method_missing and #respond_to? for NSProxy-based objects
Modified Paths:
--------------
MacRuby/trunk/dispatcher.cpp
Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp 2009-12-23 02:07:26 UTC (rev 3156)
+++ MacRuby/trunk/dispatcher.cpp 2009-12-23 02:09:33 UTC (rev 3157)
@@ -317,42 +317,50 @@
method_missing(VALUE obj, SEL sel, rb_vm_block_t *block, int argc,
const VALUE *argv, rb_vm_method_missing_reason_t call_status)
{
- GET_VM()->set_method_missing_reason(call_status);
-
- if (sel == selMethodMissing) {
- rb_vm_method_missing(obj, argc, argv);
- }
- else if (sel == selAlloc) {
+ if (sel == selAlloc) {
rb_raise(rb_eTypeError, "allocator undefined for %s",
rb_class2name(obj));
}
+ GET_VM()->set_method_missing_reason(call_status);
+
VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * (argc + 1));
char buf[100];
int n = snprintf(buf, sizeof buf, "%s", sel_getName(sel));
if (buf[n - 1] == ':') {
- // Let's see if there are more colons making this a real selector.
- bool multiple_colons = false;
- for (int i = 0; i < (n - 1); i++) {
- if (buf[i] == ':') {
- multiple_colons = true;
- break;
- }
- }
- if (!multiple_colons) {
- // Not a typical multiple argument selector. So as this is probably a
- // typical ruby method name, chop off the colon.
- buf[n - 1] = '\0';
- }
+ // Let's see if there are more colons making this a real selector.
+ bool multiple_colons = false;
+ for (int i = 0; i < (n - 1); i++) {
+ if (buf[i] == ':') {
+ multiple_colons = true;
+ break;
+ }
+ }
+ if (!multiple_colons) {
+ // Not a typical multiple argument selector. So as this is
+ // probably a typical ruby method name, chop off the colon.
+ buf[n - 1] = '\0';
+ }
}
new_argv[0] = ID2SYM(rb_intern(buf));
MEMCPY(&new_argv[1], argv, VALUE, argc);
- struct mcache *cache;
- cache = GET_CORE()->method_cache_get(selMethodMissing, false);
- return rb_vm_call_with_cache2(cache, block, obj, NULL, selMethodMissing,
- argc + 1, new_argv);
+ // In case the missing selector _is_ method_missing: OR the object does
+ // not respond to method_missing: (this can happen for NSProxy-based
+ // objects), directly trigger the exception.
+ Class k = (Class)CLASS_OF(obj);
+ if (sel == selMethodMissing
+ || class_getInstanceMethod(k, selMethodMissing) == NULL) {
+ rb_vm_method_missing(obj, argc + 1, new_argv);
+ return Qnil; // never reached
+ }
+ else {
+ struct mcache *cache = GET_CORE()->method_cache_get(selMethodMissing,
+ false);
+ return rb_vm_call_with_cache2(cache, block, obj, NULL, selMethodMissing,
+ argc + 1, new_argv);
+ }
}
extern "C"
@@ -1824,8 +1832,9 @@
assert(!check_override);
}
+ IMP imp = NULL;
const bool overriden = check_override
- ? (class_getMethodImplementation((Class)klass, selRespondTo)
+ ? ((imp = class_getMethodImplementation((Class)klass, selRespondTo))
!= basic_respond_to_imp)
: false;
@@ -1869,6 +1878,11 @@
|| (priv && status == RESPOND_TO_PRIVATE);
}
else {
+ if (imp == NULL || imp == _objc_msgForward) {
+ // The class does not respond to respond_to?:, it's probably
+ // NSProxy-based.
+ return false;
+ }
VALUE args[2];
int n = 0;
args[n++] = ID2SYM(rb_intern(sel_getName(sel)));
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091222/7e161047/attachment.html>
More information about the macruby-changes
mailing list