[macruby-changes] [4960] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 30 18:25:24 PST 2010


Revision: 4960
          http://trac.macosforge.org/projects/ruby/changeset/4960
Author:   lsansonetti at apple.com
Date:     2010-11-30 18:25:20 -0800 (Tue, 30 Nov 2010)
Log Message:
-----------
no longer register all objc classes as constants upon #framework (which had the side effect of waking them up, calling +initialize), instead we now always use the dynamic resolver

Modified Paths:
--------------
    MacRuby/trunk/class.c
    MacRuby/trunk/objc.m
    MacRuby/trunk/variable.c
    MacRuby/trunk/vm.cpp

Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c	2010-12-01 00:34:02 UTC (rev 4959)
+++ MacRuby/trunk/class.c	2010-12-01 02:25:20 UTC (rev 4960)
@@ -471,10 +471,14 @@
 	if (TYPE(klass) != T_CLASS) {
 	    rb_raise(rb_eTypeError, "%s is not a class", name);
 	}
-	if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
-	    rb_name_error(id, "%s is already defined", name);
+	if (RCLASS_RUBY(klass)) {
+	    // Only for pure Ruby classes, as Objective-C classes
+	    // might be returned from the dynamic resolver.
+	    if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
+		rb_name_error(id, "%s is already defined", name);
+	    }
+	    return klass;
 	}
-	return klass;
     }
     if (!super) {
 	rb_warn("no super class for `%s::%s', Object assumed",

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2010-12-01 00:34:02 UTC (rev 4959)
+++ MacRuby/trunk/objc.m	2010-12-01 02:25:20 UTC (rev 4960)
@@ -215,37 +215,6 @@
 }
 #endif
 
-static void
-reload_class_constants(void)
-{
-    static int class_count = 0;
-
-    const int count = objc_getClassList(NULL, 0);
-    if (count == class_count) {
-	return;
-    }
-
-    Class *buf = (Class *)malloc(sizeof(Class) * count);
-    objc_getClassList(buf, count);
-
-    for (int i = 0; i < count; i++) {
-	Class k = buf[i];
-	if (!RCLASS_RUBY(k)) {
-	    const char *name = class_getName(k);
-	    if (name[0] != '_') {
-		ID name_id = rb_intern(name);
-		if (!rb_const_defined(rb_cObject, name_id)) {
-		    rb_const_set(rb_cObject, name_id, (VALUE)k);
-		}
-	    }
-	}
-    }
-
-    class_count = count;
-
-    free(buf);
-}
-
 bool rb_objc_enable_ivar_set_kvo_notifications = false;
 
 VALUE
@@ -360,7 +329,6 @@
     }
 
     rb_objc_search_and_load_bridge_support(cstr);
-    reload_class_constants();
 
     rb_objc_enable_ivar_set_kvo_notifications = true;
 
@@ -782,8 +750,6 @@
     assert(m != NULL);
     old_imp_isaForAutonotifying = method_getImplementation(m);
     method_setImplementation(m, (IMP)rb_obj_imp_isaForAutonotifying);
-
-    reload_class_constants();
 }
 
 @interface Protocol

Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2010-12-01 00:34:02 UTC (rev 4959)
+++ MacRuby/trunk/variable.c	2010-12-01 02:25:20 UTC (rev 4960)
@@ -1466,19 +1466,19 @@
 static VALUE
 retrieve_dynamic_objc_class(VALUE klass, ID name)
 {
-    // Classes are typically pre-loaded by Kernel#framework but it is still
-    // useful to keep the dynamic import facility, because someone in the
-    // Objective-C world may dynamically define classes at runtime (like
-    // ScriptingBridge.framework).
-    if (klass == rb_cObject) {
-	VALUE k = (VALUE)objc_getClass(rb_id2name(name));
-	if (k != 0 && !RCLASS_RUBY(k)) {
-	     // Set the constant. Only if the returned class is a pure
-	     // Objective-C class, to avoid namespace conflicts in Ruby land.
-	    rb_objc_force_class_initialize((Class)k);
-	    rb_const_set(klass, name, k);
-	    return k;
+    // The Objective-C class dynamic resolver. By default, MacRuby doesn't
+    // know about native classes. They will be resolved and added into the
+    // NSObject dictionary on demand.
+    Class k = (Class)objc_getClass(rb_id2name(name));
+    if (k != NULL && !RCLASS_RUBY(k)) {
+	// Skip classes that aren't pure Objective-C, to avoid namespace
+	// conflicts in Ruby land.
+	CFMutableDictionaryRef dict = rb_class_ivar_dict_or_create(rb_cObject);
+	if (!CFDictionaryContainsKey(dict, (const void *)name)) {
+	    CFDictionarySetValue(dict, (const void *)name, (const void *)k);
+	    rb_objc_force_class_initialize(k);
 	}
+	return (VALUE)k;
     }
     return Qnil;
 }
@@ -1540,7 +1540,6 @@
     if (k != Qnil) {
 	return k;
     }
-
     return const_missing(klass, id);
 }
 
@@ -1773,7 +1772,7 @@
     const char *dest = isconst ? "constant" : "class variable";
 
     if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4) {
-      rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
+	rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
     }
     if (OBJ_FROZEN(klass)) {
 	if (BUILTIN_TYPE(klass) == T_MODULE) {

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-12-01 00:34:02 UTC (rev 4959)
+++ MacRuby/trunk/vm.cpp	2010-12-01 02:25:20 UTC (rev 4960)
@@ -1321,17 +1321,25 @@
 static VALUE
 get_klass_const(VALUE outer, ID path, bool lexical)
 {
+    VALUE klass = Qundef;
     if (lexical) {
 	if (rb_vm_const_lookup(outer, path, true, true) == Qtrue) {
-	    return rb_vm_const_lookup(outer, path, true, false);
+	    klass = rb_vm_const_lookup(outer, path, true, false);
 	}
     }
     else {
 	if (rb_const_defined_at(outer, path)) {
-	    return rb_const_get_at(outer, path);
+	    klass = rb_const_get_at(outer, path);
 	}
     }
-    return Qundef;
+    if (klass != Qundef) {
+	rb_vm_check_if_module(klass);
+	if (outer != rb_cObject && !RCLASS_RUBY(klass)) {
+	    // Ignore classes retrived by the dynamic resolver.
+	    klass = Qundef;
+	}
+    }
+    return klass;
 }
 
 extern "C"
@@ -1352,7 +1360,6 @@
     VALUE klass = get_klass_const(outer, path, dynamic_class);
     if (klass != Qundef) {
 	// Constant is already defined.
-	rb_vm_check_if_module(klass);
 	if (!(flags & DEFINE_MODULE) && super != 0) {
 	    if (rb_class_real(RCLASS_SUPER(klass), true) != super) {
 		rb_raise(rb_eTypeError, "superclass mismatch for class %s",
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20101130/8c872909/attachment-0001.html>


More information about the macruby-changes mailing list