8000 [Transforms] Down-level transformations for Async Functions by rbuckton · Pull Request #9175 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content

[Transforms] Down-level transformations for Async Functions #9175

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

Merged
merged 31 commits into from
Jul 20, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d506e92
Early support for generators.
rbuckton Feb 29, 2016
88b38f8
Merge branch 'transforms-transformer-module' into transforms-transfor…
rbuckton Mar 2, 2016
aaf3ab7
Merge branch 'transforms-transformer-module' into transforms-transfor…
rbuckton Mar 2, 2016
c267691
Fixed labels
rbuckton Mar 3, 2016
83b4cbb
merge branch 'transforms-fixMoreSourceMaps' into transforms-transform…
rbuckton May 18, 2016
4ae83fa
Fix issues after merge
rbuckton May 18, 2016
e85d3e6
Merge branch 'transforms' into transforms-generators
rbuckton Jun 13, 2016
0948f73
Cleanup, only support generators for async functions, added emit helper.
rbuckton Jun 13, 2016
8190666
Adds progress indicators to the runtests-parallel build task.
rbuckton Jun 9, 2016
3681e3c
Fixed typo
rbuckton Jun 9, 2016
4afb8c4
Fixes an issue with runtests-parallel when global mocha is not instal…
rbuckton Jun 10, 2016
aa4662e
Fixes runtests-parallel not reporting failure for failed tests.
rbuckton Jun 13, 2016
27931d5
Cleanup, fix linter errors, follow hoisted declarations.
rbuckton Jun 13, 2016
ea61f2b
Added tests and fixed related emit issues.
rbuckton Jun 15, 2016
9073572
Merge branch 'transforms' into transforms-generators
rbuckton Jun 15, 2016
5e31b25
Merge branch 'transforms' into transforms-generators
rbuckton Jun 15, 2016
4eb2a82
Merge branch 'transforms' into transforms-generators
rbuckton Jun 15, 2016
278a350
Add support for external helpers module, cleanup, and accept new base…
rbuckton Jun 15, 2016
c11b560
es6 test conformance cleanup
rbuckton Jun 27, 2016
a858db6
Remove extraneous comments.
rbuckton Jun 27, 2016
4a16f65
Removed extranous original parameter.
rbuckton Jun 27, 2016
393ee28
Move 'use strict' directive out of generator for async function.
rbuckton Jun 27, 2016
5b2e11c
Added es5 conformance tests for await in binary.
rbuckton Jun 27, 2016
48a9562
Added es5 conformance tests for async function declarations. Add abil…
rbuckton Jun 27, 2016
0c647c3
Added es5 conformance tests for awaiting a call
rbuckton Jun 27, 2016
203dab4
Added additional es5 conformance tests, better emit for functions ret…
rbuckton Jun 28, 2016
644e4da
Added es5 conformance tests for async arrow functions, add error for …
rbuckton Jun 28, 2016
9e3d6f8
Additional comments per PR feedback.
rbuckton Jun 28, 2016
252cc25
Merge branch 'transforms' into transforms-generators
rbuckton Jul 18, 2016
c832444
Accept baselines plus new linter warnings.
rbuckton Jul 18, 2016
c285767
Updated comment
rbuckton Jul 18, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add support for external helpers module, cleanup, and accept new base…
…lines.
  • Loading branch information
rbuckton committed Jun 15, 2016
commit 278a350add2fe2d82f831b335d01f670b57a1408
3 changes: 3 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17892,6 +17892,9 @@ namespace ts {
}
if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
if (languageVersion < ScriptTarget.ES6) {
verifyHelperSymbol(exports, "__generator", SymbolFlags.Value);
}
}
}
}
Expand Down
55 changes: 22 additions & 33 deletions src/compiler/emitter.ts
8000
Original file line number Diff line number Diff line change
Expand Up @@ -73,51 +73,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge

const generatorHelper = `
var __generator = (this && this.__generator) || function (body) {
var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
function step(op) {
if (_.flag) throw new TypeError("Generator is already executing.");
while (true) {
if (f) throw new TypeError("Generator is already executing.");
while (1) {
if (_.done) switch (op[0]) {
case 0 /*next*/: return { value: void 0, done: true };
case 1 /*throw*/: case 6 /*catch*/: throw op[1];
case 2 /*return*/: return { value: op[1], done: true };
case 0: return { value: void 0, done: true };
case 1: case 6: throw op[1];
case 2: return { value: op[1], done: true };
}
try {
switch (_.flag = true, op[0]) {
case 0 /*next*/: case 1 /*throw*/: sent = op; break;
case 4 /*yield*/: return _.label++, { value: op[1], done: false };
case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
switch (f = 1, op[0]) {
case 0: case 1: sent = op; break;
case 4: return _.label++, { value: op[1], done: false };
case 7: op = _.stack.pop(), _.trys.pop(); continue;
default:
var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
_.done = true;
continue;
}
if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
_.label = op[1];
}
else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
_.label = r[1], sent = op;
}
else if (r && _.label < r[2]) {
_.label = r[2], _.stack.push(op);
}
else {
if (r[2]) _.stack.pop();
_.trys.pop();
continue;
}
if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
if (r[2]) { _.stack.pop(); }
_.trys.pop();
continue;
}
op = body(_);
}
catch (e) { op = [6 /*catch*/, e]; }
finally { _.flag = false, sent = void 0; }
catch (e) { op = [6, e]; }
finally { f = 0, sent = void 0; }
}
}
return {
next: function (v) { return step([0 /*next*/, v]); },
"throw": function (v) { return step([1 /*throw*/, v]); },
"return": function (v) { return step([2 /*return*/, v]); }
next: function (v) { return step([0, v]); },
"throw": function (v) { return step([1, v]); },
"return": function (v) { return step([2, v]); }
};
};`;

