diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b61ad8a6e..da56014c2 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,10 +1,10 @@
[versions]
asm = "9.10.1"
-bouncycastle = "1.84"
+bouncycastle = "1.85"
commons-compress = "1.28.0"
commons-csv = "1.14.1"
icu4j = "78.3"
-junit-jupiter = "6.1.1"
+junit-jupiter = "6.1.2"
snakeyaml-engine = "3.0.1"
sqlite-jdbc = "3.53.2.0"
tomlj = "1.1.1"
diff --git a/pom.xml b/pom.xml
index a7615aede..78c2dbd0e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,19 +30,19 @@
org.junit.jupiter
junit-jupiter-api
- 6.1.1
+ 6.1.2
test
org.junit.jupiter
junit-jupiter-engine
- 6.1.1
+ 6.1.2
test
org.junit.jupiter
junit-jupiter-params
- 6.1.1
+ 6.1.2
test
@@ -78,12 +78,12 @@
org.bouncycastle
bcprov-jdk18on
- 1.84
+ 1.85
org.bouncycastle
bcpkix-jdk18on
- 1.84
+ 1.85
io.netty
diff --git a/src/main/perl/lib/JSON/PP.pm b/src/main/perl/lib/JSON/PP.pm
index 266a17429..cfa767e72 100644
--- a/src/main/perl/lib/JSON/PP.pm
+++ b/src/main/perl/lib/JSON/PP.pm
@@ -15,7 +15,7 @@ use Carp ();
use Scalar::Util qw(blessed reftype refaddr);
#use Devel::Peek;
-our $VERSION = '4.16';
+our $VERSION = '4.18';
our @EXPORT = qw(encode_json decode_json from_json to_json);
@@ -112,7 +112,7 @@ sub encode_json ($) { # encode
}
-sub decode_json { # decode
+sub decode_json ($) { # decode
($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
}
@@ -329,50 +329,21 @@ sub allow_bigint {
{ # Convert
- my $max_depth;
- my $indent;
- my $ascii;
- my $latin1;
- my $utf8;
- my $space_before;
- my $space_after;
- my $canonical;
- my $allow_blessed;
- my $convert_blessed;
-
- my $indent_length;
- my $escape_slash;
- my $bignum;
- my $as_nonblessed;
- my $allow_tags;
-
- my $depth;
- my $indent_count;
- my $keysort;
-
-
sub PP_encode_json {
my $self = shift;
my $obj = shift;
- $indent_count = 0;
- $depth = 0;
+ $self->{indent_count} = 0;
+ $self->{depth} = 0;
my $props = $self->{PROPS};
- ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed,
- $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags)
- = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
- P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
-
- ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
-
- $keysort = $canonical ? sub { $a cmp $b } : undef;
+ $self->{keysort} = $self->{PROPS}[P_CANONICAL] ? sub { $a cmp $b } : undef;
if ($self->{sort_by}) {
- $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
- : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
- : sub { $a cmp $b };
+ $self->{keysort} = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
+ : $self->{sort_by} =~ /\D+/ ? $self->{sort_by}
+ : sub { $a cmp $b };
}
encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
@@ -380,7 +351,7 @@ sub allow_bigint {
my $str = $self->object_to_json($obj);
- $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible
+ $str .= "\n" if ( $self->{PROPS}[P_INDENT] ); # JSON::XS 2.26 compatible
return $str;
}
@@ -401,7 +372,7 @@ sub allow_bigint {
return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
- if ( $allow_tags and $obj->can('FREEZE') ) {
+ if ( $self->{PROPS}[P_ALLOW_TAGS] and $obj->can('FREEZE') ) {
my $obj_class = ref $obj || $obj;
$obj = bless $obj, $obj_class;
my @results = $obj->FREEZE('JSON');
@@ -416,7 +387,7 @@ sub allow_bigint {
return '("'.$obj_class.'")['.join(',', @results).']';
}
- if ( $convert_blessed and $obj->can('TO_JSON') ) {
+ if ( $self->{PROPS}[P_CONVERT_BLESSED] and $obj->can('TO_JSON') ) {
my $result = $obj->TO_JSON();
if ( defined $result and ref( $result ) ) {
if ( refaddr( $obj ) eq refaddr( $result ) ) {
@@ -430,10 +401,10 @@ sub allow_bigint {
return $self->object_to_json( $result );
}
- return "$obj" if ( $bignum and _is_bignum($obj) );
+ return "$obj" if ( $self->{PROPS}[P_ALLOW_BIGNUM] and _is_bignum($obj) );
- if ($allow_blessed) {
- return $self->blessed_to_json($obj) if ($as_nonblessed); # will be removed.
+ if ($self->{PROPS}[P_ALLOW_BLESSED]) {
+ return $self->blessed_to_json($obj) if ($self->{PROPS}[P_AS_NONBLESSED]); # will be removed.
return 'null';
}
encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj)
@@ -454,19 +425,19 @@ sub allow_bigint {
my @res;
encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
- if (++$depth > $max_depth);
+ if (++$self->{depth} > $self->{max_depth});
- my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
- my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
+ my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
+ my $del = ($self->{PROPS}[P_SPACE_BEFORE] ? ' ' : '') . ':' . ($self->{PROPS}[P_SPACE_AFTER] ? ' ' : '');
- for my $k ( _sort( $obj ) ) {
+ for my $k ( $self->__sort( $obj ) ) {
push @res, $self->string_to_json( $k )
. $del
. ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
}
- --$depth;
- $self->_down_indent() if ($indent);
+ --$self->{depth};
+ $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
return '{}' unless @res;
return '{' . $pre . join( ",$pre", @res ) . $post . '}';
@@ -478,19 +449,20 @@ sub allow_bigint {
my @res;
encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
- if (++$depth > $max_depth);
+ if (++$self->{depth} > $self->{max_depth});
- my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
+ my ($pre, $post) = $self->{PROPS}[P_INDENT] ? $self->_up_indent() : ('', '');
for my $v (@$obj){
push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
}
- --$depth;
- $self->_down_indent() if ($indent);
+ --$self->{depth};
+ $self->_down_indent() if ($self->{PROPS}[P_INDENT]);
return '[]' unless @res;
- return '[' . $pre . join( ",$pre", @res ) . $post . ']';
+ my $space = $pre eq '' && $self->{PROPS}[P_SPACE_AFTER] ? ' ' : '';
+ return '[' . $pre . join( ",$space$pre", @res ) . $post . ']';
}
sub _looks_like_number {
@@ -579,20 +551,20 @@ sub allow_bigint {
my ($self, $arg) = @_;
$arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g;
- $arg =~ s/\//\\\//g if ($escape_slash);
+ $arg =~ s/\//\\\//g if ($self->{PROPS}[P_ESCAPE_SLASH]);
# On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f]
$arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg;
- if ($ascii) {
+ if ($self->{PROPS}[P_ASCII]) {
$arg = _encode_ascii($arg);
}
- if ($latin1) {
+ if ($self->{PROPS}[P_LATIN1]) {
$arg = _encode_latin1($arg);
}
- if ($utf8) {
+ if ($self->{PROPS}[P_UTF8]) {
utf8::encode($arg);
}
@@ -620,36 +592,30 @@ sub allow_bigint {
}
- sub _sort {
+ sub __sort {
+ my $self = shift;
+ my $keysort = $self->{keysort};
defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
}
sub _up_indent {
my $self = shift;
- my $space = ' ' x $indent_length;
+ my $space = ' ' x $self->{indent_length};
my ($pre,$post) = ('','');
- $post = "\n" . $space x $indent_count;
+ $post = "\n" . $space x $self->{indent_count};
- $indent_count++;
+ $self->{indent_count}++;
- $pre = "\n" . $space x $indent_count;
+ $pre = "\n" . $space x $self->{indent_count};
return ($pre,$post);
}
- sub _down_indent { $indent_count--; }
-
-
- sub PP_encode_box {
- {
- depth => $depth,
- indent_count => $indent_count,
- };
- }
+ sub _down_indent { $_[0]->{indent_count}--; }
} # Convert
@@ -724,34 +690,6 @@ BEGIN {
'/' => '/',
);
- my $text; # json data
- my $at; # offset
- my $ch; # first character
- my $len; # text length (changed according to UTF8 or NON UTF8)
- # INTERNAL
- my $depth; # nest counter
- my $encoding; # json text encoding
- my $is_valid_utf8; # temp variable
- my $utf8_len; # utf8 byte length
- # FLAGS
- my $utf8; # must be utf8
- my $max_depth; # max nest number of objects and arrays
- my $max_size;
- my $relaxed;
- my $cb_object;
- my $cb_sk_object;
-
- my $F_HOOK;
-
- my $allow_bignum; # using Math::BigInt/BigFloat
- my $singlequote; # loosely quoting
- my $loose; #
- my $allow_barekey; # bareKey
- my $allow_tags;
-
- my $alt_true;
- my $alt_false;
-
sub _detect_utf_encoding {
my $text = shift;
my @octets = unpack('C4', $text);
@@ -765,25 +703,18 @@ BEGIN {
}
sub PP_decode_json {
- my ($self, $want_offset);
+ my ($self, $text, $want_offset) = @_;
- ($self, $text, $want_offset) = @_;
-
- ($at, $ch, $depth) = (0, '', 0);
+ @$self{qw/at ch depth/} = (0, '', 0);
if ( !defined $text or ref $text ) {
- decode_error("malformed JSON string, neither array, object, number, string or atom");
+ $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
}
my $props = $self->{PROPS};
- ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
- = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
-
- ($alt_true, $alt_false) = @$self{qw/true false/};
-
- if ( $utf8 ) {
- $encoding = _detect_utf_encoding($text);
+ if ( $self->{PROPS}[P_UTF8] ) {
+ my $encoding = _detect_utf_encoding($text);
if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
require Encode;
Encode::from_to($text, $encoding, 'utf-8');
@@ -795,81 +726,84 @@ BEGIN {
utf8::encode( $text );
}
- $len = length $text;
-
- ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
- = @{$self}{qw/max_depth max_size cb_object cb_sk_object F_HOOK/};
+ $self->{len} = length $text;
+ $self->{text} = $text;
- if ($max_size > 1) {
+ if ($self->{max_size} > 1) {
use bytes;
my $bytes = length $text;
- decode_error(
+ $self->_decode_error(
sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
- , $bytes, $max_size), 1
- ) if ($bytes > $max_size);
+ , $bytes, $self->{max_size}), 1
+ ) if ($bytes > $self->{max_size});
}
- white(); # remove head white space
+ $self->_white(); # remove head white space
- decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; # Is there a first character for JSON structure?
+ $self->_decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $self->{ch}; # Is there a first character for JSON structure?
- my $result = value();
+ my $result = $self->_value();
if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
- decode_error(
+ $self->_decode_error(
'JSON text must be an object or array (but found number, string, true, false or null,'
. ' use allow_nonref to allow this)', 1);
}
- Carp::croak('something wrong.') if $len < $at; # we won't arrive here.
+ Carp::croak('something wrong.') if $self->{len} < $self->{at}; # we won't arrive here.
- my $consumed = defined $ch ? $at - 1 : $at; # consumed JSON text length
+ my $consumed = defined $self->{ch} ? $self->{at} - 1 : $self->{at}; # consumed JSON text length
- white(); # remove tail white space
+ $self->_white(); # remove tail white space
return ( $result, $consumed ) if $want_offset; # all right if decode_prefix
- decode_error("garbage after JSON object") if defined $ch;
+ $self->_decode_error("garbage after JSON object") if defined $self->{ch};
$result;
}
- sub next_chr {
- return $ch = undef if($at >= $len);
- $ch = substr($text, $at++, 1);
+ sub _next_chr {
+ my $self = shift;
+ return $self->{ch} = undef if($self->{at} >= $self->{len});
+ $self->{ch} = substr($self->{text}, $self->{at}++, 1);
}
- sub value {
- white();
+ sub _value {
+ my $self = shift;
+ $self->_white();
+ my $ch = $self->{ch};
return if(!defined $ch);
- return object() if($ch eq '{');
- return array() if($ch eq '[');
- return tag() if($ch eq '(');
- return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
- return number() if($ch =~ /[0-9]/ or $ch eq '-');
- return word();
+ return $self->_object() if($ch eq '{');
+ return $self->_array() if($ch eq '[');
+ return $self->_tag() if($ch eq '(');
+ return $self->_string() if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'"));
+ return $self->_number() if($ch =~ /[0-9]/ or $ch eq '-');
+ return $self->_word();
}
- sub string {
+ sub _string {
+ my $self = shift;
my $utf16;
my $is_utf8;
- ($is_valid_utf8, $utf8_len) = ('', 0);
+ my $utf8_len = 0;
my $s = ''; # basically UTF8 flag on
- if($ch eq '"' or ($singlequote and $ch eq "'")){
+ my $ch = $self->{ch};
+ if($ch eq '"' or ($self->{PROPS}[P_ALLOW_SINGLEQUOTE] and $ch eq "'")){
my $boundChar = $ch;
- OUTER: while( defined(next_chr()) ){
+ OUTER: while( defined($ch = $self->_next_chr()) ){
if($ch eq $boundChar){
- next_chr();
+ $self->_next_chr();
if ($utf16) {
- decode_error("missing low surrogate character in surrogate pair");
+ $self->_decode_error("missing low surrogate character in surrogate pair");
}
utf8::decode($s) if($is_utf8);
@@ -877,7 +811,7 @@ BEGIN {
return $s;
}
elsif($ch eq '\\'){
- next_chr();
+ $ch = $self->_next_chr();
if(exists $escapes{$ch}){
$s .= $escapes{$ch};
}
@@ -885,7 +819,7 @@ BEGIN {
my $u = '';
for(1..4){
- $ch = next_chr();
+ $ch = $self->_next_chr();
last OUTER if($ch !~ /[0-9a-fA-F]/);
$u .= $ch;
}
@@ -897,7 +831,7 @@ BEGIN {
# U+DC00 - U+DFFF
elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { # UTF-16 low surrogate?
unless (defined $utf16) {
- decode_error("missing high surrogate character in surrogate pair");
+ $self->_decode_error("missing high surrogate character in surrogate pair");
}
$is_utf8 = 1;
$s .= _decode_surrogates($utf16, $u) || next;
@@ -905,7 +839,7 @@ BEGIN {
}
else {
if (defined $utf16) {
- decode_error("surrogate pair expected");
+ $self->_decode_error("surrogate pair expected");
}
my $hex = hex( $u );
@@ -920,9 +854,9 @@ BEGIN {
}
else{
- unless ($loose) {
- $at -= 2;
- decode_error('illegal backslash escape sequence in string');
+ unless ($self->{PROPS}[P_LOOSE]) {
+ $self->{at} -= 2;
+ $self->_decode_error('illegal backslash escape sequence in string');
}
$s .= $ch;
}
@@ -930,22 +864,22 @@ BEGIN {
else{
if ( $ch =~ /[[:^ascii:]]/ ) {
- unless( $ch = is_valid_utf8($ch) ) {
- $at -= 1;
- decode_error("malformed UTF-8 character in JSON string");
+ unless( $ch = $self->_is_valid_utf8($ch, \$utf8_len) ) {
+ $self->{at} -= 1;
+ $self->_decode_error("malformed UTF-8 character in JSON string");
}
else {
- $at += $utf8_len - 1;
+ $self->{at} += $utf8_len - 1;
}
$is_utf8 = 1;
}
- if (!$loose) {
+ if (!$self->{PROPS}[P_LOOSE]) {
if ($ch =~ $invalid_char_re) { # '/' ok
- if (!$relaxed or $ch ne "\t") {
- $at--;
- decode_error(sprintf "invalid character 0x%X"
+ if (!$self->{PROPS}[P_RELAXED] or $ch ne "\t") {
+ $self->{at}--;
+ $self->_decode_error(sprintf "invalid character 0x%X"
. " encountered while parsing JSON string",
ord $ch);
}
@@ -957,51 +891,53 @@ BEGIN {
}
}
- decode_error("unexpected end of string while parsing JSON string");
+ $self->_decode_error("unexpected end of string while parsing JSON string");
}
- sub white {
+ sub _white {
+ my $self = shift;
+ my $ch = $self->{ch};
while( defined $ch ){
if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
- next_chr();
+ $ch = $self->_next_chr();
}
- elsif($relaxed and $ch eq '/'){
- next_chr();
+ elsif($self->{PROPS}[P_RELAXED] and $ch eq '/'){
+ $ch = $self->_next_chr();
if(defined $ch and $ch eq '/'){
- 1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r");
+ 1 while(defined($ch = $self->_next_chr()) and $ch ne "\n" and $ch ne "\r");
}
elsif(defined $ch and $ch eq '*'){
- next_chr();
+ $ch = $self->_next_chr();
while(1){
if(defined $ch){
if($ch eq '*'){
- if(defined(next_chr()) and $ch eq '/'){
- next_chr();
+ if(defined($ch = $self->_next_chr()) and $ch eq '/'){
+ $ch = $self->_next_chr();
last;
}
}
else{
- next_chr();
+ $ch = $self->_next_chr();
}
}
else{
- decode_error("Unterminated comment");
+ $self->_decode_error("Unterminated comment");
}
}
next;
}
else{
- $at--;
- decode_error("malformed JSON string, neither array, object, number, string or atom");
+ $self->{at}--;
+ $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
}
}
else{
- if ($relaxed and $ch eq '#') { # correctly?
- pos($text) = $at;
- $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
- $at = pos($text);
- next_chr;
+ if ($self->{PROPS}[P_RELAXED] and $ch eq '#') { # correctly?
+ pos($self->{text}) = $self->{at};
+ $self->{text} =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
+ $self->{at} = pos($self->{text});
+ $ch = $self->_next_chr;
next;
}
@@ -1011,33 +947,36 @@ BEGIN {
}
- sub array {
+ sub _array {
+ my $self = shift;
my $a = $_[0] || []; # you can use this code to use another array ref object.
- decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
- if (++$depth > $max_depth);
+ $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
+ if (++$self->{depth} > $self->{max_depth});
- next_chr();
- white();
+ $self->_next_chr();
+ $self->_white();
+ my $ch = $self->{ch};
if(defined $ch and $ch eq ']'){
- --$depth;
- next_chr();
+ --$self->{depth};
+ $self->_next_chr();
return $a;
}
else {
while(defined($ch)){
- push @$a, value();
+ push @$a, $self->_value();
- white();
+ $self->_white();
+ $ch = $self->{ch};
if (!defined $ch) {
last;
}
if($ch eq ']'){
- --$depth;
- next_chr();
+ --$self->{depth};
+ $self->_next_chr();
return $a;
}
@@ -1045,90 +984,97 @@ BEGIN {
last;
}
- next_chr();
- white();
+ $self->_next_chr();
+ $self->_white();
- if ($relaxed and $ch eq ']') {
- --$depth;
- next_chr();
+ $ch = $self->{ch};
+ if ($self->{PROPS}[P_RELAXED] and $ch eq ']') {
+ --$self->{depth};
+ $self->_next_chr();
return $a;
}
}
}
- $at-- if defined $ch and $ch ne '';
- decode_error(", or ] expected while parsing array");
+ $self->{at}-- if defined $ch and $ch ne '';
+ $self->_decode_error(", or ] expected while parsing array");
}
- sub tag {
- decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags;
+ sub _tag {
+ my $self = shift;
+ $self->_decode_error('malformed JSON string, neither array, object, number, string or atom') unless $self->{PROPS}[P_ALLOW_TAGS];
- next_chr();
- white();
+ $self->_next_chr();
+ $self->_white();
- my $tag = value();
+ my $tag = $self->_value();
return unless defined $tag;
- decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
+ $self->_decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
- white();
+ $self->_white();
+ my $ch = $self->{ch};
if (!defined $ch or $ch ne ')') {
- decode_error(') expected after tag');
+ $self->_decode_error(') expected after tag');
}
- next_chr();
- white();
+ $self->_next_chr();
+ $self->_white();
- my $val = value();
+ my $val = $self->_value();
return unless defined $val;
- decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
+ $self->_decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
if (!eval { $tag->can('THAW') }) {
- decode_error('cannot decode perl-object (package does not exist)') if $@;
- decode_error('cannot decode perl-object (package does not have a THAW method)');
+ $self->_decode_error('cannot decode perl-object (package does not exist)') if $@;
+ $self->_decode_error('cannot decode perl-object (package does not have a THAW method)');
}
$tag->THAW('JSON', @$val);
}
- sub object {
+ sub _object {
+ my $self = shift;
my $o = $_[0] || {}; # you can use this code to use another hash ref object.
my $k;
- decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
- if (++$depth > $max_depth);
- next_chr();
- white();
+ $self->_decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
+ if (++$self->{depth} > $self->{max_depth});
+ $self->_next_chr();
+ $self->_white();
+ my $ch = $self->{ch};
if(defined $ch and $ch eq '}'){
- --$depth;
- next_chr();
- if ($F_HOOK) {
- return _json_object_hook($o);
+ --$self->{depth};
+ $self->_next_chr();
+ if ($self->{F_HOOK}) {
+ return $self->__json_object_hook($o);
}
return $o;
}
else {
while (defined $ch) {
- $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
- white();
+ $k = ($self->{PROPS}[P_ALLOW_BAREKEY] and $ch ne '"' and $ch ne "'") ? $self->_bareKey() : $self->_string();
+ $self->_white();
+ $ch = $self->{ch};
if(!defined $ch or $ch ne ':'){
- $at--;
- decode_error("':' expected");
+ $self->{at}--;
+ $self->_decode_error("':' expected");
}
- next_chr();
- $o->{$k} = value();
- white();
+ $self->_next_chr();
+ $o->{$k} = $self->_value();
+ $self->_white();
+ $ch = $self->{ch};
last if (!defined $ch);
if($ch eq '}'){
- --$depth;
- next_chr();
- if ($F_HOOK) {
- return _json_object_hook($o);
+ --$self->{depth};
+ $self->_next_chr();
+ if ($self->{F_HOOK}) {
+ return $self->__json_object_hook($o);
}
return $o;
}
@@ -1137,14 +1083,15 @@ BEGIN {
last;
}
- next_chr();
- white();
+ $self->_next_chr();
+ $self->_white();
- if ($relaxed and $ch eq '}') {
- --$depth;
- next_chr();
- if ($F_HOOK) {
- return _json_object_hook($o);
+ $ch = $self->{ch};
+ if ($self->{PROPS}[P_RELAXED] and $ch eq '}') {
+ --$self->{depth};
+ $self->_next_chr();
+ if ($self->{F_HOOK}) {
+ return $self->__json_object_hook($o);
}
return $o;
}
@@ -1153,94 +1100,99 @@ BEGIN {
}
- $at-- if defined $ch and $ch ne '';
- decode_error(", or } expected while parsing object/hash");
+ $self->{at}-- if defined $ch and $ch ne '';
+ $self->_decode_error(", or } expected while parsing object/hash");
}
- sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
+ sub _bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition
+ my $self = shift;
my $key;
+ my $ch = $self->{ch};
while($ch =~ /[\$\w[:^ascii:]]/){
$key .= $ch;
- next_chr();
+ $ch = $self->_next_chr();
}
return $key;
}
- sub word {
- my $word = substr($text,$at-1,4);
+ sub _word {
+ my $self = shift;
+ my $word = substr($self->{text},$self->{at}-1,4);
if($word eq 'true'){
- $at += 3;
- next_chr;
- return defined $alt_true ? $alt_true : $JSON::PP::true;
+ $self->{at} += 3;
+ $self->_next_chr;
+ return defined $self->{true} ? $self->{true} : $JSON::PP::true;
}
elsif($word eq 'null'){
- $at += 3;
- next_chr;
+ $self->{at} += 3;
+ $self->_next_chr;
return undef;
}
elsif($word eq 'fals'){
- $at += 3;
- if(substr($text,$at,1) eq 'e'){
- $at++;
- next_chr;
- return defined $alt_false ? $alt_false : $JSON::PP::false;
+ $self->{at} += 3;
+ if(substr($self->{text},$self->{at},1) eq 'e'){
+ $self->{at}++;
+ $self->_next_chr;
+ return defined $self->{false} ? $self->{false} : $JSON::PP::false;
}
}
- $at--; # for decode_error report
+ $self->{at}--; # for decode_error report
- decode_error("'null' expected") if ($word =~ /^n/);
- decode_error("'true' expected") if ($word =~ /^t/);
- decode_error("'false' expected") if ($word =~ /^f/);
- decode_error("malformed JSON string, neither array, object, number, string or atom");
+ $self->_decode_error("'null' expected") if ($word =~ /^n/);
+ $self->_decode_error("'true' expected") if ($word =~ /^t/);
+ $self->_decode_error("'false' expected") if ($word =~ /^f/);
+ $self->_decode_error("malformed JSON string, neither array, object, number, string or atom");
}
- sub number {
+ sub _number {
+ my $self = shift;
my $n = '';
my $v;
my $is_dec;
my $is_exp;
+ my $ch = $self->{ch};
if($ch eq '-'){
$n = '-';
- next_chr;
+ $ch = $self->_next_chr;
if (!defined $ch or $ch !~ /\d/) {
- decode_error("malformed number (no digits after initial minus)");
+ $self->_decode_error("malformed number (no digits after initial minus)");
}
}
# According to RFC4627, hex or oct digits are invalid.
if($ch eq '0'){
- my $peek = substr($text,$at,1);
+ my $peek = substr($self->{text},$self->{at},1);
if($peek =~ /^[0-9a-dfA-DF]/){ # e may be valid (exponential)
- decode_error("malformed number (leading zero must not be followed by another digit)");
+ $self->_decode_error("malformed number (leading zero must not be followed by another digit)");
}
$n .= $ch;
- next_chr;
+ $ch = $self->_next_chr;
}
while(defined $ch and $ch =~ /\d/){
$n .= $ch;
- next_chr;
+ $ch = $self->_next_chr;
}
if(defined $ch and $ch eq '.'){
$n .= '.';
$is_dec = 1;
- next_chr;
+ $ch = $self->_next_chr;
if (!defined $ch or $ch !~ /\d/) {
- decode_error("malformed number (no digits after decimal point)");
+ $self->_decode_error("malformed number (no digits after decimal point)");
}
else {
$n .= $ch;
}
- while(defined(next_chr) and $ch =~ /\d/){
+ while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
$n .= $ch;
}
}
@@ -1248,13 +1200,13 @@ BEGIN {
if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
$n .= $ch;
$is_exp = 1;
- next_chr;
+ $ch = $self->_next_chr;
if(defined($ch) and ($ch eq '+' or $ch eq '-')){
$n .= $ch;
- next_chr;
+ $ch = $self->_next_chr;
if (!defined $ch or $ch =~ /\D/) {
- decode_error("malformed number (no digits after exp sign)");
+ $self->_decode_error("malformed number (no digits after exp sign)");
}
$n .= $ch;
}
@@ -1262,10 +1214,10 @@ BEGIN {
$n .= $ch;
}
else {
- decode_error("malformed number (no digits after exp sign)");
+ $self->_decode_error("malformed number (no digits after exp sign)");
}
- while(defined(next_chr) and $ch =~ /\d/){
+ while(defined($ch = $self->_next_chr) and $ch =~ /\d/){
$n .= $ch;
}
@@ -1274,13 +1226,13 @@ BEGIN {
$v .= $n;
if ($is_dec or $is_exp) {
- if ($allow_bignum) {
+ if ($self->{PROPS}[P_ALLOW_BIGNUM]) {
require Math::BigFloat;
return Math::BigFloat->new($v);
}
} else {
if (length $v > $max_intsize) {
- if ($allow_bignum) { # from Adam Sussman
+ if ($self->{PROPS}[P_ALLOW_BIGNUM]) { # from Adam Sussman
require Math::BigInt;
return Math::BigInt->new($v);
}
@@ -1302,13 +1254,14 @@ BEGIN {
utf8::encode($max_unicode_length);
$max_unicode_length = length $max_unicode_length;
- sub is_valid_utf8 {
+ sub _is_valid_utf8 {
+ my ($self, $ch, $utf8_len_r) = @_;
# Returns undef (setting $utf8_len to 0) unless the next bytes in $text
# comprise a well-formed UTF-8 encoded character, in which case,
# return those bytes, setting $utf8_len to their count.
- my $start_point = substr($text, $at - 1);
+ my $start_point = substr($self->{text}, $self->{at} - 1);
# Look no further than the maximum number of bytes in a single
# character
@@ -1329,8 +1282,8 @@ BEGIN {
# and return those bytes.
$copy = substr($copy, 0, 1);
utf8::encode($copy);
- $utf8_len = length $copy;
- return substr($start_point, 0, $utf8_len);
+ $$utf8_len_r = length $copy;
+ return substr($start_point, 0, $$utf8_len_r);
}
# If it didn't work, it could be that there is a full legal character
@@ -1340,15 +1293,16 @@ BEGIN {
}
# Failed to find a legal UTF-8 character.
- $utf8_len = 0;
+ $$utf8_len_r = 0;
return;
}
- sub decode_error {
+ sub _decode_error {
+ my $self = shift;
my $error = shift;
my $no_rep = shift;
- my $str = defined $text ? substr($text, $at) : '';
+ my $str = defined $self->{text} ? substr($self->{text}, $self->{at}) : '';
my $mess = '';
my $type = 'U*';
@@ -1374,18 +1328,19 @@ BEGIN {
}
Carp::croak (
- $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
+ $no_rep ? "$error" : "$error, at character offset $self->{at} (before \"$mess\")"
);
}
- sub _json_object_hook {
+ sub __json_object_hook {
+ my $self = shift;
my $o = $_[0];
my @ks = keys %{$o};
- if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) {
- my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} );
+ if ( $self->{cb_sk_object} and @ks == 1 and exists $self->{cb_sk_object}{ $ks[0] } and ref $self->{cb_sk_object}{ $ks[0] } ) {
+ my @val = $self->{cb_sk_object}{ $ks[0] }->( $o->{$ks[0]} );
if (@val == 0) {
return $o;
}
@@ -1397,7 +1352,7 @@ BEGIN {
}
}
- my @val = $cb_object->($o) if ($cb_object);
+ my @val = $self->{cb_object}->($o) if ($self->{cb_object});
if (@val == 0) {
return $o;
}
@@ -1409,19 +1364,6 @@ BEGIN {
}
}
-
- sub PP_decode_box {
- {
- text => $text,
- at => $at,
- ch => $ch,
- len => $len,
- depth => $depth,
- encoding => $encoding,
- is_valid_utf8 => $is_valid_utf8,
- };
- }
-
} # PARSE
@@ -1849,7 +1791,7 @@ and are also used to represent JSON C and C in Perl strings.
On perl 5.36 and above, will also return true when given one of perl's
standard boolean values, such as the result of a comparison.
-See L, below, for more information on how JSON values are mapped to
+See L, below, for more information on how JSON values are mapped to
Perl.
=head1 OBJECT-ORIENTED INTERFACE
@@ -2136,7 +2078,7 @@ This setting has currently no effect on tied hashes.
$enabled = $json->get_allow_nonref
-Unlike other boolean options, this opotion is enabled by default beginning
+Unlike other boolean options, this option is enabled by default beginning
with version C<4.0>.
If C<$enable> is true (or missing), then the C method can convert a
@@ -2508,7 +2450,7 @@ objects into JSON numbers.
print $json->encode($bigfloat);
# => 2.000000000000000000000000001
-See also L.
+See also L.
=head2 loose
@@ -2575,7 +2517,7 @@ then the argument will be passed to Perl's C built-in function.
As the sorting is done in the JSON::PP scope, you usually need to
prepend C to the subroutine name, and the special variables
-C<$a> and C<$b> used in the subrontine used by C function.
+C<$a> and C<$b> used in the subroutine used by C function.
Example:
@@ -2940,7 +2882,7 @@ argument being the object to serialise, and the second argument being the
constant string C to distinguish it from other serialisers.
The C method can return any number of values (i.e. zero or
-more). These values and the paclkage/classname of the object will then be
+more). These values and the package/classname of the object will then be
encoded as a tagged JSON value in the following format:
("classname")[FREEZE return values...]
diff --git a/src/main/perl/lib/JSON/PP/Boolean.pm b/src/main/perl/lib/JSON/PP/Boolean.pm
index 146446e93..000a3586a 100644
--- a/src/main/perl/lib/JSON/PP/Boolean.pm
+++ b/src/main/perl/lib/JSON/PP/Boolean.pm
@@ -11,7 +11,7 @@ overload::import('overload',
fallback => 1,
);
-our $VERSION = '4.16';
+our $VERSION = '4.18';
1;
diff --git a/src/main/perl/lib/Pod/perl.pod b/src/main/perl/lib/Pod/perl.pod
index eee74c0a8..d13b04ced 100644
--- a/src/main/perl/lib/Pod/perl.pod
+++ b/src/main/perl/lib/Pod/perl.pod
@@ -182,6 +182,7 @@ aux h2ph h2xs perlbug pl2pm pod2html pod2man splain xsubpp
perlhist Perl history records
perldelta Perl changes since previous version
+ perl5440delta Perl changes in version 5.44.0
perl5422delta Perl changes in version 5.42.2
perl5421delta Perl changes in version 5.42.1
perl5420delta Perl changes in version 5.42.0
diff --git a/src/main/perl/lib/Pod/perl5440delta.pod b/src/main/perl/lib/Pod/perl5440delta.pod
new file mode 100644
index 000000000..45eacdf6b
--- /dev/null
+++ b/src/main/perl/lib/Pod/perl5440delta.pod
@@ -0,0 +1,1393 @@
+=encoding utf8
+
+=head1 NAME
+
+perl5440delta - what is new for perl v5.44.0
+
+=head1 DESCRIPTION
+
+This document describes differences between the 5.42.0 release and the 5.44.0
+release.
+
+=head1 Core Enhancements
+
+=head2 Named Parameters in Signatures
+
+This adds a major new ability to subroutine signatures, allowing callers
+to pass parameters by name/value pairs rather than by position.
+
+ sub f ($x, $y, :$alpha, :$beta = undef) { ... }
+
+ f( 123, 456, alpha => 789 );
+
+Originally specified in
+L.
+
+This feature is currently considered B, and is described in
+further detail in L.
+
+=head2 Multi-variable C can now use aliased references
+
+Perl version 5.22 introduced reference aliases, allowing a C loop
+iteration variable to create new aliases to references. Perl version 5.36
+introduced C loops with multiple variables, consuming more than one
+input list item on each iteration. New in this version, the two features may
+now be used together, allowing multiple iteration variables where any of them
+are permitted to be reference aliases.
+
+ use v5.44;
+ use feature qw( refaliasing declared_refs );
+
+ my %hash = (
+ one => [1],
+ two => [2, 2],
+ );
+
+ foreach my ( $key, \@items ) ( %hash ) {
+ say "The $key array contains: @items";
+ }
+
+Currently both the C and C features remain
+B.
+
+=head2 Enhanced operation of regular expression patterns under /xx
+
+Experimentally, the C pattern modifier can allow bracketed
+character classes (I, C<[a-zA-Z]> to extend across multiple lines
+and to contain comments, and to warn you of potential cases where a
+portion of a pattern inadvertently has been treated as a comment instead
+of what you intended. This behavior is enabled by S>. See Lx and Exx>.
+
+=head2 Unicode 17.0 is supported
+
+See L.
+
+=head2 New source of entropy for PRNG seeding
+
+Perl now uses the C system call to fetch random bytes suitable
+for seeding the internal PRNG. Previously Perl would read raw bytes from the
+F device. Perl now seeds itself in this order (and falls through
+upon failure):
+
+=over
+
+=item 1.
+
+C on systems that support this call (Linux, BSD, MacOS)
+
+=item 2.
+
+F on systems that have it
+
+=item 3.
+
+Hash of internal state variables: Unix time, process ID, and pointer value
+
+=back
+
+Note that the internal PRNG is still unsuitable for security applications.
+See L for a discussion of security.
+
+=head1 Security
+
+=head2 CVE-2026-8376 - Buffer overflow in Perl_study_chunk
+
+Perl_study_chunk in regcomp_study.c checked the size of the joined substring
+buffer in characters rather than bytes. On 32-bit builds, this can lead to
+an integer overflow of the size of the buffer leading to out-of-bounds writes.
+
+=head2 CVE-2026-57432 - Buffer overflow in S_measure_struct
+
+If you call C or C to operate on a structure whose computed size
+is too large to fit in memory, an integer overflow could happen that would
+result in a buffer overflow. This usually happens as a result of embedding a
+large number as the repeat count for an item.
+
+=head2 CVE-2026-13221 - Regex trie 16-bit field overflow
+
+The trie optimization in the regex engine could overflow in an alternation with more than ~65k branches. This could cause both false positives and false negatives on such regular expressions.
+
+=head1 Incompatible Changes
+
+=head2 Unicode rules are now fully enforced on identifier and regular expression group names.
+
+Before Unicode, Perl accepted any C<\w> character in an identifier or other
+name, except the first character couldn't be a digit. Later, Unicode
+created two properties that described this. Even later, they found
+those properties to be insufficient, and created two new similar
+properties. These are the ones that perl has intended to use since:
+C<\p{XID_Start}> and C<\p{XID_Continue}>. (The C stands for
+"eXtended" and indicates these are the more modern versions.)
+
+(And even later, long after Perl identifier rules were formed using
+the above properties, Unicode added recommendations to further restrict
+legal identifier names. These were added to counter cases where, for
+example, programmers snuck code past reviewers using characters that
+look like other ones. The two properties are C and
+C. See L. Perl
+currently doesn't do anything with these, except to furnish you the
+ability to use them in regular expressions.)
+
+We soon discovered that there were 14 characters that match C
+and C that don't also match C<\w>. To avoid breaking code
+that had long relied on C<\w>, we chose to not add those to the list of
+acceptable identifier characters.
+
+It turns out that there are about 160 characters that match C<\w> but
+not the Unicode C properties. Thus they are illegal according to
+Unicode. Those are now explicitly forbidden in both Perl identifiers
+and regular expression group names. Previously, it was likely that
+their use in identifiers wouldn't work anyway; they could be accepted
+initially as legal, but other code would later reject them, but with a
+message that had nothing to do with the underlying problem. However
+group names in regular expression patterns could contain illegal
+continuation characters and have a higher probability of not being
+caught. That is now changed.
+
+Only programs that do L|utf8> can be affected, and then only
+characters that appear in the 2nd or later positions of the name. The
+characters that an identifier name can begin with are unchanged.
+
+130 of the now unacceptable characters are 5 sets of 26 Latin letters
+that are enclosed by some shape, such as CIRCLED LATIN CAPITAL LETTER N.
+Another 8 are generic modifiers that add shapes around other characters;
+5 are modifiers to Cyrillic numbers; and 16 are Arabic ligatures and
+isolated forms. The other two are GREEK YPOGEGRAMMENI and VERTICAL
+TILDE.
+
+=head1 Deprecations
+
+=over 4
+
+=item *
+
+Deprecated since 5.12, using C to jump into the body of a loop or
+other block construct from outside is no longer permitted.
+[L]
+
+=item *
+
+C has new restrictions
+
+Using an unescaped C<#> or literal vertical space is now deprecated in a
+regular expression bracketed character class that is compiled with the
+C modifier. These still work, but deprecation warnings will be
+generated unless turned off or the constructs are cured as follows.
+
+=over
+
+=item *
+
+Escape a C<#> by preceding it with a backslash, like in
+
+ m/ [ % \# ( ) ] /xx
+
+=item *
+
+Use constructs like C<\n> instead of literal vertical space.
+
+=back
+
+=back
+
+=head1 Performance Enhancements
+
+=over 4
+
+=item *
+
+Simple (non-overflowing) addition (C<+>), subtraction (C<->) and
+multiplication (C<*>) of integers are slightly sped up, as long as
+sufficient underlying C compiler support is available.
+
+=item *
+
+Populating a hash from a list of key/value pairs when the keys are constant
+string operands known at compile time is commonly now faster. [L]
+
+=item *
+
+Processing of signatures at the start of a subroutine under the C
+feature is now more efficient at runtime.
+
+=back
+
+=head1 Modules and Pragmata
+
+=head2 Updated Modules and Pragmata
+
+=over 4
+
+=item *
+
+L has been upgraded from version 3.04 to 3.12.
+
+This fixes CVE-2026-9538, CVE-2026-42496, and CVE-2026-42497.
+
+=item *
+
+L has been upgraded from version 0.36 to 0.37.
+
+=item *
+
+L has been upgraded from version 1.89 to 1.92.
+
+=item *
+
+L has been upgraded from version 1.007 to 1.012.
+
+=item *
+
+L has been upgraded from version 1.85 to 1.89.
+
+=item *
+
+L has been upgraded from version 1.50 to 1.51.
+
+=item *
+
+L has been upgraded from version 2.213 to 2.218.
+
+=item *
+
+L has been upgraded from version 2.213 to 2.222.
+
+=item *
+
+L has been upgraded from version 0.38 to 0.39.
+
+=item *
+
+L has been upgraded from version 2.150010 to 2.150013.
+
+=item *
+
+L has been upgraded from version 2.143 to 2.145.
+
+=item *
+
+L has been upgraded from version 1.859 to 1.860.
+
+=item *
+
+L has been upgraded from version 3.21 to 3.24.
+
+=item *
+
+L has been upgraded from version 1.11 to 1.12.
+
+=item *
+
+L has been upgraded from version 1.38 to 1.39.
+
+=item *
+
+L has been upgraded from version 0.035 to 0.036.
+
+=item *
+
+L has been upgraded from version 0.280242 to 0.280243.
+
+=item *
+
+L has been upgraded from version 7.76 to 7.78.
+
+=item *
+
+L has been upgraded from version 1.14 to 1.15.
+
+=item *
+
+L has been upgraded from version 3.57 to 3.63.
+
+=item *
+
+L has been upgraded from version 3.57 to 3.63.
+
+=item *
+
+L has been upgraded from version 1.97 to 2.02.
+
+=item *
+
+L has been upgraded from version 2.41 to 2.43.
+
+=item *
+
+L has been upgraded from version 1.04 to 1.08.
+
+=item *
+
+L has been upgraded from version 1.42 to 1.44.
+
+=item *
+
+L has been upgraded from version 3.94 to 3.95.
+
+=item *
+
+L has been upgraded from version 1.14 to 1.15.
+
+=item *
+
+L has been upgraded from version 0.2311 to 0.2312.
+
+=item *
+
+L has been upgraded from version 0.96 to 0.97.
+
+=item *
+
+L has been upgraded from version 1.64 to 1.65.
+
+=item *
+
+L has been upgraded from version 1.14 to 1.15.
+
+=item *
+
+L has been upgraded from version 0.090 to 0.096.
+
+This fixes CVE-2026-7010 and CVE-2026-7017.
+
+=item *
+
+L has been upgraded from version 1.55 to 1.56.
+
+=item *
+
+L has been upgraded from version 2.213 to 2.223.
+
+This fixes CVE-2025-15649, CVE-2026-48961, CVE-2026-48962, and CVE-2026-48959.
+
+=item *
+
+L has been upgraded from version 0.43 to 0.44.
+
+=item *
+
+L has been upgraded from version 2.005002 to 2.005003.
+
+=item *
+
+L has been upgraded from version 5.20250702 to 5.20260708.
+
+=item *
+
+L has been upgraded from version 1.000038 to 1.000039.
+
+=item *
+
+L has been upgraded from version 1.29 to 1.30.
+
+=item *
+
+L has been upgraded from version 2.76 to 2.77.
+
+=item *
+
+L has been upgraded from version 1.69 to 1.71.
+
+=item *
+
+L has been upgraded from version 0.02 to 0.03.
+
+=item *
+
+L has been upgraded from version 0.19 to 0.21.
+
+=item *
+
+L has been upgraded from version 1.35 to 1.36.
+
+=item *
+
+L has been upgraded from version 3.45 to 3.48.
+
+=item *
+
+L has been upgraded from version 2.23 to 2.26.
+
+=item *
+
+L has been upgraded from version 1.68_01 to 1.70.
+
+=item *
+
+L has been upgraded from version 1.02 to 1.03.
+
+=item *
+
+L has been upgraded from version 1.28 to 1.29.
+
+=item *
+
+L has been upgraded from version 2.038 to 2.041.
+
+This fixes CVE-2026-12087.
+
+=item *
+
+L has been upgraded from version 3.37 to 3.41.
+
+This fixes CVE-2026-57433.
+
+=item *
+
+L has been upgraded from version 0.024 to 0.028.
+
+=item *
+
+L has been upgraded from version 3.50 to 3.52.
+
+=item *
+
+L has been upgraded from version 1.302210 to 1.302219.
+
+=item *
+
+L has been upgraded from version 2.06 to 2.07.
+
+=item *
+
+L has been upgraded from version 2.43 to 2.45.
+
+=item *
+
+L has been upgraded from version 1.70 to 1.73.
+
+=item *
+
+L has been upgraded from version 1.9778 to 1.9780.
+
+=item *
+
+L has been upgraded from version 1.36 to 1.41.
+
+=item *
+
+L has been upgraded from version 0.81 to 0.83.
+
+=item *
+
+L has been upgraded from version 1.17 to 1.18.
+
+=item *
+
+L has been upgraded from version 1.27 to 1.29.
+
+=item *
+
+L has been upgraded from version 0.9933 to 0.9934.
+
+=item *
+
+L has been upgraded from version 1.74 to 1.78.
+
+=item *
+
+L has been upgraded from version 1.43 to 1.50.
+
+=item *
+
+L has been upgraded from version 0.20 to 0.22.
+
+=back
+
+=head1 Documentation
+
+=head2 Changes to Existing Documentation
+
+We have attempted to update the documentation to reflect the changes
+listed in this document. If you find any we have missed, open an issue
+at L.
+
+Additionally, the following selected changes have been made:
+
+=head3 L
+
+=over 4
+
+=item *
+
+Auto-generation of this document now includes the line number of the source
+code, as well as its documentation.
+
+=item *
+
+It now contains information about how to find what release of
+Perl first contained an API element.
+
+=back
+
+=head3 L
+
+=over 4
+
+=item *
+
+New entry for "New object system and C syntax".
+
+=back
+
+=head3 L
+
+=over 4
+
+=item *
+
+The reference manual for writing Perl XS code has been completely rewritten and
+modernized. It is about twice the size of the old file, and promotes more
+modern XS syntax, such as ANSI signatures.
+
+=back
+
+=head1 Diagnostics
+
+The following additions or changes have been made to diagnostic output,
+including warnings and fatal error messages. For the complete list of
+diagnostic messages, see L.
+
+=head2 Changes to Existing Diagnostics
+
+=over 4
+
+=item *
+
+L