First off, a little bit of basics: an object is a collection of properties (some of which are functions, and officially named “methods”). This may sound obvious, but it’s important: you refer to other values by the object and a property name.
Proxies allow you to rewrite the rules for referring to other values by that tuple of the (containing) object and a property name. For instance, you can hide “private” members behind a proxy.
A membrane presents a one-to-one relationship between each proxy and a corresponding real object. If you’re given a proxy to a document, and not the document itself, you can get other proxies, and those proxies can offer other properties that let you get back to the proxy of the document… but you can’t break out of any of the proxies to the underlying set of objects (or “object graph”).
When I made the announcement back in August of this new project, the membrane I presented was quite useless, implementing only a mirroring capability. Not anymore. There’s a few features that the latest version currently supports:
- Membrane owners can replace any proxy the membrane generates with a custom proxy, using the .modifyRules API
- .createChainHandler(…) creates a new ProxyHandler derived from a handler used for an object graph the membrane already knows about.
- .replaceProxy(oldProxy, newHandler) takes the new handler and returns a new proxy for the original value, provided the new proxy handler was created via .createChainHandler().
- Membrane owners can require a proxy to store new properties locally on the proxy, instead of propagating them through to the underlying object. (.storeUnknownAsLocal(…) )
- Membrane owners can require a proxy to delete properties locally, instead of on the underlying object. (.requireLocalDelete(…) )
- Membrane owners can hide existing properties of an object from the proxy’s users, as if those properties do not exist. (.filterOwnKeys(…) )
- Membrane owners can be notified when a new proxy is about to go to the customer, and set up new rules for that proxy before the customer ever sees it. (ObjectGraphHandler.prototype.addProxyListener(callback), ..removeProxyListener(callback) )
- Having more than one object graph could have a few applications: different privileges for different users or customers, for example.
- The es7-membrane test code uses “dry”, “wet” and “damp” object graphs.
- For lack of a better name, es7-membrane calls these “multisided” membranes. I have a document explaining how this works at a very temporary location.
Version 0.7 added the symbol support today, along with a probable memory leak clean-up and a little more protection for revoked object graphs.
The production files are available in the dist subdirectory of the es7-membrane project’s Github’ repository, or directly usable as a npm module.
I’m still looking for help in a few areas:
- Building a static interactive demo site on Github
- Code and documentation reviews
- More testing
- additional tests in Jasmine
- converting tests to test-262 format (someone suggested the standard tests for ECMAScript might use some integration tests, such as a membrane implementation)
- if there are weaknesses, where a customer who has only “dry” proxies and good old ECMAScript 6+ (no membrane access, no other proxies) can break out to reach “wet” proxies… no one’s seriously explored that yet.
- Using the membrane module to protect itself from evildoers (dogfooding bonus)
- Implementing other use cases for a multisided membrane
- And just in general, another volunteer developer or two would be extremely welcome!