Skip to content

Commit 67d0fc1

Browse files
authored
Use global Iterator.prototype for down-level generators (#59514)
1 parent 3cf708e commit 67d0fc1

File tree

91 files changed

+345
-301
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+345
-301
lines changed

src/compiler/factory/emitHelpers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ const asyncGeneratorHelper: UnscopedEmitHelper = {
836836
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
837837
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
838838
var g = generator.apply(thisArg, _arguments || []), i, q = [];
839-
return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
839+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
840840
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
841841
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
842842
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
@@ -1102,8 +1102,8 @@ const generatorHelper: UnscopedEmitHelper = {
11021102
priority: 6,
11031103
text: `
11041104
var __generator = (this && this.__generator) || function (thisArg, body) {
1105-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
1106-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
1105+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
1106+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
11071107
function verb(n) { return function (v) { return step([n, v]); }; }
11081108
function step(op) {
11091109
if (f) throw new TypeError("Generator is already executing.");

src/testRunner/unittests/evaluation/asyncGenerator.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,26 @@ describe("unittests:: evaluation:: asyncGeneratorEvaluation", () => {
8383
{ done: true, value: 2 },
8484
]);
8585
});
86+
it("Supports global `AsyncIterator.prototype` if present", () => {
87+
class AsyncIterator {}
88+
const { gen } = evaluator.evaluateTypeScript(
89+
`
90+
export async function * gen() {}
91+
`,
92+
{ target: ts.ScriptTarget.ES5 },
93+
{ AsyncIterator },
94+
);
95+
const g = gen();
96+
assert.instanceOf(g, AsyncIterator);
97+
});
98+
it("Ignores global `AsyncIterator.prototype` if missing", () => {
99+
const { gen } = evaluator.evaluateTypeScript(
100+
`
101+
export async function * gen() {}
102+
`,
103+
{ target: ts.ScriptTarget.ES5 },
104+
{ AsyncIterator: undefined },
105+
);
106+
gen();
107+
});
86108
});

src/testRunner/unittests/evaluation/generator.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,26 @@ describe("unittests:: evaluation:: generatorEvaluation", () => {
3939
assert.deepEqual(g.next(), { value: undefined, done: true });
4040
assert.deepEqual(output, []);
4141
});
42+
it("Supports global `Iterator.prototype` if present", () => {
43+
class Iterator {}
44+
const { gen } = evaluator.evaluateTypeScript(
45+
`
46+
export function * gen() {}
47+
`,
48+
{ target: ts.ScriptTarget.ES5 },
49+
{ Iterator },
50+
);
51+
const g = gen();
52+
assert.instanceOf(g, Iterator);
53+
});
54+
it("Ignores global `Iterator.prototype` if missing", () => {
55+
const { gen } = evaluator.evaluateTypeScript(
56+
`
57+
export function * gen() {}
58+
`,
59+
{ target: ts.ScriptTarget.ES5 },
60+
{ Iterator: undefined },
61+
);
62+
gen();
63+
});
4264
});

tests/baselines/reference/asyncArrowFunction11_es5.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
2020
});
2121
};
2222
var __generator = (this && this.__generator) || function (thisArg, body) {
23-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
24-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
23+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
2525
function verb(n) { return function (v) { return step([n, v]); }; }
2626
function step(op) {
2727
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncAwaitIsolatedModules_es5.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
5353
});
5454
};
5555
var __generator = (this && this.__generator) || function (thisArg, body) {
56-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
57-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
56+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
57+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
5858
function verb(n) { return function (v) { return step([n, v]); }; }
5959
function step(op) {
6060
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncAwait_es5.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
5959
});
6060
};
6161
var __generator = (this && this.__generator) || function (thisArg, body) {
62-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
63-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
62+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
63+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
6464
function verb(n) { return function (v) { return step([n, v]); }; }
6565
function step(op) {
6666
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncFunctionNoReturnType.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
1818
});
1919
};
2020
var __generator = (this && this.__generator) || function (thisArg, body) {
21-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
22-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
21+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
22+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
2323
function verb(n) { return function (v) { return step([n, v]); }; }
2424
function step(op) {
2525
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncFunctionReturnExpressionErrorSpans.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
3434
});
3535
};
3636
var __generator = (this && this.__generator) || function (thisArg, body) {
37-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
38-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
38+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
3939
function verb(n) { return function (v) { return step([n, v]); }; }
4040
function step(op) {
4141
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncFunctionTempVariableScoping.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
1717
});
1818
};
1919
var __generator = (this && this.__generator) || function (thisArg, body) {
20-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
21-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
20+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
21+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
2222
function verb(n) { return function (v) { return step([n, v]); }; }
2323
function step(op) {
2424
if (f) throw new TypeError("Generator is already executing.");

tests/baselines/reference/asyncFunctionWithForStatementNoInitializer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
3737
});
3838
};
3939
var __generator = (this && this.__generator) || function (thisArg, body) {
40-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
41-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
41+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4242
function verb(n) { return function (v) { return step([n, v]); }; }
4343
function step(op) {
4444
if (f) throw new TypeError("Generator is already executing.");

0 commit comments

Comments
 (0)