diff --git a/Expat/Expat.pm b/Expat/Expat.pm index 04ded31..fa19ab6 100644 --- a/Expat/Expat.pm +++ b/Expat/Expat.pm @@ -314,7 +314,7 @@ sub expand_ns_prefix { return ( defined($stack) and @$stack ) ? $stack->[-1] : undef; } - return undef; + return; } sub current_ns_prefixes { @@ -676,7 +676,7 @@ sub children { if ( defined $children ) { return @$children; } - return undef; + return; } sub asString { diff --git a/t/return_undef_list_context.t b/t/return_undef_list_context.t new file mode 100644 index 0000000..f35330c --- /dev/null +++ b/t/return_undef_list_context.t @@ -0,0 +1,63 @@ +use strict; +use warnings; + +use Test::More tests => 6; +use XML::Parser; + +# ContentModel::children() should return an empty list when there are +# no children (EMPTY/ANY models), not (undef). Using "return undef" +# in a list-returning method is a classic Perl footgun: it produces a +# one-element list containing undef instead of an empty list. +# +# This means code like: +# my @kids = $model->children; +# if (@kids) { ... } # incorrectly true for EMPTY models +# would silently process undef as a child element. + +my %models; + +my $p = XML::Parser->new( + Handlers => { + Element => sub { $models{ $_[1] } = $_[2] }, + }, +); + +$p->parse(<<'XML'); + + + + +]> + +XML + +# EMPTY model has no children +{ + my $m = $models{empty}; + ok( $m->isempty, 'EMPTY model detected' ); + + my @kids = $m->children; + is( scalar @kids, 0, + 'children() returns empty list for EMPTY model' ); +} + +# ANY model has no children +{ + my $m = $models{any}; + ok( $m->isany, 'ANY model detected' ); + + my @kids = $m->children; + is( scalar @kids, 0, + 'children() returns empty list for ANY model' ); +} + +# SEQ model has children — should still work +{ + my $m = $models{seq}; + ok( $m->isseq, 'SEQ model detected' ); + + my @kids = $m->children; + is( scalar @kids, 2, + 'children() returns correct count for SEQ model' ); +}