Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Top Level Await #25988

Closed
2 of 4 tasks
kitsonk opened this issue Jul 26, 2018 · 16 comments · Fixed by #35813
Closed
2 of 4 tasks

Top Level Await #25988

kitsonk opened this issue Jul 26, 2018 · 16 comments · Fixed by #35813
Assignees
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Fixed A PR has been merged for this issue Suggestion An idea for TypeScript Update Docs on Next Release Indicates that this PR affects docs

Comments

@kitsonk
Copy link
Contributor

kitsonk commented Jul 26, 2018

Search Terms

top level await

Suggestion

The ability to utilise await directly at the top level of a module or a script. Currently the compiler does not support this, though it is becoming increasing possible to accomplish it in certain runtimes.

Top level await is currently a Stage 2 TC39 proposal. (I was unable to find any tracking issue for implementation, therefore this issue)

There was this issue #20923, which was marked as a question, but really was this feature request.

Use Cases

There are many patterns the are emerging that require top level await, many which are documented in the TC39 Proposal. The current workaround that is seen a lot in the wild is wrapping an async iife. There are lots instances where the main thread of program wants to utilise await to load resources.

The value of having top level await in Node.js REPL and Chrome debugger is now allowed. There is an outstanding issue to allow it in ts-node.

I know the core team is really really adverse to implementing things that haven't reached Stage 3, but there are sufficient patterns in the wild that allow this and an increasing number for situations where it can be allowed, that allowing it under a flag feels like something that might be entertained until it is delivered under Stage 4. If we in user-land choose the potential 👣 🔫 at our own risk, so be it.

Examples

The following:

async function main() {
  const dynamic = await import('./dynamic-thing.mjs');
  const data = await fetch(dynamic.url);
  console.log(data);
}
main();

Could be rewritten as:

const dynamic = await import('./dynamic-thing');
const data = await fetch(dynamic.url);
console.log(data);

Checklist

Technically, this would allow syntax which would change the runtime behaviour of JavaScript and allows new expression level syntax which is currently not permitted (but specifically reserved by TC39 for this purpose).

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)
@weswigham
Copy link
Member

@kitsonk I don't think we can safely implement TLA until at least the variant is decided upon - otherwise how exports work in modules with TLA is liable to change (and thereby typechecking). I get that it's great in a REPL context - but at the top level of a module with exports it is much less straightforward!

@kitsonk
Copy link
Contributor Author

kitsonk commented Jul 26, 2018

I understand that it is likely more complicated than just allowing it, because variant A or variant B would have significant impacts on CFA. From a usefulness perspective, the proposed optional constraint of only allowing it in modules without exports would be sufficient for my selfish needs. While there still might be an impact on CFA, the static analysis could/would work as it does now for not top level awaiting and it would be guaranteed to know what the shape of the exports (because it has none). I suspect that restriction would work for most other real world use cases at the moment (and if it didn't there would be good justification of why TypeScript can't know).

@weswigham is it worth at least having a tracking issue at this stage of the proposal?

@mhegazy mhegazy added ES Next New featurers for ECMAScript (a.k.a. ESNext) Suggestion An idea for TypeScript labels Jul 26, 2018
@RyanCavanaugh RyanCavanaugh added the Waiting for TC39 Unactionable until TC39 reaches some conclusion label Aug 13, 2018
@sebmck
Copy link

sebmck commented Mar 9, 2019

Has there been an movement on this issue? @RyanCavanaugh, I see you added the "Waiting for TC39" label. What are you waiting on? The advancement to stage 3? The compromise listed above by @kitsonk seems like a good one that would solve the vast majority of use-cases without an impact on type checking semantics.

@RyanCavanaugh
Copy link
Member

We're waiting on stage 3 or 4 since there are possible runtime semantics implications.

"This so reasonable that surely TC39 won't come up with some other behavior" has bitten us enough that we're not really willing to risk it when it comes to runtime behavior.

@kitsonk
Copy link
Contributor Author

kitsonk commented Jun 6, 2019

The proposal has gone Stage 3.

@jhpratt
Copy link

jhpratt commented Jul 28, 2019

@RyanCavanaugh Any plans for implementation?

@weswigham
Copy link
Member

We can probably put the parsing and typechecking behavior into the backlog at some point, but be aware that ultimately the way TLA executes comes down to the module loader. Webpack can enable it pretty easily by modifying the bundled module loader (although probably not quite to spec, since implementation to spec requires inspecting promise internals to skip event loop turns), but in the context of the cjs loader or pre-TLA esm loader (as we usually consider we emit for), there's really no way to downlevel TLA (although I think amd modules might just support it out of the box, which could be nice). It's just not downlevelable without whole program rewriting, and even then exactly implementing the spec is almost impossible (technically not completely impossible with the inclusion of a native node module to synchronously unwrap a resolved promise) because of the event loop turn behaviors.

We can probably at least tag this as Needs Proposal - minimally we could probably support it when targeting esnext with no downlevel, like import.meta.

@kitsonk
Copy link
Contributor Author

kitsonk commented Jul 28, 2019

Allowing it through, with no downlevel emit would be perfect for my use case. Treating it like import.meta makes sense. It needs to be adopted somehow.

@robpalme
Copy link

robpalme commented Aug 1, 2019

I agree with @kitsonk - there are use-cases today that would benefit from parsing and type-checking without any downlevel with esnext target.

@RyanCavanaugh RyanCavanaugh added Committed The team has roadmapped this issue and removed Waiting for TC39 Unactionable until TC39 reaches some conclusion labels Aug 2, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.7.0 milestone Aug 2, 2019
@orta orta added the Update Docs on Next Release Indicates that this PR affects docs label Sep 11, 2019
@Kingwl
Copy link
Contributor

Kingwl commented Sep 17, 2019

The part of lexer and parser seems nearly be done... Is there any progress branch or tracking on this one?

@shand-obs
Copy link

shand-obs commented Oct 5, 2019

Is this in typescript@next (dev20191004)?

It seems like TLA works when I have "target": "esnext" (emits await at top level). It does not work when I have "target": "es5" even though I have "module": "esnext". Is this going to emit TLA downlevel? If it's not, it isn't going to be very useful with webpack 5. Unless I'm missing something.

I can ignore the error with // @ts-ignore but it emits "yield" instead of "await".

@CyrusNajmabadi
Copy link
Contributor

@RyanCavanaugh @DanielRosenwasser this mentioned Milestone 3.7. Is this actually available to use in the latest TS builds? If so, is there something i need to do to enable this? Thanks!

@kitsonk
Copy link
Contributor Author

kitsonk commented Oct 13, 2019

I spoke to Daniel at TSConf. He said it wasn't going to make 3.7 and he needed to update the IP.

@hayd
Copy link

hayd commented Oct 13, 2019

Related: accounting for top-level for-await tc39/proposal-top-level-await#133

@stevefan1999-personal
Copy link

https://gist.github.com/Rich-Harris/0b6f317657f5167663b493c722647221

@CyrusNajmabadi
Copy link
Contributor

@stevefan1999-personal

Therefore, a version of TLA that solves the original issue is a valuable addition to the language, and I'm in full support of the current proposal, which you can read here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Fixed A PR has been merged for this issue Suggestion An idea for TypeScript Update Docs on Next Release Indicates that this PR affects docs
Projects
None yet
Development

Successfully merging a pull request may close this issue.