several years now, but I think I've finally nailed it.
EmbperlObject.pm has code to modify the @ISA variable in a package to
make it a base class of a particular document. It executes that code
if the @ISA array is empty. BUT certain combinations of recursive
Execute({ isa => ... }) commands can create a situation where a
document already has an @ISA, but *doesn't* inherit from the class
being added. How it got that way took me a bit longer.
Here's the sequence that reliably triggered the error.
My object_base is Template.html.
HTML::Embperl::Execute got called by EmbperlObject.pm(277) with Template.html
Template.html did an Execute({object => '*', import => 0}) which
executed HTML::Embperl::Execute on index.html from
EmbperlObject.pm(294).
index.html did an Execute({isa => 'tools.epl', import => 0}). That
called HTML::Embperl::Execute directly.
tools.epl did an Execute({isa => 'SiteInit.html', input => 0}). That
called HTML::Embperl::Execute directly.
SiteInit.html did an isa on help.html.
Now HTML::EmbperlObject called HTML::Execute on Template.html from
line 314. It wanted to bless the HTML::Embperl::Req as an
HTML::Embperl::DOC::_2 (index.html), but that already has an ISA that
referenced an HTML::Embperl::DOC::_3 (tools.epl), and that has an ISA
that referenced an HTML::Embperl::DOC::_4 (SiteInit.html) and so on.
Nobody there references DOC::_1 (Template.html). And DOC::_1 is the
only one that ISA HTML::Empberl::Req.
Initially I fixed half the problem, but there are two places where
EmbperlObject sets the ISA, and they are both wrong. The first case
sets up the request handler parent (usually HTML::Embperl::Req). It
turns out that the way it does this means that your template calls
Execute({ isa => ... }) you will either lose the isa, or overwrite
the inheritance of the request class. In general multiple
inheritance isn't working.
The right solution seems to be just to call UNIVERSAL::isa and *add*
the new class to @ISA.
As a side effect this gives me something I have been wanting for a
long time but could never get to work. Your Embperl template can
isa=> load helper files and (because '*' inherits from the template)
the referenced file will automatically pick up the inheritance.
Template.html
Execute({isa => 'helper.epl', import => 0});
Execute('*');
* is now a helper.epl
I actually structure my templates differently, making them nothing
but subroutines:
$page = Execute({ object => '*', import => 0 });
so that I can then scatter calls to
$page->title()
and the like throughout the Template. But those pages always had to
execute the same base files over and over--now they don't.
I'm pretty sure this is the right patch, but I'd like feedback.
Also, I'm not sure whether the right approach is to use "push" or
"unshift". As I did it, it looks like the first @isa in the template
is the first on the stack, and the Req object is last. The latter
sounds right, I'm not sure about the former.
*** EmbperlObject.pm Sat Sep 1 17:31:10 2001
--- /Library/Perl/darwin/HTML/EmbperlObject.pm Fri Nov 28 15:14:45 2003
***************
*** 281,289 ****
#use strict ;
}
no strict ;
! if (!@{"$basepackage\:\:ISA"})
{
! @{"$basepackage\:\:ISA"} = ($req -> {object_handler_class} || 'HTML::Embperl::Req') ;
}
use strict ;
--- 281,290 ----
#use strict ;
}
no strict ;
! my $reqclass = $req -> {object_handler_class} || 'HTML::Embperl::Req';
! if (!UNIVERSAL::isa($basepackage, $reqclass))
{
! push(@{"$basepackage\:\:ISA"}, $reqclass);
}
use strict ;
***************
*** 301,309 ****
}
no strict ;
! if (!@{"$package\:\:ISA"})
{
! @{"$package\:\:ISA"} = ($basepackage) if ($package ne $basepackage) ;
}
use strict ;
--- 302,310 ----
}
no strict ;
! if (!UNIVERSAL::isa($package, $basepackage))
{
! push(@{"$package\:\:ISA"}, $basepackage);
}
use strict ;
--
Kee Hinckley
http://www.messagefire.com/ Next Generation Spam Defense
http://commons.somewhere.com/buzz/ Writings on Technology and Society
I'm not sure which upsets me more: that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.
---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org