|
ObjectProperties
How caja.js protects access to properties
Object properties and accessBackgroundEcmaScript Objects are collections of named properties. o.foo specifies the foo property of the object referenced by o. Some properties can be read and set, some can only be read, and some don't show up when enumerated via a for (... in ...) loops. ECMAScript 262 Edition 3 (hereafter ES3) defines "property attributes" in section 8.6.1. 8.6.1 Property Attributes A property can have zero or more attributes from the following set:
ES3 defines no way for user code to manipulate these attributes, but Caja whitelists access to object properties, and so some properites (e.g. the "eval" property of all objects in Firefox) are inaccessible from Caja. Containers can choose to expose properties to Caja code by granting access on a property-by-property basis. As described at NiceNeighbor, array index properties, and the length property are always readable. Methods as PropertiesES3 methods are simply properties containing function objects. These functions are not bound to the object they are called on, until the time the function is called using the special obj.method(<params>) or equivalent obj[methodName](<params>) syntax, or the reflective method.call(obj, <params>) syntax. Caja AttributesIn addition to the ReadOnly, DontEnum, DontDelete, caja adds the CanCall attribute. We also make the attribute names positive since we whitelist
CanDelete implies CanSet. CanSet implies CanEnum. CanEnum implies CanRead. Object TypesWe determine property attributes differently for two types of objects. JSON ObjectsAll Arrays and Objects are JSON objects. Their properties are assumed to be editable, readable, enumerable, and deletable by any code that can access them (modulo freezing below), and have no distinction between public and private properties. Constructed ObjectsA constructed object is any object created from a class. Constructed objects have private properties that are not accessible except to their constructor and methods. Private properties have names that end in _, so foo_ is a private property name, but foo is a public property name. A constructed object's properties are not deletable via its public API, but can be created, set, or deleted via constructors and methods which can access its private API. Private properties are not enumerable except via the private API. The private API is accessed via this, so for (var k in this) will enumerate over both public and private properties, but for (var k in o) will not include private properties. Caja does not allow functions that reference this to be called cross-class. Frozen ObjectsA frozen object is one that has been rendered immutable (not-transitively) via caja.freeze(). It cannot be modified by cajoled code, so this operation removes any fasttracked CanSet attributes. Both constructed objects and JSON objects can be frozen. Granting AccessThe container can grant access to certain code. For example, caja.js grants access to the length property of arrays and array-like objects via ___.allowRead(Object.prototype, 'length'). Other caja.js methods set the above property attributes. Public clients cannot be granted access to a constructed object's private API. Granting read access does not guarantee that the property value will be read unchanged -- unattached methods will be bound when read. Fasttrack AttributesFor efficiency, we store the fact that a certain property attribute is set. We never store the fact that CanEnum attribute is set, since we never check it, and we never store the fact that CanDelete is set, since deletes invalidate all fasttrack attributes. The diagrams below show how basic operations (C_alls, D_eletes, R_eads, S_ets) affect fasttrack attributes.
In both diagrams, arrows represent the basic operations, and ovals specify which fasttrack attributes are set. Arrows from a box to an oval mean that that transition can start from any oval in the box. Since the whole purpose of a fasttrack attribute is to let us skip runtime checks, if an oval has fx set, then there will be no outbound X transition since that transition will never be set. Note that a read of an unattached method never sets a fasttrack bit since reading an unattached method involves returning a bound version of the method. |
Sign in to add a comment