develooper Front page | perl.perl5.changes | Postings from November 2010

[perl.git] branch blead, updated. v5.13.7-195-g15e6cdd

From:
David Golden
Date:
November 29, 2010 12:31
Subject:
[perl.git] branch blead, updated. v5.13.7-195-g15e6cdd
Message ID:
E1PNANp-0006cj-LR@camel.ams6.corp.booking.com
In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/15e6cdd91beb4cefae4b65e855d68cf64766965d?hp=a812f6a926c0966af8d2a9a3d2d05fe1a5df510f>

- Log -----------------------------------------------------------------
commit 15e6cdd91beb4cefae4b65e855d68cf64766965d
Author: David Golden <dagolden@cpan.org>
Date:   Sun Nov 28 23:12:12 2010 -0500

    Filehandle method calls load IO::File on demand
    
    When a method call on a filehandle would die because the method can not
    be resolved and L<IO::File> has not been loaded, Perl now loads IO::File
    via C<require> and attempts method resolution again:
    
      open my $fh, ">", $file;
      $fh->binmode(":raw");     # loads IO::File and succeeds
    
    This also works for globs like STDOUT, STDERR and STDIN:
    
      STDOUT->autoflush(1);
    
    Because this on-demand load only happens if method resolution fails, the
    legacy approach of manually loading an IO::File parent class for partial
    method support still works as expected:
    
      use IO::Handle;
      open my $fh, ">", $file;
      $fh->autoflush(1);        # IO::File not loaded
-----------------------------------------------------------------------

Summary of changes:
 MANIFEST          |    1 +
 gv.c              |   13 +++++++++++++
 pod/perldelta.pod |   21 +++++++++++++++++++++
 t/io/iofile.t     |   25 +++++++++++++++++++++++++
 t/io/open.t       |   12 +++++++++++-
 5 files changed, 71 insertions(+), 1 deletions(-)
 create mode 100644 t/io/iofile.t

diff --git a/MANIFEST b/MANIFEST
index 5ddf5cc..d9281f4 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4485,6 +4485,7 @@ t/io/errno.t			See if $! is correctly set
 t/io/fflush.t			See if auto-flush on fork/exec/system/qx works
 t/io/fs.t			See if directory manipulations work
 t/io/inplace.t			See if inplace editing works
+t/io/iofile.t			See if we can load IO::File on demand
 t/io/iprefix.t			See if inplace editing works with prefixes
 t/io/layers.t			See if PerlIO layers work
 t/io/nargv.t			See if nested ARGV stuff works
diff --git a/gv.c b/gv.c
index 5fd385b..4775bcc 100644
--- a/gv.c
+++ b/gv.c
@@ -718,6 +718,19 @@ Perl_gv_fetchmethod_flags(pTHX_ HV *stash, const char *name, U32 flags)
 	    /* Right now this is exclusively for the benefit of S_method_common
 	       in pp_hot.c  */
 	    if (stash) {
+		/* If we can't find an IO::File method, it might be a call on
+		 * a filehandle. If IO:File has not been loaded, try to
+		 * require it first instead of croaking */
+		const char *stash_name = HvNAME_get(stash);
+		const char *io_file = "IO/File.pm";
+		if (stash_name && strEQ(stash_name,"IO::File")
+		    && ! hv_exists(GvHVn(PL_incgv),io_file, strlen(io_file))
+		) {
+		    require_pv(io_file);
+		    gv = gv_fetchmeth(stash, name, nend - name, 0);
+		    if (gv)
+			return gv;
+		}
 		Perl_croak(aTHX_
 			   "Can't locate object method \"%s\" via package \"%.*s\"",
 			   name, (int)HvNAMELEN_get(stash), HvNAME_get(stash));
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index b9c5cb0..8c660f7 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -58,6 +58,27 @@ calls C<< Devel::foo->unimport('bar') >> if the method exists.
 This is particularly useful to suppresses the default actions of a
 C<Devel::*> module's C<import> method whilst still loading it for debugging.
 
+=head2 Filehandle method calls load IO::File on demand
+
+When a method call on a filehandle would die because the method can not
+be resolved and L<IO::File> has not been loaded, Perl now loads IO::File
+via C<require> and attempts method resolution again:
+
+  open my $fh, ">", $file;
+  $fh->binmode(":raw");     # loads IO::File and succeeds
+
+This also works for globs like STDOUT, STDERR and STDIN:
+
+  STDOUT->autoflush(1);
+
+Because this on-demand load only happens if method resolution fails, the
+legacy approach of manually loading an IO::File parent class for partial
+method support still works as expected:
+
+  use IO::Handle;
+  open my $fh, ">", $file;
+  $fh->autoflush(1);        # IO::File not loaded
+
 =head1 Security
 
 XXX Any security-related notices go here.  In particular, any security
diff --git a/t/io/iofile.t b/t/io/iofile.t
new file mode 100644
index 0000000..9a5b278
--- /dev/null
+++ b/t/io/iofile.t
@@ -0,0 +1,25 @@
+#!./perl
+
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+    require './test.pl';
+}
+
+$|  = 1;
+use warnings;
+use Config;
+
+plan tests => 3;
+
+# this is essentially the same as a test on a lexical filehandle in
+# t/io/open.t, but done in a separate test process against a standard
+# filehandle
+
+# check that we can call methods on filehandles auto-magically
+# and have IO::File loaded for us
+{
+    is( $INC{'IO/File.pm'}, undef, "IO::File not loaded" );
+    ok( eval { STDOUT->autoflush(1); 1 }, 'STDOUT->autoflush(1) lives' );
+    ok( $INC{'IO/File.pm'}, "IO::File now loaded" );
+}
diff --git a/t/io/open.t b/t/io/open.t
index 5bbcb0b..5a8f008 100644
--- a/t/io/open.t
+++ b/t/io/open.t
@@ -10,7 +10,7 @@ $|  = 1;
 use warnings;
 use Config;
 
-plan tests => 111;
+plan tests => 114;
 
 my $Perl = which_perl();
 
@@ -347,3 +347,13 @@ fresh_perl_is(
         # when this fails, it leaves an extra file:
         or unlink \*STDOUT;
 }
+
+# check that we can call methods on filehandles auto-magically
+# and have IO::File loaded for us
+{
+    is( $INC{'IO/File.pm'}, undef, "IO::File not loaded" );
+    my $var = "";
+    open my $fh, ">", \$var;
+    ok( eval { $fh->autoflush(1); 1 }, '$fh->autoflush(1) lives' );
+    ok( $INC{'IO/File.pm'}, "IO::File now loaded" );
+}

--
Perl5 Master Repository



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About