GeezerVison is showing github.com — Async Iteration and down-level Generators by rbuckton · Pull Request #12346 · microsoft/TypeScript
Conversation
This PR adds full support for Async Generators and Async Iteration (for..await..of) as per the current TC39 Proposal for all script targets. It also contains full support for Generators in ES5/3, including for..of, spread, and iterator destructuring.
Iterators
ES6 introduced Iterator, which is an object that exposes three methods, next, return, and throw, as per the following interface:
interface Iterator<T> {
next(value?: any): IteratorResult<T>;
return?(value?: any): IteratorResult<T>;
throw?(e?: any): IteratorResult<T>;
}
This kind of iterator is useful for iterating over synchronously available values, such as the elements of an Array or the keys of a Map. An object that supports iteration is said to be "iterable" if it has a Symbol.iterator method that returns an Iterator object.
Async Iterators
The Async Iteration proposal introduces an AsyncIterator, which is similar to Iterator. The difference lies in the fact that the next, return, and throw methods of an AsyncIterator return a Promise for the iteration result, rather than the result itself. This allows the caller to enlist in an asynchronous notification for the time at which the AsyncIterator has advanced to the point of yielding a value. An AsyncIterator has the following shape:
interface AsyncIterator<T> {
next(value?: any): Promise<IteratorResult<T>>;
return?(value?: any): Promise<IteratorResult<T>>;
throw?(e?: any): Promise<IteratorResult<T>>;
}
An object that supports async iteration is said to be "iterable" if it has a Symbol.asyncIterator method that returns an AsyncIterator object.
Generators
ES6 also introduced "Generators", which are functions that can be used to yield partial computation results via the Iterator interface and the yield keyword. Generators can also internally delegate calls to another iterable through yield *. For example:
function* f() {
yield 1;
yield* [2, 3];
}
Async Generators
The Async Iteration proposal introduces "Async Generators", which are async functions that also can be used to yield partial computation results. Async Generators can also delegate calls via yield* to either an iterable or async iterable:
async function* f(p) {
yield 1;
await p;
yield* [2, 3];
yield* (async function *() {
await p;
yield 4;
})();
}
As with Generators, Async Generators can only be function declarations, function expressions, or methods of classes or object literals. Arrow functions cannot be Async Generators. Async Generators require a valid, global Promise implementation (either native or an ES6-compatible polyfill), in addition to a valid Symbol.asyncIterator reference (either a native symbol or a shim).
The for-await-of Statement
Finally, ES6 introduced the for..of statement as a means of iterating over an iterable. Similarly, the Async Iteration proposal introduces the for..await..of statement to iterate over an async iterable:
async function* g() { ... }
async function f() {
for await (const x of g()) {
}
}
The for..await..of statement is only legal within an Async Function or Async Generator.
Generators and Iteration for ES5/3
In addition, the following changes are included to bring full support for Generators to ES5/ES3:
- Added a
-downlevelIteration compiler option, used when targeting ES5 or ES3.
- When set, the compiler uses new type check and emit behavior that attempts to call a
[Symbol.iterator]() method on the iterated object if it is found, and creates a synthetic array iterator over the object if it is not. This requires a native Symbol.iterator or Symbol.iterator shim at runtime for any non-array values.
- When not set, array destructuring, spread, and
for..of are only supported for arrays as is the current behavior in TypeScript 2.1 and earlier.
- Array Destructuring now uses
Symbol.iterator in ES5/3 if available when using -downlevelIteration, but can be used on an Array even if it does not define Symbol.iterator at run time or design time.
- Spread elements in Array, Call, and New expressions use
Symbol.iterator in ES5/3 if available when using -downlevelIteration, but can be used on Array even if it does not define Symbol.iterator at run time or design time.
for..of statements support Symbol.iterator in ES5/3 if available when using -downlevelIteration, but can be used on an Array even if it does not define Symbol.iterator at run time or design time.
- Async Functions do not require a
Symbol.iterator polyfill at run time to operate.
Related issues
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
normalser, alitaheri, TobiaszCudnik, yortus, glen-84, jonaskello, jwbay, piotrwitek, gulshan, drywolf, and 54 more reacted with thumbs up emoji
jwbay, piotrwitek, drywolf, AdamWillden, msemikin, HerringtonDarkholme, pleerock, glen-84, aluanhaddad, mischkl, and 31 more reacted with hooray emoji
piotrwitek, AdamWillden, msemikin, HerringtonDarkholme, pleerock, alfaproject, aluanhaddad, mischkl, Mischi, thenameisflic, and 16 more reacted with heart emoji
All reactions
-
👍
64 reactions
-
🎉
41 reactions
-
❤️
26 reactions
|
This PR is planed on TypeScript 2.3 release. 😭
I hope this can be released soon.
|
benjamingr, thetechnick, rikkit, and frederickfogerty reacted with thumbs up emoji
jhwegener reacted with confused emoji
All reactions
-
👍
4 reactions
-
😕
1 reaction
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
});
|
|
|
|
|
|
var esnextLibrarySource = [
|
|
|
"esnext.asynciterable.d.ts"
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to update VS setup to include this file as well.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) {
|
|
|
// Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments
|
|
|
if (containerPos === -1 || pos !== containerPos) {
|
|
|
if ((containerPos === -1 || pos !== containerPos)) {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the parens are not needed
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) {
|
|
|
// Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments
|
|
|
if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) {
|
|
|
if ((containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd))) {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
@@ -21132,7 +21287,7 @@ namespace ts { |
|
|
function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) {
|
|
|
if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) {
|
|
|
const sourceFile = getSourceFileOfNode(location);
|
|
|
if (isEffectiveExternalModule(sourceFile, compilerOptions)) {
|
|
|
if (!isDeclarationFile(sourceFile) && isEffectiveExternalModule(sourceFile, compilerOptions)) {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need this here, should not the new helpers only be visible in expressions?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it is needed, then it should be isInAmbientContext
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Apr 20, 2017
|
Just curious, why is the downlevelIteration still undocumented under tsc --help? It seems to work, but there's no mention of it, and the errors leading up to needing it are unhelpful.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Just curious, why is the downlevelIteration still undocumented under tsc --help?
it is, just use tsc --help --all
|
jocull, SlurpTheo, and olingern reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
+1 more reviewer
Reviewers whose approvals may not affect merge requirements
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|