On 02/06/2025 17:57, Larry Garfield wrote:
Well, now you're talking about something with a totally separate compile step, 
which is not what Michael seemed to be describing at all.  But it seems like 
that would be necessary.


There's definitely some crossed wires somewhere. I deliberately left the mechanics vague in that last message, and certainly didn't mention any specific compiler steps. I'm a bit lost which part you think is "not what Michael seemed to be describing".


Picking completely at random, a file in Monolog has these lines in:

namespace Monolog\Handler;
...
use Monolog\Utils;
...
class StreamHandler extends AbstractProcessingHandler {
...
$this->url = Utils::canonicalizePath($stream);


My understanding is that our goal is to allow two slightly different copies of that file to be included at the same time. As far as I know, there have been two descriptions of how that would work:

a) Before or during compilation, every reference is automatically prefixed, so that the class is declared as "\__SomeMagicPrefix\Monolog\Handler\StreamHandler", and the reference to "\Monolog\Utils" is replaced by a reference to "\__SomeMagicPrefix\Monolog\Utils". There are existing userland implementations that take this approach.

b) While the class is being compiled, PHP swaps out the entire symbol table, so that the class is still called "\Monolog\Handler\StreamHandler", and the reference to "\Monolog\Utils" is to the class of that name in the current symbol table. In a different symbol table, both names refer to separately compiled classes.

The "new namespace root" in my last message is either (a) the special prefix, or (b) the actual root of the new symbol table. In either case, you need to decide which classes to declare under that root; either recursively tracking what requires what, or just where on disk the file was loaded from.


Even if we're willing to require the authors of Monolog to rewrite their library for the convenience of WordPress plugin authors, I don't see how we can get away from every class in PHP being fundamentally identified by name, and the compiler needing to manage those names somehow.

We can imagine a parallel universe where PHP declarations worked like JS or Python:

import * from Monolog\Handler;
...
$Utils = import Monolog\Utils;
...
$StreamHandler = class extends $AbstractProcessingHandler {
...
$this->url = $Utils::canonicalizePath($stream);

But at that point, we're just inventing a new programming language.


At which point, we're basically talking about "load this Phar file into a custom 
internalized namespace", which, from my limited knowledge of Phar, seems like the 
most logical way to do it.  That also sidesteps all the loading and linking shenanigans.


I don't think Phar files would particularly help. As far as I know, they're just a file system wrapper; you still have to include/require the individual files inside the archive, and they're still compiled in exactly the same way.

Whether we want to isolate "any definition you find in the directory /var/www/wordpress/wp-plugins/foo/" or "any definition you find in the Phar archive phar:///var/www/wordpress/wp-plugins/foo.phar", the tricky part is how to do the actual isolating.


--
Rowan Tommins
[IMSoP]

Reply via email to