static void
-mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const args, bool const ignore_triggers) {
+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;
croak("You cannot use tied HASH reference as initializing arguments");
}
- if(!ignore_triggers){
- triggers_queue = newAV_mortal();
- }
-
/* for each attribute */
for(i = 0; i < len; i++){
SV* const attr = MOUSE_av_at(attrs, i);
if(SvROK(value) && flags & MOUSEf_ATTR_IS_WEAK_REF){
weaken_slot(object, slot);
}
- if(flags & MOUSEf_ATTR_HAS_TRIGGER && triggers_queue){
+ if(flags & MOUSEf_ATTR_HAS_TRIGGER){
AV* const pair = newAV();
av_push(pair, newSVsv( mcall0s(attr, "trigger") ));
av_push(pair, newSVsv(value));
+ if(!triggers_queue) {
+ triggers_queue = newAV_mortal();
+ }
av_push(triggers_queue, (SV*)pair);
}
used++;
}
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);
}
}
}
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];
PUSHs(args);
PUTBACK;
- call_sv(AvARRAY(buildall)[i], G_VOID);
+ call_sv_safe(AvARRAY(buildall)[i], G_VOID);
/* discard a scalar which G_VOID returns */
SPAGAIN;
/* *{$package . '::' . $name} -> *gv */
gv = gv_fetchpv(form("%"SVf"::%"SVf, package, name), GV_ADDMULTI, SVt_PVCV);
mouse_install_sub(aTHX_ gv, code_ref);
+ //CvMETHOD_on((CV*)SvRV(code_ref));
(void)set_slot(methods, name, code); /* $self->{methods}{$name} = $code */
}
RETVAL = mouse_instance_create(aTHX_ MOUSE_xc_stash(xc));
mouse_class_initialize_object(aTHX_ meta, RETVAL, args, FALSE);
+ mouse_buildall(aTHX_ xc, RETVAL, args); /* BUILDALL */
}
OUTPUT:
RETVAL
void
-_initialize_object(SV* meta, SV* object, HV* args, bool ignore_triggers = FALSE)
+_initialize_object(SV* meta, SV* object, HV* args, bool is_cloning = FALSE)
CODE:
{
- mouse_class_initialize_object(aTHX_ meta, object, args, ignore_triggers);
+ mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning);
}
MODULE = Mouse PACKAGE = Mouse::Meta::Role
for(i = 0; i < items; i++){
PUSHs(ST(i));
}
- //SP += items;
+
PUTBACK;
- call_method("BUILDARGS", G_SCALAR);
+ call_method_safes("BUILDARGS", G_SCALAR);
+
SPAGAIN;
args = POPs;
PUTBACK;
/* 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);
+ mouse_buildall(aTHX_ xc, RETVAL, args); /* BUILDALL */
}
OUTPUT:
RETVAL
len = AvFILLp(demolishall) + 1;
if(len > 0){
- GV* const statusvalue = gv_fetchpvs("?", 0, SVt_PV);
+ SV* const in_global_destruction = boolSV(PL_dirty);
+ SAVEI32(PL_statusvalue); /* local $? */
+ PL_statusvalue = 0;
- if(statusvalue){ /* it can be NULL */
- SAVESPTR(GvSV(statusvalue)); /* local $? */
- GvSV(statusvalue) = sv_newmortal();
- }
SAVESPTR(ERRSV); /* local $@ */
- ERRSV = newSVpvs_flags("", SVs_TEMP);
+ ERRSV = sv_newmortal();
+
+ EXTEND(SP, 2);
for(i = 0; i < len; i++){
SPAGAIN;
PUSHMARK(SP);
- XPUSHs(object);
- XPUSHs(boolSV(PL_dirty));
+ PUSHs(object);
+ PUSHs(in_global_destruction);
PUTBACK;
call_sv(AvARRAY(demolishall)[i], G_VOID | G_EVAL);