aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/event_dispatcher
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-23 19:54:08 +0900
committernsfisis <nsfisis@gmail.com>2026-08-23 19:54:08 +0900
commit0b9834a90b20a90908acc8f698742c7218450008 (patch)
tree8361267d7481fffafada762ff40de4c42c57b155 /crates/shirabe/src/event_dispatcher
parent0b48f4a46d24248e4c012ef37d25b5963c27a78c (diff)
downloadphp-shirabe-0b9834a90b20a90908acc8f698742c7218450008.tar.gz
php-shirabe-0b9834a90b20a90908acc8f698742c7218450008.tar.zst
php-shirabe-0b9834a90b20a90908acc8f698742c7218450008.zip
docs(plugin): bring boundary text in line with the implementation
Comments that pointed at design notes kept outside the repository are dead ends for anyone reading only the tree, so what each of them explained now lives in a tagged TODO at the site it applies to. Several of those sites also stated something the implementation does not do, and the TODOs record the actual gap instead: the two halves of the codec recognize handle descriptors by different rules, the scripts Command path drops the exception class and collects output in a BufferedOutput that cannot carry an interactive command, find_shortest_path panics where PHP throws, and the package dispatch hand-rolls the variant selection AnyPackage should own. The classifier document likewise described rust-snapshot, plugin-constructible and several of the open questions as designed rather than as built. 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.rs22
1 files changed, 17 insertions, 5 deletions
diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
index fb3ad5f4..a5a238bd 100644
--- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
+++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs
@@ -751,11 +751,12 @@ impl EventDispatcher {
// PHP hosts the user's Command class in a throwaway, bare
// `Symfony\Component\Console\Application` (NOT Composer's Application),
- // built by a generated snippet running inside the worker. The command's
- // output is captured in a BufferedOutput and written back through the
- // dispatcher's IO; upstream hands the live output object of `$this->io`
- // to `$app->run()` instead, so only the interleaving with concurrent
- // writes differs.
+ // built by a generated snippet running inside the worker.
+ //
+ // TODO(plugin): the BufferedOutput has to go. The command has to run
+ // against the real output stream, the way upstream hands the live output
+ // object of `$this->io` to `$app->run()`; collecting the output and
+ // writing the buffer back once the run has returned is not a substitute.
let args = additional_args
.iter()
.map(|arg| ProcessExecutor::escape(arg))
@@ -775,6 +776,12 @@ impl EventDispatcher {
} else {
output_interface::VERBOSITY_NORMAL
};
+ // TODO(error-model): the snippet's try/catch does not reproduce upstream's
+ // boundary. Upstream wraps `$app->run()` alone and catches `\Exception`, so
+ // an `\Error` from the command, and a throw from `new $className(...)`,
+ // both escape without the "terminated with an exception" line. Here the
+ // catch is `\Throwable`, and a constructor throw leaves the snippet as a
+ // `Throw` reply from `__shirabe_eval`, so the line is written either way.
let snippet = format!(
r#"
$className = {class_name_lit};
@@ -821,6 +828,8 @@ try {{
)?;
let result = match outcome {
Ok(value) => value.to_php_mixed()?,
+ // TODO(error-model): `throw.exception_class` is dropped, so the class
+ // upstream rethrows unchanged collapses to RuntimeException here.
Err(throw) => {
self.io.write_error3(
&format!(
@@ -846,6 +855,9 @@ try {{
self.io.write3(&command_output, false, crate::io::NORMAL);
}
if let Some(throw) = result.as_array().and_then(|map| map.get("throw")) {
+ // TODO(error-model): the snippet reports `get_class($e)` as the first
+ // field and nothing reads it, so the class upstream rethrows unchanged
+ // collapses to RuntimeException here.
let fields = throw
.as_list()
.expect("the eval snippet reports exceptions as a list");