Re: Even simpler lambdas
sorry mate, thumbs down here as well ... confusing with RegExp too, no easy spread, neither shorter, abuse of dollar sign within code and no nested possibility if not through arguments trap and extra vars declarations ... a bit meh compared with what's already in place as proposal. br On Tue, Apr 17, 2012 at 11:33 AM, Peter van der Zee e...@qfox.nl wrote: Why can't lambda's be a simple case of a lexically scoped `return` keyword with any arguments implicitly defined and accessible through a predefined identifier/keyword (much like `arguments` works now)? arr.map(return ''+arguments[0]+' class='+this.getClassName(arguments[1])+'/'); arr.map(return ''+$0+' class='+this.getClassName($1)+'/'); arr.map(return ''+$[0]+' class='+this.getClassName($[1])+'/'); Or maybe the hash sign... arr.map(return ''+#0+' class='+this.getClassName(#1)+'/'); It's going to be hard to come up with a solid grammar for allowing statements this way though (return {foo:bar} would be an objlit, not a block with label). Is that why it's not being considered? You could work around that by restricting grammar for `return` and `{`. So `return{` would always start a block. I'm aware that this is also currently valid syntax for returning an object literal, but I think objections over introducing more restricted grammar rules trumps that anyways... :) Anyways, I like it because it's short, consise, and it feels very intuitive to me. We'd basically overload the return keyword much like the function keyword is right now. As a statement it'd remain the same. As an expression it becomes shorthand notation for a function. - peter ___ 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: destructuring: as patterns?
On 21 April 2012 11:56, Herby Vojčík he...@mailbox.sk wrote: Andreas Rossberg wrote: Of course, it is absolutely true that the same argument can be made about someExpression.x, but I file that under historic legacy. If we were to design JS from scratch -- and with the ES6 feature set! -- then I'd surely vote for making that throw as well (like, btw, I would for argument arity mismatches in function calls, if the callee doesn't have appropriate default or rest parameters). Clearly, it's not possible to correct that, but why should that imply that all new features need to inherit sloppy semantics, too? I disagree. Borrowing from Alan Kay IIRC, this is like making an octopus from a dog by nailing more legs on it - that is, these two points of view are incompatible. Well, that already is the case. ES5 added strict mode. With 1JS in ES6, the rules may get more fuzzy. You gonna have 'let' vs 'var'. You gonna have '=' vs 'function'. You gonna have 'for-of' vs 'for-in'. All additions that fit your description. It's not pretty, but bolting on new legs next to the old ones is the only way to keep a language like JS moving forward. JS model _is_ about sloppy semantics (I do not call it sloopy, I'd rather called it liberal), that is, undefined if not present. It's a term sometimes used on TC39, I didn't invent it (I used to call it classic mode for improved neutrality). I may take issues with associating pre-strict-mode sweeping under the rug with liberal ideals, though. :) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Apr 23, 2012, at 10:15 AM, Andreas Rossberg wrote: On 21 April 2012 01:22, Allen Wirfs-Brock al...@wirfs-brock.com wrote: Here are a few design alternates that have come up as I work the specification draft for arrow functions 1) Always strict? Should all arrow functions be considered strict functions? Pros It's a new syntactic form, so it is it easy to make it be an implicit opt-in to strict mode. We generally want to encourage use of strict mode. If not, there would no way to to make an expression-bodied arrow function a strict function (other than by nesting it in strict code) Always strict eliminates the need for some of the arrow special case alternatives discussed below Cons We shouldn't be trying to force use of strict mode. Programmers who don't know about strict mode may get confused by the application of strict mode semantics to arrow functions It would create a refactoring hazard for non-strict code. One more: It makes the rules for what mode applies where more complicated and less obvious. Unsurprisingly, I agree. To be honest, that suggestion confirms one of my fears about 1JS -- ending up with a more complicated language with ad-hoc rules about which mode applies in which context. Please let's try to resist the temptation. As much as I would like to encourage strict mode, I think we should keep it orthogonal to other constructs as much as possible. I can bear tying it to modules, but let's not go any further. 2) Redeclaring eval in non-strict arrow functions Should strict mode eval declaration/assignment restrictions be be imposed upon non-strict arrow functions? I propose disallow binding eval or assigning to it all arrow functions Same here. If it's sloppy mode, let the sloppy mode rules apply as usual. 3) Declaring arguments as a formal parameter, or local binding in a non-strict arrow function The wiki proposal says arguments can't be used as an expression primary but doesn't say anything about declarations I propose binding or assigning or referencing arguments within a arrow function. I suppose the most natural semantics would be that, like 'this', ' arguments' is bound lexically from a surrounding function, if present. But that's perhaps too confusing, so I'd be fine with ruling out its use completely. We might be able to do soft binding without much ambiguity. I'll post something here about it under separate cover. 4) Should it be a dynamic error to try to use apply/call to set the this binding of an arrow function. Cons To much existing code speculatively binding the this value when invoking a function. I propose that call/apply simply ignore the this value when invoked on an arrow function. Yes, that is consistent with what happens today when you call/apply a function after 'bind'. 5) Should arrow functions define the [[HasInstance]] internal method. In other words should should: obj instanceof () = {} do? If it doesn't have [[HasInstance]] then instanceof would throw a type error. Alternatively, it could have a [[HasInstance]] that always returns false. We have already decided that arrow functions don't have a [[Construct]] internal method nor a prototype property. I propose that arrow functions do not have a [[HasInstance]] internal method. Agreed. It would be weird to support HasInstance in the absence of the other. 6) Do arrow functions need to have per instance caller and arguments poison pill properties? I propose no, because they are a new feature. But we can include a NOTE warning against providing their non-standard legacy implementation. For simplicity and uniformity, I'd keep the same semantics as for ordinary functions. Don't special-case if there is no strong reason to do so. 7) All of the above questions also apply to functions defined using concise method syntax in object literals or classes. Should the same answers apply to them? I'd prefer if concise method syntax stayed simple syntactic sugar for functions. Methods obviously need dynamic this. If you combine that with changes like the above, then you have implicitly introduced a third kind of function that cannot be described as (simple) syntactic sugar for any of the other two. That would be unfortunate, IMO. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Alex Russell slightly...@google.com slightly...@chromium.org a...@dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Arrow binding
Despite making repeated arguments for soft binding, I'm pretty sure I haven't outlined here what it actually would *be*. Now that we're looking to add syntactic forms that create bound function objects (arrows and class methods), perhaps it's time to get consensus for or against. Soft binding has 2 properties that make it desirable: * The global contract that methods can have their this re-set with .call() and .apply() is maintained * Common-case usage avoids the hazards of unbound and mis-appropriated this contexts. Most commonly, passing a method to a function which takes a callback: node.addEventListener(click, foo.bar); The language today has 2 types of functions: * unbound: methods for which this is not fixed * hard-bound: methods bound by Function.prototype.bind() Crucially, we have no syntax which creates hard-bound methods which means that they're not common (yet). To the extent that they are used, it is explicitly through forms like: node.addEventListener(click, foo.bar.bind(foo)); Or through libraries: dojo.connect(node, onclick, foo, bar); This means that most users of most functions can still use .call() and .apply() without apprehension. Functions are still just functions. The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. What to do? One option is to barrel onward with either unbound functions, hard bound functions, or some mix thereof. These are all painful in ways I don't need to spend time here explaining. I propose a third alternative: soft binding (aka preferred binding). It enables the following: node.addEventListener(click, foo.bar.prefer(foo)); While still allowing the following: foo.bar.call(otherThis, …args); Functions with preferred bindings can still be re-bound either with new preferred binding or with new hard binding (both forms vend new functions objects and they do today). Here's a JSFiddle with an a quick ES5 desugaring + example: http://jsfiddle.net/slightlyoff/739CS/20/ Note that we need to re-define .call() and .apply() to be savvy to preferences, but this doesn't seem particularly painful. I've bluntly worked around it in this example to avoid __proto__ re-wiring. Thoughts? -- Alex Russell slightly...@google.com slightly...@chromium.org a...@dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
I'd prefer if concise method syntax stayed simple syntactic sugar for functions. Methods obviously need dynamic this. If you combine that with changes like the above, then you have implicitly introduced a third kind of function that cannot be described as (simple) syntactic sugar for any of the other two. That would be unfortunate, IMO. FWIW, I agree. kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
I'm not sure I understand the reasoning behind soft-binding. If I use arrow syntax, my intention is to close over |this|. Allowing a caller to change the binding of |this| will result in a violation of that closure. In this respect, |this| within an arrow function is no different that any other closed-over variable. I would not want a caller to be able to override the binding on any of those variables, right? kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Mon, Apr 23, 2012 at 6:53 AM, Alex Russell a...@dojotoolkit.org wrote: Despite making repeated arguments for soft binding, I'm pretty sure I haven't outlined here what it actually would *be*. Now that we're looking to add syntactic forms that create bound function objects (arrows and class methods), perhaps it's time to get consensus for or against. Soft binding has 2 properties that make it desirable: * The global contract that methods can have their this re-set with .call() and .apply() is maintained * Common-case usage avoids the hazards of unbound and mis-appropriated this contexts. Most commonly, passing a method to a function which takes a callback: node.addEventListener(click, foo.bar); The language today has 2 types of functions: * unbound: methods for which this is not fixed * hard-bound: methods bound by Function.prototype.bind() Crucially, we have no syntax which creates hard-bound methods which means that they're not common (yet). To the extent that they are used, it is explicitly through forms like: node.addEventListener(click, foo.bar.bind(foo)); Or through libraries: dojo.connect(node, onclick, foo, bar); This means that most users of most functions can still use .call() and .apply() without apprehension. Functions are still just functions. That is only true for functions that actually use |this|. Even though bind is probably not used in force yet because of cross-browser worries, var self = this is used everywhere. Functions using that pattern are no more usable with call/apply than arrow functions. The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. Last I checked, the new method form is still a dynamic binding - otherwise it wouldn't work. So really, you're just talking about arrow functions. In the cases where arrow functions make the most sense (callbacks) you rarely want a dynamic |this| - the oddball case being event handlers primarily. What to do? One option is to barrel onward with either unbound functions, hard bound functions, or some mix thereof. These are all painful in ways I don't need to spend time here explaining. I propose a third alternative: soft binding (aka preferred binding). It enables the following: node.addEventListener(click, foo.bar.prefer(foo)); While still allowing the following: foo.bar.call(otherThis, …args); Functions with preferred bindings can still be re-bound either with new preferred binding or with new hard binding (both forms vend new functions objects and they do today). Here's a JSFiddle with an a quick ES5 desugaring + example: http://jsfiddle.net/slightlyoff/739CS/20/ Note that we need to re-define .call() and .apply() to be savvy to preferences, but this doesn't seem particularly painful. I've bluntly worked around it in this example to avoid __proto__ re-wiring. Thoughts? When I enumerate the use cases, I have trouble finding a *good* reason for soft-binding. You are correct that it removes a certain amount of genericness to use hard-binding, but I think writing a generic function should be intentional. function foo(bar){ bar.call(otherThis); } If you write a function foo that expects a function parameter bar, and you intend to override it's this value, that is a contract, and the |this| you substitute also needs to abide by the contract for use inside of the bar function. Traditionally, this would be done using a *parameter* to bar, instead of changing |this| which seems fragile at best. The only use case I see for changing |this| is if the function bar passed in is already an existing method. //For this use case, why would I ever use an arrow function foo( ()=this.myBar() ); //instead of just passing the method directly foo( this.myBar ); I really just don't see the value of changing the |this| value of a function created for the purpose of being an argument to a function. And frankly, I just don't see many other use cases for arrows. Maybe thats the part I'm missing. - Russ -- Alex Russell slightly...@google.com slightly...@chromium.org a...@dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723 ___ 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: Arrow binding
On Mon, Apr 23, 2012 at 2:47 PM, Russell Leggett russell.legg...@gmail.com wrote: On Mon, Apr 23, 2012 at 6:53 AM, Alex Russell a...@dojotoolkit.org wrote: Despite making repeated arguments for soft binding, I'm pretty sure I haven't outlined here what it actually would *be*. Now that we're looking to add syntactic forms that create bound function objects (arrows and class methods), perhaps it's time to get consensus for or against. Soft binding has 2 properties that make it desirable: * The global contract that methods can have their this re-set with .call() and .apply() is maintained * Common-case usage avoids the hazards of unbound and mis-appropriated this contexts. Most commonly, passing a method to a function which takes a callback: node.addEventListener(click, foo.bar); The language today has 2 types of functions: * unbound: methods for which this is not fixed * hard-bound: methods bound by Function.prototype.bind() Crucially, we have no syntax which creates hard-bound methods which means that they're not common (yet). To the extent that they are used, it is explicitly through forms like: node.addEventListener(click, foo.bar.bind(foo)); Or through libraries: dojo.connect(node, onclick, foo, bar); This means that most users of most functions can still use .call() and .apply() without apprehension. Functions are still just functions. That is only true for functions that actually use |this|. Even though bind is probably not used in force yet because of cross-browser worries, var self = this is used everywhere. Functions using that pattern are no more usable with call/apply than arrow functions. everywhere is incredibly strong wording, and I think that in the large, you're probably not correct. Some large % of code might manually call their scope through closure binding, but even that isn't an argument against soft binding. The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. Last I checked, the new method form is still a dynamic binding - otherwise it wouldn't work. So really, you're just talking about arrow functions. In the cases where arrow functions make the most sense (callbacks) you rarely want a dynamic |this| - the oddball case being event handlers primarily. Having done this dance a couple of times, let me suggest to you that the method form will *eventually* end up at a per-class getter on the prototype which vends an instance function which is bound. People will (reasonably) want binding of some sort. What to do? One option is to barrel onward with either unbound functions, hard bound functions, or some mix thereof. These are all painful in ways I don't need to spend time here explaining. I propose a third alternative: soft binding (aka preferred binding). It enables the following: node.addEventListener(click, foo.bar.prefer(foo)); While still allowing the following: foo.bar.call(otherThis, …args); Functions with preferred bindings can still be re-bound either with new preferred binding or with new hard binding (both forms vend new functions objects and they do today). Here's a JSFiddle with an a quick ES5 desugaring + example: http://jsfiddle.net/slightlyoff/739CS/20/ Note that we need to re-define .call() and .apply() to be savvy to preferences, but this doesn't seem particularly painful. I've bluntly worked around it in this example to avoid __proto__ re-wiring. Thoughts? When I enumerate the use cases, I have trouble finding a *good* reason for soft-binding. You are correct that it removes a certain amount of genericness to use hard-binding, but I think writing a generic function should be intentional. function foo(bar){ bar.call(otherThis); } If you write a function foo that expects a function parameter bar, and you intend to override it's this value, that is a contract, and the |this| you substitute also needs to abide by the contract for use inside of the bar function. Traditionally, this would be done using a *parameter* to bar, instead of changing |this| which seems fragile at best. The only use case I see for changing |this| is if the function bar passed in is already an existing method. //For this use case, why would I ever use an arrow function foo( ()=this.myBar() ); //instead of just passing the method directly foo( this.myBar ); I really just don't see the value of changing the |this| value of a function created for the purpose of being an argument to a function. And frankly, I just don't see many other use cases for arrows. Maybe thats the part I'm missing.
Re: Arrow binding
Yeah, I think you're missing the composition arguments. If I create mixins with methods, they're going to have a promiscuious this as a *feature*. You might not write code like this today, but you probably should ;-) But anyone who understands the language would not use arrow functions for that use case. I assume you're referring to something like this (Angus posted a similar example a while back): function mixin() { this.{ addMethodA() {}, addMethodB() {} }; } Your idea of a preferred binding for methods is interesting (as a form of method extraction), but I don't think it can be applied to arrow functions. kevin ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Mon, Apr 23, 2012 at 6:46 AM, Kevin Smith khs4...@gmail.com wrote: I'm not sure I understand the reasoning behind soft-binding. If I use arrow syntax, my intention is to close over |this|. Allowing a caller to change the binding of |this| will result in a violation of that closure. In this respect, |this| within an arrow function is no different that any other closed-over variable. I would not want a caller to be able to override the binding on any of those variables, right? Right. I think this is the key issue regarding defaults and what arrow functions must do -- hard binding. Making this binding soft would destroy the integrity of lexical capture that arrow functions provide for this. Alex, http://wiki.ecmascript.org/doku.php?id=strawman:soft_bind, which we worked on together, implements soft binding as a simple small library. We wrote this over a year ago. Since then, I've never found a need for this. Could you give a concrete example where this is useful? Do such uses justify a role beyond such library implementations? I'm inclined to YAGNI on this one. kevin ___ 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: Arrow binding
On Apr 23, 2012, at 16:17 , Alex Russell wrote: Having done this dance a couple of times, let me suggest to you that the method form will *eventually* end up at a per-class getter on the prototype which vends an instance function which is bound. People will (reasonably) want binding of some sort. An important use case. However, wouldn’t it be simpler to achieve the same goal by allowing the following two operations to co-exist? - get: obj.method invokes the getter – which hard-binds on demand (but might cache via a weakmap). - call: obj.method() invokes the actual method. Hence, in addition to getters and setters, we would have callers. If a property doesn’t have a caller then obj.method() would first invoke the getter and then try to call the result. -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
Andreas Rossberg wrote: To be honest, that suggestion confirms one of my fears about 1JS -- ending up with a more complicated language with ad-hoc rules about which mode applies in which context. Please let's try to resist the temptation. As much as I would like to encourage strict mode, I think we should keep it orthogonal to other constructs as much as possible. I can bear tying it to modules, but let's not go any further. It's a good point (and I'm not one to encourage strict mode if there's no payoff for developers, but before agreeing, can you enumerate the cases that matter inside an arrow function body? Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Mon, Apr 23, 2012 at 3:53 AM, Alex Russell a...@dojotoolkit.org wrote: The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. Sorry if I missed reading about this but: why can't we re-bind 'this in bound functions when using call(), apply() ? I'm sure it will make more work for JIT optimizers but they are very good and love this kind of problem. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
The semantic of Function.prototype.bind() precludes it. If we could relax that to be effectively soft-bound, I'm *completely* on board, but I expect it will cause some problems. We could, of course, try this out in Chrome and see how it goes. On Mon, Apr 23, 2012 at 4:32 PM, John J Barton johnjbar...@johnjbarton.com wrote: On Mon, Apr 23, 2012 at 3:53 AM, Alex Russell a...@dojotoolkit.org wrote: The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. Sorry if I missed reading about this but: why can't we re-bind 'this in bound functions when using call(), apply() ? I'm sure it will make more work for JIT optimizers but they are very good and love this kind of problem. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Apr 23, 2012, at 8:32 AM, John J Barton wrote: On Mon, Apr 23, 2012 at 3:53 AM, Alex Russell a...@dojotoolkit.org wrote: The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. Sorry if I missed reading about this but: why can't we re-bind 'this in bound functions when using call(), apply() ? I'm sure it will make more work for JIT optimizers but they are very good and love this kind of problem. Because the semantics would be difficult to implement -- jit or otherwise -- and difficult to specify otherwise :-( The more serious issue though is that of program behaviour -- if a developer has strongly bound this, it is reasonable to expect that they had some reason to do so. If you provide a mechanism that can bypass that binding you can break program abstraction, potentially allowing security bugs in the SES/Caja type language models. It would also imply being able to rebind |this| in bound functions, which would be insane. --Oliver 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: A few arrow function specification issues
Andreas Rossberg wrote: On 21 April 2012 01:22, Allen Wirfs-Brockal...@wirfs-brock.com wrote: 7) All of the above questions also apply to functions defined using concise method syntax in object literals or classes. Should the same answers apply to them? I'd prefer if concise method syntax stayed simple syntactic sugar for functions. Methods obviously need dynamic this. If you combine that But they are not, already. There is that thing with home / defineMethod and super-expressions (and I am for it, it is a good thing). with changes like the above, then you have implicitly introduced a third kind of function that cannot be described as (simple) syntactic sugar for any of the other two. That would be unfortunate, IMO. /Andreas Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: destructuring: as patterns?
On Apr 23, 2012, at 2:40 AM, Andreas Rossberg wrote: On 21 April 2012 11:56, Herby Vojčík he...@mailbox.sk wrote: ... JS model _is_ about sloppy semantics (I do not call it sloopy, I'd rather called it liberal), that is, undefined if not present. It's a term sometimes used on TC39, I didn't invent it (I used to call it classic mode for improved neutrality). I may take issues with associating pre-strict-mode sweeping under the rug with liberal ideals, though. :) I like Martin Rinard's concept of code that is failure oblivious http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.68.9926rep=rep1type=pdf Arguably, the robustness of the web is dependent up the fact many Javascript based webpages will continue to operate, perhaps in a slight degraded mode, even in the face of runtime errors. I'm all for early errors that cause a structurally ill-formed script from loading. But for a well-formed program I don't see why throwing a (probably uncaught) exception is necessarily any more robust than simply returning undefined when various dynamic failures (such as the destructuring situations we are talking about) are encountered. To me, undefined propagation feels a lot like NaN propagation in numeric expressions. Those of us who don't do a lot of numeric computation may be puzzled by NaNs, but it is a lot easier to simply let a NaN propagate through a complex formula and check it at the end, then it is to check for an exception on each operation of the formula. And, sometimes it turns out that the NaN didn't really matter at all... It is important that JavaScript programmer are able to harden the failure critical portions of their applications. Trying to automatically harden everything may actually make JS a less useful languages. Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Apr 23, 2012, at 8:19 AM, Brendan Eich wrote: Andreas Rossberg wrote: To be honest, that suggestion confirms one of my fears about 1JS -- ending up with a more complicated language with ad-hoc rules about which mode applies in which context. Please let's try to resist the temptation. As much as I would like to encourage strict mode, I think we should keep it orthogonal to other constructs as much as possible. I can bear tying it to modules, but let's not go any further. It's a good point (and I'm not one to encourage strict mode if there's no payoff for developers, but before agreeing, can you enumerate the cases that matter inside an arrow function body? Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. See Annex C. Some strict mode highlights: Assignment to an unbound name throws instead of creating a property of the global object With statements are disallowed direct eval can't instantiate new binding in the enclosing environment duplicate formal parameter names are disallowed (I suggest we add this restriction to arrow functions even if we say they aren't inherently strict. ) Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
6) Do arrow functions need to have per instance caller and arguments poison pill properties? I propose no, because they are a new feature. But we can include a NOTE warning against providing their non-standard legacy implementation. For simplicity and uniformity, I'd keep the same semantics as for ordinary functions. Don't special-case if there is no strong reason to do so. Can arrow functions just not have arguments, caller, and name at all? I have to say, it's really annoying having to special case these properties when trying to create function proxies that are mostly virtual, as they are non-configurable, non-writable, and own properties. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Apr 23, 2012, at 3:30 PM, Russell Leggett wrote: That is only true for functions that actually use |this|. Even though bind is probably not used in force yet because of cross-browser worries, var self = this is used everywhere. Functions using that pattern are no more usable with call/apply than arrow functions. everywhere is incredibly strong wording, and I think that in the large, you're probably not correct. Some large % of code might manually call their scope through closure binding, but even that isn't an argument against soft binding. Let me reword from everywhere to extremely common. My point was that even though it is not used in every case, it is used often enough that |this| cannot be relied on. And my other point was that you have to know how the function passed in *uses* this, which makes it pretty tightly coupled. Last I checked, the new method form is still a dynamic binding - otherwise it wouldn't work. So really, you're just talking about arrow functions. In the cases where arrow functions make the most sense (callbacks) you rarely want a dynamic |this| - the oddball case being event handlers primarily. Having done this dance a couple of times, let me suggest to you that the method form will *eventually* end up at a per-class getter on the prototype which vends an instance function which is bound. People will (reasonably) want binding of some sort. If that happens, then I will be more inclined to agree with you. Until that happens, I guess I just don't. Your argument seems balanced on something which you think will happen. I find that hard to agree with. I really just don't see the value of changing the |this| value of a function created for the purpose of being an argument to a function. And frankly, I just don't see many other use cases for arrows. Maybe thats the part I'm missing. Yeah, I think you're missing the composition arguments. If I create mixins with methods, they're going to have a promiscuious this as a *feature*. You might not write code like this today, but you probably should ;-) I use mixins all the time, I just don't see them being being declared with arrow functions, which was the point I was trying to make here. If you are creating a mixin, then you would most likely want to use the new method syntax or at least the function syntax, but I think it would be silly to use the arrow function syntax, so I guess I'm just not sympathetic to that. If methods on classes sprout binding of some sort, this will be the natural style. And I think that's a good place to be. If both arrow and class methods lexically soft-bind, truly unbound functions will be declared as function and will be easy to spot. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
The real use case that I constantly run into has nothing to do with binding at all, rather the need for Function.prototype.partial and *no specific binding*. The primary use case for soft binding or dynamic non-method binding, as mentioned above, is the event callback and that's weird semantic captured in the way the DOM works. The problem is that with JS it's a prevalent use case because of how closely associated JS has been with the DOM. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
Brandon Benvie wrote: 6) Do arrow functions need to have per instance caller and arguments poison pill properties? I propose no, because they are a new feature. But we can include a NOTE warning against providing their non-standard legacy implementation. For simplicity and uniformity, I'd keep the same semantics as for ordinary functions. Don't special-case if there is no strong reason to do so. Can arrow functions just not have arguments, caller, and name at all? Agreed on it being better to leave these off. Do not poison new ground. I have to say, it's really annoying having to special case these properties when trying to create function proxies that are mostly virtual, as they are non-configurable, non-writable, and own properties. This seems like an issue for direct proxies that we should discuss in a separate thread. Apologies if I already missed it. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
caller poison pills, revisited (Was: A few arrow function specification issues)
On Apr 23, 2012, at 10:18 AM, Brandon Benvie wrote: 6) Do arrow functions need to have per instance caller and arguments poison pill properties? I propose no, because they are a new feature. But we can include a NOTE warning against providing their non-standard legacy implementation. For simplicity and uniformity, I'd keep the same semantics as for ordinary functions. Don't special-case if there is no strong reason to do so. Can arrow functions just not have arguments, caller, and name at all? I have to say, it's really annoying having to special case these properties when trying to create function proxies that are mostly virtual, as they are non-configurable, non-writable, and own properties. It at least partially depends upon the properties of Function.prototype because if a arrow function does not implement these properties as own properties it will inherit their definitions (or lack, there of) from Function.prototype. This raises the issue that ES5.1 overlooked poisoning caller/arguments for Function.prototype. Only function object created using the algorithm in 13.2 have the the poison pill properties and Function.prototype is not specified using 13.2. I'm becoming increasing convinced that the poison pill approach to securing the caller chain is a poor approach. We keep finding leaks in and it does nothing to prevent implementation from inventing new ways to expose the stating they are trying to hide. I now think we would be better off with a general,non-algorithmic restriction on conforming implementation that forbid them from exposing elements of the caller chain in the situations that the poison pills were intended to address. I'd like MarkM or other SES advocates to propose language that expression the restriction they need. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
Allen Wirfs-Brock wrote: This raises the issue that ES5.1 overlooked poisoning caller/arguments for Function.prototype. Only function object created using the algorithm in 13.2 have the the poison pill properties and Function.prototype is not specified using 13.2. Function.prototype is special already: js Function.prototype function () {} js Function.prototype.prototype js I think we did the right thing in not adding poisoned pills to it. Was there a capability leak involving Function.prototype that I missed? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
On Apr 23, 2012, at 11:15 AM, Brendan Eich wrote: Allen Wirfs-Brock wrote: This raises the issue that ES5.1 overlooked poisoning caller/arguments for Function.prototype. Only function object created using the algorithm in 13.2 have the the poison pill properties and Function.prototype is not specified using 13.2. Function.prototype is special already: js Function.prototype function () {} js Function.prototype.prototype js I think we did the right thing in not adding poisoned pills to it. Was there a capability leak involving Function.prototype that I missed? caller and arguments properties on functions are a non-standard extension, so the ES spec. can really say whether or not they exist on Function.prototype except by actually defining them. Poison pills prevent an implementation from extending strict functions created via 13.2 from adding such own properties. It doesn't prevent a new kind of strict function (eg, arrows) that inherit from Function.prototype but is not specified to have poison pills (as suggested by Brendan Benvie) from from inheriting an implementation defined caller or arguments property. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
Allen Wirfs-Brock wrote: caller and arguments properties on functions are a non-standard extension, Right you are: js Function.prototype.caller null js Function.prototype.arguments null and of course this is heap not code, so strictness doesn't enter into it. Still happy to change our implementation to remove these from Function.prototype if that avoids perpetuating them and their poison pill variants via arrows. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
I'm becoming increasing convinced that the poison pill approach to securing the caller chain is a poor approach. We keep finding leaks in and it does nothing to prevent implementation from inventing new ways to expose the stating they are trying to hide. I now think we would be better off with a general,non-algorithmic restriction on conforming implementation that forbid them from exposing elements of the caller chain in the situations that the poison pills were intended to address. This sounds a bit drastic—wouldn't it preclude V8's Error.captureStackTrace? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bound instance-function vending (was RE: Arrow binding)
On Apr 23, 2012, at 11:17 AM, Brendan Eich wrote: Apologies for sounding schizo. I'm saying prototypal wins at scale and I see it more often used, but closure has its fans and it's used too. With both (plus other approaches such as Angus's) I do not think it's a given that in the future, JS will make methods auto-bind |this| via prototypal accessors. That is possible today (ES5 and earlier getter/setter support in most browsers) and it's quite rare -- I can think of only a few cases, one of which is in the new I18N library. And note that the I18N usage is for a situation where the property is vending (to use Alex's term) a function that is intended to be used as a call-back that needs access to the state of the instance it was accessed from. In particular, it enables someone to say: someArray.sort(myCollator.compare) rather than someArray.sort(myCollator.compare.bind(myCollator) This seems like an important idiom hat may become even more important in the context of ES6. We probably need to encourage broader education about this idiom. But it isn't clear that it needs special syntax or even what that might be. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
The threat (not sure how real) is not a string telling the backtrace, it's an object reference to an ancestor function in the call stack. /be Domenic Denicola wrote: I'm becoming increasing convinced that the poison pill approach to securing the caller chain is a poor approach. We keep finding leaks in and it does nothing to prevent implementation from inventing new ways to expose the stating they are trying to hide. I now think we would be better off with a general,non-algorithmic restriction on conforming implementation that forbid them from exposing elements of the caller chain in the situations that the poison pills were intended to address. This sounds a bit drastic—wouldn't it preclude V8's Error.captureStackTrace? ___ 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: Bound instance-function vending (was RE: Arrow binding)
Allen Wirfs-Brock wrote: This seems like an important idiomhat may become even more important in the context of ES6. We probably need to encourage broader education about this idiom. But it isn't clear that it needs special syntax or even what that might be. Dave wrote http://wiki.ecmascript.org/doku.php?id=strawman:bind_operator for this and it's a live strawman (albeit in conflict with guard syntax, or perhaps just reusing it outside of binding contexts). Agree it's not ready for ES6, of course. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
On Mon, Apr 23, 2012 at 11:15 AM, Brendan Eich bren...@mozilla.org wrote: Allen Wirfs-Brock wrote: This raises the issue that ES5.1 overlooked poisoning caller/arguments for Function.prototype. Only function object created using the algorithm in 13.2 have the the poison pill properties and Function.prototype is not specified using 13.2. Function.prototype is special already: js Function.prototype function () {} js Function.prototype.prototype js I think we did the right thing in not adding poisoned pills to it. Was there a capability leak involving Function.prototype that I missed? As allowed by the spec, yes. Fortunately, this is securable on the latest available dev versions of IE, FF, Chrome, Safari, and Opera. For some of these, even the released version is already securable. From http://es-lab.googlecode.com/svn/trunk/src/ses/explicit.html on Chrome 19.0.1084.30 beta - [-] 29) All fine: Built in functions leak caller. See http://code.google.com/p/v8/issues/detail?id=1643 http://code.google.com/p/v8/issues/detail?id=1548 https://bugzilla.mozilla.org/show_bug.cgi?id=591846 http://wiki.ecmascript.org/doku.php?id=conventions:make_non-standard_properties_configurable See Test Sbp_A10_T1http://hg.ecmascript.org/tests/test262/file/c84161250e66/test/suite/bestPractice/Sbp_A10_T1.js - [-] 30) All fine: Built in functions leak arguments. See http://code.google.com/p/v8/issues/detail?id=1643 http://code.google.com/p/v8/issues/detail?id=1548 https://bugzilla.mozilla.org/show_bug.cgi?id=591846 http://wiki.ecmascript.org/doku.php?id=conventions:make_non-standard_properties_configurable See Test Sbp_A10_T2http://hg.ecmascript.org/tests/test262/file/c84161250e66/test/suite/bestPractice/Sbp_A10_T2.js visiting http://es-lab.googlecode.com/svn/trunk/src/ses/explicit.html in your browser will state whether your browser is securable. The diagnostic on #29 and #30 will state whether this issue in particular is securable. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: caller poison pills, revisited (Was: A few arrow function specification issues)
On Mon, Apr 23, 2012 at 11:42 AM, Brendan Eich bren...@mozilla.org wrote: The threat (not sure how real) is not a string telling the backtrace, it's an object reference to an ancestor function in the call stack. The ancestor function leak is vastly worse than the backtrace into leak, but both are real. http://code.google.com/p/es-lab/source/browse/trunk/src/ses/debug.js is SES's attempt to secure backtrace leakage on some browsers. /be Domenic Denicola wrote: I'm becoming increasing convinced that the poison pill approach to securing the caller chain is a poor approach. We keep finding leaks in and it does nothing to prevent implementation from inventing new ways to expose the stating they are trying to hide. I now think we would be better off with a general,non-algorithmic restriction on conforming implementation that forbid them from exposing elements of the caller chain in the situations that the poison pills were intended to address. This sounds a bit drastic—wouldn't it preclude V8's Error.captureStackTrace? __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
Brendan Eich wrote: Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. Dave Herman pointed out the shift for |this|-binding in function nested in arrow, under the proposal that arrow implies strict mode: (x, y) = { obj.m = function(…){…} } Again the break if that arrow is strict is for edge cases, not anything calling obj.m(...) or via prototype delegation. obj.m.call(undefined, ...) would not substitute the global object, and primitives would not be boxed. True enough, but I hang tough on wanting arrows to imply strictness. I may be wrong but the edge cases cited so far (global variable creation by assignment, 'with', direct eval injecting 'var' into its dynamic scope) along with this |this|-boxing one are underwhelming. The other good point that came out in discussion with Dave was that module as implicitly strict works better (depending on your belief about future uses) than arrow as implicitly strict would, because (a) modules are bigger; and/or (b) modules are top-level (nesting only in other modules up to the top level) and cannot nest in functions or expressions. I buy that as a one-off argument for imputing strictness to module bodies. I still think arrows could be next in line, knocking at the door, asking why they are getting the brush-off. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Apr 21, 2012, at 1:38 PM, Angus Croll wrote: a function shouldn’t work radically (and silently!) different depending on how it is invoked every current JS function behaves exactly this way :-) No, not at all. What Axel is saying is that you're proposing a new distinction that *does not exist* in JS. You cannot distinguish whether a function was called as a method, as a function, or via .call/.apply. There's no way to tell. All you have is the receiver value bound to `this`, however it was passed in. Your function can decide whether or not to disregard the receiver entirely, but it can't tell where it came from. The caller has the freedom to choose how it *provides* the receiver: f() obj.m = f; obj.m() f.call(obj) f.apply(obj, []) but the callee can't tell the difference between f.call(null) and f(). I'm painfully aware that I sound like a broken record on this, but introducing a hard-bound function option while continuing to suport dynamic-bound functions everywhere else is not going to simplify anything. Another function should not need to know how its function arguments were created in order to work properly - thats a terrible anti-functional anti-pattern! There's no difference whatsoever between a function with a lexically-bound `this` and a function that completely disregards its `this` argument. This is simply a reality of JavaScript today and forever: every function has an API that indicates what it expects of its `this` argument and what it will do with it. If you write a function that ignores its `this` argument, your callers have to know that they can't change your function's behavior by passing a different `this`. Put differently: the lexical `this` syntax is a convenient way to create a non-method function, a function that ignores its receiver. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Apr 23, 2012, at 2:45 PM, David Herman wrote: You cannot distinguish whether a function was called as a method, as a function, or via .call/.apply. There's no way to tell. PS Well, there's stack inspection, but we're all grownups here. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bound instance-function vending (was RE: Arrow binding)
Brendan Eich wrote: No, in any such prototype-getter-makes-bound-function scenario, we would need memoization, so that o.m === o.m (Edit: I see you mention this below.) The real problem is better captured by showing the prototype p and two instances, o and q: p.m === p.m should be true. So should o.m === o.m and q.m === q.m but what about o.m === p.m and o.m === q.m JS requires distinct bound function identity from the unbound p.m identity, so false and false. If we managed to extend JS with a classy declarative syntax that enabled vtables, while keeping functions first class (at the price of prototype-chain mutation: assignment to override, or shadow; also of course delete), then we might well want true and true. But there would be no way in JS itself to implement such magic in terms of properties (data or accessor, doesn't matter) with function values. This is why I continue to think that we won't see what Alex predicted: prototype getter method vending. We haven't see it much in the wild yet either. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Arrow binding
On Apr 23, 2012, at 3:53 AM, Alex Russell wrote: This means that most users of most functions can still use .call() and .apply() without apprehension. Functions are still just functions. You're assuming your conclusion: that there's some sort of platonic ideal (just functions) of JS functions always having a use for their `this` binding. But when I pass function() { elt.style.background = 'yellow' } to setTimeout, is my function some betrayal of The JavaScript Way? No it's a function that changes the background color of an element. It's not evil. It's every bit as valid a function as one that's intended to be a method. JavaScript uses functions for many different things: constructors, top-level functions, callbacks, and methods. Sometimes you need all their features, sometimes you don't. The new forms we're adding (methods and arrows) have the potential to change this radically, causing a large percentage of functions encountered by programmers to have binding. If that binding is hard-binding, .call() and .apply() break in the minds of users. Perhaps that's fine by you, but in addition to being a contractual failure, it removes a form of genericness which is unique in the language. I don't accept this frame. The contract of .call() and .apply() is that their first argument specifies the binding for `this`. The contract between a function and its caller is that the caller provides bindings for the arguments, and the callee decides what to do with those arguments. It is perfectly acceptable for the callee to disregard some arguments. Now, it's certainly possible to make functions less abstract than necessary by using closed-over variables instead of arguments (including `this`). Maybe where I'm closer to agreement with you is that *when you're implementing methods* it's better to use `this` than to lexically close over the object the methods were created for. But not all functions in JavaScript are methods. I'm much more sympathetic to the idea of having *two* shorter-function syntaxes, one optimized for methods and one optimized for non-method functions. I understand the concern about bloat, but to me it addresses the reality of different contexts in programming, e.g.: a.map(x = x + 1) vs box = { _value: 0, get: () - this._value, set(v) { this._value = v } } One option is to barrel onward with either unbound functions, hard bound functions, or some mix thereof. These are all painful in ways I don't need to spend time here explaining. Maybe you do need to, because I'm not convinced. JavaScript already lets you do either. With the shorter function syntax, we've only been discussing conveniences for things you can already express. You claim that conveniences like fat arrow are radical, but soft bind is the proposal that breaks an existing language guarantee. It introduces a new distinction: a callee can now change behavior depending on whether it was called via f() or vs f.call(null). That breaks the feature that you can always use .call/.apply as a drop-in replacement for the equivalent explicit call. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Apr 23, 2012, at 2:44 PM, Brendan Eich wrote: Brendan Eich wrote: Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. True enough, but I hang tough on wanting arrows to imply strictness. I may be wrong but the edge cases cited so far (global variable creation by assignment, 'with', direct eval injecting 'var' into its dynamic scope) along with this |this|-boxing one are underwhelming. IMO, this decision hangs on whether we think strict mode can be thought of as a cleaning up that will mostly just catch bugs, resulting in failing faster but otherwise not changing program behavior significantly. POSITION CLEANUP: If it's just a cleanup, then it makes sense to introduce strict mode in a bunch of places in the language. It'll catch bugs, and for the most part people won't have to think to themselves is this strict code? POSITION MODE: If it's something that is likely to change behavior in meaningful ways other than failing faster, then it's something programmers will have to be mindful of. In that case, having multiple constructs that implicitly introduce strict mode imposes a burden on programmers: they have to know which features are strict and which ones aren't. Every fiber of my being screams MODE. Brendan argues CLEANUP based on the rationale that the non-error semantic changes of strict mode are unlikely edge cases. This is the strongest argument against MODE. I can't prove it wrong, but it's a risky bet. If it turns out to be the case that in practice you need to keep track of whether you're in strict mode, then weak programmers who don't know better will end up with a confusing mess, and strong programmers will prophylactically make sure to put their entire programs in strict mode rather than memorize which subset of syntaxes opt in. Since strong programmers have the option to do that anyway even without multiple implicit opt-ins, why take the risk? Pascal^H^H^H^H^H^H Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: A few arrow function specification issues
As a day-to-day user who was not using strict until recently (stubborn other team member for the loss), I can say that moving to strict was much more a cleanup experience than a mode experience, with only a few small exceptions: 1) Poison-pilling arguments.callee: some code on the internet (notably [1], but elsewhere too) uses this property. 2) Throw on `delete`ing non-configurables: unlike the other throw-on-doing-something-bad, `delete`ing non-configurable properties was something we actually did on purpose. E.g. using it to clear an entry in a map, whether or not that entry was ever filled. (Cf. [2].) We never tried writing to a non-writable property, because that would cause bugs, but `delete`ing a property that doesn't exist was a common pattern. [1]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ [2]: https://github.com/cjohansen/Sinon.JS/commit/80c38bd3e4b8813ab74ef27a4db3646e4778e31c --- Otherwise, it was just cleanup: we got to get rid of our global detector (`setInterval(compareWindowPropertiesToLastTimeYouChecked(), 1000)`), never missed `with` or evil-`eval`, and due to a V8 bug never had boxed `this` in the first place. We're using it transparently throughout the codebase, in fact, due to using an XHR+`eval` module loader that can insert the `use strict` pragma before `eval`ing. -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss- boun...@mozilla.org] On Behalf Of David Herman Sent: Monday, April 23, 2012 19:11 To: Brendan Eich Cc: es-discuss Subject: Re: A few arrow function specification issues On Apr 23, 2012, at 2:44 PM, Brendan Eich wrote: Brendan Eich wrote: Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. True enough, but I hang tough on wanting arrows to imply strictness. I may be wrong but the edge cases cited so far (global variable creation by assignment, 'with', direct eval injecting 'var' into its dynamic scope) along with this |this|-boxing one are underwhelming. IMO, this decision hangs on whether we think strict mode can be thought of as a cleaning up that will mostly just catch bugs, resulting in failing faster but otherwise not changing program behavior significantly. POSITION CLEANUP: If it's just a cleanup, then it makes sense to introduce strict mode in a bunch of places in the language. It'll catch bugs, and for the most part people won't have to think to themselves is this strict code? POSITION MODE: If it's something that is likely to change behavior in meaningful ways other than failing faster, then it's something programmers will have to be mindful of. In that case, having multiple constructs that implicitly introduce strict mode imposes a burden on programmers: they have to know which features are strict and which ones aren't. Every fiber of my being screams MODE. Brendan argues CLEANUP based on the rationale that the non-error semantic changes of strict mode are unlikely edge cases. This is the strongest argument against MODE. I can't prove it wrong, but it's a risky bet. If it turns out to be the case that in practice you need to keep track of whether you're in strict mode, then weak programmers who don't know better will end up with a confusing mess, and strong programmers will prophylactically make sure to put their entire programs in strict mode rather than memorize which subset of syntaxes opt in. Since strong programmers have the option to do that anyway even without multiple implicit opt-ins, why take the risk? Pascal^H^H^H^H^H^H Dave ___ 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: A few arrow function specification issues
My two cents. A little over a year ago, I went over our JavaScript code here at Disqus and made sure that 99% of it is in strict mode. This was definitely a code cleanup aiming at catching variable leaks and other small bugs. -- Anton Kovalyov Sent with Sparrow (http://www.sparrowmailapp.com/?sig) On Monday, April 23, 2012 at 4:59 PM, Domenic Denicola wrote: As a day-to-day user who was not using strict until recently (stubborn other team member for the loss), I can say that moving to strict was much more a cleanup experience than a mode experience, with only a few small exceptions: 1) Poison-pilling arguments.callee: some code on the internet (notably [1], but elsewhere too) uses this property. 2) Throw on `delete`ing non-configurables: unlike the other throw-on-doing-something-bad, `delete`ing non-configurable properties was something we actually did on purpose. E.g. using it to clear an entry in a map, whether or not that entry was ever filled. (Cf. [2].) We never tried writing to a non-writable property, because that would cause bugs, but `delete`ing a property that doesn't exist was a common pattern. [1]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ [2]: https://github.com/cjohansen/Sinon.JS/commit/80c38bd3e4b8813ab74ef27a4db3646e4778e31c --- Otherwise, it was just cleanup: we got to get rid of our global detector (`setInterval(compareWindowPropertiesToLastTimeYouChecked(), 1000)`), never missed `with` or evil-`eval`, and due to a V8 bug never had boxed `this` in the first place. We're using it transparently throughout the codebase, in fact, due to using an XHR+`eval` module loader that can insert the `use strict` pragma before `eval`ing. -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss- boun...@mozilla.org (mailto:boun...@mozilla.org)] On Behalf Of David Herman Sent: Monday, April 23, 2012 19:11 To: Brendan Eich Cc: es-discuss Subject: Re: A few arrow function specification issues On Apr 23, 2012, at 2:44 PM, Brendan Eich wrote: Brendan Eich wrote: Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. True enough, but I hang tough on wanting arrows to imply strictness. I may be wrong but the edge cases cited so far (global variable creation by assignment, 'with', direct eval injecting 'var' into its dynamic scope) along with this |this|-boxing one are underwhelming. IMO, this decision hangs on whether we think strict mode can be thought of as a cleaning up that will mostly just catch bugs, resulting in failing faster but otherwise not changing program behavior significantly. POSITION CLEANUP: If it's just a cleanup, then it makes sense to introduce strict mode in a bunch of places in the language. It'll catch bugs, and for the most part people won't have to think to themselves is this strict code? POSITION MODE: If it's something that is likely to change behavior in meaningful ways other than failing faster, then it's something programmers will have to be mindful of. In that case, having multiple constructs that implicitly introduce strict mode imposes a burden on programmers: they have to know which features are strict and which ones aren't. Every fiber of my being screams MODE. Brendan argues CLEANUP based on the rationale that the non-error semantic changes of strict mode are unlikely edge cases. This is the strongest argument against MODE. I can't prove it wrong, but it's a risky bet. If it turns out to be the case that in practice you need to keep track of whether you're in strict mode, then weak programmers who don't know better will end up with a confusing mess, and strong programmers will prophylactically make sure to put their entire programs in strict mode rather than memorize which subset of syntaxes opt in. Since strong programmers have the option to do that anyway even without multiple implicit opt-ins, why take the risk? Pascal^H^H^H^H^H^H Dave ___ es-discuss mailing list es-discuss@mozilla.org (mailto:es-discuss@mozilla.org) https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org (mailto: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: A few arrow function specification issues
Strict mode delete non-configurable is one of the only offenders on the this really shouldn't be an error list. The useful functionality no longer allowed list is a couple of key things: caller for debug tracing, and `var` in define. The latter was an issue with Narcissus running in V8 --harmony as of recent, though I think it's fixed now. (prohibited with good reason, but providing irreplaceable functionality) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
`var` in eval I meant (and `const` in Narcissus's case) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
Ok I gotta testify for the other side: use strict is not all roses. I hit three problems with 'use strict': 1. I wrote the following code in JavaScript: function register(otherWindow, local, options) { var remote = Q_COMM.Connection(otherWindow, local, options); remote.discover = function (remoteName) {...} return remote; } Upon calling the function I was surprised to find remote.discover was not set. After a long debug session I discovered that Q_COMM had frozen 'remote', but in order for me, the library user to get an error message I had 'use strict'. In my opinion this is a bug. 2. Web Inspector has a bug related to use strict: http://code.google.com/p/chromium/issues/detail?id=114653 3. The typical solution for obtaining a reference to the global object: var global = (function() { return this; })(); fails in 'use strict'. As Domenic tells me, you have use var global = Function('return this')(); These are not fundamental problems with 'use strict', they are practical problems caused by fragmenting the language in to modes. jjb On Mon, Apr 23, 2012 at 5:11 PM, Anton Kovalyov m...@kovalyov.net wrote: My two cents. A little over a year ago, I went over our JavaScript code here at Disqus and made sure that 99% of it is in strict mode. This was definitely a code cleanup aiming at catching variable leaks and other small bugs. -- Anton Kovalyov Sent with Sparrow http://www.sparrowmailapp.com/?sig On Monday, April 23, 2012 at 4:59 PM, Domenic Denicola wrote: As a day-to-day user who was not using strict until recently (stubborn other team member for the loss), I can say that moving to strict was much more a cleanup experience than a mode experience, with only a few small exceptions: 1) Poison-pilling arguments.callee: some code on the internet (notably [1], but elsewhere too) uses this property. 2) Throw on `delete`ing non-configurables: unlike the other throw-on-doing-something-bad, `delete`ing non-configurable properties was something we actually did on purpose. E.g. using it to clear an entry in a map, whether or not that entry was ever filled. (Cf. [2].) We never tried writing to a non-writable property, because that would cause bugs, but `delete`ing a property that doesn't exist was a common pattern. [1]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ [2]: https://github.com/cjohansen/Sinon.JS/commit/80c38bd3e4b8813ab74ef27a4db3646e4778e31c --- Otherwise, it was just cleanup: we got to get rid of our global detector (`setInterval(compareWindowPropertiesToLastTimeYouChecked(), 1000)`), never missed `with` or evil-`eval`, and due to a V8 bug never had boxed `this` in the first place. We're using it transparently throughout the codebase, in fact, due to using an XHR+`eval` module loader that can insert the `use strict` pragma before `eval`ing. -Original Message- From: es-discuss-boun...@mozilla.org [mailto:es-discuss- es-discuss- boun...@mozilla.org] On Behalf Of David Herman Sent: Monday, April 23, 2012 19:11 To: Brendan Eich Cc: es-discuss Subject: Re: A few arrow function specification issues On Apr 23, 2012, at 2:44 PM, Brendan Eich wrote: Brendan Eich wrote: Without arguments runtime semantic shifts, and with |this| lexical, there aren't many strict mode changes left IIRC, and they are pretty edgy edge cases. True enough, but I hang tough on wanting arrows to imply strictness. I may be wrong but the edge cases cited so far (global variable creation by assignment, 'with', direct eval injecting 'var' into its dynamic scope) along with this |this|-boxing one are underwhelming. IMO, this decision hangs on whether we think strict mode can be thought of as a cleaning up that will mostly just catch bugs, resulting in failing faster but otherwise not changing program behavior significantly. POSITION CLEANUP: If it's just a cleanup, then it makes sense to introduce strict mode in a bunch of places in the language. It'll catch bugs, and for the most part people won't have to think to themselves is this strict code? POSITION MODE: If it's something that is likely to change behavior in meaningful ways other than failing faster, then it's something programmers will have to be mindful of. In that case, having multiple constructs that implicitly introduce strict mode imposes a burden on programmers: they have to know which features are strict and which ones aren't. Every fiber of my being screams MODE. Brendan argues CLEANUP based on the rationale that the non-error semantic changes of strict mode are unlikely edge cases. This is the strongest argument against MODE. I can't prove it wrong, but it's a risky bet. If it turns out to be the case that in practice you need to keep track of whether you're in strict mode, then weak programmers who don't know better will end up with a confusing mess, and strong programmers will prophylactically make sure to put their entire programs in
Re: A few arrow function specification issues
On Apr 23, 2012, at 4:59 PM, Domenic Denicola wrote: As a day-to-day user who was not using strict until recently (stubborn other team member for the loss), I can say that moving to strict was much more a cleanup experience than a mode experience, with only a few small exceptions: 1) Poison-pilling arguments.callee: some code on the internet (notably [1], but elsewhere too) uses this property. 2) Throw on `delete`ing non-configurables: unlike the other throw-on-doing-something-bad, `delete`ing non-configurable properties was something we actually did on purpose. E.g. using it to clear an entry in a map, whether or not that entry was ever filled. (Cf. [2].) We never tried writing to a non-writable property, because that would cause bugs, but `delete`ing a property that doesn't exist was a common pattern. [1]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ [2]: https://github.com/cjohansen/Sinon.JS/commit/80c38bd3e4b8813ab74ef27a4db3646e4778e31c The delete issue is very much along the lines of what I was referring to in another thread[3] today regarding failure oblivious computing. I just don't think I see a big benefit from a throw in the situation of deleting a non-configurable property, particularly since there was already another mechanism (delete operator returns false) that indicates that the delete could not be performed. IMO, this the delete strict mode throw was unnecessary and borders on being a bad idea. Perhaps we could remove it from ES6. How much strict mode code do we think is going to actually be dependent on getting that exception? [3]: https://mail.mozilla.org/pipermail/es-discuss/2012-April/022526.html Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Proto-walking proposal [[SetP]] comments
In the [[SetP]] implementation on this page: http://wiki.ecmascript.org/doku.php?id=harmony:proto_climbing_refactoring In step 2, the property lookup should stop when a data descriptor of any sort, writable or non-writable is uncovered. A property closer to the start of a lookup shadows one further along the prototype chain, and these semantics don't preserve that. Step 5c should return true after calling the setter. Step 5d(i) to recheck for extensibility is redundant with [[DefineOwnProperty]]'s check of the same. Technically, only step 2 needs to be changed in order to actually make the logic sane on the first point. And the second point could be fixed with a one-line addition, and the third with a one-line removal. But the algorithm's unwieldy enough with just adding more steps (particularly to step 2), I think you want a somewhat broader refactoring. I make this proposal: [[SetP]](Receiver, P, V) When the [[SetP]] internal method of O is called with initial receiver Receiver, property name P, and value V, the following steps are taken: 1. Let ownDesc be the result of calling the [[GetOwnProperty]] internal method of O with argument P. 2. If ownDesc is not undefined, then a. If IsAccessorDescriptor(ownDesc) is true, then i. Let setter be ownDesc.[[Set]]. ii. If setter is undefined, return false. iii. Call the [[Call]] internal method of setter providing Receiver as the this value and providing V as the sole argument. iv. Return true. b. Otherwise IsDataDescriptor(ownDesc) must be true. i. If ownDesc.[[Writable]] is false, return false. ii. If Receiver === O, then 1. Let updateDesc be the Property Descriptor { [[Value]]: V }. 2. Return the result of calling the [[DefineOwnProperty]] internal method of Receiver passing P, updateDesc, and false as arguments. iii. Else 1. Let newDesc be the Property Descriptor {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}. 2. Return the result of calling the [[DefineOwnProperty]] internal method of Receiver passing P, newDesc, and false as arguments. 3. Let proto be the value of the [[Prototype]] internal property of O. 4. If proto is null, then define the property on Receiver: a. Let newDesc be the Property Descriptor {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}. b. Return the result of calling the [[DefineOwnProperty]] internal method of Receiver passing P, newDesc, and false as arguments. 5. Return the result of calling the [[SetP]] internal method of proto with arguments Receiver, P, and V. Aside from fixing the noted bugs, this makes one further notable change. When the property lookup to determine whether there's a setting conflict bottoms out at the end of the prototype chain, without finding the property, this algorithm simple defines the property on the receiver as a fully mutable property. It doesn't reget the property on the receiver to determine if anything's changed, to set the property consistent with its attributes at that instant. First, this seems more efficient. Under the current algorithm any property miss must make an effort to reget the original property, even just in case. Second, I have difficulty imagining how changes would legitimately happen, in a way that we might consider good coding style. But perhaps I'm missing some reason why this reget is a design requirement; please let me know if I've missed it. Anyway, comments welcome on this -- I'm working on implementing it now, so feedback is particularly timely for me, and I'll be able to provide implementation feedback quickly. Jeff ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Mon, Apr 23, 2012 at 5:47 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Apr 23, 2012, at 4:59 PM, Domenic Denicola wrote: As a day-to-day user who was not using strict until recently (stubborn other team member for the loss), I can say that moving to strict was much more a cleanup experience than a mode experience, with only a few small exceptions: 1) Poison-pilling arguments.callee: some code on the internet (notably [1], but elsewhere too) uses this property. 2) Throw on `delete`ing non-configurables: unlike the other throw-on-doing-something-bad, `delete`ing non-configurable properties was something we actually did on purpose. E.g. using it to clear an entry in a map, whether or not that entry was ever filled. (Cf. [2].) We never tried writing to a non-writable property, because that would cause bugs, but `delete`ing a property that doesn't exist was a common pattern. [1]: http://www.devthought.com/2011/12/22/a-string-is-not-an-error/ [2]: https://github.com/cjohansen/Sinon.JS/commit/80c38bd3e4b8813ab74ef27a4db3646e4778e31c The delete issue is very much along the lines of what I was referring to in another thread[3] today regarding failure oblivious computing. I just don't think I see a big benefit from a throw in the situation of deleting a non-configurable property, particularly since there was already another mechanism (delete operator returns false) that indicates that the delete could not be performed. IMO, this the delete strict mode throw was unnecessary and borders on being a bad idea. Perhaps we could remove it from ES6. How much strict mode code do we think is going to actually be dependent on getting that exception? -1. The failure oblivious computing stuff is fascinating, but I wouldn't try it at home. Such code proceeds silently after it has lost integrity. Not great for anything important. Completely useless for code that must maintain integrity under adversarial conditions. [3]: https://mail.mozilla.org/pipermail/es-discuss/2012-April/022526.html Allen ___ 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: A few arrow function specification issues
On Apr 23, 2012, at 6:09 PM, Mark S. Miller wrote: On Mon, Apr 23, 2012 at 5:47 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: ... The delete issue is very much along the lines of what I was referring to in another thread[3] today regarding failure oblivious computing. I just don't think I see a big benefit from a throw in the situation of deleting a non-configurable property, particularly since there was already another mechanism (delete operator returns false) that indicates that the delete could not be performed. IMO, this the delete strict mode throw was unnecessary and borders on being a bad idea. Perhaps we could remove it from ES6. How much strict mode code do we think is going to actually be dependent on getting that exception? -1. The failure oblivious computing stuff is fascinating, but I wouldn't try it at home. Such code proceeds silently after it has lost integrity. Not great for anything important. Completely useless for code that must maintain integrity under adversarial conditions. The point is that much of what is done on the web is not high integrity computation. It is essential that high integrity be possible, when it is required. But forcing all computation into the high integrity category seems like as bad an idea as forcing all computation to be low integrity. I really wonder how successful JS would have been if it had started out as a high integrity language. Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
On Mon, Apr 23, 2012 at 6:30 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: The point is that much of what is done on the web is not high integrity computation. It is essential that high integrity be possible, when it is required. But forcing all computation into the high integrity category seems like as bad an idea as forcing all computation to be low integrity. I really wonder how successful JS would have been if it had started out as a high integrity language. Yes, I think that's a good point. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: A few arrow function specification issues
+1 High integrity engineering of components supports low integrity integration essential for low cost adaptable systems. We have scripting for the same reason we carpenters. We could build a house using a computer milling machine but no one could afford it; we don't want JavaScript to enforce high precision at the cost of flexibility. jjb On Apr 23, 2012 6:30 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Apr 23, 2012, at 6:09 PM, Mark S. Miller wrote: On Mon, Apr 23, 2012 at 5:47 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: ... The delete issue is very much along the lines of what I was referring to in another thread[3] today regarding failure oblivious computing. I just don't think I see a big benefit from a throw in the situation of deleting a non-configurable property, particularly since there was already another mechanism (delete operator returns false) that indicates that the delete could not be performed. IMO, this the delete strict mode throw was unnecessary and borders on being a bad idea. Perhaps we could remove it from ES6. How much strict mode code do we think is going to actually be dependent on getting that exception? -1. The failure oblivious computing stuff is fascinating, but I wouldn't try it at home. Such code proceeds silently after it has lost integrity. Not great for anything important. Completely useless for code that must maintain integrity under adversarial conditions. The point is that much of what is done on the web is not high integrity computation. It is essential that high integrity be possible, when it is required. But forcing all computation into the high integrity category seems like as bad an idea as forcing all computation to be low integrity. I really wonder how successful JS would have been if it had started out as a high integrity language. Allen ___ 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: A few arrow function specification issues
This is why I posited an explicit switch. Right now we're all talking about secondary triggers for a very important component. Why isn't it just an explicit choice? Why can't I install a foot gun where I know I have foot armor plating? The goal being that when my users, without such armor, are less likely to be exposed to it? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss