Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Gavin Barraclough

On Jul 7, 2011, at 9:49 PM, Mark S. Miller wrote:

 
 On Thu, Jul 7, 2011 at 9:41 PM, Gavin Barraclough barraclo...@apple.com 
 wrote:
 Hi Mark,
 
 In the harmony classes proposal, 
 http://wiki.ecmascript.org/doku.php?id=harmony:classes , I'm interested in 
 understanding the following issue:
 
One or two namespaces for public properties and private instance 
 variables [RESOLVED two, Mark’s argument]
 
 Do you remember if this argument was made in email, and if so would anyone 
 happen to know where to look to find this (I've tried a little googling to no 
 avail!), I'd be interested in understanding the rationale behind this 
 decision.
 
 
 I don't think it was made in before in email. Here goes:
 
 For non-const classes, their instances are extensible by default. Even if you 
 disagree with this default, I think we generally agree that there should at 
 least be an option to make extensible instances.
 
 Say public and private share one namespace. Say extensible instance X has 
 private instance property 'foo'. Say a client of X tries to extend it with a 
 public 'foo' property. What happens?

Ah, I see.  It's a fair point, but isn't this already a hazard that the 
language faces?

Suppose I have two objects, extensible instance X with private instance 
property 'foo', and extensible object Y upon which I have defined a property 
'foo' using Object.defineProperty, setting writable=false.  If a client of Y 
tries to extend if with a public 'foo' property, then this would fail (throwing 
a TypeError in strict mode code).  Would it not be acceptable for the attempted 
assignment to the private property of X to fail in a similar fashion?  It seems 
that it is already the case that if a client wishes to associate data with a 
given object under any arbitrary name, then the only truly safe way to do so is 
through an external mapping such as a weak map / ephemeron table?

Might it be reasonable to make private properties be regular properties on the 
object, with a new 'private' attribute, similar to the existing 
writable/configurable attributes?  From the perspective of code outside of the 
associated class, an instance's private property would be non-readable, 
non-writable and non-configurable (likely also non-enumerable?), with any 
attempt to get, set, or delete the property failing in a similar manner to an 
existing writable/configurable attribute violation.  It would be great to hear 
your thoughts on this.

cheers,
G.


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Brendan Eich
On Jul 7, 2011, at 11:07 PM, Gavin Barraclough wrote:

 Ah, I see.  It's a fair point, but isn't this already a hazard that the 
 language faces?

Not with private names.


 Suppose I have two objects, extensible instance X with private instance 
 property 'foo', and extensible object Y upon which I have defined a property 
 'foo' using Object.defineProperty, setting writable=false.  If a client of Y 
 tries to extend if with a public 'foo' property, then this would fail 
 (throwing a TypeError in strict mode code).  Would it not be acceptable for 
 the attempted assignment to the private property of X to fail in a similar 
 fashion?

No, that leaks the fact that there's a private-named object (if you also 
enumerate public names and do not find such a name; or enumerate property 
descriptors, etc.).


  It seems that it is already the case that if a client wishes to associate 
 data with a given object under any arbitrary name, then the only truly safe 
 way to do so is through an external mapping such as a weak map / ephemeron 
 table?

No, private names are in ES.next:

http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects


 Might it be reasonable to make private properties be regular properties on 
 the object, with a new 'private' attribute, similar to the existing 
 writable/configurable attributes?  From the perspective of code outside of 
 the associated class, an instance's private property would be non-readable, 
 non-writable and non-configurable (likely also non-enumerable?), with any 
 attempt to get, set, or delete the property failing in a similar manner to an 
 existing writable/configurable attribute violation.  It would be great to 
 hear your thoughts on this.

See above -- private means you can't probe, let alone collide, for the private 
name from outside of the abstraction. Private name objects prove much more than 
a single-bit 'private' attribute -- they allow private, protected, friend, 
shared-secret, and public-but-guarnateed-unique names.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Brendan Eich
On Jul 7, 2011, at 11:15 PM, Brendan Eich wrote:

 Suppose I have two objects, extensible instance X with private instance 
 property 'foo', and extensible object Y upon which I have defined a property 
 'foo' using Object.defineProperty, setting writable=false.  If a client of Y 
 tries to extend if with a public 'foo' property, then this would fail 
 (throwing a TypeError in strict mode code).  Would it not be acceptable for 
 the attempted assignment to the private property of X to fail in a similar 
 fashion?
 
 No, that leaks the fact that there's a private-named object

er, private property on the object.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Type of property names, as seen by proxy traps

2011-07-08 Thread Tom Van Cutsem
2011/7/7 David Herman dher...@mozilla.com

 2011/7/6 Andreas Rossberg rossb...@google.com

 While putting together some test cases for Object.keys, I wondered: is
 it intended that property names are always passed to traps as strings?


 That is indeed the intent.


 Unless they are private name objects, right?


I'm not sure. I briefly checked the private names proposal 
http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects and I
think the detailed interaction with proxies still has to be fleshed out.

The proposal does mention: All reflective operations that produce a
property name, when reflecting on a private name, produce the name’s .public
property instead of the name itself.

Would the same hold for reflective operations that consume property names,
such as handler traps?

Cheers,
Tom
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Minor type confusion in proxies proposal?

2011-07-08 Thread Andreas Rossberg
It seems like we need to make a change to Object.defineProperties, too
(regardless of the other issue). With the current wording, it will not
forward user attributes to the defineProperty trap. The most modular
fix (that seems compatible with your proposal below) probably is to
change the spec of defineProperties to go through defineProperty,
instead of calling the internal [[DefineOwnProperty]] directly.

/Andreas


On 6 July 2011 14:55, Andreas Rossberg rossb...@google.com wrote:
 On 3 July 2011 13:29, Tom Van Cutsem tomvc...@gmail.com wrote:
 Comments?

 Looks good to me. I agree with Mark's comment that it should do a
 (shallow) copy of the attributes object, though. I guess the obvious
 point would be in Object.defineProperty, before passing it to
 DefineProxyProperty.

 /Andreas


 2011/7/2 Andreas Rossberg rossb...@google.com

 Hi Tom.

 On 2 July 2011 13:50, Tom Van Cutsem tomvc...@gmail.com wrote:
  Hi Andreas,
  First, you're right about the typing issue:
  In ES5, for values of type Object, the signature for
  [[DefineOwnProperty]]
  would be:
  [[DefineOwnProperty]](P: a property name, Desc: an internal property
  descriptor, Throw: a boolean)
  On trapping proxies, that signature would need to change to:
  [[DefineOwnProperty]](P: a property name, Desc: an Object, Throw: a
  boolean)

 I don't think such a change is consistent. [[DefineOwnProperty]] is
 invoked in a number of places in the spec, and I think in many of them
 the type of the receiver is not distinguished and may well be a proxy,
 so a proxy may then receive both kinds of descriptors. Moreover, I
 think it would be a mistake to make the appropriate case distinction
 everywhere -- you really want the internal method to have the same
 signature in all cases.

  With that, I believe the strawman is otherwise internally consistent. In
  [[DefineOwnProperty]] step 5, what will be passed to the user-defined
  defineProperty trap is a proper Object, not an internal descriptor.
  I did clarify the note you referred to, to be more explicit in this
  regard.
  I don't see an alternative to changing the signature of
  [[DefineOwnProperty]]. It can't just receive an internal descriptor, as
  it
  doesn't preserve any non-standard attributes.

 How about simply bypassing [[DefineOwnProperty]] in
 Object.defineProperty for proxies, as I suggested in my reply to
 David? That seems to be the only place where additional objects can
 occur, or am I wrong?

 Cheers,
 /Andreas


  2011/7/1 Andreas Rossberg rossb...@google.com
 
  On 1 July 2011 12:12, Andreas Rossberg rossb...@google.com wrote:
   I believe there is some type confusion in the proxy proposal spec
   wrt property descriptors and their reification into attributes
   objects.
  
   1. In a note on the def of [[DefineOwnProperty]] for proxies, the
   proposal says:
  
   The Desc argument to this trap is a property descriptor object
   validated by ToPropertyDescriptor, except that it also retains any
   non-standard attributes present in the original property descriptor
   passed to Object.defineProperty. See the semantics of the modified
   Object.defineProperty built-in, below.
  
   That seems fishy, since according to ES5 8.10:
  
   Values of the Property Descriptor type are records composed of named
   fields where each field‘s name is an attribute name and its value is
   a
   corresponding attribute value as specified in 8.6.1.
  
   In particular, I take this to mean that property descriptors are not
   objects (but abstract records), and that there cannot be any fields
   whose name is not an attribute name. (In fact, in V8 we currently
   encode property descriptors using objects, but the encoding is
   different from the reified attributes object representation, and not
   quite compatible with the idea of adding arbitrary other fields.)
 
  I forgot to say: step 5 of the definition invokes the defineProperty
  trap of the handler passing Desc as the second argument. But the
  handler expects a reified attributes object.
 
   2. In the modified definition of Object.defineProperty, the proposal
   says in step 4.c:
  
   Call the [[DefineOwnProperty]] internal method of O with arguments
   name, descObj, and true.
  
   This is passing descObj, which in fact is _not_ a descriptor, but its
   reification as an attributes object.
  
   /Andreas
  
  ___
  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: Minor type confusion in proxies proposal?

2011-07-08 Thread Andreas Rossberg
Likewise, invoking Object.getOwnPropertyDescriptor on a proxy does not
return user attributes. That actually is explicitly noted in the
semantics for [[GetOwnProperty]], but I'm not sure I see the rationale
behind it.

I would prefer a more coherent story with respect to proxies and user
attributes on descriptor objects. That is, we should either support
such attributes properly, i.e. have them consistently flow both ways
(from clients to traps and vice versa). Or we do not support them at
all, i.e. filter them out everywhere.

/Andreas


