Re: traits feedback
Thanks for the feedback, John. I have to admit that at first I was also taken aback by the apparent complexity of the syntax for efficient traits strawman. Traits have many knobs, and require a lot of syntax to turn these knobs. Regardless of whether you'd want nice declarative syntax for traits for the sake of usability, for traits.js in particular, there's another important benefit to having some language support. When using Trait.create to create tamper-proof objects whose methods have an unspoofable |this|-binding, the traits.js library creates a method wrapper per method per instance (to bind |this| to the instance). I still need to verify how much overhead this actually creates, but there definitely is overhead, and I don't see any way to avoid it without some support from the language. Cheers, Tom 2011/10/5 John J Barton johnjbar...@johnjbarton.com In trying to update my JS approach I looked into 'traits'. I'm still on the fence about using them at this stage, but MarkM was asking for feedback of pretty much any kind so here is a little. I believe I understand traits for the most part just from the info on the Web site: http://traitsjs.org/ (but read the examples in the Paper, not the one in the Tutorial). Traits feel like JS to me: a reusable set of methods packaged in an object. The Trait construct add regularity and organization to a wide-spread pattern of JS use, but it feels like a tool you pick up when you need it. The key operations are create and compose, with resolve and override to handle exotic issues. On the other hand I had the opposite reaction to http://wiki.ecmascript.org/doku.php?id=strawman:syntax_for_efficient_traits That proposal is a completely different language with many new keywords and operators. I came away deciding to stop using |prototype| + new in favor of Object.create() and to revisit the traits.org library after a bit. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Tue, Oct 4, 2011 at 6:19 PM, David Bruant david.bru...@labri.fr wrote: ** I sent a message here explaining the necessity of a syntax construct for a reliable bind [1]. There is a need to investingate (one reply was very close from a solution) to make sure that such a thing is not possible in pure ES5 (without making Function.prototype.bind non-configurable), but that would be one such thing that no language compiling to JavaScript could emulate (since impossible in the language itself). I don't think security from malicious changes to Function.prototype.bind is a good argument for adding new operator syntax. The problem doesn't stop with Function.prototype.bind. ES5 as a compilation target is built on a quagmire since almost all fundamental language operations are methods that can be changed. The operators are the exception, since you can't override their meaning[1], and I can see why you wish to introduce modification-safe operators for the operations you want to preserve - but why is Function.prototype.bind more important than, say, Math.pow? In the wrong hands, I'm sure you can subvert an encryption algorithm with a malicious Math.pow. We can't have operators for all functions, and you can't check every function before using it (and it wouldn't help if you could). Also, with proxies and getters/setters, even operators aren't guaranteed to be safe unless they are defined extremely carefully. It used to be that property access (o.foo) was a safe way to look up a property on an object. Now it might trigger a proxy or accessor instead. This has actually diluted the safety of operators. Will new operators that seem safe now be diluted the same way in the future? With ES5 getters and (inherited!) setters, you can install a javascript rootkit that modifies some of the builtins, perhaps put some selected getters/setters on Object.prototype, and hides every trace of it from other scripts. To prevent that kind of maliciousness, you need to go the way of SES and lock down the entire environment *before* any untrusted code is touched, and in that case Function.prototype.bind is just as safe as an operator. (On the other hand, it's actually a fun experience to write Javascript code that can't be affected by a modified environment - the same way three-legged races are fun :) Personally, I'd prefer all the built-in functions to be unconfigurable, so a language user would actually know what function they are calling ahead of time. /L 'Freeze them! Freeze them all!' [1] But the operators can potentially do type coercion that allows arbitrary side-effects at unexpected times. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
Le 05/10/2011 10:17, Lasse Reichstein a écrit : On Tue, Oct 4, 2011 at 6:19 PM, David Bruant david.bru...@labri.fr mailto:david.bru...@labri.fr wrote: I sent a message here explaining the necessity of a syntax construct for a reliable bind [1]. There is a need to investingate (one reply was very close from a solution) to make sure that such a thing is not possible in pure ES5 (without making Function.prototype.bind non-configurable), but that would be one such thing that no language compiling to JavaScript could emulate (since impossible in the language itself). I don't think security from malicious changes to Function.prototype.bind is a good argument for adding new operator syntax. The problem doesn't stop with Function.prototype.bind. ES5 as a compilation target is built on a quagmire since almost all fundamental language operations are methods that can be changed. The operators are the exception, since you can't override their meaning[1], and I can see why you wish to introduce modification-safe operators for the operations you want to preserve - but why is Function.prototype.bind more important than, say, Math.pow? The difference I saw is that you can keep a reference to Math.pow within a scope of yours and you'll be fine. Such a thing doesn't seem possible with call, apply and bind, mostly because you need to rely on at least one of them in order to do call.call or call.bind, etc. and consequently, you always depend on the value on Function.prototype.* in a way or another. As i said before, there is a reliable way to do a call which is f(), but you can't choose the value of |this|. That's what originally motivated the idea of a syntax-based bind. I don't think that the other functions require such a thing. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
Since you're assuming you can initialize and grab stuff before your context is corrupted, what's wrong with Lasse's earlier (and very clever!) var call = Function.prototype.call.bind(Function.prototype.call); and by direct analogy: var apply = Function.prototype.call.bind(Function.prototype.apply); var bind = Function.prototype.call.bind(Function.prototype.bind); ? If there's a vulnerability with this technique, I need to know that asap, as I'm about to start writing code that depends on it for security. So any vulnerabilities you or anyone can point out now will be greatly appreciated. Thanks. On Wed, Oct 5, 2011 at 10:24 AM, David Bruant david.bru...@labri.fr wrote: ** Le 05/10/2011 10:17, Lasse Reichstein a écrit : On Tue, Oct 4, 2011 at 6:19 PM, David Bruant david.bru...@labri.frwrote: I sent a message here explaining the necessity of a syntax construct for a reliable bind [1]. There is a need to investingate (one reply was very close from a solution) to make sure that such a thing is not possible in pure ES5 (without making Function.prototype.bind non-configurable), but that would be one such thing that no language compiling to JavaScript could emulate (since impossible in the language itself). I don't think security from malicious changes to Function.prototype.bind is a good argument for adding new operator syntax. The problem doesn't stop with Function.prototype.bind. ES5 as a compilation target is built on a quagmire since almost all fundamental language operations are methods that can be changed. The operators are the exception, since you can't override their meaning[1], and I can see why you wish to introduce modification-safe operators for the operations you want to preserve - but why is Function.prototype.bind more important than, say, Math.pow? The difference I saw is that you can keep a reference to Math.pow within a scope of yours and you'll be fine. Such a thing doesn't seem possible with call, apply and bind, mostly because you need to rely on at least one of them in order to do call.call or call.bind, etc. and consequently, you always depend on the value on Function.prototype.* in a way or another. As i said before, there is a reliable way to do a call which is f(), but you can't choose the value of |this|. That's what originally motivated the idea of a syntax-based bind. I don't think that the other functions require such a thing. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
Le 05/10/2011 10:33, Mark S. Miller a écrit : Since you're assuming you can initialize and grab stuff before your context is corrupted, what's wrong with Lasse's earlier (and very clever!) var call = Function.prototype.call.bind(Function.prototype.call); and by direct analogy: var apply = Function.prototype.call.bind(Function.prototype.apply); var bind = Function.prototype.call.bind(Function.prototype.bind); ? Nothing's wrong. I forgot about this, sorry. It is indeed very clever. I take back what I said about the necessity of a syntax construct for bind. David If there's a vulnerability with this technique, I need to know that asap, as I'm about to start writing code that depends on it for security. So any vulnerabilities you or anyone can point out now will be greatly appreciated. Thanks. On Wed, Oct 5, 2011 at 10:24 AM, David Bruant david.bru...@labri.fr mailto:david.bru...@labri.fr wrote: Le 05/10/2011 10:17, Lasse Reichstein a écrit : On Tue, Oct 4, 2011 at 6:19 PM, David Bruant david.bru...@labri.fr mailto:david.bru...@labri.fr wrote: I sent a message here explaining the necessity of a syntax construct for a reliable bind [1]. There is a need to investingate (one reply was very close from a solution) to make sure that such a thing is not possible in pure ES5 (without making Function.prototype.bind non-configurable), but that would be one such thing that no language compiling to JavaScript could emulate (since impossible in the language itself). I don't think security from malicious changes to Function.prototype.bind is a good argument for adding new operator syntax. The problem doesn't stop with Function.prototype.bind. ES5 as a compilation target is built on a quagmire since almost all fundamental language operations are methods that can be changed. The operators are the exception, since you can't override their meaning[1], and I can see why you wish to introduce modification-safe operators for the operations you want to preserve - but why is Function.prototype.bind more important than, say, Math.pow? The difference I saw is that you can keep a reference to Math.pow within a scope of yours and you'll be fine. Such a thing doesn't seem possible with call, apply and bind, mostly because you need to rely on at least one of them in order to do call.call or call.bind, etc. and consequently, you always depend on the value on Function.prototype.* in a way or another. As i said before, there is a reliable way to do a call which is f(), but you can't choose the value of |this|. That's what originally motivated the idea of a syntax-based bind. I don't think that the other functions require such a thing. David ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
dunno how we ended up here but I would rather use this approach in a private scope: var // used to trap function calls via bind invoke = Function.call, // normal use cases bind = invoke.bind(invoke.bind), apply = bind(invoke, invoke.apply), call = bind(invoke, invoke) ; var hasOwnProperty = bind(invoke, {}.hasOwnProperty); hasOwnProperty({key:1}, key); // true call([].slice, [1,2,3], 1); // 2,3 apply([].slice, [1,2,3], [1]); // 2,3 Regards, Andrea Giammarchi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: OnIncremental Updates)
Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. One standard way around this dilemma is to execute such code abstractly (known as abstract interpretation). What that means is that the code is run through an alternative engine that does not execute the code in full detail, but only as far as necessary in order to infer some interesting properties. In particular, one wants the abstract interpretation not to have side-effects (like network or file system operations) and one wants it to terminate (quickly; so branches and recursion tend to be approximated). Unfortunately, interesting properties tend to be undecidable, ie, they cannot be extracted from arbitrary code while guaranteeing termination (oversimplifying: you have to run such code in full to find out what it does..). There is no magic cure for this, but it is possible to design languages and programs in such a way that a practically relevant subset of the properties of interest becomes decidable. Doing that requires thought and a lot of work (and open minds to begin with), but the benefits tend to be worth it. Without support from language and program designers, it does not matter how many companies throw how much money at tool development (no magic bullets). Unless you want to find out how much money they are willing or able to throw before they start throwing towels. Support is not so much about syntax as it is about statically recognizable programming patterns (so that one can distinguish code with arbitrary effects from code that just adds properties to a class of objects, or export items to a module; and so that one can extract useful program properties without having to run the code in full). The reason syntax tends to be mentioned is because syntax frozen in the language spec tends to be less flexible than general code implementing the same feature in the language. So it looks easier to analyze, and cannot be re-defined (in current JS). But adding this kind of special-case syntax makes a language more complex, by adding lots of constructs that -by design- do not support the full expressiveness of the language. Other languages have demonstrated that one can fix programming patterns sufficiently to permit analysis, without fixing syntax (added bonus: less syntax, less complexity -easier for coders and tools to read/analyze- and more general usage patterns through homogeneous syntax with few special cases). For this particular problem (improving analysis support), syntax is the wrong level to work at, but in order to see that, one would have to make an effort to work with modern type systems - why they work, and how that interacts with language and program design. To begin with, one can think of a type system as an abstract interpretation engine with enhanced information flow, and of types as program properties. Also, if coders can express their intentions (do they really mean an object, or a record, or a map, or an array, ..?), it tends to be easier to check whether an implementation matches those intentions (within the limits of decidability, so one is usually looking at guaranteeing invariants) than to guess what those intentions were in the first place (is this a function or a method and should we give it dynamic super or not? are objects from this constructor expected to retain a certain set of properties or can they change arbitrarily? is this function going to spider the web, or will it just add a few methods to an object? can we rely on function F to be the one in the spec, or could it have been overwritten?). It would be great if vocal JS coders with strongly expressed opinions (often in error, never in doubt) could try a language like Haskell for a mini project. Don't worry about advanced features, just convince yourself that a static type system does not have to get in the way as often as one might expect. Then, for your second project, start thinking about what you and the language have to do to make better use of types, rather than just get your code to compile: where do you have to change your coding patterns, compared to what you would do in JS, and how does that help the type system? After taking these two steps (*), you will be ready to think about the pros and cons of syntax or types for helping JS tools with code analysis. And then about how this should affect JS language design. The basics don't require a big effort, but one should allow that type/analysis research has not been idle in the
Re: On I got 99 problems and JavaScript syntax ain't one
On Tue, Oct 4, 2011 at 2:33 PM, Bob Nystrom rnyst...@google.com wrote: On Tue, Oct 4, 2011 at 2:12 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 12:59 PM, Bob Nystrom rnyst...@google.com wrote: A constructor is different from a regular function. Instead of returning the value that the body of the function returns, it returns a special newly-created object. Sorry, already you lost me ;-) I guess you mean the operand of new? If so, then the different thing is the operator 'new'. It's new that makes the operand a constructor. It's the yield that makes a function a generator. One is visible at the callsite (which means you can *forget* it at the callsite), the other is visible at the definition. Likewise, a generator is a special function that doesn't return what the body returns. But it does not look special. There is nothing similar to 'new' involved in the invocation of the generator. That's good because it means whether or not a function returns an iterable object by using yield or through some other means is an implementation detail of the function and doesn't bleed into every callsite. Let's say generators *did* have a callsite difference. Now imagine: function countdown() { for (let i = 10; i = 1; i--) yield i; } let counter = generate countdown(); // -- in callsite for (let i of counter) alert(i); alert('boom!'); This magic generate keyword means the function is to be treated like a generator. But then later it turns out that -- is really slow and you want to change countdown to: function countdown() { return [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; } Well, you can't. You'd have to fix each callsite too. Your abstraction has leaked. So I think generators do the right thing here. (And, conversely, I kind of think constructors do the *wrong* thing.) We can agree that |new| is a mess even if we don't agree on generators. and the state of the generator is hidden from the developer as far as I can tell. That's correct. That's often the cost of concision. By analogy: you can do a lot of stuff using either an explicit stack data structure or recursion. Using recursion is often more concise but then the state is hidden from you in the callstack. Sometimes that's a good trade-off, sometimes it's not. Thanks, that analogy helps confirm my opinion of generators. In my experience, the good trade-off is recursion on data structures and the not-good-trade-off is recursion for iteration. So far the only examples I've seen for generators involve iteration. I think generators are an excellent example of a feature that is well prototyped (in FF JS 1.7+). I think the developer uptake is minimal, outside of the original advocates. I don't hear any clamor for other browsers to implement this feature. Browsers don't clamor, users do. If it was up to the browsers, they wouldn't implement anything. Implementing is hard work! I've heard no clamor at all. Really this is a niche feature, an aid for the rare case where conventional iterators are a poor match. jjb In languages that do have yield (Python, C#, and Lua are the ones I know) it's used pretty frequently and without complaint. Either way, class deserves at least as much investigation. Agreed! - bob ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 12:52 AM, Tom Van Cutsem tomvc...@gmail.com wrote: Thanks for the feedback, John. I have to admit that at first I was also taken aback by the apparent complexity of the syntax for efficient traits strawman. Traits have many knobs, and require a lot of syntax to turn these knobs. Regardless of whether you'd want nice declarative syntax for traits for the sake of usability, for traits.js in particular, there's another important benefit to having some language support. When using Trait.create to create tamper-proof objects whose methods have an unspoofable |this|-binding, the traits.js library creates a method wrapper per method per instance (to bind |this| to the instance). I still need to verify how much overhead this actually creates, but there definitely is overhead, and I don't see any way to avoid it without some support from the language. Yes I sensed your anguish about this issue. However I believe experimental measurements might surprise you. Lots of JS code involves event handlers passed into DOM calls. I bet lots of JS code already duplicates methods and bind |this|. Only when you have many instances will this overhead matter, and in those cases I think you might be better off without OOP anyway. jjb Cheers, Tom 2011/10/5 John J Barton johnjbar...@johnjbarton.com In trying to update my JS approach I looked into 'traits'. I'm still on the fence about using them at this stage, but MarkM was asking for feedback of pretty much any kind so here is a little. I believe I understand traits for the most part just from the info on the Web site: http://traitsjs.org/ (but read the examples in the Paper, not the one in the Tutorial). Traits feel like JS to me: a reusable set of methods packaged in an object. The Trait construct add regularity and organization to a wide-spread pattern of JS use, but it feels like a tool you pick up when you need it. The key operations are create and compose, with resolve and override to handle exotic issues. On the other hand I had the opposite reaction to http://wiki.ecmascript.org/doku.php?id=strawman:syntax_for_efficient_traits That proposal is a completely different language with many new keywords and operators. I came away deciding to stop using |prototype| + new in favor of Object.create() and to revisit the traits.org library after a bit. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. jjb jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. jjb jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 10:48 AM, John J Barton johnjbar...@johnjbarton.comwrote: On Wed, Oct 5, 2011 at 12:52 AM, Tom Van Cutsem tomvc...@gmail.comwrote: Thanks for the feedback, John. I have to admit that at first I was also taken aback by the apparent complexity of the syntax for efficient traits strawman. Traits have many knobs, and require a lot of syntax to turn these knobs. Regardless of whether you'd want nice declarative syntax for traits for the sake of usability, for traits.js in particular, there's another important benefit to having some language support. When using Trait.create to create tamper-proof objects whose methods have an unspoofable |this|-binding, the traits.js library creates a method wrapper per method per instance (to bind |this| to the instance). I still need to verify how much overhead this actually creates, but there definitely is overhead, and I don't see any way to avoid it without some support from the language. Yes I sensed your anguish about this issue. However I believe experimental measurements might surprise you. Lots of JS code involves event handlers passed into DOM calls. I bet lots of JS code already duplicates methods and bind |this|. Only when you have many instances will this overhead matter, and in those cases I think you might be better off without OOP anyway. It's been measured: https://mail.mozilla.org/pipermail/es-discuss/2010-September/011821.html ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 8:21 AM, Dean Landolt d...@deanlandolt.com wrote: On Wed, Oct 5, 2011 at 10:48 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 12:52 AM, Tom Van Cutsem tomvc...@gmail.comwrote: Thanks for the feedback, John. I have to admit that at first I was also taken aback by the apparent complexity of the syntax for efficient traits strawman. Traits have many knobs, and require a lot of syntax to turn these knobs. Regardless of whether you'd want nice declarative syntax for traits for the sake of usability, for traits.js in particular, there's another important benefit to having some language support. When using Trait.create to create tamper-proof objects whose methods have an unspoofable |this|-binding, the traits.js library creates a method wrapper per method per instance (to bind |this| to the instance). I still need to verify how much overhead this actually creates, but there definitely is overhead, and I don't see any way to avoid it without some support from the language. Yes I sensed your anguish about this issue. However I believe experimental measurements might surprise you. Lots of JS code involves event handlers passed into DOM calls. I bet lots of JS code already duplicates methods and bind |this|. Only when you have many instances will this overhead matter, and in those cases I think you might be better off without OOP anyway. It's been measured: https://mail.mozilla.org/pipermail/es-discuss/2010-September/011821.html Well that reference says it was tried once in an undocumented way by one team focused on other things. Falls short of 'measured' for me. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
String concatenation
Is this worthy of ES.next support? Or does it belong into a library? The two concatenation approaches I know of are: 1. via += 2. push() into an array, join() it after the last push() (1) can’t possibly be efficient, but if (2) is OK on all(!) platforms, then a library would be OK. However, given how frequently this is used, I would like this to become part of the standard library. -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
Here again I am not sure how we ended up with this conversation but you can find a function able to extract properties and methods out of a generic object: https://gist.github.com/1264775 It works with jQuery too, as well as arrays, etc etc Regards, Andrea Giammarchi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 8:05 AM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. Oh I got burnt by static analysis before, I should know better. I keep thinking that static analysis means analysis of a single compilation unit outside of the runtime as most IDEs for statically typed languages use. I meant: if your tool is embedded in the run time then it knows the exact jQuery API because it can scan the exact jQuery object. No code on this jQuery object needs to run (though that issue is not a show stopper in practice, witness breakpoint debugging). I don't know what to call runtime analysis that does not run extraneous code. jjb jjb jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 11:48 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Here again I am not sure how we ended up with this conversation but you can find a function able to extract properties and methods out of a generic object: https://gist.github.com/1264775 It works with jQuery too, as well as arrays, etc etc Regards, Andrea Giammarchi Its a nice snippet, but it does require executing the code. It clearly operates on an object in running code, not an AST. Sorry, I guess I just don't understand where this thread is going.. :) - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 8:57 AM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 11:48 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Here again I am not sure how we ended up with this conversation but you can find a function able to extract properties and methods out of a generic object: https://gist.github.com/1264775 It works with jQuery too, as well as arrays, etc etc Regards, Andrea Giammarchi Its a nice snippet, but it does require executing the code. It clearly operates on an object in running code, not an AST. Sorry, I guess I just don't understand where this thread is going.. :) We are trying to convince you that limiting your analysis to ASTs will limit the scope of your tools ;-). jjb - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
with such dynamic language I would never trust much AST This is for realtime, inline, methods and properties suggestion and it's kinda fast as macro/inspector I don't know where the thread is going either :-) On Wed, Oct 5, 2011 at 5:57 PM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 11:48 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: Here again I am not sure how we ended up with this conversation but you can find a function able to extract properties and methods out of a generic object: https://gist.github.com/1264775 It works with jQuery too, as well as arrays, etc etc Regards, Andrea Giammarchi Its a nice snippet, but it does require executing the code. It clearly operates on an object in running code, not an AST. Sorry, I guess I just don't understand where this thread is going.. :) - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String concatenation
On Wed, Oct 5, 2011 at 11:45 AM, Axel Rauschmayer a...@rauschma.de wrote: Is this worthy of ES.next support? Or does it belong into a library? The two concatenation approaches I know of are: 1. via += 2. push() into an array, join() it after the last push() (1) can’t possibly be efficient, Huh? Engines have optimized the hell out of 1 by essentially doing 2 under the hood. Even rhino's about a land a patch to do just that. but if (2) is OK on all(!) platforms, then a library would be OK. However, given how frequently this is used, I would like this to become part of the standard library. What exactly do you want supported? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String concatenation
On 05.10.2011 19:45, Axel Rauschmayer wrote: Is this worthy of ES.next support? Or does it belong into a library? The two concatenation approaches I know of are: 1. via += 2. push() into an array, join() it after the last push() (1) can’t possibly be efficient, but if (2) is OK on all(!) platforms, then a library would be OK. However, given how frequently this is used, I would like this to become part of the standard library. 15.5.4.6 String.prototype.concat Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String concatenation
The two concatenation approaches I know of are: 1. via += 2. push() into an array, join() it after the last push() (1) can’t possibly be efficient, Huh? Engines have optimized the hell out of 1 by essentially doing 2 under the hood. Even rhino's about a land a patch to do just that. but if (2) is OK on all(!) platforms, then a library would be OK. However, given how frequently this is used, I would like this to become part of the standard library. What exactly do you want supported? Something like Java’s StringBuilder. If, however, (2) collects the concatenated substrings and only joins them on demand in current engines, then there is indeed no need for such a thing. -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 11:49 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 8:05 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. Oh I got burnt by static analysis before, I should know better. I keep thinking that static analysis means analysis of a single compilation unit outside of the runtime as most IDEs for statically typed languages use. I meant: if your tool is embedded in the run time then it knows the exact jQuery API because it can scan the exact jQuery object. No code on this jQuery object needs to run (though that issue is not a show stopper in practice, witness breakpoint debugging). I don't know what to call runtime analysis that does not run extraneous code. I see, yes. Yeah, I mean if I run the JavaScript console in chrome I get nice autocompletion because its using the running environment to know what properties an object has. I believe this is what a lot of smalltalk IDEs used to do. There are still a lot of limitations, though. I mean, what is the purpose of the analysis in the long run. Modern Java IDEs can do a lot of things with static analysis that are very helpful like refactoring and autocompletion. Look, I'm not trying to turn this into a static vs. dynamic debate, my point is that there are a lot of limitations - and useful tooling that is impossible with dynamic code. I think we got here because someone was trying to make the point that the ability to add statically analyzable constraints would be useful to tooling. In JavaScript, the way to do that may have to be through syntactic additions such as extends or |. I'm certainly not opposed to analysis that goes beyond ASTs. I say, any way you can get it! - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 12:04 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: with such dynamic language I would never trust much AST This is for realtime, inline, methods and properties suggestion and it's kinda fast as macro/inspector I don't know where the thread is going either :-) It would also break as soon as you hit your first function call until that function got executed. :) - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String concatenation
On Wed, Oct 5, 2011 at 12:10 PM, Axel Rauschmayer a...@rauschma.de wrote: The two concatenation approaches I know of are: 1. via += 2. push() into an array, join() it after the last push() (1) can’t possibly be efficient, Huh? Engines have optimized the hell out of 1 by essentially doing 2 under the hood. Even rhino's about a land a patch to do just that. but if (2) is OK on all(!) platforms, then a library would be OK. However, given how frequently this is used, I would like this to become part of the standard library. What exactly do you want supported? Something like Java’s StringBuilder. If, however, (2) collects the concatenated substrings and only joins them on demand in current engines, then there is indeed no need for such a thing. GWT's implementation of StringBuilder actually uses both methods #1 and #2 under the hood, because each is faster on different browsers (due to deferred binding, you only get the implementation for the browser you are using and parts of it can be inlined at call sites so you don't pay the penalty for multiple implementations). -- John A. Tamplin Software Engineer (GWT), Google ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Wed, Oct 5, 2011 at 10:18 AM, John J Barton johnjbar...@johnjbarton.comwrote: On Tue, Oct 4, 2011 at 2:33 PM, Bob Nystrom rnyst...@google.com wrote: On Tue, Oct 4, 2011 at 2:12 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 12:59 PM, Bob Nystrom rnyst...@google.comwrote: A constructor is different from a regular function. Instead of returning the value that the body of the function returns, it returns a special newly-created object. Sorry, already you lost me ;-) I guess you mean the operand of new? If so, then the different thing is the operator 'new'. It's new that makes the operand a constructor. It's the yield that makes a function a generator. One is visible at the callsite (which means you can *forget* it at the callsite), the other is visible at the definition. Likewise, a generator is a special function that doesn't return what the body returns. But it does not look special. There is nothing similar to 'new' involved in the invocation of the generator. That's good because it means whether or not a function returns an iterable object by using yield or through some other means is an implementation detail of the function and doesn't bleed into every callsite. Let's say generators *did* have a callsite difference. Now imagine: function countdown() { for (let i = 10; i = 1; i--) yield i; } let counter = generate countdown(); // -- in callsite for (let i of counter) alert(i); alert('boom!'); This magic generate keyword means the function is to be treated like a generator. But then later it turns out that -- is really slow and you want to change countdown to: function countdown() { return [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; } Well, you can't. You'd have to fix each callsite too. Your abstraction has leaked. So I think generators do the right thing here. (And, conversely, I kind of think constructors do the *wrong* thing.) We can agree that |new| is a mess even if we don't agree on generators. and the state of the generator is hidden from the developer as far as I can tell. That's correct. That's often the cost of concision. By analogy: you can do a lot of stuff using either an explicit stack data structure or recursion. Using recursion is often more concise but then the state is hidden from you in the callstack. Sometimes that's a good trade-off, sometimes it's not. Thanks, that analogy helps confirm my opinion of generators. In my experience, the good trade-off is recursion on data structures and the not-good-trade-off is recursion for iteration. So far the only examples I've seen for generators involve iteration. I think generators are an excellent example of a feature that is well prototyped (in FF JS 1.7+). I think the developer uptake is minimal, outside of the original advocates. I don't hear any clamor for other browsers to implement this feature. Browsers don't clamor, users do. If it was up to the browsers, they wouldn't implement anything. Implementing is hard work! I've heard no clamor at all. Really this is a niche feature, an aid for the rare case where conventional iterators are a poor match. Generators are more than iteration optimizations -- they enable shallow frame continuations, and open the doors to some really nice async programming patterns (just the beginnings of which are demonstrated by Dave Herman's task.js [1]). Again, they're not fully implemented in any engine, so library support is practically non-existent. How are users supposed to clamor for a feature that can't demonstrate itself as advantageous? I've heard plenty of calls for language-level async support -- generators enable this without the well-documented hazards of the alternatives. [1] https://github.com/dherman/taskjs ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: OnIncremental Updates)
On Wed, Oct 5, 2011 at 10:03 AM, Claus Reinke claus.rei...@talk21.com wrote: Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. One standard way around this dilemma is to execute such code abstractly (known as abstract interpretation). What that means is that the code is run through an alternative engine that does not execute the code in full detail, but only as far as necessary in order to infer some interesting properties. In particular, one wants the abstract interpretation not to have side-effects (like network or file system operations) and one wants it to terminate (quickly; so branches and recursion tend to be approximated). Unfortunately, interesting properties tend to be undecidable, ie, they cannot be extracted from arbitrary code while guaranteeing termination (oversimplifying: you have to run such code in full to find out what it does..). There is no magic cure for this, but it is possible to design languages and programs in such a way that a practically relevant subset of the properties of interest becomes decidable. Doing that requires thought and a lot of work (and open minds to begin with), but the benefits tend to be worth it. Without support from language and program designers, it does not matter how many companies throw how much money at tool development (no magic bullets). Unless you want to find out how much money they are willing or able to throw before they start throwing towels. Support is not so much about syntax as it is about statically recognizable programming patterns (so that one can distinguish code with arbitrary effects from code that just adds properties to a class of objects, or export items to a module; and so that one can extract useful program properties without having to run the code in full). The reason syntax tends to be mentioned is because syntax frozen in the language spec tends to be less flexible than general code implementing the same feature in the language. So it looks easier to analyze, and cannot be re-defined (in current JS). But adding this kind of special-case syntax makes a language more complex, by adding lots of constructs that -by design- do not support the full expressiveness of the language. Other languages have demonstrated that one can fix programming patterns sufficiently to permit analysis, without fixing syntax (added bonus: less syntax, less complexity -easier for coders and tools to read/analyze- and more general usage patterns through homogeneous syntax with few special cases). For this particular problem (improving analysis support), syntax is the wrong level to work at, but in order to see that, one would have to make an effort to work with modern type systems - why they work, and how that interacts with language and program design. To begin with, one can think of a type system as an abstract interpretation engine with enhanced information flow, and of types as program properties. Also, if coders can express their intentions (do they really mean an object, or a record, or a map, or an array, ..?), it tends to be easier to check whether an implementation matches those intentions (within the limits of decidability, so one is usually looking at guaranteeing invariants) than to guess what those intentions were in the first place (is this a function or a method and should we give it dynamic super or not? are objects from this constructor expected to retain a certain set of properties or can they change arbitrarily? is this function going to spider the web, or will it just add a few methods to an object? can we rely on function F to be the one in the spec, or could it have been overwritten?). I agree with this 100%. Languages as dynamic as JavaScript and Ruby are interesting, because as much as the freedoms can allow for more concise code and a level of expression that can often be difficult to achieve in more statically typed languages, it can also lead to a place with almost no constraints or guarantees. Sometimes these guarantees can be remarkably useful for the coder, the compiler, and the tooling. It would be great if vocal JS coders with strongly expressed opinions (often in error, never in doubt) could try a language like Haskell for a mini project. Don't worry about advanced features, just convince yourself that a static type system does not have to get in the way as often as one might expect. I don't think I qualify as a vocal
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
Sorry Russ, I am not sure I got it On Wed, Oct 5, 2011 at 6:14 PM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 12:04 PM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: with such dynamic language I would never trust much AST This is for realtime, inline, methods and properties suggestion and it's kinda fast as macro/inspector I don't know where the thread is going either :-) It would also break as soon as you hit your first function call until that function got executed. :) - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Minor issues with proxies
Hi Mark, Tom! I understand that you are currently working on finalizing a number of aspects of the proxies proposal, so I thought I'd send my current notes on issues I discovered. (Sorry if I'm a bit late with that, but I just returned from travelling.) Here is a list of minor issues. I'll send a separate mail describing what I think is a more fundamental problem with the current spec. - Proxy.create: What if the handler passed is not an object? Should we throw right away? - Proxy.create: What if the prototype passed is neither an object nor null? FF silently sets it to null in all other cases, but that seems inconsistent with Object.create, which throws. - Proxy.createFunction: More of a question, but do we really want to support a separate construct trap for function proxies? I would argue that it was a mistake to ever make a distinction between a regular and a construct call. Even if we cannot clean that up, we should perhaps avoid having it proliferate further, in the proxy interface. - Derived get/set traps: They use .call on accessor functions taken from a user-defined descriptor. Such a function might itself be a proxy, in which case .call is not necessarily defined. Should invoke it through Function.prototype.call.call instead. (There may be other places in the current ES spec that assume that all functions have a call method. I think they should all be changed.) - Also, we should specify that the JS code assumes that all used intrinisc properties are the original methods. - Object.{seal,freeze,preventExtensions}: When sealing a function proxy, how do we initialize the standard properties length, constructor, prototype, caller, and arguments? What if the proxy does not define them already, or returns unsuitable values? - Function.prototype.toString: should this work for function proxies? - Function.prototype.bind: requires additional language explaining how the length property is set if the curried function is a proxy. - JSON: don't we need some changes here, too? For example, step 6a of the JO operation (15.12.3) talks about the names of all the own properties of an object. Clearly, for a proxy we need to invoke the appropriate trap here. - Outside the (current?) standard, but pragmatically, how should we treat .__proto__ on a proxy? FF and V8 both treat it as an ordinary property for proxies, but that implies that Object.getPrototypeOf(p) != p.__proto__ in general. - ToStringArray, step 6.a: s/array/O/ /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Proxy-induced impurity of internal methods
Proxies invalidate one fundamental assumption of the current ES spec, namely that (most) internal methods are effectively pure. That has a couple of consequences which the current proxy proposal and semantics seem to ignore, but which we need to address. OBSERVABILITY EFFICIENCY In ES5, internal methods essentially are an implementation detail of the spec. AFAICS, there is no way their interaction is actually observable in user code. This gives JS implementations significant leeway in implementing objects (and they make use of it). This changes drastically with proxies. In particular, since most internal methods may now invoke traps directly or indirectly, we can suddenly observe many internal steps of property lookup and similar operations through potential side effects of these traps. (Previously, only the invocation of getters or setters was observable). Take the following simple example: var desc = {configurable: true, get: function() {return 8}, set: function() {return true}} var handler = {getPropertyDescriptor: function() {seq += G; return desc}} var p = Proxy.create(handler) var o = Object.create(p) var seq = o.x var seq1 = seq seq = o.x = 0 var seq2 = seq According to the proxy spec, we should see seq1==G and seq2==GG. In my local version of V8, I currently see seq1==G and seq2==G. In Firefox 7, I see seq1==GG and seq2==GG. Obviously, both implementations are unfaithful to the spec, albeit in reverse ways. At least for V8, implementing the correct behaviour may require significant changes. Also, I wonder whether the current semantics forcing seq2==GG really is what we want, given that it is unnecessarily inefficient (note that it also involves converting the property descriptor twice, which in turn can spawn numerous calls into user code). Optimizing this would require purity analysis on trap functions, which seems difficult in general. HIDDEN ASSUMPTIONS In a number of places, the ES5 spec makes hidden assumptions about the purity of internal method calls, and derives certain invariants from that, which break with proxies. For example, in the spec of [[Put]] (8.12.5), step 5.a asserts that desc.[[Set]] cannot be undefined. That is true in ES5, but no longer with proxies. Unsurprisingly, both Firefox and V8 do funny things for the following example: var handler = { getPropertyDescriptor: function() { Object.defineProperty(o, x, {get: function() { return 5 }}) return {set: function() {}} } } var p = Proxy.create(handler) var o = Object.create(p) o.x = 4 Firefox 7: InternalError on line 1: too much recursion V8: TypeError: Trap #error of proxy handler #Object returned non-configurable descriptor for property x More generally, there is no guarantee anymore that the result of [[CanPut]] in step 1 of [[Put]] is in any way consistent with what we see in later steps. In this light (and due to the efficiency reasons I mentioned earlier), we might want to consider rethinking the CanPut/Put split. This is just one case. There may be other problematic places in other operations. Most of them are probably more subtle, i.e. the spec still prescribes some behaviour, but that does not necessarily make any sense for certain cases (and would be hard to implement to the letter). We probably need to check the whole spec very carefully. FIXING PROXIES A particularly worrisome side effect is fixing a proxy. The proxy semantics contains a lot of places saying If O is a trapping proxy, do steps I-J. However, there generally is no guarantee that O remains a trapping proxy through all of I-J! Again, an example: var handler = { get set() { Object.freeze(p); return undefined }, fix: function() { return {} } } var p = Proxy.create(handler) p.x Firefox 7: TypeError on line 1: getPropertyDescriptor is not a function V8: TypeError: Object #Object has no method 'getPropertyDescriptor' The current proxy semantics has an (informal) restriction forbidding reentrant fixing of the same object, but that is only a very special case of the broader problem. Firefox 7 rejects fixing a proxy while one of (most) its traps is executing (this seems to be a recent change, and the above case probably is an oversight). But it is not clear to me what the exact semantics is there, and whether it is enough as a restriction. V8 currently even crashes on a few contorted examples. In summary, I'm slightly worried. The above all seems fixable, but is that all? Ideally, I'd like to see a more thorough analysis of how the addition of proxies affects properties of the language and its spec. But given the state of the ES spec, that is probably too much to wish for... :) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 9:11 AM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 11:49 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 8:05 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. Oh I got burnt by static analysis before, I should know better. I keep thinking that static analysis means analysis of a single compilation unit outside of the runtime as most IDEs for statically typed languages use. I meant: if your tool is embedded in the run time then it knows the exact jQuery API because it can scan the exact jQuery object. No code on this jQuery object needs to run (though that issue is not a show stopper in practice, witness breakpoint debugging). I don't know what to call runtime analysis that does not run extraneous code. I see, yes. Yeah, I mean if I run the JavaScript console in chrome I get nice autocompletion because its using the running environment to know what properties an object has. I believe this is what a lot of smalltalk IDEs used to do. There are still a lot of limitations, though. I mean, what is the purpose of the analysis in the long run. Modern Java IDEs can do a lot of things with static analysis that are very helpful like refactoring and autocompletion. Look, I'm not trying to turn this into a static vs. dynamic debate, my point is that there are a lot of limitations - and useful tooling that is impossible with dynamic code. I think we got here because someone was trying to make the point that the ability to add statically analyzable constraints would be useful to tooling. And it is on this exact point that we disagree In JavaScript, the way to do that may have to be through syntactic additions such as extends or |. I'm certainly not opposed to analysis that goes beyond ASTs. I say, any way you can get it! ... because once we go beyond ASTs much of the value of changing the language for tools goes away. Of course if you make developers do more work for tools, tools can be better. But we should first ensure that tools do their best, then decide what to force on devs. jjb - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Wed, Oct 5, 2011 at 7:18 AM, John J Barton johnjbar...@johnjbarton.comwrote: On Tue, Oct 4, 2011 at 2:33 PM, Bob Nystrom rnyst...@google.com wrote: That's correct. That's often the cost of concision. By analogy: you can do a lot of stuff using either an explicit stack data structure or recursion. Using recursion is often more concise but then the state is hidden from you in the callstack. Sometimes that's a good trade-off, sometimes it's not. Thanks, that analogy helps confirm my opinion of generators. In my experience, the good trade-off is recursion on data structures and the not-good-trade-off is recursion for iteration. Yes, I wasn't making any claim about using recursion *for iteration*. Maybe I need to be more concrete here: If you need to walk a tree, you can do so using recursion or you can use an explicit stack data structure. The former is usually more terse (because it implicitly relies on the callstack itself storing the stack) but the other can be more clear. *By analogy*, if you need to produce a sequence of values, you can do so using generators, or you can use an explicit iterator object. Again, the former is usually more terse (because the language automatically creates the iterator object for you given a function containing yield) but the latter can be more clear (because the state is laid bare). Note that those two paragraphs are separate. I'm not talking about using recursion for iteration. Is this clearer now? So far the only examples I've seen for generators involve iteration. Yup, that's what generators do. And recursion involves stacks. I've heard no clamor at all. That may be true, but it may say as much about your surrounding auditory environment as it does the feature in question. You may be right, but simply saying Bigfoot isn't in my living room doesn't disprove the existence of Bigfoot. There *are* languages in wide use that have this feature. None of those languages (Lua, C#, Python) has a reputation for catering to the esoteric programming language fanbase. Really this is a niche feature, an aid for the rare case where conventional iterators are a poor match. They said the same thing about closures. I agree that generators aren't the most important language feature in the world, but I think if you had them you'd find that you used them. Here's an example: let tree = [['a', 'b', 'c'], [['d', 'e'], 'f'], ['g']]; let inOrder = walk(tree); for (node of walk(tree)) alert(node); // a, b, c, d, ... walk(tree) { if (typeof tree == 'string') { yield tree; // leaf } else { yield* walk(tree); // branch } } What would the above look like without generators? - bob ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proxy-induced impurity of internal methods
Please keep bringing these up; they're important. This is something that we'll need to get nailed down for the spec. Yes, I'm worried too, as this problem is not well-understood. It has the feel of a research problem. Waldemar ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Sep 27 meeting notes
On Oct 4, 2011, at 6:17 AM, Russell Leggett wrote: That's why I was trying to make it less error prone and verbose. Understood, but we should not scenario solve with ad-hoc, compound additions. We seek orthogonal primitives that compose well, and the harder scenarios ideally desugar. If you are assuming .{ binds to the result of evaluating the unparenthesized | expression to its left, then there's a precedence problem. I was assuming | was evaluated first because that's how I read Allen's pattern working as well. I'm wondering how Allen's even works now. The | operator must not take an arbitrary expression on its right, because that allows for mutation of [[Prototype]] on an escaped old-born object. But | could take literal forms and concatenations of literal forms via .prototype.{...}.constructor, e.g. Or | binds tighter than . (but I think this would be a mistake). My thought was that if func | obj = func, then .{ would go on the resulting function. No, func | {...} makes an object whose [[Prototype]] is func. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Sep 27 meeting notes
On Oct 4, 2011, at 8:35 AM, Allen Wirfs-Brock wrote: On Oct 4, 2011, at 12:44 AM, Brendan Eich wrote: On Oct 4, 2011, at 5:43 AM, Russell Leggett wrote: I don't want to be pushy, so this is the last time that I'll mention it, but if we can create something using the | operator that can basically do what has been discussed for the simplest class literal, I think you're barking up several wrong trees. But yes, Allen proposed | and .{ to help make class-like syntax lighter-weight (if more punctuated), without having real class syntax. Unfortunately any such poor-person's class unsyntax will remain error prone (easy to leave out or misorder a sub-expression) and slightly verbose (compared to just-so class syntax). Brendan, It sounds like you may have missed this alternative from the Minor extension to Set Literal Prototype... thread that eliminates the mis-ordered or left-out constructor clause problem. Care to summarize? I was traveling and skimming some of the long messages in that thread. Also, I fear we are pattern-mongering prematurely. We want something like | for sure (exact spelling needs work IMHO). We could have just Object.extend instead of .{...} and some on the committee objected to the mutating nature of a variant on dot -- they wanted .= at least -- but since there is no requirement that the RHS be a literal, Object.extend is enough. IINM .{...} is trying to make a shorthand, not just for its own sake but to make a class-like pattern and reduce the perceived need for classes as sugar. I think that's not well-motivated at this point. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proxy-induced impurity of internal methods
On 5 October 2011 18:57, Andreas Rossberg rossb...@google.com wrote: FIXING PROXIES A particularly worrisome side effect is fixing a proxy. The proxy semantics contains a lot of places saying If O is a trapping proxy, do steps I-J. However, there generally is no guarantee that O remains a trapping proxy through all of I-J! Again, an example: var handler = { get set() { Object.freeze(p); return undefined }, fix: function() { return {} } } var p = Proxy.create(handler) p.x Firefox 7: TypeError on line 1: getPropertyDescriptor is not a function V8: TypeError: Object #Object has no method 'getPropertyDescriptor' Whoops, sorry, I just saw that I screwed up that example. That behaviour is perfectly fine, of course. Don't have my notes here, I'll deliver the proper example tomorrow. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: holes in spread elements/arguments
On Mon, Oct 3, 2011 at 4:37 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: apply supports holes... f.apply(Array(5)); Look at the specification of apply in section 15.3.4.3 of the ES5/5.1 spec. It does a [[Get]] on each element of the argArray to get the value that passed in the argument list. [[Get]] converts holes to undefined. The only way this is observable in ES5 is if argArray has getters for any of the indexes between 0 and argArray.length. I'm not aware of any cases of objects defining getters for indexed properties, much less those objects being passed to Function.prototype.apply. So the only consequence of this is that the hole preservation algorithms in the draft spec only call [[Get]] when [[HasProperty]] returns true. So we could either tweak the hole preservation algorithm for rest parameters to call [[Get]] regardless, or the better option IMHO, match the other algorithms by no longer calling [[Get]] for holes in argArray, at least when Function.prototype.apply is called from extended code. syntactic calls will support holes... f(...Array(5)) by syntactic calls I meant f(a,b,c). the legacy language does not allow for f(a,,c) This can be said of any any syntax being added in ES.next. Also, I'm only suggesting to add that syntax if it continues to be available in array literals. What *doesn't* support holes is the `arguments` object which is on its way out. In addition, the specification of the semantics of function invocation made no allowance for the possibility of holes in an argument list. The specification of `arguments` dictates this, not function invocation as a whole. Sorry that is incorrect, see 15.3.4.3 You are correct, sorry. However, this is merely an unobservable specification detail, so what relevance does it have to what is best for the future of the language ? What about holes makes them applicable to arrays in general but not argument arrays ? Everything else in ES.next points to reification of arguments as plain old arrays, why be different here ? Because we aren't talking about reification of arguments. We are talking about the semantics of an argument list in a function call expression and the semantics of the spread operator. The spread operator in argument lists reifies the argument list as an array in my view. But mostly I just care that the semantics are the same as when the spread oeprator occurs in an array literal, i.e. that holes are preserved for the receiver. If a caller does not want holes to be observed by a potential callee rest argument, they can use a dense argument list, however I'm not sure why they would care about this. If a caller *does* want to allow a potential callee rest parameter to utilize holes for optimization purposes, why prevent them from doing so? I would actually be ok with or without both Elision syntax and hole preservation in ES.next, I just want consistency. One concern that I've already mentioned is that recognizing holes in spread would create an inconsistency with the existing semantics of apply and that changing apply would be a breaking change that might impact existing code. apply does not have existing semantics for rest parameters since they don't yet exist, I'm not suggesting to change the semantics for `arguments` while it's still around Apply is on the caller side. It doesn't have any parameter semantics at all. It is only responsible for passing on a valid argument list. Because apply and normal function application can't depend knowledge to the callee, it is reasonable to expect that: foo.apply(undefined,x) means exactly the same thing as foo(...x) Yes, I intend for them to mean the same thing, which is that holes in x which fall within a range covered by a rest parameter in foo are preserved. If foo uses `arguments` they continue to show up as undefined values there. function f(arg) { [a='a', b='b'] = arg; The above line is not legal syntax according to the current specification draft. The destructuring binding pattern and a destructuring assignment pattern have both different syntax and semantics. In a destructuring binding, a scalar BindingElement is defined as: SingleNameBinding : BindingIdentifier Initializer-opt while in a destructuring assignment, a scalar AssignmentElement is defined as AssignmentElement : LeftHandSideExpression Note that an AssignmentElement does not have an Initializer. The reason I defined it this way is that unlike a BindingIdentifier, a LeftHandSideExpression can be an arbitrary complex expression. I didn't want to allow expressions such as: [new foo.bar[baz(x=5)].bam=0] = obj; where the trailing initializer looks like it is just part of the element expression. I'm willing to discuss the merits of that decision, but the fact remains that the semantics of destructuring binding and destructuring assignment are quite different so I consider suspect any argument that starts by
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 1:18 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 9:11 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 11:49 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 8:05 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. Oh I got burnt by static analysis before, I should know better. I keep thinking that static analysis means analysis of a single compilation unit outside of the runtime as most IDEs for statically typed languages use. I meant: if your tool is embedded in the run time then it knows the exact jQuery API because it can scan the exact jQuery object. No code on this jQuery object needs to run (though that issue is not a show stopper in practice, witness breakpoint debugging). I don't know what to call runtime analysis that does not run extraneous code. I see, yes. Yeah, I mean if I run the JavaScript console in chrome I get nice autocompletion because its using the running environment to know what properties an object has. I believe this is what a lot of smalltalk IDEs used to do. There are still a lot of limitations, though. I mean, what is the purpose of the analysis in the long run. Modern Java IDEs can do a lot of things with static analysis that are very helpful like refactoring and autocompletion. Look, I'm not trying to turn this into a static vs. dynamic debate, my point is that there are a lot of limitations - and useful tooling that is impossible with dynamic code. I think we got here because someone was trying to make the point that the ability to add statically analyzable constraints would be useful to tooling. And it is on this exact point that we disagree In JavaScript, the way to do that may have to be through syntactic additions such as extends or |. I'm certainly not opposed to analysis that goes beyond ASTs. I say, any way you can get it! ... because once we go beyond ASTs much of the value of changing the language for tools goes away. Of course if you make developers do more work for tools, tools can be better. But we should first ensure that tools do their best, then decide what to force on devs. Sometimes going beyond ASTs is extremely challenging - but OK, let's just say we reach a point where we have tools good enough that they can read in code that has been run through a build tool so that they can
Re: holes in spread elements/arguments
Removing these inconsistencies would also allow argument and parameter lists to be explained in terms of desugaring into array structuring and destructuring patterns respectively: function(a, , c = 0, ...d){ //...} would desugar to: function(){ var [a, , c = 0, ...d] = _arguments_; // even better would be let! //...} and: f(a, , c, ...d) would desugar to: Function.prototype.apply.call(f, undefined, [a, , c, ...d]); On Wed, Oct 5, 2011 at 2:19 PM, Sean Eagan seaneag...@gmail.com wrote: On Mon, Oct 3, 2011 at 4:37 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: apply supports holes... f.apply(Array(5)); Look at the specification of apply in section 15.3.4.3 of the ES5/5.1 spec. It does a [[Get]] on each element of the argArray to get the value that passed in the argument list. [[Get]] converts holes to undefined. The only way this is observable in ES5 is if argArray has getters for any of the indexes between 0 and argArray.length. I'm not aware of any cases of objects defining getters for indexed properties, much less those objects being passed to Function.prototype.apply. So the only consequence of this is that the hole preservation algorithms in the draft spec only call [[Get]] when [[HasProperty]] returns true. So we could either tweak the hole preservation algorithm for rest parameters to call [[Get]] regardless, or the better option IMHO, match the other algorithms by no longer calling [[Get]] for holes in argArray, at least when Function.prototype.apply is called from extended code. syntactic calls will support holes... f(...Array(5)) by syntactic calls I meant f(a,b,c). the legacy language does not allow for f(a,,c) This can be said of any any syntax being added in ES.next. Also, I'm only suggesting to add that syntax if it continues to be available in array literals. What *doesn't* support holes is the `arguments` object which is on its way out. In addition, the specification of the semantics of function invocation made no allowance for the possibility of holes in an argument list. The specification of `arguments` dictates this, not function invocation as a whole. Sorry that is incorrect, see 15.3.4.3 You are correct, sorry. However, this is merely an unobservable specification detail, so what relevance does it have to what is best for the future of the language ? What about holes makes them applicable to arrays in general but not argument arrays ? Everything else in ES.next points to reification of arguments as plain old arrays, why be different here ? Because we aren't talking about reification of arguments. We are talking about the semantics of an argument list in a function call expression and the semantics of the spread operator. The spread operator in argument lists reifies the argument list as an array in my view. But mostly I just care that the semantics are the same as when the spread oeprator occurs in an array literal, i.e. that holes are preserved for the receiver. If a caller does not want holes to be observed by a potential callee rest argument, they can use a dense argument list, however I'm not sure why they would care about this. If a caller *does* want to allow a potential callee rest parameter to utilize holes for optimization purposes, why prevent them from doing so? I would actually be ok with or without both Elision syntax and hole preservation in ES.next, I just want consistency. One concern that I've already mentioned is that recognizing holes in spread would create an inconsistency with the existing semantics of apply and that changing apply would be a breaking change that might impact existing code. apply does not have existing semantics for rest parameters since they don't yet exist, I'm not suggesting to change the semantics for `arguments` while it's still around Apply is on the caller side. It doesn't have any parameter semantics at all. It is only responsible for passing on a valid argument list. Because apply and normal function application can't depend knowledge to the callee, it is reasonable to expect that: foo.apply(undefined,x) means exactly the same thing as foo(...x) Yes, I intend for them to mean the same thing, which is that holes in x which fall within a range covered by a rest parameter in foo are preserved. If foo uses `arguments` they continue to show up as undefined values there. function f(arg) { [a='a', b='b'] = arg; The above line is not legal syntax according to the current specification draft. The destructuring binding pattern and a destructuring assignment pattern have both different syntax and semantics. In a destructuring binding, a scalar BindingElement is defined as: SingleNameBinding : BindingIdentifier Initializer-opt while in a destructuring assignment, a scalar AssignmentElement is defined as AssignmentElement : LeftHandSideExpression Note that an AssignmentElement does not have an Initializer. The
Re: On I got 99 problems and JavaScript syntax ain't one (was: On Incremental Updates)
On Wed, Oct 5, 2011 at 2:25 PM, Russell Leggett russell.legg...@gmail.comwrote: On Wed, Oct 5, 2011 at 1:18 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 9:11 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 11:49 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 8:05 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:52 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 5, 2011 at 7:49 AM, Russell Leggett russell.legg...@gmail.com wrote: On Wed, Oct 5, 2011 at 10:32 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 10:26 AM, Mike Samuel mikesam...@gmail.com wrote: 2011/10/4 Russell Leggett russell.legg...@gmail.com: On Tue, Oct 4, 2011 at 12:51 PM, Mike Samuel mikesam...@gmail.com wrote: No it doesn't. Just walk the object graph starting from the root object and let the set of all reachable symbols be A. Load jQuery Walk the object graph again letting the set of all reachable symbols be B. The public API of jQuery is then (B - A). That's works fine under 2 conditions: 1. You're willing to execute code instead of statically analyze it 2. You're capable of executing that code in isolation. This should be true for most libraries out there. It obviously doesn't hold for user code and definitely not for all code in an IDE since IDE's have to deal with code during editing. I'm not a jQuery person, but as far as I can tell jQuery introduces only one global value so the jQuery API is just the properties of that object at the point in the program where the developer needs to use jQuery. You don't have to execute code and the only graph you need to walk is the properties of one object. If you looked at the code for more than 5 minutes, you'd see that the jQuery codebase, while interesting to look at, would be ridiculously hard to statically analyze without understanding jQuery conventions. The bulk of the methods are added through calls to 'jQuery.extend(...' and 'jQuery.fn.extend(...' Sure, that's the way lots of JS code works, which is why I think IDEs based on static analysis are doomed. I was responding to: You don't have to execute code and the only graph you need to walk is the properties of one object. If you don't execute code, that's what static analysis is. I'm sorry, I must be missing something. And the way that jQuery (and any JS code that use a function of some kind to make classes) builds up its api is to use some helper methods, beyond which, static analysis has a really rough time. You don't seem to be disagreeing with me. Oh I got burnt by static analysis before, I should know better. I keep thinking that static analysis means analysis of a single compilation unit outside of the runtime as most IDEs for statically typed languages use. I meant: if your tool is embedded in the run time then it knows the exact jQuery API because it can scan the exact jQuery object. No code on this jQuery object needs to run (though that issue is not a show stopper in practice, witness breakpoint debugging). I don't know what to call runtime analysis that does not run extraneous code. I see, yes. Yeah, I mean if I run the JavaScript console in chrome I get nice autocompletion because its using the running environment to know what properties an object has. I believe this is what a lot of smalltalk IDEs used to do. There are still a lot of limitations, though. I mean, what is the purpose of the analysis in the long run. Modern Java IDEs can do a lot of things with static analysis that are very helpful like refactoring and autocompletion. Look, I'm not trying to turn this into a static vs. dynamic debate, my point is that there are a lot of limitations - and useful tooling that is impossible with dynamic code. I think we got here because someone was trying to make the point that the ability to add statically analyzable constraints would be useful to tooling. And it is on this exact point that we disagree In JavaScript, the way to do that may have to be through syntactic additions such as extends or |. I'm certainly not opposed to analysis that goes beyond ASTs. I say, any way you can get it! ... because once we go beyond ASTs much of the value of changing the language for tools goes away. Of course if you make developers do more work for tools, tools can be better. But we should first ensure that tools do their best, then decide
Re: traits feedback
On Tue, Oct 4, 2011 at 8:56 PM, John J Barton johnjbar...@johnjbarton.comwrote: In trying to update my JS approach I looked into 'traits'. I'm still on the fence about using them at this stage, but MarkM was asking for feedback of pretty much any kind so here is a little. I believe I understand traits for the most part just from the info on the Web site: http://traitsjs.org/ (but read the examples in the Paper, not the one in the Tutorial). Traits feel like JS to me: a reusable set of methods packaged in an object. The Trait construct add regularity and organization to a wide-spread pattern of JS use, but it feels like a tool you pick up when you need it. The key operations are create and compose, with resolve and override to handle exotic issues. On the other hand I had the opposite reaction to http://wiki.ecmascript.org/doku.php?id=strawman:syntax_for_efficient_traits That proposal is a completely different language with many new keywords and operators. I came away deciding to stop using |prototype| + new in favor of Object.create() and to revisit the traits.org library after a bit. Ok that was a quick experiment. I completely misunderstood Object.create(). I imagined that Object.create(a,b) returned an object with the properties of b and a __proto__ of a. Unfortunately the second argument is some kind of meta object. So to get {p:42} you have to write { p: { value: 42, writable: true, enumerable: true, configurable: true } }. Oy vey. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one (was: OnIncremental Updates)
On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. - Ways of isolating code from the global scope Covered by modules and module loaders. - Tools for avoiding XSS That's a cross-cutting problem, not just core language. So, yes, tools but no silver bullets. ES5 has some tools, ES6 has more. There was talk about an is or eq operator to fix equality, but it seems it got demoted or interest was lost. Wrong: wiki.ecmascript.org/doku.php?id=harmony:egal /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
Object.create does indeed require propertydescriptors as the second argument. This is the easiest way to send meta-data like read-only. However it's verbose and the defaults are restrictive. I've written a small library (github.com/Raynos/pd) to make it less verbose, you might find it useful. On Oct 5, 2011 11:59 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Tue, Oct 4, 2011 at 8:56 PM, John J Barton johnjbar...@johnjbarton.com wrote: In trying to ... Ok that was a quick experiment. I completely misunderstood Object.create(). I imagined that Object.create(a,b) returned an object with the properties of b and a __proto__ of a. Unfortunately the second argument is some kind of meta object. So to get {p:42} you have to write { p: { value: 42, writable: true, enumerable: true, configurable: true } }. Oy vey. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. `===' (Strict equality) is used for comparing the value of two objects, taking data-structure into account. Could someone enlighten me on what is not intuitive or sane about that? I mean, my starting point for comparing equality operator sanity is Common Lisp's with its 10+ equality predicates — some being implementation-dependant, so YMMV. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Oct 5, 2011, at 7:01 PM, Quildreen Motta wrote: On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. This operator is insane due to implicit conversions it does when operand types are not the same. In such cases it is not an equivalence relation. `===' (Strict equality) is used for comparing the value of two objects, taking data-structure into account. This operator is fine, unless you want to test (NaN is NaN) or (-0 isnt 0). There, you need is/isnt. Could someone enlighten me on what is not intuitive or sane about that? I mean, my starting point for comparing equality operator sanity is Common Lisp's with its 10+ equality predicates — some being implementation-dependant, so YMMV. Yes, during ES1 days Guy Steele said we were not worse than Common Lisp. Still doesn't excuse ==/!= in the case of operands of different types. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On 05/10/11 23:06, Brendan Eich wrote: On Oct 5, 2011, at 7:01 PM, Quildreen Motta wrote: On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. This operator is insane due to implicit conversions it does when operand types are not the same. In such cases it is not an equivalence relation. I would argue this is not entirely true. It would depend on what you consider equivalence. As I said, the way I see the abstract equality algorithm is that it compares values — by which I mean primitive values, — such that it can't really take into account the data structure of the operands. So, `1' equals `1' which equals `[1]' which equals `{toString:function() 1}' which might equal just about any other object which `toString' returns 1. In this case, the semantics are pretty sane (though some might argue about `[1]' and other objects). We could say it would be analogous to having a book in several different medias — ebook, paper, audio, etc. Just because the medias are different, it doesn't mean the contents of the book are. I have to agree, however, that some of the conversions are not as intuitive — at first glance — as the ones in the relational operators, which always convert the operands to the a numeric primitive value. Perhaps some of the fault of abstract equality's usage might be on the lack of chaining comparisons, though: --- // This is not what you'd usually assume it to be, based on mathematical notation 2 == 2 == [2] // = false // ...because operations are done this way (2 == 2) == [2] → (2 == ToNumber(2)) == [2] → (2 == 2) == [2] → true == [2] → true == ToPrimitive([2]) // [2].valueOf().toString() → ToNumber(true) == 2 → 1 == ToNumber(2) → 1 == 2 → false --- That said, I don't consider the semantics of abstract equality *that* complex to consider it a problem — there are some recursive conversions, yes. ToPrimitive might get confusing depending on how toString and valueOf are defined in the object. That might be a problem or an interesting feature depending on the particular use-case, considering how dynamic JS is. That's not to say it's perfect in every single conversion, but it gets at least 90% of all the practical use cases right. Other people probably have a different opinion on this kind of equivalence coming from a strong or static/strong typed background. `===' (Strict equality) is used for comparing the value of two objects, taking data-structure into account. This operator is fine, unless you want to test (NaN is NaN) or (-0 isnt 0). There, you need is/isnt. Is `egal' already in ES.next? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 10:36 PM, Jake Verbaten rayn...@gmail.com wrote: Object.create does indeed require propertydescriptors as the second argument. This is the easiest way to send meta-data like read-only. However it's verbose and the defaults are restrictive. I've written a small library (github.com/Raynos/pd) to make it less verbose, you might find it useful. That's what Object.getOwnPropertyDescriptorshttp://wiki.ecmascript.org/doku.php?id=strawman:extended_object_api would be for. I don't know why it hasn't gotten into Harmony yet. Juan ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On 06/10/11 00:02, Juan Ignacio Dopazo wrote: On Wed, Oct 5, 2011 at 10:36 PM, Jake Verbaten rayn...@gmail.com mailto:rayn...@gmail.com wrote: Object.create does indeed require propertydescriptors as the second argument. This is the easiest way to send meta-data like read-only. However it's verbose and the defaults are restrictive. I've written a small library (github.com/Raynos/pd http://github.com/Raynos/pd) to make it less verbose, you might find it useful. That's what Object.getOwnPropertyDescriptors http://wiki.ecmascript.org/doku.php?id=strawman:extended_object_api would be for. I don't know why it hasn't gotten into Harmony yet. Hm, how exactly would `#getOwnPropertyDescriptors' fix the verbosity of property descriptors when creating new slots in an object? Or were you referring to another issue? If so, I missed it, would you care to explain a little better? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 8:02 PM, Juan Ignacio Dopazo dopazo.j...@gmail.comwrote: On Wed, Oct 5, 2011 at 10:36 PM, Jake Verbaten rayn...@gmail.com wrote: Object.create does indeed require propertydescriptors as the second argument. This is the easiest way to send meta-data like read-only. However it's verbose and the defaults are restrictive. I've written a small library (github.com/Raynos/pd) to make it less verbose, you might find it useful. That's what Object.getOwnPropertyDescriptorshttp://wiki.ecmascript.org/doku.php?id=strawman:extended_object_api would be for. I don't know why it hasn't gotten into Harmony yet. Sorry I the property descriptors thing is just for library writers I guess, it's too complicated for app devs. I think what's missing is Object.extend: http://www.prototypejs.org/api/object/extend http://api.jquery.com/jQuery.extend/ http://dojotoolkit.org/reference-guide/dojo/extend.html http://docs.sencha.com/ext-js/4-0/source/Object2.html#Ext-Object-method-merge http://code.google.com/p/fbug/source/browse/branches/firebug1.9/content/firebug/lib/object.js just some examples in a few minutes. With extend, then we can write var bar = Object.extend(Object.create(aMethodList), aPropList); jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Thu, Oct 6, 2011 at 12:01 AM, Quildreen Motta quildr...@gmail.comwrote: On 05/10/11 23:06, Brendan Eich wrote: On Oct 5, 2011, at 7:01 PM, Quildreen Motta wrote: On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. This operator is insane due to implicit conversions it does when operand types are not the same. In such cases it is not an equivalence relation. Yes, == and === work fine. The problem is not in how they work, but in the learning curve for new users of the language. I think most expect == to work as ===. That, combined with object wrappers for values (new Number(5), new Boolean(false), etc), seems to be an endless source of confusion for beginners. Of course pretty much every operator does type coercion, so tampering with == and === could be as much detrimental as constructive. Juan ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Oct 5, 2011, at 8:01 PM, Quildreen Motta wrote: On 05/10/11 23:06, Brendan Eich wrote: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. This operator is insane due to implicit conversions it does when operand types are not the same. In such cases it is not an equivalence relation. I would argue this is not entirely true. It would depend on what you consider equivalence. Equivalence relation is a well-defined technical phrase, and I was employing it intentionally. Please read http://en.wikipedia.org/wiki/Equivalence_relation and note the three required properties: an e.r. must be reflexive, symmetric, and transitive. == 0 0 == 0 but != 0 in JS. If == were transitive, then would have to == 0. (NaN != NaN violates reflexive but it's a special case for numerical analysts, I'm told -- other languages do likewise.) This operator is fine, unless you want to test (NaN is NaN) or (-0 isnt 0). There, you need is/isnt. Is `egal' already in ES.next? Already answered -- wiki.ecmascript.org/doku.php?id=harmony:egal. That link remains in harmony:proposals. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Oct 5, 2011, at 8:21 PM, John J Barton wrote: I think what's missing is Object.extend: http://www.prototypejs.org/api/object/extend http://api.jquery.com/jQuery.extend/ http://dojotoolkit.org/reference-guide/dojo/extend.html http://docs.sencha.com/ext-js/4-0/source/Object2.html#Ext-Object-method-merge http://code.google.com/p/fbug/source/browse/branches/firebug1.9/content/firebug/lib/object.js just some examples in a few minutes. With extend, then we can write var bar = Object.extend(Object.create(aMethodList), aPropList); I agree we should specify Object.extend in ES6. It's the API form of the .{ monocle-mustache operator but generalized to non-literal RHS. However, IIRC PrototypeJS uses for-in and does not filter out enumerable inherited properties. It also uses assignment. Neither is good for ES6. We want only own properties, including private-name-object-keyed ones. This is good motivation for a built-in. Given Object.extend, does .{ pay for itself outside of the class pattern use-case? Does a play on dot connote the mutation of the LHS? I think maybe not and no. If we have only Object.extend, we still roll up a popular and common de-facto standard. If we must have an operator, it should take non-literal RHS and contain = in the assignment operator style. So, .= (monocle-nostrils? monocle-thin-man-mustache? ugh). /be___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Wed, Oct 5, 2011 at 8:44 PM, Brendan Eich bren...@mozilla.com wrote: On Oct 5, 2011, at 8:21 PM, John J Barton wrote: I think what's missing is Object.extend: http://www.prototypejs.org/api/object/extend http://api.jquery.com/jQuery.extend/ http://dojotoolkit.org/reference-guide/dojo/extend.html http://docs.sencha.com/ext-js/4-0/source/Object2.html#Ext-Object-method-merge http://code.google.com/p/fbug/source/browse/branches/firebug1.9/content/firebug/lib/object.js just some examples in a few minutes. With extend, then we can write var bar = Object.extend(Object.create(aMethodList), aPropList); I agree we should specify Object.extend in ES6. It's the API form of the .{ monocle-mustache operator but generalized to non-literal RHS. However, IIRC PrototypeJS uses for-in and does not filter out enumerable inherited properties. It also uses assignment. Neither is good for ES6. We want only own properties, including private-name-object-keyed ones. This is good motivation for a built-in. PrototypeJS (and Firebug) pre-date Object.keys() and .hasOwnProperty(), so their implementation was just what could be done, not what was desired. Trait.create() parallels Object.create() and I gather that Trait.compose() resembles proposed Object.extend(). I wonder if the traits.js 'parallel-universe' could be applied to Trait.resolve(). In my experience resolve() isn't needed, but academic work on traits suggests otherwise, so it might be a good thing to investigate. jjb Given Object.extend, does .{ pay for itself outside of the class pattern use-case? Does a play on dot connote the mutation of the LHS? I think maybe not and no. If we have only Object.extend, we still roll up a popular and common de-facto standard. If we must have an operator, it should take non-literal RHS and contain = in the assignment operator style. So, .= (monocle-nostrils? monocle-thin-man-mustache? ugh). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Oct 4, 2011, at 10:52 AM, Mikeal Rogers wrote: But, some of them simply double the semantics and syntax in the language without a path to deprecate previous syntax. I'm a big fan of let, but if you don't deprecate var we're going to have to contend with new programmers keeping two sets of scoping rules in their head. You mean by deprecate what, exactly? Web JS is full of var. Making any attempt to migrate a big hunk of it to ES6 require replacing all 'var' with 'let' is a huge tax, since scoping works differently. Ok, how about saying if you use 'let' in a function or at top level, you can no longer use 'var'? That's less of a tax on average, but for a long program or single function, it's as bad. On the web, deprecation is separate from obsolescence. You don't remove the bad old thing until the good new thing is out and about and actually in use. You might have to wait for the bad old thing to wither almost to nothing, all by itself. Or sometimes a breaking change that actually improves semantics, rarely breaks valid content, and has better security can be shipped sooner. Examples include window name targeting and mixed http:/https: content not loading the http: content (IE9 does this, good on them). 'var' is not such a case. Brendan said something very interesting in his talk at JSConf.eu, he said that because of the way TC39 works any new proposal that doesn't have (and I hope I'm paraphrasing this right) sexy syntax to start with doesn't have much of a chance. I never said that. In particular, I did not say sexy, and I didn't say start -- here's proof. | and .{ are proposed for ES6. They aren't quite right, many on the committee and in the community believe. That doesn't mean they'll fail to be included under some syntax -- the semantics are good (although .{ is just Object.extend, so the API would be good by itself). What I said was that it's hard to agree on syntax unless the proposer nails it, really (no double entendre there!). Often by using syntax from a nearby language. Even then, .e.g. generators (we distinguish them at the head via function*) and block-lambdas, some who don't know or do not like the nearby language balk. My main point was that syntax is hard. But syntax is UI and JS's UI has real usability bugs. I'm glad you find it easy to teach. That's not the only consideration though, because after people learn a language, as they keep using it they do progress to become fluent, even expert, at it, and its usability problems come to the fore. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proxy-induced impurity of internal methods
Good points that we will have to specify careful. Also one the reasons we do prototype implementations. Such issues seems inherent in the adoption of an intercession API and semantics. Having to deal with such issues isn't really new. In ES5 we had to deal with this possibility WRT [[Get]] and [[Set]] triggering accessors it forced us in some cases to use [[DefineOwnProperty]] instead of [[Put]]. The impact on the internal methods were relatively small in ES5. It was larger for some of the syntactic production evaluation semantics. The biggest impact was on built-ins. I agree that Proxies will have even broader impact and I can even imagine that working through them might lead to some refactoring of the internal properties in order to reduce such effects. such refactorings might then force some changes in to the Proxy Traps. more below On Oct 5, 2011, at 9:57 AM, Andreas Rossberg wrote: In summary, I'm slightly worried. The above all seems fixable, but is that all? Ideally, I'd like to see a more thorough analysis of how the addition of proxies affects properties of the language and its spec. But given the state of the ES spec, that is probably too much to wish for... :) I'm not sure what you mean my the last sentence. I have not yet done any work to incorporate proxies into the ES6 draft. What we currently have is proposal that does not address this depth of specification. I can assure you that, we will when they start to move into the ES6 draft. If you have specific issues like these a good way to capture them is to file bugs against the proposals component of the harmony products at bugs.ecmascript.org. Proposes resolutions would be good too. I definitely look at reported proposal bugs when I work on incorporating new features into the draft specification. On the other hand I don't guarantee that I will spot or remember all issues raised on this list. So file bugs. Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
A huge +1 and hugs and kisses for your entire post. And I didn't say anything like Mikeal's paraphrase, and the ES6 harmony:proposals bear this out (| is unsexy in my current font!). It's especially important not to discount shorthands and sugar for cliché, even though they could be replaced by equivalent long-hand. English does not only have is not. It has isn't as well, and we're better off for that kind of contraction. Yes, this makes it harder to teach -- I know, I have a 7 and a 6 year old learning the rules right now, along with the raft of irregular verbs in English that such children need to know -- but learners manage. /be On Oct 4, 2011, at 12:59 PM, Bob Nystrom wrote: On Tue, Oct 4, 2011 at 10:52 AM, Mikeal Rogers mikeal.rog...@gmail.com wrote: My main concern with *some* of the proposals is that I feel they add features and clever syntax for experts at the expense of keeping the language easy to understand for new programmers. It's hard to satisfy both sets of users here. It's important to try and do our best, but many things are trade-offs. I don't think we can declare thou shalt not change the language in a way that makes it harder for new users. If we can make things much better for working Javascripters at a small expense to newcomers, that may be a worthwhile trade-off or it may not. We should be open to making wise decisions like that, while remaining sympathetic to everyone who is writing JS. I'm a big fan of let, but if you don't deprecate var we're going to have to contend with new programmers keeping two sets of scoping rules in their head. I would love to kill var. With fire. Generators so a function is sometimes a constructor, sometimes a function, and sometimes it's a generator?!?! Explain that in one paragraph that new programmers can understand, I dare you. Because I can never refuse a dare... A constructor is different from a regular function. Instead of returning the value that the body of the function returns, it returns a special newly-created object. Likewise, a generator is a special function that doesn't return what the body returns. Instead, it returns an object that lets you interrupt and resume that function. This object exposes a next() method. When you call that, the function runs until it hits a yield. When it does, the function is paused at that point, and the result of the yield is returned from next(). The next time you call next() it picks up from there and continues. Brendan said something very interesting in his talk at JSConf.eu, he said that because of the way TC39 works any new proposal that doesn't have (and I hope I'm paraphrasing this right) sexy syntax to start with doesn't have much of a chance. Brendan knows better than I, but often I feel that we have the opposite problem. If all you're proposing is syntax, it's easy for anyone to shoot it down by saying You can already do that now. There's a fundmental difference between utility (can we do it all, ever, regardless of how many fingers we lose in the process) and usability (is it discoverable, easy, clear, pleasurable and not error-prone). Because we're programmers we have a tendency to ignore usability concerns because they take more work to demonstrate. We like nice clear boolean switches: I couldn't do this and now I can! It's less satisfying for many of us to say Now people encounter 17% fewer errors when doing this! Personally, I don't think that's the right way to look at things. Arguing from that angle pretty quickly turns into a Turing tarpit. I believe the entire reason we create languages is for usability. I think syntax does matter, because syntax is the user interface of the semantics. I rarely have complaints about JavaScript's semantics (except for var) but I find its notation awkward in some places. Improving those would make me more productive and make JS more fun for me to use. - bob ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On Oct 4, 2011, at 7:36 PM, Dean Landolt wrote: I think generators are an excellent example of a feature that is well prototyped (in FF JS 1.7+). I think the developer uptake is minimal, outside of the original advocates. Of course uptake is minimal -- it's only in one engine, and even then it doesn't yet match the spec. Please get the historical order right. The spec changed only recently, the implementation matched the previous spec (of five years' standing). Anyway, the changes are minor in the scheme of things, or in the terms of this debate. Unless the issue is the function head not looking different? Fixed that in ES6 for ya! ;-) function* also makes the empty basis case work for yield*. /be___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On Oct 5, 2011, at 9:02 PM, John J Barton wrote: PrototypeJS (and Firebug) pre-date Object.keys() and .hasOwnProperty(), hasOwnProperty was in ES3 in 1999. PrototypeJS is IIRC 2005-era. Firebug is post-y2k. so their implementation was just what could be done, not what was desired. Seems unhistorical :-|. Trait.create() parallels Object.create() and I gather that Trait.compose() resembles proposed Object.extend(). I wonder if the traits.js 'parallel-universe' could be applied to Trait.resolve(). In my experience resolve() isn't needed, but academic work on traits suggests otherwise, so it might be a good thing to investigate. Tom Van Cutsem should weigh in. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss