Re: Bundling vs sending serialized dependency graph
On Thu, 21 Aug 2014, John Barton wrote: > > > > I'm not sure what you mean here. The list returned from "instantiate" > > is treated the exact same way as the list auto-discovered from > > "import" statements when "instantiate" returns undefined: it's passed > > to ProcessLoadDependencies(), which calls RequestLoad() and > > AddDependencyLoad(), which, if necessary, updates [[Dependencies]]. > > I'll defer to Guy Bedford's expertise: > https://github.com/ModuleLoader/es6-module-loader/pull/204 No need to defer to Guy. You can just look at the spec. But FWIW, what Guy is saying there does not contradict what I said above, as far as I can tell. > The JS module space has had so many rounds of discussions that many > participants are no longer willing to consider alternatives to their > current point of view. It's not clear to me what to make of this. Is feedback on the module system not welcome any more? The ES process is very opaque to me; it's not clear to me how to send feedback. > > > > Finally, it would be ideal if we could also adjust those > > > > dependencies on the fly, since if we're reflecting dependencies > > > > described in the mutable DOM structure, it might be mutated. > > > > > > I think this one is technically difficult. > > > > I don't think anyone here is going to shy away from technically > > difficult problems, it's kind of our bailiwick. :-) > > Sometimes it is better to have a simpler and less powerful tool which > can be well understood than a tool with many difficult-to-master > features. That is orthogonal to how difficult it is to provide those features. Indeed simpler features are usually more difficult to provide than the difficult-to-master features. > Mutating dependencies opens the door to many new kinds of bugs, not only > in the implementation of the Loader but, more important, in the use of > the Loader by developers. I do not disagree. The number of bugs that might be present if we have two separate dependency systems seems yet higher still, though. That's the alternative here, as far as I can tell, since HTML imports allow you to mutate dependencies already. What I'm trying to do is make HTML imports reuse the ES6 model as much as possible to avoid us having to have two dependency systems. > > > > > I guess you're proposing the send the dependency graph to the > > > > > browser, then when a new root is needed, the stored graph is > > > > > compared with the currently-loaded modules. The additional > > > > > modules needed are then requested as a group. Up to this point > > > > > we can just use build tools and browsers. > > > > > > > > Actually, modulo the changes described above, the ES6 loader > > > > already does all this. > > > > > > Huh? How do you plan to parse the modules to obtain dependencies > > > without sending them to the browser? > > > > You send them to the browser, just not in the module itself. > > Where do you get them from? Same place you get the import statements you put in the script modules. > For ES6 it has to be from a build tool or from the server because no one > is going to type these in twice. A tool would certainly make things simpler, but I think you underestimate the motivations authors face when it comes to squeezing performance out of their Web pages. > Such a build tool is just not very difficult and it can be built in to > dev servers so it has no impact on developers work flow. Great! Such tools could trivially output the dependencies in a fashion interpretable by HTML processors. > > The idea is that authors be able to predeclare (relevant parts of) the > > dependency tree such that when a node in that tree is needed, e.g. A > > in the example above, all the relevant nodes can be fetched in > > parallel, e.g. A and C in the example above, rather than in a > > serialised manner, e.g. first fetching A, then parsing it, then > > fetching C. > > Authors have already predeclared the dependency relationships. Now you > want them to re-declare them. Try it and let me know how many devs you > convince. I'm not trying to convince them, they're trying to convince me. I've received voluminous feedback over the years to the effect that they want to be able to do this. > > One way to do this would be to predeclare the modules, as in: > > > > > > > > > > > > > > > > Go back to G+ and ask them if they plan to type thousands of such lines > into their .html files. Talk about a scaling problem! Yup, this wouldn't work when there's thousands of modules. It does when it's just a few dozen, though, which is the more common case. Luckily for us, sites with the complexity of G+ are the extreme, and they are also the cases where the developers are most likely to have the resources to produce their own custom solutions. Having said that, my understanding is that G+ does actually ship this information to the client currently, in a custom format. So it wou
Re: That First Next Argument
On Aug 21, 2014, at 10:42 AM, Allen Wirfs-Brock wrote: > > On Aug 21, 2014, at 9:54 AM, Brendan Eich wrote: > >> Andy Wingo wrote: >>> On Wed 20 Aug 2014 19:55, Brendan Eich writes: >>> > Kevin Smith wrote: > >> function *echo() input { > >> while (true) yield input.value; > >> } > > So input is bound to the next() actual parameter value on each > resumption. That's not bad shed-coloring! > > Andy, Dave: WDYT? >>> >>> I think changing things right now is the wrong thing to do. Since this >>> is a compatible extension, we don't have to think about this for ES6. >>> Just putting that out there;) >> >> Oh definitely -- es-discuss and twitter folks need to assume ES6 is done. >> Train model starting, annual editions if we do it right. Any compatible >> extension can catch next year's train. This means implementation at the >> agreed upon stage 2, usually much sooner than next year. See >> >> https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit >> >> (Allen: is this the canonical location?) > > > See https://github.com/tc39/ecma262 > > the plan is to setup separate sub-repos for proposals starting at stage . > They will have their own issue trackers, etc. oops, that should be "stage 1" in the sentence above. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Thu, Aug 21, 2014 at 1:55 PM, Ian Hickson wrote: > On Thu, 21 Aug 2014, John Barton wrote: > ... more misunderstanding about bundles skipped... > Let's give upon discussing bundles and pursue your dependency list scheme. > > > > > I don't think it should be particularly complex. It only requires some > > > minor changes. One is that we need to be able to declare dependencies > > > ahead of the "instantiate" hook. > > > > By the way I recently discovered that the deplist returned by the > > instantiate hook does not enter the dependency graph analysis. These > > aren't dependencies in a list rather a list of things needed to be > > loaded. > > I'm not sure what you mean here. The list returned from "instantiate" is > treated the exact same way as the list auto-discovered from "import" > statements when "instantiate" returns undefined: it's passed to > ProcessLoadDependencies(), which calls RequestLoad() and > AddDependencyLoad(), which, if necessary, updates [[Dependencies]]. > I'll defer to Guy Bedford's expertise: https://github.com/ModuleLoader/es6-module-loader/pull/204 > > That's all I'm talking about. I want to be able to update [[Dependencies]] > earlier than "instantiate", and I want to be able to mutate > [[Dependencies]] to remove nodes that are no longer dependencies before > the load is complete. > > > > > Another (a subset, really) is that we need to be able to declare > > > dependencies for ES6 modules as well as letting the ES6 infrastructure > > > discover them automatically. > > > > In theory this should be straight-forward. In practice, well good luck. > > Good luck with what? > The JS module space has had so many rounds of discussions that many participants are no longer willing to consider alternatives to their current point of view. > > > > > Finally, it would be ideal if we could also adjust those dependencies > > > on the fly, since if we're reflecting dependencies described in the > > > mutable DOM structure, it might be mutated. > > > > I think this one is technically difficult. > > I don't think anyone here is going to shy away from technically difficult > problems, it's kind of our bailiwick. :-) > Sometimes it is better to have a simpler and less powerful tool which can be well understood than a tool with many difficult-to-master features. Mutating dependencies opens the door to many new kinds of bugs, not only in the implementation of the Loader but, more important, in the use of the Loader by developers. > > The idea is, in fact, to move as many of the technically difficult > problems from things authors have to keep reinventing to things that > browsers just support natively. > > > > > > I guess you're proposing the send the dependency graph to the > > > > browser, then when a new root is needed, the stored graph is > > > > compared with the currently-loaded modules. The additional modules > > > > needed are then requested as a group. Up to this point we can just > > > > use build tools and browsers. > > > > > > Actually, modulo the changes described above, the ES6 loader already > > > does all this. > > > > Huh? How do you plan to parse the modules to obtain dependencies without > > sending them to the browser? > > You send them to the browser, just not in the module itself. > Where do you get them from? For ES6 it has to be from a build tool or from the server because no one is going to type these in twice. Such a build tool is just not very difficult and it can be built in to dev servers so it has no impact on developers work flow. > > > > > It just doesn't quite handle it at the level of pre-emptive > > > declaration of dependencies. But suppose you had two modules A, B, and > > > C. A and B depend on C. With ES6 today, when A is loaded, it loads C. > > > If late you load B, B doesn't reload C; it just links into it. So this > > > is all already supported. All that's needed is a way to tell the ES6 > > > system to get C before it has even received A. > > > > You've really lost me now. I thought your goal was to avoid sending C > > over the network. Now you want to send it without even seeing A? > > Not sending C over the network at all wouldn't work, since it would mean A > doesn't have its dependencies available. I don't follow. > > The idea is that authors be able to predeclare (relevant parts of) the > dependency tree such that when a node in that tree is needed, e.g. A in > the example above, all the relevant nodes can be fetched in parallel, e.g. > A and C in the example above, rather than in a serialised manner, e.g. > first fetching A, then parsing it, then fetching C. > Authors have already predeclared the dependency relationships. Now you want them to re-declare them. Try it and let me know how many devs you convince. > > One way to do this would be to predeclare the modules, as in: > > > > > > > > Go back to G+ and ask them if they plan to type thousands of such lines into their .html files. Talk about a scaling p
Re: Bundling vs sending serialized dependency graph
On Thu, 21 Aug 2014, John Barton wrote: > > I think your graph is upside down from mine ;-) As I learned it, leaf > nodes were the ones at the ends of branches and hence were not dependent > on any other nodes; no node depended on a root node. I don't really mind which way we view the graph. To put it your way: I mean a world where different otherwise unrelated root modules or resources depend on common shared dependencies. > > What exactly is needed depends on what posts are displayed, the user's > > preferences with respect to features like Hangouts, etc. It's a > > complicated graph. > > The only issue that matters for the efficiency of bundle loading is how > many nodes are shared between commonly used dynamically loaded root > modules. If the module is needed always it will be loaded always. If the > module is only used by a single dynamically loaded feature, then there > is no penalty for bundle loading. Even in the case where two or more > dynamic loads use the same large number of modules we can simply put > those modules in a shared bundle. So the case where bundles lose is very > rare. I think bundles are clearly always a win, since at the extreme (one resource per bundle) they just boil down to the same as no bundles. They're never worse than not bundling. But they don't solve the dependency problem. > Here is an attempt and a graph: > > A B C D E > | / \ | / \ / > R XY > > R is always loaded so its bundle loads A and B. > Optional feature X loads C and D but not B its already loaded. > Optional feature Y loads E and possibly DE if X did not already load. > > Only D is extra work and thus this scenario is relatively rare. Rare in this case. In practice, large sites have thousands of modules with many layers of depth in the graph. Modules just change the scale of the problem, they don't remove the problem. > Typically optional modules will share dependencies with the default > loaded page modules or have unique modules. Can you elaborate on how you determine that this is the typical case? Consider G+, or Facebook, or other sites of that nature, where there's hundreds of "leaf" modules (different dialogs, post types, views, etc), and there's modules for each widget (search toolbar, app drawer, notification bell, share box, nav menu, tab strip, chat widget, post box, post box photo view, photo picker, ACL entry box, photo uploader, button, checkbox, radio button, link picker, video picker, event picker, theme picker, drop down button, date picker, time picker, link widget, time zone picker, location picker, map, multiline text box, people browser, list picker, hovercard, the list goes on and on and I've barely scratched the surface of what G+ has here), each of which depends on a number of submodules and so on. I don't think that having multiple levels of dependency is rare at all. > > > But sure, it would be great to have a complete solution if it's not > > > a lot more complex. > > > > I don't think it should be particularly complex. It only requires some > > minor changes. One is that we need to be able to declare dependencies > > ahead of the "instantiate" hook. > > By the way I recently discovered that the deplist returned by the > instantiate hook does not enter the dependency graph analysis. These > aren't dependencies in a list rather a list of things needed to be > loaded. I'm not sure what you mean here. The list returned from "instantiate" is treated the exact same way as the list auto-discovered from "import" statements when "instantiate" returns undefined: it's passed to ProcessLoadDependencies(), which calls RequestLoad() and AddDependencyLoad(), which, if necessary, updates [[Dependencies]]. That's all I'm talking about. I want to be able to update [[Dependencies]] earlier than "instantiate", and I want to be able to mutate [[Dependencies]] to remove nodes that are no longer dependencies before the load is complete. > > Another (a subset, really) is that we need to be able to declare > > dependencies for ES6 modules as well as letting the ES6 infrastructure > > discover them automatically. > > In theory this should be straight-forward. In practice, well good luck. Good luck with what? > > Finally, it would be ideal if we could also adjust those dependencies > > on the fly, since if we're reflecting dependencies described in the > > mutable DOM structure, it might be mutated. > > I think this one is technically difficult. I don't think anyone here is going to shy away from technically difficult problems, it's kind of our bailiwick. :-) The idea is, in fact, to move as many of the technically difficult problems from things authors have to keep reinventing to things that browsers just support natively. > > > I guess you're proposing the send the dependency graph to the > > > browser, then when a new root is needed, the stored graph is > > > compared with the currently-loaded modu
Re: That First Next Argument
Le 20 août 2014 à 10:42, Andy Wingo a écrit : > On Tue 19 Aug 2014 08:48, Claude Pache writes: > >> Le 19 août 2014 à 06:47, Kevin Smith a écrit : >> >>It appears that the current state of affairs is that the argument >>supplied to the first call of `next` on a newborn generator is >>"ignored and inaccessibe". >> >>Is there any way that the generator function can have access to that >>lost data? >> >> This can be worked around. Basically, ask the generator to advance to >> the first `yield` at instantiation, and retrieve the value of the >> "first" `next()` with that `yield`. For example: > > This has the disadvantage of starting computation in the generator, of > course, before it has been asked for. > Indeed. Here is a version that don't start computation early. ```js const ignoreFirst = genFn => class extends genFn { next(x) { delete this.next // next calls to `next` will use directly the super method super() return super(x) } } var echo = ignoreFirst(function* echo() { var x while (true) { x = yield x } }) var iter = new echo // note: `new` is needed for correct subclassing! iter.next(4) // {value: 4, done: false} iter.next(1) // {value: 1, done: false} iter.next(6) // {value: 6, done: false} ``` —Claude ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
> > > Also, write your echo generator this way. You have to duplicate code. > > Ah, of course - thanks for reminding me. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
On Aug 21, 2014, at 9:54 AM, Brendan Eich wrote: > Andy Wingo wrote: >> On Wed 20 Aug 2014 19:55, Brendan Eich writes: >> >>> > Kevin Smith wrote: >> function *echo() input { >> while (true) yield input.value; >> } >>> > >>> > So input is bound to the next() actual parameter value on each >>> > resumption. That's not bad shed-coloring! >>> > >>> > Andy, Dave: WDYT? >> >> I think changing things right now is the wrong thing to do. Since this >> is a compatible extension, we don't have to think about this for ES6. >> Just putting that out there;) > > Oh definitely -- es-discuss and twitter folks need to assume ES6 is done. > Train model starting, annual editions if we do it right. Any compatible > extension can catch next year's train. This means implementation at the > agreed upon stage 2, usually much sooner than next year. See > > https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit > > (Allen: is this the canonical location?) See https://github.com/tc39/ecma262 the plan is to setup separate sub-repos for proposals starting at stage . They will have their own issue trackers, etc. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
Not sure if my real world use case would be super helpful here, but just in case, here it is. The app I work on is a very large single page app - over 150,000 lines of JS across more than 2000 files. Uncompressed, unminified, and concatenated together, it weighs in at close to 10MB. We've been using an in-house module solution (written before most modern tools), and it does smart bundling using a dependency graph. We use import statements (in comments) that are read using a build tool which builds the graph. The full graph is broken into a hierarchy of code bundles that rely on load order expectations. The hierarchy can go many levels deep if needed. Common dependencies are moved up to the closest shared ancestor bundle, so there is no code in multiple code bundles. Right now, this solution works pretty well for us, but is certainly not ideal. One nice thing is that there is a relatively small number (~40) of independent bundles and they can all be created upfront and served from a CDN with far future expiration. The downside is that there are definitely common dependencies that are bundled into ancestors higher up than they ideally should be. With the current spec of modules and loaders, there is no way that we could switch and rely on the behavior of ES6 modules for the reasons specified here. If I have some new code loading point, I want all of the required code to start loading at once. I can't wait for the dependency graph to be figured out as files are getting loaded. The proposal for being able to preload a dependency graph upfront would be tremendously useful for making the switch. My preference would be some kind of json format through a JavaScript API and not some weird script tag thing. - Russ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise() vs. new Promise()
I guess you haven't read the following code that does that in ES5 fashion :-) mixing up syntax ``` Object.defineProperty( Function.prototype, 'new', { configurable: true, get: function () { return Object.defineProperty( this, 'new', {value: (...args)=>new this(...args)} ).new; } } ); ``` But since most of the world of JS is scared to death since ES3 era to extend natives prototypes, wouldn't be nice to spec it as such natively in ES6 or ES7 ? Regards On Thu, Aug 21, 2014 at 5:28 PM, Allen Wirfs-Brock wrote: > > On Aug 20, 2014, at 7:30 PM, Andrea Giammarchi wrote: > > > I like the `Function.prototype.new` hint but unless it's an implicitly > > self bound method you still cannot easily pass it around as callback > > for a map without binding it all over. > > > > `arr.map(MyClass.new)` without needing to explicitly bind it each time > > is needed/used would be an exception, but probably a good one. > > true, but you can write: > > arr.map((...a)=>new Map(...a)); > > or define: > > Object.assign(Function.prototype, { >get asFactory() {return (...args)=>new this(...args)} > } > > so you can say: > > arr.map(MyClass.asFactory) > > Allen > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Comprehensions, Where Art Thou?
> Where are [methods called .lazy(), .concat(), .map(), .filter(), and > .flatMap()] defined? Is it intended that .map() and .flatMap() will > be defined on all iterables? Just in case it wasn't obvious from the repo, these are defined in traceur.init.js. Lovely style. I have to admit that the sudoku demos were quite an eye opener in terms of just what the features in es6 can do. On the other hand, I agree with others that typical use of array comprehensions are simple and fast (see fast.js) due to not having function call overhead each iteration. I'm concerned that the sexy use of yield and function* may not be as performant as simple comprehensions. -- Owen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Thu, 21 Aug 2014, C. Scott Ananian wrote: > On Thu, Aug 21, 2014 at 11:54 AM, John Barton wrote: > > Where? The Load Request records imply a dependency graph. Are these > > maintained though out the life of the page? I don't see any existing > > reason to expect these are maintained. > > Ian's proposal (well, mutation in general) certainly implies that these > (or an appropriate summary) should be maintained. Again, possibly you > can drop parts of the graph from memory once all requests have been > fulfilled... but I think that's an implementation optimization. The > simplest spec would just stipulate a persistent dependency graph. I'd > guess that you'd want to restrict arbitrary reads of the graph in order > to allow the optimization. Write-only access would be best. I don't think we need to maintain the dependency graph beyond the link stage. Once something is linked, it doesn't really matter if the dependency is still true or not, since it doesn't make any difference -- it can't block the load any more. So I'm happy with the way the ES6 spec discards the dependency information. The important change IMHO is that the dependency information be maintained from earlier in the cycle, and be mutable (write-only would be fine, assuming you can remove dependencies; there's no need, IMHO, to expose the actual dependency chain to script). -- Ian Hickson U+1047E)\._.,--,'``.fL http://ln.hixie.ch/ U+263A/, _.. \ _\ ;`._ ,. Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.' ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
Kevin Smith wrote: I've been thinking about ways to explicitly place the initial yield. One ideal is a reserved keyword sequence starting with 'yield`, such as `yield continue` to mark the initial yield point. If a generator function does not contain an explicit `yield continue`, then it is implicit at the start of the function body. So when the generator function is executed (and before next has been called), it will run until the `yield continue` (or somesuch), instead of stopping at the start of the function body? That would be great, actually. Except it's an oxymoron: the continue does not mean no-pause-at-this-yield, and the proposal abuses the keyword otherwise used only with loops. Also, write your echo generator this way. You have to duplicate code. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
Andy Wingo wrote: On Wed 20 Aug 2014 19:55, Brendan Eich writes: > Kevin Smith wrote: >> function *echo() input { >> while (true) yield input.value; >> } > > So input is bound to the next() actual parameter value on each > resumption. That's not bad shed-coloring! > > Andy, Dave: WDYT? I think changing things right now is the wrong thing to do. Since this is a compatible extension, we don't have to think about this for ES6. Just putting that out there;) Oh definitely -- es-discuss and twitter folks need to assume ES6 is done. Train model starting, annual editions if we do it right. Any compatible extension can catch next year's train. This means implementation at the agreed upon stage 2, usually much sooner than next year. See https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit (Allen: is this the canonical location?) That said, first thoughts: * I assume "input" could then be captured by nested scopes. This would be a bit strange but could work. It should act like a strict parameter binding (no arguments[arguments.length] alias!). * Really you'd want to be able to destructure too, as you can in every other part of the grammar that introduces names. That's probably not a great thing to do here, though. That would require bracketing, or at least a connecting punctuator. Could be done. * I assume Kevin meant: function *echo input { while (true) yield input } To me it smells, but perhaps that is just my grumpiness;) (Grumpy enough not to cuddle * with function :-P.) Why no () after echo for the empty parameter list? That's a surprise. Yeah, no .value needed (Kevin can confirm). Explicitly being able to place the initial yield would be nicer, but then it's more difficult to ensure that the initial yield comes before other yields. Right. I say punt;) For ES6, of course. Seems fair es-discuss fodder for future Harmony inclusion. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
> > > I've been thinking about ways to explicitly place the initial yield. One > ideal is a reserved keyword sequence starting with 'yield`, such as `yield > continue` to mark the initial yield point. If a generator function does not > contain an explicit `yield continue`, then it is implicit at the start of > the function body. > So when the generator function is executed (and before next has been called), it will run until the `yield continue` (or somesuch), instead of stopping at the start of the function body? That would be great, actually. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: That First Next Argument
On Aug 21, 2014, at 12:04 AM, Andy Wingo wrote: > On Wed 20 Aug 2014 19:55, Brendan Eich writes: > >> Kevin Smith wrote: >>>function *echo() input { >>>while (true) yield input.value; >>>} >> >> So input is bound to the next() actual parameter value on each >> resumption. That's not bad shed-coloring! >> >> Andy, Dave: WDYT? > > I think changing things right now is the wrong thing to do. Since this > is a compatible extension, we don't have to think about this for ES6. > Just putting that out there ;) > > That said, first thoughts: > > * I assume "input" could then be captured by nested scopes. This >would be a bit strange but could work. > > * Really you'd want to be able to destructure too, as you can in every >other part of the grammar that introduces names. That's probably >not a great thing to do here, though. > > * I assume Kevin meant: > > function *echo input { while (true) yield input } > > To me it smells, but perhaps that is just my grumpiness ;) > > Explicitly being able to place the initial yield would be nicer, but > then it's more difficult to ensure that the initial yield comes before > other yields. > > I say punt ;) > I've been thinking about ways to explicitly place the initial yield. One ideal is a reserved keyword sequence starting with 'yield`, such as `yield continue` to mark the initial yield point. If a generator function does not contain an explicit `yield continue`, then it is implicit at the start of the function body. I don't think it is necessary to statically ensure that `yield continue` comes before any other `yield`. It would simply be a runtime detected error if it does not. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise() vs. new Promise()
On Aug 20, 2014, at 7:30 PM, Andrea Giammarchi wrote: > I like the `Function.prototype.new` hint but unless it's an implicitly > self bound method you still cannot easily pass it around as callback > for a map without binding it all over. > > `arr.map(MyClass.new)` without needing to explicitly bind it each time > is needed/used would be an exception, but probably a good one. true, but you can write: arr.map((...a)=>new Map(...a)); or define: Object.assign(Function.prototype, { get asFactory() {return (...args)=>new this(...args)} } so you can say: arr.map(MyClass.asFactory) Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Thu, Aug 21, 2014 at 11:54 AM, John Barton wrote: > On Thu, Aug 21, 2014 at 8:37 AM, C. Scott Ananian > wrote: > Where? The Load Request records imply a dependency graph. Are these > maintained though out the life of the page? I don't see any existing reason > to expect these are maintained. Ian's proposal (well, mutation in general) certainly implies that these (or an appropriate summary) should be maintained. Again, possibly you can drop parts of the graph from memory once all requests have been fulfilled... but I think that's an implementation optimization. The simplest spec would just stipulate a persistent dependency graph. I'd guess that you'd want to restrict arbitrary reads of the graph in order to allow the optimization. Write-only access would be best. > You deleted the context of my comment. I asserted that a build tool was > needed. Ian claimed the Loader could do it. Now you are claiming I'm wrong > because a build tool is used. I apologize if I misconstrued the crux of your disagreement. --scott ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Thu, Aug 21, 2014 at 8:37 AM, C. Scott Ananian wrote: > On Thu, Aug 21, 2014 at 11:00 AM, John Barton > wrote: > >> Finally, > >> it would be ideal if we could also adjust those dependencies on the > >> fly, since if we're reflecting dependencies described in the mutable > >> DOM structure, it might be mutated. > > > > I think this one is technically difficult. > > I don't think this is actually all that hard. We have a dependency > graph, Where? The Load Request records imply a dependency graph. Are these maintained though out the life of the page? I don't see any existing reason to expect these are maintained. > along with a list of things that are (a) required, (b) already > loaded, and (optionally) (c) in-flight. We mutate the graph > arbitrarily, recompute the list of things that we need to load given > the new (a), compare that to (b) and (c), and then start new/cancel > old loads as necessary. I don't think it's worthwhile to specify > incremental algorithms here, just specify the stop-the-world > computation over the complete graph. Optimization left to the > implementation, if needed. > > > Huh? How do you plan to parse the modules to obtain dependencies without > > sending them to the browser? > [...] > > You've really lost me now. I thought your goal was to avoid sending C > over > > the network. Now you want to send it without even seeing A? > > I think Ian has explained this multiple times already. The HTML file > contains a declarative specification of all resource dependencies, via > attributes on script tags or some such. This is either generated > manually or via some future authoring tool. > You deleted the context of my comment. I asserted that a build tool was needed. Ian claimed the Loader could do it. Now you are claiming I'm wrong because a build tool is used. > > This doesn't seem so crazy to me. That's because you left out the crazy part ;-) > And, since presumably we can > already deal with mutation of the dependency graph (see above), we can > always adjust those declarations to match "reality" after we parse the > module file (although probably only to add new edges, not remove any > declared dependencies). Thus the base case with no explicit > declarations in the HTML matches the on-demand behavior given by > current ES6. > > Ian, FWIW, I've been staying out of this thread mostly because you > seem to be on top of it -- and because frankly I've already been > exhausted by the module wars. But IMO you're doing excellent work. > I agree that the part of Ian's story about sending over the deps list is beginning to sound very attractive. In fact I think it is a stronger story than the current spec altogether. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise() vs. new Promise()
On Thu, Aug 21, 2014 at 3:22 AM, Salvador de la Puente González wrote: > The only problem I see here is you can not emulate completely `new` with ES. > Why Promise add some internal slots when called with new and it does not > make the same when writing `var p = Object.create(Promise.prototype); > Promise.call(p, fn);`? Not true. See, for example: https://github.com/paulmillr/es6-shim/issues/170#issuecomment-34528376 https://github.com/paulmillr/es6-shim/blob/master/test/promise/subclass.js#L5 https://github.com/cscott/prfun/blob/master/lib/index.js#L520 It's super-annoying, but you can actually write ES5 code that will properly inherit the new internal slots in ES6. I'm a big fan of `Function.prototype.new`, though. And I think `Promise.new.bind(Promise)` is not all that terrible, if you want to pass around a constructor as a function. (And there's another es-discuss thread about trying to unify `new` as an "ordinary" function call in proxies as well.) --scott ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
instantiate() deps list
The Loader instantiate() function is described: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reflect.loader.prototype.instantiate Based on that description I assume that the 'deps' property returned by instantiate() meant "dependencies" that would be loaded by the loader. That is, one can leverage the dependency traversal from a custom loader. But it's not possible to do this. Specifically: --- Otherwise, the instantiate hook must return an eventual instantiationRequest object. An instantiateRequest object has two required properties. The value of the deps property is an array of strings. Each string is the name of a module upon which the module identified by loadRequest has dependencies. The value of the execute property is a function which the loader will use to create the module and link it with its clients and dependencies. The function should expect to receive the same number of arguments as the size of the deps array and must return an eventual Module object. The arguments are Module objects and have a one-to-one correspondence with elements of the deps array. The module is evaluated during the linking process. First all of the modules it depends upon are linked and evaluated , and then passed to the execute function. Then the resulting module is linked with the downstream dependencies. --- However it turns out that the names in 'deps' are simply fetched and passed back to instantiate(). They do not enter the dependency analysis. To give a concrete example, if A depends on B depends on C and instantiate() is called with A, it can't simply return a deps list with "b". It has to perform the entire dependency analysis of A and ensure the tree is loaded. Simply returning 'b' as a deps value will result in an execution sequence like A, B, and then C, not the order C, B, A one would expect from a dependency analysis. I'm sure there is a good reason for this behavior but it should be clearly called out in the spec. jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Thu, Aug 21, 2014 at 11:00 AM, John Barton wrote: >> Finally, >> it would be ideal if we could also adjust those dependencies on the >> fly, since if we're reflecting dependencies described in the mutable >> DOM structure, it might be mutated. > > I think this one is technically difficult. I don't think this is actually all that hard. We have a dependency graph, along with a list of things that are (a) required, (b) already loaded, and (optionally) (c) in-flight. We mutate the graph arbitrarily, recompute the list of things that we need to load given the new (a), compare that to (b) and (c), and then start new/cancel old loads as necessary. I don't think it's worthwhile to specify incremental algorithms here, just specify the stop-the-world computation over the complete graph. Optimization left to the implementation, if needed. > Huh? How do you plan to parse the modules to obtain dependencies without > sending them to the browser? [...] > You've really lost me now. I thought your goal was to avoid sending C over > the network. Now you want to send it without even seeing A? I think Ian has explained this multiple times already. The HTML file contains a declarative specification of all resource dependencies, via attributes on script tags or some such. This is either generated manually or via some future authoring tool. This doesn't seem so crazy to me. And, since presumably we can already deal with mutation of the dependency graph (see above), we can always adjust those declarations to match "reality" after we parse the module file (although probably only to add new edges, not remove any declared dependencies). Thus the base case with no explicit declarations in the HTML matches the on-demand behavior given by current ES6. Ian, FWIW, I've been staying out of this thread mostly because you seem to be on top of it -- and because frankly I've already been exhausted by the module wars. But IMO you're doing excellent work. --scott ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Bundling vs sending serialized dependency graph
On Wed, Aug 20, 2014 at 4:53 PM, Ian Hickson wrote: > On Wed, Aug 20, 2014 at 4:06 PM, John Barton > wrote: > > On Mon, Aug 18, 2014 at 10:43 AM, Ian Hickson wrote: > >> > >> This just doens't work. > >> > >> Suppose the dependency graph looks like this: > >> > >> Feature A --> Dependency A1 \__\ Dependency\ > >> Feature B --> Dependency B1 / /AB >--> Dependency D > >> Feature C --> Dependency C1 ---> Dependency C2 / > >> > >> All of A, B, and C are to be fetched on-demand-only, to avoid using up > >> too much bandwidth. All the files here are non-trivial in size. > >> > >> How do you package this? > >> > >> If you make a package for A, a package for B, and a package for C, then > >> you'll have redundant content in the packages, and when the client asks > >> for B after already having asked for A, the amount of content sent back > >> will be greater than necessary and therefore it'll be slower than > >> necessary. If you create multiple packages such that you group as much > as > >> possible into each package as possible without overlap, then you still > end > >> up with multiple resources to download when you need any of A, B, or C. > >> Basically, it boils down to: > >> > >> Package A \__\ Package\ > >> Package B / /AB >--> Package D > >> Package C -> / > >> > >> ...and then you're back to the problem I asked about. If you don't have > >> server-side support, then to avoid round-trips the client needs to know > >> about the dependencies before it makes the first request. It can't wait > >> til it receives the packages to discover the dependencies because if you > >> do that then you're serialising your RTTs instead of pipelining them. > > > > I assume you are imagining a densely connected graph with random access > to > > any of the roots. > > I'm not quite sure what that means. > It means that the graph of all possible modules for a page cannot be partitioned into packages without sending much of the shared graph over the wire multiple times. > > I mean a world where different otherwise unrelated leaf modules or > resources depend on common shared dependencies. > Leaf modules don't depend on anything. That's what a leaf means. > > > > I expect that real life pages have well partitioned graphs > > (widgets) that share some dense parts (utilities) and simple access > patterns > > -- main page, utilities, a set of widgets. > > I doubt that the Web is that convenient. On some well-designed sites > it might work out that way. > > Consider a site like Google+, though. However well-designed it is, it > fundamentally has a lot of common files used by lots of intermediate > shared files used by lots of leaf modules (and a lot more depth while > we're at it). I think your graph is upside down from mine ;-) As I learned it, leaf nodes were the ones at the ends of branches and hence were not dependent on any other nodes; no node depended on a root node. > What exactly is needed depends on what posts are > displayed, the user's preferences with respect to features like > Hangouts, etc. It's a complicated graph. > The only issue that matters for the efficiency of bundle loading is how many nodes are shared between commonly used dynamically loaded root modules. If the module is needed always it will be loaded always. If the module is only used by a single dynamically loaded feature, then there is no penalty for bundle loading. Even in the case where two or more dynamic loads use the same large number of modules we can simply put those modules in a shared bundle. So the case where bundles lose is very rare. Here is an attempt and a graph: A B C D E | / \ | / \ / R XY R is always loaded so its bundle loads A and B. Optional feature X loads C and D but not B its already loaded. Optional feature Y loads E and possibly DE if X did not already load. Only D is extra work and thus this scenario is relatively rare. Typically optional modules will share dependencies with the default loaded page modules or have unique modules. > > > But sure, it would be great to have a complete solution if it's not a lot > > more complex. > > I don't think it should be particularly complex. It only requires some > minor changes. One is that we need to be able to declare dependencies > ahead of the "instantiate" hook. By the way I recently discovered that the deplist returned by the instantiate hook does not enter the dependency graph analysis. These aren't dependencies in a list rather a list of things needed to be loaded. > Another (a subset, really) is that we > need to be able to declare dependencies for ES6 modules as well as > letting the ES6 infrastructure discover them automatically. In theory this should be straight-forward. In practice, well good luck. > Finally, > it would be ideal if we could also adjust those dependencies on the > fly, since if we're reflecting dependencies described in the mutable > DOM
Re: Promise() vs. new Promise()
It will not if you have ```js function Foo() { Bar.call(this); } ``` as generic way to extend classes in your old style logic, something that will inevitably fail the moment you do `Foo.prototype = Object.create(Bar.prototype);` with `Bar` that comes from ES6 and it has been defined as `class` instead of old style function. This is an interoperability problem where the new world cannot work in the old one and having `typeof Constructor === 'function'` means any old inheritance based code won't even bother wrapping the .call behind a try catch. I hope I've described the problem in a better way ... this choice breaks badly old patterns and I am not sure yet I understand advantages about it. Also, if you ask me, I think `Array` example I proposed is a bad spec about how the `Array` behaves, and subclassing in general in ES3. We all know that, now we have triple behavior in ES6. Regards On Thu, Aug 21, 2014 at 3:16 PM, Tab Atkins Jr. wrote: > On Thu, Aug 21, 2014 at 2:03 AM, Andrea Giammarchi > wrote: > > This is also a precedent that suggest `Object.create(Generic.prototype)` > is > > useless when the `Generic` is ES6 class due inability to initialize it > later > > on: a very "bad news" for prototypal inheritance. > > > > Accordingly, interoperability with old code (the "one JS" myth) is > > compromised and prototypal inheritance won't be "fully portable" with > > user-land classes. > > > > Latter is not necessarily unexpected since we know other cases that could > > fail, i.e. > > > > ```js > > var a = Object.create(Array.prototype); > > Array.call(a, 1, 2, 3); > > a; // still empty > > > > Array(1, 2, 3); // [1,2,3] > > ``` > > I don't generally see this kind of "inheritance" used; it seems like a > weird way to say "var a = new Array(1, 2, 3);". > > I do commonly see code like: > > ``` > function Foo() { > ... > } > Foo.prototype = Object.create(Bar.prototype); > ``` > > Which always works and will continue to work in the future. > > ~TJ > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise() vs. new Promise()
On Thu, Aug 21, 2014 at 2:03 AM, Andrea Giammarchi wrote: > This is also a precedent that suggest `Object.create(Generic.prototype)` is > useless when the `Generic` is ES6 class due inability to initialize it later > on: a very "bad news" for prototypal inheritance. > > Accordingly, interoperability with old code (the "one JS" myth) is > compromised and prototypal inheritance won't be "fully portable" with > user-land classes. > > Latter is not necessarily unexpected since we know other cases that could > fail, i.e. > > ```js > var a = Object.create(Array.prototype); > Array.call(a, 1, 2, 3); > a; // still empty > > Array(1, 2, 3); // [1,2,3] > ``` I don't generally see this kind of "inheritance" used; it seems like a weird way to say "var a = new Array(1, 2, 3);". I do commonly see code like: ``` function Foo() { ... } Foo.prototype = Object.create(Bar.prototype); ``` Which always works and will continue to work in the future. ~TJ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Status/Thoughts on Guards?
These are all great examples and resources. Thanks everyone. On Thursday, August 21, 2014, Charles Pick wrote: > Just to throw another example out there, here's a Design by Contract > library which squeezes itself within existing ES syntax - > https://github.com/codemix/contractual > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Status/Thoughts on Guards?
Just to throw another example out there, here's a Design by Contract library which squeezes itself within existing ES syntax - https://github.com/codemix/contractual ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise() vs. new Promise()
Agreed, and not only Promise. AFAIK there is no way to detect if a generic constructor is a typeof 'class' or just a function, then invokable through a well known, commonly used pattern as `Generic.call(obj, p1, p2)` is when it comes to generics initializations. This is also a precedent that suggest `Object.create(Generic.prototype)` is useless when the `Generic` is ES6 class due inability to initialize it later on: a very "bad news" for prototypal inheritance. Accordingly, interoperability with old code (the "one JS" myth) is compromised and prototypal inheritance won't be "fully portable" with user-land classes. Latter is not necessarily unexpected since we know other cases that could fail, i.e. ```js var a = Object.create(Array.prototype); Array.call(a, 1, 2, 3); a; // still empty Array(1, 2, 3); // [1,2,3] ``` but interoperability with user land classes, the inability to initialize an object through one or more constructor composing behaviors, and the inability to emulate `new` does not make it look like a wise choice. On the other hand, what is the advantage of knowing that `new` was used, if not for some syntax parser or JIT sake, if any? Why anyone would like to be sure `new` was used instead of `Object.create` and why the former should keep failing with native and now with classes too? Just curious to know who or what will end up benefiting this choice. Thanks in advance for clarifications Best Regards On Thu, Aug 21, 2014 at 8:22 AM, Salvador de la Puente González < sa...@unoyunodiez.com> wrote: > The only problem I see here is you can not emulate completely `new` with > ES. Why Promise add some internal slots when called with new and it does > not make the same when writing `var p = Object.create(Promise.prototype); > Promise.call(p, fn);`? > > > On Thu, Aug 21, 2014 at 5:18 AM, Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> To this I'd like to add that in ES6 you don't need to explicitly invoke >> inherited class constructor but rather use `super` >> >> True is that this `new` story makes Mixins like constructors more >> difficult to use as classes becuase these cannot be invoked via `.call` or >> `.apply` directly and requires a very boring `init()` like method. >> >> Although there's nothing for mixins or their initialization in ES6 so >> it's OKish ... >> >> Last, but not least, since you use instanceof, I'd like to underline in >> ES5 capable browser you have another pattern. >> >> ```js >> function SelfInstance() {'use strict'; >> return this || new SelfInstance; >> } >> ``` >> >> no need to use the `instanceof` check when `this` could be undefined ^_^ >> >> Regards >> >> >> >> >> On Wed, Aug 20, 2014 at 5:55 PM, Alex Kocharin wrote: >> >>> >>> 20.08.2014, 19:18, "Claude Pache" : >>> > Le 20 août 2014 à 16:56, Alex Kocharin a écrit : >>> >> But... why? >>> >> >>> >> I mean, every constructor can determine if it is called without >>> `new` (that "this instanceof" check on top of every other constructor). So >>> `new` keyword can really be removed from everywhere except in constructors >>> themselves. >>> >> >>> >> Using `new` does create issues. For example, you can't write "new >>> require('something').Constructor(blah)", and I don't even remember how to >>> put brackets right. >>> >> >>> >> Why make people use it? >>> > >>> > According to http://esdiscuss.org/notes/2013-07-25 (search for >>> "anti-pattern"), allowing constructors without `new` would break >>> subclassing. >>> >>> Still doesn't make much sense... This pattern (this instanceof ...) >>> breaks another pattern (BaseClass.call(this)). Why first one is deprecated, >>> not the second one? >>> >>> I mean, I was able to subclass such a class with prototype injection >>> without any issues, and it feels more natural in javascript after all. >>> >> >> >> ___ >> 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: Promise() vs. new Promise()
The only problem I see here is you can not emulate completely `new` with ES. Why Promise add some internal slots when called with new and it does not make the same when writing `var p = Object.create(Promise.prototype); Promise.call(p, fn);`? On Thu, Aug 21, 2014 at 5:18 AM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > To this I'd like to add that in ES6 you don't need to explicitly invoke > inherited class constructor but rather use `super` > > True is that this `new` story makes Mixins like constructors more > difficult to use as classes becuase these cannot be invoked via `.call` or > `.apply` directly and requires a very boring `init()` like method. > > Although there's nothing for mixins or their initialization in ES6 so it's > OKish ... > > Last, but not least, since you use instanceof, I'd like to underline in > ES5 capable browser you have another pattern. > > ```js > function SelfInstance() {'use strict'; > return this || new SelfInstance; > } > ``` > > no need to use the `instanceof` check when `this` could be undefined ^_^ > > Regards > > > > > On Wed, Aug 20, 2014 at 5:55 PM, Alex Kocharin wrote: > >> >> 20.08.2014, 19:18, "Claude Pache" : >> > Le 20 août 2014 à 16:56, Alex Kocharin a écrit : >> >> But... why? >> >> >> >> I mean, every constructor can determine if it is called without `new` >> (that "this instanceof" check on top of every other constructor). So `new` >> keyword can really be removed from everywhere except in constructors >> themselves. >> >> >> >> Using `new` does create issues. For example, you can't write "new >> require('something').Constructor(blah)", and I don't even remember how to >> put brackets right. >> >> >> >> Why make people use it? >> > >> > According to http://esdiscuss.org/notes/2013-07-25 (search for >> "anti-pattern"), allowing constructors without `new` would break >> subclassing. >> >> Still doesn't make much sense... This pattern (this instanceof ...) >> breaks another pattern (BaseClass.call(this)). Why first one is deprecated, >> not the second one? >> >> I mean, I was able to subclass such a class with prototype injection >> without any issues, and it feels more natural in javascript after all. >> > > > ___ > 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: That First Next Argument
On Wed 20 Aug 2014 19:55, Brendan Eich writes: > Kevin Smith wrote: >> function *echo() input { >> while (true) yield input.value; >> } > > So input is bound to the next() actual parameter value on each > resumption. That's not bad shed-coloring! > > Andy, Dave: WDYT? I think changing things right now is the wrong thing to do. Since this is a compatible extension, we don't have to think about this for ES6. Just putting that out there ;) That said, first thoughts: * I assume "input" could then be captured by nested scopes. This would be a bit strange but could work. * Really you'd want to be able to destructure too, as you can in every other part of the grammar that introduces names. That's probably not a great thing to do here, though. * I assume Kevin meant: function *echo input { while (true) yield input } To me it smells, but perhaps that is just my grumpiness ;) Explicitly being able to place the initial yield would be nicer, but then it's more difficult to ensure that the initial yield comes before other yields. I say punt ;) Andy ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss