From 90764c477f24e4d67d3e0cae943c33fd2b8ae220 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Thu, 6 Aug 2026 02:40:00 +0900 Subject: feat(plugin): widen the RPC surface to LibraryInstaller-based plugins An installer that extends LibraryInstaller reaches for the Composer object graph in ways the proxy did not answer: the download manager and the config, the writable repository methods, a React promise as its own return value, and `new Package(...)` from its supports() path. * `Composer::getConfig`/`getDownloadManager` are dispatched, and both classes become generated proxy stubs. Their reads and mutators answer from the Rust entity; the surfaces needing stubs of their own (ConfigSourceInterface, DownloaderInterface) stay explicit errors. * The download manager's futures are driven to completion and handed back as already-settled React promises, since PHP declares a non-nullable PromiseInterface there. A promise a plugin returns is drained the same way: settled yields its value, rejected re-raises, pending is an explicit error. * Proxy stubs now carry the real class's constructor and ask the Rust side to allocate the entity; reviving a stub for an existing entity binds the handle without running it. Classes Rust cannot build name themselves in the error. * The package proxy covers `Package`'s own setters, `CompletePackage`'s metadata, `RootPackage`'s root-only state, and `BasePackage::$id`. Link values and release dates still have no wire image, so the methods carrying them remain explicit errors. --- docs/dev/plugin-stub-generation.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'docs/dev/plugin-stub-generation.md') diff --git a/docs/dev/plugin-stub-generation.md b/docs/dev/plugin-stub-generation.md index 33025df7..27835921 100644 --- a/docs/dev/plugin-stub-generation.md +++ b/docs/dev/plugin-stub-generation.md @@ -46,12 +46,18 @@ the generator's vendor directory or the classifier report is unavailable. ## What the generator emits * **Root stubs** (targets whose parent class is not itself a target) carry the - proxy boilerplate: `__rhandle`/`__epoch` properties, a constructor that - accepts `(rhandle, epoch)` from proxy instantiation and throws a diagnosable - `RuntimeException` when plugin code tries to `new` the class directly, a + proxy boilerplate: `__rhandle`/`__epoch` properties, the `__shirabeBind` + binder the registry calls when reviving a stub for an existing entity, a destructor releasing the Rust handle, and the wire descriptor helper. The real `extends`/`implements` hierarchy is preserved and `\ShirabeRustStub` is appended to the interface list. +* **Constructors** reproduce the real class's parameter list and forward to the + Rust side (`__shirabeConstruct` on handle 0), which allocates the entity and + answers with its handle; a class Rust cannot build answers with an explicit + error naming it. One is emitted for every root stub and for every subclass + that declares a public constructor of its own, so `new SomeProxiedClass(...)` + in plugin code never yields an unbound stub. Proxy revival does not run them + (see `__shirabeBind` above). * **Instance methods** forward via `\ShirabeRpcRuntime::callRust`. For a root stub the emitted surface is the interface closure (each interface before the ones it extends, methods in declaration order; a concrete redeclaration in @@ -89,8 +95,8 @@ Generation fails — instead of emitting something quietly wrong — on: * a target missing from the classifier report, classified other than `rust-proxy`/`contract`, or a report carrying violations, -* by-ref or variadic parameters, static interface methods, magic methods - other than `__toString`/`__clone`, +* by-ref or variadic parameters (in constructors too), static interface + methods, magic methods other than `__toString`/`__clone`, * an omitted override diverging from the inherited stub signature, * a subclass target listed before its base class, or extending a class that is neither a target nor provided by `php/runtime/`, -- cgit v1.3.1