Revision: 125 http://trac.macosforge.org/projects/ruby/changeset/125 Author: lsansonetti@apple.com Date: 2008-03-31 17:29:16 -0700 (Mon, 31 Mar 2008) Log Message: ----------- fixing more Array regressions Modified Paths: -------------- MacRuby/trunk/array.c MacRuby/trunk/enumerator.c MacRuby/trunk/hash.c MacRuby/trunk/include/ruby/intern.h MacRuby/trunk/object.c MacRuby/trunk/test/ruby/test_array.rb Modified: MacRuby/trunk/array.c =================================================================== --- MacRuby/trunk/array.c 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/array.c 2008-04-01 00:29:16 UTC (rev 125) @@ -41,8 +41,10 @@ } #if WITH_OBJC +/* TODO optimize this */ struct rb_objc_ary_struct { bool frozen; + bool tainted; bool named_args; void *cptr; }; @@ -63,13 +65,29 @@ s = rb_objc_ary_get_struct(ary); if (s == NULL) { - s = xmalloc(sizeof(struct rb_objc_ary_struct)); - rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_assoc_key, s); - s->frozen = false; - s->named_args = false; + s = xmalloc(sizeof(struct rb_objc_ary_struct)); + rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_assoc_key, s); + s->frozen = false; + s->tainted = false; + s->named_args = false; + s->cptr = NULL; } return s; } + +static void +rb_objc_ary_copy_struct(VALUE old, VALUE new) +{ + struct rb_objc_ary_struct *s; + + s = rb_objc_ary_get_struct(old); + if (s != NULL) { + struct rb_objc_ary_struct *n; + + n = rb_objc_ary_get_struct2(new); + memcpy(n, s, sizeof(struct rb_objc_ary_struct)); + } +} #else #define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED) @@ -129,6 +147,22 @@ #endif } +#if WITH_OBJC +VALUE +rb_ary_taint(VALUE ary) +{ + rb_objc_ary_get_struct2(ary)->tainted = true; + return ary; +} + +VALUE +rb_ary_tainted(VALUE ary) +{ + struct rb_objc_ary_struct *s = rb_objc_ary_get_struct(ary); + return s != NULL && s->tainted ? Qtrue : Qfalse; +} +#endif + /* * call-seq: * array.frozen? -> true or false @@ -273,9 +307,7 @@ ary = rb_ary_new2(n); if (n > 0 && elts) { #if WITH_OBJC - long i; - for (i = 0; i < n; i++) - rb_ary_insert(ary, i, elts[i]); + CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)elts, n); #else MEMCPY(RARRAY_PTR(ary), elts, VALUE, n); RARRAY(ary)->len = n; @@ -1523,10 +1555,10 @@ return Qfalse; } -VALUE -rb_ary_dup(VALUE ary) +#if WITH_OBJC +static inline VALUE +rb_ary_dup2(VALUE ary) { -#if WITH_OBJC VALUE klass, dup; long n; @@ -1536,6 +1568,24 @@ if (n > 0) CFArrayAppendArray((CFMutableArrayRef)dup, (CFArrayRef)ary, CFRangeMake(0, n)); + return dup; +} + +VALUE +rb_ary_clone(VALUE ary) +{ + VALUE dup = rb_ary_dup2(ary); + rb_objc_ary_copy_struct(ary, dup); + return dup; +} +#endif + +VALUE +rb_ary_dup(VALUE ary) +{ +#if WITH_OBJC + VALUE dup = rb_ary_dup2(ary); + /* copy the named_args flag, but not other flags */ if (rb_ary_is_named_args(ary)) rb_ary_set_named_args(dup, true); #else @@ -3692,7 +3742,9 @@ volatile VALUE cc = rb_ary_new2(n); long lev = 0; +#if !WITH_OBJC RBASIC(cc)->klass = 0; +#endif MEMZERO(stack, long, n); stack[0] = -1; for (i = 0; i < nlen; i++) { @@ -3700,7 +3752,11 @@ for (lev++; lev < n; lev++) { rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1] = stack[lev]+1)); } +#if WITH_OBJC + rb_yield(rb_ary_dup(cc)); +#else rb_yield(cc); +#endif do { stack[lev--]++; } while (lev && (stack[lev+1]+n == len+lev+1)); @@ -3925,6 +3981,8 @@ FL_UNSET(rb_cArrayRuby, RCLASS_OBJC_IMPORTED); rb_const_set(rb_cObject, rb_intern("Array"), rb_cArrayRuby); rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0); + rb_define_method(rb_cArray, "taint", rb_ary_taint, 0); + rb_define_method(rb_cArray, "tainted?", rb_ary_tainted, 0); #else rb_cArray = rb_define_class("Array", rb_cObject); #endif Modified: MacRuby/trunk/enumerator.c =================================================================== --- MacRuby/trunk/enumerator.c 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/enumerator.c 2008-04-01 00:29:16 UTC (rev 125) @@ -241,7 +241,7 @@ else { ptr->iter = enumerator_each_i; } - if (argc) ptr->args = rb_ary_new4(argc, argv); + if (argc) GC_WB(&ptr->args, rb_ary_new4(argc, argv)); ptr->fib = 0; ptr->dst = Qnil; ptr->no_next = Qfalse; Modified: MacRuby/trunk/hash.c =================================================================== --- MacRuby/trunk/hash.c 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/hash.c 2008-04-01 00:29:16 UTC (rev 125) @@ -260,10 +260,12 @@ rb_objc_release(v); } +/* TODO optimize me */ struct rb_objc_hash_struct { VALUE ifnone; bool has_proc_default; bool frozen; + bool tainted; }; /* This variable will always stay NULL, we only use its address. */ @@ -287,6 +289,7 @@ s->ifnone = Qnil; s->has_proc_default = false; s->frozen = false; + s->tainted = false; } return s; } @@ -312,6 +315,27 @@ return s != NULL && s->frozen ? Qtrue : Qfalse; } +VALUE +rb_hash_taint(VALUE hash) +{ + struct rb_objc_hash_struct *s; + + s = rb_objc_hash_get_struct2(hash); + s->tainted = true; + + return hash; +} + +VALUE +rb_hash_tainted(VALUE hash) +{ + struct rb_objc_hash_struct *s; + + s = rb_objc_hash_get_struct(hash); + + return s != NULL && s->tainted ? Qtrue : Qfalse; +} + static void rb_objc_hash_set_struct(VALUE hash, VALUE ifnone, bool has_proc_default) { @@ -322,7 +346,20 @@ GC_WB(&s->ifnone, ifnone); s->has_proc_default = has_proc_default; } + +VALUE +rb_hash_clone(VALUE hash) +{ +#if 0 // TODO + VALUE klass, dup; + long n; + + klass = rb_obj_class(ary); + dup = hash_alloc(klass); #endif + return Qnil; +} +#endif static VALUE hash_alloc(VALUE klass) @@ -3046,6 +3083,8 @@ rb_const_set(rb_cObject, rb_intern("Hash"), rb_cHashRuby); rb_define_method(rb_cHash, "freeze", rb_hash_freeze, 0); rb_define_method(rb_cHash, "frozen?", rb_hash_frozen, 0); + rb_define_method(rb_cHash, "taint", rb_hash_taint, 0); + rb_define_method(rb_cHash, "tainted?", rb_hash_tainted, 0); #else rb_cHash = rb_define_class("Hash", rb_cObject); #endif Modified: MacRuby/trunk/include/ruby/intern.h =================================================================== --- MacRuby/trunk/include/ruby/intern.h 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/include/ruby/intern.h 2008-04-01 00:29:16 UTC (rev 125) @@ -81,6 +81,7 @@ VALUE rb_ary_elt(VALUE, long); void rb_ary_set_named_args(VALUE, bool); bool rb_ary_is_named_args(VALUE); +VALUE rb_ary_clone(VALUE); #endif /* bignum.c */ VALUE rb_big_clone(VALUE); @@ -361,6 +362,9 @@ struct st_table *rb_hash_tbl(VALUE); int rb_path_check(const char*); int rb_env_path_tainted(void); +#if WITH_OBJC +VALUE rb_hash_clone(VALUE); +#endif /* io.c */ #define rb_defout rb_stdout RUBY_EXTERN VALUE rb_fs; Modified: MacRuby/trunk/object.c =================================================================== --- MacRuby/trunk/object.c 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/object.c 2008-04-01 00:29:16 UTC (rev 125) @@ -157,6 +157,16 @@ static void init_copy(VALUE dest, VALUE obj) { +#if WITH_OBJC + if (rb_objc_is_non_native(obj)) { + int type = TYPE(obj); + if (type == T_ARRAY) + if (rb_ary_tainted(obj)) rb_ary_taint(dest); + else if (type == T_HASH) + if (rb_hash_tainted(obj)) rb_hash_taint(dest); + goto call_init_copy; + } +#endif if (OBJ_FROZEN(dest)) { rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest)); } @@ -197,6 +207,7 @@ } break; } +call_init_copy: rb_funcall(dest, id_init_copy, 1, obj); } @@ -234,6 +245,11 @@ } #if WITH_OBJC if (rb_objc_is_non_native(obj)) { + int type = TYPE(obj); + if (type == T_ARRAY) + return rb_ary_clone(obj); + if (type == T_HASH) + return rb_hash_clone(obj); clone = rb_obj_alloc(rb_obj_class(obj)); init_copy(clone, obj); return clone; Modified: MacRuby/trunk/test/ruby/test_array.rb =================================================================== --- MacRuby/trunk/test/ruby/test_array.rb 2008-03-31 19:26:59 UTC (rev 124) +++ MacRuby/trunk/test/ruby/test_array.rb 2008-04-01 00:29:16 UTC (rev 125) @@ -182,14 +182,14 @@ def test_00_new a = @cls.new() - assert_instance_of(@cls, a) + assert_kind_of(@cls, a) assert_equal(0, a.length) assert_nil(a[0]) end def test_01_square_brackets a = @cls[ 5, 4, 3, 2, 1 ] - assert_instance_of(@cls, a) + assert_kind_of(@cls, a) assert_equal(5, a.length) 5.times { |i| assert_equal(5-i, a[i]) } assert_nil(a[6])