X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouse.xs;h=c47072d659dac1abbc07f6cada8a34a813b7e704;hb=b5956f03156c79cfbdd20f9526f95a9df5aa26b4;hp=979fcd3353bc85eef6745abe2a94fa1139e6be35;hpb=f10b7c0fd9728b06eb9e8a7421f6da6ae94f7163;p=gitmo%2FMouse.git diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index 979fcd3..c47072d 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -291,10 +291,10 @@ mouse_report_unknown_args(pTHX_ SV* const meta, AV* const attrs, HV* const args) 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; @@ -307,10 +307,6 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const 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); @@ -330,22 +326,27 @@ mouse_class_initialize_object(pTHX_ SV* const meta, SV* const object, HV* const 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); } } @@ -356,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]; @@ -397,7 +398,7 @@ mouse_buildall(pTHX_ AV* const xc, SV* const object, SV* const args) { 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; @@ -513,6 +514,7 @@ CODE: /* *{$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 */ } @@ -578,15 +580,16 @@ 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 @@ -651,9 +654,10 @@ CODE: 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; @@ -670,8 +674,7 @@ 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); + mouse_buildall(aTHX_ xc, RETVAL, args); /* BUILDALL */ } OUTPUT: RETVAL @@ -715,21 +718,21 @@ CODE: 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);