Proxies in Use -


#1

I was at ForwardJS last week and was talking to someone about proxies. I mentioned the ability to attenuate authorities, and it seemed like they weren’t familiar with using a proxy in that way. There was also a presentation on Immer which uses proxies extensively. It made me wonder - what are people using proxies for now? And how does this differ from the original intent?


#2

I did not know about Immer before. This is a really clever use of proxies.

Proxies were designed primarily to support membranes. Membranes are about intermediation, which is in turn generally about attenuation, but is not always thought of that way. For example, when using a membrane for diagnostic purposes, by logging all operations in addition to forwarding them. Technically, this is both amplification and attenuation at once: attenuation because the caller cannot invoke without generating a log record. Amplification, because it enables the caller to effect the log record when it may not otherwise have been able to.

Some of our own non-membrane uses of proxies:

In our PlaygroundVat, we use proxies so that our unsweetened syntax for eventual sends is more pleasant. Historically,

listener ! statusChanged(newState)

would desugar to something like

Promise.resolve(listener).invoke('statusChanged', newState)

from Q and Q-connection.

However, without support for syntactic sugar, this is ugly write by hand. Instead, in our PlaygroundVat we’ve been writing approximately

Promise.resolve(listener).e.statusChanged(newState)

To make this work, .e. returns a proxy that intercepts the succeeding call and internally turns it into approximately the invoke call shown above.


#3

Our most unusual non-membrane use of proxies is in the realms shim, where we do a sloppy-mode with(aProxy) {...; return eval(...);} in order to intercept all scope lookups emanating from that nested direct eval call. This is “the heart of the shim” explained at


#4

At MetaMask we had to use a Proxy to prevent a breaking change with a developer library that had decided to delete properties from our API to construct its own.


#5

I’ve used a proxy over the Function builtin to attenuate dynamic code loading while preserving instanceof Function.

A code loading function proxy lets modules that explicitly mention Function() load code via Node.js’s vm package while preventing unintentional use of code loading via node –disallow_code_generation_from_strings.

We might use it in the Trusted Types polyfill to do trademark checking that the code is a trusted script.


I also ported some code that used new Function to create wrapper functions with the same .length to use proxies. That allowed it to run in JS engine’s with code from string loading disabled.


In both cases, the proxy is over a function and traps [[Apply]] and [[Construct]] messages to do some additional work before using Reflect.apply or Reflect.construct to delegate to the underlying function.


#6

Node.js is using proxies in order to synchronize some builtin CommonJS module facades for ES Module named exports with the CommonJS value they are wrapping.


#7

I’ve used proxies to explore-by-modeling how module bindings work when dealing with static and dynamic dependencies. It is nothing more than learning by experimenting and dumping to the console: http://experimental.smotaal.io/modules/alpha/modules

Edit: Don’t forget to actually open the console first — loading when open improves formatting for objects in Chrome and maybe others. The code is isomorphic (designed for it but can’t recall how to use with node)