Expand Down
13 changes: 6 additions & 7 deletions src/compiler/transformers/generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,7 @@ namespace ts {
Endfinally // Marks the end of a `finally` block
}

type OperationArguments = [Label]
| [Label, Expression]
| [Statement]
| [Expression]
| [Expression, Expression];
type OperationArguments = [Label] | [Label, Expression] | [Statement] | [Expression] | [Expression, Expression];

// whether a generated code block is opening or closing at the current operation for a FunctionBuilder
const enum BlockAction {
Expand Down Expand Up @@ -245,6 +241,7 @@ namespace ts {
const previousOnSubstituteNode = context.onSubstituteNode;
context.onSubstituteNode = onSubstituteNode;

let currentSourceFile: SourceFile;
let renamedCatchVariables: Map<boolean>;
let renamedCatchVariableDeclarations: Map<Identifier>;

Expand Down Expand Up @@ -297,7 +294,9 @@ namespace ts {

function transformSourceFile(node: SourceFile) {
if (node.transformFlags & TransformFlags.ContainsGenerator) {
return visitEachChild(node, visitor, context);
currentSourceFile = node;
node = visitEachChild(node, visitor, context);
currentSourceFile = undefined;
}

return node;
Expand Down Expand Up @@ -2550,7 +2549,7 @@ namespace ts {

const buildResult = buildStatements();
return createCall(
createIdentifier("__generator"),
createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"),
/*typeArguments*/ undefined,
[setNodeEmitFlags(
createFunctionExpression(
Expand Down
27 changes: 0 additions & 27 deletions tests/baselines/reference/disallowAsyncModifierInES5.errors.txt

This file was deleted.

23 changes: 0 additions & 23 deletions tests/baselines/reference/disallowAsyncModifierInES5.js

This file was deleted.

55 changes: 22 additions & 33 deletions tests/baselines/reference/es5-asyncFunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,51 +18,40 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
var __generator = (this && this.__generator) || function (body) {
var _ = { label: 0, sent: function() { if (sent[0] === 1 /*throw*/) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent;
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
function step(op) {
if (_.flag) throw new TypeError("Generator is already executing.");
while (true) {
if (f) throw new TypeError("Generator is already executing.");
while (1) {
if (_.done) switch (op[0]) {
case 0 /*next*/: return { value: void 0, done: true };
case 1 /*throw*/: case 6 /*catch*/: throw op[1];
case 2 /*return*/: return { value: op[1], done: true };
case 0: return { value: void 0, done: true };
case 1: case 6: throw op[1];
case 2: return { value: op[1], done: true };
}
try {
switch (_.flag = true, op[0]) {
case 0 /*next*/: case 1 /*throw*/: sent = op; break;
case 4 /*yield*/: return _.label++, { value: op[1], done: false };
case 7 /*endfinally*/: op = _.stack.pop(), _.trys.pop(); continue;
switch (f = 1, op[0]) {
case 0: case 1: sent = op; break;
case 4: return _.label++, { value: op[1], done: false };
case 7: op = _.stack.pop(), _.trys.pop(); continue;
default:
var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
if (!r && (op[0] === 1 /*throw*/ || op[0] === 6 /*catch*/ || op[0] === 2 /*return*/)) {
_.done = true;
continue;
}
if (op[0] === 3 /*break*/ && (!r || (op[1] > r[0] && op[1] < r[3]))) {
_.label = op[1];
}
else if (op[0] === 6 /*catch*/ && r && _.label < r[1]) {
_.label = r[1], sent = op;
}
else if (r && _.label < r[2]) {
_.label = r[2], _.stack.push(op);
}
else {
if (r[2]) _.stack.pop();
_.trys.pop();
continue;
}
if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
if (r[2]) { _.stack.pop(); }
_.trys.pop();
continue;
}
op = body(_);
}
catch (e) { op = [6 /*catch*/, e]; }
finally { _.flag = false, sent = void 0; }
catch (e) { op = [6, e]; }
finally { f = 0, sent = void 0; }
}
}
return {
next: function (v) { return step([0 /*next*/, v]); },
"throw": function (v) { return step([1 /*throw*/, v]); },
"return": function (v) { return step([2 /*return*/, v]); }
next: function (v) { return step([0, v]); },
"throw": function (v) { return step([1, v]); },
"return": function (v) { return step([2, v]); }
};
};
function empty() {
Expand Down
83 changes: 83 additions & 0 deletions tests/baselines/reference/es5-importHelpersAsyncFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//// [tests/cases/compiler/es5-importHelpersAsyncFunctions.ts] ////

//// [external.ts]
export async function foo() {
}

//// [script.ts]
async function foo() {
}

//// [tslib.d.ts]
export declare function __extends(d: Function, b: Function): void;
export declare function __assign(t: any, ...sources: any[]): any;
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
export declare function __param(paramIndex: number, decorator: Function): Function;
export declare function __metadata(metadataKey: any, metadataValue: any): Function;
export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
export declare function __generator(body: Function): any;

//// [external.js]
"use strict";
var tslib_1 = require("tslib");
function foo() {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(function (_a) {
return [2 /*return*/];
});
});
}
exports.foo = foo;
//// [script.js]
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
var __generator = (this && this.__generator) || function (body) {
var _ = { label: 0, sent: function() { if (sent[0] === 1) throw sent[1]; return sent[1]; }, trys: [], stack: [] }, sent, f;
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (1) {
if (_.done) switch (op[0]) {
case 0: return { value: void 0, done: true };
case 1: case 6: throw op[1];
case 2: return { value: op[1], done: true };
}
try {
switch (f = 1, op[0]) {
case 0: case 1: sent = op; break;
case 4: return _.label++, { value: op[1], done: false };
case 7: op = _.stack.pop(), _.trys.pop(); continue;
default:
var r = _.trys.length > 0 && _.trys[_.trys.length - 1];
if (!r && (op[0] === 6 || op[0] === 2)) { _.done = 1; continue; }
if (op[0] === 3 && (!r || (op[1] > r[0] && op[1] < r[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < r[1]) { _.label = r[1], sent = op; break; }
if (r && _.label < r[2]) { _.label = r[2], _.stack.push(op); break; }
if (r[2]) { _.stack.pop(); }
_.trys.pop();
continue;
}
op = body(_);
}
catch (e) { op = [6, e]; }
finally { f = 0, sent = void 0; }
}
}
return {
next: function (v) { return step([0, v]); },
"throw": function (v) { return step([1, v]); },
"return": function (v) { return step([2, v]); }
};
};
function foo() {
return __awaiter(this, void 0, void 0, function () {
return __generator(function (_a) {
return [2 /*return*/];
});
});
}
58 changes: 58 additions & 0 deletions tests/baselines/reference/es5-importHelpersAsyncFunctions.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
=== tests/cases/compiler/external.ts ===
export async function foo() {
>foo : Symbol(foo, Decl(external.ts, 0, 0))
}

=== tests/cases/compiler/script.ts ===
async function foo() {
>foo : Symbol(foo, Decl(script.ts, 0, 0))
}

=== tests/cases/compiler/tslib.d.ts ===
export declare function __extends(d: Function, b: Function): void;
>__extends : Symbol(__extends, Decl(tslib.d.ts, --, --))
>d : Symbol(d, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>b : Symbol(b, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

export declare function __assign(t: any, ...sources: any[]): any;
>__assign : Symbol(__assign, Decl(tslib.d.ts, --, --))
>t : Symbol(t, Decl(tslib.d.ts, --, --))
>sources : Symbol(sources, Decl(tslib.d.ts, --, --))

export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>target : Symbol(target, Decl(tslib.d.ts, --, --))
>key : Symbol(key, Decl(tslib.d.ts, --, --))
>desc : Symbol(desc, Decl(tslib.d.ts, --, --))

export declare function __param(paramIndex: number, decorator: Function): Function;
>__param : Symbol(__param, Decl(tslib.d.ts, --, --))
>paramIndex : Symbol(paramIndex, Decl(tslib.d.ts, --, --))
>decorator : Symbol(decorator, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

export declare function __metadata(metadataKey: any, metadataValue: any): Function;
>__metadata : Symbol(__metadata, Decl(tslib.d.ts, --, --))
>metadataKey : Symbol(metadataKey, Decl(tslib.d.ts, --, --))
>metadataValue : Symbol(metadataValue, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
>__awaiter : Symbol(__awaiter, Decl(tslib.d.ts, --, --))
>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
>_arguments : Symbol(_arguments, Decl(tslib.d.ts, --, --))
>P : Symbol(P, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

export declare function __generator(body: Function): any;
>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
>body : Symbol(body, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))

Loading
0