On 8 July 2011 10:59, Andreas Rossberg rossb...@google.com wrote:
 It seems like we need to make a change to Object.defineProperties, too
 (regardless of the other issue). With the current wording, it will not
 forward user attributes to the defineProperty trap. The most modular
 fix (that seems compatible with your proposal below) probably is to
 change the spec of defineProperties to go through defineProperty,
 instead of calling the internal [[DefineOwnProperty]] directly.

 /Andreas


 On 6 July 2011 14:55, Andreas Rossberg rossb...@google.com wrote:
 On 3 July 2011 13:29, Tom Van Cutsem tomvc...@gmail.com wrote:
 Comments?

 Looks good to me. I agree with Mark's comment that it should do a
 (shallow) copy of the attributes object, though. I guess the obvious
 point would be in Object.defineProperty, before passing it to
 DefineProxyProperty.

 /Andreas


 2011/7/2 Andreas Rossberg rossb...@google.com

 Hi Tom.

 On 2 July 2011 13:50, Tom Van Cutsem tomvc...@gmail.com wrote:
  Hi Andreas,
  First, you're right about the typing issue:
  In ES5, for values of type Object, the signature for
  [[DefineOwnProperty]]
  would be:
  [[DefineOwnProperty]](P: a property name, Desc: an internal property
  descriptor, Throw: a boolean)
  On trapping proxies, that signature would need to change to:
  [[DefineOwnProperty]](P: a property name, Desc: an Object, Throw: a
  boolean)

 I don't think such a change is consistent. [[DefineOwnProperty]] is
 invoked in a number of places in the spec, and I think in many of them
 the type of the receiver is not distinguished and may well be a proxy,
 so a proxy may then receive both kinds of descriptors. Moreover, I
 think it would be a mistake to make the appropriate case distinction
 everywhere -- you really want the internal method to have the same
 signature in all cases.

  With that, I believe the strawman is otherwise internally consistent. In
  [[DefineOwnProperty]] step 5, what will be passed to the user-defined
  defineProperty trap is a proper Object, not an internal descriptor.
  I did clarify the note you referred to, to be more explicit in this
  regard.
  I don't see an alternative to changing the signature of
  [[DefineOwnProperty]]. It can't just receive an internal descriptor, as
  it
  doesn't preserve any non-standard attributes.

 How about simply bypassing [[DefineOwnProperty]] in
 Object.defineProperty for proxies, as I suggested in my reply to
 David? That seems to be the only place where additional objects can
 occur, or am I wrong?

 Cheers,
 /Andreas


  2011/7/1 Andreas Rossberg rossb...@google.com
 
  On 1 July 2011 12:12, Andreas Rossberg rossb...@google.com wrote:
   I believe there is some type confusion in the proxy proposal spec
   wrt property descriptors and their reification into attributes
   objects.
  
   1. In a note on the def of [[DefineOwnProperty]] for proxies, the
   proposal says:
  
   The Desc argument to this trap is a property descriptor object
   validated by ToPropertyDescriptor, except that it also retains any
   non-standard attributes present in the original property descriptor
   passed to Object.defineProperty. See the semantics of the modified
   Object.defineProperty built-in, below.
  
   That seems fishy, since according to ES5 8.10:
  
   Values of the Property Descriptor type are records composed of named
   fields where each field‘s name is an attribute name and its value is
   a
   corresponding attribute value as specified in 8.6.1.
  
   In particular, I take this to mean that property descriptors are not
   objects (but abstract records), and that there cannot be any fields
   whose name is not an attribute name. (In fact, in V8 we currently
   encode property descriptors using objects, but the encoding is
   different from the reified attributes object representation, and not
   quite compatible with the idea of adding arbitrary other fields.)
 
  I forgot to say: step 5 of the definition invokes the defineProperty
  trap of the handler passing Desc as the second argument. But the
  handler expects a reified attributes object.
 
   2. In the modified definition of Object.defineProperty, the proposal
   says in step 4.c:
  
   Call the [[DefineOwnProperty]] internal method of O with arguments
   name, descObj, and true.
  
   This is passing descObj, which in fact is _not_ a descriptor, but its
   reification as an attributes object.
  
   /Andreas
  
  

Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Juan Ignacio Dopazo
On Fri, Jul 8, 2011 at 3:15 AM, Brendan Eich bren...@mozilla.com wrote:

 On Jul 7, 2011, at 11:07 PM, Gavin Barraclough wrote:

  Ah, I see.  It's a fair point, but isn't this already a hazard that the
 language faces?

 Not with private names.

 There's also something that was probably discussed but never got to this
list:

Private instance properties were considered to be accessible by all
instances of the class. That's a new concept in ES. Were there arguments for
keeping instance private properties private to the instance?

Juan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Mark S. Miller
On Fri, Jul 8, 2011 at 6:36 AM, Juan Ignacio Dopazo
dopazo.j...@gmail.comwrote:

 On Fri, Jul 8, 2011 at 3:15 AM, Brendan Eich bren...@mozilla.com wrote:

 On Jul 7, 2011, at 11:07 PM, Gavin Barraclough wrote:

  Ah, I see.  It's a fair point, but isn't this already a hazard that the
 language faces?

 Not with private names.

 There's also something that was probably discussed but never got to this
 list:

 Private instance properties were considered to be accessible by all
 instances of the class. That's a new concept in ES. Were there arguments for
 keeping instance private properties private to the instance?


Yes. That's done quite well by lexical capture of the constructor lexical
context by per-instance methods:

class Point {
  constructor(x, y) {
public getX() { return x; }
...
  }
}

which basically sugars the objects-as-closure pattern. If you don't mind the
allocation cost, this is superior in almost all ways to the conventional
prototype/this-based pattern.

private is needed when combining inherited methods with encapsulation.
Since inherited methods may apply to any instance of the class and are not
automagically bound to any one instance, their access to encapsulated state
cannot be any finer than per-class.



 Juan

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Type of property names, as seen by proxy traps

2011-07-08 Thread David Herman
 I'm not sure. I briefly checked the private names proposal 
 http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects and I 
 think the detailed interaction with proxies still has to be fleshed out.

Sure, I'll be happy to work with you on this.

 The proposal does mention: All reflective operations that produce a property 
 name, when reflecting on a private name, produce the name’s .public property 
 instead of the name itself.
 
 Would the same hold for reflective operations that consume property names, 
 such as handler traps?

No, they would require the private name object. The idea here is that you need 
a reference to the private name to get access to its property. So you can't do 
any proxy operations on a private property if you don't have the private name 
object. But the proxy traps do not automatically hand out that reference to a 
handler trap, in case the trap didn't already have a reference to it (which 
would constitute a leak). Instead, it hands them the corresponding public key. 
This way, *if* the trap has a reference to the private key, it can identify 
which private name is being accessed. Otherwise, the trap can't conclude 
anything more than operation X was requested on *some* private name.

Dave

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


JS control-structure abstractions, using tailnest flattening and tailcall optimization

2011-07-08 Thread Claus Reinke

Dear all,

we have seen examples of how to define control-structure
abstractions via block-lambdas (and Smalltalk blocks), including
non-local returns out of user-defined loops.

I'd like to provide an example of how to do something like this 
with JS, using only the proposed syntactic sugar for flat syntactic 
tailnests and the upcoming support for flat runtime tailcall stacks 
(for callback chains, the two complement each other).


Building up from small structures, the example aims to implement 
a variant of yield. With conventional blocks, this requires the 
upcoming generators language extension. Block-lambdas do 
not help here, I think, because yield can suspend and resume at 
statement level, and even the slightly unusual sequel feature 
does only support non-local return, no resume (calling a sequel 
returns to a lexically scoped elsewhere, not to the caller). 

If JS had call/cc or delimited continuations, we could implement 
yield on top of that, but that isn't likely. If we were to rewrite our 
code in continuation passing style (cps), we could implement 
call/cc, but even in languages with lightweight function syntax, 
that is not considered very readable. There are modular variants 
of continuation passing style that can be made to look very similar 
to normal code, but these become unreadable in JS syntax. 
Cps without tailcall optimization also quickly overflows the stack.


Which is where tailnests (readability) and tailcalls (efficiency/
useability) come in, addressing the issues that cps in current 
JS leads to overflows in syntactic and runtime stack nesting.


First, the programming pattern: in plain cps, we'd have nested 
callback chains feeding intermediate results into the rest of the

callback chain (assuming currying for the callback parameter):

   operation(..)( function(result) { ..operations..} )

With paren-free right-associative calls (f @ arg) and brace-free
definitions (function(arg) = expr) for expression functions, this
becomes:

   operation(..) @ function(result) = ..operations..

Tailcall optimization guarantees that the callbacks will not 
overflow the runtime stack, and tailnest flattening keeps the

level of syntactic nesting independent of the chain length.

In modular cps, instead of every operation taking a callback
parameter, every operation returns its result in an object 
implementing a single method 'then' (the ideas are standard,
the translation to JS is not). Calling 'then' with a callback feeds 
a value/intermediate result to the callback.


   operation(..).then @ function(result) = ..operations..

(which can be read as a clumsy way to write
let result - operation in operations, but the .then allows
us to give different meanings to the variable binding, eg., it
could mean foreach result from operation, do operations, or 
it could store the continuation and jump elsewhere, as yield)


The most basic operation is 'value', which just wraps a value
into a then-able:

   function value(val) = { then : function(cont) = cont(val) }

Since statements represented as then-ables are objects, 
conditional statements are just conditional expressions:


   cond ? t : e

or, if the condition involves then-able statements, too:

   cond.then @ function( c ) = c ? t : e

which we can either use directly, or wrap in a function (the 
then/else-branch arguments are themselves wrapped to 
delay their evaluation):


   function if_(cond) = function(ft) = function(fe) =
   cond.then @ function( c ) = c ? ft() : fe()

Hence, a while-loop with then-able condition and delayed body:

   function while_(cond) = function(body) =
   if_(cond)
   (function() = body().then @ function() = 
   while_(cond)(body) )

   (function() = value( null ) )

You can find these examples online [1], so to limit this email,
I'll jump right to the interesting bit, which is implementing yield:

yield_(val) produces a then-able that behaves a bit unusually:
instead of passing a value to continuations passed via .then(),
it swallows all such continuations, storing them for later use
(in plain cps, we'd have the whole continuation at hand; in this
modular cps variation, we have to collect nested continuations).

To get at the yielded value, we can call yield_(val).value(cont),
and to restart the generator, we can call yield_(val).next(),
which applies the internally stored continuations to val. In code:

   function yield_(val) = { then: stack(val) };

   function stack(val) = function(c1) =
 { then:  function(c2)   = stack(val)(comp_then(c2,c1))
 , value: function(cont) = cont(val)
 , next:  function() = c1(val) }; 


   function comp_then(c2,c1) = function(val) = c1(val).then(c2);

Again, the commented code and a couple of example generators 
can be found online [1]. If you use the desugaring page, you can 
see why this style isn't popular without syntactic sugar. But the
functionality is plain JS, no semantic changes! 

The code 

Re: Minor type confusion in proxies proposal?

2011-07-08 Thread Tom Van Cutsem
2011/7/8 Andreas Rossberg rossb...@google.com

 It seems like we need to make a change to Object.defineProperties, too
 (regardless of the other issue). With the current wording, it will not
 forward user attributes to the defineProperty trap. The most modular
 fix (that seems compatible with your proposal below) probably is to
 change the spec of defineProperties to go through defineProperty,
 instead of calling the internal [[DefineOwnProperty]] directly.


I agree. Noted.



 /Andreas


 On 6 July 2011 14:55, Andreas Rossberg rossb...@google.com wrote:
  On 3 July 2011 13:29, Tom Van Cutsem tomvc...@gmail.com wrote:
  Comments?
 
  Looks good to me. I agree with Mark's comment that it should do a
  (shallow) copy of the attributes object, though. I guess the obvious
  point would be in Object.defineProperty, before passing it to
  DefineProxyProperty.
 
  /Andreas
 
 
  2011/7/2 Andreas Rossberg rossb...@google.com
 
  Hi Tom.
 
  On 2 July 2011 13:50, Tom Van Cutsem tomvc...@gmail.com wrote:
   Hi Andreas,
   First, you're right about the typing issue:
   In ES5, for values of type Object, the signature for
   [[DefineOwnProperty]]
   would be:
   [[DefineOwnProperty]](P: a property name, Desc: an internal property
   descriptor, Throw: a boolean)
   On trapping proxies, that signature would need to change to:
   [[DefineOwnProperty]](P: a property name, Desc: an Object, Throw: a
   boolean)
 
  I don't think such a change is consistent. [[DefineOwnProperty]] is
  invoked in a number of places in the spec, and I think in many of them
  the type of the receiver is not distinguished and may well be a proxy,
  so a proxy may then receive both kinds of descriptors. Moreover, I
  think it would be a mistake to make the appropriate case distinction
  everywhere -- you really want the internal method to have the same
  signature in all cases.
 
   With that, I believe the strawman is otherwise internally consistent.
 In
   [[DefineOwnProperty]] step 5, what will be passed to the user-defined
   defineProperty trap is a proper Object, not an internal descriptor.
   I did clarify the note you referred to, to be more explicit in this
   regard.
   I don't see an alternative to changing the signature of
   [[DefineOwnProperty]]. It can't just receive an internal descriptor,
 as
   it
   doesn't preserve any non-standard attributes.
 
  How about simply bypassing [[DefineOwnProperty]] in
  Object.defineProperty for proxies, as I suggested in my reply to
  David? That seems to be the only place where additional objects can
  occur, or am I wrong?
 
  Cheers,
  /Andreas
 
 
   2011/7/1 Andreas Rossberg rossb...@google.com
  
   On 1 July 2011 12:12, Andreas Rossberg rossb...@google.com wrote:
