From 221e5dbc861edab87d502b2e8d85f5310d0fd1e4 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Thu, 14 Apr 2011 06:19:07 -0700 Subject: [PATCH] [perl #88486] IO::File does not always export SEEK* Commit d963bf0 made perl set @IO::File::ISA automagically. Commit 15e6cdd made filehandle methods load IO::File automagically. Commit efc5c7c attempted to solve the problem that having IO::Handle loaded causes IO::File to be bypassed, rendering 15e6cdd only semi-effective (see [perl #87940]), by requiring IO::File inside IO::Handle. That commit ended up breaking several CPAN modules, because IO::File adds @IO::Seekable::EXPORT to its own exports. If IO::Seekable is loaded first (before IO::File), before setting up its @EXPORT it loads IO::Handle, which loads IO::File, which tries to load IO::Seekable, which is in %INC already, and which is hence wait- ing for IO::File to load before it sets its own @EXPORT. So IO::File sees @IO::Seekable::EXPORT empty. Hence, every piece of code that tries to import SEEK_END from IO::File will simply not get it if IO::Seekable is already loaded (explicitly or, e.g., by File::Temp). This commit hopefully fixes the breakage and the problem that efc5c7c attempted to fix by loading IO::File only inside IO::Handle::new (the only method that IO::File overrides). --- MANIFEST | 1 + META.yml | 1 + dist/IO/lib/IO/Handle.pm | 19 ++++++++++++------- dist/IO/t/io_file_export.t | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 dist/IO/t/io_file_export.t diff --git a/MANIFEST b/MANIFEST index a28ada3..c804dea 100644 --- a/MANIFEST +++ b/MANIFEST @@ -3009,6 +3009,7 @@ dist/IO/README IO extension maintenance notice dist/IO/t/io_const.t See if constants from IO work dist/IO/t/io_dir.t See if directory-related methods from IO work dist/IO/t/io_dup.t See if dup()-related methods from IO work +dist/IO/t/io_file_export.t Test IO::File exports dist/IO/t/io_file.t See if binmode()-related methods on IO::File work dist/IO/t/io_linenum.t See if I/O line numbers are tracked correctly dist/IO/t/io_multihomed.t See if INET sockets work with multi-homed hosts diff --git a/META.yml b/META.yml index 4dc98fe..af1423f 100644 --- a/META.yml +++ b/META.yml @@ -77,6 +77,7 @@ no_index: - dist/IO/t/io_dir.t - dist/IO/t/io_dup.t - dist/IO/t/io_file.t + - dist/IO/t/io_file_export.t - dist/IO/t/io_linenum.t - dist/IO/t/io_multihomed.t - dist/IO/t/io_pipe.t diff --git a/dist/IO/lib/IO/Handle.pm b/dist/IO/lib/IO/Handle.pm index a7431fa..6ca3c8a 100644 --- a/dist/IO/lib/IO/Handle.pm +++ b/dist/IO/lib/IO/Handle.pm @@ -265,12 +265,6 @@ use Symbol; use SelectSaver; use IO (); # Load the XS module -# Since perl will automatically require IO::File if needed, but also -# initialises IO::File's @ISA as part of the core we must ensure -# IO::File is loaded if IO::Handle is. This avoids effectively -# "half-loading" IO::File. -require IO::File; - require Exporter; @ISA = qw(Exporter); @@ -315,7 +309,18 @@ $VERSION = eval $VERSION; sub new { my $class = ref($_[0]) || $_[0] || "IO::Handle"; - @_ == 1 or croak "usage: $class->new()"; + if (@_ != 1) { + # Since perl will automatically require IO::File if needed, but + # also initialises IO::File's @ISA as part of the core we must + # ensure IO::File is loaded if IO::Handle is. This avoids effect- + # ively "half-loading" IO::File. + if ($] > 5.013 && $class eq 'IO::File' && !$INC{"IO/File.pm"}) { + require IO::File; + shift; + return IO::File::->new(@_); + } + croak "usage: $class->new()"; + } my $io = gensym; bless $io, $class; } diff --git a/dist/IO/t/io_file_export.t b/dist/IO/t/io_file_export.t new file mode 100644 index 0000000..3d11990 --- /dev/null +++ b/dist/IO/t/io_file_export.t @@ -0,0 +1,18 @@ +#!./perl -w + +# This script checks that IO::File exports the SEEK* constants if +# IO::Seekable is loaded first, which was temporarily broken during 5.14 +# code freeze. See [perl #88486]. + +BEGIN{ + require($ENV{PERL_CORE} ? "../../t/test.pl" : "./t/test.pl"); + plan(tests => 3); +} + +use IO::Seekable (); # import nothing +use IO::File; # import defaults + +# No strict! +cmp_ok SEEK_END, 'ne', "SEEK_END", 'SEEK_END'; +cmp_ok SEEK_SET, 'ne', "SEEK_SET", 'SEEK_SET'; +cmp_ok SEEK_CUR, 'ne', "SEEK_CUR", 'SEEK_CUR'; -- 2.7.4