Revision: 543 http://trac.macosforge.org/projects/ruby/changeset/543 Author: lsansonetti@apple.com Date: 2008-09-01 20:30:09 -0700 (Mon, 01 Sep 2008) Log Message: ----------- fixes for #121, #117 and #52 Modified Paths: -------------- MacRuby/trunk/class.c MacRuby/trunk/objc.m MacRuby/trunk/object.c MacRuby/trunk/test/ruby/test_objc.rb MacRuby/trunk/vm_eval.c MacRuby/trunk/vm_insnhelper.c Modified: MacRuby/trunk/class.c =================================================================== --- MacRuby/trunk/class.c 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/class.c 2008-09-02 03:30:09 UTC (rev 543) @@ -61,17 +61,27 @@ return (VALUE)obj; } -static VALUE -rb_objc_init(VALUE rcv) +static BOOL +rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj) { - rb_funcall(rcv, idInitialize, 0); + return rb_funcall((VALUE)rcv, idEq, 1, OC2RB(obj)) == Qtrue; +} + +static void * +rb_obj_imp_init(void *rcv, SEL sel) +{ + rb_funcall((VALUE)rcv, idInitialize, 0); return rcv; } -static BOOL -rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj) +static VALUE +rb_objc_init(VALUE rcv) { - return rb_funcall((VALUE)rcv, idEq, 1, OC2RB(obj)) == Qtrue; + IMP imp = class_getMethodImplementation((Class)CLASS_OF(rcv), selInit); + if (imp != NULL && imp != (IMP)rb_obj_imp_init) { + return (VALUE)((void *(*)(void *, SEL))*imp)((void *)rcv, selInit); + } + return rcv; } void @@ -79,14 +89,17 @@ { rb_define_alloc_func(klass, rb_class_allocate_instance); rb_define_singleton_method(klass, "new", rb_class_new_instance, -1); + rb_define_singleton_method(klass, "__new__", rb_class_new_instance, -1); rb_define_method(klass, "dup", rb_obj_dup, 0); - rb_define_method(klass, "init", rb_objc_init, 0); + rb_define_method(klass, "initialize", rb_objc_init, 0); rb_define_method(klass, "initialize_copy", rb_obj_init_copy, 1); static SEL sel_isEqual = 0; if (sel_isEqual == 0) sel_isEqual = sel_registerName("isEqual:"); class_addMethod((Class)klass, sel_isEqual, (IMP)rb_obj_imp_isEqual, "c@:@"); + + class_addMethod((Class)klass, selInit, (IMP)rb_obj_imp_init, "@@:"); } static VALUE @@ -548,7 +561,7 @@ static void rb_mod_included_modules_nosuper(VALUE mod, VALUE ary) { - VALUE inc_mods = rb_ivar_get(mod, idIncludedModules); + VALUE inc_mods = rb_attr_get(mod, idIncludedModules); if (inc_mods != Qnil) { int i, count = RARRAY_LEN(inc_mods); for (i = 0; i < count; i++) { @@ -680,6 +693,11 @@ Method *methods; unsigned int i, count; + /* XXX: + * - fails to ignore undefined methods (#undef_method) + * - does not filter public/private/protected methods + */ + methods = class_copyMethodList((Class)mod, &count); if (methods != NULL) { for (i = 0; i < count; i++) { @@ -691,6 +709,7 @@ char buf[100]; BOOL is_ruby_method; size_t len; + IMP imp; method = methods[i]; @@ -698,12 +717,15 @@ if (sel == sel_ignored) continue; - sel_name = (char *)sel; - is_ruby_method = rb_objc_method_node3(method_getImplementation(method)) != NULL; + imp = method_getImplementation(method); + if (imp == NULL) + continue; + is_ruby_method = rb_objc_method_node3(imp) != NULL; if (!is_ruby_method && objc_methods == Qfalse) continue; + sel_name = (char *)sel; len = strlen(sel_name); if (is_ruby_method && len > 8 && sel_name[0] == '_' && sel_name[1] == '_' && sel_name[2] == 'r' && sel_name[3] == 'b' && sel_name[4] == '_' && sel_name[len - 1] == '_' && sel_name[len - 2] == '_') { Modified: MacRuby/trunk/objc.m =================================================================== --- MacRuby/trunk/objc.m 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/objc.m 2008-09-02 03:30:09 UTC (rev 543) @@ -3163,7 +3163,7 @@ CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopDefaultMode); } - rb_define_method(rb_cBasicObject, "__super_objc_send__", rb_super_objc_send, -1); + rb_define_method(rb_cNSObject, "__super_objc_send__", rb_super_objc_send, -1); Method m = class_getInstanceMethod(objc_getClass("NSKeyValueUnnestedProperty"), sel_registerName("isaForAutonotifying")); assert(m != NULL); Modified: MacRuby/trunk/object.c =================================================================== --- MacRuby/trunk/object.c 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/object.c 2008-09-02 03:30:09 UTC (rev 543) @@ -1480,7 +1480,7 @@ { VALUE obj; - if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) { + if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject && klass != rb_cObject) { rb_raise(rb_eTypeError, "can't instantiate uninitialized class"); } if (RCLASS_SINGLETON(klass)) { @@ -2441,26 +2441,32 @@ void Init_Object(void) { - rb_cNSObject = rb_cObject = (VALUE)objc_getClass("NSObject"); + rb_cObject = rb_cNSObject = (VALUE)objc_getClass("NSObject"); rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject); rb_set_class_path(rb_cObject, rb_cObject, "NSObject"); - rb_cBasicObject = rb_cObject; // TODO + rb_cBasicObject = (VALUE)objc_duplicateClass((Class)rb_cObject, "BasicObject", 0); rb_cModule = boot_defclass("Module", rb_cObject); rb_cClass = boot_defclass("Class", rb_cModule); RCLASS_SUPER(*(Class *)rb_cNSObject) = rb_cClass; - rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0); + rb_define_private_method(rb_cNSObject, "initialize", rb_obj_dummy, 0); rb_define_method(rb_cNSObject, "==", rb_obj_equal, 1); rb_define_method(rb_cNSObject, "equal?", rb_obj_equal, 1); rb_define_method(rb_cNSObject, "!", rb_obj_not, 0); rb_define_method(rb_cNSObject, "!=", rb_obj_not_equal, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy, 1); - rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy, 1); + rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0); + rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1); + rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1); + rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0); + rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1); + rb_define_private_method(rb_cNSObject, "singleton_method_added", rb_obj_dummy, 1); + rb_define_private_method(rb_cNSObject, "singleton_method_removed", rb_obj_dummy, 1); + rb_define_private_method(rb_cNSObject, "singleton_method_undefined", rb_obj_dummy, 1); + rb_mKernel = rb_define_module("Kernel"); - rb_include_module(rb_cObject, rb_mKernel); + rb_include_module(rb_cNSObject, rb_mKernel); rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1); rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1); rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1); Modified: MacRuby/trunk/test/ruby/test_objc.rb =================================================================== --- MacRuby/trunk/test/ruby/test_objc.rb 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/test/ruby/test_objc.rb 2008-09-02 03:30:09 UTC (rev 543) @@ -388,4 +388,18 @@ assert(s.respond_to?('setString:')) assert(s.respond_to?('performSelector:withObject:')) end + + class TestCallSuperOverridenNew + def self.new(x) + super + end + def initialize(x) + @x = x + end + attr_reader :x + end + def test_call_super_overriden_new + o = TestCallSuperOverridenNew.new(42) + assert_equal(42, o.x) + end end Modified: MacRuby/trunk/vm_eval.c =================================================================== --- MacRuby/trunk/vm_eval.c 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/vm_eval.c 2008-09-02 03:30:09 UTC (rev 543) @@ -1341,17 +1341,15 @@ rb_define_global_function("loop", rb_f_loop, 0); -#if WITH_OBJC rb_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1); rb_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1); rb_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1); rb_define_method(rb_cNSObject, "__send__", rb_f_send, -1); -#else + rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1); rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1); rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1); rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1); -#endif rb_define_method(rb_mKernel, "send", rb_f_send, -1); rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1); Modified: MacRuby/trunk/vm_insnhelper.c =================================================================== --- MacRuby/trunk/vm_insnhelper.c 2008-09-01 21:08:39 UTC (rev 542) +++ MacRuby/trunk/vm_insnhelper.c 2008-09-02 03:30:09 UTC (rev 543) @@ -1418,12 +1418,20 @@ #if WITH_OBJC static inline VALUE -vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, IMP *impp, SEL *selp) +vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, + IMP *impp, SEL *selp) { static ID idPreviousKlass = 0; + static ID idNew = 0, idNew2 = 0, idNew3 = 0; CFMutableDictionaryRef iv_dict; VALUE ary, k; + if (idNew == 0) { + idNew = rb_intern("new"); + idNew2 = rb_intern("new:"); + idNew3 = rb_intern("__new__"); + } + if (idPreviousKlass == 0) { idPreviousKlass = rb_intern("__previous_sklass__"); } @@ -1453,11 +1461,27 @@ } iv_dict = rb_class_ivar_dict(klass); - if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)idPreviousKlass, (const void **)&k)) { + if (iv_dict != NULL + && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, + (const void *)idPreviousKlass, + (const void **)&k)) { CFDictionaryRemoveValue(iv_dict, (const void *)idPreviousKlass); klass = k; } - return vm_search_normal_superclass(klass, recv); + + k = vm_search_normal_superclass(klass, recv); + + /* because #new is added on every new NSObject subclasses, and if overriden + we should still call our implementation with super */ + if ((mid == idNew || mid == idNew2) && k == *(VALUE *)rb_cNSObject) { + *mnp = rb_objc_method_node(klass, idNew3, impp, selp); + if (*mnp == NULL) + rb_bug("can't look up __new__ in klass `%s'\n", + class_getName((Class)klass)); + k = klass; + } + + return k; } #endif
participants (1)
-
source_changes@macosforge.org