Options
Transparent object proxies for javascript
Journal
Lecture Notes in Informatics (LNI), Proceedings - Series of the Gesellschaft fur Informatik (GI)
ISSN
16175468
Date Issued
2016-01-01
Author(s)
Keil, Matthias
Farooq, Omer
Guria, Sankha Narayan
Schlegel, Andreas
Geffken, Manuel
Thiemann, Peter
Abstract
This work appeared in the conference proceedings of the European Conference on Object-Oriented Programming, ECOOP 2015. One important question in the design of a proxy API is whether a proxy object should inherit the identity of its target. Apparently proxies should have their own identity for security-related applications whereas other applications, in particular contract systems, require transparent proxies that compare equal to their target objects. In this work we examine the issue with transparency in various use cases for proxies, discuss different approaches to obtain transparency, and propose two designs that require modest modifications in the JavaScript engine and cannot be bypassed by the programmer. The JavaScript Proxy API embodies a design decision that reveals the presence of proxies in some important use cases. This decision concerns object equality. Proxies are opaque, which means that each proxy has its own identity, different from all other (proxy or nonproxy) objects. Given opaque proxies, an equality test can be used to distinguish a proxy from its target as demonstrated in the following example: 1 var target = { /' some object '/ }; 2 var handler = { /' empty handler '/ }; 3 var proxy = new Proxy (target, handler); 4 proxy===target; // evaluates to false Even though target and proxy behave identically, they are not considered equal. Thus, in a program that uses object equality, the introduction of a proxy along one execution path may change the meaning of the program without even invoking an operation on the proxy (which may behave differently from the same operation on the target). Equality for opaque proxies works well under the assumption that proxies and their targets are never part of the same execution environment. But the assumption that proxies never share their execution environment with their targets is not always appropriate. One prominent use case is the implementation of a contract system. Two examples for such systems are the contract framework of Racket [FFP14, Chapter 7] and TreatJS for JavaScript [KT15]. Both systems implement contracts on objects with specific wrapper objects, Racket's chaperones or impersonators [St12] and JavaScript proxies, respectively. But this may chang the semantics of a program and thus it violates a ground rule for monitoring: A monitor should never interfere with a program conforming to the monitored property. Our ECOOP paper [Ke15] shows that a significant number of object comparisons would fail when mixing opaque proxies and their target objects, e.g. when gradually adding contracts to a program. As neither the transparent nor the opaque implementation of proxies is appropriate for all use cases, we propose an alternative designs for transparent proxies that is better suited for use cases such as certain contract wrappers and access restricting membranes. We use object capabilities to create proxies in a particular realm and to create an equality function that only reveals proxies for that realm. A new realm constructor returns a new transparency realm represented by an object that consists of a fresh constructor for transparent proxies (named Constructor) and an equals function revealing proxies of that realm. 5 var realm = TransparentProxy.createRealm(); 6 var proxy == realm.Constructor(target, handler); 7 proxy===target; // true 8 realm.equals(proxy, target); // false The proxy proxy is transparent with respect to equality unless someone uses the realm. equals method. The realm.equals method is a capability that represents the right to reveal proxies of that realm. In addition, the realm also contains a constructor for realm-aware weak maps and weak sets.