summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-03-08 15:26:08 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-03-08 15:26:08 +0000
commit0316cf2e523d9f77e610477697d5a93842b4d4bd (patch)
tree57833bca5dea888008e464c2be185f93b0280055
parente14095fff2aed4599a69d8c53ee5ca017a6e8826 (diff)
marshal.c: prepended objects
* marshal.c (r_object0): load prepended objects. treat the class of extended object in the included modules as prepended singleton class. [ruby-core:53202] [Bug #8041] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39642 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--marshal.c46
-rw-r--r--test/ruby/marshaltestlib.rb10
3 files changed, 49 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 59426a840a..005f543b9b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat Mar 9 00:25:57 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_object0): load prepended objects. treat the class of
+ extended object in the included modules as prepended singleton
+ class. [ruby-core:53202] [Bug #8041]
+
Fri Mar 8 19:44:00 2013 Akinori MUSHA <knu@iDaemons.org>
* man/rake.1, man/ruby.1: Use the Pa macro to make URLs stand out.
diff --git a/marshal.c b/marshal.c
index 13f01c003c..7b45d1c835 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1387,11 +1387,11 @@ path2class(VALUE path)
return v;
}
+#define path2module(path) must_be_module(rb_path_to_class(path), path)
+
static VALUE
-path2module(VALUE path)
+must_be_module(VALUE v, VALUE path)
{
- VALUE v = rb_path_to_class(path);
-
if (!RB_TYPE_P(v, T_MODULE)) {
rb_raise(rb_eArgError, "%"PRIsVALUE" does not refer to module", path);
}
@@ -1473,16 +1473,36 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
case TYPE_EXTENDED:
{
- VALUE m = path2module(r_unique(arg));
-
- if (NIL_P(extmod)) extmod = rb_ary_tmp_new(0);
- rb_ary_push(extmod, m);
-
- v = r_object0(arg, 0, extmod);
- while (RARRAY_LEN(extmod) > 0) {
- m = rb_ary_pop(extmod);
- rb_extend_object(v, m);
- }
+ VALUE path = r_unique(arg);
+ VALUE m = rb_path_to_class(path);
+
+ if (RB_TYPE_P(m, T_CLASS)) { /* prepended */
+ VALUE c;
+
+ v = r_object0(arg, 0, Qnil);
+ c = CLASS_OF(v);
+ if (c != m || FL_TEST(c, FL_SINGLETON)) {
+ rb_raise(rb_eArgError,
+ "prepended class %"PRIsVALUE" differs from class %"PRIsVALUE,
+ path, rb_class_name(c));
+ }
+ c = rb_singleton_class(v);
+ while (RARRAY_LEN(extmod) > 0) {
+ m = rb_ary_pop(extmod);
+ rb_prepend_module(c, m);
+ }
+ }
+ else {
+ must_be_module(m, path);
+ if (NIL_P(extmod)) extmod = rb_ary_tmp_new(0);
+ rb_ary_push(extmod, m);
+
+ v = r_object0(arg, 0, extmod);
+ while (RARRAY_LEN(extmod) > 0) {
+ m = rb_ary_pop(extmod);
+ rb_extend_object(v, m);
+ }
+ }
}
break;
diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb
index f14209fc19..45c94e0f15 100644
--- a/test/ruby/marshaltestlib.rb
+++ b/test/ruby/marshaltestlib.rb
@@ -75,6 +75,16 @@ module MarshalTestLib
marshal_equal_with_ancestry(o1)
end
+ def test_object_prepend
+ bug8041 = '[ruby-core:53202] [Bug #8041]'
+
+ o1 = MyObject.new(42)
+ o1.singleton_class.class_eval {prepend Mod1}
+ assert_nothing_raised(ArgumentError, bug8041) {
+ marshal_equal_with_ancestry(o1, bug8041)
+ }
+ end
+
class MyArray < Array
def initialize(v, *args)
super(args)