aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/event_dispatcher
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-20 09:50:58 +0900
committernsfisis <nsfisis@gmail.com>2026-08-20 09:50:58 +0900
commit94507ec2f265ca9400d64d42036ca1e8722e27da (patch)
treefca64359a8d9257717bc41822ae7119bdc3e2b26 /crates/shirabe/src/event_dispatcher
parent80c2120a64ce9b989da288ce1fcf80dec5cf38c1 (diff)
downloadphp-shirabe-94507ec2f265ca9400d64d42036ca1e8722e27da.tar.gz
php-shirabe-94507ec2f265ca9400d64d42036ca1e8722e27da.tar.zst
php-shirabe-94507ec2f265ca9400d64d42036ca1e8722e27da.zip
fix(event-dispatcher): let a PHP script reach the Composer object graph
A PHP script listener that walks the event it receives (Laravel's Illuminate\Foundation\ComposerScripts::postAutoloadDump asks for $event->getComposer()->getConfig()->get('vendor-dir')) aborted the run with `unknown Rust handle 2`. The event's getComposer/getIO answers register an entity in the R table and hand back its rhandle, but ScriptRpcDispatcher resolved only rhandle 0 and the one event handle of the call in flight, so it could not serve a method on a handle it had just minted itself. The R-table lookup PluginRpcDispatcher already does is now dispatch_r_table_method, shared by both. The stubs that graph hands out extend and implement the real Composer contracts (Composer\Package\PackageInterface and the rest), which live in the Composer PHP runtime and not among the generated stubs or guards, so execute_event_php_script loads that runtime the way the plugin and command-class paths do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/event_dispatcher')
-rw-r--r--crates/shirabe/src/event_dispatcher/event_dispatcher.rs29
1 files changed, 20 insertions, 9 deletions
diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
index b22c7c0a..ece83533 100644
--- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
+++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
@@ -1150,6 +1150,16 @@ try {{
.into()
})?;
+ // The event stub the script receives hands out stubs of the Composer object graph, and
+ // those extend and implement the real Composer contracts (`PackageInterface` and the
+ // rest), which only the Composer PHP runtime carries.
+ let cache_dir = self
+ .composer()
+ .borrow_partial()
+ .get_config()
+ .borrow()
+ .get_str("cache-dir")?;
+ Self::ensure_composer_php_runtime(std::path::Path::new(&cache_dir))?;
Self::ensure_script_autoloader()?;
let rhandle = shirabe_php_rpc::alloc_rhandle();
let mut dispatcher = ScriptRpcDispatcher {
@@ -1640,12 +1650,12 @@ try {{
/// Serves `CallRustMethod` requests issued by the PHP worker while a script-related call is in
/// flight: Rust handle 0 is the runtime service endpoint (autoload lookups against the
-/// Rust-side [`ClassLoader`]), and at most one live event handle is exposed per dispatched
-/// call.
+/// Rust-side [`ClassLoader`]), every other rhandle resolves through the R table, except the
+/// one live event handle exposed per dispatched call.
///
-/// TODO(plugin): this per-call scope stands in for persistent R-table registration; a stub
-/// retained by the script beyond the call observes an unknown handle error instead of the
-/// live object.
+/// TODO(plugin): a script that stores the event stub beyond its own call observes an unknown
+/// handle error afterwards; keeping events in the R table needs full proxying of the object
+/// graph an event exposes, which does not exist yet.
struct ScriptRpcDispatcher<'a> {
loader: Option<ClassLoader>,
event: Option<(u64, &'a dyn EventInterface)>,
@@ -1691,10 +1701,11 @@ impl RustMethodDispatcher for ScriptRpcDispatcher<'_> {
Some((event_rhandle, event)) if event_rhandle == rhandle => {
dispatch_event_method(event, method_name)
}
- _ => Err(runtime_throw(format!(
- "unknown Rust handle {rhandle} (script-event handles are scoped to a single \
- dispatched call)"
- ))),
+ _ => crate::plugin::php_plugin_proxy::dispatch_r_table_method(
+ rhandle,
+ method_name,
+ &args,
+ ),
}
}
}