X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseUtil.xs;h=c0e1d80dfdc803d049e253b5b6dc1f6cf77b81fd;hb=5433f84558b602c30288e7694d7597774ce49313;hp=3c02d18c8e13e523d8f49dc34078e53d0cd8fb4d;hpb=fa4ac6485baa33fc2e12f9a9924ff428b0403fa5;p=gitmo%2FMouse.git diff --git a/xs-src/MouseUtil.xs b/xs-src/MouseUtil.xs index 3c02d18..c0e1d80 100644 --- a/xs-src/MouseUtil.xs +++ b/xs-src/MouseUtil.xs @@ -120,6 +120,48 @@ mouse_throw_error(SV* const metaobject, SV* const data /* not used */, const cha } } +static I32 +S_dopoptosub(pTHX_ I32 const startingblock) +{ + const PERL_CONTEXT* const cxstk = cxstack; + I32 i; + for (i = startingblock; i >= 0; i--) { + const PERL_CONTEXT* const cx = &cxstk[i]; + + switch (CxTYPE(cx)) { + case CXt_EVAL: + case CXt_SUB: + case CXt_FORMAT: + return i; + } + } + return i; +} + +/* workaround RT #69939 */ +I32 +mouse_call_sv_safe(pTHX_ SV* const sv, I32 const flags) { + const PERL_CONTEXT* const cx = &cxstack[S_dopoptosub(aTHX_ cxstack_ix)]; + assert( (flags & G_EVAL) == 0 ); + + //warn("cx_type=0x%02x PL_eval=0x%02x (%"SVf")", (unsigned)cx->cx_type, (unsigned)PL_in_eval, sv); + if(!(cx->cx_type & CXp_TRYBLOCK)) { + I32 count; + //SAVESPTR(ERRSV); + //ERRSV = sv_newmortal(); + + count = Perl_call_sv(aTHX_ sv, flags | G_EVAL); + + if(sv_true(ERRSV)){ + croak(NULL); /* rethrow */ + } + return count; + } + else { + return Perl_call_sv(aTHX_ sv, flags); + } +} + void mouse_must_defined(pTHX_ SV* const value, const char* const name) { assert(value); @@ -199,7 +241,7 @@ mouse_call0 (pTHX_ SV* const self, SV* const method) { XPUSHs(self); PUTBACK; - call_sv(method, G_SCALAR | G_METHOD); + call_sv_safe(method, G_SCALAR | G_METHOD); SPAGAIN; ret = POPs; @@ -219,7 +261,7 @@ mouse_call1 (pTHX_ SV* const self, SV* const method, SV* const arg1) { PUSHs(arg1); PUTBACK; - call_sv(method, G_SCALAR | G_METHOD); + call_sv_safe(method, G_SCALAR | G_METHOD); SPAGAIN; ret = POPs; @@ -350,7 +392,9 @@ CODE: } { dMY_CXT; - if(MY_CXT.metas) croak("Cannot set metaclass storage more than once"); + if(MY_CXT.metas && ckWARN(WARN_REDEFINE)){ + Perl_warner(aTHX_ packWARN(WARN_REDEFINE), "Metaclass storage more than once"); + } MY_CXT.metas = metas; SvREFCNT_inc_simple_void_NN(metas); }