--- JSON-XS/XS.xs 2013/10/28 23:19:54 1.119 +++ JSON-XS/XS.xs 2013/10/28 23:23:10 1.120 @@ -685,6 +685,7 @@ encode_rv (enc_t *enc, SV *sv) { svtype svt; + GV *method; SvGETMAGIC (sv); svt = SvTYPE (sv); @@ -703,94 +704,74 @@ else encode_str (enc, "false", 5, 0); } - else if (enc->json.flags & F_CONV_BLESSED) + else if ((enc->json.flags & F_ALLOW_TAGS) && (method = gv_fetchmethod_autoload (stash, "FREEZE", 0))) { - GV *to_json = gv_fetchmethod_autoload (stash, "TO_JSON", 0); + int count; + dSP; - if (to_json) - { - dSP; - - ENTER; SAVETMPS; PUSHMARK (SP); - // we re-bless the reference to get overload and other niceties right - XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); + ENTER; SAVETMPS; PUSHMARK (SP); + EXTEND (SP, 2); + // we re-bless the reference to get overload and other niceties right + PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); + PUSHs (sv_json); + + PUTBACK; + count = call_sv ((SV *)GvCV (method), G_ARRAY); + SPAGAIN; + + // catch this surprisingly common error + if (SvROK (TOPs) && SvRV (TOPs) == sv) + croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); + + encode_ch (enc, '('); + encode_ch (enc, '"'); + encode_str (enc, HvNAME (stash), HvNAMELEN (stash), HvNAMEUTF8 (stash)); + encode_ch (enc, '"'); + encode_ch (enc, ')'); + encode_ch (enc, '['); - // calling with G_SCALAR ensures that we always get a 1 return value - PUTBACK; - call_sv ((SV *)GvCV (to_json), G_SCALAR); - SPAGAIN; + while (count) + { + encode_sv (enc, SP[1 - count--]); - // catch this surprisingly common error - if (SvROK (TOPs) && SvRV (TOPs) == sv) - croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); + if (count) + encode_ch (enc, ','); + } - sv = POPs; - PUTBACK; + encode_ch (enc, ']'); - encode_sv (enc, sv); + PUTBACK; - FREETMPS; LEAVE; - } - else if (enc->json.flags & F_ALLOW_BLESSED) - encode_str (enc, "null", 4, 0); - else - croak ("encountered object '%s' when conv_object is enabled, but TO_JSON is missing and allow_blessed disabled", - SvPV_nolen (sv_2mortal (newRV_inc (sv)))); + FREETMPS; LEAVE; } - else if (enc->json.flags & F_ALLOW_TAGS) + else if ((enc->json.flags & F_CONV_BLESSED) && (method = gv_fetchmethod_autoload (stash, "TO_JSON", 0))) { - GV *method = gv_fetchmethod_autoload (stash, "FREEZE", 0); + dSP; - if (method) - { - int count; - dSP; + ENTER; SAVETMPS; PUSHMARK (SP); + // we re-bless the reference to get overload and other niceties right + XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); - ENTER; SAVETMPS; PUSHMARK (SP); - EXTEND (SP, 2); - // we re-bless the reference to get overload and other niceties right - PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); - PUSHs (sv_json); - - PUTBACK; - count = call_sv ((SV *)GvCV (method), G_ARRAY); - SPAGAIN; - - // catch this surprisingly common error - if (SvROK (TOPs) && SvRV (TOPs) == sv) - croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); - - encode_ch (enc, '('); - encode_ch (enc, '"'); - encode_str (enc, HvNAME (stash), HvNAMELEN (stash), HvNAMEUTF8 (stash)); - encode_ch (enc, '"'); - encode_ch (enc, ')'); - encode_ch (enc, '['); - - while (count) - { - encode_sv (enc, SP[1 - count--]); - - if (count) - encode_ch (enc, ','); - } + // calling with G_SCALAR ensures that we always get a 1 return value + PUTBACK; + call_sv ((SV *)GvCV (method), G_SCALAR); + SPAGAIN; - encode_ch (enc, ']'); + // catch this surprisingly common error + if (SvROK (TOPs) && SvRV (TOPs) == sv) + croak ("%s::TO_JSON method returned same object as was passed instead of a new one", HvNAME (SvSTASH (sv))); - PUTBACK; + sv = POPs; + PUTBACK; - FREETMPS; LEAVE; - } - else if (enc->json.flags & F_ALLOW_BLESSED) - encode_str (enc, "null", 4, 0); - else - croak ("encountered object '%s' when allow_tags is enabled, but FREEZE is missing and allow_blessed disabled", - SvPV_nolen (sv_2mortal (newRV_inc (sv)))); + encode_sv (enc, sv); + + FREETMPS; LEAVE; } else if (enc->json.flags & F_ALLOW_BLESSED) encode_str (enc, "null", 4, 0); else - croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled", + croak ("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", SvPV_nolen (sv_2mortal (newRV_inc (sv)))); } else if (svt == SVt_PVHV)