Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
2012/11/28 Brandon Benvie bran...@brandonbenvie.com Object.observe would fit under after correct? Yes, with two remarks: - it only traps updating operations - the traps are called in a separate turn (i.e. asynchronously), so they cannot change the result of the operation Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
2012/11/28 David Bruant bruan...@gmail.com I don't understand why a unique token per trap invocation would be necessary. I still don't understand this point. I've gone spelunking. I've found: * the wiki page [1] (reflecting July meeting) which mentions that returning undefined would express I don't know the private name, please forward * Confirmed on July 31st [2]. * Introduction of the idea of putting the verification of known names somewhere else than for each trap return [3]. Some discussion in between about this idea. Introduction of the idea of adding a third argument [4] after which I think stops all discussions about returning something in traps to prove knowledge of a private name or forwarding when not knowing. I don't remember the point about a token per trap invocation and I haven't been able to find it (but I haven't read everything). In any case, for throw ForwardToTarget, I don't see why it would be necessary. It seems it would work unambiguously with meta-handlers, with target-as-a-proxy or with manipulate-any-other-proxy-inside-a-trap (which target-as-a-proxy is an instance of). I think throwing a special token, as is done with StopIteration would probably work in practice (little risk of confusing it with a legitimately returned value). However, it does require every trap invocation to be wrapped in a try-catch block to potentially catch that error. Maybe I'm too influenced by the JVM, but my understanding is that wrapping every call to a trap with a try-catch block won't be free. Perhaps implementors can comment. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
2012/11/29 Dean Tribble dtrib...@gmail.com As a general point, I encourage you to look for other inspiration than CLOS MOP for doign proxies (whose mother was really InterlispD). Meta-level access deeply impacts security,maintainability, reliability, understandability, etc. The tighter and more structured you can make your meta-level access, the easier it will be to to implement, use, and maintain (e.g., both coroutines and downward functions are more understandable, easier to implement, easier to secure, etc. than general continuations and call-cc). I agree (side note: the CLOS MOP didn't form a direct inspiration for JS proxies, although I'm probably influenced by having studied it). CLOS method combinations allow a composer to distinguish between before, after and around-style composition: - before-style wrapping gives you only the ability to get notified before an operation happens. You can abort, but not change, the result of the operation. This is what notification-proxies offer. You *can* change the result of the operation. You do so by modifying the state before the operation proceeds, of course. You could also extend the notification support to notify after so you could clenup (avoiding a callback hack). Indeed. I think notification proxies would benefit from both before + after notification so any cleanup of virtual properties can be done directly. That just leaves the thorny issue that for virtual object abstractions, having to set-up the target in a before-handler and clean-up the target in an after-handler is really a very indirect way of expressing the abstraction, especially if the proxy doesn't need to virtualize any invariants. - after-style wrapping allows you to get notified of an operation after-the-fact. Depending on the API, the after-wrapper may or may not get to see the outcome of the operation, and may or may not change the final outcome passed on to clients. - around-style wrapping is the most general and allows the composer to decide if and when to forward, and what result to return. It subsumes before/after wrapping. This is what direct proxies currently provide. It does not subsume before/after wrapping, because it loses the integrity of before/after (e.g., the wrapper can lie and cheat, where the before and after cannot). That may be worth it, but it is substantially different. You're right, around doesn't subsume before+after in that regard. Thanks for clarifying. Another variant is the differential version: the differential trap is like a notification, but it can also return virtual additions (or an iterator of additions). The proxy then invokes the primitive on the target, and appends (with de-dupping, etc.) the virtual additions. This allows the simple case to just use hte target, but also allows all of Allen's additional cases. As far as I can tell, virtual object abstractions like remote/persistent objects require around-style wrapping, because there's otherwise no meaningful target to automatically forward to. I thought the target in that case is an internal object to represent or reify the meta-state of the remote or persistent object. I think that still makes sense in both the persistent object and remote object cases. It does. It just feels awkward, after having been able to express these abstractions more directly with the current Proxy API for so long. Here's a list of use cases that I frequently have in mind when thinking about proxies, categorized according to whether the use case requires before/after/around wrapping: Virtual objects, hence around-style: - self-hosting exotic objects such as Date, Array (i.e. self-host an ES5/ES6 environment) - self-hosting DOM/WebIDL objects such as NodeList I should note that I'm not advocating a notification-only style for all your proxy needs; having get operations able to generate virtual results makes lots of sense. I primary suggest it for operations that are currently implemented by the system (i.e., user code cannot normally intervene) and that might be relied on for security-relevant behavior. wrapping return results of user operations in a proxy makes perfect sense to me. It's hard to force the two different use cases (wrapping vs virtual objects) into a single API. I don't have a good answer yet on how to resolve the trade-offs. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
Le 02/12/2012 17:27, Tom Van Cutsem a écrit : 2012/11/28 David Bruant bruan...@gmail.com mailto:bruan...@gmail.com I don't understand why a unique token per trap invocation would be necessary. I still don't understand this point. I've gone spelunking. I've found: * the wiki page [1] (reflecting July meeting) which mentions that returning undefined would express I don't know the private name, please forward * Confirmed on July 31st [2]. * Introduction of the idea of putting the verification of known names somewhere else than for each trap return [3]. Some discussion in between about this idea. Introduction of the idea of adding a third argument [4] after which I think stops all discussions about returning something in traps to prove knowledge of a private name or forwarding when not knowing. I don't remember the point about a token per trap invocation and I haven't been able to find it (but I haven't read everything). In any case, for throw ForwardToTarget, I don't see why it would be necessary. It seems it would work unambiguously with meta-handlers, with target-as-a-proxy or with manipulate-any-other-proxy-inside-a-trap (which target-as-a-proxy is an instance of). I think throwing a special token, as is done with StopIteration would probably work in practice (little risk of confusing it with a legitimately returned value). However, it does require every trap invocation to be wrapped in a try-catch block to potentially catch that error. Yes and no. The try-catch is inside the engine, very much like for StorIteration in for-of loops. In case current implementations had performance drawbacks, I feel they could special-case when they know they are calling a function in the context of a particular protocol (iterator or proxy trap for instance). Maybe I'm too influenced by the JVM, but my understanding is that wrapping every call to a trap with a try-catch block won't be free. The more interesting question is whether it would be significantly cheaper than 'returning a value+invariant checks' because that's the reason I suggested the addition of throw ForwardToTarget. Perhaps implementors can comment. Yep. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Reflecting on non-string property names
2012/12/1 Allen Wirfs-Brock al...@wirfs-brock.com Requirements: 1) In ES6 property keys are no longer limited to string values, we now also have keys that are Symbols. 2) Some meta-programming tasks will requires a way to reflectively obtain a list of all public property keys. 3) The existing reflection APIs for property keys (Object.getOwnPropertyNames and Object.keys) only return string values and we don't want to break existing clients of those functions by returning non-string values. Solution: 1) Object.getOwnPropertyNames and Object.keys remain unchanged. They only return a string property key values. 2) Reflect.ownKeys(obj) is a new reflection function that returns an iterator. The iterator produces the keys of all public own properties of the object pass as an argument. This includes both string and Symbol key values. A property whose key is a private Symbol is not a public property and its key is not returned by the ownKeys iterator. 3) The [[OwnPropertyKeys]] internal method is defined to return an iterator with the same definition as used for Reflect.ownKeys. (Reflect.ownKeys is implemented as a call to this internal method). [[OwnPropertyKeys]] replaces the like-named internal method in the current spec. draft and also replaces the [[GetOwnPropertyNames]] internal method used in the wiki Proxy proposals. 4) ownKeys is the corresponding Proxy trap. The getOwnPropertyNames trap is removed. 5) Object.keys and Object.getOwnPropertyNames are respecified in terms of [[OwnPropertyKeys]]. They internally drain the iterator and continue to return arrays of strings. Any objections? Sounds good. We probably still need to clear up the discussion on invariants for [[OwnPropertyKeys]] on a non-extensible proxy. I don't remember if we reached a consensus on that. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.observe inital polyfill
2012/11/30 Andrea Giammarchi andrea.giammar...@gmail.com Last, but not least, if this script is for node.js only or modern browsers, the best way to implement observe() is via Proxy, changing only one thing: you need to re address and use the observed object rather than use the normal one. See https://github.com/tvcutsem/harmony-reflect/blob/master/examples/observer.js for an implementation of that approach (usage example is here https://github.com/tvcutsem/harmony-reflect/blob/master/examples/observer.html . It was based on the original spec. for Object.observe. It may not be up-to-date with the latest version though. Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
Le 02/12/2012 17:43, David Bruant a écrit : Maybe I'm too influenced by the JVM, but my understanding is that wrapping every call to a trap with a try-catch block won't be free. The more interesting question is whether it would be significantly cheaper than 'returning a value+invariant checks' because that's the reason I suggested the addition of throw ForwardToTarget. Filed https://bugzilla.mozilla.org/show_bug.cgi?id=817401 David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
On Sun, Dec 2, 2012 at 8:40 AM, Tom Van Cutsem tomvc...@gmail.com wrote: - after-style wrapping allows you to get notified of an operation after-the-fact. Depending on the API, the after-wrapper may or may not get to see the outcome of the operation, and may or may not change the final outcome passed on to clients. - around-style wrapping is the most general and allows the composer to decide if and when to forward, and what result to return. It subsumes before/after wrapping. This is what direct proxies currently provide. It does not subsume before/after wrapping, because it loses the integrity of before/after (e.g., the wrapper can lie and cheat, where the before and after cannot). That may be worth it, but it is substantially different. You're right, around doesn't subsume before+after in that regard. Thanks for clarifying. I think we can rescue around wrapping. I'll call this approach opaque around wrapping. The idea is that the proxy passes into the handler trap a proxy-generated no-argument function (a thunk) called action. The normal case is that the trap does stuff before calling action, calls action with no arguments and ignoring action's results, does stuff after action, and returns nothing. The call to action performs the original operation on target and remembers the result. After the trap returns, the proxy returns the remembered result of action. Open questions that take us to different design possibilities: 1) what happens if the trap does not call action? 2) what happens if the trap calls action more than once? 3) do actions ever return anything, in case the trap wants to pay attention to it? 4) are there any return values from the trap that the proxy would pay attention to? 5) if the original operation performed by action throws, should the action still just return to the trap normally? 6) what happens if the trap throws rather that returning? Two attractive possibilities: A) A simple pure notification approach: 1) the proxy throws, indicating that the action was not performed 2) only the last successful action counts 3) a boolean, indicating whether the original operation succeeded on target 4) no 5) yes, but with false rather than true, as in #A.3 above. 6) the proxy throws, even though the action was performed. B) Notification with fallback to virtual properties with invariant checking: Like #A, except 1) if action is never called, then the trap return's invariants are checked, as now. 4) only if action was never called. I prefer #A to #B as it gains the full benefits of simplifying the overall spec and implementation. However, #B still seems better than current direct proxies, as the normal case gets target-maintenance and invariant checking for free. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Reflecting on non-string property names
On Dec 2, 2012, at 8:44 AM, Tom Van Cutsem wrote: 2012/12/1 Allen Wirfs-Brock al...@wirfs-brock.com Requirements: 1) In ES6 property keys are no longer limited to string values, we now also have keys that are Symbols. 2) Some meta-programming tasks will requires a way to reflectively obtain a list of all public property keys. 3) The existing reflection APIs for property keys (Object.getOwnPropertyNames and Object.keys) only return string values and we don't want to break existing clients of those functions by returning non-string values. Solution: 1) Object.getOwnPropertyNames and Object.keys remain unchanged. They only return a string property key values. 2) Reflect.ownKeys(obj) is a new reflection function that returns an iterator. The iterator produces the keys of all public own properties of the object pass as an argument. This includes both string and Symbol key values. A property whose key is a private Symbol is not a public property and its key is not returned by the ownKeys iterator. 3) The [[OwnPropertyKeys]] internal method is defined to return an iterator with the same definition as used for Reflect.ownKeys. (Reflect.ownKeys is implemented as a call to this internal method). [[OwnPropertyKeys]] replaces the like-named internal method in the current spec. draft and also replaces the [[GetOwnPropertyNames]] internal method used in the wiki Proxy proposals. 4) ownKeys is the corresponding Proxy trap. The getOwnPropertyNames trap is removed. 5) Object.keys and Object.getOwnPropertyNames are respecified in terms of [[OwnPropertyKeys]]. They internally drain the iterator and continue to return arrays of strings. Any objections? Sounds good. We probably still need to clear up the discussion on invariants for [[OwnPropertyKeys]] on a non-extensible proxy. I don't remember if we reached a consensus on that. No, and I didn't address it in my proposal above. I still think making [[OwnPropertyKeys]] produce an iterator makes sense. But it probably means we have to change how we think about the its invariants as we can't necessarily check all of the values such an iterator may yield before returning it from the Proxy implementation of [[OwnPropertyKeys]]. We can however have that [[OwnPropertyKeys]] wrap the iterator returned by the ownKeys trap with another iterator that does an invariant check of the individual values returned by the trap provided iterator. The first issue, with that approach, is whether such delayed invariant checking is acceptable. For example, returning a key that doesn't exist in a frozen target would throw on the iterator.next call that would return that key rather than when calling Object.getOwnPropertyKeys. (However, Object.getOwnProperyNames/keys would still appear to throw immediately, because they drain the iterator). This delayed checking seems ok to me, but you probably need to think about it from the perspective of membranes and similar Proxy use cases. One difference with a deferred invariant check is that is to obtain a own property keys iterator before a Proxy object/target is frozen but not check its values until after it is frozen. In this case, the keys produced by the iterator would not necessarily meet the target own property invariants of a frozen object. However, I don't see that is significantly different from the current array valued calls which also can produce key values that may no longer be valid after the objet is frozen. Deferred checking can easily enforce that a new property key isn't return returned (from the iterator) for a frozen object. It can also determine that all own property keys are returned for a frozen object (immediately before throwing IterationComplete check if the number of keys already yielded equals the number of own properties of the target, if not throw to indicate the invariant violation). What isn't so easily do is make sure that for non-frozen objects all non-configurable property keys are returned. To do this would probably require accumulating every yielded key and then checking that list against the actual target properties immediately before StopIteration. This makes be think that this final invariant perhaps isn't so important, even for the present non-iterator based definition of getOwnPropetyNames. Basically for non-frozen/sealed objects any point in time list of property keys may become stale before it is used. It may include keys that are no longer used and may miss keys that are now used. Any inclusion decisions based upon the configurability of individual properties may no longer be valid. We've talked before about the need of a reliable property list for deep freezing objects. In seems for situations like that you would want to separately determine if the object is sealed/frozen before calling Reflect.ownKeys. If it is frozen/sealed, you can depend upon the results. If not, that final invariant (and
RE: Pure functions in EcmaScript
Function purity, while an interesting concept, probably isn't as important as the function being associative. Our work with Parallel EcmaScript (aka River Trail) http://wiki.ecmascript.org/doku.php?id=strawman:data_parallelism has shown that for a useful set of kernel functions the compiler can conservatively determine that a function does not modify non-local variables. We have found no need for function annotation, instead if one passes a function to a ParallelArray method we trust but verify that it modifies only local variables. Beyond this check we do not attempt to prove that a function is associative. The results are guaranteed only to be the result of some ordering and never return an out of thin air value. Floating point anomalies aside, if the function is associative the result will be deterministic. - Rick -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Sent: Wednesday, November 28, 2012 4:48 PM To: Axel Rauschmayer Cc: es-discuss Subject: Re: Pure functions in EcmaScript Axel Rauschmayer wrote: Would returning NaN be impure (apart from running the risk of it having been changed to something different, globally)? You can't say apart from..., that's exactly the risk. It could be replaced with a global getter that has effects. Isolating a pure function to a sandbox or prepared global environment saves this, but then the function's pure annotation can't be enough to express what's required. /be On Nov 28, 2012, at 21:35 , Oliver Hunt oli...@apple.com mailto:oli...@apple.com wrote: On Nov 28, 2012, at 12:25 PM, Waldemar Horwat walde...@google.com mailto:walde...@google.com wrote: On Wed, Nov 28, 2012 at 5:39 AM, Marius Gundersen gunder...@gmail.com mailto:gunder...@gmail.com wrote: On Wed, Nov 28, 2012 at 1:20 PM, Andreas Rossberg rossb...@google.com mailto:rossb...@google.com wrote: Second, due to the extremely impure nature of JavaScript, there aren't many useful pure functions you could even write. For example, your 'sum' function is not pure, because the implicit conversions required by + can cause arbitrary side effects. Functions passed to the array methods map, reduce, filter, etc would be good candidates for pure/side-effect-free functions. These functions shouldn't alter any state; they should only return a new value based on the parameter they were sent. You haven't addressed Andreas's point: Almost any function you write is nonpure, including your sum example. As a fun exercise, go ahead and write a pure version of your sum example. Waldemar Here you go: function sum(a, b) { var undefined; switch (typeof a) { case number: case string: break; default: return +undefined; } switch (typeof b) { case number: case string: break; default: return +undefined; } return a + b; } ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de mailto:a...@rauschma.de home: rauschma.de http://rauschma.de twitter: twitter.com/rauschma http://twitter.com/rauschma blog: 2ality.com http://2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Reflecting on non-string property names
2012/12/2 Allen Wirfs-Brock al...@wirfs-brock.com I still think making [[OwnPropertyKeys]] produce an iterator makes sense. But it probably means we have to change how we think about the its invariants as we can't necessarily check all of the values such an iterator may yield before returning it from the Proxy implementation of [[OwnPropertyKeys]]. We can however have that [[OwnPropertyKeys]] wrap the iterator returned by the ownKeys trap with another iterator that does an invariant check of the individual values returned by the trap provided iterator. Indeed. I had previously thought of a similar iterator-wrapping strategy for protecting the enumerate() trap. The first issue, with that approach, is whether such delayed invariant checking is acceptable. For example, returning a key that doesn't exist in a frozen target would throw on the iterator.next call that would return that key rather than when calling Object.getOwnPropertyKeys. (However, Object.getOwnProperyNames/keys would still appear to throw immediately, because they drain the iterator). This delayed checking seems ok to me, but you probably need to think about it from the perspective of membranes and similar Proxy use cases. I also think delayed checks are fine. One difference with a deferred invariant check is that is to obtain a own property keys iterator before a Proxy object/target is frozen but not check its values until after it is frozen. In this case, the keys produced by the iterator would not necessarily meet the target own property invariants of a frozen object. However, I don't see that is significantly different from the current array valued calls which also can produce key values that may no longer be valid after the objet is frozen. Indeed, but I agree with your statement below that probably the result of ownKeys only makes sense if one determined that the proxy was frozen before starting the enumeration. Deferred checking can easily enforce that a new property key isn't return returned (from the iterator) for a frozen object. It can also determine that all own property keys are returned for a frozen object (immediately before throwing IterationComplete check if the number of keys already yielded equals the number of own properties of the target, if not throw to indicate the invariant violation). What isn't so easily do is make sure that for non-frozen objects all non-configurable property keys are returned. To do this would probably require accumulating every yielded key and then checking that list against the actual target properties immediately before StopIteration. Indeed. This makes be think that this final invariant perhaps isn't so important, even for the present non-iterator based definition of getOwnPropetyNames. Basically for non-frozen/sealed objects any point in time list of property keys may become stale before it is used. It may include keys that are no longer used and may miss keys that are now used. Any inclusion decisions based upon the configurability of individual properties may no longer be valid. We've talked before about the need of a reliable property list for deep freezing objects. In seems for situations like that you would want to separately determine if the object is sealed/frozen before calling Reflect.ownKeys. If it is frozen/sealed, you can depend upon the results. If not, that final invariant (and probably the others) doesn't really guarantee much. Right. Enumeration has weird invariants because of the complex state-space of JS object invariants. For frozen objects, the invariants become relatively easy to check (as you say: check if each enumerated key is an own property of target, and count whether the total number of generated keys equals the total amount of own properties of the target). For non-frozen objects, things are more complicated. Are you suggesting that we only enforce invariants if the proxy/target are really frozen at the start of enumeration, and give up on invariants in all other cases? I think this would be sufficient for most practical use cases, but it would be the first time that we visibly treat frozen objects specially (all other invariants are expressed only in terms of non-extensibility or non-configurability of individual properties) Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Reflecting on non-string property names
On Dec 2, 2012, at 11:16 AM, Tom Van Cutsem wrote: Right. Enumeration has weird invariants because of the complex state-space of JS object invariants. For frozen objects, the invariants become relatively easy to check (as you say: check if each enumerated key is an own property of target, and count whether the total number of generated keys equals the total amount of own properties of the target). For non-frozen objects, things are more complicated. Are you suggesting that we only enforce invariants if the proxy/target are really frozen at the start of enumeration, and give up on invariants in all other cases? I think this would be sufficient for most practical use cases, but it would be the first time that we visibly treat frozen objects specially (all other invariants are expressed only in terms of non-extensibility or non-configurability of individual properties) Yes. This goes along with the idea of a SetIntegrity internal method/trap that makes non-extensible/sealed/frozen real object states rather than the last two being derived from property inspection. I think have those states at the object level would simplify the specification of invariants (as well as eliminate many uses of observable property level operation in the validation of the invariants) Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
2012/12/2 Mark S. Miller erig...@google.com I think we can rescue around wrapping. I'll call this approach opaque around wrapping. The idea is that the proxy passes into the handler trap a proxy-generated no-argument function (a thunk) called action. Interesting. I had thought of a similar approach, but hadn't pursued it because I thought allocating a thunk per trap invocation would be deemed too expensive. I'll go ahead and sketch the design, which I think corresponds closely with your approach B) First, from the point-of-view of the trap implementor, things would work as follows (I show the defineProperty trap only as an example) All traps take an extra thunk as last argument, which I will name forward, since calling that thunk has the effect of forwarding the operation to the target, returning the original result. defineProperty: function(target, name, desc, forward) { // before var result = forward(); // after return result; } Now, from the point-of-view of the proxy implementation, how is the above trap called? // in the proxy, intercepting Object.defineProperty(proxy, name, desc) // where proxy = Proxy(target, handler) var result = Uninitialized; var thunk = function() { if (result === Disabled) throw new Error(can only call forward() during trap invocation); if (result !== Uninitialized) throw new Error(forward() can be called only once); result = Reflect.defineProperty(target, name, desc); // forward to target return result; }; var trapResult = handler[defineProperty].call(handler, target, name, desc, thunk); if (result !== Uninitialized result === trapResult) return result; // no invariant checks when original result is returned if (result === Uninitialized || result !== trapResult) { /* do invariant checks */ ; return result; } result = Disabled; // ensures one cannot call forward() outside of dynamic extent of the invocation I'll answer your questions for the above design: Open questions that take us to different design possibilities: 1) what happens if the trap does not call action? Invariant checks are performed on the returned result. 2) what happens if the trap calls action more than once? An exception is thrown. 3) do actions ever return anything, in case the trap wants to pay attention to it? Yes, it returns the value of the operation, applied to the target. 4) are there any return values from the trap that the proxy would pay attention to? Yes. If the trap returns the original result, it doesn't do any extra checks. Otherwise it does. 5) if the original operation performed by action throws, should the action still just return to the trap normally? A thrown exception would escape and abort the entire operation, unless the trap wraps the call to forward() in a try-catch block. 6) what happens if the trap throws rather that returning? Thrown exceptions are always propagated to clients. I prefer #A to #B as it gains the full benefits of simplifying the overall spec and implementation. However, #B still seems better than current direct proxies, as the normal case gets target-maintenance and invariant checking for free. I agree that #B doesn't really simplify anything in the spec (the invariant checks are still there sometimes). I'm not sure if it is inherently better than the current design though: we gain performance in terms of avoiding invariant checks, but we lose performance by having to allocate a per-call thunk, + the API becomes more complex (an additional parameter to every trap) I do think that passing an action or forward() thunk to a trap as extra argument beats David's proposed throw ForwardToTarget trick in terms of elegance and usability (maybe not in terms of performance). Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Reflecting on non-string property names
[+markm] 2012/12/2 Allen Wirfs-Brock al...@wirfs-brock.com Yes. This goes along with the idea of a SetIntegrity internal method/trap that makes non-extensible/sealed/frozen real object states rather than the last two being derived from property inspection. I think have those states at the object level would simplify the specification of invariants (as well as eliminate many uses of observable property level operation in the validation of the invariants) Ok. So we're moving towards a design where frozen objects are really the only ones with strong invariants. I think that could work. Mark, what do you think? Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array iterator questions
On Dec 1, 2012, at 8:14 AM, Jason Orendorff wrote: 1. The current draft spec has Array.prototype.@@iterator() behaving like .values(), so: for (x of [a]) print(x); would print the pair [0, a]. The proposal had Array iterators producing values only by default. Why the change? (It seems like it could be a typo, or it could be motivated by a desire for consistency across all collections. If the latter, Map should change, not Array.) Note, there is a margin note on of 15.4.4.26 that hi-lites items and says Or should this be values. There are a lot of notes like this in the draft. They are requests for knowledgable reviews to check spec. language that is uncertain for some reason. 2. According to 15.4.6.2.2, the iterators produced by Array.prototype.keys and .items will expose the index values as strings. Why strings? Don't numbers make more sense? It does that because array index keys are exposed as strings everywhere else. There is no specific definition (that I can find) of the keys iterator for arrays in the wiki proposal. There is only the general @iter.keys function which is defined in terms of for-in and hence returns string property keys. However, I don't have any objection to return integer keys in this case. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
On Dec 2, 2012, at 11:40 AM, Tom Van Cutsem wrote: 2012/12/2 Mark S. Miller erig...@google.com I think we can rescue around wrapping. I'll call this approach opaque around wrapping. The idea is that the proxy passes into the handler trap a proxy-generated no-argument function (a thunk) called action. Interesting. I had thought of a similar approach, but hadn't pursued it because I thought allocating a thunk per trap invocation would be deemed too expensive. I'll go ahead and sketch the design, which I think corresponds closely with your approach B) This is my first reaction too. I want Proxies to be lightweight enough so they really can be used be used for things like self hosting built-ins and web API objects. The need to create an pass in a action thunk on each trap calls initially feels too expensive. But that is only a first reaction. Perhaps the expense really isn't that great. Or perhaps a lot of the cases where I have assumed the Proxies would be needed could be handled by lightweight mechanisms such such as the @elementGet/@elementSet hooks described in http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation (see Implementing Built-inArray without Proxy and Rationalizing DOM HTMLCollections examples) Allen First, from the point-of-view of the trap implementor, things would work as follows (I show the defineProperty trap only as an example) All traps take an extra thunk as last argument, which I will name forward, since calling that thunk has the effect of forwarding the operation to the target, returning the original result. defineProperty: function(target, name, desc, forward) { // before var result = forward(); // after return result; } Now, from the point-of-view of the proxy implementation, how is the above trap called? // in the proxy, intercepting Object.defineProperty(proxy, name, desc) // where proxy = Proxy(target, handler) var result = Uninitialized; var thunk = function() { if (result === Disabled) throw new Error(can only call forward() during trap invocation); if (result !== Uninitialized) throw new Error(forward() can be called only once); result = Reflect.defineProperty(target, name, desc); // forward to target return result; }; var trapResult = handler[defineProperty].call(handler, target, name, desc, thunk); if (result !== Uninitialized result === trapResult) return result; // no invariant checks when original result is returned if (result === Uninitialized || result !== trapResult) { /* do invariant checks */ ; return result; } result = Disabled; // ensures one cannot call forward() outside of dynamic extent of the invocation I'll answer your questions for the above design: Open questions that take us to different design possibilities: 1) what happens if the trap does not call action? Invariant checks are performed on the returned result. 2) what happens if the trap calls action more than once? An exception is thrown. 3) do actions ever return anything, in case the trap wants to pay attention to it? Yes, it returns the value of the operation, applied to the target. 4) are there any return values from the trap that the proxy would pay attention to? Yes. If the trap returns the original result, it doesn't do any extra checks. Otherwise it does. 5) if the original operation performed by action throws, should the action still just return to the trap normally? A thrown exception would escape and abort the entire operation, unless the trap wraps the call to forward() in a try-catch block. 6) what happens if the trap throws rather that returning? Thrown exceptions are always propagated to clients. I prefer #A to #B as it gains the full benefits of simplifying the overall spec and implementation. However, #B still seems better than current direct proxies, as the normal case gets target-maintenance and invariant checking for free. I agree that #B doesn't really simplify anything in the spec (the invariant checks are still there sometimes). I'm not sure if it is inherently better than the current design though: we gain performance in terms of avoiding invariant checks, but we lose performance by having to allocate a per-call thunk, + the API becomes more complex (an additional parameter to every trap) I do think that passing an action or forward() thunk to a trap as extra argument beats David's proposed throw ForwardToTarget trick in terms of elegance and usability (maybe not in terms of performance). Cheers, Tom ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array iterator questions
On Dec 1, 2012, at 9:58 PM, Brendan Eich wrote: Jason Orendorff wrote: 1. The current draft spec has Array.prototype.@@iterator() behaving like .values(), so: for (x of [a]) print(x); would print the pair [0, a]. The proposal had Array iterators producing values only by default. Why the change? This came up two days ago at the TC39 meeting. It's a drafting error. (It seems like it could be a typo, or it could be motivated by a desire for consistency across all collections. If the latter, Map should change, not Array.) There is some desire, which motivated Allen's Array.prototype.{keys,values,items} additions in the latest draft, to have self-polymorphic method dispatch for implementing {keys,values,items}. This led to a discussion that concluded by separating the method naming scheme and standard troika (and Andreas Rossberg proposed entries not items, which everyone thought better), from the generic object-reflection function troika that return iterators for property keys, values, and [key, value] pairs. We argued about whether the two name-troikas should match, and I think ended up allowing for this. A related issue is which iterator to select in various contexts. For example, if @iterator returns values for arrays and entry key/value pairs for maps then using @iterator may not be the best choice for, for example, processing the argument of Array.from. Basically, iteration clients need to know what they are asking for. If you are going to write for (i of x) doSomething(x,i); You better have the expected @iterator behavior of x pretty locked down If you known you want values and aren't sure of the actual class of x then you should probably write: for (i of x.values()) doSomething(x,i); and let it break if x doesn't have a values method. For things like Array.from and spread, a fall back sequences is a possible approach: 1) if obj has a values method us it to get the iterator 2) else if obj as a @iterator method use it to get the iterator 3) else do an array like iteration using the obj's length property value. I've already been butting into these kinds of situations when specify handling the optional argument to the Map and Set constructors. It's also the reason I have been slow to update the Array.from spec. to handle anything other than array-likes. Map really wants key value pairs so calling @iterator on an Array, if it returns values, isn't what it should do. However, Set really wants only values. In general, when dealing with generic collections you can't just use @iterator. You need to be more explicit about whether you expect to process keys, values, or both. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array iterator questions
On Sun, Dec 2, 2012 at 2:47 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Dec 1, 2012, at 8:14 AM, Jason Orendorff wrote: snip 2. According to 15.4.6.2.2, the iterators produced by Array.prototype.keys and .items will expose the index values as strings. Why strings? Don't numbers make more sense? It does that because array index keys are exposed as strings everywhere else. There is no specific definition (that I can find) of the keys iterator for arrays in the wiki proposal. There is only the general @iter.keys function which is defined in terms of for-in and hence returns string property keys. However, I don't have any objection to return integer keys in this case. +1 Users will take this for granted and assume the index value is going to be a number since map, forEach, filter, every, some and reduce all pass a number as the index argument and for-loops increment a number. Rick Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Proposal: Reflecting on non-string property names
-Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Allen Wirfs-Brock Sent: Friday, November 30, 2012 19:18 1) Object.getOwnPropertyNames and Object.keys remain unchanged. They only return a string property key values. 2) Reflect.ownKeys(obj) is a new reflection function that returns an iterator. The iterator produces the keys of all public own properties of the object pass as an argument. This includes both string and Symbol key values. A minor qualm compared to all the other things being discussed here, but isn't it confusing to have keys mean two different things? In ES5 usage it means enumerable, string-valued whereas in this proposed Reflect.ownKeys it means no qualifiers: non-enumerable OK, symbol-valued OK. From an ES5 perspective, property names (as in getOwnPropertyNames) are enumerable or non-enumerable string-valued whereas keys are enumerable string-valued. Ideally there would be a new designation for non-string–valued. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
Le 02/12/2012 18:34, Mark S. Miller a écrit : On Sun, Dec 2, 2012 at 8:40 AM, Tom Van Cutsem tomvc...@gmail.com wrote: - after-style wrapping allows you to get notified of an operation after-the-fact. Depending on the API, the after-wrapper may or may not get to see the outcome of the operation, and may or may not change the final outcome passed on to clients. - around-style wrapping is the most general and allows the composer to decide if and when to forward, and what result to return. It subsumes before/after wrapping. This is what direct proxies currently provide. It does not subsume before/after wrapping, because it loses the integrity of before/after (e.g., the wrapper can lie and cheat, where the before and after cannot). That may be worth it, but it is substantially different. You're right, around doesn't subsume before+after in that regard. Thanks for clarifying. I think we can rescue around wrapping. I'll call this approach opaque around wrapping. The idea is that the proxy passes into the handler trap a proxy-generated no-argument function (a thunk) called action. The normal case is that the trap does stuff before calling action, calls action with no arguments and ignoring action's results, does stuff after action, and returns nothing. The point of around is to do something with the result in the middle of the trap, isn't it? For question 3, I'd answer that the action should return the result. The call to action performs the original operation on target and remembers the result. After the trap returns, the proxy returns the remembered result of action. target = {a:1}; var p = new Proxy(target, { get: function(target, name, action){ var v = action(); target[name] = 2; } }) p.a; // ? If p.a is 1 because the call to action remembered the 1, then the target and the proxy look awkwardly desynchronized. To know what's being returned from the trap, one needs to remember when the action is being called which makes writing traps harder I feel. With the current design, looking at the return statements is enough. If p.a is 2, I don't understand the point of action. Or at least, I don't see how it's better than just calling Reflect[trap]. 1) what happens if the trap does not call action? If calling action was made compulsory, then, it would have the same downsides than the notification proxies when it comes like virtual objects including the necessity of a physical backing. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)
Le 02/12/2012 20:40, Tom Van Cutsem a écrit : 2012/12/2 Mark S. Miller erig...@google.com mailto:erig...@google.com I think we can rescue around wrapping. I'll call this approach opaque around wrapping. The idea is that the proxy passes into the handler trap a proxy-generated no-argument function (a thunk) called action. Interesting. I had thought of a similar approach, but hadn't pursued it because I thought allocating a thunk per trap invocation would be deemed too expensive. I'll go ahead and sketch the design, which I think corresponds closely with your approach B) I think that for most traps, action could be a deeply frozen wrapped version of Reflect.trap. It would reduce action functions to one per trap which would be much better than one per trap invocation. 4) are there any return values from the trap that the proxy would pay attention to? Yes. If the trap returns the original result, it doesn't do any extra checks. Otherwise it does. Said a bit differently, the extra check is reduced to the equality between the return value of action and trap return value. I prefer #A to #B as it gains the full benefits of simplifying the overall spec and implementation. However, #B still seems better than current direct proxies, as the normal case gets target-maintenance and invariant checking for free. I agree that #B doesn't really simplify anything in the spec (the invariant checks are still there sometimes). I'm not sure if it is inherently better than the current design though: we gain performance in terms of avoiding invariant checks, but we lose performance by having to allocate a per-call thunk, + the API becomes more complex (an additional parameter to every trap) I do think that passing an action or forward() thunk to a trap as extra argument beats David's proposed throw ForwardToTarget trick in terms of elegance and usability (maybe not in terms of performance). I agree it looks less hacky. But I'm not entirely convinced when it comes to usability. As mentioned in the other answer, it makes understanding the trap a bit harder because what comes out of the trap may be less clear: since there is no explicit return statement, one has to figure out, what the value of the action function specifically when it's called for the around case. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array iterator questions
Yes, we should have a new covenant that avoids adding stringized array indexes for new APIs. New APIs need to turn down the arrays-are-objects setting JS had from 1.0 (JS1 in 1995 had something even more object-like: objects equated indexes to property names added in creation order! See DOM forms/elements/links array-likes where elements can have aliasing names depending on markup...). /be Rick Waldron wrote: On Sun, Dec 2, 2012 at 2:47 PM, Allen Wirfs-Brock al...@wirfs-brock.com mailto:al...@wirfs-brock.com wrote: On Dec 1, 2012, at 8:14 AM, Jason Orendorff wrote: snip 2. According to 15.4.6.2.2, the iterators produced by Array.prototype.keys and .items will expose the index values as strings. Why strings? Don't numbers make more sense? It does that because array index keys are exposed as strings everywhere else. There is no specific definition (that I can find) of the keys iterator for arrays in the wiki proposal. There is only the general @iter.keys function which is defined in terms of for-in and hence returns string property keys. However, I don't have any objection to return integer keys in this case. +1 Users will take this for granted and assume the index value is going to be a number since map, forEach, filter, every, some and reduce all pass a number as the index argument and for-loops increment a number. Rick Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array iterator questions
This discussion brings iterator protocol back into play for spread no? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Fw: lexical 'super' in arrow functions?
On Sun, Dec 2, 2012 at 3:13 PM, Claus Reinke claus.rei...@talk21.comwrote: First attempt got lost or stuck somewhere, trying again. --** From: Claus Reinke claus.rei...@talk21.com Sent: Thursday, November 29, 2012 10:02 PM To: es-discuss@mozilla.org Subject: lexical 'super' in arrow functions? Is 'super' currently limited to method bodies, excluding local functions? super is limited to ClassBody Given that 'this' is lexical in arrow functions, I expected any enclosing 'super' to be available, as well, but I cannot confirm this from the spec. Can you clarify... did you mean something like: class Mine extends Array { constructor(...args) { this.foo = () = { super(...args); }; } } ? This is from listening in on some of the TypeScript traffic, where people are running into all kind of issues when trying to use ES6 classes, btw. I've been following all of the tickets and offering support wherever I can—I'd love to see the specific cases that you're referring to. Rick Claus http://clausreinke.github.com/ __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical 'super' in arrow functions?
On Dec 2, 2012, at 12:13 PM, Claus Reinke wrote: First attempt got lost or stuck somewhere, trying again. -- From: Claus Reinke claus.rei...@talk21.com Sent: Thursday, November 29, 2012 10:02 PM To: es-discuss@mozilla.org Subject: lexical 'super' in arrow functions? Is 'super' currently limited to method bodies, excluding local functions? Given that 'this' is lexical in arrow functions, I expected any enclosing 'super' to be available, as well, but I cannot confirm this from the spec. Yes, clearly super should be able to be used in an arrow function that is lexically scoped to an enclosing super binding. The mechanism for describing this are mostly in the spec., but I just checked and there are a few loose ends that I will clean-up in the next spec. draft. Whether anything besides a concise method in a class can have a super binding is something that still needs to be discuss. There are some uses, eg class-side methods that reference super that can not be expressed if super use is restricted to concise methods within class bodies. This is from listening in on some of the TypeScript traffic, where people are running into all kind of issues when trying to use ES6 classes, btw. Claus Do you have a link to the threads? Sounds interesting... Allen http://clausreinke.github.com/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss