From: Jesse Luehrs Date: Thu, 11 Nov 2010 23:02:38 +0000 (-0600) Subject: also need to remove methods from the map when it's invalidated X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e4679e2cce46297ade239d8d5fd87ba9e32eb840;p=gitmo%2FClass-MOP.git also need to remove methods from the map when it's invalidated --- diff --git a/t/003_methods.t b/t/003_methods.t index ac985bf..a94ae99 100644 --- a/t/003_methods.t +++ b/t/003_methods.t @@ -379,5 +379,20 @@ is_deeply( '_get_local_methods handles constants properly' ); +{ + package DeleteFromMe; + sub foo { 1 } +} + +{ + my $DFMmeta = Class::MOP::Class->initialize('DeleteFromMe'); + ok($DFMmeta->get_method('foo')); + + delete $DeleteFromMe::{foo}; + + ok(!$DFMmeta->get_method('foo')); + ok(!DeleteFromMe->can('foo')); +} + done_testing; diff --git a/xs/HasMethods.xs b/xs/HasMethods.xs index 88422ae..44bb8d5 100644 --- a/xs/HasMethods.xs +++ b/xs/HasMethods.xs @@ -7,51 +7,38 @@ SV *mop_wrap; static void mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map) { - const char *const class_name_pv = HvNAME(stash); /* must be HvNAME(stash), not SvPV_nolen_const(class_name) */ char *method_name; I32 method_name_len; - SV *coderef; + SV *method; HV *symbols; symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE); sv_2mortal((SV*)symbols); - (void)hv_iterinit(symbols); - while ( (coderef = hv_iternextsv(symbols, &method_name, &method_name_len)) ) { - CV *cv = (CV *)SvRV(coderef); - char *cvpkg_name; - char *cv_name; - SV *method_slot; - - if (!mop_get_code_info(coderef, &cvpkg_name, &cv_name)) { + + (void)hv_iterinit(map); + while ((method = hv_iternextsv(map, &method_name, &method_name_len))) { + SV *body; + SV *stash_slot; + + if (!SvROK(method)) { continue; } - /* this checks to see that the subroutine is actually from our package */ - if ( !(strEQ(cvpkg_name, "constant") && strEQ(cv_name, "__ANON__")) ) { - if ( strNE(cvpkg_name, class_name_pv) ) { - continue; - } + if (sv_isobject(method)) { + /* $method_object->body() */ + body = mop_call0(aTHX_ method, KEY_FOR(body)); + } + else { + body = method; } - method_slot = *hv_fetch(map, method_name, method_name_len, TRUE); - if ( SvOK(method_slot) ) { - SV *body; - - if ( sv_isobject(method_slot) ) { - body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */ - } - else { - body = method_slot; - } - - if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) { - continue; - } - else { - /* $map->{$method_name} = undef */ - sv_setsv(method_slot, &PL_sv_undef); - } + stash_slot = *hv_fetch(symbols, method_name, method_name_len, TRUE); + if (SvROK(stash_slot) && ((CV*)SvRV(body)) == ((CV*)SvRV(stash_slot))) { + continue; } + + /* $map->{$method_name} = undef */ + sv_setsv(method, &PL_sv_undef); } }