Skip to content

Commit 2a9e4b8

Browse files
authored
await using normative changes (#58624)
1 parent 1659a9d commit 2a9e4b8

File tree

55 files changed

+245
-54
lines changed

Some content is hidden

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

55 files changed

+245
-54
lines changed

src/compiler/factory/emitHelpers.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,16 +1395,18 @@ export const addDisposableResourceHelper: UnscopedEmitHelper = {
13951395
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
13961396
if (value !== null && value !== void 0) {
13971397
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
1398-
var dispose;
1398+
var dispose, inner;
13991399
if (async) {
14001400
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
14011401
dispose = value[Symbol.asyncDispose];
14021402
}
14031403
if (dispose === void 0) {
14041404
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
14051405
dispose = value[Symbol.dispose];
1406+
if (async) inner = dispose;
14061407
}
14071408
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
1409+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
14081410
env.stack.push({ value: value, dispose: dispose, async: async });
14091411
}
14101412
else if (async) {

src/testRunner/unittests/evaluation/awaitUsingDeclarations.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,4 +1791,87 @@ describe("unittests:: evaluation:: awaitUsingDeclarations", () => {
17911791
"no interleave",
17921792
]);
17931793
});
1794+
1795+
// https://github.com/microsoft/TypeScript/issues/58077
1796+
it("Promise returned by sync dispose is not awaited", async () => {
1797+
const { main, output } = evaluator.evaluateTypeScript(
1798+
`
1799+
export const output: any[] = [];
1800+
1801+
export async function main() {
1802+
const promiseDispose = new Promise<void>((resolve) => {
1803+
setTimeout(() => {
1804+
output.push("y dispose promise body");
1805+
resolve();
1806+
}, 0);
1807+
});
1808+
1809+
{
1810+
await using x = {
1811+
async [Symbol.asyncDispose]() {
1812+
output.push("x asyncDispose body");
1813+
},
1814+
};
1815+
await using y = {
1816+
[Symbol.dispose]() {
1817+
output.push("y dispose body");
1818+
return promiseDispose;
1819+
},
1820+
};
1821+
}
1822+
1823+
output.push("body");
1824+
await promiseDispose;
1825+
}
1826+
1827+
`,
1828+
{ target: ts.ScriptTarget.ES2018 },
1829+
);
1830+
1831+
await main();
1832+
1833+
assert.deepEqual(output, [
1834+
"y dispose body",
1835+
"x asyncDispose body",
1836+
"body",
1837+
"y dispose promise body",
1838+
]);
1839+
});
1840+
1841+
// https://github.com/microsoft/TypeScript/issues/58077
1842+
it("Exception thrown by sync dispose is handled as rejection", async () => {
1843+
const { main, output } = evaluator.evaluateTypeScript(
1844+
`
1845+
export const output: any[] = [];
1846+
1847+
export async function main() {
1848+
const interleave = Promise.resolve().then(() => { output.push("interleave"); });
1849+
1850+
try {
1851+
await using x = {
1852+
[Symbol.dispose]() {
1853+
output.push("dispose");
1854+
throw null;
1855+
},
1856+
};
1857+
}
1858+
catch {
1859+
output.push("catch");
1860+
}
1861+
1862+
await interleave;
1863+
}
1864+
1865+
`,
1866+
{ target: ts.ScriptTarget.ES2018 },
1867+
);
1868+
1869+
await main();
1870+
1871+
assert.deepEqual(output, [
1872+
"dispose",
1873+
"interleave",
1874+
"catch",
1875+
]);
1876+
});
17941877
});

