You are viewing a plain text version of this content. The canonical link for it is here.
Posted to embperl@perl.apache.org by Kee Hinckley <na...@somewhere.com> on 2003/11/28 21:33:47 UTC

HTML::EmbperlObject and @ISA corrupted HTML::Embperl::Req...

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


Re: HTML::EmbperlObject and @ISA corrupted HTML::Embperl::Req...

Posted by Gerald Richter <ri...@ecos.de>.
Hi Kee,

>
> 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.

After looking over your patch, it seems to me that is really doing the right
thing. Also using push seems to be ok to me.

Thanks very much for nailing this down! I will will put it into 2.0 and if
there will be another 1.3.x release the patch will be in it also. I think
the "ISA corrupted" check must be adapted also to avoid the warning. I will
take a look at it.

Gerald


--------------------------------------------------------------
Gerald Richter     ecos electronic communication services gmbh
IT-Securitylösungen * dynamische Webapplikationen * Consulting

Post:       Tulpenstrasse 5          D-55276 Dienheim b. Mainz
E-Mail:     richter@ecos.de          Voice:   +49 6133 939-122
WWW:        http://www.ecos.de/      Fax:     +49 6133 939-333
--------------------------------------------------------------
|
|   ECOS BB-5000 Firewall- und IT-Security Appliance: www.bb-5000.info
|
+-------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe@perl.apache.org
For additional commands, e-mail: embperl-help@perl.apache.org