Subject: | Delegation to "import" breaks 'use My::Mech;' |
HTML::Element is the default element class, and implements an 'import'
method. WWW::Mechanize::TreeBuilder uses introspection to add
delegations for all Element methods that aren't implemented in the
composing class. It's quite common for composing classes to not
implement an 'import' method. This has the unfortunate effect of adding
an 'import' implementation that calls 'import' as an instance method on
the 'tree' attribute. This blows up with an unintuitive error message
whenever 'import' is called as a static method (eg. "use My::Mech;").
Can't use string ("My::Mech") as a HASH ref while "strict refs" in use
at reader My::Mech::tree (defined at
/opt/perl-5.14.2/lib/site_perl/5.14.2/WWW/Mechanize/TreeBuilder.pm line
167) line 5.
A simple test case is attached, along with a patch for
WWW-Mechhanize-TreeBuilder-1.10003 which explicitly prevents 'import'
from being delegated.
A work-around for existing code is to:
a) add an empty 'import' method to the composing class
b) always avoid calling 'import', eg. "use My::Mech ();"
Subject: | broken_import_delegation.t |
package My::Mech;
use Moose;
extends 'WWW::Mechanize';
with 'WWW::Mechanize::TreeBuilder';
package main;
use strict;
use warnings;
use Test::More tests => 1;
eval { My::Mech->import };
diag $@ if $@;
ok !$@, q{My::Mech->import() doesn't explode};
Subject: | fix_import_delegation.patch |
diff --git a/lib/WWW/Mechanize/TreeBuilder.pm b/lib/WWW/Mechanize/TreeBuilder.pm
index 891a352..d32b9b6 100644
--- a/lib/WWW/Mechanize/TreeBuilder.pm
+++ b/lib/WWW/Mechanize/TreeBuilder.pm
@@ -158,6 +158,9 @@ has 'tree' => (
my %methods = map { $_->name => 1
} $attr->associated_class->get_all_methods;
+
+ # Never delegate the 'import' method
+ $methods{import} = 1;
return
map { $_->name => $_->name }