Re: ES4 draft: Object
On Mar 10, 2008, at 7:01 PM, Lars Hansen wrote: We are the WG. Are you saying that substantive discussions of your proposals are not welcome? Not sure what the point of participating is if that's the case. Sorry, I didn't realize that I find it abhorrent qualified as substantive discussion. My fault. Won't happen again. The optional second argument to make propertyIsEnumerable a setter has some practical problems: 1) It violates the very strong norm that getter and setter functions are separate and have their own different arguments. It will make the feature harder to use and code using it harder to understand, to some extent. 2) It makes it impossible to feature test for the ability to disable enumerability, compared to a separate setter. Against the argument that it is too risky compatibility-wise to add a new method to the object prototype (apparently the only reason things were done), I propose that it is overblown. Mozilla has defined new methods and properties on all objects. We have copied some in Safari and seen no web compatibility issues, I assume Mozilla has not had any as well. Specifically, I am thinking of __defineSetter__, __defineGetter__, __lookupSetter__, __lookupGetter__, and __proto__. Has any study been done on how many sites currently make use of the property names of a likely setter for propertyIsEnumerable? I'm dealing with a serious insurrection of folks who believe that the ES4 working group has a bad attitude, based on Brendan's public comments and responses to issues like this one. They're quite visible. Debate is only good. I merely pointed out the obvious thing, namely that until there is an alternative proposal written up to deal with this issue, the current design stands unless the WG, as a group, decides to just get rid of it (leaving the problem it was designed to solve solution-less). Surely reviewing this spec is the appropriate time to revisit this issue. I'd like to propose the following three alternatives to the current proposal: 1) Remove the feature entirely from ES4 (as part of the judicious feature cuts process) until a more appropriate syntax is found 2) Replace two-argument form of propertyIsEnumerable with setPropertyIsEnumerable 3) Replace two-argument form of propertyIsEnumerable with __setPropertyIsEnumerable__ I think each of these options is so trivial as to not require a lengthy write-up. What is the process for the WG deciding whether to make one of these changes, or something else? I like the idea of making non-public-namespaced properties be not-enumerable and getting rid of DontEnum. We've talked loosely about it for a while. But it's remained loose talk, it has never made it to the stage where it is a coherent proposal. I don't like syntax-based alternatives since they cannot be made to degrade gracefully in ES3 UAs. Regards, Maciej ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Insurrection (was: ES4 draft: Object)
On Mar 10, 2008, at 9:54 PM, Mark Miller wrote: ES3 has several abstraction mechanisms: * lambda abstraction, which it gets approximately as right as Scheme! * objects as a generalization of records, which has some pros and cons * prototype-based sharing of common behavior, which is used almost exclusively by JavaScript programmers to express only class-like patterns. Altogether, ES3 has many virtues and many problems. One of its great virtues is its almost perfect support for lexical nesting. Virtually any thisless construct that could appear at top level can also appear within a nested lexical context with the same meaning. ES3 also avoids the CommonLisp trap of multiple namespaces, instead siding with Scheme's single namespace approach. Even ignoring ES4's type system, ES4 adds all the following abstraction mechanisms to those in ES3: * classes * packages * units * namespaces You forgot interfaces (and the type system also adds record types, (sort-of)-tuples, typed arrays and parametric types). That does seem like a lot. - Maciej ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Insurrection (was: ES4 draft: Object)
ES3 has several abstraction mechanisms: * lambda abstraction, which it gets approximately as right as Scheme! * objects as a generalization of records, which has some pros and cons * prototype-based sharing of common behavior, which is used almost exclusively by JavaScript programmers to express only class-like patterns. Altogether, ES3 has many virtues and many problems. One of its great virtues is its almost perfect support for lexical nesting. Virtually any thisless construct that could appear at top level can also appear within a nested lexical context with the same meaning. ES3 also avoids the CommonLisp trap of multiple namespaces, instead siding with Scheme's single namespace approach. Even ignoring ES4's type system, ES4 adds all the following abstraction mechanisms to those in ES3: * classes * packages * units * namespaces You forgot interfaces (and the type system also adds record types, (sort-of)-tuples, typed arrays and parametric types). That does seem like a lot. There are also like / wrap types. Geoff ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
On Mar 10, 2008, at 11:14 PM, Maciej Stachowiak wrote: The optional second argument to make propertyIsEnumerable a setter has some practical problems: 1) It violates the very strong norm that getter and setter functions are separate and have their own different arguments. It will make the feature harder to use and code using it harder to understand, to some extent. 2) It makes it impossible to feature test for the ability to disable enumerability, compared to a separate setter. Against the argument that it is too risky compatibility-wise to add a new method to the object prototype (apparently the only reason things were done), I propose that it is overblown. Mozilla has defined new methods and properties on all objects. We have copied some in Safari and seen no web compatibility issues, I assume Mozilla has not had any as well. Specifically, I am thinking of __defineSetter__, __defineGetter__, __lookupSetter__, __lookupGetter__, and __proto__. Has any study been done on how many sites currently make use of the property names of a likely setter for propertyIsEnumerable? I forgot to mention, making two-argument propertyIsEnumerable have setter semantics can be a tiny compatibility risk too, if any code accidentally calls it with two args and does not expect it to act as a setter in this case. Do we have any way to quantify the relative compatibility risk of the current design vs. a separate setter? Regards, Maciej ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
On Mon, Mar 10, 2008 at 11:14 PM, Maciej Stachowiak [EMAIL PROTECTED] wrote: [...] I'd like to propose the following three alternatives to the current proposal: 1) Remove the feature entirely from ES4 (as part of the judicious feature cuts process) until a more appropriate syntax is found 2) Replace two-argument form of propertyIsEnumerable with setPropertyIsEnumerable 3) Replace two-argument form of propertyIsEnumerable with __setPropertyIsEnumerable__ So long as setPropertyIsEnumerable is a method of Object.prototype, it raises the otherwise pointless question of the meaning of overriding it. At the last ES3.1 face-to-face, we agreed instead on the following static method on Object, as recorded at http://wiki.ecmascript.org/doku.php?id=es3.1:targeted_additions_to_array_string_object_date: - Object.dontEnum(object, memberName) The own property memberName of object is marked to be excluded for the for in enumeration. If a new object is made that delegates to object, the new object may create and change its own memberName property, and that property will be enumerable. - That page also lists static methods on Object to set the attributes DontDelete and ReadOnly. The proposed static Object.fix(obj) is inspired by proposed ES4's notion of a fixture -- a non-dynamic object. Such static methods allow most of the restrictions associated with ES4's classes to be expressed without new syntax or major new concepts. -- Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
On Mar 10, 2008, at 11:35 PM, Mark S. Miller wrote: On Mon, Mar 10, 2008 at 11:14 PM, Maciej Stachowiak [EMAIL PROTECTED] wrote: [...] I'd like to propose the following three alternatives to the current proposal: 1) Remove the feature entirely from ES4 (as part of the judicious feature cuts process) until a more appropriate syntax is found 2) Replace two-argument form of propertyIsEnumerable with setPropertyIsEnumerable 3) Replace two-argument form of propertyIsEnumerable with __setPropertyIsEnumerable__ So long as setPropertyIsEnumerable is a method of Object.prototype, it raises the otherwise pointless question of the meaning of overriding it. I don't see how it raises any special questions - it's not called internally by the implementation or anything. At the last ES3.1 face-to-face, we agreed instead on the following static method on Object, as recorded at http://wiki.ecmascript.org/doku.php?id=es3.1:targeted_additions_to_array_string_object_date : That proposal seems to depart markedly from the past plan that ES 3.1 is to be a subset of ES4. Has that plan been abandoned? ES3.1 organizers, what's up? (If you'd like to propose this design for ES4 as well then the basic approach seems sound, in that it avoids whatever risk there is to polluting the namespace of all objects without being conceptually confusing. Also the names lean too much towards terse instead of descriptive for such obscure operations. For instance Object.readOnly(o, p) would read much better as something like Object.makePropertyReadOnly(o, p).) Regards, Maciej ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
On 11/03/2008, Maciej Stachowiak [EMAIL PROTECTED] wrote: This is not unreasonable, but if adding to Object.prototype is truly terrifying then I think the approach Mark Miller linked to, of static methods on the Object constructor, is cleaner: /snip/ It might even be better to make this transition one-way, since it shouldn't be allowed to make built-in properties that are DontEnum enumerable: Could as well make it a global function then. Just give it an obscure __preventEnumeration__(obj, propName) signature or something. I would very much like to see a declarative keyword for use with global, class and namespace variable and function declarations and in object literals. There's really not much reason to require a function call for a declarative feature if there's a cheap and much nicer way to do it in ES4, as long as you have a solution for ES3. (Kinda like how there's a specific slice syntax in ES4, but the slice functionality itself is ES3 compatible.) -- David liorean Andersson ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Yuh-Ruey Chen [EMAIL PROTECTED] wrote: Which gets me back to the cognitive load issue. Even with a name like 'hidden', they may think they may have to do some funky syntax like |obj.hidden::other_ns::prop| do hide a prop in another namespace. This was confusing me... How would you define a property to have a qualified name and be in the dontenum namespace at the same time? Or are namespaced properties non-enumerable anyway? (That would feel wrong to me..) namespace dontenum_ns = dontenum other_ns; obl.dontenum_ns::prop = 1; ? The problem here would be the property would always be accessible to all scopes, since only one of the namespaces needs to be open. ES4 doesn't currently have a way to express AND/OR namespace combinations. Peter ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Insurrection (was: ES4 draft: Object)
Hi Mark, I agree with a number of your objections. I hope you don't mind if I try to distinguish between some of the points I agree with and disagree with. The current fad in language design is expressive static type systems. As a result, several recent type systems have grown eat their language. Java 1.5 is a particularly nasty example. Simple bits of Java code become so overwhelmed by complex type declarations as to obscure the logic of the code itself. Proposed ES4 suffers from the same disease, though it has not (yet) come down with as bad a case as Java. I'd love for us to get past the points about popularity and fads. I know that static types are all the rage and that dynamic languages have consequently suffered in the court of popular opinion. I'm a member of the Scheme community so I feel it acutely. But I'm skeptical of your comparison to Java 5. Java is a statically typed language that gained even more types. The ES4 proposal is a dynamic language with optional type annotations. These are there to help people when they feel that types would serve to document their code and type checking would help improve the robustness of their code and/or make the kinds of ad-hoc checking (hand-written assertions) cleaner. When people don't feel they add value, they don't have to use them. In Java 5, you're locked in to complex type annotations and can't get out. An important design goal in the ES4 type system has been to make the relationship between typed and untyped code relaxed enough that this doesn't happen. Even ignoring ES4's type system, ES4 adds all the following abstraction mechanisms to those in ES3: * classes * packages * units * namespaces I'm sympathetic-- I've always been uncomfortable with packages and namespaces. (My reaction to units was more hopeful, since the global object is so problematic in ES3, but I'm not yet up to speed on the proposal.) If instead classes, for example, were defined purely by syntactic expansion to the constructs in ES3.1, then classes would inherit the lexical nestability of the constructs they expand into. Even Java's classes are lexically nestable! Nestability is a good design goal, and I'm glad you brought it up. Syntactic expansion has many benefits, too, of course. I just want to point out the main pitfall in making classes syntactic sugar. One of the real problems with ES3 is the inability to make guarantees about any bindings except for lexical ones. With vanilla ES3 objects, there's no way to share information between (conceptual) modules of code and preserve the integrity of the container, unless you either a) hide the data in a closure or b) copy the data into a dummy container. Classes, in addition to being a well-understood mechanism and the de facto style of the JS community, should help the programmer protect the integrity of their bindings. For example, a class declaration in ES4 creates fixtures for its properties-- meaning that the programmer can rely on them not being deleted. The current ad hoc approaches in use in ES3 can't guarantee that, and manually using closures is too heavyweight. That said, you've hinted at alternative approaches, perhaps with constructs desugaring to closures of some sort: The namespace mechanism seems motivated by a failure to appreciate the power available by modest extensions of simple lambda abstraction. I'd certainly like to hear what you're thinking here. Why should we prefer foo::bar::baz? What is gained by having two mechanisms? Fair criticisms (and I personally feel the namespace mechanism is one of the most deserving of criticism). Primarily, the purpose it's serving is a way to protect object properties with a key that you can then control via e.g. lexical hiding. The Foo.Bar.baz pattern in ES3 doesn't provide a way to hide such bindings. When I first read the overview, I was puzzled by the lack of uniformity between the types [int] and [int, String]. IIUC, the first represents the type of all arrays *all* of whose elements are ints. That's not my understanding. IIRC, for a type [T1,...,Tn,Tn+1] there are required to be zero or more array elements of Tn+1. So [int] is the type of arrays with zero or more ints, and [int, String] is the type of arrays with an int at index 0 followed by zero or more Strings. I'll grant that this is unconventional. But it's an attempt to make the type structure match actual usage in JS: people use arrays both as arrays and as tuples. So we have a type that accomodates the idiomatic usage of the language. Dave ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
1) Remove the feature entirely from ES4 (as part of the judicious feature cuts process) until a more appropriate syntax is found Setting dontEnum is immensely valuable as a framework developer. I realize that is not a very technical argument, but controlling dontEnum is of more value than many of the other features in ES4, and would certainly hope it is not omitted. So long as setPropertyIsEnumerable is a method of Object.prototype, it raises the otherwise pointless question of the meaning of overriding it. At the last ES3.1 face-to-face, we agreed instead on the following static method on Object, as recorded at http://wiki.ecmascript.org/doku.php?id=es3.1:targeted_additions_to_array_string_object_date: - Object.dontEnum(object, memberName) I realize I wasn't there (at the ES3.1 F2F, only called in), but why was this discussed for ES3.1? I thought the page you are referencing was simply items that hadn't been cleaned up yet, since it clearly does not subset ES4 (as I noted in my comments on that page). If we desire that this be a part of ES3.1, it should be brought up as a proposal for ES4, so that ES3.1 can safe subset it, rather than creating new divergent features for ES3.1. Frankly, I like the idea of using Object.dontEnum(object, memberName), that sounds great to me, but it should be an ES4 proposal first and should not be considered for inclusion in ES3.1 unless and until accepted by ES4. BTW, Another possible syntax could be: Object.setAttribute(object, memberName,attributeFlag) which could be used to set the dontEnum, readOnly, and dontDelete flags and probably more closely follows the internal structure of implementations as well. Thanks, Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Function
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Jon Zeppieri Sent: 10. mars 2008 20:39 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: ES4 draft: Function On 3/10/08, Lars Hansen [EMAIL PROTECTED] wrote: First draft of the spec for the Function class. Please comment. Suggestion: deprecate the Function constructor and static invoke(). Almost all of its uses are better handled by function expressions and, in those cases where eval() in required, one can use eval(). I think there are three points to be made here. The first is that the Function constructor provides functionality that eval does not, namely, creating new functions that are closed in the global environment only. Erik made the argument that this is sometimes useful; I agree. The second point is about deprecation. TG1 has had a difficult time with deprecation in general. It is not clear that deprecation means anything on the web, except /maybe/ in the very long term. The fact that we deprecate something has no bearing on existing content, and new engines will need to support old behavior. So though TG1 finally (on my insistence) deprecated the arguments object, it was with a shrug, and it would be surprising to me if the deprecation clause makes it into the final spec, as it has no real impact. (I actually wanted to remove the arguments object from ES4 so that ES4-only implementations would not have to implement it at all, to be replaced by rest arguments and this function.) The third point is, why deprecate that particular functionality? It's not like it costs much at all in terms of spec space or implementation complexity. Eval already requires hooks into a run-time compiler, which is where the heavy lifting goes. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Map
Draft 3 enclosed. Changelog near the top; the only significant change is fixing the bug Erik noted in the prototype get and put methods. Please note one open issue; the current design is probably OK but I would appreciate comments. --lars -Original Message- From: Lars Hansen Sent: 3. mars 2008 02:03 To: Lars Hansen; es4-discuss@mozilla.org Subject: RE: ES4 draft: Map Draft 2 enclosed (changelog near the top). --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Lars Hansen Sent: 29. februar 2008 11:34 To: es4-discuss@mozilla.org Subject: ES4 draft: Map I'm enclosing the draft for the Map class. Please comment. --lars Title: The class "Map" The class Map NAME: "The class 'Map'" FILE: spec/library/Map.html CATEGORY: Pre-defined classes (E262-3 Chapter 15) SOURCES:REFERENCES [1], [2], [3] SPEC AUTHOR:Lars DRAFT STATUS: DRAFT 3 - 2008-03-11 REVIEWED AGAINST ES3: N/A REVIEWED AGAINST ERRATA:N/A REVIEWED AGAINST BASE DOC: N/A REVIEWED AGAINST PROPOSALS: YES REVIEWED AGAINST CODE: YES REVIEWED AGAINST TICKETS: YES IMPLEMENTATION STATUS: ES4 RI TEST CASE STATUS: Unknown OPEN ISSUES * 'intrinsic::clear' uses 'iterator::get' and 'intrinsic::remove' to perform removal. That is by design (it allows overridden methods that observe or modify iteration and removal to work during clearing as well). But is it desirable? CHANGES SINCE DRAFT 2 (2008-03-03) * The prototype 'get' and 'put' methods also accept a 'notfound' parameter. * Presentation: - section headers for intrinsic methods now use the syntax 'intrinsic::foo()' instead of just 'foo'. - compatibility note ("new in 4th edition") - added an explicit "extends Object" clause. - the informative method 'allElements' was renamed as 'allItems'. - corrected a typo - common fields in the status block above CHANGES SINCE DRAFT 1 (2008-02-29) * The value returned by 'hashcode' is constrained to be a number and is always explicitly converted to uint * Map(x) returns x if x is a Map * 'get' and 'put' have (V|undefined) return types * 'get' and 'put' accept an optional value (defaulting to undefined) which is returned if the association was not found in the map * There is a new method 'clear' to clear the map * The object returned from helper::iterate has been annotated with an explicit type, fixing the next field. NOTES * Informative methods: Informative methods on Map do not call program-visible (i.e., public, protected, intrinsic, reflect, meta, iterator, or prototype) methods on their 'this' object except as explicitly specified in this document. (The above clarification belongs in a general preface to the library.) * Subtyping for parameterized classes: We've agreed that for a parameterized type Cls and type T, Cls.T is a subtype of Cls.*. That has yet to be fully formalized. The Map class relies on that subtyping rule for its 'this' constraints on prototype methods, and for type testing in the static 'meta::invoke' method. REFERENCES [1] http:wiki.ecmascript.org/doku.php?id=proposals:dictionary [2] http:bugs.ecmascript.org/ticket/146 [3] http:bugs.ecmascript.org/ticket/203 The class Map is a parameterized, dynamic, non-final, direct subclass of Object that provides a reliable, efficient, mutable, and iterable map from keys to values. Keys and values may be of arbitrary types. COMPATIBILITY NOTE The class Map is new in the 4th Edition of this Standard. A Map is realized as a hash table. When the Map is constructed the caller may provide specialized functions that compare keys and compute hash values for keys. Synopsis The class Map provides the following interface: __ES4__ dynamic class Map.K,V> extends Object { public function Map(equals: function = (function(a,b) a === b), hashcode: function = intrinsic::hashcode) static meta function invoke(object: Object): Map.EnumerableId,*> static public const length = 2; intrinsic function size() : uint intrinsic function get(key: K, notfound: (V|undefined)=undefined) : (V|undefined) intrinsic function put(key: K, value: V, notfound: (V|undefined)=undefined) : (V|undefined) intrinsic function has(key:K) : boolean intrinsic function remove(key:K) : boolean intrinsic function clear() : void iterator function get(deep: boolean = false) : iterator::IteratorType.K> iterator function getKeys(deep: boolean = false) : iterator::IteratorType.K> iterator function getValues(deep: boolean = false) : iterator::IteratorType.V> iterator function getItems(deep: boolean = false) : iterator::IteratorType.[K,V]> private const equals :
Re: ES4 draft: Function
On Tue, Mar 11, 2008 at 10:49 AM, Lars Hansen [EMAIL PROTECTED] wrote: I think there are three points to be made here. The first is that the Function constructor provides functionality that eval does not, namely, creating new functions that are closed in the global environment only. Erik made the argument that this is sometimes useful; I agree. Doesn't global.eval() meet this requirement? From the overview document: === ES4 additionally defines eval as a function bound in the global environment that can be called indirectly through that environment (e.g., as window.eval(s) in a web browser) or whose value can be read and passed around, stored in other variables and so on, and called as a plain function: var e = eval ... e(myprog) In both of these cases, the evaluation takes place in the global environment in which the eval function is defined. === The second point is about deprecation. TG1 has had a difficult time with deprecation in general. It is not clear that deprecation means anything on the web, except /maybe/ in the very long term. The fact that we deprecate something has no bearing on existing content, and new engines will need to support old behavior. Deprecation isn't solely (or even primarily) for the benefit of implementors. It tells the programmer: This probably isn't what you want, and even if it does what you want, there's a more sane way to do it. What does new Function() get you that eval doesn't (taking into consideration global.eval())? For the most part, it's just syntactic... well, not sugar, because it doesn't actually result in a cleaner syntactic construction. 'Syntactic salt' still suggests some kind of enhancement... I'd call it a syntactic booger. To the extent that it isn't just a special case of eval(), it's useless. You could, for example, define a subclass of Function that might do something potentially useful. I notice that you can't instrument the normal call functionality, since the instance version of meta::invoke() is final, but you might be able to instrument apply() for some potentially useful debugging purpose. But to make use of it, you would need to construct your functions using 'new' and incur the enormous performance penalty -- not to mention the fact that since all functions so created are closed in the global environment, it's completely worthless for functions that need to close over lexical bindings. So though TG1 finally (on my insistence) deprecated the arguments object, it was with a shrug, and it would be surprising to me if the deprecation clause makes it into the final spec, as it has no real impact. (I actually wanted to remove the arguments object from ES4 so that ES4-only implementations would not have to implement it at all, to be replaced by rest arguments and this function.) I sympathize. The third point is, why deprecate that particular functionality? It's not like it costs much at all in terms of spec space or implementation complexity. Eval already requires hooks into a run-time compiler, which is where the heavy lifting goes. Again -- this isn't for the benefit of implementors. -Jon --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Peter Hall wrote: Yuh-Ruey Chen [EMAIL PROTECTED] wrote: Which gets me back to the cognitive load issue. Even with a name like 'hidden', they may think they may have to do some funky syntax like |obj.hidden::other_ns::prop| do hide a prop in another namespace. This was confusing me... How would you define a property to have a qualified name and be in the dontenum namespace at the same time? Or are namespaced properties non-enumerable anyway? (That would feel wrong to me..) The latter. It is weird, I agree. But the enumerator can easily be customized, so I want the default enumerator be as non-magical as possible - and therefore, as simple as possible. In fact, I'm a bit bothered that propertyIsEnumerable is a method of Object yet can be rendered useless when changing the enumerator - along this line of reasoning, one would think that such a specific method shouldn't be a method of Object at all, but rather the enumerator itself. ES4 doesn't currently have a way to express AND/OR namespace combinations. Yeah, I vaguely remember some discussion concerning multiple namespaces per property a long time ago (maybe a year ago). It was rejected probably due to complexity. -Yuh-Ruey Chen ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Function
I promise not to drag out this discussion, since no one else seems to be interested in it. On Tue, Mar 11, 2008 at 12:16 PM, Lars Hansen [EMAIL PROTECTED] wrote: Sure, nobody argues about that per se, but I don't see the spec as being the place to take an ideological stand about whether global.eval is cleaner than 'new Function', if taking a stand doesn't gain practical implementations anything at all. I'm not trying to make an ideological stand -- or, at least, not a particularly controversial one. I put far too much stress on syntax in my last message. The more important objection to 'new Function' concerns its semantics. The Function constructor has an awkward status in the language. Most objects are constructed by calling a constructor or by using a literal syntax, the semantics of which can be specified in terms of constructor call + accessor calls. E.g.: [a, b] has the same semantics as let (t = new Array()) (t[0] = a, t[1] = b, t) ...whereas you cannot, in the general case, *locally* rewrite a function expression in terms of 'new Function.' Also, there's the point I did raise in my last message: while you can subclass function, there doesn't appear to be much point in actually doing so -- precisely because most function construction does not go through the Function constructor. The reality is that 'new Function' and 'arguments' are available in all implementations, they are in wide-spread use, and their use will be propagated as long as implementations support them. Maybe if they are deprecated in the spec their use will see some decline; maybe ditto if better, alternative features are added to the language. I have more faith in the latter than in the former. These options aren't mutually exclusive, and I don't see the harm in deprecating this stuff. Now, if someone will offer a defense of 'new Function,' that's a different story. I am not trying to be controversial here. I don't really care about 'new Function' as it's just another API to functionality that will exist anyway, and 'new Function' is comparatively clean -- I don't agree that it is significantly less sane than global.eval. But I and others do care about 'arguments', so we have rest arguments and 'this function'; we do care about the operator form of 'eval', so there's been some discussion about whether to simply outlaw its use inside classes. These are better ways to make progress than paper deprecation, IMO. No question that 'arguments' is a more important issue. -Jon --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
The latter. It is weird, I agree. But the enumerator can easily be customized, so I want the default enumerator be as non-magical as possible - and therefore, as simple as possible. In fact, I'm a bit bothered that propertyIsEnumerable is a method of Object yet can be rendered useless when changing the enumerator - along this line of reasoning, one would think that such a specific method shouldn't be a method of Object at all, but rather the enumerator itself. So how would you go about enumerating the properties of an arbitrary dynamic object, whose properties could be in namespaces? Yeah, I vaguely remember some discussion concerning multiple namespaces per property a long time ago (maybe a year ago). It was rejected probably due to complexity. Not being able to combine them effectively makes many of the initial proposal's use-cases useless, because two use-cases may arise simultaneously when integrating two codebases, and be irreparably conflicting. Peter ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Map
-Original Message- From: Erik Arvidsson [mailto:[EMAIL PROTECTED] Sent: 11. mars 2008 11:25 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: ES4 draft: Map I still find this bad UI for people that do not use types, and remember types are supposed to be optional. I agree, default type parameters would be nice. Currently there is no way to create a map without providing types (not entirely true, see below). Neither of the following works as we have speced it today: var m = new Map; var m2 = Map(); The latter should work, thanks for catching the bug. the closest thing would be to do var m3 = Map({}); but that is pretty ugly. And very likely it will become illegal, since we think that class statics will only be available on instantiated classes (unlike now, when they are available only on uninstantiated classes), so you'd have to write var m3 = Map.string,int() or worse. What I would like is that the type params are optional and if left out treated as the any type. Another simpler option is to make the argument to meta::invoke to be optional and if left out an empty Map.EnumerableId, * is returned. We discussed default type parameters a few times, but it was always thrown out. I think the chief reason for that was that we always tried to make it work in the context of Array (so that Array could be both what it is in ES3 and something typed besides). That was a non-starter, and rightly so. In any case, this was the sketch we were toying with: class Map.K=EnumerableId, V=* { } One issue that I remember was the question of the meaning of an expression that names the type without parameters. For example, if we want new Map() to mean new Map.EnumerableId,*() (and this is what you're asking for) then what do we mean when we say simply Map ? Do we mean to pass the uninstantiated class object around or do we mean to instantiate it with the default parameters? The former is the obvious interpretation, but then what about x = Map new x() Does that instantiate, and so on? No doubt all these details could be resolved, we just thought that some things should be postponed to ES5. --lars 2008/3/11 Lars Hansen [EMAIL PROTECTED]: Draft 3 enclosed. Changelog near the top; the only significant change is fixing the bug Erik noted in the prototype get and put methods. Please note one open issue; the current design is probably OK but I would appreciate comments. --lars -Original Message- From: Lars Hansen Sent: 3. mars 2008 02:03 To: Lars Hansen; es4-discuss@mozilla.org Subject: RE: ES4 draft: Map Draft 2 enclosed (changelog near the top). --lars -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Lars Hansen Sent: 29. februar 2008 11:34To: es4-discuss@mozilla.org Subject: ES4 draft: Map I'm enclosing the draft for the Map class. Please comment. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss -- erik ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
On Mar 11, 2008, at 1:14 AM, Maciej Stachowiak wrote: The optional second argument to make propertyIsEnumerable a setter has some practical problems: 1) It violates the very strong norm that getter and setter functions are separate and have their own different arguments. It will make the feature harder to use and code using it harder to understand, to some extent. 2) It makes it impossible to feature test for the ability to disable enumerability, compared to a separate setter. I agree with these points. Against the argument that it is too risky compatibility-wise to add a new method to the object prototype (apparently the only reason things were done), No, that was not the only reason. The other reason (it may be a bad reason, but I pointed it out in an earlier message to make it apparent): so calls passing two arguments would not cause ES3 implementations to fail as would undetected calls to a new method. But I agree that the numbered points you make are sufficient to reconsider the two-argument proposal that was accepted a while go. Just for the es4-discuss list's information, I want to provide some historical context. the working group at that time had many large and small issues to grapple with, so we did not dedicate too much time to the Prototype Ajax library problem (wanting to set DontEnum on user- defined properties). We were not so much in favor of the _de minimus_ second argument idea that was quickly settled on, as we were opposed to adding another method with a plain name to Object.prototype. And even that wasn't a strong objection, in light of namespaces (more below on that). This was at the time very much small potatoes, which I for one am happy to revisit (I've already sketched a namespace-based alternative). It should not be used to impeach the entirely of the group's work. I propose that it is overblown. Mozilla has defined new methods and properties on all objects. In 1998 or 1999, we added meta methods and properties, distinguished (after Python) by leading and trailing double underscores. We haven't tried adding a plainly named property to Object.prototype in quite a while. We have copied some in Safari and seen no web compatibility issues, I assume Mozilla has not had any as well. Specifically, I am thinking of __defineSetter__, __defineGetter__, __lookupSetter__, __lookupGetter__, and __proto__. These are all metaprogramming hooks, but so arguably is __setPropertyIsEnumerable__ -- so I agree with your reasoning here. Has any study been done on how many sites currently make use of the property names of a likely setter for propertyIsEnumerable? We have not crawled the web looking for plain-named methods, but we have spidered for other patterns we proposed to change incompatibly, and the results are not decisive. For example, looking for attempts to rebind standard constructors found only a dead MSN .js file rebinding Error, but when we tried in Firefox 3 beta 2 to lock down the global bindings for Date, etc., we found many sites and web apps breaking. This is a different case, of course, but my point stands: searching the web is informative, but not decisive. Debate is only good. I merely pointed out the obvious thing, namely that until there is an alternative proposal written up to deal with this issue, the current design stands unless the WG, as a group, decides to just get rid of it (leaving the problem it was designed to solve solution-less). Surely reviewing this spec is the appropriate time to revisit this issue. Yes, and this list is the right place. It's pretty clear Lars agrees, and nothing he wrote cited above contradicts it. So let's discuss more. I'd like to propose the following three alternatives to the current proposal: 1) Remove the feature entirely from ES4 (as part of the judicious feature cuts process) until a more appropriate syntax is found 2) Replace two-argument form of propertyIsEnumerable with setPropertyIsEnumerable 3) Replace two-argument form of propertyIsEnumerable with __setPropertyIsEnumerable__ I think each of these options is so trivial as to not require a lengthy write-up. What is the process for the WG deciding whether to make one of these changes, or something else? Arguing here in es4-discuss might be enough, if the argument makes progress and the participants reach a consensus. I like the idea of making non-public-namespaced properties be not-enumerable and getting rid of DontEnum. We've talked loosely about it for a while. But it's remained loose talk, it has never made it to the stage where it is a coherent proposal. I don't like syntax-based alternatives since they cannot be made to degrade gracefully in ES3 UAs. I think that's a good point too, since as noted above it was one of the two reasons for the lame-duck two-argument proposal we've accepted. /be ___ Es4-discuss
Controlling DontEnum (was: ES4 draft: Object)
Here is a modest proposal based on Mark's and Maciej's messages: Goal: A detectable method requiring no new syntax to set the DontEnum attribute on an existing property. Goal: Avoid breaking any existing ES3 code that might depend on a plainly named method not being predefined. Anti-goal: The ability to turn off DontEnum where it has been set on predefined properties. Proposal: Add Object.prototype.__makePropertyNonEnumerable__(name), defined as if by: Object.prototype.__makePropertyNonEnumerable__ = function (name) { if (this has a direct property identified by name) { set the DontEnum attribute for this[name]; return true; } return false; } Note that if this has a direct property identified by name, but this [name] already has the DontEnum attribute, then the function returns true. The specification with prose of setting DontEnum would occur redundantly in this case, but it is not observable in ES3 or ES4 as proposed, so for simplicity I left out a test of DontEnum to avoid a redundant set. The use of a __-bracketed name satisfies the second goal, but it would be a problem for Caja or similar. This is an issue where I would appreciate Mark's feedback. Comments welcome. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
The use of a __-bracketed name satisfies the second goal, but it would be a problem for Caja or similar. This is an issue where I would appreciate Mark's feedback. I can't speak for Mark, but it seems like it might actually be beneficial that unsecured code (regular ES4) would have the ability to set DontEnum and secured code (Secure ES, Cajoled Caja, ADsafe, or whatever) wouldn't have that capability. +1 Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
If there is no method to make a property enumerable again (which I now agree is better not to exist) it feels somehow bad to be able to make a property non-enumerable after its declaration. Consider: let a = {b:2, c:3}; for(let s in a){ print(s); // b, c } a.__makePropertyNonEnumerable__(b); for(let s in a){ print(s); // c } It seems wrong that the code should run once one way, and then another way, but there be no way back. It's not so much that I think there should be a way back, but I'd rather that than this, which I consider a weird situation. Also the double underscores are really ugly syntax... Perhaps you can't achieve this without new syntax, but the declarative approach seems cleanest and not prone to this sort of anomaly. If new syntax could be considered, an |enumerable| attribute, complemented by a |!enumerable| attribute seems very clean. type T = {enumerable a:int, b:int}; let t:T = {a:1, b:2}:T; // a is enumerable, b is not let s = {a:1, !enumerable b:1}; // a is enumerable, b is not class C { enumerable var p; } Peter On Tue, Mar 11, 2008 at 7:45 PM, Brendan Eich [EMAIL PROTECTED] wrote: Here is a modest proposal based on Mark's and Maciej's messages: Goal: A detectable method requiring no new syntax to set the DontEnum attribute on an existing property. Goal: Avoid breaking any existing ES3 code that might depend on a plainly named method not being predefined. Anti-goal: The ability to turn off DontEnum where it has been set on predefined properties. Proposal: Add Object.prototype.__makePropertyNonEnumerable__(name), defined as if by: Object.prototype.__makePropertyNonEnumerable__ = function (name) { if (this has a direct property identified by name) { set the DontEnum attribute for this[name]; return true; } return false; } Note that if this has a direct property identified by name, but this [name] already has the DontEnum attribute, then the function returns true. The specification with prose of setting DontEnum would occur redundantly in this case, but it is not observable in ES3 or ES4 as proposed, so for simplicity I left out a test of DontEnum to avoid a redundant set. The use of a __-bracketed name satisfies the second goal, but it would be a problem for Caja or similar. This is an issue where I would appreciate Mark's feedback. Comments welcome. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On Tue, Mar 11, 2008 at 2:32 PM, Peter Hall [EMAIL PROTECTED] wrote: Perhaps you can't achieve this without new syntax, but the declarative approach seems cleanest and not prone to this sort of anomaly. If new syntax could be considered, an |enumerable| attribute, complemented by a |!enumerable| attribute seems very clean. type T = {enumerable a:int, b:int}; let t:T = {a:1, b:2}:T; // a is enumerable, b is not let s = {a:1, !enumerable b:1}; // a is enumerable, b is not class C { enumerable var p; } Hi Peter, I like the idea of a more declarative approach as well, if one can be found. However, this proposal has two problems from our perspective: * It introduces new syntax, as you mention. * It depends on the proposed ES4 type system which is unacceptable to the ES3.1 effort. ES3.1 needs a way to express these integrity constraints in the absence of ES4 types. -- Text by me above is hereby placed in the public domain Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
[+google-caja-discuss] On Tue, Mar 11, 2008 at 12:53 PM, Kris Zyp [EMAIL PROTECTED] wrote: The use of a __-bracketed name satisfies the second goal, but it would be a problem for Caja or similar. This is an issue where I would appreciate Mark's feedback. I can't speak for Mark, but it seems like it might actually be beneficial that unsecured code (regular ES4) would have the ability to set DontEnum and secured code (Secure ES, Cajoled Caja, ADsafe, or whatever) wouldn't have that capability. +1 Kris I think Kris is right, but I'm not yet sure. I've forwarded this thread to [EMAIL PROTECTED] for discussion of what would be the best ways to support Caja's needs. Nono of these issues are specific to DontEnum. They affect all other integrity restriction attributes, such as ReadOnly, DontDelete, and fixture (i.e., non-dynamic). -- Text by me above is hereby placed in the public domain Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
It seems wrong that the code should run once one way, and then another way, but there be no way back. It's not so much that I think there should be a way back, but I'd rather that than this, which I consider a weird situation. Declarative is nice, but as mentioned before, it ignores one of the primary use cases: addition of non-enumerable properties to built-ins (by libraries, primarily). Also the double underscores are really ugly syntax... That's the idea, no one is currently using such an ugly method ;). Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On Mar 11, 2008, at 5:16 PM, Kris Zyp wrote: Declarative is nice, but as mentioned before, it ignores one of the primary use cases: addition of non-enumerable properties to built-ins (by libraries, primarily). I've read mention of the weirdness of the timing window between the property definition and it's marking as non-enumerable. That combined with the above observation makes me wonder if this should really be obj.__setNonEnumerableProperty__(name, value); ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On Mar 11, 2008, at 3:21 PM, Neil Mix wrote: On Mar 11, 2008, at 5:16 PM, Kris Zyp wrote: Declarative is nice, but as mentioned before, it ignores one of the primary use cases: addition of non-enumerable properties to built-ins (by libraries, primarily). I've read mention of the weirdness of the timing window between the property definition and it's marking as non-enumerable. That combined with the above observation makes me wonder if this should really be obj.__setNonEnumerableProperty__(name, value); +1 /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
I've read mention of the weirdness of the timing window between the property definition and it's marking as non-enumerable. That combined with the above observation makes me wonder if this should really be obj.__setNonEnumerableProperty__(name, value); +1 I like it too. Any chance that by setting the attribute at the same time of setting the property value, we could resurrect the possibility of setting other attributes as well (with a single method): Object.prototype.__setPropertyWithAttributes__(name, value, dontEnum: boolean, readOnly: boolean, dontDelete: boolean); And various proposed syntax like: obj = {dontenum a: 1, const b: 2, var c: 3}; could be written: obj = {}; obj.__setPropertyWithAttributes__(a,1,true); // property a is not enumerable obj.__setPropertyWithAttributes__(b,2,false,true); // property b is readonly obj.__setPropertyWithAttributes__(c,3,false,false,true); // propery c is permanent I wonder if readonly and dontdelete are other attributes where there might be benefits derived from trusted code (regular ES3/4) being able to control, and untrusted code (ses, caja) not being able to control. I can't think of what those benefits might be, maybe another question for Mark or Doug to think on. Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss