Re: Number.isNaN
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
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
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
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
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
[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
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)
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
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
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
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
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
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)
{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
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
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
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)
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
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
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
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
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?
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
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/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/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
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/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/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
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
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
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