Hi, Recently, I've been thinking about the structured clone algorithm used in postMessage The browser has to do a copy of an object and pass it to the message receiving context. In some cases, if the object has a lot of properties, it could be costly to do this copy. So I thought "hey, what about wrapping it with a proxy and just hand the proxy?". For the rest of this use case, I will consider myself in the role of the browser (implementing postMessage and tryiing to do so in JavaScript) and I may use the "become" primitive if needed since I'm in "privileged code".
Basically, the proxy has to forward "reads" to the target object, keep the "writes" internally and make sure future "reads" are consistent if some "writes" occured. You can see my implementation of "LazyReadCopy" at: https://github.com/DavidBruant/HarmonyProxyLab/tree/master/LazyReadCopy (I discuss limitations below) So now we can send an object in the message Receiving Context (RC). This object is a copy of the one in the message Sending Context (SC). The RC can manipulate the object and this will have no noticeable effect in the SC. However, the opposite is not true. If a property is added in the SC, the RC can read this new property. So, for my implementation to work, I would need 2 lazy read copies. One for the SC, one for the RC. The one in the SC can replace the object thanks to the "become" privileged primitive. So far, so good, we have an object, two lazy read copies of it (one in each context), basic expectations are respected. Now, consider the following snippet: ----- var o = {}; Object.preventExtension(o); Object.isExtensible(o); // false receivingContext.postMessage(o); // The browser replaces o with a lazy read copy of o. That's now a proxy. Object.isExtensible(o); // true, because it's a proxy :-s ----- Of course, that's my fault, I shouldn't play too much with the "become" primitive. However I feel that I should be allowed to create non-extensible proxies to cover this use case. And well, you probably see my proposal coming: what about doing invariant-enforcing with [[Extensible]]=false instead of the fix+become? There would only be a need for a preventExtension fundamental trap (freeze and seal would be derived or even not trap at all, calling the preventExtension trap anyway) I haven't taken the time to try to implement it, but starting from Tom's FixedHandler implementation [1], it looks like it would be just adding a this.extensible boolean (and the set of properties can be retrieved from this.fixedProps). One-property traps would need a lookup to a property set (hopefully, JS engines have efficient implementations for that for the "in" operator) to avoid lies on whether the property is part of the object already or not. The rest of the one-property traps invariants are already taken care of by FixedHandler. Several-property traps (get{Own}PropertyNames, enumerate, keys) could call the trap, throw away the result and return the set of properties. The inconvenient of this would be that the user-returned order wouldn't be respected. The costly alternative is to check that the returned array isn't adding properties that shouldn't be there. Another idea is to provide the choice between the invariant-checking flavor and the "turn me into a normal object" flavor with the return value of the fix/preventExtension trap. Any thoughts? Limitations of my implementation regarding the structured clone algorithm. * Non-enumerable and inherited properties are not filtered out * Doing a lazy copy read is not performed recursively * The object in the receiving context should only have data property, so if there are accessors, their getters should be called once at copy time and the result stored in the copy. (this last point cannot be implemented efficiently in JavaScript, I think) David [1] http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/FixedHandler.js _______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

