perl-embperl mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kee Hinckley <naz...@somewhere.com>
Subject HTML::EmbperlObject and @ISA corrupted HTML::Embperl::Req...
Date Fri, 28 Nov 2003 20:33:47 GMT
The "@ISA corrupted" error has been the bane of my existence for 
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


Mime
View raw message