pperl 0.6.24#
2026-10-15 to 2026-10-25, 457 commits.
JIT and parallelization#
Loops over arrays sized with $#a stay compiled: a loop that stores into an array whose size was set with
$#a = $n, directly or through a reference, now runs as compiled code. It used to fall back to the interpreter on every element until the JIT gave the loop up, and ran about three times slower than the same loop over an array filled with values first.& | ^ under use v5.28 and later are compiled: with the
bitwisefeature, whichuse v5.28and later versions turn on, the numeric&,|and^are separate operations, and a loop holding one of them ran in the interpreter. Such loops are now compiled, signed underuse integerand unsigned otherwise, as perl computes them.Index arithmetic no longer decides how a statement computes: in
$y[$n] = $C[$i] + $C[$i + 64]over an array of floating-point numbers, the integer$i + 64made the compiled loop treat the whole statement as integer arithmetic, and every element fell back to the interpreter until the loop was given up. Arithmetic that only computes an array index is now plain integer arithmetic, its overflow checked, whatever the elements hold. Loops of this kind that ran about four times slower when every value they computed was 0.0, such as a reverb fed silence, now run as fast as on any other input.Float arithmetic survives a run of zeros: a loop that computes with arrays of floating-point numbers, such as an audio filter fed silence, kept falling back to the interpreter while every value it saw was zero, and was then replaced by a slower form that also ran the signal after the silence. An array of floats that also holds a value perl keeps as an integer too is now recognised as an array of floats.
A copied array element keeps its spelling: in compiled code, copying an array element that holds a number written as a string, such as
my $x = $list->[$i]of “-2.0”, “0.10” or “1e1” after it had been compared numerically, gave the number instead: “-2”, “0.1”, “10”. The copy is now the string, as in perl. Complete::Sah’s completions of floating-point values were affected.A
nextout of a branch that was cold no longer crashes: a loop nest compiled while anifbranch holding its own loop and anexthad never run, as inif ($four) { while (...) { ... } next }, could crash pperl once that branch ran, when the enclosing sub returned. It runs as under perl now.A loop that increments the position it reads no longer crashes: a loop such as
for (my $k = 0; $k < length $s; $k++) { $n += ord substr($s, $k, 1) }aborted pperl once it ran often enough to be compiled. Such loops now run compiled.Negative array indexes stay compiled:
$a[-1], or an index such as$n - 100that goes below zero, counts from the end of the array in compiled code. In a loop over an array of plain numbers, each such access used to fall back to the interpreter, and a loop doing it often was given up.Loops over unsigned 64-bit integers stay compiled: a loop whose numbers go past 9223372036854775807, perl’s unsigned integers as in 64-bit hashes, masks and random numbers, or a C function returning
uint64, fell back to the interpreter on every trip until the JIT gave the loop up, and one naming such a number as a constant, such as0x9E3779B97F4A7C15, was never compiled. Such loops now run compiled with perl’s exact values, underuse integertoo; a result perl computes as a floating-point number still takes the interpreter’s path. A loop that only reads a large integer, such as an argument of -9223372036854775808, no longer leaves the compiled code each time it starts either.
Language and runtime#
END blocks run after an exit during compilation: when a program exits or dies while it is still being compiled, in a
BEGINblock or in the import a-MModule=...switch calls, theENDblocks compiled so far now run and can set the exit status, as in perl. A failing test file that exited this way reported success, which broke the test suite of Test::Needs and every CPAN distribution that needs it. AnENDblock that sets$?to 0 afterexit 5now makes the exit status 0.Arguments that are not UTF-8: an argument that is not valid UTF-8, such as a file name in Latin-1, made pperl stop with an internal error before running anything. Arguments,
-ecode, script names and-Idirectories now reach the program byte for byte, as in perl. Andpperl -e CODE a -xhands its programaand-xinstead of rejecting-xas an unknown option.A regex match creates no variable: a pattern match no longer creates
${^RE_DEBUG_FLAGS}inmain::, and no longer looks that variable up on every match. Code that walks the main symbol table while matching names, such as Devel::Symdump, saw it appear under its iterator and warned “Use of each() on hash after insertion”.The built-in library is a directory on disk: the modules built into pperl are a real directory now,
$Config{privlibexp}under~/.cache/pperl, which@INC,%INCand__FILE__name. It is written the first time a program looks at it - a file test,opendir,chdir,glob,abs_pathor reading a module as a file - never at startup, and holds the modules as perl installs them, documentation included, with perl’spod/files andConfig.pod. Tools that search@INCas a filesystem, such as Pod::Find, Module::Path and Module::List, find pperl’s own modules now.@INC hooks see built-in modules: a code reference at the front of
@INC, as Test::Without::Module anduse lib sub {...}put it there, is asked for a built-in module before pperl’s own copy is used, as in perl. Such a hook can hide a built-in module or serve its own version of it. A directory in@INCstill never replaces a built-in module.Modules fall back to Perl when their compiled part is missing: a module whose compiled part pperl does not have now fails to load with perl’s message for that case, “Can’t locate loadable object for module … in @INC”, instead of “dynamic loading not available”. Modules that try their compiled part and go on in Perl without it look for exactly that message, so DateTime and others now run in their Perl implementation where they died before.
A built-in module’s file runs however it is reached: when a built-in module’s file reaches perl without a plain
require- served by an@INChook such as lib::filter’s or a FatPacker one, read withdo FILE, or checked withperl -c- its compiled part now loads, as perl finds the module’s shared object. Such a file used to die “Can’t locate loadable object”, which took Moo down with lib::filter.Installed scripts run with pperl:
$Config{perlpath}and$Config{startperl}name the pperl binary that is running. They named/usr/bin/perl, so the commands a distribution installs withpperl --cpanstarted the system’s perl, or failed on a machine without one.pperl starts faster: a short script runs in about a quarter less time, as the binary has less than half the addresses to fix up when it is loaded and a run no longer reads the CPU topology unless it goes parallel. The binary is also 5.5 MB smaller. A panic inside pperl itself, which is always a bug, no longer names a source file and line.
Catching errors from built-in modules no longer leaks memory: a built-in module that died with an error built at run time left a few hundred bytes behind every time, so a program catching such errors in a loop with
evalgrew without bound. Peta::FFI, Storable, Opcode, POSIX and the other built-in modules now free everything before they die, andopsetwith an unknown name no longer leaks the set it was building, as it does under perl. The error messages are unchanged.
Modules#
DBI 1.655: the built-in DBI is 1.655, up from 1.651.
DBD::DBMaccepts only a module name asdbm_typeanddbm_mldbm, so a file path given there is no longer loaded and run, andDBD::Fileno longer reads a table linked into a directory whose name merely begins with that off_dir. These are the fixes for CVE-2026-78030 and CVE-2026-15392.DBI: sql_type_cast and fetchrow_hashref as in DBI under perl:
DBI::sql_type_castreturns what DBI’s compiled version returns, soSQL_INTEGERrefuses “3.14”, “1e3” and “inf”,DBIstcf_DISCARD_STRINGleaves only the number, and the two flags have DBI’s values. A plain number withSQL_INTEGERandDBIstcf_DISCARD_STRINGis handled too, where DBI 1.655 aborts perl.fetchrow_hashrefwith a key name that holds no column list, fromFetchHashKeyNameor its argument, sets the handle’s error and returns undef instead of dying whateverRaiseErrorsays, and a number as that name is taken as a name.PDL: update_data_from reads the value of a tied source:
$pdl->update_data_from($bytes)fetches a tied or otherwise magical$bytesand copies its current value, as PDL does under perl. It used to copy whatever that scalar last held.PDL: the operator overloads are PDL’s own subs:
PDL::overload_plusand the other handlers PDL installs for its operators exist under their names and are whatoverload::Methodreturns, as with PDL under perl. An error raised through an operator, such as a broadcast mismatch in$a + $b, now names PDL’s own line and the handler in its backtrace, and so does a warning such as “isn’t numeric” for a string operand. A redefinedPDL::plus, or a subclass’s owninplace, is now what the operators use.PDL::FFT loads quietly under -w:
use PDL::FFTunder-wno longer warns “Subroutine PDL::realfft redefined”, as it doesn’t with PDL under perl.Pod::Text and Pod::Man 6.1.1: the POD formatters are those of podlators 6.1.1, up from the 6.0.2 that perl 5.44.0 ships. Formatting a document whose
=overnesting brings the margin to the output width no longer loops forever while the output fills memory (CVE-2026-82560).Pod::Manlists with tags now use.TPand the fixed-width font isCR, for groff 1.24.Text::LineFold no longer repeats its input:
foldon text holding form feeds, vertical tabs or other special breaks returned the whole text once for every piece between them, so the output grew with the square of the input (CVE-2026-8594). Each piece is folded once now; the Text::LineFold of CPAN still has the fault.Hash::Util::FieldHash is built in: perl’s field hashes for inside-out classes, whose entries vanish with the object they are keyed by, together with
id,id_2obj,registerand idhashes. It was the one module of perl’s own library that would not load, andB::Hooks::EndOfScope,namespace::clean,namespace::autocleanand Mojolicious, which need it, now install from CPAN and pass their tests.Five more CPAN modules with compiled parts are built in:
XString0.005,Test::LeakTrace0.17,PerlIO::utf8_strict0.010,Scalar::Util::Numeric0.40 andSub::Identify0.14. Each passes its own test suite with the results it has under perl. Distributions that need one of them, such as DateTime, Specio, PPI and Template Toolkit, get past it when they are installed from CPAN.Sub::Name is built in:
Sub::Name0.28, which renames a sub forcallerand stack traces, passes its own tests as under perl. It runs the code ofSub::Util::set_subname, which perl ships and which was taken from it, so renaming a sub under the debugger no longer leaks a reference to its%DB::subentry with every call, asSub::Namedoes under perl.B::COW is built in:
B::COW0.007 reports whether a string shares its buffer copy-on-write and the share count, with the same answers as under perl, and passes its own tests.Digest::SHA1 is built in:
Digest::SHA12.13, the SHA-1 module older code uses where newer code usesDigest::SHA, passes its own tests with the results it has under perl. Its digests are computed by the built-inDigest::SHA, with the processor’s SHA instructions where it has them.sha1_transformgiven more than 64 bytes uses the first 64, where perl aborts.String::CRC32 is built in:
String::CRC322.100 computes the CRC-32 of a string or of what a filehandle reads, with the results it has under perl, and passes its own tests. The CRC is computed by the zlib of the built-inCompress::Raw::Zlib. A filehandle whose read fails, such as a closed one, gives the CRC of no data, where perl crashes.Crypt::OpenSSL::Random is built in:
Crypt::OpenSSL::Random0.17 draws bytes from OpenSSL’s random-number generator and seeds it, in the builds that include Net::SSLeay, and passes its own tests. It reaches libcrypto through Net::SSLeay, so both draw from one generator. Asking for 0 bytes returns the empty string, where perl returns stray memory; a negative count returns false, and 0 from Net::SSLeay’sRAND_bytes, where perl exits.URL::Encode is built in:
URL::Encode0.03 and its fast halfURL::Encode::XSencode and decode URL-encoded strings and split query strings into their parameters, with the results they have under perl, and pass their own tests. The fast half is used, as under perl when it is installed, and is about 17 times as fast as the pure-Perl one.Text::LevenshteinXS is built in:
Text::LevenshteinXS0.03 computes the edit distance of two strings, with the results it has under perl, and passes its own tests. Long strings work: perl needs memory for a table of both lengths multiplied, and crashes when that memory is not there (two strings of 20000 bytes need 1.6 GB).Math::Random::MT is built in:
Math::Random::MT1.17, the Mersenne Twister random-number generator, gives the same sequences as under perl for the same seeds, and passes its own tests.Data::UUID is built in:
Data::UUID1.227 makes time-based and name-based UUIDs and converts them, passing its own tests with the results it has under perl. Its name-based UUIDs are computed by the built-inDigest::MD5. Where perl reads or writes past a string - a binary UUID shorter than 16 bytes, a Base64 UUID that is too short, too long or has bytes above 0x7F, a hex UUID that ends inside a byte - the result is zero-filled, cut to 16 bytes, or an error instead.Params::Util is built in:
Params::Util1.102, whose checks such as_STRING,_HASHand_INSTANCEmany CPAN modules validate their arguments with, passes its own tests with the results it has under perl. It did not load at all before, so PPI, Package::DeprecationManager, Config::MVP and the modules that need them could not be installed from CPAN.Class::Load::XS is built in: the compiled
is_class_loadedofClass::Load::XS0.10, which Class::Load uses when it is there, passes its own tests with the results it has under perl. Class::Load itself, which loads it, is installed from CPAN as before.Template::Stash::XS is built in: the compiled stash of Template Toolkit 3.106, which the Template Toolkit uses by default, passes the Template Toolkit’s own tests with the results they have under perl. The Template Toolkit itself, which did not install without it, now installs from CPAN with
pperl --cpan. A method that dies “Can’t locate object method” no longer overwrites the caller’s arguments, andseton a value that is not a reference dies with an error where perl crashes.Package::Stash::XS is built in:
Package::Stash::XS0.32, the compiled implementation ofPackage::Stashthat Moose, namespace::clean and many others read and change symbol tables through, passes its own tests with the results it has under perl.Package::Stashitself comes from CPAN and now uses it, as it does under perl, instead of its pure-Perl implementation.List::MoreUtils::XS is built in: the compiled backend of
List::MoreUtils0.430 passes its own tests and those of the front end with the results they have under perl, andList::MoreUtils, installed from CPAN, now uses it instead of its pure-Perl implementation. Where perl crashes or answers wrongly, pperl does not: a block that is a compiled sub, arrays with holes, objects overloading@{}over a hash, and<=>overloading that gives no number.reduce_u,reduce_0andreduce_1no longer overwrite the caller’s$_, andfrequencyno longer leaks.Term::ReadKey is built in:
Term::ReadKey2.38 sets terminal modes, reads keys with a timeout or without blocking, and reports the terminal’s size, speed and control characters as it does under perl; modules that need it, such asCPAN::Uploader, now install from CPAN. Where perl aborts, pperl does not: a timed read on a closed handle or on a descriptor of 1024 or above, andSetTerminalSizewith a width or height ten characters long.GetSpeedof a handle that is not a terminal returns 0 for both speeds where perl returns leftover memory.Filter::Util::Exec, Filter::tee and Filter::decrypt are built in: the source filters of Filter 1.65 that run a program through a command (
Filter::exec,Filter::sh,Filter::m4), copy it to a file or decrypt it work as they do under perl and pass the dist’s own tests. Where perl crashes, pperl does not: these filters, andfilter_addof Filter::Util::Call, called while nothing is being compiled. A command that stops reading early, such ashead -n 1on a long source, no longer kills the program without a word or leaves it empty: what the command wrote is compiled.Filter::cppis not available, because pperl’s configuration names no C preprocessor.IO::Tty and IO::Pty are built in: IO-Tty 1.31 allocates pseudo-terminals, names them, sets their window sizes and defines the terminal constants as it does under perl, and passes the dist’s own tests. Where perl crashes or reports a length it read from unrelated memory, pperl does not:
IO::Tty::unpack_winsizeof undef, a number or a reference dies saying the length is 0.Moose loads: the compiled part of Moose 2.4001 is built in, so Moose’s own modules load and pass Moose’s own tests with the results they have under perl.
pperl --cpaninstalls Moose and what is built on it, Catalyst and Dist::Zilla among them: a distribution’s check for a working C compiler (ExtUtils::HasCompiler) answers yes when the compiled part it needs is built in. Where perl crashes on a malformed metaclass or method object, pperl dies with an error or leaves it alone.JSON::XS is built in: JSON-XS 4.04 encodes and decodes JSON, parses it incrementally and calls
TO_JSON,FREEZEandTHAWas it does under perl, and passes its own tests; Types::Serialiser, whose booleans JSONtrueandfalsedecode to, is built in with it. Where perl crashes, pperl does not: a method called on something blessed intoJSON::XSthatnewdid not make dies with an error, andJSON::XS::CLONEcalled by hand no longer breaksnew.YAML::XS and YAML::PP are built in: YAML-LibYAML 0.910.0 loads and dumps YAML with the settings, objects and output it has under perl and passes its own tests, over YAML::PP 0.43.0, pperl’s YAML engine. YAML is read as the YAML 1.2 specification reads it, so the few documents libyaml reads otherwise, rejects or wrongly accepts follow the specification, and
Dumpescapes U+2028 and U+2029 so that what it writes loads back unchanged. Where perl crashes or refuses, pperl does not: the object interface loading a flow mapping inside a flow sequence, and dumping strings of latin-1 bytes. A document that does not parse dies with YAML::PP’s account of the problem: nearly always the same document and line, in other words.FFI::Platypus is built in: FFI-Platypus 2.12 calls C functions with every type it offers, from integers, strings and arrays to records by value, closures and custom types, as it does under perl, and no C compiler is needed to install it. Where perl fails, pperl does not: reading an array member of a record no longer leaks memory, an index past an opaque array member warns instead of reading beyond the record, and a hash reference passed for a pointer no longer crashes. A regex capture or a tied scalar passed as an argument passes its value, where perl passes 0, or no string at all, which crashes
strlen($1), and a callback that a library calls from a thread of its own stops the program with a message where perl crashes.FFI::Build is built in: a CPAN module that ships C code for FFI::Platypus to call, built at install time with FFI::Build, now installs, passes its tests and runs under pperl when a C compiler is on
PATH, as it does under perl. Capture::Tiny, which FFI::Build uses, is built in with it.DynaLoader loads shared libraries:
dl_load_file,dl_find_symbol,dl_unload_file,dl_findfileand the rest work on any C library as they do under perl, and FFI::CheckLib, which finds libraries with them, is built in. A module’s compiled part is still never loaded from a file:XSLoaderandDynaLoader::bootstrapload only pperl’s built-in modules. Unloading a library that failed to load no longer crashes, as it does under perl when FFI::CheckLib meets a linker script such aslibm.so.XSLoader checks the version a module asks for:
XSLoader::load($module, $VERSION)dies “… object version … does not match bootstrap parameter …” when the built-in compiled part is of another version, as it does under perl, and loads a built-in module’s compiled part even when nothing has required the module yet.Peta::FFI reaches more of any C library: signatures gain fixed-width integers from
i8tou64,bool, variadic functions such asioctlandsnprintf, strings the caller must free, and C objects as Perl objects whose destructor runs with their last reference.functionandattachprepare a C function once and call it as a Perl sub, a function pointer can be called by its address, anderrnoreports what a call left behind. A callback that a library calls from a thread of its own now stops the program with a message instead of corrupting it, and Peta::FFI::EventSource brings such a library’s events to Perl through a file descriptor that AnyEvent, EV, Mojo::IOLoop or aselectloop watches.scanfinds the libraries in the directories it is given, or inPETA_FFI_PATHand the dynamic linker’s own, and lists only the files this program can load.Peta::FFI passes C structs, arrays and long doubles:
recorddeclares a C struct as a Perl class with an accessor per member, and a signature passes and returns it by value or by pointer, callbacks included. Signatures gain pointers to numbers and strings for out-parameters, arrays the function reads and changes in place,long doubleand the complex types, and an output buffer that holds what the function wrote.symbol,fetch,storeandvariableread and write a library’s global variables and any typed value in memory. FFI::Platypus now runs on the same engine, so whatever it can call, Peta::FFI can.Peta::FFI reaches C unions:
uniondeclares one asrecorddeclares a struct, with every member at its start, to be passed by pointer and read and written in memory, asSDL_PollEventfills anSDL_Event. Passing a union by value is refused, because on some platforms that would call the function wrongly instead of failing. A record member that is itself a record now reads as an object of its class and is set from one.Peta::FFI takes what C functions hand over: a handle or a string a function stores through a pointer, as
sqlite3_opendoes, becomes the caller’s object or string, and arrays of handles, of records and of pointers ended by NULL can be passed. An array the function allocates itself, its length given by the result, by another argument or by a NULL at its end, comes back as a Perl array of objects, strings, records or numbers. Everything is freed with the library’s own functions once nothing uses it, so a record taken from such an array still reads its strings for as long as it lives.Peta::FFI reads arrays C lends and sets strings in records: an array a function hands out from memory it keeps, as libxkbcommon hands out a keymap’s keysyms, is written
&T[r],&T[#k]or&T[0]and is copied without being freed, whether it comes through an argument or, as&T[#k]or&T[0], as the result. A record’s string member can now be set from Perl: the record keeps its own copy for as long as it lives,undefpasses NULL, and a string C put there is never freed by Perl. When C moves the strings between records, as sorting an array of them does, each string stays alive with the record that now points to it.Peta::FFI reads byte buffers C allocates: a buffer a function allocates and hands over through a pointer, with its length in the result or in another argument, is written
*P[r]or*P[#k]. It arrives as one byte string, NULs and all, and is then freed with the library’s own function, which is how librados’srados_mon_commandreturns its reply. Bytes a function only lends,&P[r]or&P[#k], are copied and never freed, and a callback handed bytes with their length,&P[#k], gets them as a string.Peta::FFI::Pool runs C calls that may hang: a function prepared with Peta::FFI runs on one of a pool’s threads, with a deadline, so
statfson a dead NFS mount no longer needs a child process with a timeout. Each call is reported as an event, through a descriptor any event loop can watch as a Peta::FFI::EventSource: done, with its result and what it wrote back; timed out; or busy, when every thread is taken. A call that returns after its deadline changes nothing.Peta::FFI::Queue takes callbacks from a library’s own threads: a closure made with
queue => $queuemay be called on any thread, as librados calls its monitor log and watch callbacks. It copies its arguments into the queue, returns a value given once, and its sub runs later, when Perl’s event loop takes the queue’s events through a Peta::FFI::EventSource. A queue holds a bounded number of calls and counts those it had to drop.Loops that call C functions run compiled: a loop calling a C function prepared with Peta::FFI or FFI::Platypus used to stay out of the JIT entirely. When the function takes and returns plain integers, pointers or floating-point numbers, the compiled loop now calls it directly; other calls, and any call while C holds a Perl callback, still go through the library as before.
C functions called often cost less: a C function prepared with Peta::FFI’s
functionorattach, or attached with FFI::Platypus, that takes and returns plain numbers or pointers is compiled into machine code of its own once it has been called a few thousand times. A call oflabsorldexpoutside a compiled loop then takes about 30% less time, with the same results and the same errors as before. A function that is seldom called is never compiled, so declaring a library’s functions costs no more than it did.Peta::LMDB and Peta::PCRE2 are now Peta::FFI::LMDB and Peta::FFI::PCRE2: pperl’s own modules for C libraries live under Peta::FFI, beside Peta::FFI::UUID. Programs that load Peta::FFI::LMDB or Peta::FFI::PCRE2 work as before, with the class names, error class and
$Peta::FFI::LMDB::DBM_WRITErenamed to match; the old names no longer load.Cairo survives a libcairo without a function it calls: when the installed libcairo lacks a function a Cairo method needs, as an older release does, calling the method stopped the whole program. It now dies with a message naming the function, which
evalcatches, as the other library modules already did.EV and Coro no longer need a system perl: the built-in
EVandCorostart withuse common::sense, which pperl did not carry, so they loaded only where a system perl’s copy was on@INC, andAnyEventotherwise fell back to its pure-Perl event loop without a word.common::sense3.75 is built in now, with the warnings and features it sets under perl 5.44.Event runs on libev, and EV and Event share signals:
Eventnow waits for descriptors, signals and time through libev, the engine behindEV, and reports the same readiness and conditions as before; its timers and event queues are its own, as they were. A signal that both modules watch now reaches the watchers of both. Under perl the module that installed its handler last took it, and an EV loop reading signals through a signalfd hid them from Event entirely.XML::Parser, HTML::TokeParser and PDL::IO::Pic load without a system perl: they need
File::ShareDir,HTML::TagsetandFile::Which, which pperl did not carry, and loaded only where a system perl’s copy was on@INC. Those three are built in now, withClass::Inspector, whichFile::ShareDirneeds;HTML::LinkExtoris fixed with them.XML::Parser parses with libxml2:
XML::ParserandXML::Parser::Expatread documents with libxml2 2.15 or newer, and the expat library is no longer needed. Handlers see what they saw over expat: the same calls with the same arguments, character data split where expat splits it, the same positions and source text fromcurrent_byte,recognized_stringandoriginal_string, and expat’s error messages. A document withstandalone="yes"has the parameter entities of its internal subset read, as XML requires; expat left them unread and then refused the document.Devel::Cover measures coverage: the compiled part of Devel::Cover 1.52 is built in, so with the distribution installed by
pperl --cpan Devel::Cover,pperl -MDevel::Covercollects statement, branch, condition and subroutine coverage, andcoverreports it, with the same counts as perl. Devel::Cover’s own test suite passes. While it collects, loops are not compiled, since compiled code would bypass the counting.JSON::PP works in compiled code:
JSON::PPencodes and decodes with the same compiled engine asJSON::XS, with JSON::PP’s own options, results and error messages, about 6 times faster at encoding and 14 times at decoding. CPAN’s metadata files and everything else that reads or writes JSON through it gain with it. Where JSON::PP went wrong it no longer does:decode_prefixcounts characters as documented, what aFREEZEmethod returns is encoded as JSON, the incremental parser keeps Latin-1 text and the rest of its buffer as they are, and bare keys keep their non-ASCII characters.Text::CSV is built in: Text::CSV 2.06 comes with pperl, and its pure-Perl engine
Text::CSV_PPparses, warns and checks its settings as Text::CSV_XS 1.65 does. A CR at the very end of the input after an empty last field is error 2032, as after any other field; a failedprintreturns “” and warns where it was called; a separator, quote or line end longer than 16 bytes is refused. Installing Text::CSV withpperl --cpangets the same engine, and Text::CSV_XS installs over it with all of its own tests passing.
Command line#
pperl -S finds the program on PATH:
pperl -S proveruns theproveinstalled on the search path, asperl -Sdoes; pperl rejected the switch.A program’s arguments are its own: pperl’s switches, such as
--parallelor--no-jit, are read only before the program, as perl reads its own. After it, they reach the program in@ARGV; pperl used to take them out, sotool.pl --parallel 4 listsaw only4 list.pperl -v names the build and credits perl: the first line names what kind of binary it is, its native tier and added features such as
dbi,pdlorshell, the second is the copyright, and the text says pperl is “compatible to perl 5.44 by Larry Wall and others”.pperl -Vstill lists everything. Tests that read-vas perl’s, such as those of IPC::System::Simple and Expect, pass.pperl –cpan no longer asks you to set PPERL5LIB: pperl finds what it installs into your own tree without it, so the advice that ended every install is gone.
pperl –cpan –system installs where pperl looks: a system-wide install now goes to
/usr/local/share/pperl/site_perl, which every pperl searches, with its scripts and manuals beside it; it used to land in a directory pperl never looked in. It now stops before downloading anything when the account may not write there, and says to run it as root.pperl –cpan applies distribution preferences: a CPAN.pm distroprefs file under
~/.pperl/cpan/prefsthat matches a distribution now takes effect, including its patches, which are looked up beside it. A.ymlpreference used to be read only where the separate YAML distribution happened to be installed, and now uses pperl’s built-in YAML::XS. Any patch a preference named stopped the install, because no patch command was configured.pperl –cpan installs XS distributions it has a substitute for: each run first fetches pperl’s pure-Perl substitutes for distributions with a compiled part from
https://perl.petamem.com/downloads/cppan, so a substitute published after your pperl applies to it too. Text::CSV_XS installs and runs on the Perl engine of Text::CSV, true, multidimensional and bareword::filehandles on perl’s own features, Scalar::Readonly, Test::Taint, Regexp::Util, next::XS and Socket6 on its built-in modules, and Crypt::SSLeay (Net::SSL) on its OpenSSL binding, where it no longer builds under perl with OpenSSL 3; the few places where their own tests show a difference are marked as known in them.PPERL_CPPAN_URLnames another address, and set empty it skips the fetch.JavaScript::QuickJS runs on QuickJS-NG:
pperl --cpaninstalls JavaScript::QuickJS as a binding over the QuickJS-NG library (libqjs.so.0, on Arch Linux thequickjs-ngpackage), used where it is installed; without it the module installs, its tests skip and say why, and it works once the library is there. The distributions that need it, such as Data::Sah and the Perinci family, install with it. Where QuickJS-NG differs from the QuickJS the CPAN distribution bundles, its own behaviour shows: its error messages, and a Date’sgetTimeas a floating-point number.pperl –cpan downloads over https with curl or wget: like perl’s own first-run setup, it now finds
make,tar,gzip,gpg,wgetorcurland the other tools CPAN.pm uses on yourPATH. A pperl built without TLS support therefore fetches from CPAN over https throughwgetorcurlinstead of falling back to plain http, and the XS substitutes come the same way.pperl –cpan builds the pure-Perl form of a distribution: it asks every build for the distribution’s Perl-only variant, as
PUREPERL_ONLY=1and--pureperl-onlydo, so a distribution such as Params::Validate that has a Perl implementation beside its compiled one installs instead of failing for want of a C compiler. A module that does not load without its compiled part is named and kept, not removed: Params::Util switches to its Perl half when its tests ask for it, and those tests now run.Config names the C compiler:
$Config{cc}, its flags, its preprocessor andgccversiondescribe the C compiler found onPATH(cc, gcc or clang), so FFI::Build compiles the C libraries a distribution bundles and Devel::CheckLib’s probes run.usedlanddlsrcsay what perl’s say on Linux, as DynaLoader loads shared libraries. Modules with a compiled part still load only when they are built in, and ExtUtils::CBuilder’shave_compilerstill says no.@INC includes the architecture directories of PERL5LIB and -I: as under perl, each entry’s
x86_64-linuxsubdirectory, and that of each of its version directories, comes ahead of the entry when it exists. An installer puts a distribution’s Perl files there whenever the distribution carries anything architecture-dependent, so modules installed into a local::lib bycpanm -l, Alien modules among them, are now found.pperl --cpaninstalls into its tree’s architecture directory as perl’s installers do, and pperl’s own tree is searched the same way.ipps runs programs as functions: with the new
autorunsetting on, calling a sub that does not exist runs the program of that name and returns its output, a list of lines in list context, as inwhoami()ormy @files = ls('*.pl').:programs ls catmakes such names subs that need no parentheses, whetherautorunis on or not, and:programsalone lists them. A program that cannot be run is an error, and the exit status is in$?as for backticks.
Documentation#
Links in the changelog: the entries of every version link the modules, built-in functions, command-line options, guides and tutorials they name to their pages, in every language of the documentation.