littledan / proposal-proxy-transparent

Transparent Proxies--tunneling private fields, etc.
8 stars 0 forks source link

Current status

In a review, transparent proxies faced significant doubts from some TC39 delegates (details). Because of that, the author of this proposal has no plans to present this proposal to TC39.


Transparent Proxies

JavaScript developers sometimes use Proxies in a membrane-style information-hiding pattern, but often they just want to intercept all object operations, including in methods on the object or defined in subclasses. There are a couple of interactions with the rest of the language or proposals where this doesn't quite work out with current Proxy. These features don't "tunnel" through Proxy. Unless the Proxy implements a membrane pattern (which would remove the Proxy traps from references inside the class), the receiver (which is the Proxy) will be "wrong" and not have the private fields that the underlying target does.

This repository proposes transparent Proxies as a solution to the problem. Transparent Proxies are a mechanism for allowing the object model operations to be intercepted, but to permit other things (private fields and some internal slots) to pass right through to the target. Unlike ordinary Proxies, they are not an encapsulation mechanism.

API

Proxy.transparent(target, handlers)

Analogous to new Proxy: Create a transparent Proxy with the given target and handlers. Returns a single Proxy object. Creating a transparent Proxy of a transparent Proxy throws a TypeError.

Proxy.transparent.unwrap(obj)

Semantics

For the most part, transparent Proxies act exactly like ordinary Proxies. The only difference is that, in several algorithms, there is an extra step to "tunnel" down to the underlying receiver, with the Proxy.transparent.unwrap algorithm.

Usage cases

In general, transparent Proxies unwrap themselves before usages of relevant internal slots that would make sense to carry through. Internal slots are not directly forwarded, however, to minimize the amount of unexpected states that existing algorithms may encounter (as these can currently assume that an object with certain internal slots will not have overridden object operations).

Specification integration details

The above locations in the JavaScript and embedder specifications check for the presence of an internal slot, and throw an exception if the internal slot is not present. This is how type checks are generally specified. These locations are generally the locations that make sense to upgrade to transparent proxy unwrapping.

Some advantages of unwrapping at this point:

GetObjectWithSlot(obj, slot)

  1. Perform ? RequireObjectCoercible(obj).
  2. If obj has a slot internal slot, return obj.
  3. If obj is not a transparent Proxy, throw a TypeError.
  4. Let target be the Proxy target of obj.
  5. If target has a slot internal slot, return target.
  6. Throw a TypeError.

Object capability analysis

Proxy.transparent is equivalent to the existing ES2015 Proxy mechanism, plus a WeakMap mapping opted-in Proxies to targets. As such, it does not lead to any new information leak. It is proposed to be part of the JS standard library so that various built-in mechanisms, such as private field access, can access this mapping.