Skip to content

Instantly share code, notes, and snippets.

@lrz
Created April 23, 2011 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lrz/939092 to your computer and use it in GitHub Desktop.
Save lrz/939092 to your computer and use it in GitHub Desktop.
Fix for #1238 and #1240 (work in progress)
diff --git a/class.c b/class.c
index 8b18f71..e411aeb 100644
--- a/class.c
+++ b/class.c
@@ -23,6 +23,27 @@
extern st_table *rb_class_tbl;
extern VALUE rb_cRubyObject;
+VALUE
+rb_class_super(VALUE klass)
+{
+ if (klass == 0 || RCLASS_MODULE(klass)) {
+ return 0;
+ }
+ return (VALUE)class_getSuperclass((Class)klass);
+}
+
+void
+rb_class_set_super(VALUE klass, VALUE super)
+{
+ class_setSuperclass((Class)klass, (Class)super);
+}
+
+int
+rb_class_ismeta(VALUE klass)
+{
+ return class_isMetaClass((Class)klass);
+}
+
void
rb_objc_class_sync_version(Class ocklass, Class ocsuper)
{
@@ -153,11 +174,7 @@ rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
goto no_more_classes;
}
- if (super == 0) {
- super = rb_cObject;
- }
-
- Class ocklass = objc_allocateClassPair((Class)super, ocname, sizeof(id));
+ Class ocklass = objc_allocateClassPair((Class)super, ocname, 0);
if (ocklass == NULL) {
goto no_more_classes;
}
@@ -170,7 +187,7 @@ rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
objc_registerClassPair(ocklass);
- if (klass != 0) {
+ if (klass != 0 && super != 0) {
rb_objc_class_sync_version(ocklass, (Class)super);
}
@@ -183,6 +200,9 @@ no_more_classes:
VALUE
rb_objc_create_class(const char *name, VALUE super)
{
+ if (super == 0) {
+ super = rb_cObject;
+ }
VALUE klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
if (super != rb_cNSObject && super != 0
@@ -503,12 +523,11 @@ rb_define_module_id(ID id)
{
VALUE mdl = rb_objc_alloc_class(id == 0 ? NULL : rb_id2name(id),
rb_cObject, T_MODULE, rb_cModule);
-
- if ((rb_mKernel != 0) && (id == 0)) {
- /* because Module#initialize can accept a block */
- rb_objc_define_method(*(VALUE *)mdl, "initialize", rb_mod_initialize, 0);
+ if (rb_mKernel != 0 && id == 0) {
+ // Because Module#initialize can accept a block.
+ rb_objc_define_method(*(VALUE *)mdl, "initialize",
+ rb_mod_initialize, 0);
}
-
return mdl;
}
@@ -825,7 +844,7 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (VALUE,
if (recur == Qfalse) {
break;
}
- mod = (VALUE)class_getSuperclass((Class)mod);
+ mod = RCLASS_SUPER(mod);
}
return ary;
diff --git a/eval.c b/eval.c
index 28bcd79..481589f 100644
--- a/eval.c
+++ b/eval.c
@@ -588,7 +588,7 @@ rb_mod_append_features(VALUE module, SEL sel, VALUE include)
}
m = RCLASS_SUPER(m);
}
- while (m == 0 || RCLASS_SINGLETON(m));
+ while (m != 0 && RCLASS_SINGLETON(m));
return module;
}
@@ -647,7 +647,7 @@ rb_extend_object(VALUE obj, VALUE module)
}
m = RCLASS_SUPER(m);
}
- while (m == 0 || RCLASS_SINGLETON(m));
+ while (m != 0 && RCLASS_SINGLETON(m));
}
/*
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index ad7b1cb..8ca9f4b 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -428,9 +428,12 @@ struct RBasic {
VALUE flags;
};
-#define RCLASS_SUPER(m) ((VALUE)class_getSuperclass((Class)m))
-#define RCLASS_SET_SUPER(m, s) (class_setSuperclass((Class)m, (Class)s))
-#define RCLASS_META(m) (class_isMetaClass((Class)m))
+VALUE rb_class_super(VALUE klass);
+void rb_class_set_super(VALUE klass, VALUE super);
+int rb_class_ismeta(VALUE klass);
+#define RCLASS_SUPER(m) (rb_class_super((VALUE)m))
+#define RCLASS_SET_SUPER(m, s) (rb_class_set_super((VALUE)m, (VALUE)s))
+#define RCLASS_META(m) (rb_class_ismeta((VALUE)m))
#define RFLOAT_VALUE(v) FIXFLOAT2DBL(v)
#define DOUBLE2NUM(dbl) rb_float_new(dbl)
diff --git a/variable.c b/variable.c
index 3f1dac5..62f9780 100644
--- a/variable.c
+++ b/variable.c
@@ -933,43 +933,16 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj)
}
}
-static inline bool
-rb_class_has_ivar_dict(VALUE mod)
-{
- const long v = RCLASS_VERSION(mod);
- return (v & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS
- && (v & RCLASS_KVO_CHECK_DONE) != RCLASS_KVO_CHECK_DONE;
-}
-
-#define RCLASS_RUBY_IVAR_DICT(mod) \
- (*(CFMutableDictionaryRef *) \
- ((void *)mod + class_getInstanceSize(*(Class *)RCLASS_SUPER(mod))))
-
CFMutableDictionaryRef
rb_class_ivar_dict(VALUE mod)
{
- if (rb_class_has_ivar_dict(mod)) {
- return RCLASS_RUBY_IVAR_DICT(mod);
- }
return generic_ivar_dict(mod, false);
}
void
rb_class_ivar_set_dict(VALUE mod, CFMutableDictionaryRef dict)
{
- if (rb_class_has_ivar_dict(mod)) {
- CFMutableDictionaryRef old_dict = RCLASS_RUBY_IVAR_DICT(mod);
- if (old_dict != dict) {
- if (old_dict != NULL) {
- GC_RELEASE(old_dict);
- }
- GC_RETAIN(dict);
- RCLASS_RUBY_IVAR_DICT(mod) = dict;
- }
- }
- else {
- generic_ivar_dict_set(mod, dict);
- }
+ generic_ivar_dict_set(mod, dict);
}
CFMutableDictionaryRef
@@ -1508,7 +1481,7 @@ retry:
}
tmp = RCLASS_SUPER(tmp);
}
- if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
+ if (!exclude && !mod_retry && RCLASS_MODULE(klass)) {
mod_retry = 1;
tmp = rb_cObject;
goto retry;
@@ -1713,7 +1686,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse)
}
tmp = RCLASS_SUPER(tmp);
}
- if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
+ if (!exclude && !mod_retry && RCLASS_MODULE(klass)) {
mod_retry = 1;
tmp = rb_cObject;
goto retry;
@@ -1752,7 +1725,7 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
}
if (OBJ_FROZEN(klass)) {
- if (BUILTIN_TYPE(klass) == T_MODULE) {
+ if (TYPE(klass) == T_MODULE) {
rb_error_frozen("module");
}
else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment