← All messages

Six places where the engine said nothing and should have

A review of the engine against every app on the development server turned up six faults that no app had hit yet, each one quiet in its own way. None of them changes what a working app compiles to: all thirty-two apps on the server rebuild byte for byte the same with the fix in place, and the build takes as long as it did.

dx() in an async request. The dump-and-stop helper marks the response done and hands the dump to apply(). It did those two things in the wrong order. apply() refuses a response that is already done, so the refusal replaced the PhloDump exception that phlo_thread() knows how to swallow, the exception handler tried one more apply(), and the request ended in a PHP fatal with no dump in it. In worker mode that fatal ends the worker. The sync debug page never had the problem. The flag is set after the apply() now, and an exception that arrives after an async answer has already left is logged and nothing more, instead of being carried in a second apply() that could only throw.

route both VERB path @k1,k2. The generated route() call wrote its arguments positionally for as long as the previous ones were present. A both route writes no async argument, so the key list landed in that slot and PHP read it as async: true: the route only answered async requests and never checked a key. Named now. The 457 both routes without keys on this server compile exactly as before.

A body that opens two pairs on one line. method keys($x) => strtr($x, [ leaves a parenthesis and a bracket open, and the parser translated the openers in order and waited for a line reading )]. The real closing line is ]), so the body ran to the end of the file and took every node after it along, without a word; php -l then failed somewhere else entirely. The closers come in reverse order now, a pair that opens and closes on the first line itself no longer counts, and a body whose closing line never comes is a build error that names the file and the line. The old advice to open such bodies with a parenthesis is gone from the guide, because prop x => [ always worked; it was the second opener that did not.

% followed by a digit. sprintf('%05d'), a URL-encoded %2Fpath or %20foo inside a string compiled to phlo('05d'), phlo('2Fpath') and phlo('20foo'). A resource is a class, and a class name cannot start with a digit, so those could never have meant anything. Names that start with a letter are rewritten as before, inside strings too, and that stays deliberate: an optional resource is reached as class_exists('x') && %x->..., and a %x that the build does not know must still become phlo('x') for that guard to work.

Two in the Control Center. A trace was read by an id taken from the URL unchecked, so trace/../../app read data/app.json and any other .json the app could open; an id now has to look like what trace writes. And saving data/app.json only checked that the text decoded: [] or "x" passed, were written, and left the app and the Control Center on a 500 until someone repaired the file by hand. The editor requires a JSON object now, and a build that fails after the save puts the previous file back, the way enabling a resource already did.

One more that is not a fault but a gap: reflect::functionIndex indexed phlo.php and debug.php and skipped functions.php, so route, view, apply, output, location and esc, the functions an app calls most, were missing from the index and from reflect::findFunction. They are natives in the index now.

We use essential cookies to make this site work. With your permission we also use analytics to improve the site.