Revision: 3954 http://trac.macosforge.org/projects/ruby/changeset/3954 Author: lsansonetti@apple.com Date: 2010-04-21 18:54:06 -0700 (Wed, 21 Apr 2010) Log Message: ----------- remove the ugly & evil code that was automatically inserting special objective-c primitive methods when subclassing NSArray/String/Dictionary from ruby, with the new architecture it's unlikely to happen anymore Modified Paths: -------------- MacRuby/trunk/NSArray.m MacRuby/trunk/NSDictionary.m MacRuby/trunk/array.c MacRuby/trunk/class.c MacRuby/trunk/hash.c MacRuby/trunk/include/ruby/intern.h MacRuby/trunk/object.c MacRuby/trunk/spec/macruby/core/array_spec.rb MacRuby/trunk/spec/macruby/core/hash_spec.rb MacRuby/trunk/spec/macruby/core/string_spec.rb MacRuby/trunk/spec/macruby/tags/macruby/core/hash_tags.txt MacRuby/trunk/spec/macruby/tags/macruby/core/string_tags.txt MacRuby/trunk/string.c Modified: MacRuby/trunk/NSArray.m =================================================================== --- MacRuby/trunk/NSArray.m 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/NSArray.m 2010-04-22 01:54:06 UTC (rev 3954) @@ -17,7 +17,6 @@ VALUE rb_cArray; VALUE rb_cNSArray; VALUE rb_cNSMutableArray; -static VALUE rb_cCFArray; static id nsary_dup(id rcv, SEL sel) @@ -939,12 +938,6 @@ void Init_NSArray(void) { -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 - rb_cCFArray = (VALUE)objc_getClass("NSCFArray"); -#else - rb_cCFArray = (VALUE)objc_getClass("__NSCFArray"); -#endif - assert(rb_cCFArray != 0); rb_cNSArray = (VALUE)objc_getClass("NSArray"); assert(rb_cNSArray != 0); rb_cArray = rb_cNSArray; @@ -1036,113 +1029,6 @@ rb_objc_define_method(rb_cArray, "sample", rary_sample, -1); } -#define PREPARE_RCV(x) \ - Class old = *(Class *)x; \ - *(Class *)x = (Class)rb_cCFArray; - -#define RESTORE_RCV(x) \ - *(Class *)x = old; - -static long -imp_rb_array_count(id rcv, SEL sel) -{ - PREPARE_RCV(rcv); - const long count = [rcv count]; - RESTORE_RCV(rcv); - return count; -} - -static id -imp_rb_array_objectAtIndex(id rcv, SEL sel, long idx) -{ - PREPARE_RCV(rcv); - id obj = [rcv objectAtIndex:idx]; - RESTORE_RCV(rcv); - return obj; -} - -static void -imp_rb_array_insertObjectAtIndex(id rcv, SEL sel, id obj, long idx) -{ - PREPARE_RCV(rcv); - [rcv insertObject:obj atIndex:idx]; - RESTORE_RCV(rcv); -} - -static void -imp_rb_array_removeObjectAtIndex(id rcv, SEL sel, long idx) -{ - PREPARE_RCV(rcv); - [rcv removeObjectAtIndex:idx]; - RESTORE_RCV(rcv); -} - -static void -imp_rb_array_replaceObjectAtIndexWithObject(id rcv, SEL sel, long idx, id obj) -{ - PREPARE_RCV(rcv); - [rcv replaceObjectAtIndex:idx withObject:obj]; - RESTORE_RCV(rcv); -} - -static void -imp_rb_array_addObject(id rcv, SEL sel, id obj) -{ - PREPARE_RCV(rcv); - [rcv addObject:obj]; - RESTORE_RCV(rcv); -} - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 -// This is to work around a bug where CF will try to call an non-existing -// method. -static CFIndex -imp_rb_array_cfindexOfObjectInRange(void *rcv, SEL sel, void *obj, - CFRange range) -{ - CFIndex i; - PREPARE_RCV(rcv); - i = CFArrayGetFirstIndexOfValue((CFArrayRef)rcv, range, obj); - RESTORE_RCV(rcv); - return i; -} -#endif - -void -rb_objc_install_array_primitives(Class klass) -{ - rb_objc_install_method2(klass, "count", (IMP)imp_rb_array_count); - rb_objc_install_method2(klass, "objectAtIndex:", - (IMP)imp_rb_array_objectAtIndex); - - const bool is_mutable = class_getSuperclass(klass) - == (Class)rb_cNSMutableArray; - - if (is_mutable) { - rb_objc_install_method2(klass, "insertObject:atIndex:", - (IMP)imp_rb_array_insertObjectAtIndex); - rb_objc_install_method2(klass, "removeObjectAtIndex:", - (IMP)imp_rb_array_removeObjectAtIndex); - rb_objc_install_method2(klass, "replaceObjectAtIndex:withObject:", - (IMP)imp_rb_array_replaceObjectAtIndexWithObject); - rb_objc_install_method2(klass, "addObject:", - (IMP)imp_rb_array_addObject); - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 - // This is to work around a bug where CF will try to call an non-existing - // method. - rb_objc_install_method2(klass, "_cfindexOfObject:range:", - (IMP)imp_rb_array_cfindexOfObjectInRange); - Method m = class_getInstanceMethod(klass, - sel_registerName("_cfindexOfObject:range:")); - class_addMethod(klass, sel_registerName("_cfindexOfObject:inRange:"), - method_getImplementation(m), method_getTypeEncoding(m)); -#endif - - //rb_objc_define_method(*(VALUE *)klass, "alloc", ary_alloc, 0); -} - // MRI compatibility API. VALUE Modified: MacRuby/trunk/NSDictionary.m =================================================================== --- MacRuby/trunk/NSDictionary.m 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/NSDictionary.m 2010-04-22 01:54:06 UTC (rev 3954) @@ -17,7 +17,6 @@ VALUE rb_cHash; VALUE rb_cNSHash; VALUE rb_cNSMutableHash; -static VALUE rb_cCFHash; static id to_hash(id hash) @@ -436,12 +435,6 @@ void Init_NSDictionary(void) { -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 - rb_cCFHash = (VALUE)objc_getClass("NSCFDictionary"); -#else - rb_cCFHash = (VALUE)objc_getClass("__NSCFDictionary"); -#endif - assert(rb_cCFHash != 0); rb_cNSHash = (VALUE)objc_getClass("NSDictionary"); assert(rb_cNSHash != 0); rb_cHash = rb_cNSHash; @@ -506,121 +499,6 @@ nshash_compare_by_id_p, 0); } -// NSDictionary + NSMutableDictionary primitives. These are added automatically -// on singleton classes of pure NSDictionaries. Our implementation just calls -// the original methods, by tricking the receiver's class. - -#define PREPARE_RCV(x) \ - Class __old = *(Class *)x; \ - *(Class *)x = (Class)rb_cCFHash; - -#define RESTORE_RCV(x) \ - *(Class *)x = __old; - -static unsigned -nshash_count(id rcv, SEL sel) -{ - PREPARE_RCV(rcv); - const unsigned count = [rcv count]; - RESTORE_RCV(rcv); - return count; -} - -static id -nshash_keyEnumerator(id rcv, SEL sel) -{ - PREPARE_RCV(rcv); - id keys = [rcv allKeys]; - RESTORE_RCV(rcv); - return [keys objectEnumerator]; -} - -static id -nshash_objectForKey(id rcv, SEL sel, id key) -{ - PREPARE_RCV(rcv); - id value = [rcv objectForKey:key]; - RESTORE_RCV(rcv); - return value; -} - -static void -nshash_setObjectForKey(id rcv, SEL sel, id value, id key) -{ - PREPARE_RCV(rcv); - [rcv setObject:value forKey:key]; - RESTORE_RCV(rcv); -} - -static void -nshash_getObjectsAndKeys(id rcv, SEL sel, id *objs, id *keys) -{ - PREPARE_RCV(rcv); - [rcv getObjects:objs andKeys:keys]; - RESTORE_RCV(rcv); -} - -static void -nshash_removeObjectForKey(id rcv, SEL sel, id key) -{ - PREPARE_RCV(rcv); - [rcv removeObjectForKey:key]; - RESTORE_RCV(rcv); -} - -static void -nshash_removeAllObjects(id rcv, SEL sel) -{ - PREPARE_RCV(rcv); - [rcv removeAllObjects]; - RESTORE_RCV(rcv); -} - -static bool -nshash_isEqual(id rcv, SEL sel, id other) -{ - PREPARE_RCV(rcv); - const bool res = [rcv isEqualToDictionary:other]; - RESTORE_RCV(rcv); - return res; -} - -static bool -nshash_containsObject(id rcv, SEL sel, id value) -{ - PREPARE_RCV(rcv); - const bool res = [[rcv allKeysForObject:value] count] > 0; - RESTORE_RCV(rcv); - return res; -} - -void -rb_objc_install_hash_primitives(Class klass) -{ - rb_objc_install_method2(klass, "count", (IMP)nshash_count); - rb_objc_install_method2(klass, "keyEnumerator", (IMP)nshash_keyEnumerator); - rb_objc_install_method2(klass, "objectForKey:", (IMP)nshash_objectForKey); - rb_objc_install_method2(klass, "getObjects:andKeys:", - (IMP)nshash_getObjectsAndKeys); - rb_objc_install_method2(klass, "isEqual:", (IMP)nshash_isEqual); - rb_objc_install_method2(klass, "containsObject:", - (IMP)nshash_containsObject); - - const bool mutable = - class_getSuperclass(klass) == (Class)rb_cNSMutableHash; - - if (mutable) { - rb_objc_install_method2(klass, "setObject:forKey:", - (IMP)nshash_setObjectForKey); - rb_objc_install_method2(klass, "removeObjectForKey:", - (IMP)nshash_removeObjectForKey); - rb_objc_install_method2(klass, "removeAllObjects", - (IMP)nshash_removeAllObjects); - } - - //rb_objc_define_method(*(VALUE *)klass, "alloc", hash_alloc, 0); -} - // MRI compatibility API. VALUE Modified: MacRuby/trunk/array.c =================================================================== --- MacRuby/trunk/array.c 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/array.c 2010-04-22 01:54:06 UTC (rev 3954) @@ -3484,6 +3484,8 @@ Init_NSArray(); rb_cRubyArray = rb_define_class("Array", rb_cNSMutableArray); + RCLASS_SET_VERSION_FLAG(rb_cRubyArray, RCLASS_IS_ARRAY_SUBCLASS); + rb_objc_define_method(*(VALUE *)rb_cRubyArray, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)rb_cRubyArray, "alloc", rary_alloc, 0); Modified: MacRuby/trunk/class.c =================================================================== --- MacRuby/trunk/class.c 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/class.c 2010-04-22 01:54:06 UTC (rev 3954) @@ -20,44 +20,35 @@ extern st_table *rb_class_tbl; -void rb_objc_install_array_primitives(Class); -void rb_objc_install_hash_primitives(Class); -void rb_objc_install_string_primitives(Class); -void rb_objc_install_set_primitives(Class); - -bool -rb_objc_install_primitives(Class ocklass, Class ocsuper) +void +rb_objc_class_sync_version(Class ocklass, Class ocsuper) { - if (rb_cRubyArray != 0 && rb_cRubyHash != 0 && rb_cString != 0) { - do { - if (ocsuper == (Class)rb_cRubyArray) { - RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS); - return false; - } - if (ocsuper == (Class)rb_cArray) { - rb_objc_install_array_primitives(ocklass); - RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS); - return true; - } - if (ocsuper == (Class)rb_cRubyHash) { - RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS); - return false; - } - if (ocsuper == (Class)rb_cHash) { - rb_objc_install_hash_primitives(ocklass); - RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS); - return true; - } - if (ocsuper == (Class)rb_cString) { - rb_objc_install_string_primitives(ocklass); - RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_STRING_SUBCLASS); - return true; - } - ocsuper = class_getSuperclass(ocsuper); - } - while (ocsuper != NULL); + const long super_version = RCLASS_VERSION(ocsuper); + long klass_version = RCLASS_VERSION(ocklass); + + if ((super_version & RCLASS_NO_IV_SLOTS) == RCLASS_NO_IV_SLOTS) { + klass_version |= RCLASS_NO_IV_SLOTS; } - return false; + + if (ocsuper == (Class)rb_cObject + || (super_version & RCLASS_IS_OBJECT_SUBCLASS) + == RCLASS_IS_OBJECT_SUBCLASS) { + klass_version |= RCLASS_IS_OBJECT_SUBCLASS; + } + if ((super_version & RCLASS_IS_ARRAY_SUBCLASS) + == RCLASS_IS_ARRAY_SUBCLASS) { + klass_version |= RCLASS_IS_ARRAY_SUBCLASS; + } + if ((super_version & RCLASS_IS_HASH_SUBCLASS) + == RCLASS_IS_HASH_SUBCLASS) { + klass_version |= RCLASS_IS_HASH_SUBCLASS; + } + if ((super_version & RCLASS_IS_STRING_SUBCLASS) + == RCLASS_IS_STRING_SUBCLASS) { + klass_version |= RCLASS_IS_STRING_SUBCLASS; + } + + RCLASS_SET_VERSION(ocklass, klass_version); } static void * @@ -193,22 +184,12 @@ if (flags == T_MODULE) { version_flag |= RCLASS_IS_MODULE; } - const long super_version = RCLASS_VERSION(super); - if (super == rb_cObject - || (super_version & RCLASS_IS_OBJECT_SUBCLASS) - == RCLASS_IS_OBJECT_SUBCLASS) { - version_flag |= RCLASS_IS_OBJECT_SUBCLASS; - } - if ((super_version & RCLASS_NO_IV_SLOTS) == RCLASS_NO_IV_SLOTS) { - version_flag |= RCLASS_NO_IV_SLOTS; - } - RCLASS_SET_VERSION(ocklass, version_flag); objc_registerClassPair(ocklass); if (klass != 0) { - rb_objc_install_primitives(ocklass, (Class)super); + rb_objc_class_sync_version(ocklass, (Class)super); } return (VALUE)ocklass; @@ -348,7 +329,7 @@ rb_raise(rb_eTypeError, "can't copy singleton class"); } clone = rb_mod_init_copy(clone, 0, orig); - rb_objc_install_primitives((Class)clone, (Class)orig); + rb_objc_class_sync_version((Class)clone, (Class)orig); return clone; } Modified: MacRuby/trunk/hash.c =================================================================== --- MacRuby/trunk/hash.c 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/hash.c 2010-04-22 01:54:06 UTC (rev 3954) @@ -1774,6 +1774,8 @@ id_yield = rb_intern("yield"); rb_cRubyHash = rb_define_class("Hash", rb_cNSMutableHash); + RCLASS_SET_VERSION_FLAG(rb_cRubyHash, RCLASS_IS_HASH_SUBCLASS); + rb_objc_define_method(*(VALUE *)rb_cRubyHash, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)rb_cRubyHash, "alloc", rhash_alloc, 0); Modified: MacRuby/trunk/include/ruby/intern.h =================================================================== --- MacRuby/trunk/include/ruby/intern.h 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/include/ruby/intern.h 2010-04-22 01:54:06 UTC (rev 3954) @@ -150,7 +150,7 @@ /* class.c */ #if WITH_OBJC VALUE rb_objc_create_class(const char *name, VALUE super); -bool rb_objc_install_primitives(Class ocklass, Class ocsuper); +void rb_objc_class_sync_version(Class klass, Class super_class); void rb_define_object_special_methods(VALUE klass); VALUE rb_class_new_instance_imp(VALUE, SEL, int, VALUE *); VALUE rb_make_singleton_class(VALUE super); Modified: MacRuby/trunk/object.c =================================================================== --- MacRuby/trunk/object.c 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/object.c 2010-04-22 01:54:06 UTC (rev 3954) @@ -1898,12 +1898,7 @@ super = rb_cRubyObject; } RCLASS_SET_SUPER(klass, super); - if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) - != RCLASS_IS_OBJECT_SUBCLASS) { - long v = RCLASS_VERSION(klass) ^ RCLASS_IS_OBJECT_SUBCLASS; - RCLASS_SET_VERSION(klass, v); - } - rb_objc_install_primitives((Class)klass, (Class)super); + rb_objc_class_sync_version((Class)klass, (Class)super); rb_class_inherited(super, klass); rb_mod_initialize(klass, 0); Modified: MacRuby/trunk/spec/macruby/core/array_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/array_spec.rb 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/spec/macruby/core/array_spec.rb 2010-04-22 01:54:06 UTC (rev 3954) @@ -15,17 +15,6 @@ end end -describe "The NSArray class" do - it "can be subclassed and later instantiated" do - k = Class.new(NSArray) - a = k.new - a.class.should == k - a.size.should == 0 - # TODO - #lambda { a << 42 }.should raise_error(RuntimeError) - end -end - describe "An Array object" do it "is an instance of the Array/NSMutableArray class" do [].class.should == Array @@ -72,13 +61,4 @@ a.size.should == 0 lambda { a << 123 }.should raise_error(RuntimeError) end - -=begin - it "can have a singleton class" do - a = NSArray.array - def a.foo; 42; end - a.foo.should == 42 - lambda { a << 123 }.should raise_error(RuntimeError) - end -=end end Modified: MacRuby/trunk/spec/macruby/core/hash_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/hash_spec.rb 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/spec/macruby/core/hash_spec.rb 2010-04-22 01:54:06 UTC (rev 3954) @@ -15,17 +15,6 @@ end end -describe "The NSDictionary class" do - it "can be subclassed and later instantiated" do - k = Class.new(NSDictionary) - a = k.new - a.class.should == k - a.size.should == 0 - # TODO - #lambda { a[42] = 123 }.should raise_error(RuntimeError) - end -end - describe "An Hash object" do it "is an instance of the Hash class" do {}.class.should == Hash @@ -72,11 +61,4 @@ a.size.should == 0 lambda { a[42] = 123 }.should raise_error(RuntimeError) end - - it "can have a singleton class" do - a = NSDictionary.dictionary - def a.foo; 42; end - a.foo.should == 42 - lambda { a[42] = 123 }.should raise_error(RuntimeError) - end end Modified: MacRuby/trunk/spec/macruby/core/string_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/string_spec.rb 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/spec/macruby/core/string_spec.rb 2010-04-22 01:54:06 UTC (rev 3954) @@ -15,17 +15,6 @@ end end -describe "The NSString class" do - it "can be subclassed and later instantiated" do - k = Class.new(NSString) - a = k.new - a.class.should == k - a.size.should == 0 - # TODO - #lambda { a << 'foo' }.should raise_error(RuntimeError) - end -end - describe "A String object" do it "is an instance of the String/NSMutableString class" do ''.class.should == String @@ -55,17 +44,14 @@ a.foo = 42 a.foo.should == 42 end - - it "can match() a Regex" do - a = 'aaba' - a.should match(/a+b./) - end end describe "An NSString object" do - it "is an instance of the NSString class" do + it "is an instance of the String class" do a = NSString.string - a.class.should == NSString + a.class.should == String + a = NSString.stringWithString('OMG') + a.class.should == String end it "is immutable" do @@ -74,14 +60,6 @@ lambda { a << 'foo' }.should raise_error(RuntimeError) end - it "can have a singleton class" do - a = NSString.string - def a.foo; 42; end - a.foo.should == 42 - # TODO - #lambda { a << 'foo' }.should raise_error(RuntimeError) - end - it "forwards the block when calling a ruby method" do NSString.stringWithString("ybuRcaM").sub(/.+/) { |s| s.reverse }.should == "MacRuby" end Modified: MacRuby/trunk/spec/macruby/tags/macruby/core/hash_tags.txt =================================================================== --- MacRuby/trunk/spec/macruby/tags/macruby/core/hash_tags.txt 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/spec/macruby/tags/macruby/core/hash_tags.txt 2010-04-22 01:54:06 UTC (rev 3954) @@ -1,3 +1 @@ -critical:The NSDictionary class can be subclassed and later instantiated -critical:An NSDictionary object can have a singleton class critical:An NSDictionary object is immutable Modified: MacRuby/trunk/spec/macruby/tags/macruby/core/string_tags.txt =================================================================== --- MacRuby/trunk/spec/macruby/tags/macruby/core/string_tags.txt 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/spec/macruby/tags/macruby/core/string_tags.txt 2010-04-22 01:54:06 UTC (rev 3954) @@ -1,5 +1 @@ -critical:The NSString class can be subclassed and later instantiated -critical:An NSString object can have a singleton class critical:An NSString object is immutable -fails:An NSString object is an instance of the NSString class -fails:A String object can match() a Regex Modified: MacRuby/trunk/string.c =================================================================== --- MacRuby/trunk/string.c 2010-04-21 21:34:24 UTC (rev 3953) +++ MacRuby/trunk/string.c 2010-04-22 01:54:06 UTC (rev 3954) @@ -5422,6 +5422,7 @@ Init_NSString(); // rb_cRubyString is defined earlier in Init_PreVM(). + RCLASS_SET_VERSION_FLAG(rb_cRubyString, RCLASS_IS_STRING_SUBCLASS); rb_set_class_path(rb_cRubyString, rb_cObject, "String"); rb_const_set(rb_cObject, rb_intern("String"), rb_cRubyString); @@ -5583,12 +5584,6 @@ return true; } -void -rb_objc_install_string_primitives(Class klass) -{ - // TODO -} - // ByteString emulation. #define IS_BSTR(obj) (IS_RSTR(obj) && !str_is_stored_in_uchars(RSTR(obj)))
participants (1)
-
source_changes@macosforge.org