diff -ru perl5.004_04.dist/sv.c perl5.004_04/sv.c --- perl5.004_04.dist/sv.c Mon Oct 6 13:03:36 1997 +++ perl5.004_04/sv.c Mon Dec 29 11:14:17 1997 @@ -2671,15 +2671,18 @@ if (defstash) { /* Still have a symbol table? */ dSP; GV* destructor; + HV* class; ENTER; SAVEFREESV(SvSTASH(sv)); - destructor = gv_fetchmethod(SvSTASH(sv), "DESTROY"); + class = SvSTASH(sv); + destructor = gv_fetchmethod(class, "DESTROY"); if (destructor) { SV ref; + SV *super; - Zero(&ref, 1, SV); + Zero(&ref, 1, SV); sv_upgrade(&ref, SVt_RV); SvRV(&ref) = SvREFCNT_inc(sv); SvROK_on(&ref); @@ -2687,12 +2690,29 @@ creating+destructing a ref leads to disaster. */ - EXTEND(SP, 2); - PUSHMARK(SP); - PUSHs(&ref); - PUTBACK; - perl_call_sv((SV*)GvCV(destructor), - G_DISCARD|G_EVAL|G_KEEPERR); + class = GvSTASH(destructor); + super = sv_2mortal(newSVpvf("%s::SUPER::DESTROY", + HvNAME(class))); + + while (destructor) { + /* sv_dump((SV *) destructor); */ + + EXTEND(SP, 2); + PUSHMARK(SP); + PUSHs(&ref); + PUTBACK; + perl_call_sv((SV*)GvCV(destructor), + G_DISCARD|G_EVAL|G_KEEPERR); + + destructor = gv_fetchmethod(class, SvPVX(super)); + + if (destructor) { + class = GvSTASH(destructor); + sv_setpvf(super, "%s::SUPER::DESTROY", + HvNAME(class)); + } + } + del_XRV(SvANY(&ref)); SvREFCNT(sv)--; } diff -ru perl5.004_04.dist/t/op/ref.t perl5.004_04/t/op/ref.t --- perl5.004_04.dist/t/op/ref.t Fri Sep 19 09:00:07 1997 +++ perl5.004_04/t/op/ref.t Mon Dec 29 10:22:51 1997 @@ -1,6 +1,6 @@ #!./perl -print "1..51\n"; +print "1..56\n"; # Test glob operations. @@ -223,20 +223,65 @@ print "# left block\n"; +# test for recursive DESTROY +package main; + +sub ClassA::DESTROY { print "# ClassA\nok ", $_[0][0] + 2, "\n" } +sub ClassB::DESTROY { print "# ClassB\nok ", $_[0][0] + 1, "\n" } +sub ClassC::DESTROY { print "# ClassC\nok $_[0][0]\n" } + +@ClassC::ISA = 'ClassB'; +@ClassB::ISA = 'ClassA'; + +{ + my $obj = bless [ 48 ], 'ClassC'; + 1; +} + +## make sure we walk the ISA graph properly +## classes marked with a star have DESTROY methods +# +# *A +# \ +# B *C +# \/ +# *D *E +# \/ +# Start +# +# Expect D -> A + +package main; + +@Start::ISA = ('D', 'E'); +@D::ISA = ('B', 'C'); +@B::ISA = ('A'); + +sub E::DESTROY { print "# E\nnot ok ", $_[0][0], "\n" } +sub D::DESTROY { print "# D\nok ", $_[0][0], "\n" } + +sub C::DESTROY { print "# C\nnot ok ", $_[0][0] + 1, "\n" } +sub A::DESTROY { print "# A\nok ", $_[0][0] + 1, "\n" } + +{ + my $obj = bless [ 51 ], 'Start'; + 1; +} + # another glob test -$foo = "not ok 48"; +$foo = "not ok 53"; { local(*bar) = "foo" } -$bar = "ok 48"; +$bar = "ok 53"; local(*bar) = *bar; print "$bar\n"; package FINALE; { - $ref3 = bless ["ok 51\n"]; # package destruction - my $ref2 = bless ["ok 50\n"]; # lexical destruction - local $ref1 = bless ["ok 49\n"]; # dynamic destruction + $ref3 = bless ["ok 56\n"]; # package destruction + my $ref2 = bless ["ok 55\n"]; # lexical destruction + local $ref1 = bless ["ok 54\n"]; # dynamic destruction 1; # flush any temp values on stack }