]> git.vpit.fr Git - perl/modules/Sub-Op.git/commitdiff
Handle existing constant subs
authorVincent Pit <vince@profvince.com>
Mon, 4 Jan 2010 14:49:06 +0000 (15:49 +0100)
committerVincent Pit <vince@profvince.com>
Mon, 4 Jan 2010 14:49:06 +0000 (15:49 +0100)
Op.xs
lib/Sub/Op.pm
t/11-existing.t

diff --git a/Op.xs b/Op.xs
index 89716e7602a4ed44c9719441ebd3e2fb3aae26fe..cdcc89af7a2d45946ff78f87bf3f87190316c42e 100644 (file)
--- a/Op.xs
+++ b/Op.xs
@@ -381,3 +381,15 @@ PPCODE:
   XSRETURN_UNDEF;
  ST(0) = sv_2mortal(newSVpvn(&on->buf, on->len));
  XSRETURN(1);
+
+void
+_constant_sub(SV *sv)
+PROTOTYPE: $
+PPCODE:
+ if (!SvROK(sv))
+  XSRETURN_UNDEF;
+ sv = SvRV(sv);
+ if (SvTYPE(sv) < SVt_PVCV)
+  XSRETURN_UNDEF;
+ ST(0) = sv_2mortal(newSVuv(CvCONST(sv)));
+ XSRETURN(1);
index c8f7c2e24d156c0686aa15e71a63fa5dd5a2fafb..c075bbb8612aae2b8fe7502139a8ad8419116341 100644 (file)
@@ -142,8 +142,14 @@ my $sw = Variable::Magic::wizard(
   my $pkg = $data->{pkg};
   my $fqn = join '::', $pkg, $name;
 
-  no strict 'refs';
-  *$fqn = $placeholder unless exists &$fqn;
+  {
+   local $SIG{__WARN__} = sub {
+    CORE::warn(@_) unless $_[0] =~ /^Constant subroutine.*redefined/;
+   } if _constant_sub(do { no strict 'refs'; \&$fqn });
+   no strict 'refs';
+   no warnings 'redefine';
+   *$fqn = $placeholder;
+  }
 
   return;
  },
@@ -155,6 +161,7 @@ sub _tag {
  my $fqn = join '::', $pkg, $name;
 
  return {
+  old   => _defined_sub($fqn) ? \&$fqn : undef,
   proto => prototype($fqn),
  };
 }
@@ -296,11 +303,22 @@ sub disable {
  my $pkg = @_ > 0 ? $_[0] : caller;
  my $map = _map($pkg);
 
+ my $fqn = join '::', $pkg, $name;
+
  if (defined $map) {
-  my $proto = $map->{$name}->{proto};
+  my $tag = $map->{$name};
+
+  my $old = $tag->{old};
+  if (defined $old) {
+   no strict 'refs';
+   no warnings 'redefine';
+   *$fqn = $old;
+  }
+
+  my $proto = $tag->{proto};
   if (defined $proto) {
    no strict 'refs';
-   Scalar::Util::set_prototype(\&{"${pkg}::$name"}, $proto);
+   Scalar::Util::set_prototype(\&$fqn, $proto);
   }
 
   delete $map->{$name};
index c45a71b464ca7e9dabd24ff59271964f4bb48094..749fff136fa63311fd3925a2032b383dc6b2dd6a 100644 (file)
@@ -5,7 +5,7 @@ use warnings;
 
 use blib 't/Sub-Op-LexicalSub';
 
-use Test::More tests => 2 *((4 + 2 * 4) + (2 * 5) + 1);
+use Test::More tests => 2 * ((1 + 2) * 4 + (1 + 1) * 5) + (2 + 2) + 4;
 
 our $call_foo;
 sub foo { ok $call_foo, 'the preexistent foo was called' }
@@ -13,6 +13,8 @@ sub foo { ok $call_foo, 'the preexistent foo was called' }
 our $call_bar;
 sub bar () { ok $call_bar, 'the preexistent bar was called' }
 
+sub X () { 1 }
+
 our $called;
 
 {
@@ -74,6 +76,9 @@ our $called;
 
 is prototype('main::foo'), undef, "foo's prototype was preserved";
 is prototype('main::bar'), '',    "bar's prototype was preserved";
+is prototype('main::X'),   '',    "X's prototype was preserved";
+ok Sub::Op::_constant_sub(do { no strict "refs"; \&{"main::X"} }),
+                                  'X is still a constant';
 
 __DATA__
 foo();
@@ -161,3 +166,7 @@ my $bar = \&bar;
 &$bar;
 ----
 bar # () #
+####
+is X, 2, 'constant overriding';
+----
+X # 2 # [ ]