Re: function hoisting like var
Ingvar von Schoultz wrote: [EMAIL PROTECTED] wrote: I'm trying to keep the language relatively simple. You can't get away from supporting this: { function a(){} var b = a; } What do you mean? This is a syntax error in both ES3 and ES3.1. On the contrary, the functionality already exists, as shown above. It does not already exist in ES3 or ES3.1. Keep in mind that function assignments hoist to the beginning of the scope in which the function is defined, so your proposal won't work. When the programmer explicitly says that the assignment depends on sequential code, then do what the programmer says. Anything else is an error. Do it by assigning |undefined| before scope entry. This is the only correct thing to do. I don't understand. You're trying to do a complex split-scope approach where each function definition has *two* scopes, one in which it is declared and one in which it is defined, but even that won't work with const, typed functions and variables, etc. Are you saying that the function /body/ gets into trouble, or the function /name/? Both. The function /body/ stays where it is. The hoisting doesn't affect it in any way. Moving the body would change its context and meaning catastrophically. Don't touch it. That doesn't answer the question. The problem is that the body can capture variables that haven't been declared yet. The /name/ becomes a var. Treat it like any other var. Hoist it and assign |undefined|, exactly like you do with other vars. That's incompatible with how functions are defined in ES3. Are you saying that because this var is related to a function it can't be treated like other vars? Is this var fundamentally different from other vars? At least above it isn't. Huh? Do you understand how ES3 works? That email is about some wildly unworkable dynamic scoping. It has nothing to do with anything I ever said. You jumped to that conclusion. Please stop insisting that I'm proposing that nonsense. I'm not. I never did. I haven't seen a sensible and compatible proposal yet. You'd then have to introduce extra rules about some definitions only being possible within {{}} blocks, which would then affect the behavior of existing definitions like var if one of the other definitions within the same block was a const or function, which would snowball into a complex mess. Unrelated, I believe. So you're saying that your {{}} proposal has nothing to do with this? Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Surprising semantics
We've been down this road before, and the arguments you present have been hashed out over years. This approach doesn't work. Read the archives of the ES4 group. The problem is that you then get a plethora of ways to define things: var const function type namespace let let const let function let type let namespace Furthermore, some of them don't make sense (such as function without let) because they can conditionally capture variables that may not even exist. The example you give of conditional definitions: if (foo) { const c = 37; } else { const c = abc; } ... do something with c ... is particularly disruptive. You must then support conditional holes: // outer scope function c() ...; // inner scope { if (foo) { const c = 37; } ... c can be either 37 or the outer scope function here ... } It gets worse: // outer scope function c() ...; // inner scope { function f() { return c; } a = f(); if (foo) { const c = 37; } b = f(); ... just what do a and b hold here? Was f's captured variable rebound by the if statement? ... } Also consider: for (i = 0; i foo.length; i++) { const v = foo[i]; } You'll catch everyone off-guard if you make folks do a let const instead of a const here. In E4 it gets worse still because c can have a type: type c = ... { if (foo) { const c:Number = 37; } else if (bar) { var c:String = abc; } } ... do something with c, which is either a type, a constant, or a variable, and can be statically typed as either a Number or a String ... const d:c = ... // Conditional definition requires variable types to be evaluated at run-time, which is not somewhere we want to go in the first version I don't know of anyone here who wants to support something like that. Waldemar Ingvar von Schoultz wrote: These are some impressions looking at what I expect from the language, and how some things in the specification can cause confusion. I would have contributed here during the discussions, but I discovered the mailing lists just a couple of days ago. I expect the compiler's interpretation of program-code text to be close to my intuitive understanding of what the text says. It's very unfortunate if keywords have unexpected meanings that cause mysterious side effects. If I learn that ECMAScript will let me change my var(iables) into const(ants) I expect this to turn them into constants, in the sense that trying to change their value will be considered an error. It's very disappointing that by default they are instead defined to have the baffling and mysterious behavior of silently ignoring an attempt to change them, acting as if no error had occurred. You'll have to keep this oddity in mind at all times, and even then errors related to this will sometimes cause symptoms to appear far from where the error is, costing quite some time to explore. Why doesn't my program change its behavior even though I'm provoking changes? Where in this big program's complicated sequence of events is the change silently, secretly lost? If instead you use var, at least the problems that can come from this will tend to give symptoms closely connected to the incorrect change in the value. So this is a disappointing red flag: Don't use const, it is likely to cause baffling problems and unlikely to help. Unfortunately there's another problem with const that is much more important. I often use constants for conditional settings: if (Debugging) { var DatabaseName = TestDatabase; var DisplayCount = 5; } else { var DatabaseName = RealDatabase; var DisplayCount = 15; } The redundant vars are a defensive habit, omitting them would be a warning about accesses outside the current scope. If I haven't been warned, and hear that ECMAScript understands const, I expect that replacing var with const will change the above from variables into constants. The keyword in no way suggests that it will hide them from view. If they disappear I'll inevitably consider such a completely unrelated side effect a compiler bug. Because of this I'm unhappy about the conclusions of ES3.1 that the visibility scope of const should be the enclosing brace- delimited block. Such intricate semantics hidden in words that express something completely unrelated will make the language seem difficult and fraught with hidden surprises. I much prefer what ES4 says in various places on the website: that you express this localness with let const and let function. One block-scope keyword for all block-scope visibility. Consistency and clarity. However this brings me to the unfortunate word let. Although this word has a precise and clear technical meaning for the initiate, for us in the unwashed masses I can't see that the English word let gives even the remotest suggestion of local containment. In fact it suggests very clearly that it's related
Re: ES3.1 Object static methods rationale document
Allen Wirfs-Brock wrote: In summary, not providing reflective access to an object's prototype doesn't really provide any real security, it just makes some useful tasks less convenient. Reverting to barnyard analogies: the barn door is already wide open and we're debating an inch wide trench that spans the opening. If we want to keep the horses in we need to think about how to put an iron gate across that gap rather than worrying about the risks of filling in the trench. On the other hand, providing reflective access to an object's prototype is harmful to compatibility because it prevents implementations from introducing intermediate prototypes without breaking the web. Consider the example of having just Numbers and later compatibly introducing more specific subkinds of Numbers. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: A read/write __proto__ that can vanish
Ingvar von Schoultz wrote: Some people yearn hotly for __proto__, preferrably writable if at all possible, while others point to problems with security and software privacy. I get the impression that this could be solved by adding a fourth flag among the property flags Enumerable, Writable and Flexible. There might be a flag called Visible, so you could make __proto__ apparently vanish by setting Visible to false. Adding switches like this is making code too complicated and will result in plenty of arguments about whether a particular class should have the switch turned on or off. Often the classes you want to use will have it set the wrong way, leading to more balkanization of libraries. In the committee we've already spent too much time discussing which properties should be enumerable, dontDelete, etc., and we still get those wrong at times. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: BOM inside tokens
Igor Bukanov wrote: It seems the current IE7/IE8 behavior is to allow Cf only in srtring and regexp literals and to allow BOM only in string/regexps or at the beginning of the source, Precisely what does in string and regexp literals mean? The exact interpretation of this phrase is the core source of the aforementioned security holes. Folks have exploited putting special characters right after a backslash to break out of whitelisted literals and execute arbitrary code from JSON; a few months ago I demonstrated such an attack. Regular expressions offer even more opportunities for this kind of mischief. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ToString for Numbers: reducing variation.
David Jones wrote: After I wrote a blog article on this subject someone suggested I raise the issue here. Currently, ECMA 262 3rd edition section 9.8.1, the ToString operator permits implementations to vary in how they convert certain numbers to strings. For example the number 5e-324 could legally be converted as 3e-324, 4e-324, and so on up to 7e-324. This would permit an implementation to evaluate the following expression as undefined: ({5e-324:true})[5e-324] I do not think any reasonable implementation would have a good reason for doing this. It also permits the value of 'a' to vary between implementations in the following loop body: for(a in {5e-324:true}) {...} In order to ensure implementations all behave the same way I suggest the note at end of section 9.8.1 be moved to normative status. As far as I can tell, the text is essentially the same between ECMA 262 3rd edition and the Oslo draft published on 2008-07-04. Cheers, drj I don't mind specifying it if the implementations agree. Incidentally, this is a big problem with C and C++ right now. gcc will generate code for double x = some floating-point expression; double y = x; ... bool b1 = x == y; ... bool b2 = x == y; ... bool b3 = x == y; where b1 and b3 will evaluate to true and b2 to false (the results depend on its register allocation strategy). Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Newly revised Section 10 for ES3.1.
Mike Shaver wrote: On Thu, Jul 10, 2008 at 1:48 AM, Allen Wirfs-Brock [EMAIL PROTECTED] wrote: FWIW, this sort of thing is a reason that I'm pretty concerned about ES3.1 getting into an advanced specification state without the benefit of any in-browser implementation. You need to have an advance specification state before you can meaningfully test it in an implementation. Sure, there's an interdependency, but it seems like you wouldn't want to propose something for inclusion into a short-turn spec like ES3.1 unless you'd seen it run _somewhere_ relevant, no? Is there a document somewhere that tracks which ES3.1 features have been implemented in what prototype engine? The key criterion here is whether you can come up with a language that makes sense. None of the existing behaviors make sense because they would make 'function' hoist differently from 'const' hoist differently from declaring other kinds of things in ES4, etc., with the only way of fixing it being introducing yet more ways of declaring things. The net result would be gratuitously hostile to everyone in the long term. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Update on ES3.1 block scoped function declarations
Brendan, You're beating a dead horse here. If this call to eval is allowed, the only reasonable answer is 21. All that means is that you must be able to recreate the bindings if the function uses eval. Unless you're proposing to take block-scoped declarations out of ES4, what's the harm with ES3.1 having a compatible subset of them? Waldemar Brendan Eich wrote: On Jul 10, 2008, at 3:28 PM, Mark S. Miller wrote: On Thu, Jul 10, 2008 at 2:51 PM, Allen Wirfs-Brock [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] wrote: I see, yes there is a potential eval tax. If I thought this was really a concern (and as you say, we already have the issue for catch and such) I'd be more inclined to fiddling with the scoping rule of eval rather than discarding lexically scoped consts. BTW, I think many of the use cases for such const are more in support of code generators then actual end user programming. Could you explain the eval tax issue you guys are concerned about? I don't get it. Thanks. In ES1-3, the scope chain is a linked list of objects. Every function call creates an activation object to be the variable object used when entering the execution context for that function's code. Thus when entering the execution context for eval code, one uses the caller's scope chain. Real implementations do not reify objects for all activations. This is a good way to be slow. Separately, we aspire to lexical scope. This does not necessarily mean block scope, see e.g. ES4 comprehensions. But however it maps onto syntax, lexical scope holds out the hope that the binding information is compile-time only. After that, the implementation can forget about bindings and the lexical scopes they inhabit. That's not possible if eval can see const bindings in ES3.1 as proposed, or let/const/sub-statement-function bindings in ES4. The Previously http://www.nabble.com/Eval-invisible-let-bindings-td14182651.html%2523a14182651 thread I cited talks about an alternative where eval cannot see lexical bindings. But that thread concluded (IMHO) with the victorious and inevitable usability argument that programmers would be greatly put out, as well as surprised, if eval could not see its caller's lexical bindings. So implementations have to save lexical binding information when compiling, and reify or otherwise propagate it to eval. Implementations that support indirect eval must not only save the lexical binding information, they must reify bindings as properties and scopes as objects (or something morally equivalent), since the compiler cannot see all eval calls and make a private arrangement to pass private binding/scope data structures preserved with the function or script that calls eval. The indirect eval activation really does need to see objects on a scope chain. This can be done on demand, but it is not pretty. Imposing this tax on implementations of ES3.1 and not giving them let and function sub-statements seems half-hearted, and implementations are likely to extend. Block scope is nice, but it's a big change for ES3.1. The alternative is to a. confine const grammatically to top level where it can be treated like a property of the global or activation object in the spec, and b. deal with eval referencing a catch variable or named lambda specially. The (b) cases were specified in ES3 using as if by new Object or equivalent, which is a bug, but some implementations ignored ES3 and used lexical binding machinery. I'm not sure whether all such all eval to see such bindings. Firefox 2 and 3 do for catch variables. I'll test Opera and report back. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Forwards-compatible syntax proposal
I've had a request to repeat the example I showed at the meeting, so here's one: { if (false) { // Say we're introducing a new cast syntax '(expr) expr' var y = (int)/fo+/.exec(abcfoo); } push_the_button = false; { z = y/x; } } In ECMAScript parsing and lexing are interleaved. There is no way to tell without correctly parsing a piece of code whether / starts a regexp or is a division. In the above example the regexp was meant to be /fo+/, but the syntax error recovery code will instead think that /.exec...y/x is an extended (multiline) regexp, missing the crucial closing brace of the block and the push_the_button = false statement. Many other syntax errors can lead to this kind of lexer misalignment, hence it is impossible to isolate a syntax error to the first inner block above (or any other similar syntactic construct), despite the fact that it never executes due to the if (false). You can make guesses based on indentation and such but guesses don't belong in a standard. Waldemar Waldemar Horwat wrote: This wouldn't work. Without syntactically distinguishing a / that is a division from a / that starts a regexp, there is no way to find the end of the block. To make this distinction you need to be able to parse the contents of the block without errors. To complicate matters further, various language extension proposals, ranging from ES3.1 to various ES4 extensions, muck with the regexp syntax. ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Forwards-compatible syntax proposal
This wouldn't work. Without syntactically distinguishing a / that is a division from a / that starts a regexp, there is no way to find the end of the block. To make this distinction you need to be able to parse the contents of the block without errors. To complicate matters further, various language extension proposals, ranging from ES3.1 to various ES4 extensions, muck with the regexp syntax. Waldemar Ian Hickson wrote: One of the problems with ES4 relative to ES3 is that the new syntax means that a script using ES4 features doesn't work in ES3 compilers. There's not much we can do in the ES3-ES4 language migration about this. But we _can_ prevent this problem from existing again in ES5 and up. I propose that ES4 clients, when they hit a syntax error, back up to the start of the current block, and then look for the end of the block, which is the } corresponding to the last token in this grammar: block = { tokens* } tokens = block | string | comment | regexp | other string = single-quote [ no-backslash | escape ]* [ single-quote | end of line ] string = double-quote [ no-backslash | escape ]* [ double-quote | end of line ] string = (triple-quoted string) no-backslash = anything but \ escape = \ followed by anything comment = /* ... */ comment = // ... end of line comment = !-- ... end of line regexp = / [ no-backslash | escape ]* [ / | end of line ] other = anything else ...and then compile the whole block to one throw SyntaxError statement. I may have missed some things we should include, and the grammar above may be too simple and may have to have changes made, but hopefully it conveys the basic idea. Comments? ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 note: Reserved namespaces
Lars Hansen wrote: -Original Message- From: Waldemar Horwat [mailto:[EMAIL PROTECTED] Sent: 28. april 2008 18:39 To: Lars Hansen Cc: es4-discuss Subject: Re: ES4 note: Reserved namespaces I agree with everything except: * reserved namespaces may not be aliased (ie they are illegal on the right hand side of = in namespace ns1 = ns2) If we want to make reserved namespaces into keywords, We do not... that might be ok. However, at the current time they're not keywords, and one could write: const foo = intrinsic; But foo can't be used as a namespace qualifier in any context, so that's OK. and: namespace instrinsic = my_namespace; That one either shadows an existing namespace or causes an ambiguity, so I don't think that's a problem either. Being able to write those but not: namespace foo = intrinsic; is just splitting hairs without achieving anything important. I disagree. The rules guarantee that it is possible for the implementation to determine statically whether a particular fixture definition introduces a binding in one of the reserved namespaces. (That actually depends on namespace annotations always being statically resolvable. Some of the details of how that's handled are still open but that's the goal.) That's missing the point. As far as I've seen in this discussion so far, prohibiting namespace foo = intrinsic; does not achieve anything important and it does introduce a weird asymmetry (and yet another strange rule for programmers to memorize) into the language. It does *not* achieve the guarantee that it's statically possible to determine whether a particular fixture definition introduces a binding in one of the reserved namespaces. That guarantee is satisfied by resolving namespaces at compile time, with or without this prohibition. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Next meeting
Brendan Eich wrote: On Apr 28, 2008, at 6:50 PM, Lars Hansen wrote: To my knowledge we are not having a meeting in Vancouver. The next scheduled meeting for ES4 work is the TC meeting in San Francisco at the end of May. That's right -- the tentative plan for a meeting in Vancouver fell through, as the travel burden was too high for key people. OK. That meeting was on the meeting schedule page on the wiki as of yesterday. I don't know if it's there today -- the wiki doesn't answer me right now. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 note: Reserved namespaces
I agree with everything except: * reserved namespaces may not be aliased (ie they are illegal on the right hand side of = in namespace ns1 = ns2) If we want to make reserved namespaces into keywords, that might be ok. However, at the current time they're not keywords, and one could write: const foo = intrinsic; and: namespace instrinsic = my_namespace; Being able to write those but not: namespace foo = intrinsic; is just splitting hairs without achieving anything important. You still shouldn't be able to define properties in the reserved namespaces except as outlined in the proposal. One can also write: var intrinsic = 3; which (I hope) would shadow the intrinsic namespace within its hoisted scope. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Iteration in ES4
Brendan Eich wrote: On Apr 25, 2008, at 2:08 PM, Brendan Eich wrote: for (prop in obj) { ... obj[prop] ... } to look like for each (value in obj) { ... value ... } where obj might be an Array. The symmetry between for-each-in and for- in that E4X half-supports (viz, prototype property enumeration with shadowing, and deleted-after-loop-starts coherence) is broken. Just in case this is not well-known, SpiderMonkey starting in Firefox 1.5 supported E4X and made the for-each-in loop work for all object types, not just XML/XMLList. But not on Array element (indexed property) values only, in index order -- again property creation order, and named as well as indexed enumerable properties, are visited. This shares code with for-in and preserves the equivalence shown in the rewrite example above. I'm baffled trying to figure out what you're trying to say in the last paragraph. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Next meeting
Are we having a meeting in Vancouver? What day and time and what's the agenda? Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Namespaces on definitions
There is an old downside to the attribute syntax: You can't put line breaks between the attributes and the definition, even though it's tempting to do so on long lines. Otherwise you silently change the meaning of existing ES3 code like: foo var bar = 3 Waldemar Jeff Dyer wrote: Here are some other interesting cases involving destructuring patterns. Qualified syntax: var {x = ns::x, y = ns::y, z = ns::z}: {x:A, y:B, z:C } = ... var [ns::x, ns::y, ns::z}: [A, B, C ] = ... Attribute syntax: ns var {x, y, z}: {x:A, y:B, z:C} = ... ns var [x, y, z]: [A, B, C] = ... To my eye the latter are cleaner and clearer. There is another sense in which I think the attribute syntax is better. The identifier is the short name of the binding and having it cleanly delineated from the namespace part of the name makes the meaning of the binding clearer. I agree that having two ways of naming properties is unfortunate, but it’s probably unavoidable. I tried the opposite approach of using ‘var’ and ‘const’ forms in object initializers to get rid of some uses of qualified names there. But in the end, that is just noisier. I’ve resigned myself to the view that “N::X” is the way to name dynamic properties, and “N var X” (and the like) is the way to name fixed properties. Jd On 4/16/08 6:38 AM, Brendan Eich wrote: On Apr 16, 2008, at 2:50 AM, Yuh-Ruey Chen wrote: I agree. I don't see why there should be multiple syntaxes that are as concise as each other and both have about equal precedent (AS3 vs. E4X). If in some futuer spec, properties can inhabit multiple namespaces, then we can consider the |ns1 ns2 ... var foo| syntax again. The syntaxes are not equally concise, not only because :: is heavier visually and in terms of keyboard input (two shifted chars) than spaces. Consider ns var foo, bar; vs. var ns::foo, ns::bar; It's true you can't distribute one type across several variables: var foo:T, bar:T; but that's not a reason to restrict namespace syntax /per se/. Cases of ns including public, protected, private, and internal may be the most useful ones for this distributive syntax, but are those namespaces? Either way, the ns var foo syntax is more concise. /be ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: the global object
My comments on this chapter: The operator form of eval is used before it's described, which confused me while reading this document. It bothers me that the eval operator form and the eval function form produce different valid results for the same input. If we provide both and both are called eval, then the latter must be a subset of the former. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: enumerability
My comments on this chapter: I understand and agree with the simple form of iteration though an object using the empty set of namespaces. On the other hand, I don't see why extending this beyond that functionality is useful. It makes things larger and more complicated and, given that namespaced fixtures aren't enumerated anyway, isn't useful for anything I'd want to use it for like exploring the environment or introspecting data held in records some of whose properties are const. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: DRAFT: Names spec
Mark S. Miller wrote: 2008/4/6 Jeff Dyer [EMAIL PROTECTED] mailto:[EMAIL PROTECTED]: Every unforgeable namespace is considered non-equal to every other namespace. *Implementation* fun compareNamespaces (n1: NAMESPACE, n2: NAMESPACE) : bool = case (n1, n2) of (ForgeableNamespace s1, ForgeableNamespace s2) = s1 = s2 | _ = false In ES3, NaN is the only value that isn't reflexive, i.e., for which x != x or x !== x. Does this spec propose that unforgeable namespaces are also non-reflexive? I pointed out the same thing. I'm pretty sure that's a bug in the document. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Declarations
Michael O'Brien wrote: As a follow up, the following somewhat surprised me. { let b = 1 { function fun() { print(CALL: + b) } } } fun() gives: **ERROR** EvalError: uncaught exception: ReferenceError: unresolved lexical reference {multiname: [ns public '']::b [ns internal '']::b [ns public '__ES4__']::b } (near /Users/dherman/es4/src/builtins/ Error.es:86:55-86.55) ie. the function is hoisted to the outer var block, but does not seem to capture the scope chain of where it was declared and b is out of scope. Is this correct or an RI bug? This is incorrect and an RI bug, but for a different reason: fun should be undefined in the outer scope, since it should not get hoisted out of the inner block, as we agreed at the last face-to-face meeting. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 stable draft: object initializers
My comments: The grammar doesn't work: {meta::prototype:17} can be parsed as either a FieldName or as the meta::prototype production. To make parsing unambiguous you can't allow meta to be included in AnyIdentifier (or implement some other similar fix). Class type discussion: Do the properties in the literal need to have any correspondence to the members of the class? As far as I can tell, they can be anything. If a property name in the record type that annotates the literal What record type? You didn't say that the type has to be a record type here. If a literal field is annotated by |const| or |var| and the field is also named in the record type that annotates the literal then the type of the property is the type given in the record type, not the type implied by the initial value of the property (see below). This paragraph is misplaced. Instead, fix the descriptions of const and var below, as they lead to the wrong conclusion in this case without any hints that they're overridden here. What is the type of fields without a type annotation? Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 stable draft: object initializers
There is also another ambiguity in the grammar: var {x:y, p:q} = expr; is both an assignment expression statement and a destructuring variable binding statement. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: array initializer expressions
My comments: The grammar is ambiguous. var [x, y] = expr; is both an assignment expression statement and a destructuring variable binding statement. How does the length property work for structural type literals? Is it always a fixture? If the array initializer is prefixed by |const| or |var| then the array properties created will be created as fixtures; if the prefix is |const| those fixtures will additionally be read-only. Am I to read this as stating that the length is also a constant if const is used? It's a bit unclear. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Namespaces on definitions
My views on this are: - There should be only *one* syntax for specifying namespaces in definitions. It shouldn't be ns::foo = xyz in one place (object initializers) and ns var foo = xyz someplace else (variable definitions). - The historical reason I chose the syntax ns var foo = xyz for ES4 was that I allowed the same definition to simultaneously go into several namespaces: ns1 ns2 ns3 var foo = xyz would create ns1::foo, ns2::foo, and ns3::foo, which would be aliases of the same variable (not three different variables). ES4 doesn't support that any more, so this reason goes away and the issue can be reconsidered. Now that the issue has been brought up, I'm warming up to the syntax var ns::foo = xyz everywhere. It's simpler to remember. It doesn't match Java, but if that were a goal then we should first change our type annotation syntax to that of C++ and Java. Waldemar Lars Hansen wrote: -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Jon Zeppieri Sent: 11. april 2008 09:50 ... The question is: why not apply it to classes, too? By the way, I was wrong about the grammar allowing var public::count = ... in classes. It doesn't. But why not allow it there and consider it canonical? (Doesn't 'var' also indicate that the property is a fixture in a class definition, too? It's not part of the name, anyway.) One motivation is that programmers are likely to prefer the Java-like syntax where the namespace (in its role as access control) shows up early: public var count = private var key = I really think this is the right syntax for variables. The syntax var private::key, private::foo, public::x, private::bar; is certainly workable and unambiguous but public var x; private var key, foo, bar; works better for me, because the access control is visible and separated from the names, because each phrase is shorter, and because I'm guaranteed to separate my privates from my publics. Classes are sort of funny since you can consider a property name in a class both as a property on the instance (o.id) but also just as a scoped variable, inside all the methods of the class. If you're *really* into Java the former case disappears completely because there will be getter/setter pairs for everything ;) so the scoped variable case is completely dominant. I'm not sure that's wrong, and I think a variable declaration syntax is more natural than an object property syntax. (The syntax of field names in object initializers, on the other hand, is a consequence of how that syntax has evolved.) Matters of taste? To an extent. But preserving brain print from other languages (Java, Python) is not unimportant, it's one of the principles that have been used in designing the language. --lars ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Strict mode recap
Mark Miller wrote: - Disable FunctionObject.arguments (not actually in ES3 but woefully used in practice) This is an interesting one, since disallowing it would mean that the ES3.1 and ES4 specs would have to re-allow it so that they could explicitly disallow it :) Yes. It's also an interesting test of how strong our stomachs are in codifying reality. Any web browser that doesn't provide these will break (or be broken by) the web. However, it has never been specified and should never have been implemented or used. I do think that standards mode should include it and strict mode should ban it. Otherwise, de-facto JavaScript continues to differ too greatly from what's documented. I think this would be going too far. I would not want to normatively introduce this little abomination into the spec even if it's de facto used by legacy scripts in browsers -- it was never in the spec and there are other uses of JavaScript not in browsers that shouldn't have to suffer from it. The same goes for a few of the regexp features/bugs that aren't in ES3. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft LAST CALL: Map
The current definition in 1.2.2 of what Map(o) does is a harmful dead end. The current behavior is: - If o is already a Map then leave it alone. - Otherwise enumerate the visible properties of o and construct a Map out of those. This is harmful because it's guaranteed to cause current and future incompatibilities. There are many other map-like things for which this is the wrong default and we'll be unable to fix them for compatibility reasons. Here are just a few: - If you construct a Map out of a Vector, you want the mapping of indices to the elements, with nothing else. The default behavior brings in extraneous miscellaneous housekeeping properties (length, maybe fixed, perhaps more in the future). - Folks will write libraries that define MultiMap and Set classes. We'll want to later allow natural conversion of these to a Map, but the default will get in the way. For these reasons the current definition of Map(o) is broken and should not be adopted. The fix is to take out the auto-enumerating behavior. If it's needed, it should be done by a static function. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Name
Mark S. Miller wrote: The one use-case I can see for names and namespaces that isn't addressed adequately by existing patterns is expanding the property-name-space, to avoid accidental collisions on extensions to common abstractions. I note that Smalltalk has long faced this issue, and I know of at least three independent proposals for first-class selector names that were intended to address it. At least one of these were actually implemented. None were ever adopted by a significant user community. The problem with all of these is that, by introducing another layer of translation between the identifier the programmer wrote and the thing that's looked up, you have to introduce and explain all the mechanism for determining which translation to use in what context. (The T variant of Scheme is the only example I know where first-class selectors saw significant use. Though widely admired, no other Scheme or Lisp variants picked up on this feature.) Really? Lisp is a great example of the benefit of namespaces. Namespaces are essential to Common Lisp. In my Netscape days I wrote the semantic engine for the reference implementation of ES4 in Common Lisp. Lisp namespaces were crucial to maintaining my sanity while structuring that program. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Nature of Parametrized types
Doing this would require multiple inheritance if you tried to apply it to a two-level class hierarchy. class A.X; class B.X extends A.X; Now consider where the unqualified type B would belong in the hierarchy. Waldemar Peter Hall wrote: Note that this is not to say that the type Cls is nonsensical on its own. Some operations are possible with it: it can be compared to other types, it can be captured as a value and passed around, and it can be instantiated with argument types. You just can't reach into it before it's been parameterized, any more than you can reach into an un-applied function. Ok. Does Cls.int is Cls evaluate to true? ie, could the specification be written so that: class Cls.T1,T2 extends S { /* code using T1 and T2 */ } is compiled as if you had written: class Cls extends S { } but somehow internally marked with the parameters that are required in order to instantiate it. And, on encountering references to Cls.string,int, generate an unnamed class as if created by the following ES4 code: class Cls_string_int extends Cls { /* replace T1,T2,.. here */} So that: new Cls.string,int is Cls; evaluates to true. Then it could also allow code like this: class MyCls.S1 extends Cls.S1,int { /* code using S1 */ } So, when MyCls.string is referenced, it would generate an unnamed class as if written: class MyCls_string extends Cls_string_int { /* */ } And the is relationship holds throughout. The only obvious niggle is that the Java behaviour for statics would naturally emerge, so you would have to take them into special account to get the behaviour you want. ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: union type syntax
There is no solid technical reason for requiring parentheses here. They're here because of people's preferences. I don't find them particularly useful here. Waldemar Peter Hall wrote: Now that union type uses | instead of , for the delimiter, could the parentheses be made optional? It seems like parentheses are used elsewhere only for grouping and function calls/definitions. UnionType ::= Type ( | UnionType )? which should be easily distinguishable from a bitwise OR expression. ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Namespace
Lars Hansen wrote: Please define the terms forgeable and unforgeable in the synopsis before using them later. The terms are (will be) defined in the language part of the spec, and there is already an entry in the NOTES section that defines what they mean for the moment, since the language part does not yet exist. Will that not suffice? I don't know; I'm reviewing the sections based solely on the text you've shared so far, so the questions I note might be answered in parts I haven't seen yet. In this case I'm not sure what you mean by the language part of the spec; ES3 has an overview but it's non-normative. Waldemar ___ 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: 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: 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: eval
Lars Hansen wrote: In my opinion the following is roughly right: obj.eval(x) if eval is the original global eval function then if obj is an ES global object (window, frame) then invoke eval as follows: the scope chain holds that window (global) object only the variable object is that window object the value of this is that window object else this is an error else we don't care; invoke the method eval on obj eval(x) look up eval if the found value v is the original eval function and the binding object x holding eval is an ES global object and the global object on the scope chain for v is x then invoke eval as follows: the scope chain is the lexical chain in effect at the point of invocation the variable object is the innermost variable object in effect (which is to say that it excludes binding objects introduced for let, catch, named function expressions, switch type, and note also that code at the top level of a class is static initialization code so the variable object is the global object) the value of this is the global object x else we don't care; invoke v as a normal function Seems reasonable, although anything dealing with eval evil can get tricky. What about the other cases such as: obj.foo(x) foo(x) new foo(x) where foo happens to contain the original eval function. Do you try to do the eval, throw an EvalError, or do something else? ES3 gave the implementations a choice of either doing the eval or throwing an EvalError. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Vector
new Vector.T ( length=..., fixed=... ) It would be helpful for readability to have the types here. The |Vector| constructor is implementation-defined. This is misleading. Usually when a standard states that something is implementation-defined, it means that its semantics are not specified in the standard. Having no standard-defined vector constructor would be strange indeed. If you merely don't want to write pseudo-code for the Vector constructor, please just omit the Implementation section. Vector( object ) When the |Vector| class object is called as a function, it creates a new variable-length |Vector| object of type |*| ... static meta function invoke(object) { if (object is Vector.*) return object; The description and code don't match. [Also, I'm a bit unclear about how parametrized types currently work. The overview document has examples that seem to indicate that you call bound types as functions. What happens when you call Vector.Foo as a function and pass it a Vector.Bar?] toLocaleString: This seems overspecified. Do you want to explicitly define what happens if the vector is modified in the middle of running this? concat: VectorX cannot be a subtype of VectorY even if X is a subtype of Y. If it were, the type system would be unsound: you could pass a VectorX to a function F expecting a VectoryY and then have F write a Y into that vector. every, filter, etc.: These seem overspecified. For example, the definition of filter states that the implementation must perform the lookup and fetch of each found element twice, which unnecessarily forbids more efficient implementations. forEach: Why is clamp here? The static indexOf method ...: indexOf isn't a static method. Why does indexOf return AnyNumber? lastIndexOf: What happens when you do i-- on a uint with the value of 0? Do you get 4294967295? sort: Doesn't return anything. splice: if (items.length delcnt) { let shift = delcnt - items.length; for ( let n=0, i=first; n shift ; n++, i++ ) this[i] = this[i+shift]; length -= shift; } else { let shift = items.length - delcnt; for ( let n=shift-1, i=first+shift; n = 0 ; n--, i-- ) this[i] = this[i-shift]; } Both of these seem wrong. I think there are at least four different errors here. unshift: Need to raise length first. for ( let i=0 ; i numitems ; i++ ) this[newlimit-i] = this[oldlimit-i]; The bounds on this loop are wrong. 1.4: Typo: defined on directly on When you iterate through Maps, you get the old length if the Map is modified during the iteration. When you iterate through Vectors, you get the new length. The discrepancy seems jarring. fixed should be a constant property or be removed altogether. It's useless as a variable -- anybody can change the length of the vector at any time anyway, and now code that hands out references to vectors to clients has to deal with bozos who make those vectors fixed just for grins. What happens if you try to index a vector with +Infinity or NaN? I assume it's RangeError, but don't know enough about how numerically named properties work. prototype function every(this:Vector.*, checker, thisObj=undefined) (this.intrinsic::every(checker, thisObj is Object) ? thisObj : null); prototype function filter(this:Vector.*, checker, thisObj=undefined) (this.intrinsic::filter(checker, thisObj is Object) ? thisObj : null); prototype function forEach(this:Vector.*, eacher, thisObj=undefined) (this.intrinsic::forEach(checker, thisObj is Object) ? thisObj : null); Why are you passing a boolean as the thisObj argument to intrinsic::every et al.? Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
intrinsic function propertyIsEnumerable(name: EnumerableId, flag: (boolean|undefined) = undefined): boolean I too find the second parameter here abhorrent. Please find another way to solve it (Brendan's namespace idea maybe) or remove this feature altogether. How does property lookup deal with properties indexed by numbers that are not int or uint? toEnumerableId converts them to strings, but the Vector proposal indicated that vectors don't. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft last call: line continuation in string and regex literals
The character sequence BACKSLASH lineterminator (where lineterminator will be one of the characters LF, LS, or PS) is removed from string literals delimited by either single or triple SINGLEQUOTE or DOUBLEQUOTE characters. (Triple-quoting is defined in [5].) This states that: abc\\ tde evaluates to the string abctabde. Is this really what we want? I'd find such nested escape sequences really strange. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 process tweaks
Jeff Dyer wrote: - Phone calls as needed Is there one tomorrow? There's a blank agenda page for it. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft last call: line continuation in string and regex literals
Lars Hansen wrote: The character sequence BACKSLASH lineterminator (where lineterminator will be one of the characters LF, LS, or PS) is removed from string literals delimited by either single or triple SINGLEQUOTE or DOUBLEQUOTE characters. (Triple-quoting is defined in [5].) This states that: abc\\ tde evaluates to the string abctabde. Is this really what we want? I'd find such nested escape sequences really strange. That looks like an illegal token to me, since the lexer will read a b c \ and then see an unescaped linefeed. Since the speclet states nothing about changing the way strings are lexed, normal escape character processing should be in effect, and that dictates that \\ is processed into \ independently of what follows. It's what we all want. As written, that's not what it states. This isn't ready to go in until this bug is corrected. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Object
Lars Hansen wrote: The feature was approved by the WG and solves a practical problem. If another way to solve this practical problem is proposed (in a more structured form than in the ongoing discussion) and finds favor with the WG, then fine -- of course we can replace it. Until then, this feature stays as it is until the WG can be convinced that it needs to be removed. Personally I think that it is ugly/abhorrent is a weak basis on which to remove the current feature. We are the WG. Are you saying that substantive discussions of your proposals are not welcome? Not sure what the point of participating is if that's the case. I'm dealing with a serious insurrection of folks who believe that the ES4 working group has a bad attitude, based on Brendan's public comments and responses to issues like this one. They're quite visible. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Default argument values
Steven Mascaro wrote: One last issue. I was going to leave it till later, but I realised it may affect ES4. The nicest syntax for named arguments would be to use ':', just like with object literals. e.g.: /// Define function foo(arg1 = 0, arg2 = 1) { ... } /// Call foo(arg2: 10, arg1: 5); (I find this even more attractive than the Python syntax.) But this could potentially conflict with the type annotation syntax. e.g.: /// Call foo(arg1: ClassA, arg2); At the moment, the RI throws a ParseError for that, so there's no conflict. I'd like to request that this syntax be reserved solely for named arguments. Fair enough. I don't see any issues with preserving that call syntax for the future. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: ES4 draft: Map
The optional /hashcode/ argument is a function that takes a key and returns a numeric code for it. This code may be used to find associations more quickly in the map. Two calls to the /hashcode/ function on the same key value must return the same numeric code, and the /hashcode/ function must always return the same numeric code for two objects that compare equal by the /equals/ function. The default value for /hashcode/ is the intrinsic global function |hashcode|. Dost thou desire arbitrary numeric hashcodes or integral ones? Map( object ) When the |Map| class object is called as a function, it creates a new |Map| object from |EnumerableId| to |*|, populating the new |Map| object with the own properties of /object/. Making Map(x) do something specialized like this seems like a bad idea. If x is already a Map, I'd expect Map(x) to be idempotent and return x. Should thou need this functionality, use a static method to get it. Why does get return null instead of undefined when it fails to find an instance? A version of get with a second parameter X that returns X when the value isn't present would be useful. Need a clear() method that deletes all bindings. The iteration protocol makes a copy before starting to iterate. It might be implemented via copy-on-write but I'd like to see how expensive this is. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss
Re: Access to spreadsheet
Brendan Eich wrote: On Feb 27, 2008, at 3:59 PM, Waldemar Horwat wrote: I'd like write access to the spreadsheet so we can fill in the Google column: http://spreadsheets.google.com/pub?key=pFIHldY_CkszsFxMkQOReAQgid=2 Also, some features have been omitted from the spreadsheet, such as tuple types. Are those out of the language? It's not that fine-grained. Array types under Structural types includes homogeneous array types (e.g, [int]) and tuple types ([boolean, string]). Most of the categories are quite fine-grained in the spreadsheet. The other kinds of types are in there, so tuples should be listed as well or the entry renamed Array and Tuple types. It's mighty confusing otherwise. Waldemar ___ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss