also need to remove methods from the map when it's invalidated
Jesse Luehrs [Thu, 11 Nov 2010 23:02:38 +0000 (17:02 -0600)]
t/003_methods.t
xs/HasMethods.xs

index ac985bf..a94ae99 100644 (file)
@@ -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;
index 88422ae..44bb8d5 100644 (file)
@@ -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);
     }
 }