From cd395e0a5d575d2d9d4ca7f34b3e8ae6ddf3db4a Mon Sep 17 00:00:00 2001 From: Vadim Belman Date: Tue, 5 Jan 2016 20:51:53 -0500 Subject: [PATCH] Item13897: Fixes of problems. - Added 'last resort' try/catch in Engine::CGI to display lost exceptions. - Moo-fied Foswiki::If::Parser, Foswiki::Query::Parser. - Changed 'isa' to 'is' in some 'has' clauses (no good of typing faster than thinking :) ). --- core/lib/Foswiki/Engine/CGI.pm | 20 +++++++++++-- core/lib/Foswiki/If/Parser.pm | 20 ++++++------- core/lib/Foswiki/Infix/Error.pm | 4 +-- core/lib/Foswiki/Infix/Node.pm | 4 +-- core/lib/Foswiki/Infix/Parser.pm | 49 ++++++++++++++++---------------- core/lib/Foswiki/Query/Parser.pm | 25 ++++++++++------ 6 files changed, 72 insertions(+), 50 deletions(-) diff --git a/core/lib/Foswiki/Engine/CGI.pm b/core/lib/Foswiki/Engine/CGI.pm index 8f952ffb4d..3bcdb85c5f 100644 --- a/core/lib/Foswiki/Engine/CGI.pm +++ b/core/lib/Foswiki/Engine/CGI.pm @@ -16,6 +16,8 @@ use strict; use warnings; use CGI; +use CGI::Carp; +use Data::Dumper; use Foswiki::Engine (); our @ISA = ('Foswiki::Engine'); @@ -25,6 +27,7 @@ use Foswiki::Request (); use Foswiki::Request::Upload (); use Foswiki::Response (); use Unicode::Normalize; +use Try::Tiny; BEGIN { if ( $Foswiki::cfg{UseLocale} ) { @@ -97,8 +100,21 @@ sub run { exit 1; } if ( UNIVERSAL::isa( $req, 'Foswiki::Request' ) ) { - my $res = Foswiki::UI::handleRequest($req); - $this->finalize( $res, $req ); + try { + my $res = Foswiki::UI::handleRequest($req); + $this->finalize( $res, $req ); + } + catch { +# Whatever error we get here – we generate valid HTTP response. At least we try... +# This is the last frontier of error handling. +# SMELL XXX Test code. + + # untie of the handles is required when remote debugging is used. + untie(*STDOUT) if tied(*STDOUT); + untie(*STDERR) if tied(*STDERR); + + CGI::Carp::confess( $_->{-text} ); + }; } } diff --git a/core/lib/Foswiki/If/Parser.pm b/core/lib/Foswiki/If/Parser.pm index a98e242e88..dcfe0c81fb 100644 --- a/core/lib/Foswiki/If/Parser.pm +++ b/core/lib/Foswiki/If/Parser.pm @@ -10,12 +10,6 @@ Support for the conditions in %IF{} statements. package Foswiki::If::Parser; -use strict; -use warnings; - -use Foswiki::Query::Parser (); -our @ISA = ('Foswiki::Query::Parser'); - use Assert; use Foswiki::If::Node (); @@ -28,6 +22,11 @@ use Foswiki::If::OP_isempty (); use Foswiki::If::OP_istopic (); use Foswiki::If::OP_isweb (); +use Moo; +use namespace::clean; + +extends 'Foswiki::Query::Parser'; + BEGIN { if ( $Foswiki::cfg{UseLocale} ) { require locale; @@ -40,16 +39,15 @@ BEGIN { use constant OPS => qw(allows context defined dollar ingroup isempty istopic isweb ); -sub new { - my ($class) = @_; +sub BUILD { + my $this = shift; + + $this->nodeClass('Foswiki::If::Node'); - my $this = $class->SUPER::new( { nodeClass => 'Foswiki::If::Node', } ); foreach my $op ( OPS() ) { my $on = 'Foswiki::If::OP_' . $op; $this->addOperator( $on->new() ); } - - return $this; } 1; diff --git a/core/lib/Foswiki/Infix/Error.pm b/core/lib/Foswiki/Infix/Error.pm index 5a7be2af29..f9a29de40d 100644 --- a/core/lib/Foswiki/Infix/Error.pm +++ b/core/lib/Foswiki/Infix/Error.pm @@ -15,11 +15,11 @@ use namespace::clean; extends 'Foswiki::Exception'; has expr => ( - is => 'ro', + is => 'rw', predicate => 1, ); has at => ( - is => 'ro', + is => 'rw', predicate => 1, ); our @_newParameters = qw(text expr at); diff --git a/core/lib/Foswiki/Infix/Node.pm b/core/lib/Foswiki/Infix/Node.pm index 3545deb45d..797c138de3 100644 --- a/core/lib/Foswiki/Infix/Node.pm +++ b/core/lib/Foswiki/Infix/Node.pm @@ -37,9 +37,9 @@ use constant { META => 5, }; -has op => ( isa => 'rw', ); +has op => ( is => 'rw', ); -has params => ( isa => 'rw', ); +has params => ( is => 'rw', ); =begin TML diff --git a/core/lib/Foswiki/Infix/Parser.pm b/core/lib/Foswiki/Infix/Parser.pm index 0ec17790d1..a6f9db1220 100644 --- a/core/lib/Foswiki/Infix/Parser.pm +++ b/core/lib/Foswiki/Infix/Parser.pm @@ -18,24 +18,22 @@ Escapes are supported in strings, using backslash. package Foswiki::Infix::Parser; -use strict; -use warnings; +BEGIN { + if ( $Foswiki::cfg{UseLocale} ) { + require locale; + import locale(); + } +} + use Assert; use Try::Tiny; use Foswiki::Infix::Error; -use Foswiki::Infix::Node (); +use Foswiki::Infix::Node; use Moo; use namespace::clean; extends 'Foswiki::Object'; -BEGIN { - if ( $Foswiki::cfg{UseLocale} ) { - require locale; - import locale(); - } -} - # Set to 1 for debug use constant MONITOR_PARSER => 0; @@ -84,28 +82,28 @@ be escaped using backslash (\). # Object properties has node_factory => ( - isa => 'ro', + is => 'ro', init_arg => 'nodeClass', ); has operators => ( - isa => 'rw', - default => sub { []; }, + is => 'rw', + default => sub { return []; }, ); has initialised => ( - isa => 'rw', + is => 'rw', default => 0, ); has numbers => ( - isa => 'rw', - default => qr/(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?/, + is => 'rw', + default => sub { qr/(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?/ }, ); has words => ( - isa => 'rw', - default => qr/\w+/, + is => 'rw', + default => sub { qr/\w+/ }, ); # Break circular references. @@ -314,15 +312,18 @@ s/(?throw( $_->text, $expr, $$input ); + my $text; + if ( $_->isa('Error') || $_->isa('Error::Simple') ) { + $text = $_->{-text}; + } + else { + $text = $_->text; + } + + Foswiki::Infix::Error->throw( $text, $expr, $$input ); } }; - #catch Error with { - - # # Catch errors thrown during the tree building process - # throw Foswiki::Infix::Error( shift, $expr, $$input ); - #}; Foswiki::Infix::Error->throw( 'Missing operator', $expr, $$input ) unless scalar(@opands) == 1; Foswiki::Infix::Error->throw( diff --git a/core/lib/Foswiki/Query/Parser.pm b/core/lib/Foswiki/Query/Parser.pm index c9cb9dca97..94544db7ff 100644 --- a/core/lib/Foswiki/Query/Parser.pm +++ b/core/lib/Foswiki/Query/Parser.pm @@ -25,9 +25,6 @@ BEGIN { } } -use Foswiki::Infix::Parser (); -our @ISA = ('Foswiki::Infix::Parser'); - use Foswiki::Query::Node (); # operator name precedence @@ -69,6 +66,20 @@ use Foswiki::Query::OP_int (); # 1000 use Foswiki::Query::OP_ob (); # 1100 +use Moo; +use namespace::clean; + +extends 'Foswiki::Infix::Parser'; + +has words => ( + is => 'ro', + default => sub { qr/([A-Z:][A-Z0-9_:]*|({[A-Z][A-Z0-9_]*})+)/i }, +); +has nodeClass => ( + is => 'rw', + default => 'Foswiki::Query::Node', +); + =begin TML Query Language BNF @@ -101,17 +112,13 @@ use constant OPS => qw (match and eq lc lte not ref d2n gte length lt ob uc dot gt like ne or where comma plus minus neg times div in int ); -sub new { - my ( $class, $options ) = @_; +sub BUILD { + my $this = shift; - $options->{words} ||= qr/([A-Z:][A-Z0-9_:]*|({[A-Z][A-Z0-9_]*})+)/i; - $options->{nodeClass} ||= 'Foswiki::Query::Node'; - my $this = $class->SUPER::new($options); foreach my $op ( OPS() ) { my $on = 'Foswiki::Query::OP_' . $op; $this->addOperator( $on->new() ); } - return $this; } # Ensure there is at least one operand on the opstack when closing