module exports
I'm trying to understand the options for exporting things from a module. Here's how I think it works, mostly based on what I see in Traceur. Does any of this look wrong? To export a value, export var someName = someValue; To export a function, export function someName(args) { ... }; To export multiple things defined elsewhere in this file, export {name1, name2, ...}; Here's the part that confuses me most. It seems that importers have three options. 1) import specific things from a given module 2) import everything that was exported from a given module 3) import a subset of what a given module exports that it identified as the default (presumably the most commonly used things) To define the default subset of things to export from a module, export default = some-value or some-function; where some-value could be an object holding a collection of things to export. -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
Have you ever used JavaScript module systems before? If so, the idea of a default export should be somewhat familiar… On Mar 14, 2014, at 6:31, Mark Volkmann r.mark.volkm...@gmail.com wrote: I'm trying to understand the options for exporting things from a module. Here's how I think it works, mostly based on what I see in Traceur. Does any of this look wrong? To export a value, export var someName = someValue; To export a function, export function someName(args) { ... }; To export multiple things defined elsewhere in this file, export {name1, name2, ...}; Here's the part that confuses me most. It seems that importers have three options. 1) import specific things from a given module 2) import everything that was exported from a given module 3) import a subset of what a given module exports that it identified as the default (presumably the most commonly used things) To define the default subset of things to export from a module, export default = some-value or some-function; where some-value could be an object holding a collection of things to export. -- R. Mark Volkmann Object Computing, Inc. ___ 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: module exports
I have used Node.js extensively. In that environment, as I'm sure you know, a module exports one thing. It can be an object with lots of properties on it, a single function, or a single value. I suppose you could say that all Node has is a default export which is the one thing the module exports. I'm trying to understand how that compares to ES6 modules. I see how in ES6 I can import specific things from a module or I can import everything a module exports. Am I correct that a default export can be somewhere in the middle ... a subset of everything that is exported? On Fri, Mar 14, 2014 at 8:22 AM, Domenic Denicola dome...@domenicdenicola.com wrote: Have you ever used JavaScript module systems before? If so, the idea of a default export should be somewhat familiar... On Mar 14, 2014, at 6:31, Mark Volkmann r.mark.volkm...@gmail.com wrote: I'm trying to understand the options for exporting things from a module. Here's how I think it works, mostly based on what I see in Traceur. Does any of this look wrong? To export a value, export var someName = someValue; To export a function, export function someName(args) { ... }; To export multiple things defined elsewhere in this file, export {name1, name2, ...}; Here's the part that confuses me most. It seems that importers have three options. 1) import specific things from a given module 2) import everything that was exported from a given module 3) import a subset of what a given module exports that it identified as the default (presumably the most commonly used things) To define the default subset of things to export from a module, export default = some-value or some-function; where some-value could be an object holding a collection of things to export. -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
I'm trying to understand how that compares to ES6 modules. I see how in ES6 I can import specific things from a module or I can import everything a module exports. You can't really import all exported bindings. You can import the module instance object itself: module M from wherever; which will give you access to all of the exports. Am I correct that a default export can be somewhere in the middle ... a subset of everything that is exported? Not really. The default export is literally just an export named default. There is sugar on the import side, where you can leave off the braces: import foo from somewhere; is equivalent to: import { default as foo } from somewhere; The specialized default export syntax is just plain confusing and should be jettisoned, in my opinion. It would be less confusing for users to simply write: export { foo as default }; I fail to see why sugar over this form is necessary. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
I understand it's hard to make changes after a certain point. It's too bad though that developers will have to remember that the way to import a few things from a module is: import {foo, bar} from 'somewhere'; but the way to import the whole module is: module SomeModule from 'somewhere'; instead of import SomeModule from 'somewhere'; It just seems so clean to say that if you want to import something, you always use the import keyword. On Fri, Mar 14, 2014 at 9:12 AM, Kevin Smith zenpars...@gmail.com wrote: export { foo as default }; I fail to see why sugar over this form is necessary. I completely agree. Plus if this is taken away then the import keyword can be used to get the whole module as in my example above. At that point maybe there is no need for the module keyword. Maybe, but at this point that would be too big of a change to swallow. I think if we can just focus on eliminating this one pointless and confusing aspect (the export default [expr] form), we'll be good to go. -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: module exports
Importing is nothing like destructuring. You import mutable bindings; you don't do assignment. I'm very glad that different syntax is used for each case. From: Mark Volkmann r.mark.volkm...@gmail.com Sent: Friday, March 14, 2014 10:19 To: Kevin Smith Cc: Domenic Denicola; es-discuss@mozilla.org Subject: Re: module exports I understand it's hard to make changes after a certain point. It's too bad though that developers will have to remember that the way to import a few things from a module is: import {foo, bar} from 'somewhere'; but the way to import the whole module is: module SomeModule from 'somewhere'; instead of import SomeModule from 'somewhere'; It just seems so clean to say that if you want to import something, you always use the import keyword. On Fri, Mar 14, 2014 at 9:12 AM, Kevin Smith zenpars...@gmail.commailto:zenpars...@gmail.com wrote: export { foo as default }; I fail to see why sugar over this form is necessary. I completely agree. Plus if this is taken away then the import keyword can be used to get the whole module as in my example above. At that point maybe there is no need for the module keyword. Maybe, but at this point that would be too big of a change to swallow. I think if we can just focus on eliminating this one pointless and confusing aspect (the export default [expr] form), we'll be good to go. -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
What is a 'mutable binding'? On Fri, Mar 14, 2014 at 7:30 AM, Domenic Denicola dome...@domenicdenicola.com wrote: Importing is nothing like destructuring. You import mutable bindings; you don't do assignment. I'm very glad that different syntax is used for each case. -- *From:* Mark Volkmann r.mark.volkm...@gmail.com *Sent:* Friday, March 14, 2014 10:19 *To:* Kevin Smith *Cc:* Domenic Denicola; es-discuss@mozilla.org *Subject:* Re: module exports I understand it's hard to make changes after a certain point. It's too bad though that developers will have to remember that the way to import a few things from a module is: import {foo, bar} from 'somewhere'; but the way to import the whole module is: module SomeModule from 'somewhere'; instead of import SomeModule from 'somewhere'; It just seems so clean to say that if you want to import something, you always use the import keyword. On Fri, Mar 14, 2014 at 9:12 AM, Kevin Smith zenpars...@gmail.com wrote: export { foo as default }; I fail to see why sugar over this form is necessary. I completely agree. Plus if this is taken away then the import keyword can be used to get the whole module as in my example above. At that point maybe there is no need for the module keyword. Maybe, but at this point that would be too big of a change to swallow. I think if we can just focus on eliminating this one pointless and confusing aspect (the export default [expr] form), we'll be good to go. -- R. Mark Volkmann Object Computing, Inc. ___ 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: module exports
```js // module1.js export let foo = 5; export function changeFoo() { foo = 10; } // module2.js import { foo, changeFoo } from ./module1; // Import imports mutable bindings // So calling changeFoo will change the foo in current scope (and original scope) console.log(foo); // 5 changeFoo(); console.log(foo); // 10 // module3.js module module1 from ./module1; let { foo, changeFoo } = module1; // Destructuring uses assignment to copy over the current values // So calling changeFoo does not affect this binding for foo console.log(foo); // 5 changeFoo(); console.log(foo); // 5 From: John Barton johnjbar...@google.com Sent: Friday, March 14, 2014 10:35 To: Domenic Denicola Cc: Mark Volkmann; Kevin Smith; es-discuss@mozilla.org Subject: Re: module exports What is a 'mutable binding'? On Fri, Mar 14, 2014 at 7:30 AM, Domenic Denicola dome...@domenicdenicola.com wrote: Importing is nothing like destructuring. You import mutable bindings; you don't do assignment. I'm very glad that different syntax is used for each case. From: Mark Volkmann r.mark.volkm...@gmail.com Sent: Friday, March 14, 2014 10:19 To: Kevin Smith Cc: Domenic Denicola; es-discuss@mozilla.org Subject: Re: module exports I understand it's hard to make changes after a certain point. It's too bad though that developers will have to remember that the way to import a few things from a module is: import {foo, bar} from 'somewhere'; but the way to import the whole module is: module SomeModule from 'somewhere'; instead of import SomeModule from 'somewhere'; It just seems so clean to say that if you want to import something, you always use the import keyword. On Fri, Mar 14, 2014 at 9:12 AM, Kevin Smith zenpars...@gmail.com wrote: export { foo as default }; I fail to see why sugar over this form is necessary. I completely agree. Plus if this is taken away then the import keyword can be used to get the whole module as in my example above. At that point maybe there is no need for the module keyword. Maybe, but at this point that would be too big of a change to swallow. I think if we can just focus on eliminating this one pointless and confusing aspect (the export default [expr] form), we'll be good to go. -- R. Mark Volkmann Object Computing, Inc. ___ 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: module exports
On Fri, Mar 14, 2014 at 10:07 AM, Mark Volkmann r.mark.volkm...@gmail.comwrote: On Fri, Mar 14, 2014 at 8:54 AM, Kevin Smith zenpars...@gmail.com wrote: I'm trying to understand how that compares to ES6 modules. I see how in ES6 I can import specific things from a module or I can import everything a module exports. You can't really import all exported bindings. You can import the module instance object itself: module M from wherever; which will give you access to all of the exports. That's what I meant by importing all the exports. I'd prefer it if the syntax for that was import M from wherever; As Kevin said, this already means import the default export from 'wherever' That way I could think of import is doing something like destructuring where the other syntax below is just getting some of the exports. import {foo, bar} from wherever'; Am I correct that a default export can be somewhere in the middle ... a subset of everything that is exported? Not really. The default export is literally just an export named default. There is sugar on the import side, where you can leave off the braces: import foo from somewhere; is equivalent to: import { default as foo } from somewhere; The specialized default export syntax is just plain confusing and should be jettisoned, in my opinion. It would be less confusing for users to simply write: export { foo as default }; I fail to see why sugar over this form is necessary. Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
Is the common use case for export default when you want to give users of the module an easy way to obtain a single function? So instead of users doing this: import {someFn} from 'wherever'; they can do this: import someFn from 'wherever'; On Fri, Mar 14, 2014 at 9:40 AM, Rick Waldron waldron.r...@gmail.comwrote: On Fri, Mar 14, 2014 at 10:07 AM, Mark Volkmann r.mark.volkm...@gmail.com wrote: On Fri, Mar 14, 2014 at 8:54 AM, Kevin Smith zenpars...@gmail.comwrote: I'm trying to understand how that compares to ES6 modules. I see how in ES6 I can import specific things from a module or I can import everything a module exports. You can't really import all exported bindings. You can import the module instance object itself: module M from wherever; which will give you access to all of the exports. That's what I meant by importing all the exports. I'd prefer it if the syntax for that was import M from wherever; As Kevin said, this already means import the default export from 'wherever' That way I could think of import is doing something like destructuring where the other syntax below is just getting some of the exports. import {foo, bar} from wherever'; Am I correct that a default export can be somewhere in the middle ... a subset of everything that is exported? Not really. The default export is literally just an export named default. There is sugar on the import side, where you can leave off the braces: import foo from somewhere; is equivalent to: import { default as foo } from somewhere; The specialized default export syntax is just plain confusing and should be jettisoned, in my opinion. It would be less confusing for users to simply write: export { foo as default }; I fail to see why sugar over this form is necessary. Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} Rick -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: module exports
Indeed. If you have used Node.js extensively, I am sure you are familiar with this paradigm. From: es-discuss es-discuss-boun...@mozilla.org on behalf of Mark Volkmann r.mark.volkm...@gmail.com Sent: Friday, March 14, 2014 10:50 To: Rick Waldron Cc: es-discuss@mozilla.org Subject: Re: module exports Is the common use case for export default when you want to give users of the module an easy way to obtain a single function? So instead of users doing this: import {someFn} from 'wherever'; they can do this: import someFn from 'wherever'; On Fri, Mar 14, 2014 at 9:40 AM, Rick Waldron waldron.r...@gmail.commailto:waldron.r...@gmail.com wrote: On Fri, Mar 14, 2014 at 10:07 AM, Mark Volkmann r.mark.volkm...@gmail.commailto:r.mark.volkm...@gmail.com wrote: On Fri, Mar 14, 2014 at 8:54 AM, Kevin Smith zenpars...@gmail.commailto:zenpars...@gmail.com wrote: I'm trying to understand how that compares to ES6 modules. I see how in ES6 I can import specific things from a module or I can import everything a module exports. You can't really import all exported bindings. You can import the module instance object itself: module M from wherever; which will give you access to all of the exports. That's what I meant by importing all the exports. I'd prefer it if the syntax for that was import M from wherever; As Kevin said, this already means import the default export from 'wherever' That way I could think of import is doing something like destructuring where the other syntax below is just getting some of the exports. import {foo, bar} from wherever'; Am I correct that a default export can be somewhere in the middle ... a subset of everything that is exported? Not really. The default export is literally just an export named default. There is sugar on the import side, where you can leave off the braces: import foo from somewhere; is equivalent to: import { default as foo } from somewhere; The specialized default export syntax is just plain confusing and should be jettisoned, in my opinion. It would be less confusing for users to simply write: export { foo as default }; I fail to see why sugar over this form is necessary. Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} Rick -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} The alternative here is: function MyThing() {} export { MyThing as default }; Which is more clear, more readable, and barely less ergonomic. If you *really* want the AssignmentExpression form, you've got to put the equals in there. I've said this before, but without the equals it looks too much like a declaration: export default class C {} var c = new C(); // No C defined, WTF? Node users don't elide the equals sign, do they? module.exports = whateva; So why are we? Equals aside, let's look at the cost/benefit ratio here: - Benefit: a little less typing (at most one savings per module) - Cost: more confusion and StackOverflow questions about default export syntax. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
Sigh. The example just better demonstrates how clunky the syntax is and how surprising the semantics can be. :( rant I hope one of the CommonJS or RequireJS folks write a good ES6 module loader so that I can continue to use reasonable syntax and ignore all of this. This really smells like Second System Syndrome. The module spec is trying to do too much. *Both* module objects *and* mutable bindings. *Both* defaults *and* named exports. There is a certain elegance to the way both RequireJS and CommonJS reuse fundamental JavaScript patterns (assignment, functions-with-arguments, objects-with-properties). The `gjs` module system was even smaller, with a single magic `imports` object. I really wish the ES6 module system could be chopped down to clearly express a single idea, and do more with less. /rant --scott ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Fri, Mar 14, 2014 at 11:04 AM, Kevin Smith zenpars...@gmail.com wrote: Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} The alternative here is: function MyThing() {} export { MyThing as default }; Which is more clear, more readable, I think it's fair to say that these are subjective claims. and barely less ergonomic. If you *really* want the AssignmentExpression form, you've got to put the equals in there. I don't understand this claim, any legal AssignmentExpression form is allowed. I've said this before, but without the equals it looks too much like a declaration: export default class C {} var c = new C(); // No C defined, WTF? Why is this surprising? Named function expressions don't create a lexical binding for their name and therefore cannot be called by that name from outside of the function body: var f = function a() {}; a(); // nope. The same thing applies to class expressions, which is what is written in your example--class C {} is effectively the same as the expression _between_ = and ; of the following: var D = class C {}; And no one would expect to be able to this: var c = new C(); But if you used the `export Declaration` form, it will work (as it does today, without `export` of course): export class C {} var c = new C(); export function F() {} var f = new F(); Node users don't elide the equals sign, do they? module.exports = whateva; So why are we? To make a single form that works across platforms (ie. an amd module doesn't just work in node and vice versa). I don't think this is strong enough to be considered a valid counter-point, I recommend not pursuing it. `export default function() {}` will work the same way on all platforms. Equals aside, let's look at the cost/benefit ratio here: - Benefit: a little less typing (at most one savings per module) - Cost: more confusion and StackOverflow questions about default export syntax. If a developer knows how named function expression bindings work today, this won't be a big surprise. Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Fri, Mar 14, 2014 at 9:15 AM, Rick Waldron waldron.r...@gmail.comwrote: On Fri, Mar 14, 2014 at 11:04 AM, Kevin Smith zenpars...@gmail.comwrote: Because it doesn't allow for the Assignment Expression form (specifically, function expressions) that developers expect to be able to write: export default function() {} The alternative here is: function MyThing() {} export { MyThing as default }; Which is more clear, more readable, I think it's fair to say that these are subjective claims. Indeed, and subjectively I agree with Kevin. and barely less ergonomic. If you *really* want the AssignmentExpression form, you've got to put the equals in there. I don't understand this claim, any legal AssignmentExpression form is allowed. I've said this before, but without the equals it looks too much like a declaration: export default class C {} var c = new C(); // No C defined, WTF? Why is this surprising? It is surprising because it looks like it should work like export class C {} The keyword 'default' looks like a modifier like 'const'. If a developer knows how named function expression bindings work today, this won't be a big surprise. I know how named function expressions work and it's still surprising. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
var f = function a() {}; a(); // nope. Sure, note the equals (which is my point). var D = class C {}; And no one would expect to be able to this: var c = new C(); Same thing. Note the equals, which gives the reader the necessary visual cue that we are entering an AssignmentExpression context. But if you used the `export Declaration` form, it will work (as it does today, without `export` of course): export class C {} var c = new C(); export function F() {} var f = new F(); Right. The lack of equals sign shows us that this is clearly a declaration. Node users don't elide the equals sign, do they? module.exports = whateva; So why are we? To make a single form that works across platforms (ie. an amd module doesn't just work in node and vice versa). I don't think this is strong enough to be considered a valid counter-point, I recommend not pursuing it. `export default function() {}` will work the same way on all platforms. Sorry, I don't understand this. ES6 modules, whatever they are, will be the same across platforms. And if I believe TC39 is making a mistake, I will pursue it : ) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
I like that more I read about this, more the `with` statement comes into my mind ... console.log(foo); // Oh, yeah, this really means module1.foo looks like that changeFoo(); here the implicit context ? ... if so, I have no idea which one it is and why ... also, can I change it? Maybe I asked for a function utility, not for a trapped context bound into an exported function I cannot change later on console.log(foo); // Ok, since this is secretly module1.foo, the result '10' makes sense. nope, not at all, at least here Cheers On Fri, Mar 14, 2014 at 9:27 AM, John Barton johnjbar...@google.com wrote: I've used es6 modules for several months now and I'm curious to know when I would want to leverage mutable bindings. I guess I need to begin to imagine that variables bound to imports are really a kind of property name of s secret object: import { foo, changeFoo } from ./module1; console.log(foo); // Oh, yeah, this really means module1.foo changeFoo(); console.log(foo); // Ok, since this is secretly module1.foo, the result '10' makes sense. jjb On Fri, Mar 14, 2014 at 7:40 AM, Domenic Denicola dome...@domenicdenicola.com wrote: ```js // module1.js export let foo = 5; export function changeFoo() { foo = 10; } // module2.js import { foo, changeFoo } from ./module1; // Import imports mutable bindings // So calling changeFoo will change the foo in current scope (and original scope) console.log(foo); // 5 changeFoo(); console.log(foo); // 10 // module3.js module module1 from ./module1; let { foo, changeFoo } = module1; // Destructuring uses assignment to copy over the current values // So calling changeFoo does not affect this binding for foo console.log(foo); // 5 changeFoo(); console.log(foo); // 5 From: John Barton johnjbar...@google.com Sent: Friday, March 14, 2014 10:35 To: Domenic Denicola Cc: Mark Volkmann; Kevin Smith; es-discuss@mozilla.org Subject: Re: module exports What is a 'mutable binding'? On Fri, Mar 14, 2014 at 7:30 AM, Domenic Denicola dome...@domenicdenicola.com wrote: Importing is nothing like destructuring. You import mutable bindings; you don't do assignment. I'm very glad that different syntax is used for each case. From: Mark Volkmann r.mark.volkm...@gmail.com Sent: Friday, March 14, 2014 10:19 To: Kevin Smith Cc: Domenic Denicola; es-discuss@mozilla.org Subject: Re: module exports I understand it's hard to make changes after a certain point. It's too bad though that developers will have to remember that the way to import a few things from a module is: import {foo, bar} from 'somewhere'; but the way to import the whole module is: module SomeModule from 'somewhere'; instead of import SomeModule from 'somewhere'; It just seems so clean to say that if you want to import something, you always use the import keyword. On Fri, Mar 14, 2014 at 9:12 AM, Kevin Smith zenpars...@gmail.com wrote: export { foo as default }; I fail to see why sugar over this form is necessary. I completely agree. Plus if this is taken away then the import keyword can be used to get the whole module as in my example above. At that point maybe there is no need for the module keyword. Maybe, but at this point that would be too big of a change to swallow. I think if we can just focus on eliminating this one pointless and confusing aspect (the export default [expr] form), we'll be good to go. -- R. Mark Volkmann Object Computing, Inc. ___ 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 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Fri, Mar 14, 2014 at 12:24 PM, Kevin Smith zenpars...@gmail.com wrote: var f = function a() {}; a(); // nope. Sure, note the equals (which is my point). var D = class C {}; And no one would expect to be able to this: var c = new C(); Same thing. Note the equals, which gives the reader the necessary visual cue that we are entering an AssignmentExpression context. What about the following: Functions with return AssignmentExpression that include = and without--are the ones without also confusing without the necessary visual cue? function a() { var F; return F = function() {}; } function b() { var C; return C = class {}; } vs. function c() { return function F() {}; } function d() { return class C {}; } Or yield in generators? function * a() { var F; yield F = function F() {}; } function * b() { var C; yield C = class C {}; } vs. function * c() { yield function F() {}; } function * d() { yield class C {}; } But if you used the `export Declaration` form, it will work (as it does today, without `export` of course): export class C {} var c = new C(); export function F() {} var f = new F(); Right. The lack of equals sign shows us that this is clearly a declaration. Node users don't elide the equals sign, do they? module.exports = whateva; So why are we? To make a single form that works across platforms (ie. an amd module doesn't just work in node and vice versa). I don't think this is strong enough to be considered a valid counter-point, I recommend not pursuing it. `export default function() {}` will work the same way on all platforms. Sorry, I don't understand this. ES6 modules, whatever they are, will be the same across platforms. Isn't that exactly what I said? You asked So why are we?, I answered To make a single form that works across platforms and added that amd and cjs don't just work together. Then I concluded by with a specific example, but surely that wasn't too misleading? Rick ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
I don't understand this claim, any legal AssignmentExpression form is allowed. I've said this before, but without the equals it looks too much like a declaration: export default class C {} var c = new C(); // No C defined, WTF? Why is this surprising? It is surprising because it looks like it should work like export class C {} The keyword 'default' looks like a modifier like 'const'. I completely agree with this. It looks like a modifier. In addition to not having an = or some other reason to think it will be evaluated as an expression, default *is* a reserved word *and* has special significance here. Yes, it is grammatically unambiguous and can be learned, but this is a question of intuition. The meaning here goes very strongly against my intuition. If a developer knows how named function expression bindings work today, this won't be a big surprise. I know how named function expressions work and it's still surprising. Same here. If anything, I would say that it makes more sense to go ahead and run with the intuition we seem to be feeling with is that it seems like a modifier of the export. So maybe like: export default class C {} var c = new C(); //works export default function f(){} f(); //works export default let obj = {a:1,b:2}; var a = obj.a; //works ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Initializer expression on for-in syntax subject
JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) --Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Mar 14, 2014, at 9:27 AM, John Barton johnjbar...@google.com wrote: I've used es6 modules for several months now and I'm curious to know when I would want to leverage mutable bindings. So cycles work! // model.js import View from view; export default class Model { ... } // view.js import Model from model; export default class View { ... } This kind of thing just falls flat on its face in Node and AMD. I guess I need to begin to imagine that variables bound to imports are really a kind of property name of s secret object: If that gets you there, that's cool. But it's a bit sloppy. It blurs userland data structures with internal language implementation data structures. Here's how I think about it. A variable in JS denotes a binding, which is basically an association with a mutable location in memory. In particular it doesn't denote a value. The binding has a value at any given time. When you export from a module, you're exporting bindings, rather than values. This means you can refactor between module m from foo; ... m.bar and import { bar } from foo; ... bar and they're fully equivalent. But it also means that when you have modules that mutate their exports during initialization, you don't run into as many subtle order-of-initialization issues as you do with AMD and Node, because importing something syntactically early doesn't mean you accidentally snapshot its pre-initialized state. (Also, keep in mind that the vast majority of module exports are set once and never changed, in which case this semantics *only* fixes bugs.) Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Mar 14, 2014, at 9:37 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I like that more I read about this, more the `with` statement comes into my mind ... There's nothing like this in JS today, so if you're only looking for precedent there, you're only going to be able to come up with weak analogies. The differences between aliasing bindings from a module with a fixed, declarative set of bindings, and aliasing bindings from an arbitrary user-specified and dynamically modifiable object are massive. And see my reply to JJB to get an understanding of why this is such an important semantics. tl;dr non-busted cycles. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Mar 14, 2014, at 10:50 AM, Russell Leggett russell.legg...@gmail.com wrote: I completely agree with this. It looks like a modifier. This is a good point, and folks working on the Square transpiler noticed this, too. I think there's a more surgical fix, though (and I'm not entertaining major syntax redesign at this point). In fact it's one with precedent in JS. In statements, we allow both expressions and declarations, which is a syntactic overlap. But visually people expect something that looks like a declaration in that context to be a declaration, so the lookahead restriction breaks the tie in favor of declarations. I think we're seeing the exact same phenomenon with `export default` -- the modifiers make it look more like a declaration context. So I think we should consider doing the same thing as we do for ExpressionStatement: ExportDeclaration : ... export default FunctionDeclaration ; export default ClassDeclaration ; export default [lookahead !in { function, class }] AssignmentExpression ; This actually results in no net change to the language syntax, but it allows us to change the scoping rules so that function and class declarations scope to the entire module: // function example export default function foo() { ... } ... foo(); // class example export default class Foo { ... } ... let x = new Foo(...); // expression example export default { x: 1, y: 2, z: 3 }; I argue that not only does this avoid violating surprise, it's not any more of a special-casing logic than we already have with ExpressionStatement, because it's the same phenomenon: a context that allows a formally ambiguous union of two productions, but whose context strongly suggests the declaration interpretation over the expression interpretation in the overlapping cases. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
Sad panda. At least we can disable it in strict mode, right? And who knows, maybe some day, some day... Dave, dreaming of ES24 On Mar 13, 2014, at 4:59 PM, Oliver Hunt oli...@apple.com wrote: JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) --Oliver ___ 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: module exports
From: es-discuss es-discuss-boun...@mozilla.org on behalf of David Herman dher...@mozilla.com So I think we should consider doing the same thing as we do for ExpressionStatement: ... This actually results in no net change to the language syntax, but it allows us to change the scoping rules so that function and class declarations scope to the entire module: This seems nice; a tentative +1. I like how surgical of a change it is. Personally I have not found the current state confusing. `default`, just like `yield` or `return` or `throw` or others, was a fine signifier for me that we're entering an expression context. But since others don't seem to have adapted, perhaps this will help them. And it is definitely convenient in cases where you want to refer to the default export elsewhere within the module. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
ExportDeclaration : ... export default FunctionDeclaration ; export default ClassDeclaration ; export default [lookahead !in { function, class }] AssignmentExpression ; I think this would allay most of my concerns. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: module exports
David Herman wrote: I think we're seeing the exact same phenomenon with `export default` -- the modifiers make it look more like a declaration context. So I think we should consider doing the same thing as we do for ExpressionStatement: snip I agree with the confusion (due in part because the nearly-identical TypeScript syntax puts the exported identifiers in scope), and the fix seems to address the problem so I support it. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Fri, Mar 14, 2014 at 11:42 AM, David Herman dher...@mozilla.com wrote: When you export from a module, you're exporting bindings, rather than values. This means you can refactor between module m from foo; ... m.bar and import { bar } from foo; ... bar and they're fully equivalent. Ok great, so one solution to potential confusion caused by 'import' is simply to always use 'module'. But it also means that when you have modules that mutate their exports during initialization, you don't run into as many subtle order-of-initialization issues as you do with AMD and Node, because importing something syntactically early doesn't mean you accidentally snapshot its pre-initialized state. (Also, keep in mind that the vast majority of module exports are set once and never changed, in which case this semantics *only* fixes bugs.) If I am understanding correctly, I'm skeptical because the semantics of these bindings resemble the semantics of global variables. Our experience with global variables is that they make somethings easy at the cost of creating opportunities for bugs. Function arguments and return values provide a degree of isolation between parts of programs. Bindings allow two parts of a program, related only by importing the same module, to interact in ways that two functions called by the same function could not. The coupling is rather like public object properties but without the object prefix to remind you that you are interacting with shared state. That's where the 'module' form may be more suitable: I expect 'm.bar' to have a value which might change within my scope due to operations in other functions. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
David I know the analogy was weak but since indeed you said there's nothing like that, I named the one that felt somehow close because of some implicit behavior. I am personally easy going on modules, I like node.js require and I think that behind an await like approach could work asynchronously too but I don't want to start a conversation already done many times so ... I'll watch from the outside, waiting for a definitive how it's going to be spec before even analyzing how that even works. IMO, modules in ES6 went a bit too far than expected. Take care On Fri, Mar 14, 2014 at 11:45 AM, David Herman dher...@mozilla.com wrote: On Mar 14, 2014, at 9:37 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: I like that more I read about this, more the `with` statement comes into my mind ... There's nothing like this in JS today, so if you're only looking for precedent there, you're only going to be able to come up with weak analogies. The differences between aliasing bindings from a module with a fixed, declarative set of bindings, and aliasing bindings from an arbitrary user-specified and dynamically modifiable object are massive. And see my reply to JJB to get an understanding of why this is such an important semantics. tl;dr non-busted cycles. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: module exports
On Fri, Mar 14, 2014 at 3:34 PM, John Barton johnjbar...@google.com wrote: On Fri, Mar 14, 2014 at 11:42 AM, David Herman dher...@mozilla.com wrote: When you export from a module, you're exporting bindings, rather than values. This means you can refactor between module m from foo; ... m.bar and import { bar } from foo; ... bar and they're fully equivalent. Ok great, so one solution to potential confusion caused by 'import' is simply to always use 'module'. Another way to put this is that changing: ```js import { bar } from foo; ``` to ```js module m from foo; let bar = m.bar; ``` will always be a subtle source of bugs. Looked at another way, the module spec is introducing a new sort of assignment statement, where the bindings are mutable. But instead of adding this as a high-level feature of the language, it's being treated as a weird special case for modules only. I would be happier introducing a general purpose mutable binding assignment like: ```js let mutable bar = m.bar; ``` where every reference to bar is always treated as a dereference of `m.bar`. That way the new assignment feature isn't pigeonholed as a weird part of the module spec. Couldn't we assemble the desired semantics out of pre-existing primitives, instead of inventing new stuff? For example, if `m.bar` in the example above was a proxy object we could preserve the desired mutable binding without inventing new language features. --scott ps. I foresee a future where modules are (ab)used to create mutable bindings. Better to make them first-class language features! pps. Circular references work just fine in node. You have to be a little careful about them, but the 'mutable bindings' don't change that. They just introduce `bar` as a new shorthand for writing `m.bar`. IMHO the latter is actually preferable, as it makes it obvious to the author and reader of the code exactly what is going on. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
On Fri, Mar 14, 2014 at 12:29 PM, David Herman dher...@mozilla.com wrote: Sad panda. At least we can disable it in strict mode, right? yes! And who knows, maybe some day, some day... Dave, dreaming of ES24 I'll hazard a public prediction for the record: Since ES6 does implicit strict opt-in for both classes and modules, by the time of wide ES7 deployment, sloppy mode will no longer matter much for new code. Or ES8 at the latest. It's just a prediction, so no need to argue until we're in the predicted timeframe. On Mar 13, 2014, at 4:59 PM, Oliver Hunt oli...@apple.com wrote: JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) --Oliver ___ 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 -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
On 14 March 2014 00:59, Oliver Hunt oli...@apple.com wrote: JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) I'd be curious to know what the actual code is, and to get an idea why they are using it that way. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
Andreas Rossberg wrote: On 14 March 2014 00:59, Oliver Huntoli...@apple.com wrote: JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) I'd be curious to know what the actual code is, and to get an idea why they are using it that way. http://battlelog.battlefield.com/bf4/ for (var i = 0 in debug.audio) I say we should evangelize this site. Cc'ing some awesome Mozilla site evangelists. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
Brendan Eich wrote: for (var i = 0 in debug.audio) BTW, ur-JS in Netscape would not parse this. The optional initializer fell out of grammar over-reuse in ES1, possibly also works-in-JScript lobbying (my memory fades but that is where it came from). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
JSC has been trying to kill off the initialiser expression in the for(in) statement, but we've encountered a bunch of reasonably significant content that breaks with it disallowed (a particularly prominent one currently is http://battlelog.battlefield.com/bf4/), so we will be bringing back support for for (var Identifier = Expression in Expression) I suggested to Oliver that we accept Identifier = Expression in Expression” as valid syntax, but drop = Expression” from the parse tree after the fact. That way, we can still almost completely remove the construct from the language without harming web compatibility. I don’t see much value in making this decision based on strict mode. So far, we’ve got nothing but trouble from policies like that. Geoff___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Source maps (was: Multiline Strings)
I'm not married to the AST format I proposed. I do feel very strongly that each language targeting JS shouldn't have to write a browser devtools extension for every browser its users want to debug. I feel very strongly that users debugging their sources that were compiled to js should be able to set watch expressions and conditional breakpoints in their source language. I feel very strongly that users should be able to inspect their program's environment and bindings whether or not those bindings have been compiled into JS variables or into an index in a typed array. I feel very strongly that users should be able to inspect their values and data types directly rather than the implementation of those data types when compiled to JS. (Imagine using GDB and only printing binary blobs instead of a nice printout of a struct and its slot names and corresponding values). Perhaps not all of that belongs in the debug format, but the functionality should be exposed somehow. One thing I tried to stress about the importance of an extensible format was that it would be easy for compilers to progressively add more debugging information to the source maps they generated. If the compiler should decide that it will only ever do source location mapping, that would be fine as well. _Nick_ On Thu, Mar 13, 2014 at 7:20 AM, David Nolen dnolen.li...@gmail.com wrote: As the maintainer of the ClojureScript compiler this doesn't sound like much of a simplification. The sum total of source map support in ClojureScript is 400 lines of Clojure. To support what's being proposed would add a significant amount of complexity for something we don't care about at all - the JavaScript AST. We currently rely entirely on the Google Closure Compiler for the final pass as it offers best of class minification, optimization, and dead code elimination. A source map format based on annotating a JS AST seems to introduce a lot of complexity once you start thinking about how this information will be preserved over multiple stages of minification, optimization, and dead code elimination. Some of your suggestions also seem to me to be best handled by other means and don't belong in a source map proposal at all - REPL support and printing/presentation of language objects. FWIW, the ClojureScript community has completely embraced the existing source map technology. Some of the issues raised like scope we find to be minor issues that don't really impeded effective debugging as we try to avoid renaming and unclear munging as much as possible. Honestly the two things we really want - REPL support and printing of ClojureScript objects could easily be addressed by providing appropriate simple hooks into the dev tools offered by a browser vendor. To have to bother with generating and annotating JS ASTs to achieve these two things just sounds like pointless work. David On Wed, Mar 12, 2014 at 5:00 PM, Nick Fitzgerald fitz...@gmail.com wrote: 4) Browsers are still all over the place in how they report Error stack trace information. We (Firefox Developer Tools) purposefully don't expose source mapped stacks to the web because it would require adding some kind of API to know when source maps are done being fetched or blocking(!) on Error.prototype.stack until the source map is fetched. We also avoid fetching source maps unless the debugger is open, so this would expose to the web if the debugger is open. Furthermore, we wouldn't want to only have the source mapped stack, you would also want the plain JS stack if you think that the source map could be bogus or if you are debugging the source maps you are generating as a tool author. This would further complicate the stack string. 1) There is not yet a standard for sourcemaps. But see https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k, https://developers.google.com/chrome-developer-tools/docs/javascript-debugging#source-maps, and https://github.com/mozilla/source-map/. Would someone care to champion this for inclusion in ES7? If a debug format for targeting JavaScript were to be standardized, it should do more than simply file/line/column translation. My thoughts on this subject outgrew an email reply, so I have collected them here: http://fitzgeraldnick.com/weblog/55/ _Nick_ ___ 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: Initializer expression on for-in syntax subject
Geoffrey Garen wrote: I suggested to Oliver that we accept Identifier = Expression in Expression” as valid syntax, but drop = Expression” from the parse tree after the fact. Note that the issue here is only legacy that uses 'var' before Identifier. So you can't be sure of no compat break, since for (var x = 'haha' in {}); with no enumerable properties on Object.prototype will iterate zero times, and the hoisted var x will be initialized to 'haha' and available after the loop. That way, we can still almost completely remove the construct from the language without harming web compatibility. I wish. But let's just evangelize the site, and any others that use this botch from the ancient world (JScript = ES1). I don’t see much value in making this decision based on strict mode. So far, we’ve got nothing but trouble from policies like that. I agree we shouldn't fuss with strict mode, it doesn't pay. We should impulse-shoot the bad old form, right between the eyes, in ES6. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
On Fri, Mar 14, 2014 at 3:31 PM, Brendan Eich bren...@mozilla.org wrote: Geoffrey Garen wrote: I suggested to Oliver that we accept Identifier = Expression in Expression” as valid syntax, but drop = Expression” from the parse tree after the fact. Note that the issue here is only legacy that uses 'var' before Identifier. So you can't be sure of no compat break, since for (var x = 'haha' in {}); with no enumerable properties on Object.prototype will iterate zero times, and the hoisted var x will be initialized to 'haha' and available after the loop. That way, we can still almost completely remove the construct from the language without harming web compatibility. I wish. But let's just evangelize the site, and any others that use this botch from the ancient world (JScript = ES1). I don’t see much value in making this decision based on strict mode. So far, we’ve got nothing but trouble from policies like that. Your nothing but claim is so silly it doesn't need a serious response. There are a zillion counter-examples starting with lexical scoping. But leaving aside the nothing but silliness, what trouble do you have in mind? I agree we shouldn't fuss with strict mode, it doesn't pay. We should impulse-shoot the bad old form, right between the eyes, in ES6. Hey, if we can kill the bad feature completely, great. The strict mode suggestion is only relevant if we can't kill it is sloppy mode. /be ___ 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
ES6 iteration over object values
Does ES6 add any new ways to iterate over the values in an object? I've done a lot of searching, but haven't seen anything. I'm wondering if there is something more elegant than this: Object.keys(myObj).forEach(function (key) { let obj = myObj[key]; // do something with obj }); -- R. Mark Volkmann Object Computing, Inc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ES6 iteration over object values
On 3/14/2014 5:16 PM, Mark Volkmann wrote: Does ES6 add any new ways to iterate over the values in an object? I've done a lot of searching, but haven't seen anything. I'm wondering if there is something more elegant than this: Object.keys(myObj).forEach(function (key) { let obj = myObj[key]; // do something with obj }); Not built in, but ES6 does provide a better story for this using generators and for-of: ```js // using a generator function function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } // an alternative version using a generator expression function entries(obj) { return (for (key of Object.keys(obj)) [key, obj[key]]); } for (let [key, value] of entries(myObj)) { // do something with key|value } ``` ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Initializer expression on for-in syntax subject
Peter van der Zee wrote: Which browsers currently don't accept this construct? I wasn't even aware that JSC didn't support it at some point. Did anyone say JSC lacked support? I think KJS followed ES3, and this was in the ES1 grammar, so I doubt it was never supported. Minifiers might rely on this construct. And perhaps some js1k entries, if that matters anything. Extremely doubtful. It doesn't save anything. A minifier cannot count on the loop iterating 0 times. Why is there a desire for banishment anyways? Only lack of consistency compared to not using the var keyword, This is only about the 'var' case. The initialiser in 'for (var x = y in z)' is due only to reuse of the wrong grammar nonterminal in ES1, based on JScript de-facto non-standard behavior. It is a wart and a pain to implement. We don't expect it to be hard to remove, unlike other warts, but we'll find out. or was there a bigger problem with this? The thread comes out of the blue to me so I probably missed a prior discussion :) ES6 revised the old grammar dating from ES1, breaking for(var x = y in z). That was intentional and discussed in past meetings and threads. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss