Revert __set_strict_constructor
[gitmo/Mouse.git] / xs-src / Mouse.xs
index f27c52f..250604d 100644 (file)
@@ -294,7 +294,7 @@ static void
 mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const is_cloning) {
     AV* const xc    = mouse_get_xc(aTHX_ meta);
     AV* const attrs = MOUSE_xc_attrall(xc);
-    I32 len         = AvFILLp(attrs) + 1;
+    I32 const len   = AvFILLp(attrs) + 1;
     I32 i;
     AV* triggers_queue = NULL;
     I32 used = 0;
@@ -338,13 +338,15 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const
             }
             used++;
         }
-        else if(!is_cloning){ /* no init arg, noop while cloning */
+        else { /* no init arg */
             if(flags & (MOUSEf_ATTR_HAS_DEFAULT | MOUSEf_ATTR_HAS_BUILDER)){
-                if(!(flags & MOUSEf_ATTR_IS_LAZY)){
+                /* skip if the object has the slot (it occurs on cloning/reblessing) */
+                if(!(flags & MOUSEf_ATTR_IS_LAZY) && !has_slot(object, slot)){
                     mouse_xa_set_default(aTHX_ xa, object);
                 }
             }
-            else if(flags & MOUSEf_ATTR_IS_REQUIRED) {
+            /* don't check while cloning (or reblesseing) */
+            else if(!is_cloning && flags & MOUSEf_ATTR_IS_REQUIRED) {
                 mouse_throw_error(attr, NULL, "Attribute (%"SVf") is required", slot);
             }
         }
@@ -355,7 +357,7 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const
     }
 
     if(triggers_queue){
-        len = AvFILLp(triggers_queue) + 1;
+        I32 const len = AvFILLp(triggers_queue) + 1;
         for(i = 0; i < len; i++){
             AV* const pair    = (AV*)AvARRAY(triggers_queue)[i];
             SV* const trigger = AvARRAY(pair)[0];
@@ -522,7 +524,8 @@ BOOT:
     INSTALL_SIMPLE_READER(Class, roles);
     INSTALL_SIMPLE_PREDICATE_WITH_KEY(Class, is_anon_class, anon_serial_id);
     INSTALL_SIMPLE_READER(Class, is_immutable);
-    INSTALL_SIMPLE_READER_WITH_KEY(Class, __strict_constructor, strict_constructor);
+
+    INSTALL_SIMPLE_READER_WITH_KEY(Class, __strict_constructor,     strict_constructor);
 
     INSTALL_CLASS_HOLDER(Class, method_metaclass,     "Mouse::Meta::Method");
     INSTALL_CLASS_HOLDER(Class, attribute_metaclass,  "Mouse::Meta::Attribute");
@@ -534,7 +537,6 @@ BOOT:
     newCONSTSUB(gv_stashpvs("Mouse::Meta::Method::Destructor::XS", TRUE), "_generate_destructor",
         newRV_inc((SV*)get_cvs("Mouse::Object::DESTROY", TRUE)));
 
-
 void
 linearized_isa(SV* self)
 PPCODE:
@@ -569,18 +571,40 @@ PPCODE:
     }
 }
 
-SV*
+void
 new_object(SV* meta, ...)
 CODE:
 {
     AV* const xc   = mouse_get_xc(aTHX_ meta);
     HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax, items);
+    SV* object;
 
-    RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc));
-    mouse_class_initialize_object(aTHX_ meta, RETVAL, args, FALSE);
+    object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc));
+    mouse_class_initialize_object(aTHX_ meta, object, args, FALSE);
+    mouse_buildall(aTHX_ xc, object, sv_2mortal(newRV_inc((SV*)args))); /* BUILDALL */
+    ST(0) = object; /* because object is mortal, we should return it as is */
+    XSRETURN(1);
+}
+
+void
+clone_object(SV* meta, SV* object, ...)
+CODE:
+{
+    AV* const xc   = mouse_get_xc(aTHX_ meta);
+    HV* const args = mouse_buildargs(aTHX_ meta, NULL, ax + 1, items - 1);
+    SV* proto;
+
+    if(!mouse_is_an_instance_of(aTHX_ MOUSE_xc_stash(xc), object)) {
+        mouse_throw_error(meta, object,
+            "You must pass an instance of the metaclass (%"SVf"), not (%"SVf")",
+            mcall0(meta, mouse_name), object);
+    }
+
+    proto = mouse_instance_clone(aTHX_ object);
+    mouse_class_initialize_object(aTHX_ meta, proto, args, TRUE);
+    ST(0) = proto; /* because object is mortal, we should return it as is */
+    XSRETURN(1);
 }
-OUTPUT:
-    RETVAL
 
 void
 _initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE)
@@ -632,7 +656,7 @@ PPCODE:
 
 MODULE = Mouse  PACKAGE = Mouse::Object
 
-SV*
+void
 new(SV* klass, ...)
 CODE:
 {
@@ -640,6 +664,7 @@ CODE:
     AV* const xc   = mouse_get_xc(aTHX_ meta);
     UV const flags = MOUSE_xc_flags(xc);
     SV* args;
+    SV* object;
 
     /* BUILDARGS */
     if(flags & MOUSEf_XC_HAS_BUILDARGS){
@@ -669,13 +694,12 @@ CODE:
     }
 
     /* new_object */
-    RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc));
-    mouse_class_initialize_object(aTHX_ meta, RETVAL, (HV*)SvRV(args), FALSE);
-
-    mouse_buildall(aTHX_ xc, RETVAL, args);
+    object = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc));
+    mouse_class_initialize_object(aTHX_ meta, object, (HV*)SvRV(args), FALSE);
+    mouse_buildall(aTHX_ xc, object, args); /* BUILDALL */
+    ST(0) = object; /* because object is mortal, we should return it as is */
+    XSRETURN(1);
 }
-OUTPUT:
-    RETVAL
 
 void
 DESTROY(SV* object)