also handle weakening in anon roles
Jesse Luehrs [Fri, 1 Oct 2010 05:31:01 +0000 (00:31 -0500)]
lib/Moose/Meta/Role.pm
t/030_roles/036_free_anonymous_roles.t

index 3789245..3a459f4 100644 (file)
@@ -161,12 +161,22 @@ $META->add_attribute(
 sub initialize {
     my $class = shift;
     my $pkg   = shift;
-    return Class::MOP::get_metaclass_by_name($pkg)
-        || $class->SUPER::initialize(
+
+    if (defined(my $meta = Class::MOP::get_metaclass_by_name($pkg))) {
+        return $meta;
+    }
+
+    my %options = @_;
+
+    my $meta = $class->SUPER::initialize(
         $pkg,
         'attribute_metaclass' => 'Moose::Meta::Role::Attribute',
-        @_
-        );
+        %options,
+    );
+
+    Class::MOP::weaken_metaclass($pkg) if $options{weaken};
+
+    return $meta;
 }
 
 sub reinitialize {
@@ -189,13 +199,19 @@ sub reinitialize {
         );
     }
 
+    my %options = @_;
+    $options{weaken} = Class::MOP::metaclass_is_weak($meta->name)
+        if !exists $options{weaken}
+        && blessed($meta)
+        && $meta->isa('Moose::Meta::Role');
+
     # don't need to remove generated metaobjects here yet, since we don't
     # yet generate anything in roles. this may change in the future though...
     # keep an eye on that
     my $new_meta = $self->SUPER::reinitialize(
         $pkg,
         %existing_classes,
-        @_,
+        %options,
     );
     $new_meta->_restore_metaobjects_from($meta)
         if $meta && $meta->isa('Moose::Meta::Role');
@@ -513,9 +529,6 @@ sub create {
         }
     }
 
-    Class::MOP::weaken_metaclass($meta->name)
-        if $meta->is_anon_role;
-
     return $meta;
 }
 
@@ -557,6 +570,7 @@ sub consumers {
 
     sub create_anon_role {
         my ($role, %options) = @_;
+        $options{weaken} = 1 unless exists $options{weaken};
         my $package_name = $ANON_ROLE_PREFIX . ++$ANON_ROLE_SERIAL;
         return $role->create($package_name, %options);
     }
index 855e2bf..6d06d23 100644 (file)
@@ -33,4 +33,31 @@ ok(!$weak, "the role metaclass is freed after its last reference (from a consumi
 
 ok(!$name->can('improperly_freed'), "we blew away the role's symbol table entries");
 
+do {
+    my $anon_class;
+
+    do {
+        my $role = Moose::Meta::Role->create_anon_role(
+            methods => {
+                improperly_freed => sub { 1 },
+            },
+            weaken => 0,
+        );
+        weaken($weak = $role);
+
+        $name = $role->name;
+
+        $anon_class = Moose::Meta::Class->create_anon_class(
+            roles => [ $role->name ],
+        );
+    };
+
+    ok($weak, "we still have the role metaclass because the anonymous class that consumed it is still alive");
+    ok($name->can('improperly_freed'), "we have not blown away the role's symbol table");
+};
+
+ok($weak, "the role metaclass still exists because we told it not to weaken");
+
+ok($name->can('improperly_freed'), "the symbol table still exists too");
+
 done_testing;