Avoid removing previously imported symbols
Florian Ragwitz [Tue, 5 Oct 2010 23:15:58 +0000 (01:15 +0200)]
lib/Moose/Exporter.pm
t/010_basics/009_import_unimport.t

index aca3f3a..d416b98 100644 (file)
@@ -51,12 +51,7 @@ sub build_import_methods {
         $is_reexport,
     );
 
-    my $exporter = Sub::Exporter::build_exporter(
-        {
-            exports => $exports,
-            groups  => { default => [':all'] }
-        }
-    );
+    my $exporter = $class->_make_exporter($exports, $is_reexport);
 
     my %methods;
     $methods{import} = $class->_make_import_sub(
@@ -90,6 +85,49 @@ sub build_import_methods {
     return ( $methods{import}, $methods{unimport}, $methods{init_meta} );
 }
 
+sub _make_exporter {
+    my ($class, $exports, $is_reexport) = @_;
+
+    return Sub::Exporter::build_exporter(
+        {
+            exports   => $exports,
+            groups    => { default => [':all'] },
+            installer => sub {
+                my ($arg, $to_export) = @_;
+                my $meta = Class::MOP::class_of($arg->{into});
+
+                goto &Sub::Exporter::default_installer unless $meta;
+
+                # don't overwrite existing symbols with our magically flagged
+                # version of it if we would install the same sub that's already
+                # in the importer
+
+                my @filtered_to_export;
+                my %installed;
+                for (my $i = 0; $i < @{ $to_export }; $i += 2) {
+                    my ($as, $cv) = @{ $to_export }[$i, $i + 1];
+
+                    next if !ref($as)
+                         && $meta->has_package_symbol('&' . $as)
+                         && $meta->get_package_symbol('&' . $as) == $cv;
+
+                    push @filtered_to_export, $as, $cv;
+                    $installed{$as} = 1 unless ref $as;
+                }
+
+                Sub::Exporter::default_installer($arg, \@filtered_to_export);
+
+                for my $name ( keys %{$is_reexport} ) {
+                    no strict 'refs';
+                    no warnings 'once';
+                    next unless exists $installed{$name};
+                    _flag_as_reexport( \*{ join q{::}, $arg->{into}, $name } );
+                }
+            },
+        }
+    );
+}
+
 {
     my $seen = {};
 
@@ -416,12 +454,6 @@ sub _make_import_sub {
         }
 
         $class->$exporter( $extra, @args );
-
-        for my $name ( keys %{$is_reexport} ) {
-            no strict 'refs';
-            no warnings 'once';
-            _flag_as_reexport( \*{ join q{::}, $CALLER, $name } );
-        }
     };
 }
 
index 89bab82..95caad9 100644 (file)
@@ -73,4 +73,28 @@ ok(!Bar->can($_), '... Bar can no longer do ' . $_) for @moose_type_constraint_e
 
 can_ok( 'Baz', 'blessed' );
 
+{
+    package Moo;
+
+    use Scalar::Util qw( blessed );
+    use Moose;
+
+    no Moose;
+}
+
+can_ok( 'Moo', 'blessed' );
+
+my $blessed;
+{
+    package Quux;
+
+    use Scalar::Util qw( blessed );
+    use Moose blessed => { -as => \$blessed };
+
+    no Moose;
+}
+
+can_ok( 'Quux', 'blessed' );
+is( $blessed, \&Scalar::Util::blessed );
+
 done_testing;