I believe there is some type confusion in the proxy proposal
 spec
wrt property descriptors and their reification into attributes
objects.
   
1. In a note on the def of [[DefineOwnProperty]] for proxies, the
proposal says:
   
The Desc argument to this trap is a property descriptor object
validated by ToPropertyDescriptor, except that it also retains any
non-standard attributes present in the original property
 descriptor
passed to Object.defineProperty. See the semantics of the modified
Object.defineProperty built-in, below.
   
That seems fishy, since according to ES5 8.10:
   
Values of the Property Descriptor type are records composed of
 named
fields where each field‘s name is an attribute name and its value
 is
a
corresponding attribute value as specified in 8.6.1.
   
In particular, I take this to mean that property descriptors are
 not
objects (but abstract records), and that there cannot be any
 fields
whose name is not an attribute name. (In fact, in V8 we currently
encode property descriptors using objects, but the encoding is
different from the reified attributes object representation, and
 not
quite compatible with the idea of adding arbitrary other fields.)
  
   I forgot to say: step 5 of the definition invokes the defineProperty
   trap of the handler passing Desc as the second argument. But the
   handler expects a reified attributes object.
  
2. In the modified definition of Object.defineProperty, the
 proposal
says in step 4.c:
   
Call the [[DefineOwnProperty]] internal method of O with
 arguments
name, descObj, and true.
   
This is passing descObj, which in fact is _not_ a descriptor, but
 its
reification as an attributes object.
   
/Andreas
   
   ___
   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: Minor type confusion in proxies proposal?

2011-07-08 Thread Tom Van Cutsem
2011/7/8 Andreas Rossberg rossb...@google.com

 Likewise, invoking Object.getOwnPropertyDescriptor on a proxy does not
 return user attributes. That actually is explicitly noted in the
 semantics for [[GetOwnProperty]], but I'm not sure I see the rationale
 behind it.

 I would prefer a more coherent story with respect to proxies and user
 attributes on descriptor objects. That is, we should either support
 such attributes properly, i.e. have them consistently flow both ways
 (from clients to traps and vice versa). Or we do not support them at
 all, i.e. filter them out everywhere.


I believe the note at [[GetOwnProperty]] predates our thoughts on allowing
user-defined attributes. So yes, we should be consistent and perform the
same type of normalization of property descriptors as for defineProperty.


 /Andreas


 On 8 July 2011 10:59, Andreas Rossberg rossb...@google.com wrote:
  It seems like we need to make a change to Object.defineProperties, too
  (regardless of the other issue). With the current wording, it will not
  forward user attributes to the defineProperty trap. The most modular
  fix (that seems compatible with your proposal below) probably is to
  change the spec of defineProperties to go through defineProperty,
  instead of calling the internal [[DefineOwnProperty]] directly.
 
  /Andreas
 
 
  On 6 July 2011 14:55, Andreas Rossberg rossb...@google.com wrote:
  On 3 July 2011 13:29, Tom Van Cutsem tomvc...@gmail.com wrote:
  Comments?
 
  Looks good to me. I agree with Mark's comment that it should do a
  (shallow) copy of the attributes object, though. I guess the obvious
  point would be in Object.defineProperty, before passing it to
  DefineProxyProperty.
 
  /Andreas
 
 
  2011/7/2 Andreas Rossberg rossb...@google.com
 
  Hi Tom.
 
  On 2 July 2011 13:50, Tom Van Cutsem tomvc...@gmail.com wrote:
   Hi Andreas,
   First, you're right about the typing issue:
   In ES5, for values of type Object, the signature for
   [[DefineOwnProperty]]
   would be:
   [[DefineOwnProperty]](P: a property name, Desc: an internal property
   descriptor, Throw: a boolean)
   On trapping proxies, that signature would need to change to:
   [[DefineOwnProperty]](P: a property name, Desc: an Object, Throw: a
   boolean)
 
  I don't think such a change is consistent. [[DefineOwnProperty]] is
  invoked in a number of places in the spec, and I think in many of them
  the type of the receiver is not distinguished and may well be a proxy,
  so a proxy may then receive both kinds of descriptors. Moreover, I
  think it would be a mistake to make the appropriate case distinction
  everywhere -- you really want the internal method to have the same
  signature in all cases.
 
   With that, I believe the strawman is otherwise internally
 consistent. In
   [[DefineOwnProperty]] step 5, what will be passed to the
 user-defined
   defineProperty trap is a proper Object, not an internal
 descriptor.
   I did clarify the note you referred to, to be more explicit in this
   regard.
   I don't see an alternative to changing the signature of
   [[DefineOwnProperty]]. It can't just receive an internal descriptor,
 as
   it
   doesn't preserve any non-standard attributes.
 
  How about simply bypassing [[DefineOwnProperty]] in
  Object.defineProperty for proxies, as I suggested in my reply to
  David? That seems to be the only place where additional objects can
  occur, or am I wrong?
 
  Cheers,
  /Andreas
 
 
   2011/7/1 Andreas Rossberg rossb...@google.com
  
   On 1 July 2011 12:12, Andreas Rossberg rossb...@google.com
 wrote:
I believe there is some type confusion in the proxy proposal
 spec
wrt property descriptors and their reification into attributes
objects.
   
1. In a note on the def of [[DefineOwnProperty]] for proxies, the
proposal says:
   
The Desc argument to this trap is a property descriptor object
validated by ToPropertyDescriptor, except that it also retains
 any
non-standard attributes present in the original property
 descriptor
passed to Object.defineProperty. See the semantics of the
 modified
Object.defineProperty built-in, below.
   
That seems fishy, since according to ES5 8.10:
   
Values of the Property Descriptor type are records composed of
 named
fields where each field‘s name is an attribute name and its value
 is
a
corresponding attribute value as specified in 8.6.1.
   
In particular, I take this to mean that property descriptors are
 not
objects (but abstract records), and that there cannot be any
 fields
whose name is not an attribute name. (In fact, in V8 we currently
encode property descriptors using objects, but the encoding is
different from the reified attributes object representation, and
 not
quite compatible with the idea of adding arbitrary other fields.)
  
   I forgot to say: step 5 of the definition invokes the
 defineProperty
   trap of the handler passing Desc as the second argument. But the
   

Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 6:36 AM, Juan Ignacio Dopazo wrote:

 On Fri, Jul 8, 2011 at 3:15 AM, Brendan Eich bren...@mozilla.com wrote:
 On Jul 7, 2011, at 11:07 PM, Gavin Barraclough wrote:
 
  Ah, I see.  It's a fair point, but isn't this already a hazard that the 
  language faces?
 
 Not with private names.
 
 There's also something that was probably discussed but never got to this list:
 
 Private instance properties were considered to be accessible by all instances 
 of the class. That's a new concept in ES. Were there arguments for keeping 
 instance private properties private to the instance?

Yes, on this list, going back to the Harmony Oslo July 2008 meeting, with 
followup at the Kona Nov. 2008 meeting.

Mark may have notes from the more recent sub-group of TC39ers who championed 
classes. My recollection is that we chose class-private for both usability and 
private-name equivalence, but we still have open issues on how one accesses 
private foo in both |this| and |other| for a dyadic operator method, e.g.

/be


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 7:43 AM, Juan Ignacio Dopazo wrote:

 My first thought was: why not just statically replace this.x, with private x, 
 with this[xPrivateName] and forget about accessing private properties of 
 other objects? That would still leave the problem of closures inside methods, 
 though...

If xPrivateName is a private name object, then there's no reason to forget 
about accessing private properties of other objects. Both this[xPrivateName] 
and other[xPrivateName] work as you would expect.

/be___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Type of property names, as seen by proxy traps

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 7:17 AM, David Herman wrote:

 The proposal does mention: All reflective operations that produce a 
 property name, when reflecting on a private name, produce the name’s .public 
 property instead of the name itself.
 
 Would the same hold for reflective operations that consume property names, 
 such as handler traps?
 
 No, they would require the private name object.

I don't think that's what Tom was asking about, though. The proposal may simply 
be unclear in using produce instead of consume since the proxy mechanism 
does not produce private names in any generative sense when one writes p[q] for 
proxy p and private name q.

Rather, the VM substitutes q.public for q when calling p's handler's relevant 
trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as you note, and 
the owner of q is free to share it with trap implementations that should have 
access to it, so they can compare name == q.public, memoize in q.public in a 
weak map, etc.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Type of property names, as seen by proxy traps

2011-07-08 Thread David Herman
Sorry, yes. Too early in the morning for me. :)

Indeed, handler traps are exactly the place where the system *produces* names 
and hands them to handler traps which consume them, and that's where it must 
produce a public key rather than a private name object.

Dave

On Jul 8, 2011, at 8:20 AM, Brendan Eich wrote:

 On Jul 8, 2011, at 7:17 AM, David Herman wrote:
 
 The proposal does mention: All reflective operations that produce a 
 property name, when reflecting on a private name, produce the name’s 
 .public property instead of the name itself.
 
 Would the same hold for reflective operations that consume property names, 
 such as handler traps?
 
 No, they would require the private name object.
 
 I don't think that's what Tom was asking about, though. The proposal may 
 simply be unclear in using produce instead of consume since the proxy 
 mechanism does not produce private names in any generative sense when one 
 writes p[q] for proxy p and private name q.
 
 Rather, the VM substitutes q.public for q when calling p's handler's relevant 
 trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as you note, 
 and the owner of q is free to share it with trap implementations that should 
 have access to it, so they can compare name == q.public, memoize in q.public 
 in a weak map, etc.
 
 /be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Type of property names, as seen by proxy traps

2011-07-08 Thread David Herman
And just to be clear, I meant produce in the sense of producer/consumer 
relationship on the trap functions, not in the generative sense.

Dave

On Jul 8, 2011, at 8:40 AM, David Herman wrote:

 Sorry, yes. Too early in the morning for me. :)
 
 Indeed, handler traps are exactly the place where the system *produces* names 
 and hands them to handler traps which consume them, and that's where it must 
 produce a public key rather than a private name object.
 
 Dave
 
 On Jul 8, 2011, at 8:20 AM, Brendan Eich wrote:
 
 On Jul 8, 2011, at 7:17 AM, David Herman wrote:
 
 The proposal does mention: All reflective operations that produce a 
 property name, when reflecting on a private name, produce the name’s 
 .public property instead of the name itself.
 
 Would the same hold for reflective operations that consume property names, 
 such as handler traps?
 
 No, they would require the private name object.
 
 I don't think that's what Tom was asking about, though. The proposal may 
 simply be unclear in using produce instead of consume since the proxy 
 mechanism does not produce private names in any generative sense when one 
 writes p[q] for proxy p and private name q.
 
 Rather, the VM substitutes q.public for q when calling p's handler's 
 relevant trap (getOwnPropertyDescriptor, get, ...). So there's no leak, as 
 you note, and the owner of q is free to share it with trap implementations 
 that should have access to it, so they can compare name == q.public, memoize 
 in q.public in a weak map, etc.
 
 /be
 
 ___
 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: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Juan Ignacio Dopazo
On Fri, Jul 8, 2011 at 12:15 PM, Brendan Eich bren...@mozilla.com wrote:

 On Jul 8, 2011, at 7:43 AM, Juan Ignacio Dopazo wrote:

 My first thought was: why not just statically replace this.x, with private
 x, with this[xPrivateName] and forget about accessing private properties
 of other objects? That would still leave the problem of closures inside
 methods, though...


 If xPrivateName is a private name object, then there's no reason to forget
 about accessing private properties of other objects. Both
 this[xPrivateName] and other[xPrivateName] work as you would expect.

 /be

You are very much right. What are the open issues with privates in classes
then?

Juan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: JS control-structure abstractions, using tailnest flattening and tailcall optimization

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 7:34 AM, Claus Reinke wrote:

 Tailcall optimization guarantees that the callbacks will not overflow the 
 runtime stack, and tailnest flattening keeps the
 level of syntactic nesting independent of the chain length.

ES.next has generators and proper tail calls already. I'm hard-pressed to call 
the syntax extensions you propose 'more readable than what can be done with 
generators and libraries such as taskjs (https://github.com/dherman/taskjs). I 
have to say @ and expression-forms seem less readable in general.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Juan Ignacio Dopazo
On Fri, Jul 8, 2011 at 1:52 PM, Brendan Eich bren...@mozilla.com wrote:

 On Jul 8, 2011, at 8:45 AM, Juan Ignacio Dopazo wrote:

 You are very much right. What are the open issues with privates in classes
 then?


 The wiki lists some. Here are a few from memory:

 * Syntax to use instead of private(this), private(other). The straw
 private(foo) syntax is too verbose and it wrongly suggests that a private
 data record is a distinct object. Are we ready to claim @ as prefix and
 infix operator (with restriction against LineTerminator on its left)?


Why do privates need special syntax? Isn't the point to just use them with
this.privateWhatever?


 * Private prototype methods and other properties may be useful, especially
 methods. One can wrap a closure around the class and put private helpers
 there, of course, but with private syntax in the proposal, why stop short?


+1!


 If we do support private prototype properties, then what are the semantics?
 Private name objects, as recently noted, have their .public counterparts
 passed as name parameters to proxy traps, so something about private
 prototype properties may be observable:

 class Victim prototypes Proxy { private protoMethod() {
 privat(super).protoMethod(); } }


Isn't that only an issue of protected vs private?

Juan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Public/private namespaces in harmony classes proposal

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 10:20 AM, Juan Ignacio Dopazo wrote:

 On Fri, Jul 8, 2011 at 1:52 PM, Brendan Eich bren...@mozilla.com wrote:
 On Jul 8, 2011, at 8:45 AM, Juan Ignacio Dopazo wrote:
 You are very much right. What are the open issues with privates in classes 
 then?
 
 The wiki lists some. Here are a few from memory:
 
 * Syntax to use instead of private(this), private(other). The straw 
 private(foo) syntax is too verbose and it wrongly suggests that a private 
 data record is a distinct object. Are we ready to claim @ as prefix and infix 
 operator (with restriction against LineTerminator on its left)?
 
 Why do privates need special syntax? Isn't the point to just use them with 
 this.privateWhatever? 

No, because of the other.x problem:

  class Point {
constructor(x, y) {...}
equals(other) { return this.x is other.x  this.y is other.y; }
...
  }

We cannot know how to ask for private-x from other without special syntax of 
some kind, either at the access point or as a binding declaration affecting all 
.x (and x: in object literals).


 If we do support private prototype properties, then what are the semantics? 
 Private name objects, as recently noted, have their .public counterparts 
 passed as name parameters to proxy traps, so something about private 
 prototype properties may be observable:
 
 class Victim prototypes Proxy { private protoMethod() { 
 privat(super).protoMethod(); } }
 
 Isn't that only an issue of protected vs private?

Sorry, that may be a bad example. Consider the Point example above, where other 
is a proxy and we use @ for private access:

  class Point {
constructor(x, y) {...}
equals(other) { return @x is other@x  @y is other@y; }
...
  }

(The unary prefix form @foo is short for binary this@foo.)

The spec has to say what the proxy denoted by other sees as the name 
parameter when its handler's relevant trap is called.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


using Private name objects for declarative property definition.

2011-07-08 Thread Allen Wirfs-Brock
The current Harmony classes proposal 
http://wiki.ecmascript.org/doku.php?id=harmony:classes includes the concept of 
private instance members and syntax for defining them.  While it presents a 
syntax for accessing them (eg, private(foo).bar accesses the private 'bar' 
member of the object that is the value of foo) there does not yet appear to be 
consensus acceptance of this access syntax. There also appears to be a number 
of still unresolved semantic issues WRT such private instance members.  As an 
alternative, the classes proposal says that  a pattern composing private names 
with classes can satisfy the requirements for private instance members. 
However, so far, we have no concrete proposals on what these patterns might be. 
 This is a first cut at proposing such patterns.


The current versions of the private names proposal 
http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects  simply 
exposes a constructor for creating unique values can be be used as property 
keys:

const key = Name.create();

Those values can be used to define and access object properties:

let obj = {};
   print(obj.key); // undefined
   obj[key]=some private state;   //create a property with a private name key
   print(obj.key);// still undefined
   print(obj[key]); //undefined
   print(obj[key]);   // some private state

In the above example the property created by using the private name value is 
essentially an instance private member of  obj.  In general, various levels of 
visibility (instance private, class private, friends, module private, etc.) can 
be achieved simply by using lexical scoping to control access to the variable 
that contain private key values. 

For example:

   function ObjWithInstancePrivateMember(secret) {
const s = Name.create();
this[s]= secret;
this.method = function () {
return doSomething(this[s]);
}
   }

   const priv = Name.create();
   function ObjWithClassPrivateMember(secret) {
const s = Name.create();
this[priv]= secret;
this.method = function (another) {
return doSomethingTogether(this[priv], another[priv]);
}
   }

Note that  [ ] notation with an expression that evaluates to a private name 
value must be used to access such private members.  There have been various 
proposals such as http://wiki.ecmascript.org/doku.php?id=strawman:names and  
http://wiki.ecmascript.org/doku.php?id=strawman:private_names to allow dotted 
property access to be used with private name keys.  However, these either had 
technical problems or their semantics were rejected by community discussion on 
this list.  The issues raised in response to those proposals are likely to 
recur for any private member access syntax that uses dot notation.

A weakness with using private names object to define private members is that 
currently there is no way to declaratively define objects with such members. 
Consider the following definition of a Point abstraction using extended object 
literals and a simple naming convention to identify private members:

const Point = {
 //private members
 __x: 0,
 __y: 0, 
 __validate(x,y) { return typeof x == 'number'  typeof y = 'number'},
 //public members
 new(x,y) {
  if (!this.__validate(x,y)) throw invalid;
  return this | {
  __x: x,
  __y: y
 }
  };
 add(anotherPoint) {
   return this.new(this.__x+another.__x, this.__y+another.__y)
 }
}

using private name objects this would have to be written as:

const __x=Name.create();
const __y=Name.create();
const __validate=Name.create();
const Point = {
 //public members
 new(x,y) {
  if (!this[__validate](x,y)) throw invalid;
  let obj = this | { };
 obj[__x] = x;
 obj[__y] = y;
 return obj;
   };
 add(anotherPoint) {
   return this.new(this[__x]+another[__x], this[__y]+another[__y])
 }
}
 //private members for Point
Point[__x] = 0;
Point[__y] = 0,;
Point[ __validate] = function (x,y) { return typeof x == 'number'  tyupeof y 
= 'number'};

The biggest issue with this rewrite is it loose the declarative definition and 
replaces it with an hybrid that has some declarative parts and some imperative 
parts. This breaks the logical encapsulation of the definition of the Point 
abstraction making it harder to be understand and manipulated by both humans 
and mechanical tools.  The reason this is necessary is that object literal 
notation currently has no way to express that a definition of a property uses a 
name that needs be interpreted as a reference to a lexical variable whose value 
is the actual private name object.  Fixes these requires an additional 
extension to object literals.

One possibility, is to use a prefix keyword to each property definition that 
uses a private key value.  For example:

const __x=Name.create();
const 

Re: using Private name objects for declarative property definition.

2011-07-08 Thread Andreas Rossberg
On 8 July 2011 21:16, Allen Wirfs-Brock al...@wirfs-brock.com wrote:
 The current versions of the private names proposal
 http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects  simply
 exposes a constructor for creating unique values can be be used as property
 keys:

Of the several private names proposals around, I find this one
preferable. It is clean and simple, and provides the functionality
needed in an orthogonal manner. It seems worth exploring how well this
works in practice before we settle on something more complicated.

One minor suggestion I'd have is to treat names as a proper new
primitive type, i.e. typeof key == name, not object. That way, it
can be defined much more cleanly what a name is, where its use is
legal (as opposed to proper objects), and where it maybe enjoys
special treatment.

 Another alternative that avoids using the 'private' prefix is to allow the
 property name in a property definition to be enclosed with brackets:
 const __x=Name.create();
 const __y=Name.create();
 const __validate=Name.create();
  Point = {
      //private members
      [__x]: 0,
      [ __y]: 0,
      [__validate](x,y) { return typeof x == 'number'  typeof y =
 'number'},
      //public members
      new(x,y) {
           if (!this[__validate](x,y)) throw invalid;
           return this | {
                   [__x]: x,
                   [__y]: y
                  }
       };
      add(anotherPoint) {
            return this.new(this[__x]+another[__x], this[__y]+another[__y])
      }
 }

I like this notation most, because it can be generalised in a
consistent manner beyond the special case of private names: there is
no reason that the bit in brackets is just an identifier, we could
allow arbitrary expressions. So the notation would be the proper dual
to bracket access notation. From a symmetry and expressiveness
perspective, this is very appealing.

Notation-wise, I think people would get used to using brackets. I see
no good reason to introduce yet another projection syntax, like @.

Whether additional sugar is worthwhile -- e.g. private declarations --
remains to be explored. (To be honest, I haven't quite understood yet
in what sense such sugar would really be more declarative. Sure, it
is convenient and perhaps more readable. But being declarative is a
semantic property, and cannot be achieved by simple syntax tweaks.)

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: using Private name objects for declarative property definition.

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 12:16 PM, Allen Wirfs-Brock wrote:

 The current Harmony classes proposal 
 http://wiki.ecmascript.org/doku.php?id=harmony:classes includes the concept 
 of private instance members and syntax for defining them.  While it presents 
 a syntax for accessing them (eg, private(foo).bar accesses the private 'bar' 
 member of the object that is the value of foo) there does not yet appear to 
 be consensus acceptance of this access syntax.

Oh, quite the opposite -- everyone on TC39 with whom I've spoken agrees that 
private(this) syntax is straw that must be burned up. We need new syntax, or 
else we need to do at least what Dave proposed in minimal classes: defer 
private syntax, let programmers use private name objects and explicit [] 
indexing.

I do think we can say a few more things about private in class that may not be 
in the requirements on the wiki:

On the level of rationale for why class- and not instance-private, Juan Ignacio 
Dopazo in private correspondence made a good observation, shown by his example:

class MyClass {
  private foo() {}
  bar() {
var self = this;
setTimeout(function () {
  self.foo();
}, 0);
  }
} 

Because |this| is not lexical, instance- rather than class-private access that 
requires this. to the left of the private variable reference does not work 
unless you use the closure pattern explicitly and abjure |this|.

The straw private(foo) syntax doesn't help if the goal is instance privacy, 
since the inner function has no idea (runtime, never mind compile-time) how to 
enforce to which particular instance self must refer.

Requiring .bind(this) after the function expression passed to setTimeout can be 
used to work around such a hypothetical, mandatory this.-prefix 
instance-private restriction, but that's onerous and it can be too costly.

Another observation about any class-private scheme we might consider in the 
current context: private instance variables in many ways (notably not for 
Object.freeze) act like properties, and the syntax mooted so far casts them in 
that light. Even if the ES5 reflective APIs, such as 
Object.getOwnPropertyNames, rightly skip privates on a class instance, proxies 
may raise the question: how does a private variable name reflect as a property 
name?

  class Point {
constructor(x, y) { private x = x, y = y; }
equals(other) {
 return private(this).x is private(other).x 
private(this).y is private(other).y;
}
...
  }

We cannot know how to ask for private-x from other without special syntax of 
some kind, either at the access point or as a binding declaration affecting all 
.x (and x: in object literals). So here I use the proposal's straw private(foo) 
syntax.

Could other be a proxy that somehow has a private data record? Could other 
denote a class instance whose [[Prototype]] is a proxy? I claim we do not want 
private(foo) by itself, no .x after, to reify as an object, but if it did, then 
it seems to me it could be used with a proxy to reflect on private variable 
names.

There are certainly several choices here, but the one I currently favor as 
simplest, which creates no new, ad-hoc concepts in the language, is that 
class-private instance variables are properties named by private name objects.

Per the requirements for private in the classes proposal, this means 
Object.freeze does not freeze private-named properties, or at least does not 
make private-named data properties non-writable.

Perhaps Object.preventExtensions should not restrict private-named properties 
from being added to the object. This seems strange and wrong at first, but if 
freeze does not affect private-named properties, I'm not sure there is a 
defensive consistency threat from attackers decorating frozen objects with 
ad-hoc properties named by private name objects that only the attacker could 
create or access, which cannot collide with the class's private names.

Perhaps this is uncontroversial. I hope so, but I don't assume it is, and I 
suspect people who worked on the classes proposal may disagree. Cc'ing Mark in 
particular, since I'm just writing down some preliminary thoughts and 
intermediate conclusions here, and I could be way off base.

Ok, back to your good point about wanting private names to be usable in object 
initialisers:


 Each of these approaches seem plausible.  For a side-by-side comparison of 
 the above example using the alternatives see 
 http://wiki.ecmascript.org/lib/exe/fetch.php?id=harmony%3Aprivate_name_objectscache=cachemedia=harmony:private-name-alternatives.pdf
  .  I'm interested in feedback on the alternatives.

The first thing I'd say is that, whatever the syntax (private prefix, [] around 
property name, or @ prefix), it seems too verbose to require boilerplate of 
const __x = Name.create(), etc. before the object literal.