tests/baselines/reference/awaitUsingDeclarations.1(target=es2015).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
112112
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
113113
if (value !== null && value !== void 0) {
114114
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
115-
var dispose;
115+
var dispose, inner;
116116
if (async) {
117117
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
118118
dispose = value[Symbol.asyncDispose];
119119
}
120120
if (dispose === void 0) {
121121
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
122122
dispose = value[Symbol.dispose];
123+
if (async) inner = dispose;
123124
}
124125
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
126+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
125127
env.stack.push({ value: value, dispose: dispose, async: async });
126128
}
127129
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.1(target=es2017).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,18 @@ export {};
103103
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
104104
if (value !== null && value !== void 0) {
105105
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
106-
var dispose;
106+
var dispose, inner;
107107
if (async) {
108108
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
109109
dispose = value[Symbol.asyncDispose];
110110
}
111111
if (dispose === void 0) {
112112
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
113113
dispose = value[Symbol.dispose];
114+
if (async) inner = dispose;
114115
}
115116
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
117+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
116118
env.stack.push({ value: value, dispose: dispose, async: async });
117119
}
118120
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.1(target=es2022).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,18 @@ export {};
103103
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
104104
if (value !== null && value !== void 0) {
105105
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
106-
var dispose;
106+
var dispose, inner;
107107
if (async) {
108108
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
109109
dispose = value[Symbol.asyncDispose];
110110
}
111111
if (dispose === void 0) {
112112
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
113113
dispose = value[Symbol.dispose];
114+
if (async) inner = dispose;
114115
}
115116
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
117+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
116118
env.stack.push({ value: value, dispose: dispose, async: async });
117119
}
118120
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.1(target=es5).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
139139
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
140140
if (value !== null && value !== void 0) {
141141
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
142-
var dispose;
142+
var dispose, inner;
143143
if (async) {
144144
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
145145
dispose = value[Symbol.asyncDispose];
146146
}
147147
if (dispose === void 0) {
148148
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
149149
dispose = value[Symbol.dispose];
150+
if (async) inner = dispose;
150151
}
151152
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
153+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
152154
env.stack.push({ value: value, dispose: dispose, async: async });
153155
}
154156
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.2(target=es2015).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
2121
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2222
if (value !== null && value !== void 0) {
2323
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
24-
var dispose;
24+
var dispose, inner;
2525
if (async) {
2626
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2727
dispose = value[Symbol.asyncDispose];
2828
}
2929
if (dispose === void 0) {
3030
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
3131
dispose = value[Symbol.dispose];
32+
if (async) inner = dispose;
3233
}
3334
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
35+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
3436
env.stack.push({ value: value, dispose: dispose, async: async });
3537
}
3638
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.2(target=es2017).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,18 @@ export {};
1212
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
1313
if (value !== null && value !== void 0) {
1414
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
15-
var dispose;
15+
var dispose, inner;
1616
if (async) {
1717
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
1818
dispose = value[Symbol.asyncDispose];
1919
}
2020
if (dispose === void 0) {
2121
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2222
dispose = value[Symbol.dispose];
23+
if (async) inner = dispose;
2324
}
2425
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
26+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
2527
env.stack.push({ value: value, dispose: dispose, async: async });
2628
}
2729
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.2(target=es2022).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,18 @@ export {};
1212
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
1313
if (value !== null && value !== void 0) {
1414
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
15-
var dispose;
15+
var dispose, inner;
1616
if (async) {
1717
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
1818
dispose = value[Symbol.asyncDispose];
1919
}
2020
if (dispose === void 0) {
2121
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2222
dispose = value[Symbol.dispose];
23+
if (async) inner = dispose;
2324
}
2425
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
26+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
2527
env.stack.push({ value: value, dispose: dispose, async: async });
2628
}
2729
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.2(target=es5).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
4848
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
4949
if (value !== null && value !== void 0) {
5050
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
51-
var dispose;
51+
var dispose, inner;
5252
if (async) {
5353
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
5454
dispose = value[Symbol.asyncDispose];
5555
}
5656
if (dispose === void 0) {
5757
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
5858
dispose = value[Symbol.dispose];
59+
if (async) inner = dispose;
5960
}
6061
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
62+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
6163
env.stack.push({ value: value, dispose: dispose, async: async });
6264
}
6365
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.3(target=es2015).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
2323
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2424
if (value !== null && value !== void 0) {
2525
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
26-
var dispose;
26+
var dispose, inner;
2727
if (async) {
2828
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2929
dispose = value[Symbol.asyncDispose];
3030
}
3131
if (dispose === void 0) {
3232
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
3333
dispose = value[Symbol.dispose];
34+
if (async) inner = dispose;
3435
}
3536
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
37+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
3638
env.stack.push({ value: value, dispose: dispose, async: async });
3739
}
3840
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.3(target=es2017).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ export {};
1414
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
1515
if (value !== null && value !== void 0) {
1616
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
17-
var dispose;
17+
var dispose, inner;
1818
if (async) {
1919
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2020
dispose = value[Symbol.asyncDispose];
2121
}
2222
if (dispose === void 0) {
2323
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2424
dispose = value[Symbol.dispose];
25+
if (async) inner = dispose;
2526
}
2627
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
28+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
2729
env.stack.push({ value: value, dispose: dispose, async: async });
2830
}
2931
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.3(target=es2022).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ export {};
1414
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
1515
if (value !== null && value !== void 0) {
1616
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
17-
var dispose;
17+
var dispose, inner;
1818
if (async) {
1919
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2020
dispose = value[Symbol.asyncDispose];
2121
}
2222
if (dispose === void 0) {
2323
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2424
dispose = value[Symbol.dispose];
25+
if (async) inner = dispose;
2526
}
2627
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
28+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
2729
env.stack.push({ value: value, dispose: dispose, async: async });
2830
}
2931
else if (async) {

tests/baselines/reference/awaitUsingDeclarations.3(target=es5).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,18 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
5050
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
5151
if (value !== null && value !== void 0) {
5252
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
53-
var dispose;
53+
var dispose, inner;
5454
if (async) {
5555
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
5656
dispose = value[Symbol.asyncDispose];
5757
}
5858
if (dispose === void 0) {
5959
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
6060
dispose = value[Symbol.dispose];
61+
if (async) inner = dispose;
6162
}
6263
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
64+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
6365
env.stack.push({ value: value, dispose: dispose, async: async });
6466
}
6567
else if (async) {

tests/baselines/reference/awaitUsingDeclarationsInFor(target=es2015).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
2222
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2323
if (value !== null && value !== void 0) {
2424
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
25-
var dispose;
25+
var dispose, inner;
2626
if (async) {
2727
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
2828
dispose = value[Symbol.asyncDispose];
2929
}
3030
if (dispose === void 0) {
3131
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
3232
dispose = value[Symbol.dispose];
33+
if (async) inner = dispose;
3334
}
3435
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
36+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
3537
env.stack.push({ value: value, dispose: dispose, async: async });
3638
}
3739
else if (async) {

tests/baselines/reference/awaitUsingDeclarationsInFor(target=es2017).js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,18 @@ async function main() {
1313
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
1414
if (value !== null && value !== void 0) {
1515
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
16-
var dispose;
16+
var dispose, inner;
1717
if (async) {
1818
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
1919
dispose = value[Symbol.asyncDispose];
2020
}
2121
if (dispose === void 0) {
2222
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
2323
dispose = value[Symbol.dispose];
24+
if (async) inner = dispose;
2425
}
2526
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
27+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
2628
env.stack.push({ value: value, dispose: dispose, async: async });
2729
}
2830
else if (async) {

0 commit comments

Comments
 (0)