Re: block scope + direct non-strict eval
Btw, how does versioning work across eval? If I have a function body with an eval in it, will the body/eval run as in ES5 or as in ES6? Will that change if the body or the eval contain ES6 features? Will ES5/ES6 scripts be able to eval ES6/ES5 code? On this very thread we are hashing out how eval(let x = ...) interacts with the dynamic scope. Yes. Prompted by this, I am trying to understand how eval interacts with implicit versioning (no ES6 opt-in; btw, is the current state of discussion on opt-in summarized somewhere? I get lost in the threads here, and the wiki seems to predate this discussion). Both ES6 detection-by-feature-use and some ES6 features imply static checks, with a clear phase distinction between a static and a dynamic phase. eval ensures that ES is multi-staged (static/dynamic phase switches may occur nested, with the static phase of an eval occurring during the dynamic phase of the outer code that reaches that eval). ..[ points about direct vs indirect eval, strict vs non-strict code].. These precedents seem to suggest that the eval code language version will mostly be independent of versioning the outer code. Which seems sensible: the eval source is dynamic data, so cannot be used for static language version determination of outer code; and, on a larger scale, we want to be able to eval both ES5 and ES6 code. But, on a smaller scale, that means that eval can be used to embed ES5 features in ES6 code, and vice versa. Take this problematic example from the old no-opt-in thread: function f(a) { arguments[0]=2; return a } print(f(1)); //2 if ES5, 1 if ES6 There is nothing in the source file that implies which specification to apply so for backwards computability a browser must default to interpreting such program as a ES5 program. Anything syntactically unique to ES5 (eg, use of a with statment) or ES6 (eg, use rest or spread) would force one interpretation or another and embed the assignment in an eval: function f(a) { eval(arguments[0]=2); return a } print(f(1)); // 2 or 1? If the language version for eval code is independent of the context, we could have ES5 features used in the middle of ES6 code (so the result could be 2 even if f is part of ES6 code, unless such cross-version interactions are prevented by a dynamic barrier), and vice versa. If the language version for the eval code is not independent of the context, we have other problems. Claus ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block scope + direct non-strict eval
On Feb 1, 2012, at 7:08 AM, Claus Reinke wrote: Take this problematic example from the old no-opt-in thread: function f(a) { arguments[0]=2; return a } print(f(1)); //2 if ES5, 1 if ES6 There is nothing in the source file that implies which specification to apply so for backwards computability a browser must default to interpreting such program as a ES5 program. Anything syntactically unique to ES5 (eg, use of a with statment) or ES6 (eg, use rest or spread) would force one interpretation or another No, things changed at the last TC39 meeting. New features can generally be used anywhere. All code is non-strict unless it is either made strict using a use strict directive or contained within a module body (module bodes have an implicit use strict). The above code works the same in ES5 and ES6. If it is strict code it returns 1. If it is non-strict code it returns 2 and embed the assignment in an eval: function f(a) { eval(arguments[0]=2); return a } print(f(1)); // 2 or 1? same as above, same as ES5 If the language version for eval code is independent of the context, we could have ES5 features used in the middle of ES6 code (so the result could be 2 even if f is part of ES6 code, unless such cross-version interactions are prevented by a dynamic barrier), and vice versa. If the language version for the eval code is not independent of the context, we have other problems. Sticking with the strict/non-strict distinction, can you give an example where a ES6 feature within a strict direct eval within a non-strict code context would be problematic? Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: I18n - defining format() and compare() as getters to simplify usage
On Jan 31, 2012, at 4:23 PM, Nebojša Ćirić wrote: 31. јануар 2012. 15.50, Norbert Lindenberg ecmascr...@norbertlindenberg.com је написао/ла: I can imagine doing this for Collator.prototype.compare because Array.prototype.sort is such a common use case for it, but why for the format() methods? I think there is a straightforward design rule to apply in deciding whether such a property should be a unbound method or a bound function. If the value of the property is a function that is dependent upon the state of its access object and the function is likely to be routinely invoke as a standalone function then use a bound (or otherwise closed over the object) function as the property value. More simply, if the property is routinely accessed with an expression like: obj.prop then it should be a bound function. If it is routinely accessed with an expression like: obj.prop() then it can be a normal method. We have a good use case for Collator.compare that strongly suggests it should be bound: array.sort(col.compare) Do we have comparable use cases for Formatter.format? I heard a couple of reasons for format methods to be bound: 1. Can be passed as functions, thus hiding the object details would this be routinely done? If so it is a strong use case for a bound function displayDate(dt, mdyFmtr.format) 2. Makes it symmetrical to compare (in case we follow Allen's advice) symmetry is only important if the use cases of the two functions are similar. I assume that booth Collator and Formatter have plenty of properties that are normally invoked as regular methods. 3. No binding gotchas for users There are always gotchas if you try to dissociate a function that has (explicit or implicit,if built-in) this reference dependencies. That is the reason for the above design rule. Retrieving a bound function is a different logical operation than extracting a method implementation as an reflective operation. We don't want to impose the overhead of creating a bound function on each call to format() unless there's a good reason... Would caching first one resolve the overhead, like so (not sure about syntax): Yes, you would definitely want to memoize the function on first access or perhaps even upon object creation. NumberFormat.prototype = { get format(date) { var that = this; if (that.__bound === undefined) that.__bound = function(a) { uses that; return a b }; return that.__bound; } } Yes, logically. However a built-in implementation would use a private internal state variable [[CompareFunction]] instead of a regular property. An ES6 implementation in ECMAScript would use a private name property. Alternatively, you could simply create the bound function when you instantiate the Format instancet object and make it the value of the format (in this example) own property of the new instance. However, that technique would create issues if anybody ever wants to do prototypal inheritance from such an instance. For that reason, I would stick with the accessor on the prototype pattern. Of course, doing it for one and not the other is somewhat inconsistent. And since ES 5 has Function.prototype.bind (implemented in the leading browsers except Safari), it's not hard to bind compare() without library support: myArray.sort(collator.compare.bind(collator)); Do you really want a naive HTML coder to have to remember this pattern? Yes, we should probably pick one or the other - go jQuery route and force developers to .bind manually, or any other library where they either bind for the users or provide two versions of the same method (one bind the other one not). For these cases, I don't see why you would need the unbound method. Such a unbound method is really only useful it you are going to move it to another object and this isn't any particular reason why that should be expected to work in this scenario. Even though the function is bound you can still say: col.compare(a,b) if you want to invoke it using a method invocation style Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
On Jan 31, 2012, at 4:06 PM, Mike Samuel wrote: I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. A few [no whitespace here] tokens will probably be needed I addressed this at http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/tokenize.html A more direct like to this from the Quasis ecmascript.org wiki page would be helpful. The only current link does directly to the demo shell. Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Google indexing code patterns (Re: lexical for-in/for-of loose end)
I did a code search for for (var ident = before code search was shut down and the only code it found was from test suites. On Jan 31, 2012 6:31 AM, Nadav Shesek na...@shesek.info wrote: On Jan 31, 2012 3:38 PM, Sam Tobin-Hochstadt sa...@ccs.neu.edu wrote: Google Code Search is no longer available, sadly. Oh, I didn't know it was shutdown. Hopefully some Google internals can still use that data to give some stats when those questions arise... ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Google indexing code patterns (Re: lexical for-in/for-of loose end)
I think it would be semantically correct to allow at least let there as it is for loops for (let i = 0; i length; i++); // OK for (let key in obj); // not OK ? weird, I know destructuration is OK but for/in are still for loops my 2 cents, br ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Google indexing code patterns (Re: lexical for-in/for-of loose end)
Sorry, the search was a lot more elaborate to include in too. On Feb 1, 2012 9:29 AM, Erik Arvidsson erik.arvids...@gmail.com wrote: I did a code search for for (var ident = before code search was shut down and the only code it found was from test suites. On Jan 31, 2012 6:31 AM, Nadav Shesek na...@shesek.info wrote: On Jan 31, 2012 3:38 PM, Sam Tobin-Hochstadt sa...@ccs.neu.edu wrote: Google Code Search is no longer available, sadly. Oh, I didn't know it was shutdown. Hopefully some Google internals can still use that data to give some stats when those questions arise... ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: On Jan 31, 2012, at 2:36 PM, Waldemar Horwat wrote: On 01/28/2012 02:54 PM, Erik Arvidsson wrote: Under the open issues for Quasi Literals, http://wiki.ecmascript.org/doku.php?id=harmony:quasis#nesting , the topic of nesting is brought up. After implementing Quasi Literals in Traceur it is clear that supporting nested quasi literals is easier than not supporting them. What is the argument for not supporting nesting? Can we resolve this? This has been hashed out in committee before. Do you have a solution to the grammar problems, such as having a full ECMAScript parser inside the lexer? You can't just count parentheses because that breaks regexps. I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
On Feb 1, 2012, at 11:28 AM, Waldemar Horwat wrote: On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: On Jan 31, 2012, at 2:36 PM, Waldemar Horwat wrote: On 01/28/2012 02:54 PM, Erik Arvidsson wrote: Under the open issues for Quasi Literals, http://wiki.ecmascript.org/doku.php?id=harmony:quasis#nesting , the topic of nesting is brought up. After implementing Quasi Literals in Traceur it is clear that supporting nested quasi literals is easier than not supporting them. What is the argument for not supporting nesting? Can we resolve this? This has been hashed out in committee before. Do you have a solution to the grammar problems, such as having a full ECMAScript parser inside the lexer? You can't just count parentheses because that breaks regexps. I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. Was there some particular issue you were running into? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
2012/2/1 Waldemar Horwat walde...@google.com: On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: On Jan 31, 2012, at 2:36 PM, Waldemar Horwat wrote: On 01/28/2012 02:54 PM, Erik Arvidsson wrote: Under the open issues for Quasi Literals, http://wiki.ecmascript.org/doku.php?id=harmony:quasis#nesting , the topic of nesting is brought up. After implementing Quasi Literals in Traceur it is clear that supporting nested quasi literals is easier than not supporting them. What is the argument for not supporting nesting? Can we resolve this? This has been hashed out in committee before. Do you have a solution to the grammar problems, such as having a full ECMAScript parser inside the lexer? You can't just count parentheses because that breaks regexps. I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. What should I put in the proposal? A delta to the lexical grammar? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
Another loose end. With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols. An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility: for (let [c] in obj) print(c); //print the first character of each of obj's enumerable property names for (const {length:len} in obj) print(len); print the length of each of obj's enumerable property names Given this lack of utility, why should we allow de-structuring in this context? Eliminating it arguably increases language complexity by introducing in a bit more grammar irregularity. On the other hand, eliminating useless functionality can be seen as as simplification. I'm leaning towards banning destructing in for-in. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
On Feb 1, 2012, at 12:12 PM, Mike Samuel wrote: 2012/2/1 Waldemar Horwat walde...@google.com: On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. What should I put in the proposal? A delta to the lexical grammar? I expect that what we will ultimately end up with is some token additions to the lexical grammar and some new syntactic grammar productions that put those tokens together into complete Quasis. If you want to work on a first cut at those it would be great. Otherwise, I'll need to do the work when I start editing Quasis into the actual specification. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
Allen Wirfs-Brock wrote: Another loose end. With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols. An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility: for (let [c] in obj) print(c); //print the first character of each of obj's enumerable property names for (const {length:len} in obj) print(len); print the length of each of obj's enumerable property names Given this lack of utility, why should we allow de-structuring in this context? These are not totally silly examples. I say when in doubt, let language regularity win. We are also thereby future-friendly in case some evolution of property keys becomes even more structured. I know, unlikely, but again: regularity when in doubt. Eliminating it arguably increases language complexity by introducing in a bit more grammar irregularity. On the other hand, eliminating useless functionality can be seen as as simplification. Not useless, your own examples show use-cases. I'm leaning towards banning destructing in for-in. Too nannyish! /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
How to ensure that your script runs first in a webpage
Hi, I have claimed here a couple of times, that in a JavaScript application containing code from different parties, the first to run is the one that is in position to make decisions about security of the overall application (freezing the primordials for a defender or monkey-patching them if you're an attacker). I still have no proof (I feel it's coming though) about it, but a strong intuition. Assuming this is true, then, on the web, one has to make sure that her protecting script runs first. How to ensure this, though? There is always a risk that with an XSS an attacker scripts runs before the protecting one. I think I have found an answer and it is: with Content Security Policy (CSP) [1]. CSP introduces a script-src directive [2] allowing only a whitelist of script URLs to be fetchable as script@src. Moreover, by default, inline scripts (in scripts or as on* attributes) won't execute. Consequently, in browsers that support the script-src CSP directive (script whitelisting even reduced to one element and the If 'unsafe-inline' is not in allowed script sources rule), one can enforce running her script first. The restriction is even stronger, because the whitelisted script is just the only one to run. It has to be noted that it does not limit the scripts that /can/ be run on the page since the unique script can still download other scripts and eval them. If a raw eval sounds too unsafe, you can embed in your unique script a JavaScript rewriter [3] ;-) Browser support: Firefox 4+, Webkit-based browsers, IE10. David [1] https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html [2] https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#script-src [3] http://code.google.com/p/google-caja/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
On Feb 1, 2012, at 2:13 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: Another loose end. With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols. An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility: for (let [c] in obj) print(c); //print the first character of each of obj's enumerable property names for (const {length:len} in obj) print(len); print the length of each of obj's enumerable property names Given this lack of utility, why should we allow de-structuring in this context? These are not totally silly examples. I say when in doubt, let language regularity win. Well, they're at least 98% silly and these were the only even semi-plausable example I could think of. We are also thereby future-friendly in case some evolution of property keys becomes even more structured. I know, unlikely, but again: regularity when in doubt. In which case, it would be easy enough to allow them in the future. It's always easer to relax a restriction then it is to add one. Eliminating it arguably increases language complexity by introducing in a bit more grammar irregularity. On the other hand, eliminating useless functionality can be seen as as simplification. Not useless, your own examples show use-cases. I'm leaning towards banning destructing in for-in. Too nannyish! I don't really see the consistency in trying to ban the initializer in for (var k=42 in obj) ; because it is a awful, lazy-grammar-resue error. While adding for (var [c] in obj) ; I don't actually feel too strongly either way and it is actually more work for me to disallow the destructuring pattern. However, I am trying to find some basis for consistency in the design choices we make. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How to ensure that your script runs first in a webpage
On Wed, Feb 1, 2012 at 2:41 PM, David Bruant bruan...@gmail.com wrote: Hi, I have claimed here a couple of times, that in a JavaScript application containing code from different parties, the first to run is the one that is in position to make decisions about security of the overall application (freezing the primordials for a defender or monkey-patching them if you're an attacker). I still have no proof (I feel it's coming though) about it, but a strong intuition. Assuming this is true, then, on the web, one has to make sure that her protecting script runs first. How to ensure this, though? There is always a risk that with an XSS an attacker scripts runs before the protecting one. I think I have found an answer and it is: with Content Security Policy (CSP) [1]. Perhaps you can help me understand your reasoning here. To me, you have indeed found the answer and the one that is in position to make decisions about security of the overall application is in fact the browser the implements CSP. I guess you have some use case in mind that you might share. It seems to me if you don't want a script to load, then don't load it. But somehow you want to load this attacker then prevent it from being successful? jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
Allen Wirfs-Brock wrote: On Feb 1, 2012, at 2:13 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: Another loose end. With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols. An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility: for (let [c] in obj) print(c); //print the first character of each of obj's enumerable property names for (const {length:len} in obj) print(len); print the length of each of obj's enumerable property names Given this lack of utility, why should we allow de-structuring in this context? These are not totally silly examples. I say when in doubt, let language regularity win. Well, they're at least 98% silly and these were the only even semi-plausable example I could think of. So you agree with my point about regularity + non-silly use-cases winning? :-/ We are also thereby future-friendly in case some evolution of property keys becomes even more structured. I know, unlikely, but again: regularity when in doubt. In which case, it would be easy enough to allow them in the future. It's always easer to relax a restriction then it is to add one. How would you restrict them? Splitting productions, or semantic restrictions? It matters, not just aesthetically but for implementation simplicity. I don't really see the consistency in trying to ban the initializer in for (var k=42 in obj) ; because it is a awful, lazy-grammar-resue error. ES1 was based on real implementations. The Netscape one did not allow an initaliser here. There's no good use for it compared to destructuring key lengths or substrings, especially not with var (which hoists). You want an initial var value to survive a zero-iteration loop? Hoist the var. While adding for (var [c] in obj) ; Are you really adding? It depends on good vs. bad reuse of sub-grammar. I appealed to regularity. That means standard rules for conjugating verbs, etc., in natural languages. In programming languages one would hope that binding forms would compose the same with for-in as for-of as for;; and other binding contexts, modulo the initialiser. At least, that's what users of JS1.7-and-up have hoped. That evidence is tainted because we did make for-in programmable via an iteration protocol, as for-of is in ES6. Granted. But unless there's an actual hardship in regularity (I don't believe there is with for-in, but I welcome evidence from you on spec front, and other implementors on impl front) I still think regularity wins. I don't actually feel too strongly either way and it is actually more work for me to disallow the destructuring pattern. I'm not super-strong on this, don't get me wrong. It's much less of an issue either way than banning the initialiser for let and const. I hope we agree on that much, as a partial order of preferences or strong convictions! It also seems relevant that you'd have to do more work in the spec, and presumably make the grammar bigger, to disallow destructuring (with and without var/let/const) in for-in. More spec effort and grammar size make for errata habitat. Just as with code. However, I am trying to find some basis for consistency in the design choices we make. Again, for-in as designed in JS1 never allowed an initialiser and it's an unwanted feature added to match JScript or (perhaps JScript too lacked it) to reuse part of the grammar a certain way. Note that the reuse of VariableDeclarationNoIn didn't save anything in the grammar, so I bet the issue was JScript allowing an initialiser. Anyone know? It's never inconsistent to allow one thing and disallow another. The particulars matter. This isn't anything goes. Destructuring has a bit of utility and a lot of regularity in for-in head position. The initialiser from VariableDeclarationNoIn has neither specific utility nor regularity with respect to for-in in AWK, Python, or any other language with such a construct. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
Brendan Eich wrote: It's never inconsistent to allow one thing and disallow another. The particulars matter. This isn't anything goes. Destructuring has a bit of utility and a lot of regularity in for-in head position. The initialiser from VariableDeclarationNoIn has neither specific utility nor regularity with respect to for-in in AWK, Python, or any other language with such a construct. More to say, I sent too soon. Don't take this as more than it is: an attempt to explore an alternative meaning of for-in combined with certain destructuring patterns. We have a request that seemed to receive popular support, to support for own (k in o) ...; This could compose with the following nicely, and it tries to pave the CoffeeScript cowpath a bit (without taking CoffeeScript as normative or overriding or anything like that). We could make just-so meanings for destructuring in for-in, also inspired by CoffeeScript (and JS1.7, which did this too while muddying the waters by failing to separate iteration protocol into for-of): for ([k, v] in o) ...; Our current position is use for-of and an items helper function: import items from @reflect; // currently @iter; could be part of standard prelude for ([k, v] of items(o)) ...; But I think detailing the design of ES6 must be allowed to entertain an even easier-to-use extension to for-in. If you want values not keys, then per the current proposal you use for (v of values(o)) ...; given the necessary values import, or inclusion in a standard prelude. There's a hole vs. CoffeeScript: we do not want for-of on a plain Object to iterate over enumerable property values. Arrays, yes, Objects, no -- no Object.prototype.@iterator. So no |for (v of o) ...| for o = {p:1, q:2, r:3}. Also no for each (v in o) as E4X (ECMA-357) promulgated. SpiderMonkey and Rhino support it and probably will have to carry it, but such each does not say its meaning (values not keys) clearly, and it doesn't compose with own nicely. But with destructuring for-in, you could write for ([, v] in o) ...; This is a bit ugly (holes never look pretty, even when they're useful). Not sure what I think of this but I thought I'd throw it out here on es-discuss. The reason I bring it up is twofold: 1) for own (k in o) still needs to be discussed; 2) the for ([k, v] of items(o)) ...; tax is a bit higher than I'd like. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Nested Quasis
On 02/01/2012 11:35 AM, Allen Wirfs-Brock wrote: On Feb 1, 2012, at 11:28 AM, Waldemar Horwat wrote: On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: On Jan 31, 2012, at 2:36 PM, Waldemar Horwat wrote: On 01/28/2012 02:54 PM, Erik Arvidsson wrote: Under the open issues for Quasi Literals, http://wiki.ecmascript.org/doku.php?id=harmony:quasis#nesting , the topic of nesting is brought up. After implementing Quasi Literals in Traceur it is clear that supporting nested quasi literals is easier than not supporting them. What is the argument for not supporting nesting? Can we resolve this? This has been hashed out in committee before. Do you have a solution to the grammar problems, such as having a full ECMAScript parser inside the lexer? You can't just count parentheses because that breaks regexps. I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. Was there some particular issue you were running into? Here's one which I couldn't express in a lexer grammar: How to restart the quasi after an included expression is over. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
On Feb 1, 2012, at 3:31 PM, Brendan Eich wrote: Brendan Eich wrote: It's never inconsistent to allow one thing and disallow another. The particulars matter. This isn't anything goes. Destructuring has a bit of utility and a lot of regularity in for-in head position. The initialiser from VariableDeclarationNoIn has neither specific utility nor regularity with respect to for-in in AWK, Python, or any other language with such a construct. More to say, I sent too soon. Don't take this as more than it is: an attempt to explore an alternative meaning of for-in combined with certain destructuring patterns. We have a request that seemed to receive popular support, to support for own (k in o) ...; This could compose with the following nicely, and it tries to pave the CoffeeScript cowpath a bit (without taking CoffeeScript as normative or overriding or anything like that). Towards the end of https://mail.mozilla.org/pipermail/es-discuss/2011-November/018332.html I made an argument that own-ness of properties is an implementation choice that normally should not be of concern to application clients of an object-based abstraction. Own-ness is primarily relevant to abstraction implementors or somebody who is using reflection to examine the implementation structure of an object. Hopefully reflection is tucked away in a obscure but pleasant corner of the language and not widely used for routine application logic. Generally, reflection doesn't deserve (or require) statement level support. That raises the question of the role of the for-in statement in the language (besides just being an obsolete and less useful alternative to for-of). Being a full fledged syntactic statement of the language, it certainly isn't hiding in an obscure corner. If we want to think of it as something other than an over exposed reflection tool, what is it for?. The best expression of this that I can come up with, is that for-in is a statement that is primarily useful for iterating the data member keys of simple record and array like data abstractions. From that perspective, own-ness again is something that should primarily be an implementation concern. Clients who are iterating over my public data members shouldn't be concerned about whether or not I decided to implement my data abstraction using a tree of objects or be impacted if I change my mind. To me, for-own-in makes it too easy for client code to create dependencies upon what should inconsequential implementation decisions. We have a goal of making ES a language that is better for creating and using abstractions. For-own-in is a tool that tunnels through abstractions. Such a tool is fine as part of the reflection facility, but making it a full fledged statement seems like it would be creating an attractive nuisance. We could make just-so meanings for destructuring in for-in, also inspired by CoffeeScript (and JS1.7, which did this too while muddying the waters by failing to separate iteration protocol into for-of): for ([k, v] in o) ...; Clearly, this isn't a general destructuring. It is a special syntactic form that is mimicking array destructuring syntax. We could probably have a long thread about whether such mimicry is clever language design or a confusing creole. I reserve my opinion on the general questions. Our current position is use for-of and an items helper function: import items from @reflect; // currently @iter; could be part of standard prelude for ([k, v] of items(o)) ...; see the main part of the message I referenced above. Pure functional filters like item are unfriendly to collection abstracton builders. But I think detailing the design of ES6 must be allowed to entertain an even easier-to-use extension to for-in. Another simplification would be to make default iterator produce {key,value} item objects, Then we have three concise formulations: for ({key, value} of o) ...; for ({key} of o) ...; for ({value} of o) ... If you want values not keys, then per the current proposal you use for (v of values(o)) ...; given the necessary values import, or inclusion in a standard prelude. There's a hole vs. CoffeeScript: we do not want for-of on a plain Object to iterate over enumerable property values. Arrays, yes, Objects, no -- no Object.prototype.@iterator. So no |for (v of o) ...| for o = {p:1, q:2, r:3}. (I note at this point that there are some huge es-discuss threads on topics such as the above for which the conclusions (if any) have not been extracted. I'm starting to go over them to see what I can extract from them) I assume that you are arguing that the default @iterator for Object.prototype (however it is provided) does a key enumeration just like ES1-5 for-in. Or are you arguing that it produces nothing? I'm not exactly sure why either of those is better than |for (v of o) ...| but I think there are a couple threads that I
Re: Nested Quasis
On Feb 1, 2012, at 5:33 PM, Waldemar Horwat wrote: On 02/01/2012 11:35 AM, Allen Wirfs-Brock wrote: On Feb 1, 2012, at 11:28 AM, Waldemar Horwat wrote: On 01/31/2012 03:04 PM, Allen Wirfs-Brock wrote: On Jan 31, 2012, at 2:36 PM, Waldemar Horwat wrote: On 01/28/2012 02:54 PM, Erik Arvidsson wrote: Under the open issues for Quasi Literals, http://wiki.ecmascript.org/doku.php?id=harmony:quasis#nesting , the topic of nesting is brought up. After implementing Quasi Literals in Traceur it is clear that supporting nested quasi literals is easier than not supporting them. What is the argument for not supporting nesting? Can we resolve this? This has been hashed out in committee before. Do you have a solution to the grammar problems, such as having a full ECMAScript parser inside the lexer? You can't just count parentheses because that breaks regexps. I would think the solution to this is pretty straightforward. Basically, a Quasi is not a single token. the grammar in the proposal can almost be read that way right now. It should only take a little cleanup to factor it into a pure lexical part and a syntactic part. I'd love to see this little cleanup. I thought about it for a while and couldn't come up with it myself; I'm not sure it can even be done. Was there some particular issue you were running into? Here's one which I couldn't express in a lexer grammar: How to restart the quasi after an included expression is over. I wouldn't because I would produce the complete quasi as a single token. I would leave it up to the syntactic grammar to assemble the quasi pieces and inclusion expression into a complete unit. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: lexical for-in/for-of loose end
On Feb 1, 2012, at 3:05 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: On Feb 1, 2012, at 2:13 PM, Brendan Eich wrote: Allen Wirfs-Brock wrote: Another loose end. With the addition of for-of, for-in reverts back to always iterating over the property keys of an object as it does not support the generalized iteration protocols. An implication of this is that using a de-structuring pattern as the iteration variable has very limited utility: for (let [c] in obj) print(c); //print the first character of each of obj's enumerable property names for (const {length:len} in obj) print(len); print the length of each of obj's enumerable property names Given this lack of utility, why should we allow de-structuring in this context? These are not totally silly examples. I say when in doubt, let language regularity win. Well, they're at least 98% silly and these were the only even semi-plausable example I could think of. So you agree with my point about regularity + non-silly use-cases winning? :-/ I like regularity, which was why I was content to keep the 98+% silly initialization expression in for-in |for (var k=debugLog(starting loop) in obj)...|. keeps it all together for refactoring :-\ But, in reality I was probably more concerned about the breaking change issue. We are also thereby future-friendly in case some evolution of property keys becomes even more structured. I know, unlikely, but again: regularity when in doubt. In which case, it would be easy enough to allow them in the future. It's always easer to relax a restriction then it is to add one. How would you restrict them? Splitting productions, or semantic restrictions? It matters, not just aesthetically but for implementation simplicity. In this particular case I would probably use separate productions (already did that to eliminate the initializers for |for (let/const x in)|. In general, I prefer to only use static semantic restrictions only when they involve non-nearby contextual information about the program. However, that is a specification aesthetic. I don't see why an implementation parser would necessarily want to make the same grammar trade-offs. Converting grammar to static checks and visa versa seems like very routine parser engineering. I don't really see the consistency in trying to ban the initializer in for (var k=42 in obj) ; because it is a awful, lazy-grammar-resue error. ES1 was based on real implementations. The Netscape one did not allow an initaliser here. There's no good use for it compared to destructuring key lengths or substrings, especially not with var (which hoists). You want an initial var value to survive a zero-iteration loop? Hoist the var. While adding for (var [c] in obj) ; Are you really adding? It depends on good vs. bad reuse of sub-grammar. I appealed to regularity. That means standard rules for conjugating verbs, etc., in natural languages. Well, its adding to the grammar I wrote this morning... I already have to have additional productions (or static semantic rules, they amount to the same thing) that don't have initializer expressions on the for (let/const forms. But I like standard rules too. Too many special cases make the language harder to learn. But regularity that allow for WTF situations also isn't good. There is a sweat spot that needs to be found. In programming languages one would hope that binding forms would compose the same with for-in as for-of as for;; and other binding contexts, modulo the initialiser. At least, that's what users of JS1.7-and-up have hoped. That evidence is tainted because we did make for-in programmable via an iteration protocol, as for-of is in ES6. Granted. But unless there's an actual hardship in regularity (I don't believe there is with for-in, but I welcome evidence from you on spec front, and other implementors on impl front) I still think regularity wins. I actually think may two use cases for for-in de-structuring (as currently defined) are pretty close to WTF scenarios. Most people are going to have to stop and think carefully about what they mean. Probably more important, allowing destructuing in for-in is likely to further confuse people regularly forget that it iterates over keys rather than values. I don't actually feel too strongly either way and it is actually more work for me to disallow the destructuring pattern. I'm not super-strong on this, don't get me wrong. It's much less of an issue either way than banning the initialiser for let and const. I hope we agree on that much, as a partial order of preferences or strong convictions! It also seems relevant that you'd have to do more work in the spec, and presumably make the grammar bigger, to disallow destructuring (with and without var/let/const) in for-in. More spec effort and grammar size make for
Re: lexical for-in/for-of loose end
Allen Wirfs-Brock wrote: On Feb 1, 2012, at 3:31 PM, Brendan Eich wrote: Brendan Eich wrote: It's never inconsistent to allow one thing and disallow another. The particulars matter. This isn't anything goes. Destructuring has a bit of utility and a lot of regularity in for-in head position. The initialiser from VariableDeclarationNoIn has neither specific utility nor regularity with respect to for-in in AWK, Python, or any other language with such a construct. More to say, I sent too soon. Don't take this as more than it is: an attempt to explore an alternative meaning of for-in combined with certain destructuring patterns. We have a request that seemed to receive popular support, to support for own (k in o) ...; This could compose with the following nicely, and it tries to pave the CoffeeScript cowpath a bit (without taking CoffeeScript as normative or overriding or anything like that). Towards the end of https://mail.mozilla.org/pipermail/es-discuss/2011-November/018332.html I made an argument that own-ness of properties is an implementation choice that normally should not be of concern to application clients of an object-based abstraction. Own-ness is primarily relevant to abstraction implementors or somebody who is using reflection to examine the implementation structure of an object. That's an ideal but the reality is for-in and easy transpilation from better derived forms to it are with us, and will be for a while. Hopefully reflection is tucked away in a obscure but pleasant corner of the language and not widely used for routine application logic. Generally, reflection doesn't deserve (or require) statement level support. still want easy array-value iteration. That's what for-of does out of the box. This is important, it shouldn't take any more chars than for (v of a)... eliding declaration of v and decl/init of array a. That raises the question of the role of the for-in statement in the language (besides just being an obsolete and less useful alternative to for-of). Being a full fledged syntactic statement of the language, it certainly isn't hiding in an obscure corner. If we want to think of it as something other than an over exposed reflection tool, what is it for?. The best expression of this that I can come up with, is that for-in is a statement that is primarily useful for iterating the data member keys of simple record and array like data abstractions. So far, so good, and latent here is the best case for not elaborating the left-hand side to include destructuring, if you can avoid bloating the grammar too much. Contra my regularity plus small use-cases argument, we leave for-in alone. We can even leave it underspecified as in ES5. From that perspective, own-ness again is something that should primarily be an implementation concern. Historically this came up because pre-ES5 people couldn't extend Array.prototype, e.g., without making enumerable properties. But of course then the wisdom said don't use for-in on arrays. Object.prototype is verboten, and at some cost in using custom functional-programming style iteration, we're ok (PrototypeJS status quo). The problem that may remain is that for own (k in o) ...; still beats for (k in keys(o)) ...; not only by a couple of chars not counting import or assuming prelude, but in terms of people's historical memory and folk-wisdom learning. Should we ignore all this and say just use for-of with the right iterator? To me, for-own-in makes it too easy for client code to create dependencies upon what should inconsequential implementation decisions. In reality the shoe is on the other foot. Implementation decisions that should be without consequence mess up for-in, requiring hasOwnProperty testing. People want a shorter-path solution. Giving a longer-path solution with for-of and iterators is good, we want that. Is it good enough to be the only solution we build into the language? We have a goal of making ES a language that is better for creating and using abstractions. For-own-in is a tool that tunnels through abstractions. I think you're making too sweeping a statement about abstractions. Does for-own-in tunnel in ways that violate abstractions, or is it really what the doctor ordered for JS close to today's best practices (not always followed)? I say more the latter, but not clear cut in any event. Such a tool is fine as part of the reflection facility, but making it a full fledged statement seems like it would be creating an attractive nuisance. We have a full-fledged statement, for-in. It can't be deprecated quite yet. Adding for-of helps, but is it enough? That's the issue I'm raising. We could make just-so meanings for destructuring in for-in, also inspired by CoffeeScript (and JS1.7, which did this too while muddying the waters by failing to separate iteration protocol into for-of): for ([k, v] in o) ...; Clearly, this