Wouldn't it be better for the prefix, brackets or sigil to by itself define a 
private name and use it, also putting it in scope for the 

Re: using Private name objects for declarative property definition.

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 2:43 PM, Andreas Rossberg wrote:

 One minor suggestion I'd have is to treat names as a proper new
 primitive type, i.e. typeof key == name, not object. That way, it
 can be defined much more cleanly what a name is, where its use is
 legal (as opposed to proper objects), and where it maybe enjoys
 special treatment.

We went back and forth on this. I believe the rationale is in the wiki (but 
perhaps in one of the strawman:*name* pages). There are a couple of reasons:

1. We want private name objects to be usable as keys in WeakMaps. Clearly we 
could extend WeakMaps to have either object (but not null) or name 
typeof-type keys, but that complexity is not warranted yet.

2. Private name objects are deeply frozen and behave like value types (since 
they have no copy semantics and you can only generate fresh ones). Thus they 
are typeof-type object but clearly distinct from string-equated property 
names that JS has sported so far.

In other words, we don't gain any distinctiveness, or make any particular 
claims about private name objects that could not be made about other 
(deeply-frozen, generated-only, say by Object.create or Proxy.create in a 
distinguished factory function) kinds of objects, via a new typeof-type.

In light of these points, making private names be objects in both the 
as-proposed WeakMap sense, and the typeof-result sense, seems best.

So, while we have added null as a new typeof result string, and we have 
considered adding other novel typeof results, and we believe that we can add 
new typeof results with good enough reason (thanks to IE adding some 
non-standard ones long ago, and programmers tending to write non-exhaustive 
switch and if-else cond structures to handle only certain well-known typeof 
cases), in the case of private name objects, we don't think we have good enough 
reason to add a typeof name -- and then to complicate WeakMap.


  Point = {
  //private members
  [__x]: 0,
  [ __y]: 0,
  [__validate](x,y) { return typeof x == 'number'  typeof y =
 'number'},
  //public members
  new(x,y) {
   if (!this[__validate](x,y)) throw invalid;
   return this | {
   [__x]: x,
   [__y]: y
  }
   };
  add(anotherPoint) {
return this.new(this[__x]+another[__x], this[__y]+another[__y])
  }
 }
 
 I like this notation most, because it can be generalised in a
 consistent manner beyond the special case of private names: there is
 no reason that the bit in brackets is just an identifier, we could
 allow arbitrary expressions.

Then the shape of the object is not static. Perhaps this is worth the costs to 
implementations and other analyzers (static program analysis, human readers). 
We should discuss a bit more first, as I just wrote in reply to Allen.


 So the notation would be the proper dual
 to bracket access notation. From a symmetry and expressiveness
 perspective, this is very appealing.

It does help avoid eval abusage, on the upside.

Proceeding bottom-up, with orthogonal gap-filling primitives that compose well, 
is our preferred way for Harmony. Private name objects without new syntax, 
requiring bracket-indexing, won in part by filling a gap without jumping to 
premature syntax with novel binding semantics (see below).

Here, with obj = { [expr]: value } as the way to compute a property name in an 
object initialiser (I must not write object literal any longer), we are 
proceeding up another small and separate hill. But, is this the right design 
for object initialisers (which the normative grammar does call 
ObjectLiterals)?


 Notation-wise, I think people would get used to using brackets. I see
 no good reason to introduce yet another projection syntax, like @.

Agreed that unless we use @ well for both property names in initialisers and 
private property access, and in particular if we stick with bracketing for 
access, then square brackets win for property naming too -- but there's still 
the loss-of-static-shape issue.


 Whether additional sugar is worthwhile -- e.g. private declarations --
 remains to be explored. (To be honest, I haven't quite understood yet
 in what sense such sugar would really be more declarative. Sure, it
 is convenient and perhaps more readable. But being declarative is a
 semantic property, and cannot be achieved by simple syntax tweaks.)

Good point!

The original name declaration via private x that Dave championed was 
definitely semantic: it created a new static lookup hierarchy, lexical but for 
names after . in expressions and before : in property assignments in object 
literals. This was, as Allen noted, controversial and enough respected folks on 
es-discuss (I recall Andrew Dupont in particular) and in TC39 reacted 
negatively that we separated and deferred it. I do not know how to revive it 
productively.

/be___
es-discuss mailing list
es-discuss@mozilla.org

Design principles for extending ES object abstractions

2011-07-08 Thread Allen Wirfs-Brock

On Jul 8, 2011, at 2:58 PM, Brendan Eich wrote on the thread using Private name 
objects for declarative property definition. :

 But whatever the class syntax, and the disposition of private in class and 
 even classes in ES.next, I agree we should expect private declarative and 
 expression forms to work the same in object initialisers and in classes.
 
 It would be good to get everyone buying into this 
 private-means-property-with-private-name-key-everywhere agreement.
 

I wanted to generalize this a bit.  In designing classes and other new ES 
abstractions there are a couple design principles that I think it is important 
that we follow:

1) Everything works with plain objects.

Objects (and functions) are the primitive abstraction mechanisms of ES.
Any new functionality we add must be applicable and available to plain vanilla 
singleton objects.
Anti-example:  super keyword that is only available in a class declaration
Acceptable solution: super keyword is available for both class declaration and 
object literals.

2) Anything that can be done declaratively can also be done imperatively.

Imperative/reflective object construction is a power feature of ES that has 
been widely exploited by everyday developers as well as  metaprogrammers.
Any new object capabilities that we make available via declarative  constructs 
must also be available via an imperative API.
Anti-example: functions definitions using super keyword may only occur within 
an object literal or class declaration.
Acceptable solution: Object.defineMethod can be used to bind an externally 
defined function that uses the super keyword to a specific object.

I don't expect that anybody will significantly disagree with either of these 
principles.  But I think it is good to explicitly articulate them and make sure 
we have agreement one them. Sometimes we spend a lot of time discussing an idea 
that doesn't or can't conform to these principles.

Allen ___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 3:49 PM, Allen Wirfs-Brock wrote:

 On Jul 8, 2011, at 2:58 PM, Brendan Eich wrote on the thread using Private 
 name objects for declarative property definition. :
 
 But whatever the class syntax, and the disposition of private in class and 
 even classes in ES.next, I agree we should expect private declarative and 
 expression forms to work the same in object initialisers and in classes.
 
 It would be good to get everyone buying into this 
 private-means-property-with-private-name-key-everywhere agreement.
 
 
 I wanted to generalize this a bit.  In designing classes and other new ES 
 abstractions there are a couple design principles that I think it is 
 important that we follow:
 
 1) Everything works with plain objects.
 
 Objects (and functions) are the primitive abstraction mechanisms of ES.
 Any new functionality we add must be applicable and available to plain 
 vanilla singleton objects.
 Anti-example:  super keyword that is only available in a class declaration
 Acceptable solution: super keyword is available for both class declaration 
 and object literals.
 
 2) Anything that can be done declaratively can also be done imperatively.
 
 Imperative/reflective object construction is a power feature of ES that has 
 been widely exploited by everyday developers as well as  metaprogrammers.
 Any new object capabilities that we make available via declarative  
 constructs must also be available via an imperative API.
 Anti-example: functions definitions using super keyword may only occur within 
 an object literal or class declaration.
 Acceptable solution: Object.defineMethod can be used to bind an externally 
 defined function that uses the super keyword to a specific object.
 
 I don't expect that anybody will significantly disagree with either of these 
 principles.  But I think it is good to explicitly articulate them and make 
 sure we have agreement one them. Sometimes we spend a lot of time discussing 
 an idea that doesn't or can't conform to these principles.

