fix(validate): support decorated classes extending decorated classes#194
Merged
teamchong merged 3 commits intoJun 12, 2026
Merged
Conversation
🦋 Changeset detectedLatest commit: 17d5408 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
9130edc to
7bb21cc
Compare
866c993 to
3ce9472
Compare
- Replace constructor-returns-Proxy in __validateRpcClass with in-place prototype method wrapping, idempotent via a WRAPPED_METHOD symbol - Decorated classes extending decorated classes now resolve subclass-only methods against the subclass validator instead of refusing them - Instances stay real branded RpcTargets, removing the Proxy-serialization hazard over native workerd RPC - Reword refusal errors to distinguish instance-property access from methods not declared on the RPC interface
- Cover subclass-only and inherited methods on decorated-extends-decorated - Verify double-decoration is a no-op and instanceof identity is preserved - Assert instance-property refusal semantics and #-field privacy intact
3ce9472 to
4986418
Compare
Member
|
Let's plan on @dimitropoulos reviewing changes to this package, I probably don't have bandwidth to really learn the code myself. |
dimitropoulos
approved these changes
Jun 12, 2026
dimitropoulos
left a comment
Collaborator
There was a problem hiding this comment.
some very very minor things I noticed - none blocking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A downstream repo hit:
and calls to subclass-only methods failed with the same misleading error.
Root cause:
@validateRpc()returned anew Proxy(...)from the decorated constructor. When a decorated class extends another decorated class (Class2 extends Class1),super()returns the base class's validator proxy, so every subclass-only method (method2,method3, ...) is checked against the base validator and refused. The generated validator itself is correct; only the runtime wrapping was wrong.The constructor-returns-Proxy approach had a second cost: instances were Proxies rather than real branded
RpcTargets, a serialization hazard over native workerd RPC.Fix
__validateRpcClassnow wraps the declared methods in place on the class's prototype instead of returning a Proxy from the constructor.WRAPPED_METHODsymbol marks wrapped functions), so decorated-extends-decorated and double-decoration compose: each class's methods are validated against its own validator, and inheritance behaves like ordinary JS.RpcTargets with intactinstanceofidentity and#-field privacy.v.stubOf(...)) now pass through as native stubs instead of being wrapped in validation proxies. The wrapper proxy could not be forwarded over native workerd RPC (for example, handing a received callback to a Durable Object). The trade-off: return values from those callbacks are no longer validated by default. This follows the review direction on Add capnweb-validate RPC validators #169: incoming wrappers validate only arguments, and stub validation is explicit opt-in viavalidateStub<T>(stub)rather than automatic.Verification
capnweb-validatesuite: 179/179 pass. New regression filedecorated-class-runtime.test.tscovers subclass-only methods, inherited methods, double-decoration, prototype/identity preservation, and refusal semantics.RpcStubcallback through a validated service and forwards it to a Durable Object, both as a top-level argument and nested inside an object. The test fails against the previous wrapping behavior.method2 is not in the generated validatorRpcTargetfield1)Note: the downstream
Class1.field1console error is independently legitimate.protectedfields are runtime-public properties and should be#-private in the downstream code; this PR makes the refusal message say so explicitly.