aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-rpc/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-05 03:58:03 +0900
committernsfisis <nsfisis@gmail.com>2026-08-05 03:58:03 +0900
commit9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec (patch)
treeb1041b55bc3ed36a391370cc2f5ececc8cb386b2 /crates/shirabe-php-rpc/src
parentbe3458128ef09b3d1074b134f2822162e077e165 (diff)
downloadphp-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.tar.gz
php-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.tar.zst
php-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.zip
feat(plugin): run plugin-provided commands in a worker-side application
A same-FQCN Composer\Console\Application, hand-written under the new php/runtime/ tree, hosts CommandProvider commands inside the PHP worker: PhpCommandProxy overrides run() and forwards the stringified input, so the real Symfony machinery binds, validates and executes against the live command object, while help/list render Rust-side from a definition read back at construction. Reverse \Shirabe\RustCommandStub rows let a plugin command invoke built-in commands back in the Rust process, keeping every command on the side whose helper set it was written for. Composer\EventDispatcher\Event moves from a generated stub to a dual-mode runtime class: the real BaseCommand::initialize constructs a PreCommandRunEvent natively in the worker, which a proxy-only constructor guard rejected. Its PRE_COMMAND_RUN dispatch reaches a new EventDispatcher stub whose dispatch supports the observably-no-op no-listener case and fails explicitly otherwise. The stub generator now accepts runtime-provided classes as stub bases (never as targets) and cross-checks the Application handoff property table against the real class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-php-rpc/src')
-rw-r--r--crates/shirabe-php-rpc/src/lib.rs24
1 files changed, 21 insertions, 3 deletions
diff --git a/crates/shirabe-php-rpc/src/lib.rs b/crates/shirabe-php-rpc/src/lib.rs
index ba5443d2..ef11d542 100644
--- a/crates/shirabe-php-rpc/src/lib.rs
+++ b/crates/shirabe-php-rpc/src/lib.rs
@@ -563,8 +563,8 @@ const GLUE_SCRIPT: &str = include_str!("../php/worker.php");
/// generator's `--check` mode verifies both the file contents and this list).
const STUB_FILES: &[(&str, &str)] = &[
(
- "Composer/EventDispatcher/Event.php",
- include_str!("../php/stubs/Composer/EventDispatcher/Event.php"),
+ "Composer/EventDispatcher/EventDispatcher.php",
+ include_str!("../php/stubs/Composer/EventDispatcher/EventDispatcher.php"),
),
(
"Composer/Script/Event.php",
@@ -640,6 +640,24 @@ const STUB_FILES: &[(&str, &str)] = &[
),
];
+/// Hand-written worker-side classes (two-world implementations with behavior of their own, not
+/// mechanical proxies), written into the same autoload directory as the generated stubs so the
+/// prepended stub autoloader resolves their FQCNs ahead of any real class file.
+const RUNTIME_FILES: &[(&str, &str)] = &[
+ (
+ "Composer/Console/Application.php",
+ include_str!("../php/runtime/Composer/Console/Application.php"),
+ ),
+ (
+ "Composer/EventDispatcher/Event.php",
+ include_str!("../php/runtime/Composer/EventDispatcher/Event.php"),
+ ),
+ (
+ "Shirabe/RustCommandStub.php",
+ include_str!("../php/runtime/Shirabe/RustCommandStub.php"),
+ ),
+];
+
struct Worker {
stream: UnixStream,
// Also queried for its exit status when a socket read/write fails, to tell a dead worker
@@ -707,7 +725,7 @@ fn spawn_worker() -> anyhow::Result<Worker> {
std::fs::write(&script_path, GLUE_SCRIPT)?;
let stubs_dir = tempdir.path().join("stubs");
- for (relative_path, contents) in STUB_FILES {
+ for (relative_path, contents) in STUB_FILES.iter().chain(RUNTIME_FILES) {
let path = stubs_dir.join(relative_path);
std::fs::create_dir_all(path.parent().expect("stub paths have a parent"))?;
std::fs::write(&path, contents)?;