Week in review: 18 May 2026
A recap of what shipped during the week of 18 May. Four items this week: opening transpilation of PhpSpreadsheet with its test suite, an initial conversion of CodeIgniter 4, multi-process testing finished for nette/schema and nette/utils, and a transpiler-side cleanup pass that trims a noticeable amount of superfluous emitted JavaScript.
PhpSpreadsheet conversion and tests started
phpoffice/phpspreadsheet is the most widely deployed spreadsheet library in PHP. It is also one of the larger Phase 2 candidates by some distance: tens of thousands of lines, a deep dependency on PHP's ZIP and XML extensions for the XLSX format, on GD or Imagick for embedded images, and on a substantial chunk of the math and string functions for cell-value coercion. Pext now transpiles the source tree end to end. The test suite runs, with the usual first-pass mix of green, yellow, and red that any project of this size produces on its first contact with the runtime.
The first scan surfaced the expected things: a few unimplemented ZIP entries, some XML parser edge cases around namespaced attributes, and a handful of timezone-sensitive tests that depend on the datetime work that landed for cron-expression a few weeks back. None of them are blocking. The next pass is on categorising failures and assigning them to the right runtime module.
Initial conversion of CodeIgniter 4
codeigniter4/framework is the other big arrival this week. CodeIgniter is the framework that quietly powers a large slice of the smaller-and-medium PHP-shop world, and its 4.x line is the modern PSR-compatible rewrite. The transpiler now produces a converted tree for the full framework, including the request/response layer, the routing, the validation rules, and the database abstraction. The transpiled output runs under the Pext CLI; the framework's own test suite is the next thing to run end to end.
The reason this matters beyond CodeIgniter itself is that the framework exercises a different shape of PHP from Laravel and Symfony. Less heavy reliance on attributes, fewer magic methods, more straightforward request handling. Two large frameworks with different shapes are more useful as parity benchmarks than one. The early signs are good.
Multi-process testing for nette/schema and nette/utils
nette/schema and nette/utils both moved from converted to running their suites under the multi-process test runner this week. The two packages had been at the "transpiles cleanly" stage for a while, but their tests rely on a worker layout where the runner forks per test file to enforce isolation, and the multi-process driver in the Pext test harness needed to catch up to that.
With the driver in place, the suites complete end to end. Pass rates for both packages now show up in the open source showcase, and both move to the active-work column for the remaining gaps. The fork-per-file pattern is also used by a number of other Phase 2 candidates, so the runner work generalises.
Trimming the emitted JavaScript
The fourth item this week is on the transpiler rather than on any single conversion. A pass through the code-generation layer surfaced a few categories of output that the transpiler was emitting defensively but did not actually need to emit. Redundant pvar wrappers around values that were never going to be reassigned, defensive pnull initialisations for properties whose default the runtime already handled, and a handful of duplicated boilerplate around static-method dispatch.
None of these affected correctness. They did affect the size and the readability of the transpiled tree, and they slowed down the runtime by a small but measurable amount on every property access. The cleanup pass cuts the size of typical transpiled output by enough that you can feel it on large projects (PhpSpreadsheet's converted tree is noticeably smaller after the pass), and the readability gain matters for everyone who ever has to read the emitted code, which is one of the things we promised would stay readable.