diff -Nru libmojolicious-perl-9.31+dfsg/Changes libmojolicious-perl-9.33+dfsg/Changes --- libmojolicious-perl-9.31+dfsg/Changes 2022-12-21 00:34:34.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/Changes 2023-06-14 17:41:01.000000000 +0000 @@ -1,4 +1,15 @@ +9.33 2023-06-14 + - Improved log messages to refer to the FAQ when they have an entry. + - Fixed a bug where the prefork server could sometimes send redundant QUIT signals, which could result in unintended + core dumps because of a race condition. (brsakai-csco) + +9.32 2023-05-09 + - Improved file and line number details in async/await exceptions. (batman) + - Fixed various CSS selector equation bugs in Mojo::DOM::CSS. (mauke) + - Fixed exceptions being added to the stash for formats other than HTML. (rawleyfowler) + - Fixed context sensitivity issue. (Grinnz) + 9.31 2022-12-21 - This release contains fixes for security issues, everybody should upgrade! - Removed experimental status from links method in Mojo::Headers. diff -Nru libmojolicious-perl-9.31+dfsg/debian/changelog libmojolicious-perl-9.33+dfsg/debian/changelog --- libmojolicious-perl-9.31+dfsg/debian/changelog 2022-12-22 16:58:02.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/debian/changelog 2023-08-11 16:12:06.000000000 +0000 @@ -1,3 +1,11 @@ +libmojolicious-perl (9.33+dfsg-1) unstable; urgency=medium + + * Import upstream version 9.33+dfsg. + * Update years of upstream and packaging copyright. + * Drop unneeded version constraints from (build) dependencies. + + -- gregor herrmann Fri, 11 Aug 2023 18:12:06 +0200 + libmojolicious-perl (9.31+dfsg-1) unstable; urgency=medium * Import upstream version 9.31+dfsg. diff -Nru libmojolicious-perl-9.31+dfsg/debian/control libmojolicious-perl-9.33+dfsg/debian/control --- libmojolicious-perl-9.31+dfsg/debian/control 2022-12-22 16:58:02.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/debian/control 2023-08-11 16:12:06.000000000 +0000 @@ -12,7 +12,7 @@ Build-Depends-Indep: libcpan-meta-yaml-perl , libcpanel-json-xs-perl , libfuture-asyncawait-perl (>= 0.52) , - libio-socket-ip-perl (>= 0.39-3~) , + libio-socket-ip-perl , libjs-bootstrap4 , libjs-highlight.js , libjs-jquery , @@ -28,20 +28,19 @@ Architecture: all Depends: ${misc:Depends}, ${perl:Depends}, - libio-socket-ip-perl (>= 0.39-3~), + libio-socket-ip-perl, libjs-bootstrap4, libjs-highlight.js, libjs-jquery Recommends: libcpan-meta-yaml-perl, libcpanel-json-xs-perl, - libev-perl (>= 4.32), + libev-perl, libfuture-asyncawait-perl (>= 0.52), libio-socket-socks-perl, libio-socket-ssl-perl, libmojo-server-fastcgi-perl, librole-tiny-perl -Breaks: libmango-perl (<< 1.30-2~), - libmojolicious-plugin-openapi-perl (<< 4.04) +Breaks: libmojolicious-plugin-openapi-perl (<< 4.04) Description: simple, yet powerful, Web Application Framework Mojolicious is a Perl Web Application Framework built around the familiar Model-View-Controller philosophy. It supports a simple single file mode via diff -Nru libmojolicious-perl-9.31+dfsg/debian/copyright libmojolicious-perl-9.33+dfsg/debian/copyright --- libmojolicious-perl-9.31+dfsg/debian/copyright 2022-12-22 16:58:02.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/debian/copyright 2023-08-11 16:12:06.000000000 +0000 @@ -10,16 +10,16 @@ lib/Mojolicious/resources/public/mojo/bootstrap Files: * -Copyright: 2008-2022, Sebastian Riedel +Copyright: 2008-2023, Sebastian Riedel License: Artistic-2.0 Files: lib/Mojolicious/resources/public/mojo/* -Copyright: 2010-2022, Sebastian Riedel +Copyright: 2010-2023, Sebastian Riedel License: CC-BY-SA-4.0 Files: debian/* Copyright: 2010-2011, Jonathan Yu - 2010-2022, gregor herrmann + 2010-2023, gregor herrmann 2011, Angel Abad 2011, Fabrizio Regalli 2011-2012, Krzysztof Krzyżaniak (eloy) diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/DOM/CSS.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/DOM/CSS.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/DOM/CSS.pm 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/DOM/CSS.pm 2023-03-08 18:43:29.000000000 +0000 @@ -117,11 +117,8 @@ # ":nth-*" (with An+B notation) $args = _equation($args) if $name =~ /^nth-/; - # ":first-*" (rewrite to ":nth-*") - ($name, $args) = ("nth-$1", [0, 1]) if $name =~ /^first-(.+)$/; - - # ":last-*" (rewrite to ":nth-*") - ($name, $args) = ("nth-$name", [-1, 1]) if $name =~ /^last-/; + # ":first-*", ":last-*" (rewrite to ":nth-(last-)*") + ($name, $args) = ("nth-$+", [0, 1]) if $name =~ /^(?:first-(.+)|(last-.+))$/; push @$last, ['pc', $name, $args]; } @@ -144,7 +141,7 @@ return [0, 0] unless my $equation = shift; # "even" - return [2, 2] if $equation =~ /^\s*even\s*$/i; + return [2, 0] if $equation =~ /^\s*even\s*$/i; # "odd" return [2, 1] if $equation =~ /^\s*odd\s*$/i; @@ -241,13 +238,16 @@ if (ref $args) { my $type = $class eq 'nth-of-type' || $class eq 'nth-last-of-type' ? $current->[1] : undef; my @siblings = @{_siblings($current, $type)}; - @siblings = reverse @siblings if $class eq 'nth-last-child' || $class eq 'nth-last-of-type'; - + my $index; for my $i (0 .. $#siblings) { - next if (my $result = $args->[0] * $i + $args->[1]) < 1; - return undef unless my $sibling = $siblings[$result - 1]; - return 1 if $sibling eq $current; + $index = $i, last if $siblings[$i] eq $current; } + $index = $#siblings - $index if $class eq 'nth-last-child' || $class eq 'nth-last-of-type'; + $index++; + + my $delta = $index - $args->[1]; + return 1 if $delta == 0; + return $args->[0] != 0 && ($delta < 0) == ($args->[0] < 0) && $delta % $args->[0] == 0; } # Everything else diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/IOLoop/Client.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/IOLoop/Client.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/IOLoop/Client.pm 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/IOLoop/Client.pm 2023-04-27 20:33:00.000000000 +0000 @@ -10,13 +10,13 @@ use Socket qw(IPPROTO_TCP SOCK_STREAM TCP_NODELAY); # Non-blocking name resolution requires Net::DNS::Native -use constant NNR => $ENV{MOJO_NO_NNR} ? 0 : eval { require Net::DNS::Native; Net::DNS::Native->VERSION('0.15'); 1 }; +use constant NNR => $ENV{MOJO_NO_NNR} ? 0 : !!eval { require Net::DNS::Native; Net::DNS::Native->VERSION('0.15'); 1 }; my $NDN; # SOCKS support requires IO::Socket::Socks use constant SOCKS => $ENV{MOJO_NO_SOCKS} ? 0 - : eval { require IO::Socket::Socks; IO::Socket::Socks->VERSION('0.64'); 1 }; + : !!eval { require IO::Socket::Socks; IO::Socket::Socks->VERSION('0.64'); 1 }; use constant READ => SOCKS ? IO::Socket::Socks::SOCKS_WANT_READ() : 0; use constant WRITE => SOCKS ? IO::Socket::Socks::SOCKS_WANT_WRITE() : 0; diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/IOLoop/TLS.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/IOLoop/TLS.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/IOLoop/TLS.pm 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/IOLoop/TLS.pm 2023-04-27 20:33:00.000000000 +0000 @@ -6,7 +6,7 @@ use Scalar::Util qw(weaken); # TLS support requires IO::Socket::SSL -use constant TLS => $ENV{MOJO_NO_TLS} ? 0 : eval { require IO::Socket::SSL; IO::Socket::SSL->VERSION('2.009'); 1 }; +use constant TLS => $ENV{MOJO_NO_TLS} ? 0 : !!eval { require IO::Socket::SSL; IO::Socket::SSL->VERSION('2.009'); 1 }; use constant READ => TLS ? IO::Socket::SSL::SSL_WANT_READ() : 0; use constant WRITE => TLS ? IO::Socket::SSL::SSL_WANT_WRITE() : 0; diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/JSON.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/JSON.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/JSON.pm 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/JSON.pm 2023-04-27 20:33:00.000000000 +0000 @@ -10,7 +10,7 @@ # For better performance Cpanel::JSON::XS is required use constant JSON_XS => $ENV{MOJO_NO_JSON_XS} ? 0 - : eval { require Cpanel::JSON::XS; Cpanel::JSON::XS->VERSION('4.09'); 1 }; + : !!eval { require Cpanel::JSON::XS; Cpanel::JSON::XS->VERSION('4.09'); 1 }; our @EXPORT_OK = qw(decode_json encode_json false from_json j to_json true); @@ -49,7 +49,7 @@ sub j { return encode_json($_[0]) if ref $_[0] eq 'ARRAY' || ref $_[0] eq 'HASH'; - return eval { decode_json($_[0]) }; + return scalar eval { decode_json($_[0]) }; } sub to_json { _encode_value(shift) } diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/Promise.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/Promise.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/Promise.pm 2022-10-31 13:36:40.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/Promise.pm 2023-03-08 18:49:14.000000000 +0000 @@ -1,7 +1,7 @@ package Mojo::Promise; use Mojo::Base -base; -use Carp qw(carp); +use Carp qw(carp croak); use Mojo::Exception; use Mojo::IOLoop; use Scalar::Util qw(blessed); @@ -18,8 +18,9 @@ sub AWAIT_GET { my $self = shift; my @results = @{$self->{results} // []}; - die $results[0] unless $self->{status} eq 'resolve'; - return wantarray ? @results : $results[0]; + return wantarray ? @results : $results[0] if $self->{status} eq 'resolve'; + die $results[0] if ref $results[0] || $results[0] =~ m!\n!; + croak $results[0]; } sub AWAIT_IS_CANCELLED {undef} diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/Server/Daemon.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/Server/Daemon.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/Server/Daemon.pm 2022-12-10 17:55:56.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/Server/Daemon.pm 2023-05-15 09:23:01.000000000 +0000 @@ -200,7 +200,7 @@ $stream->on(close => sub { $self && $self->_close($id) }); $stream->on(error => sub { $self && $self->app->log->error(pop) && $self->_close($id) }); $stream->on(read => sub { $self->_read($id => pop) }); - $stream->on(timeout => sub { $self->_trace($id, 'Inactivity timeout') }); + $stream->on(timeout => sub { $self->_trace($id, 'Inactivity timeout (see FAQ for more)') }); } ); diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/Server/Prefork.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/Server/Prefork.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/Server/Prefork.pm 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/Server/Prefork.pm 2023-06-14 17:38:31.000000000 +0000 @@ -110,7 +110,7 @@ next unless my $w = $self->{pool}{$pid}; # No heartbeat (graceful stop) - $log->error("Worker $pid has no heartbeat ($ht seconds), restarting") and $w->{graceful} = $time + $log->error("Worker $pid has no heartbeat ($ht seconds), restarting (see FAQ for more)") and $w->{graceful} = $time if !$w->{graceful} && ($w->{time} + $interval + $ht <= $time); # Graceful stop with timeout @@ -181,7 +181,10 @@ while ($chunk =~ /(\d+):(\d)\n/g) { next unless my $w = $self->{pool}{$1}; @$w{qw(healthy time)} = (1, $time) and $self->emit(heartbeat => $1); - $w->{graceful} ||= $time if $2; + if ($2) { + $w->{graceful} ||= $time; + $w->{quit}++; + } } } diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojo/Util.pm libmojolicious-perl-9.33+dfsg/lib/Mojo/Util.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojo/Util.pm 2022-11-23 00:28:59.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojo/Util.pm 2023-04-27 20:33:00.000000000 +0000 @@ -22,7 +22,7 @@ use Unicode::Normalize (); # Check for monotonic clock support -use constant MONOTONIC => eval { !!Time::HiRes::clock_gettime(Time::HiRes::CLOCK_MONOTONIC()) }; +use constant MONOTONIC => !!eval { Time::HiRes::clock_gettime(Time::HiRes::CLOCK_MONOTONIC()) }; # Punycode bootstring parameters use constant { diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Guides/Cookbook.pod libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Guides/Cookbook.pod --- libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Guides/Cookbook.pod 2022-12-10 17:55:56.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Guides/Cookbook.pod 2023-02-01 20:11:01.000000000 +0000 @@ -1799,10 +1799,10 @@ $self->renderer->paths->[0] = $self->home->child('templates'); # Exclude author commands - $self->commands->namespaces(['Mojolicious::Commands']); + $self->commands->namespaces(['Mojolicious::Command']); my $r = $self->routes; - $r->get('/welcome')->to('example#welcome'); + $r->get('/')->to('example#welcome'); } 1; diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Guides/Routing.pod libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Guides/Routing.pod --- libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Guides/Routing.pod 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Guides/Routing.pod 2023-04-27 20:33:00.000000000 +0000 @@ -256,6 +256,10 @@ $self->stash(mymessage => 'Welcome'); } +You can use L to set default stash values that will be available everywhere in the application. + + $app->defaults(mymessage => 'Howdy'); + For a full list of reserved stash values see L. =head2 Nested routes diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Plugin/DefaultHelpers.pm libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Plugin/DefaultHelpers.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojolicious/Plugin/DefaultHelpers.pm 2022-09-10 15:04:08.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojolicious/Plugin/DefaultHelpers.pm 2023-05-08 22:06:24.000000000 +0000 @@ -90,6 +90,11 @@ return Mojo::ByteStream->new($hash->{$name} // ''); } +sub _convert_to_exception { + my $e = shift; + return (blessed $e && $e->isa('Mojo::Exception')) ? $e : Mojo::Exception->new($e); +} + sub _csrf_token { $_[0]->session->{csrf_token} ||= hmac_sha1_sum($$ . steady_time . rand, $_[0]->app->secrets->[0]) } sub _current_route { @@ -100,7 +105,7 @@ sub _development { my ($page, $c, $e) = @_; - $c->helpers->log->error(($e = _is_e($e) ? $e : Mojo::Exception->new($e))->inspect) if $page eq 'exception'; + $c->helpers->log->error(($e = _convert_to_exception($e))->inspect) if $page eq 'exception'; # Filtered stash snapshot my $stash = $c->stash; @@ -187,8 +192,6 @@ return $c; } -sub _is_e { blessed $_[0] && $_[0]->isa('Mojo::Exception') } - sub _is_fresh { my ($c, %options) = @_; return $c->app->static->is_fresh($c, \%options); @@ -196,6 +199,7 @@ sub _json_exception { my ($c, $e) = @_; + $c->stash->{exception} = _convert_to_exception($e); return $c->render(json => {error => $e}, status => 500) if $c->app->mode eq 'development'; return $c->render(json => {error => 'Internal Server Error'}, status => 500); } @@ -242,9 +246,7 @@ } ); - # Unknown length (fall back to connection close) - $source_res->once(finish => sub { $content->$write('') and $tx->resume }) - unless length($headers->content_length // ''); + $source_res->once(finish => sub { $content->$write('') and $tx->resume }); } ); weaken $source_tx; @@ -317,6 +319,7 @@ sub _txt_exception { my ($c, $e) = @_; + $c->stash->{exception} = _convert_to_exception($e); return $c->render(text => $e, format => 'txt', status => 500) if $c->app->mode eq 'development'; return $c->render(text => 'Internal Server Error', format => 'txt', status => 500); } diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojolicious/resources/templates/mojo/debug.html.ep libmojolicious-perl-9.33+dfsg/lib/Mojolicious/resources/templates/mojo/debug.html.ep --- libmojolicious-perl-9.31+dfsg/lib/Mojolicious/resources/templates/mojo/debug.html.ep 2022-12-18 19:20:49.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojolicious/resources/templates/mojo/debug.html.ep 2023-04-27 22:37:27.000000000 +0000 @@ -306,7 +306,7 @@ Free and Open Source.
- 2008-2022 Sebastian Riedel and the + 2008-2023 Sebastian Riedel and the Mojolicious contributors.
diff -Nru libmojolicious-perl-9.31+dfsg/lib/Mojolicious.pm libmojolicious-perl-9.33+dfsg/lib/Mojolicious.pm --- libmojolicious-perl-9.31+dfsg/lib/Mojolicious.pm 2022-12-21 00:30:55.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/lib/Mojolicious.pm 2023-05-15 09:22:06.000000000 +0000 @@ -45,7 +45,7 @@ my $self = shift; # Warn developers about insecure default - $self->log->trace('Your secret passphrase needs to be changed'); + $self->log->trace('Your secret passphrase needs to be changed (see FAQ for more)'); # Default to moniker return [$self->moniker]; @@ -57,7 +57,7 @@ has validator => sub { Mojolicious::Validator->new }; our $CODENAME = 'Waffle'; -our $VERSION = '9.31'; +our $VERSION = '9.33'; sub BUILD_DYNAMIC { my ($class, $method, $dyn_methods) = @_; @@ -141,7 +141,8 @@ $self->plugins->emit_chain(around_dispatch => $c); # Delayed response - $c->helpers->log->trace('Nothing has been rendered, expecting delayed response') unless $c->stash->{'mojo.rendered'}; + $c->helpers->log->trace('Nothing has been rendered, expecting delayed response (see FAQ for more)') + unless $c->stash->{'mojo.rendered'}; } sub helper { shift->renderer->add_helper(@_) } @@ -752,7 +753,7 @@ =head2 Mojolicious Artwork - Copyright (C) 2010-2022, Sebastian Riedel. + Copyright (C) 2010-2023, Sebastian Riedel. Licensed under the CC-SA License, Version 4.0 L. @@ -1030,6 +1031,8 @@ Leon Brocard +Lukas Mai + Magnus Holm Maik Fischer @@ -1100,6 +1103,8 @@ Randal Schwartz +Rawley Fowler + Richard Elberger Rick Delaney @@ -1192,7 +1197,7 @@ =head1 COPYRIGHT AND LICENSE -Copyright (C) 2008-2022, Sebastian Riedel and others. +Copyright (C) 2008-2023, Sebastian Riedel and others. This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0. diff -Nru libmojolicious-perl-9.31+dfsg/META.json libmojolicious-perl-9.33+dfsg/META.json --- libmojolicious-perl-9.31+dfsg/META.json 2022-12-21 00:35:27.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/META.json 2023-06-14 19:25:30.000000000 +0000 @@ -64,6 +64,6 @@ "web" : "https://web.libera.chat/#mojo" } }, - "version" : "9.31", + "version" : "9.33", "x_serialization_backend" : "JSON::PP version 4.07" } diff -Nru libmojolicious-perl-9.31+dfsg/META.yml libmojolicious-perl-9.33+dfsg/META.yml --- libmojolicious-perl-9.31+dfsg/META.yml 2022-12-21 00:35:27.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/META.yml 2023-06-14 19:25:30.000000000 +0000 @@ -35,5 +35,5 @@ homepage: https://mojolicious.org license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/mojolicious/mojo.git -version: '9.31' +version: '9.33' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -Nru libmojolicious-perl-9.31+dfsg/t/mojo/dom.t libmojolicious-perl-9.33+dfsg/t/mojo/dom.t --- libmojolicious-perl-9.31+dfsg/t/mojo/dom.t 2022-12-10 22:30:41.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/t/mojo/dom.t 2023-03-08 18:43:33.000000000 +0000 @@ -1040,28 +1040,28 @@ is_deeply \@li, ['F'], 'found third last li element'; @li = (); $dom->find('li:nth-child(1n+0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(1n-0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(n+0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(n)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(n+0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:NTH-CHILD(N+0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:Nth-Child(N+0)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(n)')->each(sub { push @li, shift->text }); - is_deeply \@li, [qw(A B C D E F G)], 'found all li elements'; + is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements'; @li = (); $dom->find('li:nth-child(0n+1)')->each(sub { push @li, shift->text }); is_deeply \@li, [qw(A)], 'found first li element'; @@ -1102,19 +1102,19 @@ is_deeply \@e, [qw(A E H)], 'found all odd li elements'; @e = (); $dom->find('ul li:not(:first-child, :last-child)')->each(sub { push @e, shift->text }); - is_deeply \@e, [qw(C E F H)], 'found all odd li elements'; + is_deeply \@e, [qw(C E F H)], 'found all li elements but first/last'; @e = (); $dom->find('ul li:is(:first-child, :last-child)')->each(sub { push @e, shift->text }); - is_deeply \@e, [qw(A I)], 'found all odd li elements'; + is_deeply \@e, [qw(A I)], 'found first/last li elements'; @e = (); $dom->find('li:nth-last-of-type( odd )')->each(sub { push @e, shift->text }); - is_deeply \@e, [qw(C F I)], 'found all odd li elements'; + is_deeply \@e, [qw(C F I)], 'found all odd li elements (counting from end)'; @e = (); $dom->find('p:nth-of-type(odd)')->each(sub { push @e, shift->text }); is_deeply \@e, [qw(B G)], 'found all odd p elements'; @e = (); $dom->find('p:nth-last-of-type(odd)')->each(sub { push @e, shift->text }); - is_deeply \@e, [qw(B G)], 'found all odd li elements'; + is_deeply \@e, [qw(B G)], 'found all odd p elements (counting from end)'; @e = (); $dom->find('ul :nth-child(1)')->each(sub { push @e, shift->text }); is_deeply \@e, ['A'], 'found first child'; @@ -1193,6 +1193,9 @@ @e = (); $dom->find('div div:only-of-type')->each(sub { push @e, shift->text }); is_deeply \@e, [qw(J K)], 'found only child'; + @e = (); + $dom->find('div :nth-child(-n+2)')->each(sub { push @e, shift->text }); + is_deeply \@e, [qw(J Mojo! K)], 'found first two children of each div'; }; subtest 'Links' => sub { diff -Nru libmojolicious-perl-9.31+dfsg/t/mojo/promise_async_await.t libmojolicious-perl-9.33+dfsg/t/mojo/promise_async_await.t --- libmojolicious-perl-9.31+dfsg/t/mojo/promise_async_await.t 2022-10-31 13:36:40.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/t/mojo/promise_async_await.t 2023-03-08 18:49:14.000000000 +0000 @@ -137,6 +137,12 @@ $t->get_ok('/four')->status_is(500)->content_like(qr/this went perfectly/); }; +subtest 'Exception handling with file and line reporting' => sub { + my $error; + reject_p()->catch(sub { $error = shift })->wait; + like $error, qr/^Rejected promise at .*promise_async_await\.t line \d+\.$/, 'right content'; +}; + subtest 'Exception handling without "Unhandled rejected promise" warning' => sub { my ($error, @warn); local $SIG{__WARN__} = sub { push @warn, $_[0] }; diff -Nru libmojolicious-perl-9.31+dfsg/t/mojolicious/exception_lite_app.t libmojolicious-perl-9.33+dfsg/t/mojolicious/exception_lite_app.t --- libmojolicious-perl-9.31+dfsg/t/mojolicious/exception_lite_app.t 2022-09-10 15:28:46.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/t/mojolicious/exception_lite_app.t 2023-05-08 22:06:24.000000000 +0000 @@ -302,9 +302,12 @@ ->json_like('/error', qr/dead template!/); $t->get_ok('/does_not_exist')->status_is(404)->content_type_is('application/json;charset=UTF-8') ->json_is({error => 'Not Found'}); - + my $stash; + $t->app->hook(after_dispatch => sub { $stash = shift->stash }); $t->get_ok('/txt/exception')->status_is(500)->header_is('X-Text' => 'txt') ->content_type_is('text/plain;charset=UTF-8')->content_like(qr/Text exception/); + ok $stash->{exception}, 'exception exists in stash'; + isa_ok $stash->{exception}, 'Mojo::Exception', 'is stash exception correct type?'; $t->app->mode('production'); $t->get_ok('/dead_template')->status_is(500)->content_type_is('application/json;charset=UTF-8') @@ -319,9 +322,12 @@ $t->get_ok('/dead_template')->status_is(500)->content_type_is('text/plain;charset=UTF-8') ->content_like(qr/dead template!/); $t->get_ok('/does_not_exist')->status_is(404)->content_type_is('text/plain;charset=UTF-8')->content_is('Not Found'); - + my $stash; + $t->app->hook(after_dispatch => sub { $stash = shift->stash }); $t->get_ok('/txt/exception')->status_is(500)->header_is('X-Text' => 'txt') ->content_type_is('text/plain;charset=UTF-8')->content_like(qr/Text exception/); + ok $stash->{exception}, 'exception exists in stash'; + isa_ok $stash->{exception}, 'Mojo::Exception', 'is stash exception correct type?'; $t->app->mode('production'); $t->get_ok('/dead_template')->status_is(500)->content_type_is('text/plain;charset=UTF-8') diff -Nru libmojolicious-perl-9.31+dfsg/t/mojolicious/proxy_app.t libmojolicious-perl-9.33+dfsg/t/mojolicious/proxy_app.t --- libmojolicious-perl-9.31+dfsg/t/mojolicious/proxy_app.t 2022-06-14 11:31:51.000000000 +0000 +++ libmojolicious-perl-9.33+dfsg/t/mojolicious/proxy_app.t 2023-03-08 18:43:37.000000000 +0000 @@ -17,6 +17,26 @@ my $url = Mojo::URL->new("http://127.0.0.1:$port"); my $r = $app->routes; $r->get( + '/size/:code/:length' => {code => 204, length => 0} => sub { + my $c = shift; + my $code = $c->param('code'); + my $length = $c->param('length'); + $c->res->headers->header('X-Mojo-App' => 'Size'); + $c->render(data => 'x' x $length, status => $code); + } +)->name('size'); +$r->get( + '/redirect/:code1/:code2/:length' => {code1 => 302, code2 => 204, length => 0} => sub { + my $c = shift; + my $code1 = $c->param('code1'); + my $code2 = $c->param('code2'); + my $length = $c->param('length'); + $c->res->headers->header('X-Mojo-App' => 'Redirect'); + $c->res->code($code1); + $c->redirect_to($c->url_for('size', {code => $code2, length => $length})->to_abs); + } +)->name('redirect'); +$r->get( '/res1' => sub { my $c = shift; $c->res->headers->header('X-Mojo-App' => 'One'); @@ -69,7 +89,7 @@ get '/proxy1/*target' => sub { my $c = shift; my $target = $c->stash('target'); - $c->proxy->get_p($url->path($target))->catch(sub { + $c->proxy->get_p($url->clone->path($target))->catch(sub { my $err = shift; $c->render(text => "Error: $err", status => 400); }); @@ -102,6 +122,32 @@ my $t = Test::Mojo->new; subtest 'Various response variants' => sub { + $t->get_ok('/proxy1/size/200/2')->status_is(200)->header_is('X-Mojo-App' => 'Size')->header_is('Content-Length' => 2) + ->content_is('xx'); + $t->get_ok('/proxy1/size/200/1')->status_is(200)->header_is('X-Mojo-App' => 'Size')->header_is('Content-Length' => 1) + ->content_is('x'); + $t->get_ok('/proxy1/size/200/0')->status_is(200)->header_is('X-Mojo-App' => 'Size')->header_is('Content-Length' => 0) + ->content_is(''); + $t->get_ok('/proxy1/size/204/0')->status_is(204)->header_is('X-Mojo-App' => 'Size') + ->header_is('Content-Length' => undef)->content_is(''); + $t->get_ok('/proxy1/redirect/304/200/1')->status_is(304)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => undef)->content_is(''); + $t->get_ok('/proxy1/redirect/302/200/1')->status_is(302)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); + $t->get_ok('/proxy1/redirect/301/200/1')->status_is(301)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); + $t->get_ok('/proxy1/redirect/304/200/0')->status_is(304)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => undef)->content_is(''); + $t->get_ok('/proxy1/redirect/302/200/0')->status_is(302)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); + $t->get_ok('/proxy1/redirect/301/200/0')->status_is(301)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); + $t->get_ok('/proxy1/redirect/304/204/0')->status_is(304)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => undef)->content_is(''); + $t->get_ok('/proxy1/redirect/302/204/0')->status_is(302)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); + $t->get_ok('/proxy1/redirect/301/204/0')->status_is(301)->header_is('X-Mojo-App' => 'Redirect') + ->header_is('Content-Length' => 0)->content_is(''); $t->get_ok('/proxy1/res1')->status_is(200)->header_is('X-Mojo-App' => 'One')->content_is('One!'); $t->get_ok('/proxy1/res2')->status_is(200)->header_is('X-Mojo-App' => 'Two')->content_is('Two!'); $t->get_ok('/proxy1/res3')->status_is(200)->header_is('X-Mojo-App' => 'Three')->header_is('X-Mojo-Method' => 'GET')