RE: ES4 draft last call: line continuation in string and regexliterals
OK. I'll make a brief annotation on the proposal page about left-to-right interpretation so that we can move on and say that we've accepted the proposal; when the grammar is later written up there should be no room for confusion about what the intent of this proposal was. --lars -Original Message- From: Waldemar Horwat [mailto:[EMAIL PROTECTED] Sent: 12. mars 2008 18:57 To: Jeff Dyer Cc: Lars Hansen; es4-discuss Discuss Subject: Re: ES4 draft last call: line continuation in string and regexliterals Jeff Dyer wrote: Waldemar, can you suggest a fix? The correct fix is to add the relevant productions to the lexer grammar. It's fairly straightforward in the string literal grammar. It's painful in the regexp grammar. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Brendan Eich wrote: If we end up making all namespaced properties non-enumerable, then we may want a property iterator that returns the names of all properties in a given object. Even if this is not in the standard, it's likely to be an extension. Or it could be added in the future. Absolutely. In fact, I thought there was already an iterator that yields all properties regardless of enumerability, just that this iterator would not be the default iterator for objects. If it's not in ES4, it should definitely be there because it's essential for those that want to customize enumerability. The question of whether ES3+4 mixtures might not want enumerable ES3 properties to appear to be in a predefined-in-ES4 namespace seems to me worth considering, at the limit as a future-proofing step. What do you mean by ES3+4 mixture - how would you tell that one part is ES3 and another part ES4, or how a program is pure ES4? -Yuh-Ruey Chen ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Peter Hall wrote: 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? I thought there was an iterator that would enumerate all properties regardless of enumerability (including those in other namespaces), but apparently not. There should be such an iterator though. 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 What initial proposal are you talking about? -Yuh-Ruey ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
the frequency of use). Thus on Object.prototype and as an intrinsic propety on Object instances: function __createProperty__(name:EnumerableId, dontEnum:boolean=false, dontDelete:boolean=false, readOnly:boolean=false): void I thought that this only made sense in conjunction with Neil's suggestion of providing the value at the same time. If you create a readonly property, how are you supposed to set the value otherwise? Shouldn't it be: function __createProperty__(name:EnumerableId, value, dontEnum:boolean=false, dontDelete:boolean=false, readOnly:boolean=false): void And if readOnly implied dontDelete, I would have guessed readOnly to be a little more frequent than dontDelete, but of course that is just a guess. Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Function
Why doesn't Function have something like apply that does the same as in a new expression, i.e. allocate-init-and-apply? To put it another way: given arguments in an array, I want to write: F.thisThing(args) and have it mean the same as new F(args[0], args[1], ... args[n-1]) Or is what happens behind the veil of object creation detailed enough that I can write a facsimile of it with apply? I guess something like: var x = {}; x.prototype = F.prototype; x = F.apply(x, args) || x; But why force me to guess? No doubt I am wrong. Dominic On Mon, Mar 10, 2008 at 7:38 PM, Jon Zeppieri [EMAIL PROTECTED] wrote: 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(). -Jon ___ 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: Function
Hi Dustin, Well it does, apparently it was called the splat operator, which (to me) sounds a better than spread. I think it works like:- var args = [12, true]; new C(...args); function C( count, isSemiAnnual) { } - Maybe one of guys writing the specs can comment on that. It can be hacked in ES3:- /** * @param {Function} fun constructor to be invoked. * @param {Array} args arguments to pass to the constructor. * Instantiates a constructor and uses apply(). */ newApply : function(fun, args) { if(arguments.length === 0) return; var f = arguments.callee, i; f.prototype = fun.prototype;// Copy prototype. f.prototype.constructor = fun; i = new f; fun.apply(i, args); // Apply the original constructor. return i; }, - from http://dhtmlkitchen.com/ape/build/APE.js Garrett On Thu, Mar 13, 2008 at 10:48 AM, Dominic Cooney [EMAIL PROTECTED] wrote: Why doesn't Function have something like apply that does the same as in a new expression, i.e. allocate-init-and-apply? To put it another way: given arguments in an array, I want to write: F.thisThing(args) and have it mean the same as new F(args[0], args[1], ... args[n-1]) Or is what happens behind the veil of object creation detailed enough that I can write a facsimile of it with apply? I guess something like: var x = {}; x.prototype = F.prototype; x = F.apply(x, args) || x; But why force me to guess? No doubt I am wrong. Dominic On Mon, Mar 10, 2008 at 7:38 PM, Jon Zeppieri [EMAIL PROTECTED] wrote: 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(). -Jon ___ 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 ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Function
Neat! Thanks for the link. Dominic On Thu, Mar 13, 2008 at 10:58 AM, Jon Zeppieri [EMAIL PROTECTED] wrote: On Thu, Mar 13, 2008 at 1:48 PM, Dominic Cooney [EMAIL PROTECTED] wrote: Why doesn't Function have something like apply that does the same as in a new expression, i.e. allocate-init-and-apply? To put it another way: given arguments in an array, I want to write: F.thisThing(args) and have it mean the same as new F(args[0], args[1], ... args[n-1]) How about the proposed spread/spat(...) operator : new F(...args) http://bugs.ecmascript.org/ticket/357 -Jon ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Yuh-Ruey Chen wrote: Brendan Eich wrote: If we end up making all namespaced properties non-enumerable, then we may want a property iterator that returns the names of all properties in a given object. Even if this is not in the standard, it's likely to be an extension. Or it could be added in the future. Absolutely. In fact, I thought there was already an iterator that yields all properties regardless of enumerability, just that this iterator would not be the default iterator for objects. If it's not in ES4, it should definitely be there because it's essential for those that want to customize enumerability. As was discussed before, the language cannot have such an iterator. Were this iterator to exist, an attacker could use it to discover hidden properties of objects, get access to private and other restricted namespaces, alter private state, and break through abstraction barriers. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
Is there enough value in complicating matters by adding the ability to set dontDelete and readOnly? You can create non-deletable properties by using a class or record type, and you can create read-only properties by adding a get function without a corresponding set... Are there any use cases where these solutions won't cover it? Peter ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Controlling DontEnum (was: ES4 draft: Object)
-Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Peter Hall Sent: 13. mars 2008 12:38 To: Lars Hansen Cc: Kris Zyp; es4-discuss@mozilla.org Subject: Re: Controlling DontEnum (was: ES4 draft: Object) Is there enough value in complicating matters by adding the ability to set dontDelete and readOnly? You can create non-deletable properties by using a class or record type, and you can create read-only properties by adding a get function without a corresponding set... Are there any use cases where these solutions won't cover it? Depends on your point of view. I wrote a paper on evolutionary programming in ES4 (available from ecmascript.org), which demonstrates a progression from ES3 style code to ES4 style code with various stops along the way. One of the holes in that story is that it's not possible to make the properties introduced in a function-style constructor anything but enumerable, deletable, and writable: function Server(host) { this.host = host this.database = [] } Both these fields are supposed to be constant, and there's no reason for them to be enumerable. The paper shows how you can use a user-defined namespace to make them inaccessible (non-public namespaced properties are not enumerated, and if the namespace is hidden from client code -- not always easy -- then the field can't be accessed or deleted), but it's clearly a bit of a hack in that it is a consequence of other design choices in the language. The direct approach would set the properties explicitly: function Server(host) { this.__createProperty__(host, host, true, true, true); this.__createProperty__(database, [], true, true, true); } So this is a use case if you believe that relatively fine-grained evolution from ES3 style to ES4 style is a feature of the language. (I do.) There are declarative ways of solving the problem -- essentially annotating the function, saying this is a constructor function and the fields named such and so are going to have these and those attributes, but they add yet more features to an already fairly feature-laden language. (One proposal goes like this: constructor function Server(host) : { const host: string, const database: array } { this.host = host this.database = [] } and it's not all that heavyweight, but it's a new, ad hoc feature all the same.) I'm mostly agnostic about __createProperty__ being able to set DontDelete and ReadOnly; DontEnum is the really important one. At the same time, it seems silly not to just solve the general problem when we have a chance. Just because you can't enumerate a property doesn't mean that you -- or a library you import -- can't accidentally -- or maliciously -- overwrite it. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
set dontDelete and readOnly? You can create non-deletable properties by using a class or record type They can't be added after an object is created. and you can create read-only properties by adding a get function without a corresponding set... Unless behavior is different than ES3, setters (and lack thereof) are not dontDelete, therefore still easily mutated: obj = {get foo() { return 'hi' }} Object foo=hi obj.foo hi delete obj.foo true obj.foo = 'goodbye' goodbye obj.foo goodbye ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On 13/03/2008, Lars Hansen [EMAIL PROTECTED] wrote: Since our method is creating a new property and not setting one, I suggest __createProperty__ as the most appropriate name, so I'm going to use that below. Sounds perfectly reasonable to me. I still think it may be right that properties in non-public namespaces should not be enumerated, but I also think that's orthogonal to the discussion that's going on here, about dynamic properties and their attributes. We've pretty much decided (ticket #233 has some of the discussion) that for future compatibility there ought to be a difference between fixture properties and DontDelete dynamic properties. So dynamic properties have at least one attribute bit like they do in ES3 (for deletability). Consequently, they might as well have all the ES3 bits: for enumerability and writability. For ES4, shouldn't this function also take a type binding? Ergo, let's assume that we are not finessing more than we have to, and dynamic properties have all these attribute bits. I don't know why __createProperty__ should not be able to set all of these. Neither can I. (They're not independent, ReadOnly implies DontDelete.) __createProperty__ should throw an exception (TypeError?) if the property already exists on the object or would shadow a ReadOnly property, a la [[CanPut]], or if the object is not dynamic. It should probably throw an exception if its arguments are not consistent (ReadOnly !DontDelete). If ReadOnly is specified, is there even a reason to look at DontDelete? Pesonally I like the strings approach, but the only interface among these four that has good compile-time checking is the first one, so I'm going to propose that we use that one, with dontEnum as the first flag, dontDelete as the second, and readOnly as the third (based on a guess about the frequency of use). Thus on Object.prototype and as an intrinsic propety on Object instances: function __createProperty__(name:EnumerableId, dontEnum:boolean=false, dontDelete:boolean=false, readOnly:boolean=false): void ReadOnly would need to be instanciated at the same time, no? And you probably want to be able to specify a type binding for ES4. * The above does not preclude complementary declarative mechanisms in ES4 (but not in ES3.1 obviously) Good to hear, because I still want to see something that can be used in object literals and property declarations. -- David liorean Andersson ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On Mar 13, 2008, at 11:47 AM, Lars Hansen wrote: function __createProperty__(name:EnumerableId, dontEnum:boolean=false, dontDelete:boolean=false, readOnly:boolean=false): void I like where this is going. May I (in addition to Kris's suggestion for adding a value parameter) kindly nit on the parameter names? function __createProperty__(name:EnumerableId, value:*, enumerable:boolean=true, removable:boolean=true, writable:boolean=true): void Or some reasonable variant therein? I have no strong opinions on the form the parameters eventually take, but trying to parse what dontenum=false means tends to give me headaches. ;) ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Controlling DontEnum (was: ES4 draft: Object)
-Original Message- From: Neil Mix [mailto:[EMAIL PROTECTED] Sent: 13. mars 2008 14:47 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: Controlling DontEnum (was: ES4 draft: Object) On Mar 13, 2008, at 11:47 AM, Lars Hansen wrote: function __createProperty__(name:EnumerableId, dontEnum:boolean=false, dontDelete:boolean=false, readOnly:boolean=false): void I like where this is going. May I (in addition to Kris's suggestion for adding a value parameter) kindly nit on the parameter names? function __createProperty__(name:EnumerableId, value:*, enumerable:boolean=true, removable:boolean=true, writable:boolean=true): void Or some reasonable variant therein? I have no strong opinions on the form the parameters eventually take, but trying to parse what dontenum=false means tends to give me headaches. ;) Well, it had to come up at some point ;) I suspect what you're proposing is the better UI. Obviously JS1/ES3 shows a bias for enumerable, removable, writable properties -- the attribute bits flag exceptions from the general rule. The more general design has attribute bits that simply control those property aspects, and the less biased names feel like an improvement. Brendan, opinions? --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
On Mar 13, 2008, at 2:07 PM, Lars Hansen wrote: -Original Message- From: Neil Mix [mailto:[EMAIL PROTECTED] function __createProperty__(name:EnumerableId, value:*, enumerable:boolean=true, removable:boolean=true, writable:boolean=true): void Or some reasonable variant therein? I have no strong opinions on the form the parameters eventually take, but trying to parse what dontenum=false means tends to give me headaches. ;) Well, it had to come up at some point ;) I suspect what you're proposing is the better UI. Obviously JS1/ES3 shows a bias for enumerable, removable, writable properties -- the attribute bits flag exceptions from the general rule. The more general design has attribute bits that simply control those property aspects, and the less biased names feel like an improvement. Brendan, opinions? Neil's names are much better. For the record, I didn't come up with DontDelete and DontEnum in ES1 daze. SpiderMonkey internally uses PERMANENT for the former and ENUMERATE for the inverse of the latter (since the native-biased API finds callers wanting enumerable pre- defined properties to be the exception). /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
FWIW, AS3, which doesn't have iterators, enumerates only the expando properties of an object. This was in part because we didn't have (qualified) name objects that could be enumerated, and in part because of it being complicated to determine the set of names that could be safely exposed (e.g. all the names in open namespaces, all the public names regardless of their current visibility, etc). IOW, we punted. Jd On 3/13/08 11:29 AM, Waldemar Horwat wrote: Yuh-Ruey Chen wrote: Brendan Eich wrote: If we end up making all namespaced properties non-enumerable, then we may want a property iterator that returns the names of all properties in a given object. Even if this is not in the standard, it's likely to be an extension. Or it could be added in the future. Absolutely. In fact, I thought there was already an iterator that yields all properties regardless of enumerability, just that this iterator would not be the default iterator for objects. If it's not in ES4, it should definitely be there because it's essential for those that want to customize enumerability. As was discussed before, the language cannot have such an iterator. Were this iterator to exist, an attacker could use it to discover hidden properties of objects, get access to private and other restricted namespaces, alter private state, and break through abstraction barriers. Waldemar ___ 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: Function
I agree with Lars on this issue for exactly the same reasons as what he stated. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Function
Here are my comments on this section: static public function apply(fn /*: function*/, thisArg: Object=null, argArray: Object=null) static public function bind(method /*: function*/, thisObj: Object=null, ...args) static public function call(fn /*: function*/, thisObj: Object=null, ...args) prototype function apply(/*this: function, */ thisArg=undefined, argArray=undefined) prototype function bind(/*this: function, */ thisObj=undefined, ...args) prototype function call(/*this: function, */ thisObj=undefined, ...args) What does /*: function*/ mean here? Are these arguments required to have the function type or not? Although apply is redundant in the presence of the splat operator, I see no harm in keeping it for consistency with ES3. *Implementation* The implementation of the meta function |invoke| is implementation-dependent. Omit the implementation section altogether. Saying implementation-dependent is misleading here, as its behavior should not be implementation-dependent. intrinsic function apply(thisArg: Object=null, argArray: Object=null) Function.apply(this, thisArg, argArray); intrinsic function bind(thisObj: Object=null, ...args) Function.helper::bind(this, thisObj, args); intrinsic function call(thisObj: Object=null, ...args) Function.apply(this, thisObj, args); The middle one is not like the other two. Hmmm another use case for the splat operator. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ==, ===, and Name/Namspace (was: RE: ES4 draft: Name)
On Mar 13, 2008, at 3:39 PM, Lars Hansen wrote: Firefox currently has that new Namespace (for E4X) produces a new object that is == to another namespace produced with the same string but not ===. From looking at the code, ActionScript3 does the same thing. Ditto for names (QName in E4X, not Name). All per ECMA-357, the E4X spec. But in Firefox, Namespace is dynamic (not so in ActionScript) so == but not === makes sense; if Namespace is not dynamic in ES4 we can get away with the changed behavior. Still, might pose a backward compatibility risk. On the third hand, E4X is not used on the web in general, only in apps targeted to FF and AS3. This is a non-issue, AFAIK. See my earlier post on E4X. No interoperable web content uses E4X, and the Firefox-hosted E4X implementation could be versioned to support the old way, in the worst-case -- if there were significant Firefox-only content whose owners were unwilling or unable to upgrade their code. I doubt that any such code exists, but the approach I would favor, given an incompatible but better ES4 spec, would be to try to break support for such code early during a major Mozilla milestone cycle, to smoke out any customers and then persuade them to revise their to satisfy ES4's rules. I know of no E4X code that depends on current identity and mutability rules. Zwetan (for AS3), Jeff Walden, and others may have thoughts, so thanks for posting this to the list. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Name
-Original Message- From: Waldemar Horwat [mailto:[EMAIL PROTECTED] Sent: 11. mars 2008 19:17 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: ES4 draft: Name public function Name(a, b=undefined) static meta function invoke(a, b=undefined): Name It would be help the spec's readability if the formal parameters had more descriptive names than a and b. Here it's not clear which one is which. new Name( a, b=... ) Ah, I see why the formal parameters were called a and b. I think that the design is too weird though -- one of the parameters ought to be a name and the other one ought to be an optional namespace. If I have the following: var ns:Namespace = ... var id:string = ... and don't know anything about the ...'s, then I currently can't just call: n = new Name(ns, id); Instead, I must use: if (ns !== null) n = new Name(ns, id); else n = new Name(id, undefined); The reason is that, under the current specification, new Name(null, x) requires x to be undefined (null is a Name). Maybe that would be the better bug to fix -- allowing null explicitly as a namespace to cover that case. [I'm assuming that the expression null is T is true for any nullable type T. If that's not the case, then there are different issues here.] That is the case. My preference would be to always have the identifier as the first parameter and the namespace as the optional second parameter. This will avoid hassles with values like null that can be either a namespace or a name. As Igor pointed out that is incompatible with E4X, but that's hardly a good reason. (What we could be looking at here is an artifact of specifying the language entirely with ES code, which is too weak to express the idea of multiple interfaces to a function.) I think it's desirable to keep the current order for compatibility with existing designs (it's not like E4X sees no use). I'll try to clean up the constructor interface to be more robust / friendly. Is there a compelling reason to treat numbers between 0 and 2^32-1 specially here? It adds complexity and I'm not sure what it's for. It's because of EnumerableId, which treats values in that range specially. The thought behind the code the way it's written is that if one wishes to construct a Name, then the parameters must conform to those of EnumerableId: Name, string, or uint. Otherwise there's a type error. However, this is a little too hard-nosed, and EnumerableId is changing anyway (if int and uint go away, as I expect they will), so I'll probably remove the checking here, and just add conversion to string for any argument at all. Creating the ambiguity of whether Name values appear to be interned is likely to lead to trouble. Yes. See separate thread that I spun off this one. The |Name| constructor is implementation-dependent. What implementation-dependent behavior does it have, other than the above? Shouldn't it be normatively specified in the spec? It's implementation-defined whether the result of this is true: x = new Name(a,b) y = new Name(a,b) x === y but as discussed in that other thread, that problem needs to be solved, so the problem with implementation-defined here should go away. What is analyzeArgs? It's defined but not used here. The helper function analyzeArgs, called by the Name constructor, takes the two values a and b that were passed to the Name constructor and returns an object containing a qualifier in the form of a namespace (which may be null) and an identifier in the form of a string. The qualifier and identifier are used to create the Name object. Why does valueOf do a toString on the Name? Entirely because the original spec (on the wiki) required it. I suspect this is the wrong design (and I think even Brendan, who wrote it up, questioned it, because it's left as an open issue on the wiki); the ActionScript implementation of the E4X QName valueOf method returns 'this'; that is probably the right behavior here as well. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Namespace
-Original Message- From: Waldemar Horwat [mailto:[EMAIL PROTECTED] Sent: 12. mars 2008 18:54 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: ES4 draft: Namespace Here's my review of this section: Is null a valid value of the class Namespace? The description states that it is a final, non-dynamic, direct subclass of Object. I don't recall us ever discussing whether it is nullable or not. I have no strong opinions. There is a natural initializer value for Namespace, namely the compatibility namespace noNS (Jeff's writeup on these matters is forthcoming). So it could be non-nullable. Opinions from others are solicited... (Maybe this is addressed somewhere else, but I haven't seen it yet.) What do ==, , etc. do on Namespaces? Can I create a Map with Namespace as the key? As written up elsewhere, == and === probably ought to compare two Namespace objects created from the same string [through the use of the syntax namespace ns = mystring since there's no public constructor for Namespace] as equal. The natural behavior on etc would be as in ES3, ie, if valueOf on namespace returns this, as is most natural, then the toString() operator ends up being called, and the string names of the namespaces would be compared. Since the string representation is not specified, there is no specified ordering, but unless the implementation randomizes the output of toString, it should at least be dependable per-implementation. We could add a constraint to toString that says that if two namespaces N1 and N2 are created from strings S1 and S2 then N1 and N2 compare the same as S1 and S2. (For unforgeable namespaces -- those created without an explicit string name -- all bets are off, and no two are equal.) Can you create a Map with a namespace as a key? Presumably you mean with the default comparator and hashcode values. Yes, you can, because the spec for intrinsic::hashcode says that if v1 === v2 then we must have hashcode(v1) == hashcode(v2). (Incidentally this means that the implementation for hashcode must behave specially for Namespace and Name objects, once we settle the rules for ===.) --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Controlling DontEnum (was: ES4 draft: Object)
From: Neil Mix [mailto:[EMAIL PROTECTED] function __createProperty__(name:EnumerableId, value:*, enumerable:boolean=true, removable:boolean=true, writable:boolean=true): void On Thu, Mar 13, 2008 at 2:21 PM, Lars Hansen [EMAIL PROTECTED] wrote: This feels like convergence. I'll hook this into the RI and write it up in the next couple of days (barring further discussion, of course). I've been following this discussion and am quite happy with the overall direction! With these changes, ES3.1 should be a much friendlier base to subset into a Caja-like secure language. I'm hopeful that the resulting Caja-like language could safely be a much larger subset of ES3.1 than with current Caja vs ES3. I haven't yet thought these issues through well, but I'll offer some half baked suggestions for now. * As someone pointed out, using positional boolean flag parameters (..., false, true, false, ...) makes call-site readability too hard. This point was raised earlier but seems to have been dropped. IIRC, *all* the other parameterization suggestions had better call site readability. My favorite was simply a list of strings. OTOH, an advantage of the bit-mask approach is that sensible combinations of flags can be named and used simply. * I love Neil's suggestion of moving towards names saying what's allowed, rather than saying what's denied. I'd like to go further and suggest that __createProperty__ adopt the security best-practice of default-deny: When a property is explicitly created by this mechanism, only those operations that are explicitly allowed are permitted. All others attributes default to denying permission. To maintain compatibility of course, a property created the old fashioned way is implicitly fully permissive. * As Brendan reminds us, an erroneous __createProperty__ request should throw rather than failing silently or merely returning false. And a property access that fails because __createProperty__ did not allow it should also fail with a throw rather than silently. If we want to be strictly legacy compatible, then these throws should only happen for properties created with __createProperty__. Unfortunately, that means the semantics and implementations would need to distinguish, for example, legacy silently non-writable properties from new noisily non-writable properties. Can we instead specify that all these failures will be noisy? * Kris raises, we need to think about the interaction of these attributes with the notion of virtual properties defined using getters and setters. In particular, how does one create a non-removable virtual property? Should virtual properties have deleters in addition to getters and setters? * Might there be a sensible way to extend this mechanism to distinguish public from non-public properties? Based on the Caja design, might we adopt the rule that non-public property foo can only be addressed as this.foo or this['foo']. In other words, x.foo would only work is foo is public or unrestricted. The general approach we're following here for properties is: default to legacy-compatible overly-permissive behavior, but allow restriction to a fail-stop subset of this behavior. We should prefer to make expressible those restrictions that contribute to reasoning about integrity. (This is the right criteria whether on not one is trying to define a secure subset.) We should apply this general approach to objects as well as individual properties of objects. The most important, borrowed from ES4, is fixture vs dynamic. The Caja concept frozen then becomes exactly: fixture + all existing properties are non-writable and non-removable. We can even use this approach to clean up the main source of confusion in ES3 while preserving compatibility: What is the intended behavior of a function? It would be great to explicitly restrict a function to be callable only as a function, or only as a method, or only as a constructor, or only as a final constructor. An unrestricted function could continue to be callable in all these ways, as with ES3 functions. Moving these restrictions into the language would clear up a major source of vulnerability in the current Caja design: confused deputy dangers at the taming boundary between cajoled code and uncajoled code. If there's interest, I can expand on this issue. -- Cheers, --MarkM ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: Controlling DontEnum (was: ES4 draft: Object)
Speaking for myself, I should say from the outset that I am not in favor of taking this much further than it has been taken. The base language is ES3; we're trying to fix a small problem in that language in the cheapest possible way. I would rather backtrack to a solution that only fixes the DontEnum problem than to go forward into an elaborate design that attempts to fix various dodgy (or perceived as dodgy) features in the base language. Getters and setters should not be an issue. There is no way in ES4 to add a getter or setter to an object after the fact; getters and setters defined by an object initializer or in a class are fixtures and hence not deletable. (Some browsers have functions __defineGetter__ and __defineSetter__ that allow getters and setters to be added after the fact. Those are normally deletable. I suggest that these browsers expand their API to match that of __createProperty__.) --lars -Original Message- From: Mark S. Miller [mailto:[EMAIL PROTECTED] Sent: 13. mars 2008 17:22 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: Controlling DontEnum (was: ES4 draft: Object) From: Neil Mix [mailto:[EMAIL PROTECTED] function __createProperty__(name:EnumerableId, value:*, enumerable:boolean=true, removable:boolean=true, writable:boolean=true): void On Thu, Mar 13, 2008 at 2:21 PM, Lars Hansen [EMAIL PROTECTED] wrote: This feels like convergence. I'll hook this into the RI and write it up in the next couple of days (barring further discussion, of course). I've been following this discussion and am quite happy with the overall direction! With these changes, ES3.1 should be a much friendlier base to subset into a Caja-like secure language. I'm hopeful that the resulting Caja-like language could safely be a much larger subset of ES3.1 than with current Caja vs ES3. I haven't yet thought these issues through well, but I'll offer some half baked suggestions for now. * As someone pointed out, using positional boolean flag parameters (..., false, true, false, ...) makes call-site readability too hard. This point was raised earlier but seems to have been dropped. IIRC, *all* the other parameterization suggestions had better call site readability. My favorite was simply a list of strings. OTOH, an advantage of the bit-mask approach is that sensible combinations of flags can be named and used simply. * I love Neil's suggestion of moving towards names saying what's allowed, rather than saying what's denied. I'd like to go further and suggest that __createProperty__ adopt the security best-practice of default-deny: When a property is explicitly created by this mechanism, only those operations that are explicitly allowed are permitted. All others attributes default to denying permission. To maintain compatibility of course, a property created the old fashioned way is implicitly fully permissive. * As Brendan reminds us, an erroneous __createProperty__ request should throw rather than failing silently or merely returning false. And a property access that fails because __createProperty__ did not allow it should also fail with a throw rather than silently. If we want to be strictly legacy compatible, then these throws should only happen for properties created with __createProperty__. Unfortunately, that means the semantics and implementations would need to distinguish, for example, legacy silently non-writable properties from new noisily non-writable properties. Can we instead specify that all these failures will be noisy? * Kris raises, we need to think about the interaction of these attributes with the notion of virtual properties defined using getters and setters. In particular, how does one create a non-removable virtual property? Should virtual properties have deleters in addition to getters and setters? * Might there be a sensible way to extend this mechanism to distinguish public from non-public properties? Based on the Caja design, might we adopt the rule that non-public property foo can only be addressed as this.foo or this['foo']. In other words, x.foo would only work is foo is public or unrestricted. The general approach we're following here for properties is: default to legacy-compatible overly-permissive behavior, but allow restriction to a fail-stop subset of this behavior. We should prefer to make expressible those restrictions that contribute to reasoning about integrity. (This is the right criteria whether on not one is trying to define a secure subset.) We should apply this general approach to objects as well as individual properties of objects. The most important, borrowed from ES4, is fixture vs dynamic. The Caja concept frozen then becomes exactly: fixture + all existing properties are
RE: ES4 draft: Namespace
-Original Message- From: Waldemar Horwat [mailto:[EMAIL PROTECTED] Sent: 13. mars 2008 17:35 To: Lars Hansen Cc: es4-discuss@mozilla.org Subject: Re: ES4 draft: Namespace Lars Hansen wrote: The natural behavior on etc would be as in ES3, ie, if valueOf on namespace returns this, as is most natural, then the toString() operator ends up being called, and the string names of the namespaces would be compared. Since the string representation is not specified, there is no specified ordering, but unless the implementation randomizes the output of toString, it should at least be dependable per-implementation. We could add a constraint to toString that says that if two namespaces N1 and N2 are created from strings S1 and S2 then N1 and N2 compare the same as S1 and S2. (For unforgeable namespaces -- those created without an explicit string name -- all bets are off, and no two are equal.) Do we ever want to allow for any ordered containers analogous to C++'s map and set? If we were to define one then this could cause problems because an ordered container typically uses a less-than comparison function and considers x and y to be equal if neither x y nor y x holds. The actual order wouldn't matter, as long as two different namespaces wouldn't appear equal to each other in the above sense. I suppose we could simply state that two Namespaces yield the same string value iff they are ===, and that two invocations of toString() always yields the same string. Doesn't seem particularly onerous, it would probably be the case in most implementations anyhow. Then the same property for Name follows, since the string representation for a Name is defined to be either the identifier string if there's no Namespace part or the concatentation of the string representation of its Namespace, ::, and its identifier string otherwise. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
RE: ES4 draft: Namespace
I suppose we could simply state that two Namespaces yield the same string value iff they are ===, and that two invocations of toString() ... on the same Namespace object ... always yields the same string. Doesn't seem particularly onerous, it would probably be the case in most implementations anyhow. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Namespace
On Mar 13, 2008, at 4:43 PM, Lars Hansen wrote: I suppose we could simply state that two Namespaces yield the same string value iff they are ===, and that two invocations of toString() always yields the same string. Doesn't seem particularly onerous, it would probably be the case in most implementations anyhow. Let's specify this. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Name
On Mar 13, 2008, at 4:05 PM, Lars Hansen wrote: Why does valueOf do a toString on the Name? Entirely because the original spec (on the wiki) required it. I suspect this is the wrong design (and I think even Brendan, who wrote it up, questioned it, because it's left as an open issue on the wiki); The motivation there was to masquerade Name instances as strings to ES3 code that did for (var i in es4obj) { ... something assuming i is a string per ES3 here ... } It was necessary to override valueOf and toString, since when this proposal was written we believed that for-in loops over objects with namespaced properties should iterate i over Name objects where necessary to distinguish such properties from those identified by names in no namespace. We now are converging on hiding all namespaced properties from for-in enumeration, which is great. This change does not eliminate the need for Name objects in ES4, but it does mean that they may not need to masquerade as Strings via subtyping, for backward compatibility. So we should reconsider all the String hacks in Name.es in this light. the ActionScript implementation of the E4X QName valueOf method returns 'this'; that is probably the right behavior here as well. E4X's QName prototype valueOf is not specified, so that method is delegated to Object.prototype.valueOf, which returns this. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Deleting Getters and Setters (was Re: Controlling DontEnum...)
the fact; getters and setters defined by an object initializer or in a class are fixtures and hence not deletable. Really, that doesn't create a compatibility problem? I realize getters and setters aren't in ES3, but this seems like ES4 would be making a significant departure in behavior from the majority of current browser implementations of the same getter/setter syntax used by ES4: obj = {get foo() { return 'hi' }} Object foo=hi obj.foo hi delete obj.foo true obj.foo = 'goodbye' goodbye obj.foo goodbye With ES4, obj.foo would still be returning hi at the end? That sounds nice, but is there no fear of compatibility issues with that? Kris ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss