Skip to content
Commit Detail

Commit 36d0b80

Author
Kenton Varda <kenton@cloudflare.com> 2024-12-04 22:43:59 -0600
Parents
401c665
Tree
17db145
JSRPC: Allow wrapping RPC targets in Proxy objects.

When serializing a value for RPC, if we encounter a `Proxy`, we will check if it claims to be an instance of `RpcTarget` (via the prototype chain) and, if so, treat it as one, wrapping it in a stub with the same semantics as an actual `RpcTarget`.

Additionally, if the `Proxy` claims to be a plain object (the prototype is `Object.prototype`), we will allow this too, wrapping it in a stub that allows access to the object's "own" properties. This is not exactly the same thing as we'd do if it were really a raw object: in that case, we would actually send the object content. However, it is consistent with our access control model, which says that for plain objects, "own" properties are exposed, but for `RpcTarget` instances, only prototype properties are exposed.

A `Proxy` can even be used to cause an object of class type that is _not_ derived from `RpcTarget` behave as if it were, by overriding `getPrototypeOf()` to return `RpcTarget.prototype`. This is a feature, not a bug! The reasons we don't normally support non-RpcTarget classes by default are (1) we want to reserve the right to add by-value serialization to existing API types in the future, without breaking compatibility, and (2) classes not explicitly written for RPC may not have been written with the understanding that their public API is a security boundary. However, if the developer uses a `Proxy` to fake that the object is an `RpcTarget`, then the developer is "opting in" to `RpcTarget` behavior, namely (1) the object is strictly pass-by-stub, and (2) they are comfortable with exposing the class's public interface.

Fixes #3184

Files changed