Re: Notification proxies (Was: possible excessive proxy invariants for Object.keys/etc??)

2012-12-02 Thread Tom Van Cutsem
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-12-02 Thread Tom Van Cutsem
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-12-02 Thread Tom Van Cutsem
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??)

2012-12-02 Thread David Bruant

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-02 Thread Tom Van Cutsem
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-12-02 Thread Tom Van Cutsem
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??)

2012-12-02 Thread David Bruant

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??)

2012-12-02 Thread Mark S. Miller
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

2012-12-02 Thread Allen Wirfs-Brock

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

2012-12-02 Thread Hudson, Rick
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-02 Thread Tom Van Cutsem
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

2012-12-02 Thread Allen Wirfs-Brock

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-02 Thread Tom Van Cutsem
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

2012-12-02 Thread Tom Van Cutsem
[+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

2012-12-02 Thread Allen Wirfs-Brock

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??)

2012-12-02 Thread Allen Wirfs-Brock

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

2012-12-02 Thread Allen Wirfs-Brock

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

2012-12-02 Thread Rick Waldron
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

2012-12-02 Thread Domenic Denicola
 -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??)

2012-12-02 Thread David Bruant

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??)

2012-12-02 Thread David Bruant

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

2012-12-02 Thread Brendan Eich
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

2012-12-02 Thread Brandon Benvie
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?

2012-12-02 Thread Rick Waldron
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?

2012-12-02 Thread Allen Wirfs-Brock

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