+1.

Note that generators as we've prototyped them have the same 
imperative/reflective constructor as functions: Function. You just use yield 
in the body string. In working on generators for standardization, we proposed 
requiring * after function at the head to distinguish (for readers) 
generator functions from non-generator functions, since yield in the body is 
sometimes far removed from the start of the function.

But the stronger reason for function* as mandator generator syntax introducer 
came when we considered yield* (yield from in Python's PEP380): the utility 
of a zero-iterations basis case for a sub-generator. As Dave noted, otherwise 
you'd have to write function* () {if (false) yield;} or some such.

Does this mean we need a distinguished generator function constructor, e.g. 
Function.createGenerator? Probably so, for the stronger (zero-iterations, empty 
generator basis case) and for symmetry. Not a big deal but something to 
consider.

In any case, I like the generalizations you make here.

/be___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 3:59 PM, Brendan Eich wrote:

 But the stronger reason for function* as mandator

mandatory of course (need new keyboard).


 generator syntax introducer came when we considered yield* (yield from in 
 Python's PEP380): the utility of a zero-iterations basis case for a 
 sub-generator. As Dave noted, otherwise you'd have to write function* () {if 
 (false) yield;} or some such.

function () {if (false) yield;} of course -- the hypothesis there assumes no 
* after function, in which case you must write a dead yield to make the 
function be a generator in the first place.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Design principles for extending ES object abstractions

2011-07-08 Thread Luke Hoban
I agree wholeheartedly with these.  In fact, I'd go further on (2), and say 
Anything that can be done declaratively can also be done imperatively, using 
ES5 syntax.  ES.next will have two syntaxes running on a single runtime, 
sharing objects across a shared heap.  I think we should ensure that all 
relevant semantics of ES.next are pushed down into the shared runtime, and 
exposed through libraries available to both syntaxes, to ensure full 
interoperability between the two.

The one additional place I know of in existing ES.next proposals where I 
believe this principle is not yet met is the ability to define a module from 
ES5 syntax, and consume it from ES.next syntax.  Inline with these principles, 
I expect the module loader API should offer a way to imperatively define a 
module that can be later loaded using module loader APIs.

Luke

From: es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] On 
Behalf Of Allen Wirfs-Brock
Sent: Friday, July 08, 2011 3:49 PM
To: es-discuss@mozilla.org
Subject: Design principles for extending ES object abstractions

[snip...]

I wanted to generalize this a bit.  In designing classes and other new ES 
abstractions there are a couple design principles that I think it is important 
that we follow:

1) Everything works with plain objects.

Objects (and functions) are the primitive abstraction mechanisms of ES.
Any new functionality we add must be applicable and available to plain vanilla 
singleton objects.
Anti-example:  super keyword that is only available in a class declaration
Acceptable solution: super keyword is available for both class declaration and 
object literals.

2) Anything that can be done declaratively can also be done imperatively.

Imperative/reflective object construction is a power feature of ES that has 
been widely exploited by everyday developers as well as  metaprogrammers.
Any new object capabilities that we make available via declarative  constructs 
must also be available via an imperative API.
Anti-example: functions definitions using super keyword may only occur within 
an object literal or class declaration.
Acceptable solution: Object.defineMethod can be used to bind an externally 
defined function that uses the super keyword to a specific object.

I don't expect that anybody will significantly disagree with either of these 
principles.  But I think it is good to explicitly articulate them and make sure 
we have agreement one them. Sometimes we spend a lot of time discussing an idea 
that doesn't or can't conform to these principles.

Allen

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 4:05 PM, Luke Hoban wrote:

 I agree wholeheartedly with these.  In fact, I’d go further on (2), and say 
 “Anything that can be done declaratively can also be done imperatively, using 
 ES5 syntax”.

The problem here is that some new syntax cannot be faked with old syntax, 
namely function calls, without quoting code in strings. This is not usable.

A second problem is that adding API functions means injecting more names into 
some extant object, probably not the global object. Must all new APIs be 
Object.createPrivateName and only that? We have already accepted proposals that 
use built-in modules instead, so that there is no name pollution.


   ES.next will have two syntaxes running on a single runtime, sharing objects 
 across a shared heap.

The shared heap imposes some requirements on us, including that old code 
operating using old syntax with known semantics on a new object must not behave 
badly (details vary).

But this does *not* require that all new features, especially those requiring 
new syntax to be *usable*, must have old, string-based, name-pollusting API 
functions.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: using Private name objects for declarative property definition.

2011-07-08 Thread Allen Wirfs-Brock

On Jul 8, 2011, at 3:24 PM, Brendan Eich wrote:

 On Jul 8, 2011, at 2:43 PM, Andreas Rossberg wrote:
 
  Point = {
  //private members
  [__x]: 0,
  [ __y]: 0,
  [__validate](x,y) { return typeof x == 'number'  typeof y =
 'number'},
  //public members
  new(x,y) {
   if (!this[__validate](x,y)) throw invalid;
   return this | {
   [__x]: x,
   [__y]: y
  }
   };
  add(anotherPoint) {
return this.new(this[__x]+another[__x], this[__y]+another[__y])
  }
 }
 
 I like this notation most, because it can be generalised in a
 consistent manner beyond the special case of private names: there is
 no reason that the bit in brackets is just an identifier, we could
 allow arbitrary expressions.
 
 Then the shape of the object is not static. Perhaps this is worth the costs 
 to implementations and other analyzers (static program analysis, human 
 readers). We should discuss a bit more first, as I just wrote in reply to 
 Allen.

This is one of the reason I think I slightly prefer the @ approach.  @ can be 
defined similarly to . in that it must be followed by an identifier and that 
the identifier must evaluate to a private name object.  The latter in the 
general case would have to be a runtime check but in many common cases could be 
statically verified.  Even this doesn't guarantee that we statically know the 
shape.  Consider:

function f(a,b)  {
return {
   @a: 1,
   @b: 2
}
};

const x=Name.create();
const y=Name.create();
let obj1 = f(x,y);
let obj2 = f(y,x);
let obj3 = f(x,x);
let obj4 = f(y,y);

 
 
 So the notation would be the proper dual
 to bracket access notation. From a symmetry and expressiveness
 perspective, this is very appealing.
 
 It does help avoid eval abusage, on the upside.

If you mean something like:
 let propName  = computeSomePropertyName();
 let  obj = eval(({+propName+:  null}));

I'd say whoever does that doesn't know the language well enough as their are 
already good alternatives such as:
  let obj = {};
  obj[propName] = null;

or 
  let obj = new Object;
  Object.defineProperty(obj, propName,{value:null, writable: true, enumerable: 
true, configurable: true});

I know that people do stupid and unnecessary eval tricks today but I doubt that 
adding yet another non-eval way to accomplish the same thing is going to stop 
that.  The basic problem they have is not knowing the language and make the 
language bigger isn't likely to make things any better for them.

 
 Proceeding bottom-up, with orthogonal gap-filling primitives that compose 
 well, is our preferred way for Harmony. Private name objects without new 
 syntax, requiring bracket-indexing, won in part by filling a gap without 
 jumping to premature syntax with novel binding semantics (see below).
 
 Here, with obj = { [expr]: value } as the way to compute a property name in 
 an object initialiser (I must not write object literal any longer), we are 
 proceeding up another small and separate hill. But, is this the right design 
 for object initialisers (which the normative grammar does call 
 ObjectLiterals)?
 

Another concern is that it creates another look-ahead issue for the unify 
blocks and object initializers proposal.


 
 Notation-wise, I think people would get used to using brackets. I see
 no good reason to introduce yet another projection syntax, like @.
 
 Agreed that unless we use @ well for both property names in initialisers and 
 private property access, and in particular if we stick with bracketing for 
 access, then square brackets win for property naming too -- but there's still 
 the loss-of-static-shape issue.

There is also an argument to me made that [ ] and @ represent two different use 
cases: computed property access and private property access and for that reason 
there should be a syntactic distinction between them.

 
 
 Whether additional sugar is worthwhile -- e.g. private declarations --
 remains to be explored. (To be honest, I haven't quite understood yet
 in what sense such sugar would really be more declarative. Sure, it
 is convenient and perhaps more readable. But being declarative is a
 semantic property, and cannot be achieved by simple syntax tweaks.)
 
 Good point!
 
 The original name declaration via private x that Dave championed was 
 definitely semantic: it created a new static lookup hierarchy, lexical but 
 for names after . in expressions and before : in property assignments in 
 object literals. This was, as Allen noted, controversial and enough respected 
 folks on es-discuss (I recall Andrew Dupont in particular) and in TC39 
 reacted negatively that we separated and deferred it. I do not know how to 
 revive it productively.

Actually, I think you can blame be rather than Dave for the dual lookup 
hierarchy.  Dave (and Sam's) original proposal did have special semantics for 
private name declarations bug only had a single lookup 

RE: Design principles for extending ES object abstractions

2011-07-08 Thread Luke Hoban
 I agree wholeheartedly with these.  In fact, I'd go further on (2), and 
 say Anything that can be done declaratively can also be done 
 imperatively, using ES5 syntax.

The problem here is that some new syntax cannot be faked with old syntax, 
namely function calls, without quoting code in strings. This is not usable.

I think it's fine for the imperative solution to be less usable.  That's the 
value-add of opting-in to the ES.next syntax.  And of course some (most) new 
syntax is just syntax, and the ultimate objects it creates are ones that could 
have been created using some more complex path.  Those don't need any library 
support.

When Allen mentioned imperatively, I assumed he meant with a library.  I'm 
not actually sure what other interpretation there would be.   So I sort of 
expected that clarification to using ES5 syntax to be a no-op, though I 
expect it is practically quite important.

A second problem is that adding API functions means injecting more names into 
some extant object, probably not the global object. Must all new APIs be 
Object.createPrivateName and only that? We have already accepted proposals 
that use built-in modules instead, so that there is no name pollution.

I hope, and believe, there are actually not very many new runtime capabilities 
being added in ES.next that don't already have proposed libraries.  I do think 
there will need to be some rationalization of the goal to use built-in modules 
with the reality of ES5-syntax consumers of these libraries.  I'm not sure 
whether module loaders currently provide a way to do this that would feel 
accessible.

  ES.next will have two syntaxes running on a single runtime, sharing 
 objects across a shared heap.

The shared heap imposes some requirements on us, including that old code 
operating using old syntax with known semantics on a new object must not 
behave badly (details vary). But this does *not* require that all new 
features, especially those requiring new syntax to be *usable*, must have 
old, string-based, name-pollusting API functions.

I agree, the shared heap requirement by itself does not impose this.  But I 
believe the design principle Allen outlined should lead us to this anyway, and 
the value we'll offer to the many millions of existing 'text/javascript' 
developers through object-detectable runtime capability additions is a nice 
bonus :).




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Allen Wirfs-Brock

