Mouse::Util::does_role() respects $thing->does() method
[gitmo/Mouse.git] / xs-src / MouseUtil.xs
index c0e1d80..3ec7d8c 100644 (file)
@@ -112,54 +112,39 @@ mouse_throw_error(SV* const metaobject, SV* const data /* not used */, const cha
             mPUSHs(newSVpvs("depth"));
             mPUSHi(-1);
         }
-
         PUTBACK;
-
-        call_method("throw_error", G_VOID);
-        croak("throw_error() did not throw the error (%"SVf")", message);
-    }
-}
-
-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;
+        if(SvOK(metaobject)) {
+            call_method("throw_error", G_VOID);
         }
+        else {
+            call_pv("Mouse::Util::throw_error", G_VOID);
+        }
+        croak("throw_error() did not throw the error (%"SVf")", message);
     }
-    return i;
 }
 
-/* workaround RT #69939 */
+/* workaround Perl-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 );
+    I32 count;
+    ENTER;
+    /* Don't do SAVETMPS */
 
-    //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();
+    SAVESPTR(ERRSV);
+    ERRSV = sv_newmortal();
 
-        count = Perl_call_sv(aTHX_ sv, flags | G_EVAL);
+    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);
+    if(sv_true(ERRSV)){
+        SV* const err = sv_mortalcopy(ERRSV);
+        LEAVE;
+        sv_setsv(ERRSV, err);
+        croak(NULL); /* rethrow */
     }
+
+    LEAVE;
+
+    return count;
 }
 
 void
@@ -338,7 +323,7 @@ mouse_install_sub(pTHX_ GV* const gv, SV* const code_ref) {
 
     if(GvCVu(gv)){ /* delete *slot{gv} to work around "redefine" warning */
         SvREFCNT_dec(GvCV(gv));
-        GvCV(gv) = NULL;
+        GvCV_set(gv, NULL);
     }
 
     sv_setsv_mg((SV*)gv, code_ref); /* *gv = $code_ref */
@@ -366,7 +351,7 @@ mouse_install_sub(pTHX_ GV* const gv, SV* const code_ref) {
             }
         }
 
-        CvGV(cv) = gv;
+        CvGV_set(cv, gv);
         CvANON_off(cv);
     }
 }