Re: Throwing errors on mutating immutable bindings
On Oct 2, 2014, at 8:31 AM, Andreas Rossberg wrote: > On 2 October 2014 17:17, Allen Wirfs-Brock wrote: >> I believe that the module champions have always wanted static unresolvablse >> reference rejection to be part of the module semantics. But we've never had >> actual specification for that semantics. > > Yes, I had always hoped for a "stricter mode" applied to modules. But > I don't think that's something that's still possible at this (or a > later) point. If it had been, then it would have made total sense for > it to check against const assignments as well, along with a number of > other things. Yeah, I did wish for it, but we conceded a long time ago that it wasn't going to work out to have additional checks in modules. It's especially problematic because whether something is unbound or global is entirely dynamic (globals can be added and removed), scripts can be loaded at dynamically unpredictable times (so predicting the state of the global at the time code will be loaded is hard), in some modes HTML even throws element ids on the global and removes them again ... > >> Personally, I think it would be fine for all of these sort of conditions to >> be specified as runtime errors and leave it to linters to find them early >> and JS implementations to optimize the runtime checks away. > > Outside modules, with the language being as it is, adding one minor > new static check definitely does not seem worth the trouble and the > cost risk. Agreed. The consolation prize is that modules now make it possible for linters to do free variable analysis and errors without any user-configuration at all. (By contrast, JSHint has historically required programmers to annotate the set of globals they intend to use so that they aren't reported as free variable errors.) Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Toplevel 'let' binding can be left permanently uninitialized after an error
On Sep 30, 2014, at 4:03 AM, Andreas Rossberg wrote: > On 30 September 2014 12:52, Jason Orendorff wrote: >> I just realized this has an unfortunate implication for REPLs. Suppose >> you make this typo: >> >>js> let x = Math.cso(a)// oops, TypeError, should be Math.cos >> >> Now x is irreparably hosed in your REPL. That seems bad. > > No surprise. One of the reasons why I always favoured a nested scopes > model for multiple scripts... We've had this debate a million times, but for anyone who's unfamiliar with the arguments: nested scopes makes recursive bindings across scripts impossible and is also hard to understand with things like asynchronous script execution order (such as
Re: ES6 Loader proposed changes
On Aug 28, 2014, at 10:10 AM, Ian Hickson wrote: > Here are the changes that would be needed to make the ES6 loader > infrastructure underpin the Web platform's loader infrastructure > (basically, placing the ES6 loader the management layer between the Web > platform APIs on top, and Service Workers underneath). > ... > If we can reuse this for the rest of the Web platform, it gives authors a > really uniform API for all loading operations. The module loader isn't the right layer for the kinds of things you're trying to do. I understand you're trying to avoid having similar mechanisms at multiple layers of the platform, but repurposing the module loader system as a general purpose web resource loading system means conflating web resources and modules, which leads to a mixing of concerns exposed to the development model. Let me go into some more detail. ## What the `System` module loader is for First, let's talk about what the module loader *is* for, and what the important requirements the browser's default `System` loader should address. In particular, I'm *not* saying that there should be *no* reflection of web assets to the JS module system. ### JS module name resolution * *Basic name resolution for JS modules.* Refer to global and relative modules. * *Module naming conventions that work across JS ecosystems.* Conventions that work on both client and server, particularly with npm. Straw-examples: ```javascript import _ from "underscore"; // global module import spinner from "./spinner.js"; // relative module ``` ### HTML interop * *Making JS modules available to HTML.* Allow HTML files to import from JS. Straw-examples: ```html import $ from "jquery"; import frobify from "/scripts/frobify.js"; $(".frob").each((i, elt) => { frobify(elt); }); import $ from "jquery"; // etc. ``` * *Reflecting web assets as JS modules.* Make web assets available to JS as modules that export a DOM element. Straw-example: ```javascript import icon from "./icon.png"; console.log(icon instanceof HTMLImageElement); // true ``` ### Installing HTML/CSS components via module import * *Applying CSS via import.* Mechanism for applying stylesheets by importing them from JS. Straw-example: ```javascript import "./main.css"; // guarantees CSS is loaded and applied by the time this module executes import $ from "jquery"; $("#main").show(); ``` * *Installing HTML imports via import.* Mechanism for installing HTML imports by importing them from JS. Straw-example: ```javascript import widget from "./widget.html"; console.log(widget instanceof DocumentFragment); // true ``` ### Enriched response API * *Cross-origin fetch.* Cross-origin requests should succeed by returning and opaque response, just as ServiceWorker does, that cannot be inspected but can be returned back into the pipeline for execution. * *Streaming fetch.* It should be possible for a request to return a stream instead of a string, to allow asynchronous stream processing; this should use the API that results from the stream standardization process. ## What the `System` module loader is NOT for * *Bundling requests.* While it's attractive to use the loader for serving multiple assets in a single payload, this wants a more general solution for bundling arbitrary assets -- perhaps for performance (since despite the impending coolness of HTTP2, people will likely still use bundling as a successful optimization technique for a long time), but also for ergonomic deployment and inclusion. Jeni Tennison has done an excellent [proposal based on the link tag](https://github.com/w3ctag/packaging-on-the-web), and I've started exploring another approach based on URLs. Meanwhile people can experiment in userland with ServiceWorker-based techniques for bundling payloads. * *Repurposing the module registry to reflect caching of arbitrary browser fetches.* The registry is meant to record installation of things that are conceptually modules, not arbitrary network fetches of web assets. It's not the right place to store a cache of fetches. In particular, notice how above I said that it makes sense for modules to be able to import from, say, PNG files. In that case, the developer has explicitly requested that a web resource be reflected as a module, and it should be installed as a module. But using the registry for all web fetches means that non-JS is polluting the module registry with random modules reflecting arbitrary assets in the application. * *Forcing resource management to be reflected as modules.* The ServiceWorker API gives programmatic control over fetching of network payloads and a caching API. The module loader API gives programmatic control over fetching of modules and a caching API. What you're describing is using the latter for programmatic control over fetching and caching web assets, but that means you force them -- in the exposed API -- to be reflected as modules. * *Exposing loaded assets in a pe
Re: Understanding the 'normalize' Loader hook
On Aug 12, 2014, at 2:46 PM, Ian Hickson wrote: > On Tue, 12 Aug 2014, David Herman wrote: >> >> This is part of the design work we're actively working on. I'd ask you >> to hold off until we have some more information for you. I'll keep you >> posted -- we should have some more details for you soon. > > Where is the design work happening? I'd love to be part of it, since this > directly impacts the rest of the work I'm doing on the HTML spec right now. Right now what I've been doing is working with various stakeholders gathering requirements and constraints and beginning to sketch out what the solution space looks like. This includes people working on userland loader implementations, people in the Node community and browser development communities, people working on the JS modules design and spec, and people working on WC and HTML imports. Most of that has been in one-off discussions e.g. at the last TC39 face-to-face. I'll be filling out https://github.com/dherman/web-modules/tree/master/browser-loader with our progress. I don't want to block you and I'm happy to include you in these discussions, but there are enough stakeholders that it's not going to work to make everyone come to #whatwg at this stage. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Understanding the 'normalize' Loader hook
On Aug 12, 2014, at 2:05 PM, Ian Hickson wrote: > Assume my script is http://example.com/test.js, and assume that there is > no extra information (nobody has registered any module names or anything > like that). If I do: > > import "a"; > import "./a"; > import "/a"; > import "//example.com/a"; > import "http://example.com/a"; > > ...am I supposed to end up with the same normalized name for all five? > > How many entries in [[Modules]] should this result in? > > (I understand that the answer depends on the default loader; what I'm > asking is, what should the default loader's behaviour be.) This is part of the design work we're actively working on. I'd ask you to hold off until we have some more information for you. I'll keep you posted -- we should have some more details for you soon. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Adding out-of-band dependencies for a module
On Aug 11, 2014, at 5:06 PM, Ian Hickson wrote: > So I'm trying to figure out how to spec the HTML spec's Loader. We should coordinate -- I've been actively working on this (not the spec per se, but the design) with people engaged in the JS modules work. The HTML default loader design has some requirements that touch on existing JS ecosystems and practices, so we need to be sure we don't spec it in isolation. > One of the things that we're likely to add as part of this is a generic > dependency system. You've mentioned this to me before, but I'm afraid I haven't seen any clear rationale written up anywhere, nor a good description of what this means. One thing it might mean is a resource-fetching dependency system, meaning that for any two elements A and B that require fetching a network resource, you can state that A depends on B, meaning that whenever A's resource is fetched, B's resource should be fetched too and the system should not consider A's fetch complete until B's fetch is complete. If that's what you mean, I'm skeptical that an attribute is the right level for programmers to express this kind of resource grouping. In particular, HTTP2 and the TAG's work on package management are better approaches to grouping network resources than scattering dependency attributes across a DOM tree. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ModuleImport
On Jun 19, 2014, at 3:31 AM, Michał Gołębiowski wrote: > Thanks, Dave, for bringing that up, it shows you're open for feedback. That > said (bikeshed begins), lol :) > what's wrong with: > ```js > import "fs" as fs; > ``` Indeed we've talked about that one before. Some objected to the inconsistency of having the binding appear at the end and not having the module name at the end (all other import forms have the binding on the left and the module name at the end). But more importantly, this doesn't help with the problem of visually disambiguating from importing the default export. To put it another way, the `*` is critical in the `* as _` syntax, because it makes it explicit that we're talking about the named exports. > ? I feel that a lot of effort went in ES6 into reducing boilerplate via e.g. > arrow functions, classes etc. but if you start with Node's require, this adds > clutter. Compare these 3 forms of importing all the module "lodash" bindings > to an object _: > ```js > var _ = require("lodash"); // Node > import * as _ from "lodash"; // Dave's syntax > import "lodash" as _; > ``` My feeling is that the clutter is small, and it's acceptable to have it be slightly less minimal than default export since that is the case we are favoring. This isn't so cluttered as to be downright *punishing* multi-export utility modules (it's literally only two characters longer than your Node code, albeit admittedly a little chattier), but it's good that default import is the winner. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ModuleImport
On Jun 19, 2014, at 2:03 AM, Axel Rauschmayer wrote: > Does the proposed syntax clash with `export * FromClause` (which, I’m > assuming, re-exports everything, not just the named exports)? No inconsistency; it imports everything. Exactly the same semantics as always, just a change in surface syntax. Remember that the module instance object contains all named exports, but the default export is simply an export with the name `default`. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
ModuleImport
Thanks to everyone for working through the issues around ModuleImport. I know it's been frustrating, but the discussions have really helped clarify the key constraints. ## Constraints First, let me restate the most important arguments. In favor of removal: * **The syntactic distinction between ModuleImport and default import is vague.** We've consistently seen confusion between the semantics of ModuleImport and default export. While certainly some of the confusion might be chalked up to misinformation and lack of documentation, we've seen people be confused by this even when correctly explained the semantics. The problem with the syntax is that the only visual distinction is the initial keyword (`module` vs `import`), and it's not clear from that keyword which concept you're talking about. (Once you've internalized the structure of module instance objects, you get a hint from the `module` keyword, but that doesn't help people who are just learning the system, particularly if they're already familiar with other JS module systems.) Against removal: * **Without ModuleImport, authors of multi-export modules would be pressured to circumvent the named exports functionality.** Without ModuleImport, clients of multi-export modules have two options. Either they use named import: ```js import { readFile, writeFile } from "fs"; ``` or if they want to explicitly namespace those functions, they have to use the dynamic API: ```js import "fs"; // state the dependency var fs = this.get("fs"); ``` That's inconvenient, confusing, and makes you feel like you're stepping outside the normal usage patterns intended for the system. Since this is a choice forced on the clients of a module, the module author will feel pressure to circumvent the named export feature altogether and instead export a default object with all the properties. This is bad -- it creates pressure for people to abandon part of the module system. ## Conclusion Here's the conclusion I've come to based on all of the above. * **We need a form like ModuleImport.** As many have said, clients of named-export modules need the freedom to choose whether to explicitly namespace those imports, and they need a syntax that doesn't feel like they've stepped outside the normal system. * **The current syntax of ModuleImport is wrong.** The confusion reported in developer feedback is real, and it's important. * **The syntax should still favor default import.** ES6 favors the single/default export style, and gives the sweetest syntax to importing the default. Importing named exports can and even should be slightly less concise. * **A better ModuleImport syntax is possible, and we should settle it soon.** I'll propose a better ModuleImport syntax below. Syntax being syntax, everyone will of course unsheathe their bikeshed paintbrush. That's OK. The champions will keep it from going on unbounded and help settle the debate, and we'll make sure to capture the conclusion in the next TC39 meeting. I do acknowledge the concerns about reopening topics for debate and delay. But given the usability feedback, I think this case is worth fixing. We should resolve it for ES6, perhaps in part because it's less editorial work to change the ModuleImport production than to defer it, but more because I don't want to delay the resolution so that implementations can ship the better syntax. But keep in mind it doesn't matter what spec it lands in as long as implementations are shipping it. We're still in the early days of transpiler implementations, and there are no native implementations of modules yet. So there's time, as long as we don't let the bikeshed go on forever. So let's get to it! ## Proposal OK, so we're talking about a better syntax for importing a module and binding its named exports to a variable (as distinct from importing a module and binding its default export to a variable). Here's my proposal: ```js import * as fs from "fs"; // importing the named exports as an object import Dict from "dict"; // importing a default export, same as ever ``` Why is this better? Because it dovetails with the named export syntax, **which makes it clear that it's binding `fs` to the named exports.** It saves the reader from having to know that the module instance object is not the same thing as the default export. So there you have it... Feedback welcome, and as always we'll collect it all, weigh it, and try to shepherd consensus. Oh, and just to put parameters on the discussion: * **I'm not proposing additional new import forms.** If this syntax is future-compatible with other possible syntactic forms, that's great, but that's not what we're discussing. * **I'm not interested in discussing changes to the rest of the module syntax.** This isn't the time or place to redesign the whole system. * **The `this` binding in modules is a separate topic.** The `this` binding in modules can be discussed independently of this topic. tl;dr
Re: @@new
Your proposal is appealing but I haven't convinced myself it works. There are a couple bits I haven't quite grokked. > The special `constructor` method in ClassDeclaration/ClassExpression syntax > would desugar to a static @@new method. This class: > >class Point { >constructor(x = 0, y = 0) { >this.x = x; >this.y = y; >} >} > > would amount to this: > >class Point { >static [Symbol.new](x = 0, y = 0) { >var obj = super[Symbol.new](); >obj.x = x; >obj.y = y; >return obj; >} >} You're inlining the method body into the @@new body, but I want to make sure I understand what the specification of the Point function itself would be. You've said Point !== Point[@@new] but calling Point(...args) should behave the same as new Point(...args). So then would the specification of the Point function's behavior just be to delegate to Point[@@new](...args)? > The "super Arguments" call syntax in the ES6 drafts would be constrained to > appear only at the top of a constructor, as in Java: This part is what I'm the most unclear about. What invariant are you trying to maintain? It seems like you're using this to attempt to guarantee that all superclasses have had the chance to initialize their internal fields before user code starts running, so that built-in classes can have consistent internal representations and not have to worry about guarding against reading from uninitialized internal slots. But this is a tricky invariant to guarantee. First of all I think you'd have to put syntactic restrictions in place to disallow referring to `this` in the super call, to avoid e.g.: class Sneaky extends Date { constructor(x) { super((console.log(this.valueOf()), x)); } } But that's not enough, because you also have to worry about the superclass constructors calling overloaded methods: class Dupe extends Date { constructor(x) { super(x); initDupe(); } initDupe() { ... } } class Sneaky extends Dupe { constructor(x) { super(x); } initDupe() { console.log(this.valueOf()); super.initDupe(); } } (These are common pitfalls in languages that try to provide hard guarantees about field initialization. They come up, for example, in typed OO languages that try to provide guaranteed non-nullable fields.) But maybe I'm misunderstanding what invariant you're aiming at? > * Base class constructors are always called. Are you saying you would not only restrict the super call to the top, but require one to always be there? Or would an absence of a super call imply an implicit `super()`? > * These productions would be dropped from the ES6 grammar: > >MemberExpression : new super Arguments >NewExpression : new super Clearly with your design `super[Symbol.new](...args)` is equivalent to `new super`. Is it also emulate-able in the @@create semantics also? If so it seems like the question of whether to keep or drop the `new super` syntax is 100% orthogonal to your proposal. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: exposing system time zone
On Jun 17, 2014, at 5:31 PM, Domenic Denicola wrote: >> Interesting questions in that thread about what to do about time zone >> changes. An event for time zone changes seems important, but we don't >> currently have any precedent for standard library events in ECMAScript. > > Object.observe change records? A synthetic change event seems perfect for > this use case. I knew someone would suggest that. :) Personally, I think that's pretty gross: it's encoding a real-world event (e.g. I moved into a different time zone) as a reflective object mutation event, rather than just building an API at a more intuitive level of abstraction. But I suppose if it works without having to actually standardize anything, then it just works. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
exposing system time zone
This was brought up on specifiction: http://discourse.specifiction.org/t/navigator-timezone/152 Does anyone know why it was left out of the first version of the Intl API? Just for lack of time? Is it planned for the next edition? Are there tricky issues around standardizing IANA time zones, or around incompatibilities between different OSes? Interesting questions in that thread about what to do about time zone changes. An event for time zone changes seems important, but we don't currently have any precedent for standard library events in ECMAScript. Maybe that remains the purview of web APIs. But if we do expose the TZ via a standard API, it should have some way of dynamically querying the current TZ rather than just fixing the time zone at some random point in time. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: April 10 2014 Meeting Notes
On Apr 25, 2014, at 9:10 AM, Allen Wirfs-Brock wrote: > People will write code like this if we allow it. But we don't have to allow. > We can preserve the semantics of try-finally by simply making the occurrence > of the 'yield' operator syntactically illegal within the try block of a > try-finally. > > We could do this. The parameterized grammar notation we now use in the ES6 > spec. makes it fairly easy to specify that you can't write code like the > above. > > Should we do it? I'm not sure. I still think that @@return is a reasonable > but imperfect alternative that allows generator authors to continue to use > what many think is a useful feature. Outlawing 'yield' in a try-finally is a > almost perfect solution to the semantic impedance mismatch between > try-finally and generators. But we also loose some expressiveness. Promised you a reply to this one, sorry -- I'm not comfortable with this restriction. It violates my Schemer's intuition [1]. In particular it creates a number of refactoring hazards: (1) add some try/finally code around code to deal with something other than the yield it contains; (2) refactor some try/finally code outside of a generator into a generator. Here's my perspective: - Iterators should generally be short-lived. - We should optimize the language design around ensuring that they will generally be exhausted. - In most use cases users won't even touch an iterator directly; it'll just be created and passed directly into the for-of loop (or a combinator, which itself will often be implemented with a generator function that consumes the wrapped iterator in a for-of loop). - The fact that iterators are first-class objects means it's *possible* to prevent an iterator from being terminated, but termination is never an absolute guarantee in Turing-complete languages to begin with. So the design I favor is: - Generators always have a .return() method. - All three of .next, .throw, and .return should take an optional argument. - All three of .next, .throw, and .return should return an iteration record ({ value: any, done: boolean }). - The semantics of for-of (as well as any combinators we specify post-ES6) should call .return() on the underlying iterator iff there's an abrupt completion. If the iterator terminates itself the loop should not force a .return() -- this isn't just a performance compromise, it avoids calling .return() on a closed generator. - If the implicit .return() of a for-of loop produces done: false, that indicates the iterator refused to be terminated, and the for-of loop should throw an exception. (This exception should throw from outside the loop, so no catch blocks inside the loop should catch it.) Dave [1] "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary." ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Iterators, generators, finally, and scarce resources (Was: April 10 2014 Meeting Notes)
On Apr 29, 2014, at 12:17 PM, Domenic Denicola wrote: > Anyway, regardless of the specifics of my `using` proposal, I hope that > highlighting the iterability vs. disposability aspects of this conversation > was helpful to people. I do think it's helpful for understanding the space, thanks. But here's why I don't think it ultimately helps: we are going to need combinators for iterators, and they are going to have to make the same decision. We aren't going to have e.g. map and mapDispose. I still contend that the common case is that iterators are short-lived, and the language should safely ensure they are disposed of. So the combinators should ensure that their underlying iterator is disposed of, and for-of should behave consistently with the combinators. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Destructuring and evaluation order
On Apr 25, 2014, at 10:42 AM, Allen Wirfs-Brock wrote: > Nope, it's always been designed this, going back to the original wiki > strawman > http://wiki.ecmascript.org/doku.php?id=harmony:destructuring#semantics and I > assume the original FF implementation. > > It has also been something that we has been discussed here and in TC39 > multiple times. If we wan to revisit this decision we really need to dredge > up all of those previous discussions to see if there is new data that would > cause us to change this decision. > > Basically for destructing assignment, each property element can be an > arbitrary assignment expression and all of their Reference values would have > to be saved to get left to right order. FWIW (not much probably) I've always agreed with what Andreas and Ollie are saying here, but I don't have the time or energy to do the dredging. :) Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Iterators, generators, finally, and scarce resources (Was: April 10 2014 Meeting Notes)
On Apr 29, 2014, at 12:40 AM, Andy Wingo wrote: > I'm a bit grumpy that this is being brought up again, and > this late, and in multiple forums, but as it seems that people want to > talk about it again, that talking about it again is the thing to do... Sorry about that. :( But the fact is Jafar joined TC39 very late and his technical points have merit, so we do have to grapple with them. (As for multiple forums, I wish I had a solution.) > If I may summarize Jafar's argument, it's that the iterator in a for-of > may hold a scarce resource, like a file descriptor, and because of that, > for-of should be able to release this scarce resource on an early exit > via "break". The provisional consensus elaborates a method to do this. > > Is this a fair summary? I don't quite agree with that summary. These are IMO the most important points: - Iterators might include "on cleanup" logic, although this is admittedly rare in synchronous code. - Nevertheless, generators are the common implementation strategy for iterators, and try/finally is a part of the language, making "on cleanup" logic more likely to arise. While we can't ever guarantee that code won't run a first-class iterator object to its completion (just like you can't guarantee that a try block won't iloop), it's a bad smell if code that creates an iterator in a for-of loop head, loops over it, and *never even touches the iterator directly* doesn't shut down the iterator. - Iterators are intended to be short-lived (in particular, long-lived iterators over mutable data sources are invalidation hazards). So the common consumer of iterators, for-of, should properly dispose of them. - The uncommon case of using an iterator partially and in several loops can be easily implemented with combinators (or while loops), but we should be safe by default. - The problems of "on cleanup" logic will be greatly exacerbated with future asynchronous iteration features, which are IMO an extremely high priority for the future. The overwhelming majority of JS programs that operate on sequences of data are doing so asynchronously. The moment we start going down the road of designing asynchronous iteration features (such as `for (await ... of ...)`), which in fact Jafar and I have been starting work on, the try/finally hazards will show up much more often. If we don't do proper disposal of synchronous iterators, we'll create an asymmetry between synchronous and asynchronous iteration, which would not only be a nasty wart but also a refactoring hazard. > Indeed I expect that in > practice most iterators in an ES6 program will be map, set, and array > iterators, which in practice will not be implemented with generators. I strongly disagree with this. Generators will by far be the most convenient and common way to implement iterators, regardless of their data source. > Incidentally I think that if TC39 decided to re-add this method, it > should be called close() instead, because it doesn't make sense to > "return" from a non-generator iterator. I thought so at first too, until I remembered that iterators have a return value. So I still think return is the right name. > == Calling return() on iterators is rarely appropriate You're arguing "rarely necessary," not "rarely appropriate," which is a weaker claim. But I dispute that too because of asynchronous iteration, as I explained above. > However in this case it is possible to arrange to close the iterator, > with a different interface: This is a *dramatic* weakening of the power of iterators, in that you force *all* iteration abstractions to expose their external resources to consumers. Again, it may not seem like a big deal now but it'll be completely unacceptable for the asynchronous case. > The other case is when you have an iterator consumer which is decoupled > from the code that created the iterator, as in: > > function (iterable) { >... >for (var x of iterable) { > if foo(x) break; >} >... > } > > But it is precisely in this case when you would *not* want to close the > iterator, because you don't know its lifetime. As I said above, we should not optimize the design for this case. It's easy enough to create combinators for it: function (iterable) { ... for (var x of keepalive(iterable)) { if foo(x) break; } ... } But this will not be the common case. The majority of the time when you're working with sequences you use the data you need and then you're done with it. > == return() in generators is semantically weird It's not as weird as you make it out to be. Return is not much different from throw, first of all. Note also that ES7 do-expressions allow expressions to return. > Also, the insistence on a return() that doesn't run catch blocks seems > to me to be ill-placed. I think it's telling that the counter-examples > are from Python, which has a different semantic model, as it has > finalization. Implementing abstrac
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 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
On Mar 14, 2014, at 10:50 AM, Russell Leggett 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: module exports
On Mar 14, 2014, at 9:37 AM, Andrea Giammarchi 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 9:27 AM, John Barton 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: Detecting a Module object
OK, we can discuss and report back. We'll definitely want to take into account Guy's use case about being able to recognize module instance objects as such. Dave On Feb 21, 2014, at 12:53 PM, Allen Wirfs-Brock wrote: > > On Feb 21, 2014, at 12:08 PM, David Herman wrote: > >> I think it should be Module.isModule. > > I don't think we actually need something named Module, but that's a separate > conversation I have in the queue to have with you. > > But food for thought: for module loader reflection purposes, it would be > better for use a mirror-like object rather than the actual magic module > objects. > > allen > > > > > >> >> Dave >> >> On Feb 21, 2014, at 10:57 AM, Allen Wirfs-Brock >> wrote: >> >>> it's not going to be instanceof for various technical reasons. >>> >>> I suspect, we can have a isModule predicate function somewhere. Perhaps, >>> Reflect.isModule or Reflect.Loader.isModule... >>> >>> Allen >>> >>> >>> On Feb 21, 2014, at 3:53 AM, Guy Bedford wrote: >>> >>>> Being able to do `m instanceof Module` is certainly a lot nicer here >>>> though. >>>> >>>> Just to return to the consideration of modules as classes, I still don't >>>> understand what the major issue is with having a module as a class without >>>> any prototype methods. >>>> >>>> >>>> On 21 February 2014 00:07, Guy Bedford wrote: >>>> Thanks John for explaining. As for the usefulness of this path as I say it >>>> is yet to be determined. >>>> >>>> Specifically the ability to detect a module instance is needed to allow >>>> ES6 loaders to load AMD that was transpiled from ES6 into AMD. >>>> >>>> It may be a little bit of an obscure use case, the exact details of the >>>> use case are described in this gist - >>>> https://gist.github.com/guybedford/5622c9ed5c9ad4bc0417. >>>> >>>> The key point being raised here is that there is a scenario in which >>>> detecting a module instance is useful. >>>> >>>> >>>> On 20 February 2014 23:45, John Barton wrote: >>>> >>>> >>>> >>>> On Thu, Feb 20, 2014 at 1:01 PM, Allen Wirfs-Brock >>>> wrote: >>>> >>>> On Feb 20, 2014, at 12:53 PM, Guy Bedford wrote: >>>> >>>>> Thanks, if there is some way to detect this it may well be useful. >>>>> >>>>> The use case I came across it was trying to allow ES6 modules to be >>>>> transpiled into AMD for use in an ES6 loader. I'm still not sure how >>>>> necessary the use case is, but it definitely would need this >>>>> functionality work. >>>> >>>> The Es6 module loader design has specific hooks to support importing from >>>> foreign module systems. However, I'll leave it to Dave or Sam to explain >>>> how to use them... >>>> >>>> Guy is trying to support an important path for JS developers to get to ES6 >>>> and adopt ES module loading: allow developers to mix ES6 and AMD modules. >>>> He already supports loading AMD via ES6-loader. Now he wants to allow >>>> that AMD code to depend upon ES6 modules. This allows AMD teams to >>>> transition smoothly to ES6. He needs something like: >>>> define(['a', 'b'], function(a, b) { >>>> if (!(a instanceof Module)) a = { default: a } >>>> if (!(b instanceof Module)) b = { default: b } >>>> >>>> so his generated AMD code can accept ES6 modules. >>>> >>>> HTH, >>>> jjb >>>> >>>> >>> >>> ___ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >> >> > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting a Module object
no, it's in Reflect Dave On Feb 21, 2014, at 12:13 PM, Domenic Denicola wrote: > Is Module a global now? > > From: es-discuss on behalf of David Herman > > Sent: Friday, February 21, 2014 15:08 > To: Allen Wirfs-Brock > Cc: es-discuss > Subject: Re: Detecting a Module object > > I think it should be Module.isModule. > > Dave > > On Feb 21, 2014, at 10:57 AM, Allen Wirfs-Brock wrote: > >> it's not going to be instanceof for various technical reasons. >> >> I suspect, we can have a isModule predicate function somewhere. Perhaps, >> Reflect.isModule or Reflect.Loader.isModule... >> >> Allen >> >> >> On Feb 21, 2014, at 3:53 AM, Guy Bedford wrote: >> >>> Being able to do `m instanceof Module` is certainly a lot nicer here though. >>> >>> Just to return to the consideration of modules as classes, I still don't >>> understand what the major issue is with having a module as a class without >>> any prototype methods. >>> >>> >>> On 21 February 2014 00:07, Guy Bedford wrote: >>> Thanks John for explaining. As for the usefulness of this path as I say it >>> is yet to be determined. >>> >>> Specifically the ability to detect a module instance is needed to allow ES6 >>> loaders to load AMD that was transpiled from ES6 into AMD. >>> >>> It may be a little bit of an obscure use case, the exact details of the use >>> case are described in this gist - >>> https://gist.github.com/guybedford/5622c9ed5c9ad4bc0417. >>> >>> The key point being raised here is that there is a scenario in which >>> detecting a module instance is useful. >>> >>> >>> On 20 February 2014 23:45, John Barton wrote: >>> >>> >>> >>> On Thu, Feb 20, 2014 at 1:01 PM, Allen Wirfs-Brock >>> wrote: >>> >>> On Feb 20, 2014, at 12:53 PM, Guy Bedford wrote: >>> >>>> Thanks, if there is some way to detect this it may well be useful. >>>> >>>> The use case I came across it was trying to allow ES6 modules to be >>>> transpiled into AMD for use in an ES6 loader. I'm still not sure how >>>> necessary the use case is, but it definitely would need this functionality >>>> work. >>> >>> The Es6 module loader design has specific hooks to support importing from >>> foreign module systems. However, I'll leave it to Dave or Sam to explain >>> how to use them... >>> >>> Guy is trying to support an important path for JS developers to get to ES6 >>> and adopt ES module loading: allow developers to mix ES6 and AMD modules. >>> He already supports loading AMD via ES6-loader. Now he wants to allow that >>> AMD code to depend upon ES6 modules. This allows AMD teams to transition >>> smoothly to ES6. He needs something like: >>> define(['a', 'b'], function(a, b) { >>> if (!(a instanceof Module)) a = { default: a } >>> if (!(b instanceof Module)) b = { default: b } >>> >>> so his generated AMD code can accept ES6 modules. >>> >>> HTH, >>> jjb >>> >>> >> >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Detecting a Module object
I think it should be Module.isModule. Dave On Feb 21, 2014, at 10:57 AM, Allen Wirfs-Brock wrote: > it's not going to be instanceof for various technical reasons. > > I suspect, we can have a isModule predicate function somewhere. Perhaps, > Reflect.isModule or Reflect.Loader.isModule... > > Allen > > > On Feb 21, 2014, at 3:53 AM, Guy Bedford wrote: > >> Being able to do `m instanceof Module` is certainly a lot nicer here though. >> >> Just to return to the consideration of modules as classes, I still don't >> understand what the major issue is with having a module as a class without >> any prototype methods. >> >> >> On 21 February 2014 00:07, Guy Bedford wrote: >> Thanks John for explaining. As for the usefulness of this path as I say it >> is yet to be determined. >> >> Specifically the ability to detect a module instance is needed to allow ES6 >> loaders to load AMD that was transpiled from ES6 into AMD. >> >> It may be a little bit of an obscure use case, the exact details of the use >> case are described in this gist - >> https://gist.github.com/guybedford/5622c9ed5c9ad4bc0417. >> >> The key point being raised here is that there is a scenario in which >> detecting a module instance is useful. >> >> >> On 20 February 2014 23:45, John Barton wrote: >> >> >> >> On Thu, Feb 20, 2014 at 1:01 PM, Allen Wirfs-Brock >> wrote: >> >> On Feb 20, 2014, at 12:53 PM, Guy Bedford wrote: >> >> > Thanks, if there is some way to detect this it may well be useful. >> > >> > The use case I came across it was trying to allow ES6 modules to be >> > transpiled into AMD for use in an ES6 loader. I'm still not sure how >> > necessary the use case is, but it definitely would need this functionality >> > work. >> >> The Es6 module loader design has specific hooks to support importing from >> foreign module systems. However, I'll leave it to Dave or Sam to explain >> how to use them... >> >> Guy is trying to support an important path for JS developers to get to ES6 >> and adopt ES module loading: allow developers to mix ES6 and AMD modules. >> He already supports loading AMD via ES6-loader. Now he wants to allow that >> AMD code to depend upon ES6 modules. This allows AMD teams to transition >> smoothly to ES6. He needs something like: >> define(['a', 'b'], function(a, b) { >> if (!(a instanceof Module)) a = { default: a } >> if (!(b instanceof Module)) b = { default: b } >> >> so his generated AMD code can accept ES6 modules. >> >> HTH, >> jjb >> >> > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: System.import FTW
On Feb 14, 2014, at 12:09 PM, John Barton wrote: > (There is no spec on "System", just rumors that it will be a predefined, > global instance of Loader). "Rumors" is a bit much. :) The notes do show the discussion but the resolution for some reason didn't get recorded. IIRC there was agreement that Reflect and System will both be globals (this has also been the general understanding for a long time, so it's nothing new). https://github.com/rwaldron/tc39-notes/blob/9ac398908394f9e2f8a1ac9b1e0c83952cd2f2fa/es6/2014-01/jan-28.md#spec-status-update Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: System.import FTW
On Feb 14, 2014, at 12:32 PM, C. Scott Ananian wrote: > john: yes, I suspected that System was underspecified. That's too bad. It's a separation of responsibilities. `System` is the point where the ECMAScript language (core module system) meets the host environment (filesystem/web browsers/etc). We are working towards a separate spec for the behavior of the browser's `System` binding, which will be a web spec, not a part of the ECMAScript spec. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The case for modular Loader.
On Feb 10, 2014, at 8:55 AM, John Barton wrote: > Indeed, however, this herring is only red on one fin: the mutability of > System is not limited to the registry and in fact every aspect of the System > is mutable. As far as I can tell, a mutation to say normalize or locate is > entirely unpredictable without runtime tracing. Unless I am wrong about > this, we should not ignore this herring just because of a small botch of red. OK, I see what you're saying. I'm just not as concerned because configuring the loader is not something everyone should be doing. It's effectively application-wide configuration. > Did we give up on
Re: The case for modular Loader.
On Feb 7, 2014, at 8:06 AM, John Barton wrote: > The first goal listed for ecmascript modules: > • Obviate need for globals > (http://wiki.ecmascript.org/doku.php?id=harmony:modules). > Ironically, the current proposal for module loading includes a global > "System" and possibly "Loader". Sorry the goal was unclear. It didn't mean we should never add globals to JS, it meant we should make it so programmers don't need to use globals as a mechanism for code sharing. That doesn't mean there's never any point to adding globals. Even in languages that are born with a module system from day one, they tend to have a standard prelude of globals that are common enough that it would be anti-usable to force programmers to explicit import them. > Worse, it seems like the global System is explicitly expected to be mutated. This is a red herring; a registry is inherently a shared mutable table, whether you make it accessible via a global variable or via a (globally accessible) module. > Just in case the not-global is goal is controversial, consider the following > code snippets: > > 1. Using Globals: >System.import('./myGreatModule'); > 2. Using Modules: >import System from './MyCustomLoader'; >System.import('./myGreatModule'); This isn't a viable option. The module system needs to be accessible from script code (e.g. HTML element attributes), which can't syntactically import. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: multiple modules with the same name
On Jan 27, 2014, at 2:18 PM, Marius Gundersen wrote: > So then there would be two versions of the same module, and a module could > get access to both these modules at the same time. For example, if ModuleB, > which depends on ModuleA is loaded and linked, and later ModuleA is > redefined, then ModuleC could depend on both ModuleB and ModueA, and would > get (indirect) access to two versions of ModuleA. Is this problem preventable? It's important to be able to modify module registration for things like polyfilling. But that doesn't mean it's something people should do in general. Note that Jason only gave you an answer in the context of the basic module loader semantics; he didn't say what will happen in the HTML semantics. In particular, we can make it an error for there to be two definitions of the same module name in the same HTML, a la: I'm inclined to call that an error, and require imperative modifications of existing module registrations to use imperative code. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Generator returning a value should throw SyntaxError
Here are several ways to think about return: - A generator function is like a normal function but it can be paused. The act of pausing can send an intermediate value out to the caller (yield's argument) and the caller can send an intermediate value back in when resuming (yield's result). None of this changes the fact that, like ordinary functions, there are still arguments passed into the function and a result passed out. Refusing return values just breaks down this generalization. - A generator function produces an iterator object, which produces a record on each iteration that has a .value and a .done flag indicating whether the iteration is done. Refusing return values eliminates the .value field in this special case, making things less consistent. Finally, task.js is just an example of building a control abstraction out of iterators. It happens that the for-of control flow form is imperative and doesn't have a use for a return value. That doesn't mean other control flow operations won't. Dave On Jan 27, 2014, at 2:18 PM, Adam Ahmed wrote: > In light of the recent thread discussing async and await keywords, I thought > it'd be appropriate to raise this point again, understanding it may be too > late to make a change. > > As my original post details, the concept of `return` within a generator is > surprising in its difference in behavior from `yield`. > > This does not do as 'expected' in a for-in: > > function * threeCount() { > yield 1; > yield 2; > return 3; > } > > The argument for allowing return values was that usages in the vein of > task.js will use the return value as a real return value and the yields for > scheduling. > > If we' re going to have async and await serve the scheduling purpose as well, > can we remove the 'return' foot gun from generators? It sounds like it's just > a stopgap until async-await, and a painful one, IMO. A syntax error on a > generator that returns values would make the scheduling (async-await) vs > iteration (generator) use cases much more clear. It'll be much easier for new > JS devs to understand generators. > > Happy to be shutdown again, just thought it was worth reconsidering with new > async-await keywords in play. > > On 27/09/2013 3:46 PM, "Brandon Benvie" wrote: > On 9/26/2013 10:40 PM, Brandon Benvie wrote: > ```js > function* foo() { > yield 'what'; > yield 'ever'; > return "DONE"; > } > > function* bar() { > console.log(yield* foo()); > } > ``` > > Err, this logs "DONE" when you do: > > ```js > var gen = bar(); > gen.next(); > gen.next(); > gen.next(); > ``` > but you got the idea... > ___ > 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: detecting JS language mode for tools
[Resending, not sure why it's not getting through to the list...] On Jan 27, 2014, at 10:41 AM, David Herman wrote: > On Jan 27, 2014, at 2:07 AM, David Bruant wrote: > >> Indeed. I'm wondering why we need inline for modules. > > Because people write inline scripts all the time. It's unacceptably > inconvenient not to be able to bootstrap your app with inline code. It also > allows you to control for when the scripts resource is there, in particular > to be sure that necessary bootstrapping/kernel code has loaded before you > need to do some wiring up of your app. > > But it's not even worth overthinking. It's so obviously, obscenely > anti-usable not to be able to write > ><script module> >import $ from "jquery"; >import go from "myapp"; >$(go); > > > inline that I'm surprised this is even a discussion. > > Dave > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: detecting JS language mode for tools
On Jan 27, 2014, at 2:07 AM, David Bruant wrote: > Indeed. I'm wondering why we need inline for modules. Because people write inline scripts all the time. It's unacceptably inconvenient not to be able to bootstrap your app with inline code. It also allows you to control for when the scripts resource is there, in particular to be sure that necessary bootstrapping/kernel code has loaded before you need to do some wiring up of your app. But it's not even worth overthinking. It's so obviously, obscenely anti-usable not to be able to write