Re: Number.isNaN

2012-12-18 Thread Olov Lassus
2012/12/14 Allen Wirfs-Brock al...@wirfs-brock.com

 BTW, I think there are probably other related issues that need to be
 discussed/resolved at that level.  For example, is SameValue really want we
 want for Map/Set equivalence (the -0 different from +0 issue), did we agree
 to parameterize the equivalance operator for Map/Set?,  and the question
 about the need for Number.isNaN if we have Object.is available.


I'm happy to read that the unintentional dual zeroes issue is being
considered by committee members. My attempt to raise this issue two weeks
back (Object.is(0,-0) and its data structures implications 
https://mail.mozilla.org/pipermail/es-discuss/2012-December/026794.html)
didn't generate any public responses, however multiple people responded
privately about it. Thanks!

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


Re: Number.isNaN

2012-12-18 Thread gaz Heyes
On 14 December 2012 16:39, Allen Wirfs-Brock al...@wirfs-brock.com wrote:

 No,  the whole point of Number.isNaN is to provide a definitively test for
 NaN number values which  cannot be tested for in the usual way using ===.
 The definitiveness of the test would be lost if other values such a Number
 wrapper instance also returned true when passed as the argument for
 Number.isNaN.


Why is it needed? Can't we just simply do:

function isReallyNaN(o) {
 return o!=oisNaN(o);
}

I don't get the point of detecting Object(NaN) since it's type is an object
not number.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Number.isNaN

2012-12-18 Thread David Bruant

Le 18/12/2012 14:43, gaz Heyes a écrit :
On 14 December 2012 16:39, Allen Wirfs-Brock al...@wirfs-brock.com 
mailto:al...@wirfs-brock.com wrote:


No,  the whole point of Number.isNaN is to provide a definitively
test for NaN number values which  cannot be tested for in the
usual way using ===.   The definitiveness of the test would be
lost if other values such a Number wrapper instance also returned
true when passed as the argument for Number.isNaN.


Why is it needed?
If anything, to explain devs that isNaN is broken and they should move 
to Number.isNaN.



Can't we just simply do:

function isReallyNaN(o) {
 return o!=oisNaN(o);
}

o!=o will be enough I think. You've got a polyfill :-)

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


Re: URLs / subclassing JavaScript

2012-12-18 Thread Alex Russell
hey Anne, Sam! Comments inline:

On Monday, December 17, 2012, Sam Tobin-Hochstadt wrote:

 On Mon, Dec 17, 2012 at 9:19 AM, Anne van Kesteren 
 ann...@annevk.nljavascript:;
 wrote:
  If down the road we want to allow for the theoretical possibility of
  having all platform APIs implemented in JavaScript, we might want a
  sync Object.observe.


I don't think that's wise. Rafael (cc'd) can explain why in much more
detail, but the gist of it is:

Object.observe() is a notification, not interception, mechanism. Where we
need to stratify an intercept, ES 6 Proxies are the mechanism we should
lean on, but in the main, we should ALWAYS seek to avoid using them. That
is to say, if we must do magic (use proxies), we must do magic; however we
should only arrive there after exhausting all other routes; both on the JS
and DOM sides.


 If we have types down the road as well (this
  might be a bit presumptuous), URLQuery could just be a MultiMap and
  whenever the MultiMap was mutated you'd update the associated URL
  synchronously (and potentially do other things, such as navigating to
  a URL). The latter would require synchronous change delivery. Or I
  suppose some kind of subclass that changes all the manipulation
  methods to also perform some kind of notification.


In the shorter term, your constructor can vend a Proxy (using the mechanism
Allen et. al. have devised on es-discuss and here recently).


  I guess the problems here are that a) there's no MultiMap b) there's
  no types


The lack of typing strikes me as something we can use de-sugaring in
WebIDL-generated JS to enforce. I.e., generate the JS that you'd need for
type checking:

Imagine we have IDL for a function:

// IDL
void takesOnlyStrings(DOMString arg, ...);

// JS de-sugaring
function takesOnlyStrings(...args) {
  if(!args.every(function(i) { return typeof i == string; })) {
throw new TypeError(...);
  }
  // implementation goes here
}

But if we consider a JS-only world, the typing discussion becomes a bit
less obvious. The semantic I'd instead expect in most libraries is for them
to call .toString() on the argument in question, not to reject with an
error.

 c) we want to reduce the burdon on developers for doing URL
  manipulation probably without waiting for a/b, but I rather not pull a
  Typed Array.

 First, I don't really see what types are doing in this discussion.
 Are you thinking about classes?

 Second, by far the easiest way to accomplish all of this would be to
 just make `URLQuery` implement the same interface as a MultiMap (and a
 Map).  Then there's no need for any observation, or proxies, or any of
 that, since Maps are carefully designed to be implementable entirely
 in JS.  As far as I can see, some deeper tying of URLQuery to a
 platform-builtin MultiMap would accomplish potentially the following:

   - making `instanceof` work in a few cases.
   - allowing use of MultiMap.prototype.get.call on a URLQuery.
   - anything else?

 I think `instanceof` is irrelevant, and that functions that expect
 MultiMaps or URLQuerys should just use the `m.get()` of the value they
 have, and not expect nominal typing. [1]

  Oh, and by the way, I read
  http://infrequently.org/2012/12/reforming-the-w3c-tag/#comment-240289
  the other day. 1) In so far there would be an organisation responsible
  for the URL work, it would be the WHATWG, not the W3C. 2) But really
  as far as the API of URLQuery goes, that's mostly arv, TabAtkins, and
  I. 3) If you have feedback on it, better to email it :-)

 The point I was making in that comment is that one thing we on TC39
 might want to do is provide more collection APIs so that you don't
 have to design them on the DOM side.  I'm glad that you're talking to
 TC39 about the design you're doing.


Agreed on both counts.


 [1] Item 57 in Effective JS. :)
 ___
 es-discuss mailing list
 es-discuss@mozilla.org javascript:;
 https://mail.mozilla.org/listinfo/es-discuss

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


Re: URLs / subclassing JavaScript

2012-12-18 Thread Anne van Kesteren
On Tue, Dec 18, 2012 at 4:32 PM, Alex Russell slightly...@google.com wrote:
 Object.observe() is a notification, not interception, mechanism. Where we
 need to stratify an intercept, ES 6 Proxies are the mechanism we should lean
 on, but in the main, we should ALWAYS seek to avoid using them. That is to
 say, if we must do magic (use proxies), we must do magic; however we should
 only arrive there after exhausting all other routes; both on the JS and DOM
 sides.