On Jul 8, 2011, at 4:27 PM, Luke Hoban wrote:

  I agree wholeheartedly with these.  In fact, I’d go further on (2), and 
  say “Anything that can be done declaratively can also be done 
  imperatively, using ES5 syntax”.
  
 The problem here is that some new syntax cannot be faked with old syntax, 
 namely function calls, without quoting code in strings. This is not usable.
  
 I think it’s fine for the imperative solution to be less usable.  That’s the 
 value-add of opting-in to the ES.next syntax.  And of course some (most) new 
 syntax is just syntax, and the ultimate objects it creates are ones that 
 could have been created using some more complex path.  Those don’t need any 
 library support.  
  
 When Allen mentioned “imperatively”, I assumed he meant “with a library”.  
 I’m not actually sure what other interpretation there would be.   So I sort 
 of expected that clarification to “using ES5 syntax” to be a no-op, though I 
 expect it is practically quite important.

Mostly, although
 obj[foo] = blah;
is also an imperative way to define a property. 

Also note that my intent was to restricted both principles to matters directly 
relating to objects even though I didn't explicitly mention objects in naming 
the 2nd principle.  There are many things  in Es.next (and ES5, for that 
matter) that can be done declaratively WRT constructing closures that has no 
API based alternative (other than eval, which I choose not to count).  There is 
probably an argument to be made for accomplishing the somethings via reflective 
APIs.  However, given that there is no history of that in ES I don't think we 
need to make it a Es.next requirement.


Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: using Private name objects for declarative property definition.

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 4:21 PM, Allen Wirfs-Brock wrote:

 On Jul 8, 2011, at 3:24 PM, Brendan Eich wrote:
 
 Then the shape of the object is not static. Perhaps this is worth the costs 
 to implementations and other analyzers (static program analysis, human 
 readers). We should discuss a bit more first, as I just wrote in reply to 
 Allen.
 
 This is one of the reason I think I slightly prefer the @ approach.  @ can be 
 defined similarly to . in that it must be followed by an identifier and that 
 the identifier must evaluate to a private name object.  The latter in the 
 general case would have to be a runtime check but in many common cases could 
 be statically verified.

This does give a probabilistic edge to implementations optimizing @ for private 
names only (but with guards that throw on non-private-name result of evaluating 
what's on the right of @), and predicting or static-analyzing shape.


 Even this doesn't guarantee that we statically know the shape. 

Certainly not. And that is a change from today, which I think we ought to 
discuss. Because as you note below, private names could be added to objects 
declared by initialisers that lack any private name syntax, after the 
initialiser; or after a new Object or Object.create.


 It does help avoid eval abusage, on the upside.
 
 If you mean something like:
 let propName  = computeSomePropertyName();
 let  obj = eval(({+propName+:  null}));
 
 I'd say whoever does that doesn't know the language well enough as their are 
 already good alternatives such as:
  let obj = {};
  obj[propName] = null;
 
 or 
  let obj = new Object;
  Object.defineProperty(obj, propName,{value:null, writable: true, enumerable: 
 true, configurable: true});

No, the problem is not that there aren't other ways to do this. Or that people 
are too dumb. I've had real JS users, often with some Python knowledge but 
sometimes just proceeding from a misunderstanding of how object literals are 
evaluated, ask for the ability to compute property names selectively in object 
literals.

Sure, they can add them after. That sauce for the goose is good for the 
private-name gander too, no?


 Here, with obj = { [expr]: value } as the way to compute a property name in 
 an object initialiser (I must not write object literal any longer), we are 
 proceeding up another small and separate hill. But, is this the right design 
 for object initialisers (which the normative grammar does call 
 ObjectLiterals)?
 
 Another concern is that it creates another look-ahead issue for the unify 
 blocks and object initializers proposal.

Yes, indeed. I've been thinking about that one since yesterday, without much 
more to show for it except this: I think we should be careful not to extend 
object literals in ways that create more ambiguity with blocks.

I grant that the new method syntax is too sweet to give up. But I don't think 
{[..., {!..., etc. for # and ~ after {, are yet worth the ambiguity that is 
future-hostile to block vs. object literal unity.


 Agreed that unless we use @ well for both property names in initialisers and 
 private property access, and in particular if we stick with bracketing for 
 access, then square brackets win for property naming too -- but there's 
 still the loss-of-static-shape issue.
 
 There is also an argument to me made that [ ] and @ represent two different 
 use cases: computed property access and private property access and for that 
 reason there should be a syntactic distinction between them.

Is this different from your first point above, about implementation 
optimization edge?


 The original name declaration via private x that Dave championed was 
 definitely semantic: it created a new static lookup hierarchy, lexical but 
 for names after . in expressions and before : in property assignments in 
 object literals. This was, as Allen noted, controversial and enough 
 respected folks on es-discuss (I recall Andrew Dupont in particular) and in 
 TC39 reacted negatively that we separated and deferred it. I do not know how 
 to revive it productively.
 
 Actually, I think you can blame be rather than Dave for the dual lookup 
 hierarchy.  Dave (and Sam's) original proposal did have special semantics for 
 private name declarations bug only had a single lookup hierarchy.

Of course -- sorry about that, credit and blame where due ;-).

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 4:27 PM, Luke Hoban wrote:

  I agree wholeheartedly with these.  In fact, I’d go further on (2), and 
  say “Anything that can be done declaratively can also be done 
  imperatively, using ES5 syntax”.
  
 The problem here is that some new syntax cannot be faked with old syntax, 
 namely function calls, without quoting code in strings. This is not usable.
  
 I think it’s fine for the imperative solution to be less usable.

I think we need to agree that eval does not count, as Allen just wrote.

That is, if you'd be happy if old script could call, e..g

  Object.evalInHarmony(...)

then we're done.


   That’s the value-add of opting-in to the ES.next syntax.  And of course 
 some (most) new syntax is just syntax, and the ultimate objects it creates 
 are ones that could have been created using some more complex path.  Those 
 don’t need any library support.  

If eval does count, we're done.

If eval doesn't count, then how pray tell does old code create a generator? Not 
by building an interpreter in JS.


 When Allen mentioned “imperatively”, I assumed he meant “with a library”.  
 I’m not actually sure what other interpretation there would be.   So I sort 
 of expected that clarification to “using ES5 syntax” to be a no-op, though I 
 expect it is practically quite important.

The issue is not with a library, it is whether the only new APIs in ES.next 
must be Object.uglyNameGoesHere, with string arguments for anything that can't 
be expressed in the old syntax (like yield in a generator).

If we have built-in modules in ES.next, we shouldn't have duplicate 
Object.mumble APIs for them as well (Object is one of those shared-heap objects 
common to old and new scripts loaded against the same global with the default 
module loader).


 A second problem is that adding API functions means injecting more names 
 into some extant object, probably not the global object. Must all new APIs 
 be Object.createPrivateName and only that? We have already 
 acceptedproposals that use built-in modules instead, so that there is no 
 name pollution.
  
 I hope, and believe, there are actually not very many new runtime 
 capabilities being added in ES.next that don’t already have proposed 
 libraries.  I do think there will need to be some rationalization of the goal 
 to use built-in modules with the reality of ES5-syntax consumers of these 
 libraries.  I’m not sure whether module loaders currently provide a way to do 
 this that would feel accessible.

That's a good point. If we expose just one property, say

  Object.ModuleLoader

then by my reading of the module loaders proposal, ES5 code can do whatever it 
wants with built-in and other new modules.

Would this be enough for what you're after?


 The shared heap imposes some requirements on us, including that old code 
 operating using old syntax with known semantics on a new object must not 
 behave badly (details vary). But this does *not* require that all new 
 features, especially those requiring new syntax to be *usable*, must have 
 old, string-based, name-pollusting API functions.
  
 I agree, the shared heap requirement by itself does not impose this.  But I 
 believe the design principle Allen outlined should lead us to this anyway, 
 and the value we’ll offer to the many millions of existing ‘text/javascript’ 
 developers through object-detectable runtime capability additions is a nice 
 bonus J.

Arguing about Principles as if they were ironclad law is a good timekiller, 
over which TC39 will fall out of Harmony quickly if we do make the mistake of 
killing too much time.

We need use-cases as well as abstractions like capital-P Principles. We need 
Aristotle as well as Plato 
(http://answers.yahoo.com/question/index?qid=20090513192850AAGmPAH). And we 
need some good taste and judgment in knowing when to ease off on the 
Principle-mongering.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 3:49 PM, Allen Wirfs-Brock wrote:

 2) Anything that can be done declaratively can also be done imperatively.

What's the imperative API for | (which has the syntactic property that it 
operators on newborns on the right, and cannot mutate the [[Prototype]] of an 
object that was already created and perhaps used with its original 
[[Prototype]] chain)?

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread David Herman
I think I still haven't fully grokked what | means on array literals, but 
could it also be used to subclass Array? For example:

function SubArray() {
return SubArray.prototype | [];
}

SubArray.prototype = new Array;

I'm not sure what Array.prototype methods would or wouldn't work on instances 
of SubArray.

Dave

On Jul 8, 2011, at 5:48 PM, Allen Wirfs-Brock wrote:

 
 On Jul 8, 2011, at 5:16 PM, Brendan Eich wrote:
 
 On Jul 8, 2011, at 3:49 PM, Allen Wirfs-Brock wrote:
 
 2) Anything that can be done declaratively can also be done imperatively.
 
 What's the imperative API for | (which has the syntactic property that it 
 operators on newborns on the right, and cannot mutate the [[Prototype]] of 
 an object that was already created and perhaps used with its original 
 [[Prototype]] chain)?
 
 Fair point and one I was already thinking about :-)
 
 For regular objects, it is Object.create.
 
 For special built-in object with literal forms, I've previously argument that 
  | can be used to implement an imperative API:
 
 Array.create = function (proto,members) {
 let obj = proto | {};
 Object.defineProperties(obj,members);
  return obj;
 }
 
 Basically, | is sorta half imperative operator, half declaration component.
 
 This may be good enough.  It would be nice it it was and we didn't have to 
 have additional procedural APIs for constructing instances of the built-ins.  
 Somebody has already pointed out | won't work for built-in Date objects 
 because they lack a literal form. I think the best solution for that is to 
 actually reify access to a Date object's timevalue by making it a private 
 named property.   BTW, way did ES1(?) worry about allowing for alternative 
 internal timevalue representations?  If in really there really any perf 
 issues that involve whether or not the timevalue is represented as a double 
 or something else?
 
 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: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 5:48 PM, Allen Wirfs-Brock wrote:

 On Jul 8, 2011, at 5:16 PM, Brendan Eich wrote:
 
 What's the imperative API for | (which has the syntactic property that it 
 operators on newborns on the right, and cannot mutate the [[Prototype]] of 
 an object that was already created and perhaps used with its original 
 [[Prototype]] chain)?
 
 Fair point and one I was already thinking about :-)
 
 For regular objects, it is Object.create.
 
 For special built-in object with literal forms, I've previously argument that 
  | can be used to implement an imperative API:
 
 Array.create = function (proto,members) {
 let obj = proto | {};
 Object.defineProperties(obj,members);
  return obj;
 }

And likewise for Function.create and RegExp.create. Boolean, Number, String, 
and Date get nothing :-P.

We have a somewhat-troubled proposal in Harmony to make Function.create an 
alternative Function constructor that takes a leading name parameter, and then 
parameters and body string parameters. But perhaps that could be renamed 
Function.createNamed.


 Basically, | is sorta half imperative operator, half declaration component.
 
 This may be good enough.  It would be nice it it was and we didn't have to 
 have additional procedural APIs for constructing instances of the built-ins.  
 Somebody has already pointed out | won't work for built-in Date objects 
 because they lack a literal form. I think the best solution for that is to 
 actually reify access to a Date object's timevalue by making it a private 
 named property.