It seems you either need to use a Proxy, some kind of wrapper method,
or a custom implementation in most cases. Typically when objects akin
to Map or Array are exposed in a platform API, mutating them has
observable (synchronous) side effects.


 Imagine we have IDL for a function:

 // IDL
 void takesOnlyStrings(DOMString arg, ...);

 // JS de-sugaring
 function takesOnlyStrings(...args) {
   if(!args.every(function(i) { return typeof i == string; })) {
 throw new TypeError(...);
   }
   // implementation goes here
 }

 But if we consider a JS-only world, the typing discussion becomes a bit less
 obvious. The semantic I'd instead expect in most libraries is for them to
 call .toString() on the argument in question, not to reject with an error.

That is what IDL specifies, fwiw.


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


Fwd: Function identity of non-configurable accessors

2012-12-18 Thread Mark S. Miller
[Reposted at David's request.]

-- Forwarded message --
From: Mark S. Miller erig...@google.com
Date: Tue, Dec 18, 2012 at 8:19 AM
Subject: Re: Function identity of non-configurable accessors
To: David Bruant bruan...@gmail.com



On Tue, Dec 18, 2012 at 8:08 AM, David Bruant bruan...@gmail.com wrote:

  [off-list]

 Hi Mark,

 I have an email with the conclusions on the whole WindowProxy thing and
 ramifications to be cross-posted to es-discuss and public-script-coord.
 There are one remaining pending issues about function identity of
 non-configurable accessors. There are 2 main ideas:
 * Allow non-configurable accessors to change the getter/setter functions


That is unacceptable. That breaks the intended invariants. That this
invariant isn't specified is an oversight.



  * Don't allow to change the functions and for WindowProxy, define
 functions to have a special deeply frozen Function.prototype and
 Object.prototype (null realm solution championed by Brendan).


That could work, but because of its complexity, I'm leaning back towards
the configurable data property that refuses to be configured approach. Is
there a problem with that? It self-hosts fine.




 Since you're concerned about ES invariants, could you share your opinion
 on the topic as well as give your opinion on the different proposed
 solutions?

 Thanks,

 David


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


Re: URLs / subclassing JavaScript

2012-12-18 Thread Allen Wirfs-Brock

On Dec 18, 2012, at 8:08 AM, Anne van Kesteren wrote:

 On Tue, Dec 18, 2012 at 4:32 PM, Alex Russell slightly...@google.com wrote:
 Object.observe() is a notification, not interception, mechanism. Where we
 need to stratify an intercept, ES 6 Proxies are the mechanism we should lean
 on, but in the main, we should ALWAYS seek to avoid using them. That is to
 say, if we must do magic (use proxies), we must do magic; however we should
 only arrive there after exhausting all other routes; both on the JS and DOM
 sides.
 
 It seems you either need to use a Proxy, some kind of wrapper method,
 or a custom implementation in most cases. Typically when objects akin
 to Map or Array are exposed in a platform API, mutating them has
 observable (synchronous) side effects.
 

http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation 
proposes a mechanism that would support defining such object behaviors without 
requiring the full magic of Proxy.  

Allen




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


Expressing that a property is non-deletable (was: Function identity of non-configurable accessors)

2012-12-18 Thread David Bruant

Hi,

Le 18/12/2012 18:08, Brendan Eich a écrit :

Mark S. Miller wrote:
That could work, but because of its complexity, I'm leaning back 
towards the configurable data property that refuses to be 
configured approach. Is there a problem with that? It self-hosts fine.


Certainly this is the simplest solution. It has a slight smell, but no 
worse than the others'!
In an earlier message [1] I suggested that enumerable was more of a 
convention than an actual semantics. Indeed, neither host objects nor 
upcoming proxies are expected anything when it comes to enumerable. 
However, a script can have some expectations that a property defined 
and/or reflected as enumerable: true will show up in for-in and 
Object.keys while won't if enumerable: false.


One idea to reduce the smell of configurable-yet-non-deletable 
properties would be to add a new nonDeletable attribute (I'm not happy 
with the negation, but can't find a better wording). Just to clarify, 
this attribute doesn't need to be defined on every property of every 
object, only in cases where one could expect configurable:false for the 
[dontDelete] part, but configurable is actually true for other reasons.


In our case, this attribute would be relevant for both WindowProxy 
global var/functions and [Unforgeable] properties of the same object. 
This way, host objects and proxies have a convention when they want to 
express to the code that interact with them that a property can't be 
removed by use of the delete operator, but the property may disappear 
by other means (in the case of WindowProxy, change of the underlying 
window).


Defining the nonDeletable attribute (or whatever better name) is a 
decision that could be fully made on the WebIDL side, because it defines 
host objects and host objects can define their own properties, but I 
think it's important the convention emerges from the ECMAScript side.


David

[1] https://mail.mozilla.org/pipermail/es-discuss/2012-December/027200.html
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function identity of non-configurable accessors

2012-12-18 Thread Allen Wirfs-Brock

On Dec 15, 2012, at 2:51 PM, David Bruant wrote:

 Le 15/12/2012 16:14, David Bruant a écrit :
 Le 15/12/2012 15:49, Sam Tobin-Hochstadt a écrit :
 If I create a non-configurable property with a getter that I define (such
 as `() = 3`), I know that accessing the property will always produce
 a known value.Relaxing this restriction means that proxies could
 produce whatever they wanted in this situation.
 Indeed. Note that it's true currently true with ES5 host objects.
 I'd like to add that you can defend yourself by checking if the reflected 
 function is the one you put in there.
 As far as expecting some behavior on [[Get]] or [[Set]], nothing prevents a 
 proxy from either not calling the getter/setter you passed or do call them 
 but do/return whatever inconsistent with the accessor. Or why not call the 
 setter on [[Get]] and the getter on [[Set]].
 That might be one reason why there was no invariant regarding accessors in 
 ES5.
 

The whole whole idea of such invariants was a late addition to ES5, and not 
without some controversy. I don't think anyone believed that ES5 had a complete 
set of invariants or even what that might be.

Regarding the identify of stored/retrieved get/set functions, for ordinary 
objects that is fairly explicit in the ES5 spec. [[DefineOwnProperty]] sets a 
properties internal attributes to the provided values and [[GetOwnProperty]] 
retrieves the values of those attributes.  The only specified way to modify the 
identify of such a stored get/set attribute would be by an intervening 
[[DefineOwnProperty]] call.  Hence, we have identify preservation across 
setting/retrieving of get/set accessor functions.  I've thought about making 
this even more explicit, but the ES5 language seems clear enough.

For exotic objects, as is usual for most such hypothetical invariants, 
anything goes in ES5.  So, a host object could change the identity of a get/set 
accessor function. That doesn't bother me,  exotic objects are an escape 
mechanism for unanticipated new semantics.  But, the provider of such an object 
really needs to fully document its behavior.  Otherwise, its not going to be 
very useful.  But if the documentation says that the identify of get/set 
functions are not preserved, then that seems like sufficient warning.

Allen







 David
 ___
 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: Function identity of non-configurable accessors

2012-12-18 Thread Allen Wirfs-Brock

On Dec 18, 2012, at 9:08 AM, Brendan Eich wrote:

 Mark S. Miller wrote:
 That could work, but because of its complexity, I'm leaning back towards the 
 configurable data property that refuses to be configured approach. Is 
 there a problem with that? It self-hosts fine.
 
 Certainly this is the simplest solution. It has a slight smell, but no worse 
 than the others'!
 

I'm really bothered by this concept. It seems to be saying:

For my important use cases,  I must be able to depend upon the meaning of 
[[Configurable]]: false.  So implementation must take all measures necessary to 
ensure that meaning. However, I don't care about other use cases that might 
depend upon the meaning of [[Configurable]]: true.  I think its fine that  an 
implementation lies and says that an object is configurable when it really 
isn't.

This really seems like a double standard. Integrity issue are important, and in 
some cases may need to be given special consideration, but we need to consider 
the full spectrum of use cases.

Regarding simplicity.  I don't really see it.

For example, we presumably still want global object bindings introduced via var 
to not be deletable via delete (unless they were introduced using eval).  How 
do we express the link between the semantic of var and delete if we can't use 
[[DefineOwnProperty]], [[GetOwnProperty]] and the [[Configurable]] attribute . 
Instead we have to define some new mechanism/state to establish this 
relationship  [1].

More generally, if we forbid certain host object from having [[Configurable]]: 
false properties yet we also need to have some properties be non-deletable then 
we will need a new mechanism that allows that to be expressed and specified.

If we are only talking about the Global Object, we can probably accommodate 
almost anything by defining it as a special kind of exotic object.  We already 
have special case handling for declarations and identifier resolution involving 
it.  But once we're in the space of arbitrary exotic objects I think we should 
be very careful about trying to identify and enforce additional invariants.

Allen

[1] https://mail.mozilla.org/pipermail/es-discuss/2012-December/027196.html 





 /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: Function identity of non-configurable accessors

2012-12-18 Thread Mark S. Miller
On Tue, Dec 18, 2012 at 9:38 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:

 The whole whole idea of such invariants was a late addition to ES5, and not 
 without some controversy. I don't think anyone believed that ES5 had a 
 complete set of invariants or even what that might be.

As part of the proxy work, Tom and I have started a more complete list
of invariants. Yes, it would be good to make more progress on this.



 Regarding the identify of stored/retrieved get/set functions, for ordinary 
 objects that is fairly explicit in the ES5 spec. [[DefineOwnProperty]] sets 
 a properties internal attributes to the provided values and 
 [[GetOwnProperty]] retrieves the values of those attributes.  The only 
 specified way to modify the identify of such a stored get/set attribute would 
 be by an intervening [[DefineOwnProperty]] call.  Hence, we have identify 
 preservation across setting/retrieving of get/set accessor functions.  I've 
 thought about making this even more explicit, but the ES5 language seems 
 clear enough.

Agreed so far.



 For exotic objects, as is usual for most such hypothetical invariants, 
 anything goes in ES5.  So, a host object could change the identity of a 
 get/set accessor function. That doesn't bother me,  exotic objects are an 
 escape mechanism for unanticipated new semantics.  But, the provider of such 
 an object really needs to fully document its behavior.  Otherwise, its not 
 going to be very useful.  But if the documentation says that the identify of 
 get/set functions are not preserved, then that seems like sufficient warning.

This seems nonsensical to me. At
http://wiki.ecmascript.org/doku.php?id=es3.1:attribute_states is my
summary of the point of some of these invariants -- that no state
transitions beyond those shown in this diagram are possible. When
David pointed out the getter/setter identity stability invariant was
missing, this surprised me. It is clearly an oversight. It never
occurred to me when drawing this diagram that the lack of
getter/setter change applies only to ordinary objects.

JavaScript is a very dynamically typed language. Static reasoning
proceeds safely often without knowledge of the object types of the
values involved, nor (as usual) of potential aliasing. These
invariants enable useful static reasoning precisely because they are
universal (and so not type dependent) and monotonic (and so aliasing
independent). Further, as I've mentioned several times, direct proxies
can leverage the presence of a single invariant-violating exotic
object to create any number of other invariant violating objects.


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


8.2.4 The Reference Specification Type

2012-12-18 Thread John J Barton
I'm trying to decode section 8.2.4
The Reference Specification Type

I believe that it is trying to say
  obj.prop = ...
obj is reference base
prop is reference name

But base can also be Boolean, String, Number and env. record. I can't
figure out what a reference name means in these cases. I guess the |name|
is only relevant for Object, in which case the spec would be clearer if we
called it a |property key|, as in
  GetReferencedPropertyKey(V). Returns the referenced property key
component of the reference V.

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


Re: Function identity of non-configurable accessors

2012-12-18 Thread Mark S. Miller
On Tue, Dec 18, 2012 at 10:23 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 If we are only talking about the Global Object, we can probably accommodate
 almost anything by defining it as a special kind of exotic object.

AFAICT, we are only talking about the global object, in order to deal
with the navigation behavior embodied by WindowProxy.


 We
 already have special case handling for declarations and identifier
 resolution involving it.  But once we're in the space of arbitrary exotic
 objects I think we should be very careful about trying to identify and
 enforce additional invariants.

By invariant here, I only mean those that are universal. NONE of the
invariants we have been discussing here have applied only to ordinary
objects. We are not talking about adding any additional invariants.
But we should certainly flesh out the list of invariants we've got so
they form a coherent set. The getter/setter-identity issue is the only
such that I've seen in this thread which we had previously failed to
identify, though no doubt there are others. But this doesn't seem to
be the invariant you're arguing with. The more general
non-configurable implies stability invariant isn't new, and has
always applied to exotics.


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


Re: Expressing that a property is non-deletable (was: Function identity of non-configurable accessors)

2012-12-18 Thread Andrea Giammarchi
{deletable: false} does not look that bad, semantically speaking ... you
don't have to explain much what that would do in a property descriptor.
Thing is, all others are false by default so you might want to chose same
default for this property and in this case the name is wrong.
{nondeletable:false} looks like a typo while {sealed:false} for the single
property would be probably better? {sealed:true, configurable:true} means
non deletable and {sealed:true, configurable:false} could mean even
inherited properties cannot be re-defined while sealed:false would be the
default?

Or maybe not ...


On Tue, Dec 18, 2012 at 9:31 AM, David Bruant bruan...@gmail.com wrote:

 Hi,

 Le 18/12/2012 18:08, Brendan Eich a écrit :

 Mark S. Miller wrote:

 That could work, but because of its complexity, I'm leaning back towards
 the configurable data property that refuses to be configured approach. Is
 there a problem with that? It self-hosts fine.


 Certainly this is the simplest solution. It has a slight smell, but no
 worse than the others'!

 In an earlier message [1] I suggested that enumerable was more of a
 convention than an actual semantics. Indeed, neither host objects nor
 upcoming proxies are expected anything when it comes to enumerable.
 However, a script can have some expectations that a property defined and/or
 reflected as enumerable: true will show up in for-in and Object.keys while
 won't if enumerable: false.

 One idea to reduce the smell of configurable-yet-non-deletable properties
 would be to add a new nonDeletable attribute (I'm not happy with the
 negation, but can't find a better wording). Just to clarify, this attribute
 doesn't need to be defined on every property of every object, only in cases
 where one could expect configurable:false for the [dontDelete] part, but
 configurable is actually true for other reasons.

 In our case, this attribute would be relevant for both WindowProxy global
 var/functions and [Unforgeable] properties of the same object. This way,
 host objects and proxies have a convention when they want to express to
 the code that interact with them that a property can't be removed by use of
 the delete operator, but the property may disappear by other means (in
 the case of WindowProxy, change of the underlying window).

 Defining the nonDeletable attribute (or whatever better name) is a
 decision that could be fully made on the WebIDL side, because it defines
 host objects and host objects can define their own properties, but I think
 it's important the convention emerges from the ECMAScript side.

 David

 [1] https://mail.mozilla.org/**pipermail/es-discuss/2012-**
 December/027200.htmlhttps://mail.mozilla.org/pipermail/es-discuss/2012-December/027200.html
 __**_
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss

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


Bringing ES6 to programmers as soon as possible

2012-12-18 Thread Axel Rauschmayer
FWIW: This topic has been on my mind for a long time. I’ve finally written down 
my thoughts. Feedback welcome.

http://www.2ality.com/2012/12/es6-workflow.html

-- 
Dr. Axel Rauschmayer
a...@rauschma.de

home: rauschma.de
twitter: twitter.com/rauschma
blog: 2ality.com

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


Re: 8.2.4 The Reference Specification Type

2012-12-18 Thread Brandon Benvie
In that example obj itself would first have been a Reference with no base
and the name obj which would resolve to an environment record. Then after
prop would be another Reference with the resolved obj as its base and
prop as the name.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: 8.2.4 The Reference Specification Type

2012-12-18 Thread Brandon Benvie
Er I was a bit unclear. It would look like:

objReference = {
  base: undefined,
  name: obj
};

Which would resolve to the object obj, on an environment record.

objPropRefence = {
  base: IdentifierResolution(objReference),
  name: prop
}


On Tue, Dec 18, 2012 at 2:01 PM, Brandon Benvie
bran...@brandonbenvie.comwrote:

 In that example obj itself would first have been a Reference with no
 base and the name obj which would resolve to an environment record. Then
 after prop would be another Reference with the resolved obj as its base
 and prop as the name.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Expressing that a property is non-deletable (was: Function identity of non-configurable accessors)

2012-12-18 Thread Mark S. Miller
I see no reason why this needs to be a reflected property. As to
whether it is an exotic internal property or just prose, that is a
specification expository issue for which I defer to Allen. But the
spec only needs such extra state for the exotic global object. There's
nothing general about it.

On Tue, Dec 18, 2012 at 10:56 AM, Andrea Giammarchi
andrea.giammar...@gmail.com wrote:
 {deletable: false} does not look that bad, semantically speaking ... you
 don't have to explain much what that would do in a property descriptor.
 Thing is, all others are false by default so you might want to chose same
 default for this property and in this case the name is wrong.
 {nondeletable:false} looks like a typo while {sealed:false} for the single
 property would be probably better? {sealed:true, configurable:true} means
 non deletable and {sealed:true, configurable:false} could mean even
 inherited properties cannot be re-defined while sealed:false would be the
 default?

 Or maybe not ...


 On Tue, Dec 18, 2012 at 9:31 AM, David Bruant bruan...@gmail.com wrote:

 Hi,

 Le 18/12/2012 18:08, Brendan Eich a écrit :

 Mark S. Miller wrote:

 That could work, but because of its complexity, I'm leaning back towards
 the configurable data property that refuses to be configured approach. Is
 there a problem with that? It self-hosts fine.


 Certainly this is the simplest solution. It has a slight smell, but no
 worse than the others'!

 In an earlier message [1] I suggested that enumerable was more of a
 convention than an actual semantics. Indeed, neither host objects nor
 upcoming proxies are expected anything when it comes to enumerable.
 However, a script can have some expectations that a property defined and/or
 reflected as enumerable: true will show up in for-in and Object.keys while
 won't if enumerable: false.

 One idea to reduce the smell of configurable-yet-non-deletable properties
 would be to add a new nonDeletable attribute (I'm not happy with the
 negation, but can't find a better wording). Just to clarify, this attribute
 doesn't need to be defined on every property of every object, only in cases
 where one could expect configurable:false for the [dontDelete] part, but
 configurable is actually true for other reasons.

 In our case, this attribute would be relevant for both WindowProxy global
 var/functions and [Unforgeable] properties of the same object. This way,
 host objects and proxies have a convention when they want to express to
 the code that interact with them that a property can't be removed by use of
 the delete operator, but the property may disappear by other means (in the
 case of WindowProxy, change of the underlying window).

 Defining the nonDeletable attribute (or whatever better name) is a
 decision that could be fully made on the WebIDL side, because it defines
 host objects and host objects can define their own properties, but I think
 it's important the convention emerges from the ECMAScript side.

 David

 [1]
 https://mail.mozilla.org/pipermail/es-discuss/2012-December/027200.html
 ___
 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: Function identity of non-configurable accessors

2012-12-18 Thread Allen Wirfs-Brock

On Dec 18, 2012, at 10:34 AM, Mark S. Miller wrote:

 On Tue, Dec 18, 2012 at 9:38 AM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 
 The whole whole idea of such invariants was a late addition to ES5, and not 
 without some controversy. I don't think anyone believed that ES5 had a 
 complete set of invariants or even what that might be.
 
 As part of the proxy work, Tom and I have started a more complete list
 of invariants. Yes, it would be good to make more progress on this.
 
 
 
 Regarding the identify of stored/retrieved get/set functions, for ordinary 
 objects that is fairly explicit in the ES5 spec. [[DefineOwnProperty]] sets 
 a properties internal attributes to the provided values and 
 [[GetOwnProperty]] retrieves the values of those attributes.  The only 
 specified way to modify the identify of such a stored get/set attribute 
 would be by an intervening [[DefineOwnProperty]] call.  Hence, we have 
 identify preservation across setting/retrieving of get/set accessor 
 functions.  I've thought about making this even more explicit, but the ES5 
 language seems clear enough.
 
 Agreed so far.
 
 
 
 For exotic objects, as is usual for most such hypothetical invariants, 
 anything goes in ES5.  So, a host object could change the identity of a 
 get/set accessor function. That doesn't bother me,  exotic objects are an 
 escape mechanism for unanticipated new semantics.  But, the provider of such 
 an object really needs to fully document its behavior.  Otherwise, its not 
 going to be very useful.  But if the documentation says that the identify of 
 get/set functions are not preserved, then that seems like sufficient warning.
 
 This seems nonsensical to me. At
 http://wiki.ecmascript.org/doku.php?id=es3.1:attribute_states is my
 summary of the point of some of these invariants -- that no state
 transitions beyond those shown in this diagram are possible. When
 David pointed out the getter/setter identity stability invariant was
 missing, this surprised me. It is clearly an oversight. It never
 occurred to me when drawing this diagram that the lack of
 getter/setter change applies only to ordinary objects.

Similarly, then a value: identify (actually value)  stability invariant is also 
missing...

This diagram is based upon [[DefineOwnProperty]] for ordinary objects.  The 
fact it is specified as an internal method is a way of explicitly saying that 
exotic objects might apply different rules.  That has pretty much always been 
the ES definition of host object, an object that doesn't follow the ordinary 
rules.

 
 JavaScript is a very dynamically typed language. Static reasoning
 proceeds safely often without knowledge of the object types of the
 values involved, nor (as usual) of potential aliasing. These
 invariants enable useful static reasoning precisely because they are
 universal (and so not type dependent) and monotonic (and so aliasing
 independent).

I think you and I differ on what useful static reasoning means.  To me, 
wearing the hat of an application developer who is predominately dealing with 
my own or other trusted code, it means that I can reason about the expect 
behavior of my program using the ordinary semantics plus any exceptional 
semantics that I am explicitly expecting to deal with.  Anything else that 
might occur corresponds to a bug.  I look for and test for bugs, but 
realistically I never expect a program to be totally bug free.

However, in your description above you use the term safely which I understand 
that for you goes hand-in-hand with useful. For high integrity code, static 
reasoning is presumably only useful if it is also safe from an integrity 
perspective.  Basically, you need perfect code.  You can't tolerate bugs in 
your code, your reasoning, or violations of the invariants that are the axioms 
of you reasoning.

This seems like the crux of  matter WRT whether OCAP within a general purpose 
OO language can be useful as the sole high integrity encapsulation mechanism.  
To you, as a builder of high integrity sandboxes, enforcement of certain 
invariants are essential.  To me, as a application programmer or even a library 
programmer, enforcement of these invariants are generally unnecessary. If 
enforcement impacts performance or expressibility they have a negative impact 
on my ability to get my job done.

I wrote about some related issues here: 
http://www.wirfs-brock.com/allen/posts/379
Personally, I think we need the sort of kernel/framework separation I wrote 
about there.  OCAP probably isn't the sole answer.


 Further, as I've mentioned several times, direct proxies
 can leverage the presence of a single invariant-violating exotic
 object to create any number of other invariant violating objects.

I buy this and I'm sure you've probably described a specific scenario already.  
Can you provide a link to the specific exploit you have in mind here.

Allen




 
 
 --
Cheers,
--MarkM
 


Re: 8.2.4 The Reference Specification Type

2012-12-18 Thread Allen Wirfs-Brock

On Dec 18, 2012, at 10:42 AM, John J Barton wrote:

 I'm trying to decode section 8.2.4
 The Reference Specification Type
 
 I believe that it is trying to say 
   obj.prop = ...
 obj is reference base
 prop is reference name
 
 But base can also be Boolean, String, Number and env. record. I can't figure 
 out what a reference name means in these cases. I guess the |name| is only 
 relevant for Object, in which case the spec would be clearer if we called it 
 a |property key|, as in 
   GetReferencedPropertyKey(V). Returns the referenced property key component 
 of the reference V.
  


I'r all in 8.2.4.1 and 8.2.4.2 (GetValue/SetValue).

Consider  an expression like:
123.0.toFixed

This evaluates to a Reference value {base: 0, referenced name: toFixed, 
strict: false}
(or strict is true if in strict code)

GetValue/SetValue explicitly coerces primitive base values to Objects in order 
to do property lookup.

In general, within the ES6 spec, the introduction of symbols as property keys 
introduces some confusion about the implications of the work name.  I'm 
slowly migrating some uses of name to key.  However, symbols doesn't seem 
to be the source of your problem here.  

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


Re: 8.2.4 The Reference Specification Type

2012-12-18 Thread Allen Wirfs-Brock
oops, I meant {base: 123.0, referenced name: toFixed, strict: false} below

On Dec 18, 2012, at 11:39 AM, Allen Wirfs-Brock wrote:

 
 On Dec 18, 2012, at 10:42 AM, John J Barton wrote:
 
 I'm trying to decode section 8.2.4
 The Reference Specification Type
 
 I believe that it is trying to say 
  obj.prop = ...
 obj is reference base
 prop is reference name
 
 But base can also be Boolean, String, Number and env. record. I can't figure 
 out what a reference name means in these cases. I guess the |name| is only 
 relevant for Object, in which case the spec would be clearer if we called it 
 a |property key|, as in 
  GetReferencedPropertyKey(V). Returns the referenced property key component 
 of the reference V.
 
 
 
 I'r all in 8.2.4.1 and 8.2.4.2 (GetValue/SetValue).
 
 Consider  an expression like:
123.0.toFixed
 
 This evaluates to a Reference value {base: 0, referenced name: toFixed, 
 strict: false}
 (or strict is true if in strict code)
 
 GetValue/SetValue explicitly coerces primitive base values to Objects in 
 order to do property lookup.
 
 In general, within the ES6 spec, the introduction of symbols as property keys 
 introduces some confusion about the implications of the work name.  I'm 
 slowly migrating some uses of name to key.  However, symbols doesn't seem 
 to be the source of your problem here.  
 
 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: 8.2.4 The Reference Specification Type

2012-12-18 Thread John J Barton
On Tue, Dec 18, 2012 at 11:39 AM, Allen Wirfs-Brock
al...@wirfs-brock.comwrote:

 ...

 I'r all in 8.2.4.1 and 8.2.4.2 (GetValue/SetValue).

 Consider  an expression like:
 123.0.toFixed

 This evaluates to a Reference value {base: 0, referenced name: toFixed,
 strict: false}
 (or strict is true if in strict code)

 GetValue/SetValue explicitly coerces primitive base values to Objects in
 order to do property lookup.

 In general, within the ES6 spec, the introduction of symbols as property
 keys introduces some confusion about the implications of the work name.
  I'm slowly migrating some uses of name to key.  However, symbols
 doesn't seem to be the source of your problem here.


No, indeed. The source of my problem was to much C-heritage: I could not
imagine 123.0.toFixed(). (Plus that could not be the explanation since I've
not been able to understand any of the discussion about the mysterious
'symbols' ;-)

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


Do Anonymous Exports Solve the Backwards Compatibility Problem?

2012-12-18 Thread Kevin Smith
At first glance, it seems like anonymous exports might provide a way for
pre-ES6 (read: Node) modules and ES6 modules to coexist.  After all:

exports = function A() {};

just looks so much like:

module.exports = function A() {};

But is that the case?  Does this oddball syntax actually help?

My conclusion is that it does not, *unless* the loading environment is
willing to statically analyze every single module it wishes to load.
 Moreover, the desired interop is not even possible without performing
static analysis.

There are two directions that an interop strategy will have to deal with.
 First, we might want an ES6 module to be loaded by a pre-ES6 module:

// es5-module.js
var ES6Module = require(es6-module.js);

We might want to use this when a dependency is upgraded to ES6 modules and
we want to leave the dependent alone.  Now, since ES6 modules are
asynchronous, and require is synchronous, we must load es6-module.js
*before* es5-module.js is executed.  The only way to do that is to
statically analyze es5-module.js, searching for calls to require.

However, since require allows an arbitrary expression argument, there are
many cases in Node where this static analysis will fail.

What about the other direction?  Let's say that we want to load an ES5
module from an ES6 module:

import ES5Module from es5-module.js;

Let's say that the ES5 module looks like this:

// es5-module.js
module.exports = function A() {};

We could dynamically add the following text to the end of es5-module.js:

exports = module.exports;

And thereby export the necessary binding.  But if we use such a trick on an
*ES6* module, we could run into problems:

exports = foo;
// dynamically generated line:
exports = module.exports;

This would presumably result in an error!   The only way to avoid such
problems (without resorting to something like package language version
flags) is to statically analyze es5-module.js and only apply the trick
if ES6 module declarations are *not* found.

So interop implies static analysis.  And since parsing and analyzing
javascript, in javascript, for every single loaded module would be quite a
performance hit, I think such a strategy is infeasible.

So where does that leave anonymous exports?  My personal opinion is
nowhere.

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


Strawman page for ECMA 402 spec

2012-12-18 Thread Nebojša Ćirić
Hi all,
 since we have our namespace in the wiki (Globalization) we decided to put
our strawman proposals there. I've created a new page -
http://wiki.ecmascript.org/doku.php?id=globalization:strawman to hold them.

 I've started adding proposals there just to describe the overall structure
of the page.

 Should I also link this page to the main ES strawman list?

-- 
Nebojša Ćirić
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A DOM use case that can't be emulated with direct proxies

2012-12-18 Thread Tom Van Cutsem
2012/12/12 Kevin Reid kpr...@google.com

 On Wed, Dec 12, 2012 at 12:35 PM, David Bruant bruan...@gmail.com wrote:

 I was a bit too strong in my statement, sorry. Let me rephrase: the
 internal [[Target]] can't be changed, but a proxy can emulate changing of
 fake target as long as what happens with this fake target doesn't
 involve invariant checking.
 That's the reason I was suggesting that WindowProxies could (maybe
 depending on how the object reference was obtained) throw whenever
 invariant checks are involved.


 Exactly. So a user-defined switching proxy needs only to:
 1. refuse to commit to any invariant (non-configurable property or
 preventExtensions)
 2. even if its switchable-target has an invariant, do not expose that
 invariant (i.e. pretend each property is configurable)


Sorry for arriving late to this thread.


The solution that Kevin described is also how I would approach a
retargetable proxy (i.e. a proxy that can wrap different target objects
over time).
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A DOM use case that can't be emulated with direct proxies

2012-12-18 Thread Tom Van Cutsem
2012/12/13 David Bruant bruan...@gmail.com

  Le 13/12/2012 20:47, Jason Orendorff a écrit :


 David: https://gist.github.com/4279162

 I think this is what Kevin has in mind. Note in particular that the target
 of the Proxy is just a dummy object, and the handler ignores it entirely.
 The proxy uses it for invariant checks, but the intent is that those would
 always pass.

 but they do not; try:

 var [p, setTarget] = retargetableProxy({}); // I love destructuring
 sooo much!
 Object.defineProperty(p, 'a', {configurable: false, value:31});
 setTarget({});
 Object.getOwnPropertyDescriptor(p, 'a'); // invariant check throws here

 Any variant that can be written will have the same issue. Even trickeries
 with the defineProperty trap.
 The proxy is enforcing invariants against the dummy [[target]]. The same
 is to be expected from WindowProxy instances even if their underlying
 window changes. It doesn't matter if the invariant is enforced on the dummy
 target on an actual window instance. It is enforced and that's the
 problem (with WindowProxy implemented as they are now not being emulable
 with proxies)


To clarify, there won't be any invariant violations if you ensure all three
of the following conditions hold:


a) the dummy target object never acquires any invariants (letting it be a
dummy empty object and otherwise ignoring the target completely achieves
that)

b) handler traps that *query* the proxy never reveal any invariants, even
if the real target currently pointed-to has invariants (i.e.
getOwnPropertyDescriptor always changes the returned property descriptor's
configurable attribute to true, isExtensible always returns false, etc.)

c) handler traps that *update* the proxy refuse to commit
(preventExtensions throws, defineProperty returns false when dealing with
configurable:false properties, ...)


It's a heavyweight way of going about things, but as Brandon mentioned,
it's the price to pay for wanting to do weird things no normal ES5 object
could ever do. The more a proxy's behavior deviates from that of an ES5
object, the uglier its implementation will be to circumvent the invariant
checks.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: URLs / subclassing JavaScript

2012-12-18 Thread Anne van Kesteren
On Tue, Dec 18, 2012 at 6:01 PM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 It seems you either need to use a Proxy, some kind of wrapper method,
 or a custom implementation in most cases. Typically when objects akin
 to Map or Array are exposed in a platform API, mutating them has
 observable (synchronous) side effects.

 http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation
 proposes a mechanism that would support defining such object behaviors
 without requiring the full magic of Proxy.

I think we're talking past each other or I might be misunderstanding.
Lets say that hypothetically Map is sufficient for URL query
parameters and we do not need a MultiMap for its semantics. We have a
URL object and you can get to its query parameters using
URL.prototype.query. That property cannot point directly to a Map
because when I perform an operation on that Map, say
query.delete(x), not only should x be deleted from the Map, it
should also be removed from URL's string synchronously. The latter
does not seem possible using Map directly, but such a pattern is found
all over.

(That delete()'s and friends argument needs to be stringified is
another reason of course that makes it hard to reuse native types
directly.)


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


Re: A DOM use case that can't be emulated with direct proxies

2012-12-18 Thread Tom Van Cutsem
2012/12/13 Kevin Reid kpr...@google.com

 Yes, exactly. I was just this minute in the process of writing such a
 proxy myself, and have not yet confirmed whether it is accepted by the
 invariant checks for all the cases I'm thinking of (testing against FF
 18.0).

 Note that either
 (1) all the switched-among targets need to have the same [[Prototype]],
 (2) the proxy has to pretend that all inherited properties are actually
 own,
 (3) or mutating [[Prototype]] (i.e. __proto__) needs to be possible.
 In my particular use case, (1) is not a suitable option, so I would
 implement (2) if (3) is not available. Not that I approve of (3), but one
 does what one must to accomplish virtualization.


It's worth noting that direct proxies do not enforce any invariants w.r.t.
inherited property access/update. For instance, the get trap is allowed
to return arbitrary values over time for a non-configurable, non-writable
*inherited* property.


In other words, it's as if direct proxies always have a mutable __proto__
(even if Object.getPrototypeOf returns a stable result). Hence, (3) is the
best way to rationalize the behavior of direct proxies.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A DOM use case that can't be emulated with direct proxies

2012-12-18 Thread Tom Van Cutsem
2012/12/14 Mark S. Miller erig...@google.com

 On Fri, Dec 14, 2012 at 10:19 AM, Brendan Eich bren...@mozilla.com
 wrote:
  David Bruant wrote:
  Le 14/12/2012 08:25, Brendan Eich a écrit :
  window.location can be set by assignment to navigate to a new URL.
 
  location is [Unforgeable, PutForward], so it should be reflected as a
  non-configurable getter+setter according to WebIDL.
 [...]
  Nevertheless, since ES5-standard reflection is new, I doubt anyone cares
  that location appears to be a data property. It should be an accessor.
 But
  it needs to be non-configurable, so we still have a problem -- or do we?

 AFAICT, a non-configurable accessor fits all the constraints.


Also, when emulating this property using a proxy, reflecting it as a
non-configurable accessor will not violate any proxy invariants, so this is
good.

However, regarding the retargetable proxy pattern put forward by Kevin and
Jason to emulate WindowProxy, that implementation cannot accurately expose
window.location as non-configurable, but would need to expose it as
configurable instead.

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


Proxies: wrong receiver used in default set trap

2012-12-18 Thread Tom Van Cutsem
Hi,

Someone recently reported an issue [1] while using my harmony-reflect shim
for direct proxies. The fix probably requires a change in the proxy
specification. I'm unsure how to resolve it, so I thought I'd bring it to
the list.

The issue is as follows:

consider a proxy with an empty handler:
var proxy = Proxy(target, {});

now consider assigning a property to the proxy:
proxy.foo = 42

This triggers the proxy's set trap, but since the handler does not define
this trap, the default behavior is to forward the assignment to the target.

As currently specified, the intercepted assignment is forwarded as:

Reflect.set(target, 'foo', 42, proxy)

where 'proxy' is used as the initial receiver of the property assignment.

This fourth receiver argument matters for two reasons:
1) if 'target' defines or inherits 'foo' as an accessor property, inside
that accessor, |this| will point to that receiver argument.
2) if receiver !== target, then Reflect.set will *add* a new data property
to receiver, rather than *update* an existing data property on the target.

Currently, for an assignment as shown above, the proxy itself is passed as
the fourth 'receiver' argument. Thus:
1) inside triggered accessors, |this| will refer to the proxy, not to the
target. This is acceptable.
2) since proxy !== target, Reflect.set will try to *add* data properties to
'proxy', rather than *update* an existing data property on the target. This
is not acceptable and is what causes the issue [1].

I see two solutions, but can't decide on which is better. There may be
better solutions altogether.

Option A:
change the default forwarding behavior of the set trap to:

if the proxy is the initial receiver of the property assignment, then
  return Reflect.set(target, name, val, target)
else
  return Reflect.set(target, name, val, receiver)

If the initial receiver is an object that delegates to a proxy, the proxy
won't change the receiver upon forwarding, in order to not interfere with
prototype inheritance.

This solution fixes point 2) since Reflect.set is no longer confused about
the proxy.
Re. point 1), the |this|-binding inside forwarded accessors will now refer
to the target object itself, which I find equally acceptable.

For reasons of symmetry, if we go this route, we probably need to change
the default forwarding behavior of get in a similar way. Point 2) does
not come up in this case, but Point 1) does. We probably want the rules for
|this|-binding in forwarded getters to be consistent with setters.

Option B:
Address point 2) directly by changing the test that determines property
addition versus property update inside Reflect.set (i.e. the [[SetP]]
internal method of objects) so that the algorithm no longer tests whether
target === receiver, but rather whether target === receiver || receiver is
a proxy for target.

This solves the issue at hand, although it feels like a more ad hoc
solution.


Another way of looking at things is that the Reflect.set (or [[SetP]])
algorithm currently assumes that the receiver argument is either the
target object itself, or otherwise an object that directly or indirectly
inherits from the target object. If this assumption is violated, strange
behavior can ensue. In the above example, the proxy passed in as the
receiver argument is neither the target object nor an object that
inherits from it, hence the strange behavior.

Cheers,
Tom

[1] https://github.com/tvcutsem/harmony-reflect/issues/11
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proxies: wrong receiver used in default set trap

2012-12-18 Thread Allen Wirfs-Brock
I think it has to be A, for consistency with [[Call]].  Note that when [[Call]] 
is directly forwarded to the target, the this value is set to target. It 
wouldn't be self-consistent if directly forwarded foo.access and foo.method() 
invocations used different this values.

I assume that by proxy is the initial receiver, you mean that for a 
[[SetP]]/[[GetP]] invocation that  SameValue(O,Receiver) is true.  If so, that 
also seems right to me.  In writjing various [[SetP]]/[[GetP]]/equivalent proxy 
traps, this test is one I've found that I routine have  to make.  It basically 
distinguished between the initial application of the operation and  a proto 
climbing (or other similar delegating) application. 

I'm actually surprised that I didn't notice this wrong receiver issue when I 
incorporated Proxy exotics into the ES6 spec. as I spend a lot of time thinking 
about what was the correct this value to forward in various situations.  I'm 
not blissfully happy with the current forwarding model, but I think it is ok as 
long as we make sure it is completely self consistent.  The situations I was 
concerned with are similar for [[Call]] when it is directly forward.  If 
prox.foo() is forwarded so that the foo method is invoked with the proxy's 
target as the this value then any this.bar() calls within the foo method 
dispatches through the target rather than prox.  From an OO delegation 
perspective this feels wrong.  However, it feels ok if you think of direct 
forward not as a form of object delegation but rather redirection to a 
completely oindependent object(the target).  In that case, it is very important 
that all forwarding consistently use the target as the receiver.

If you really want to [[Call]] a target method with the proxy as the this value 
or do the equivalent for [[SetP]]//[[GetP]] you can do it by providing a hander 
that does what you want rather than depending upon direct forwarding.

Allen

 

On Dec 18, 2012, at 1:56 PM, Tom Van Cutsem wrote:

 Hi,
 
 Someone recently reported an issue [1] while using my harmony-reflect shim 
 for direct proxies. The fix probably requires a change in the proxy 
 specification. I'm unsure how to resolve it, so I thought I'd bring it to the 
 list.
 
 The issue is as follows:
 
 consider a proxy with an empty handler:
 var proxy = Proxy(target, {});
 
 now consider assigning a property to the proxy:
 proxy.foo = 42
 
 This triggers the proxy's set trap, but since the handler does not define 
 this trap, the default behavior is to forward the assignment to the target.
 
 As currently specified, the intercepted assignment is forwarded as:
 
 Reflect.set(target, 'foo', 42, proxy)
 
 where 'proxy' is used as the initial receiver of the property assignment.
 
 This fourth receiver argument matters for two reasons:
 1) if 'target' defines or inherits 'foo' as an accessor property, inside that 
 accessor, |this| will point to that receiver argument.
 2) if receiver !== target, then Reflect.set will *add* a new data property to 
 receiver, rather than *update* an existing data property on the target.
 
 Currently, for an assignment as shown above, the proxy itself is passed as 
 the fourth 'receiver' argument. Thus:
 1) inside triggered accessors, |this| will refer to the proxy, not to the 
 target. This is acceptable.
 2) since proxy !== target, Reflect.set will try to *add* data properties to 
 'If you want to   ddasfdasfasdfafasfasffsff
 
 I see two solutions, but can't decide on which is better. There may be better 
 solutions altogether.
 
 Option A:
 change the default forwarding behavior of the set trap to:
 
 if the proxy is the initial receiver of the property assignment, then
   return Reflect.set(target, name, val, target)
 else
   return Reflect.set(target, name, val, receiver)
 
 If the initial receiver is an object that delegates to a proxy, the proxy 
 won't change the receiver upon forwarding, in order to not interfere with 
 prototype inheritance.
 
 This solution fixes point 2) since Reflect.set is no longer confused about 
 the proxy.
 Re. point 1), the |this|-binding inside forwarded accessors will now refer to 
 the target object itself, which I find equally acceptable.
 
 For reasons of symmetry, if we go this route, we probably need to change the 
 default forwarding behavior of get in a similar way. Point 2) does not come 
 up in this case, but Point 1) does. We probably want the rules for 
 |this|-binding in forwarded getters to be consistent with setters.
 
 Option B:
 Address point 2) directly by changing the test that determines property 
 addition versus property update inside Reflect.set (i.e. the [[SetP]] 
 internal method of objects) so that the algorithm no longer tests whether 
 target === receiver, but rather whether target === receiver || receiver is a 
 proxy for target.
 
 This solves the issue at hand, although it feels like a more ad hoc solution.
 
 
 Another way of looking at things is that the Reflect.set (or [[SetP]]) 

Re: URLs / subclassing JavaScript

2012-12-18 Thread Allen Wirfs-Brock

On Dec 18, 2012, at 1:36 PM, Anne van Kesteren wrote:

 On Tue, Dec 18, 2012 at 6:01 PM, Allen Wirfs-Brock
 al...@wirfs-brock.com wrote:
 It seems you either need to use a Proxy, some kind of wrapper method,
 or a custom implementation in most cases. Typically when objects akin
 to Map or Array are exposed in a platform API, mutating them has
 observable (synchronous) side effects.
 
 http://wiki.ecmascript.org/doku.php?id=strawman:object_model_reformation
 proposes a mechanism that would support defining such object behaviors
 without requiring the full magic of Proxy.
 
 I think we're talking past each other or I might be misunderstanding.
 Lets say that hypothetically Map is sufficient for URL query
 parameters and we do not need a MultiMap for its semantics. We have a
 URL object and you can get to its query parameters using
 URL.prototype.query. That property cannot point directly to a Map
 because when I perform an operation on that Map, say
 query.delete(x), not only should x be deleted from the Map, it
 should also be removed from URL's string synchronously. The latter
 does not seem possible using Map directly, but such a pattern is found
 all over.
 
 (That delete()'s and friends argument needs to be stringified is
 another reason of course that makes it hard to reuse native types
 directly.)

Several, observations

1) yes, we probably are talking past each other, sorry...

2) To me, we are also talking about OO design esthetics and we may well be 
applying different esthetics.

As you now more fully describe the situations, I would say, that a query 
object certainly should not be just a Map or any other basic collection style 
object. The reason is that the primary role of any collection is to hold and 
provide structured access (in some specific manner) to a collection of data.  
(see http://www.wirfs-brock.com/PDFs/Characterizing%20Classes.pdf ).  As soon 
as you starting adding domain specific semantics to a collection you are giving 
it a very different role.  Probably that  of a service provider or coordinator. 
 

In this case, (and without really knowing your actual requirements for a URL 
query parameter object) I would say the value provided by URL.prototype.query 
should be an instance of the URLQuery class (or would URLFilter or URLInspector 
be a better name) whose primary responsibility is to support structured 
manipulation/inspection of a URL.  It may present a Map-like interface for 
accomplish for performing these manipulations. But that collection style 
interface is simply a secondary (although perhaps very convenient) 
characteristic of the object.

When implementing a URLQuery (or whatever it's called) object in JavaScript you 
might well choose to encapsulate a regular Map object as part of the URLQuery 
internal state.  In that case, you would probably implement the Map interface 
on URLQuery by some sort of wrapper method delegating to the encapsulated Map 
instance.  But the wrapper methods would also do other things, like updating 
the URL string.

3) When initially setting a query on an URL, it may be convenient to pass the 
parameters for initialize the query object as a regular Map or other generic 
collection.  That's fine, as long as it is understood that what is being passed 
is only initialization parameters and that the actual query object will be a 
new object (probably of a different domain specific kind) rather than the Map 
that was originally passed.

3) I agree, this pattern is found all over and in all kinds of applications.  
Arguably it is at the essence of what object-oriented design is all about.  
When do you reuse a canned general purpose object and when do you need to 
introduce a new application domain specific  special-purpose kind of object.

Many years ago I coined a phrase for a style guideline for Smalltalk 
programmers.  It was never use an Array when an Object will do.  The basic 
idea is still the same, and it really applies to all generic collection objects 
and all languages.  The basic message is don't place application domain 
specific behavior into general purpose collection objects and conversely don't 
use a general purpose collection where you need to have domain specific 
behavior. Use a domain object (eg, URLQuery) in situations like this.

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