That is an old idea I've brought up from time to time. If that private name 
were exported, you could even make useful Date subclasses (rather than Date 
instances that have extended proto chains).


   BTW, way did ES1(?) worry about allowing for alternative internal timevalue 
 representations?  If in really there really any perf issues that involve 
 whether or not the timevalue is represented as a double or something else?

The extrapolated Gregorian calendar's range in milliseconds was chosen 
carefully to fit in an IEEE 754 double without loss of precision.

Real implementations decode the double into commonly-accessed fields that would 
have to track any updates to the milliseconds since (negative for before) the 
epoch.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: using Private name objects for declarative property definition.

2011-07-08 Thread Allen Wirfs-Brock

On Jul 8, 2011, at 2:58 PM, Brendan Eich wrote:

 On Jul 8, 2011, at 12:16 PM, Allen Wirfs-Brock wrote:
 
 The current Harmony classes proposal 
 http://wiki.ecmascript.org/doku.php?id=harmony:classes includes the concept 
 of private instance members and syntax for defining them.  While it presents 
 a syntax for accessing them (eg, private(foo).bar accesses the private 'bar' 
 member of the object that is the value of foo) there does not yet appear to 
 be consensus acceptance of this access syntax.
 
 Oh, quite the opposite -- everyone on TC39 with whom I've spoken agrees that 
 private(this) syntax is straw that must be burned up. We need new syntax, or 
 else we need to do at least what Dave proposed in minimal classes: defer 
 private syntax, let programmers use private name objects and explicit [] 
 indexing.
 
 I do think we can say a few more things about private in class that may not 
 be in the requirements on the wiki:
 
 On the level of rationale for why class- and not instance-private, Juan 
 Ignacio Dopazo in private correspondence made a good observation, shown by 
 his example:
 
 class MyClass {
   private foo() {}
   bar() {
 var self = this;
 setTimeout(function () {
   self.foo();
 }, 0);
   }
 } 
 
 Because |this| is not lexical, instance- rather than class-private access 
 that requires this. to the left of the private variable reference does not 
 work unless you use the closure pattern explicitly and abjure |this|.
 
 The straw private(foo) syntax doesn't help if the goal is instance privacy, 
 since the inner function has no idea (runtime, never mind compile-time) how 
 to enforce to which particular instance self must refer.
 
 Requiring .bind(this) after the function expression passed to setTimeout can 
 be used to work around such a hypothetical, mandatory this.-prefix 
 instance-private restriction, but that's onerous and it can be too costly.

An block lambdas would presumably also provide a solution if they were added to 
the language.
 
 Another observation about any class-private scheme we might consider in the 
 current context: private instance variables in many ways (notably not for 
 Object.freeze) act like properties, and the syntax mooted so far casts them 
 in that light. Even if the ES5 reflective APIs, such as 
 Object.getOwnPropertyNames, rightly skip privates on a class instance, 
 proxies may raise the question: how does a private variable name reflect as a 
 property name?
 
   class Point {
 constructor(x, y) { private x = x, y = y; }
 equals(other) {
  return private(this).x is private(other).x 
 private(this).y is private(other).y;
 }
 ...
   }
 
 We cannot know how to ask for private-x from other without special syntax of 
 some kind, either at the access point or as a binding declaration affecting 
 all .x (and x: in object literals). So here I use the proposal's straw 
 private(foo) syntax.
 
 Could other be a proxy that somehow has a private data record? Could other 
 denote a class instance whose [[Prototype]] is a proxy? I claim we do not 
 want private(foo) by itself, no .x after, to reify as an object, but if it 
 did, then it seems to me it could be used with a proxy to reflect on private 
 variable names.
 
 There are certainly several choices here, but the one I currently favor as 
 simplest, which creates no new, ad-hoc concepts in the language, is that 
 class-private instance variables are properties named by private name objects.

There is more general issue about reflection on private members (and I 
intentionally said members here rather than names).  Some of us believe 
that private members should never be exposed via reflection.  Others of us 
think there are plenty of reflection use cases where it is either useful or 
necessary to reflect using private names.  The current private name objects 
allows whether or not reflection is permitted using that name  to be set when 
the private name is created.  The pure declarative form in the proposed class 
declarations don't have any way to specify that regardless of whether or not 
private names are used as the underlyng implementation for private members).  
If it did allow such control (and private names were used in the 
implementation), there would still need to be a way to access the private name 
associated by the class declaration with a specific private member in order to 
reflect upon it.  Sure you could use getOwnPropertyNames to access all of the 
property names but if that was all you had how could you be sure of the 
correspondence between private names and declared private members.

 

 
 Per the requirements for private in the classes proposal, this means 
 Object.freeze does not freeze private-named properties, or at least does not 
 make private-named data properties non-writable.
 
 Perhaps Object.preventExtensions should not restrict private-named properties 
 from being added to the object. This seems strange and wrong at 

Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 5:53 PM, David Herman wrote:

 I think I still haven't fully grokked what | means on array literals, but 
 could it also be used to subclass Array? For example:
 
 function SubArray() {
 return SubArray.prototype | [];
 }
 
 SubArray.prototype = new Array;
 
 I'm not sure what Array.prototype methods would or wouldn't work on instances 
 of SubArray.

Instances of SubArray must mean (new SubArray) results, but those are indeed 
true Array instances. They simply have a prototype chain that has been extended:

a = SubArray(); // or new SubArray

Object.getPrototypeOf(a) - SubArray.prototype (which is an Array)
Object.getPrototypeOf(SubArray.prototype) - Array.prototype
and Array.prototype of course delegates to Object.prototype

This allows new methods to be added to SubArray.prototype.

Sometimes people try to make a new Array instance be the prototype of some 
other object:

js var o = Object.create([])
js o[2] = 0
0
js o.length
0
js o[1] = 1
1
js o[0] = 2
2
js o.toString()

js o.slice(0,1)
[]
js o.length = 3
3
js o.slice(0,1) 
[2]
js o.sort(function(a,b){return a-b}).toString()
0,1,2
js o.reverse().toString()
2,1,0

Note the lack of automagic length maintenance in this case. I think this is all 
per ES5.

/be___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Allen Wirfs-Brock
On Jul 8, 2011, at 5:53 PM, David Herman wrote:

 I think I still haven't fully grokked what | means on array literals, but 
 could it also be used to subclass Array? For example:

yes, it creates a new object that is an array instance ([[Class]]=='Array', 
support the length constraints, etc.) that has LHS of | as its [[Prototype]] 
value.
(BTW, in my initial working draft for the ES6 spec. I have already purged 
[[Class]] from the specification)

 
 function SubArray() {
 return SubArray.prototype | [];
 }
 
 SubArray.prototype = new Array;
 
 I'm not sure what Array.prototype methods would or wouldn't work on instances 
 of SubArray.

All of them.  They are all generic.  However, subarray instances have all the 
internal state and methods that make them true arrays so even if some of the 
inherited Array methods weren't generic they would still work.

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Allen Wirfs-Brock

On Jul 8, 2011, at 6:03 PM, Brendan Eich wrote:

 On Jul 8, 2011, at 5:48 PM, Allen Wirfs-Brock wrote:
 
 On Jul 8, 2011, at 5:16 PM, Brendan Eich wrote:
 
 What's the imperative API for | (which has the syntactic property that it 
 operators on newborns on the right, and cannot mutate the [[Prototype]] of 
 an object that was already created and perhaps used with its original 
 [[Prototype]] chain)?
 
 Fair point and one I was already thinking about :-)
 
 For regular objects, it is Object.create.
 
 For special built-in object with literal forms, I've previously argument 
 that  | can be used to implement an imperative API:
 
 Array.create = function (proto,members) {
let obj = proto | {};
Object.defineProperties(obj,members);
 return obj;
 }
 
 And likewise for Function.create and RegExp.create. Boolean, Number, String, 
 and Date get nothing :-P.

Actually in the | proposal I define it to work with boolean, number, and 
string literals on the LHS.  Sorta useless but I included them so the complete 
set of literals was covered.  So it really is only Date that didn't get invited 
to the party.
 
 We have a somewhat-troubled proposal in Harmony to make Function.create an 
 alternative Function constructor that takes a leading name parameter, and 
 then parameters and body string parameters. But perhaps that could be renamed 
 Function.createNamed.

I think that create methods on Constructors should generally follow the 
argument pattern of Object.create.  Things that don't should get a different 
name. 

 
 
 Basically, | is sorta half imperative operator, half declaration component.
 
 This may be good enough.  It would be nice it it was and we didn't have to 
 have additional procedural APIs for constructing instances of the built-ins. 
  Somebody has already pointed out | won't work for built-in Date objects 
 because they lack a literal form. I think the best solution for that is to 
 actually reify access to a Date object's timevalue by making it a private 
 named property.
 
 That is an old idea I've brought up from time to time. If that private name 
 were exported, you could even make useful Date subclasses (rather than Date 
 instances that have extended proto chains).
 
 
  BTW, way did ES1(?) worry about allowing for alternative internal timevalue 
 representations?  If in really there really any perf issues that involve 
 whether or not the timevalue is represented as a double or something else?
 
 The extrapolated Gregorian calendar's range in milliseconds was chosen 
 carefully to fit in an IEEE 754 double without loss of precision.
 
 Real implementations decode the double into commonly-accessed fields that 
 would have to track any updates to the milliseconds since (negative for 
 before) the epoch.

Seems like this could be an invisible implementation detail.  An it is really 
worth the effort. How often does anybody set Date components in a situation 
that is so time critical that this would matter.  (any shouldn't dates be 
immutable...oh well)

Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Design principles for extending ES object abstractions

2011-07-08 Thread Brendan Eich
On Jul 8, 2011, at 6:38 PM, Allen Wirfs-Brock wrote:

 And likewise for Function.create and RegExp.create. Boolean, Number, String, 
 and Date get nothing :-P.
 
 Actually in the | proposal I define it to work with boolean, number, and 
 string literals on the LHS.  Sorta useless but I included them so the 
 complete set of literals was covered.  So it really is only Date that didn't 
 get invited to the party.

For ES4 we entertained date literals based ISO 8601 T literals. Couldn't 
justify 'em, the use-cases were all unlikely hardcodings.


 We have a somewhat-troubled proposal in Harmony to make Function.create an 
 alternative Function constructor that takes a leading name parameter, and 
 then parameters and body string parameters. But perhaps that could be 
 renamed Function.createNamed.
 
 I think that create methods on Constructors should generally follow the 
 argument pattern of Object.create.  Things that don't should get a different 
 name. 

Agreed.


 The extrapolated Gregorian calendar's range in milliseconds was chosen 
 carefully to fit in an IEEE 754 double without loss of precision.
 
 Real implementations decode the double into commonly-accessed fields that 
 would have to track any updates to the milliseconds since (negative for 
 before) the epoch.
 
 Seems like this could be an invisible implementation detail.

Certainly, it is invisible.


  An it is really worth the effort. How often does anybody set Date components 
 in a situation that is so time critical that this would matter.  (any 
 shouldn't dates be immutable...oh well)

SunSpider, cough.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss