From f025a5b879f0c2eb26dd0b15af04f7b61cbcc05b Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 16 Aug 2024 11:57:04 -0400 Subject: [PATCH] built-in iterators should be disposable (#59633) --- src/harness/evaluatorImpl.ts | 2 +- src/lib/esnext.disposable.d.ts | 8 ++ .../evaluation/awaitUsingDeclarations.ts | 136 ++++++++++++++++++ .../unittests/evaluation/usingDeclarations.ts | 73 +++++----- ...arationsWithAsyncIteratorObject.errors.txt | 19 +++ ...eclarationsWithAsyncIteratorObject.symbols | 33 +++++ ...gDeclarationsWithAsyncIteratorObject.types | 40 ++++++ ...gDeclarationsWithIteratorObject.errors.txt | 28 ++++ ...singDeclarationsWithIteratorObject.symbols | 72 ++++++++++ ...tUsingDeclarationsWithIteratorObject.types | 123 ++++++++++++++++ .../reference/builtinIterator.symbols | 2 +- ...(exactoptionalpropertytypes=false).symbols | 51 ++++--- ...y2(exactoptionalpropertytypes=false).types | 58 ++++++-- ...2(exactoptionalpropertytypes=true).symbols | 51 ++++--- ...ty2(exactoptionalpropertytypes=true).types | 58 ++++++-- ...gDeclarationsWithIteratorObject.errors.txt | 31 ++++ ...singDeclarationsWithIteratorObject.symbols | 72 ++++++++++ .../usingDeclarationsWithIteratorObject.types | 123 ++++++++++++++++ .../discriminateWithOptionalProperty2.ts | 7 +- ...singDeclarationsWithAsyncIteratorObject.ts | 17 +++ ...waitUsingDeclarationsWithIteratorObject.ts | 26 ++++ .../usingDeclarationsWithIteratorObject.ts | 26 ++++ 22 files changed, 951 insertions(+), 105 deletions(-) create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.errors.txt create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.symbols create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.types create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.errors.txt create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.symbols create mode 100644 tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.types create mode 100644 tests/baselines/reference/usingDeclarationsWithIteratorObject.errors.txt create mode 100644 tests/baselines/reference/usingDeclarationsWithIteratorObject.symbols create mode 100644 tests/baselines/reference/usingDeclarationsWithIteratorObject.types create mode 100644 tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts create mode 100644 tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts create mode 100644 tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts diff --git a/src/harness/evaluatorImpl.ts b/src/harness/evaluatorImpl.ts index 9fdeed5b6cd..706e613aa5d 100644 --- a/src/harness/evaluatorImpl.ts +++ b/src/harness/evaluatorImpl.ts @@ -10,7 +10,7 @@ const sourceFileJs = vpath.combine(vfs.srcFolder, "source.js"); // Define a custom "Symbol" constructor to attach missing built-in symbols without // modifying the global "Symbol" constructor -const FakeSymbol: SymbolConstructor = ((description?: string) => Symbol(description)) as any; +export const FakeSymbol: SymbolConstructor = ((description?: string) => Symbol(description)) as any; (FakeSymbol as any).prototype = Symbol.prototype; for (const key of Object.getOwnPropertyNames(Symbol)) { Object.defineProperty(FakeSymbol, key, Object.getOwnPropertyDescriptor(Symbol, key)!); diff --git a/src/lib/esnext.disposable.d.ts b/src/lib/esnext.disposable.d.ts index 75a596a5502..0f1a00bfc83 100644 --- a/src/lib/esnext.disposable.d.ts +++ b/src/lib/esnext.disposable.d.ts @@ -1,4 +1,6 @@ /// +/// +/// interface SymbolConstructor { /** @@ -165,3 +167,9 @@ interface AsyncDisposableStackConstructor { readonly prototype: AsyncDisposableStack; } declare var AsyncDisposableStack: AsyncDisposableStackConstructor; + +interface IteratorObject extends Disposable { +} + +interface AsyncIteratorObject extends AsyncDisposable { +} diff --git a/src/testRunner/unittests/evaluation/awaitUsingDeclarations.ts b/src/testRunner/unittests/evaluation/awaitUsingDeclarations.ts index 2ba072b2122..6cd8864e857 100644 --- a/src/testRunner/unittests/evaluation/awaitUsingDeclarations.ts +++ b/src/testRunner/unittests/evaluation/awaitUsingDeclarations.ts @@ -1874,4 +1874,140 @@ describe("unittests:: evaluation:: awaitUsingDeclarations", () => { "catch", ]); }); + + it("deterministic collapse of Await", async () => { + const { main, output } = evaluator.evaluateTypeScript( + ` + export const output: any[] = []; + + let asyncId = 0; + function increment() { asyncId++; } + + export async function main() { + // increment asyncId at the top of each turn of the microtask queue + let pending = Promise.resolve(); + for (let i = 0; i < 10; i++) { + pending = pending.then(increment); + } + + { + using sync1 = { [Symbol.dispose]() { output.push(asyncId); } }; // asyncId: 2 + await using async1 = null, async2 = null; + using sync2 = { [Symbol.dispose]() { output.push(asyncId); } }; // asyncId: 1 + await using async3 = null, async4 = null; + output.push(asyncId); // asyncId: 0 + } + + output.push(asyncId); // asyncId: Ideally, 2, but ends up being 4 due to delays imposed by 'await' + + await pending; // wait for the remaining 'increment' frames to complete. + } + + `, + { target: ts.ScriptTarget.ES2018 }, + ); + + await main(); + + assert.deepEqual(output, [ + 0, + 1, + 2, + + // This really should be 2, but our transpile introduces an extra `await` by necessity to observe the + // result of __disposeResources. The process of adopting the result ends up taking two turns of the + // microtask queue. + 4, + ]); + }); + + it("'await using' with downlevel generators", async () => { + abstract class Iterator { + return?(): void; + [evaluator.FakeSymbol.iterator]() { + return this; + } + [evaluator.FakeSymbol.dispose]() { + this.return?.(); + } + } + + const { main } = evaluator.evaluateTypeScript( + ` + let exited = false; + + function * f() { + try { + yield; + } + finally { + exited = true; + } + } + + export async function main() { + { + await using g = f(); + g.next(); + } + + return exited; + } + `, + { + target: ts.ScriptTarget.ES5, + }, + { + Iterator, + }, + ); + + const exited = await main(); + assert.isTrue(exited, "Expected 'await using' to dispose generator"); + }); + + it("'await using' with downlevel async generators", async () => { + abstract class AsyncIterator { + return?(): PromiseLike; + [evaluator.FakeSymbol.asyncIterator]() { + return this; + } + async [evaluator.FakeSymbol.asyncDispose]() { + await this.return?.(); + } + } + + const { main } = evaluator.evaluateTypeScript( + ` + let exited = false; + + async function * f() { + try { + yield; + } + finally { + exited = true; + } + } + + export async function main() { + { + await using g = f(); + await g.next(); + } + + return exited; + } + `, + { + target: ts.ScriptTarget.ES5, + }, + { + AsyncIterator, + }, + ); + + const exited = await main(); + assert.isTrue(exited, "Expected 'await using' to dispose async generator"); + }); }); diff --git a/src/testRunner/unittests/evaluation/usingDeclarations.ts b/src/testRunner/unittests/evaluation/usingDeclarations.ts index f244e27844b..64bfa12416b 100644 --- a/src/testRunner/unittests/evaluation/usingDeclarations.ts +++ b/src/testRunner/unittests/evaluation/usingDeclarations.ts @@ -1811,49 +1811,48 @@ describe("unittests:: evaluation:: usingDeclarations", () => { ]); }); - it("deterministic collapse of Await", async () => { - const { main, output } = evaluator.evaluateTypeScript( - ` - export const output: any[] = []; - - let asyncId = 0; - function increment() { asyncId++; } - - export async function main() { - // increment asyncId at the top of each turn of the microtask queue - let pending = Promise.resolve(); - for (let i = 0; i < 10; i++) { - pending = pending.then(increment); + it("'using' with downlevel generators", () => { + abstract class Iterator { + return?(): void; + [evaluator.FakeSymbol.iterator]() { + return this; } - - { - using sync1 = { [Symbol.dispose]() { output.push(asyncId); } }; // asyncId: 2 - await using async1 = null, async2 = null; - using sync2 = { [Symbol.dispose]() { output.push(asyncId); } }; // asyncId: 1 - await using async3 = null, async4 = null; - output.push(asyncId); // asyncId: 0 + [evaluator.FakeSymbol.dispose]() { + this.return?.(); } - - output.push(asyncId); // asyncId: Ideally, 2, but ends up being 4 due to delays imposed by 'await' - - await pending; // wait for the remaining 'increment' frames to complete. } + const { main } = evaluator.evaluateTypeScript( + ` + let exited = false; + + function * f() { + try { + yield; + } + finally { + exited = true; + } + } + + export function main() { + { + using g = f(); + g.next(); + } + + return exited; + } `, - { target: ts.ScriptTarget.ES2018 }, + { + target: ts.ScriptTarget.ES5, + }, + { + Iterator, + }, ); - await main(); - - assert.deepEqual(output, [ - 0, - 1, - 2, - - // This really should be 2, but our transpile introduces an extra `await` by necessity to observe the - // result of __disposeResources. The process of adopting the result ends up taking two turns of the - // microtask queue. - 4, - ]); + const exited = main(); + assert.isTrue(exited, "Expected 'using' to dispose generator"); }); }); diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.errors.txt b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.errors.txt new file mode 100644 index 00000000000..82e1293db61 --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.errors.txt @@ -0,0 +1,19 @@ +awaitUsingDeclarationsWithAsyncIteratorObject.ts(11,23): error TS2851: The initializer of an 'await using' declaration must be either an object with a '[Symbol.asyncDispose]()' or '[Symbol.dispose]()' method, or be 'null' or 'undefined'. + + +==== awaitUsingDeclarationsWithAsyncIteratorObject.ts (1 errors) ==== + declare const ai: AsyncIterator; + declare const aio: AsyncIteratorObject; + declare const ag: AsyncGenerator; + + async function f() { + // should pass + await using it0 = aio; + await using it1 = ag; + + // should fail + await using it2 = ai; + ~~ +!!! error TS2851: The initializer of an 'await using' declaration must be either an object with a '[Symbol.asyncDispose]()' or '[Symbol.dispose]()' method, or be 'null' or 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.symbols b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.symbols new file mode 100644 index 00000000000..6ff871600af --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.symbols @@ -0,0 +1,33 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts] //// + +=== awaitUsingDeclarationsWithAsyncIteratorObject.ts === +declare const ai: AsyncIterator; +>ai : Symbol(ai, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 0, 13)) +>AsyncIterator : Symbol(AsyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) + +declare const aio: AsyncIteratorObject; +>aio : Symbol(aio, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 1, 13)) +>AsyncIteratorObject : Symbol(AsyncIteratorObject, Decl(lib.es2018.asynciterable.d.ts, --, --), Decl(lib.esnext.disposable.d.ts, --, --)) + +declare const ag: AsyncGenerator; +>ag : Symbol(ag, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 2, 13)) +>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) + +async function f() { +>f : Symbol(f, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 2, 47)) + + // should pass + await using it0 = aio; +>it0 : Symbol(it0, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 6, 15)) +>aio : Symbol(aio, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 1, 13)) + + await using it1 = ag; +>it1 : Symbol(it1, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 7, 15)) +>ag : Symbol(ag, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 2, 13)) + + // should fail + await using it2 = ai; +>it2 : Symbol(it2, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 10, 15)) +>ai : Symbol(ai, Decl(awaitUsingDeclarationsWithAsyncIteratorObject.ts, 0, 13)) +} + diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.types b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.types new file mode 100644 index 00000000000..43d7a7d5ed1 --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithAsyncIteratorObject.types @@ -0,0 +1,40 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts] //// + +=== awaitUsingDeclarationsWithAsyncIteratorObject.ts === +declare const ai: AsyncIterator; +>ai : AsyncIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const aio: AsyncIteratorObject; +>aio : AsyncIteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const ag: AsyncGenerator; +>ag : AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +async function f() { +>f : () => Promise +> : ^^^^^^^^^^^^^^^^^^^ + + // should pass + await using it0 = aio; +>it0 : AsyncIteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>aio : AsyncIteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it1 = ag; +>it1 : AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ag : AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + // should fail + await using it2 = ai; +>it2 : AsyncIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ai : AsyncIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.errors.txt b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.errors.txt new file mode 100644 index 00000000000..af20bc9b029 --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.errors.txt @@ -0,0 +1,28 @@ +awaitUsingDeclarationsWithIteratorObject.ts(20,23): error TS2851: The initializer of an 'await using' declaration must be either an object with a '[Symbol.asyncDispose]()' or '[Symbol.dispose]()' method, or be 'null' or 'undefined'. + + +==== awaitUsingDeclarationsWithIteratorObject.ts (1 errors) ==== + declare const i: Iterator; + declare const io: IteratorObject; + declare const g: Generator; + + class MyIterator extends Iterator { + next() { return { done: true, value: undefined }; } + } + + async function f() { + // should pass + await using it0 = io; + await using it1 = g; + await using it2 = Iterator.from(i) + await using it3 = new MyIterator(); + await using it4 = [].values(); + await using it5 = new Map().entries(); + await using it6 = new Set().keys(); + + // should fail + await using it7 = i; + ~ +!!! error TS2851: The initializer of an 'await using' declaration must be either an object with a '[Symbol.asyncDispose]()' or '[Symbol.dispose]()' method, or be 'null' or 'undefined'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.symbols b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.symbols new file mode 100644 index 00000000000..11f28871b6e --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.symbols @@ -0,0 +1,72 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts] //// + +=== awaitUsingDeclarationsWithIteratorObject.ts === +declare const i: Iterator; +>i : Symbol(i, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 0, 13)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + +declare const io: IteratorObject; +>io : Symbol(io, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 1, 13)) +>IteratorObject : Symbol(IteratorObject, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.disposable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + +declare const g: Generator; +>g : Symbol(g, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 2, 13)) +>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) + +class MyIterator extends Iterator { +>MyIterator : Symbol(MyIterator, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 2, 41)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + + next() { return { done: true, value: undefined }; } +>next : Symbol(MyIterator.next, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 4, 43)) +>done : Symbol(done, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 5, 21)) +>value : Symbol(value, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 5, 33)) +>undefined : Symbol(undefined) +} + +async function f() { +>f : Symbol(f, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 6, 1)) + + // should pass + await using it0 = io; +>it0 : Symbol(it0, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 10, 15)) +>io : Symbol(io, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 1, 13)) + + await using it1 = g; +>it1 : Symbol(it1, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 11, 15)) +>g : Symbol(g, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 2, 13)) + + await using it2 = Iterator.from(i) +>it2 : Symbol(it2, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 12, 15)) +>Iterator.from : Symbol(IteratorConstructor.from, Decl(lib.esnext.iterator.d.ts, --, --)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) +>from : Symbol(IteratorConstructor.from, Decl(lib.esnext.iterator.d.ts, --, --)) +>i : Symbol(i, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 0, 13)) + + await using it3 = new MyIterator(); +>it3 : Symbol(it3, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 13, 15)) +>MyIterator : Symbol(MyIterator, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 2, 41)) + + await using it4 = [].values(); +>it4 : Symbol(it4, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 14, 15)) +>[].values : Symbol(Array.values, Decl(lib.es2015.iterable.d.ts, --, --)) +>values : Symbol(Array.values, Decl(lib.es2015.iterable.d.ts, --, --)) + + await using it5 = new Map().entries(); +>it5 : Symbol(it5, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 15, 15)) +>new Map().entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --)) + + await using it6 = new Set().keys(); +>it6 : Symbol(it6, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 16, 15)) +>new Set().keys : Symbol(Set.keys, Decl(lib.es2015.iterable.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --)) +>keys : Symbol(Set.keys, Decl(lib.es2015.iterable.d.ts, --, --)) + + // should fail + await using it7 = i; +>it7 : Symbol(it7, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 19, 15)) +>i : Symbol(i, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 0, 13)) +} + diff --git a/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.types b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.types new file mode 100644 index 00000000000..54cd3d16dd0 --- /dev/null +++ b/tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.types @@ -0,0 +1,123 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts] //// + +=== awaitUsingDeclarationsWithIteratorObject.ts === +declare const i: Iterator; +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const io: IteratorObject; +>io : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const g: Generator; +>g : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +class MyIterator extends Iterator { +>MyIterator : MyIterator +> : ^^^^^^^^^^ +>Iterator : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + next() { return { done: true, value: undefined }; } +>next : () => { done: boolean; value: any; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ done: true, value: undefined } : { done: boolean; value: undefined; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>done : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>value : undefined +> : ^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ +} + +async function f() { +>f : () => Promise +> : ^^^^^^^^^^^^^^^^^^^ + + // should pass + await using it0 = io; +>it0 : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>io : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it1 = g; +>it1 : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it2 = Iterator.from(i) +>it2 : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Iterator.from(i) : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Iterator.from : (value: Iterator | Iterable) => IteratorObject +> : ^ ^^ ^^ ^^^^^ +>Iterator : IteratorConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>from : (value: Iterator | Iterable) => IteratorObject +> : ^ ^^ ^^ ^^^^^ +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it3 = new MyIterator(); +>it3 : MyIterator +> : ^^^^^^^^^^ +>new MyIterator() : MyIterator +> : ^^^^^^^^^^ +>MyIterator : typeof MyIterator +> : ^^^^^^^^^^^^^^^^^ + + await using it4 = [].values(); +>it4 : ArrayIterator +> : ^^^^^^^^^^^^^^^^^^ +>[].values() : ArrayIterator +> : ^^^^^^^^^^^^^^^^^^ +>[].values : () => ArrayIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +>values : () => ArrayIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it5 = new Map().entries(); +>it5 : MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map().entries() : MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map().entries : () => MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map() : Map +> : ^^^^^^^^^^^^^^^^^^^ +>Map : MapConstructor +> : ^^^^^^^^^^^^^^ +>entries : () => MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + await using it6 = new Set().keys(); +>it6 : SetIterator +> : ^^^^^^^^^^^^^^^^^^^ +>new Set().keys() : SetIterator +> : ^^^^^^^^^^^^^^^^^^^ +>new Set().keys : () => SetIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Set() : Set +> : ^^^^^^^^^^^ +>Set : SetConstructor +> : ^^^^^^^^^^^^^^ +>keys : () => SetIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + // should fail + await using it7 = i; +>it7 : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/builtinIterator.symbols b/tests/baselines/reference/builtinIterator.symbols index 00c37ef1982..34ba5eea534 100644 --- a/tests/baselines/reference/builtinIterator.symbols +++ b/tests/baselines/reference/builtinIterator.symbols @@ -184,7 +184,7 @@ const iter1 = Iterator.from(g1); declare const iter2: IteratorObject; >iter2 : Symbol(iter2, Decl(builtinIterator.ts, 71, 13)) ->IteratorObject : Symbol(IteratorObject, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) +>IteratorObject : Symbol(IteratorObject, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.disposable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) const iter3 = iter2.flatMap(() => g1); >iter3 : Symbol(iter3, Decl(builtinIterator.ts, 72, 5)) diff --git a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).symbols b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).symbols index 92e1297495f..d0e1cd81e82 100644 --- a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).symbols +++ b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).symbols @@ -110,8 +110,10 @@ function mapAsyncIterable( >next : Symbol(AsyncIterator.next, Decl(lib.es2018.asynciterable.d.ts, --, --)) }, - async return(): Promise> { + async return(value: R): Promise> { >return : Symbol(return, Decl(discriminateWithOptionalProperty2.ts, 32, 6)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 33, 17)) +>R : Symbol(R, Decl(discriminateWithOptionalProperty2.ts, 4, 31)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) >IteratorResult : Symbol(IteratorResult, Decl(lib.es2015.iterable.d.ts, --, --)) >U : Symbol(U, Decl(discriminateWithOptionalProperty2.ts, 4, 28)) @@ -122,11 +124,12 @@ function mapAsyncIterable( >iterator : Symbol(iterator, Decl(discriminateWithOptionalProperty2.ts, 8, 7)) >return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) - ? mapResult(await iterator.return()) + ? mapResult(await iterator.return(value)) >mapResult : Symbol(mapResult, Decl(discriminateWithOptionalProperty2.ts, 8, 52)) >iterator.return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) >iterator : Symbol(iterator, Decl(discriminateWithOptionalProperty2.ts, 8, 7)) >return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 33, 17)) : { value: undefined as any, done: true }; >value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 36, 11)) @@ -164,35 +167,47 @@ function mapAsyncIterable( >this : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) }, + async [Symbol.asyncDispose]() { +>[Symbol.asyncDispose] : Symbol([Symbol.asyncDispose], Decl(discriminateWithOptionalProperty2.ts, 46, 6)) +>Symbol.asyncDispose : Symbol(SymbolConstructor.asyncDispose, Decl(lib.esnext.disposable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>asyncDispose : Symbol(SymbolConstructor.asyncDispose, Decl(lib.esnext.disposable.d.ts, --, --)) + + await this.return(undefined!); +>this.return : Symbol(AsyncGenerator.return, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>this : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>return : Symbol(AsyncGenerator.return, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>undefined : Symbol(undefined) + } }; } const items = [1, 2, 3]; ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) const iterable = { ->iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 5)) +>iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 5)) [Symbol.asyncIterator]() { ->[Symbol.asyncIterator] : Symbol([Symbol.asyncIterator], Decl(discriminateWithOptionalProperty2.ts, 52, 18)) +>[Symbol.asyncIterator] : Symbol([Symbol.asyncIterator], Decl(discriminateWithOptionalProperty2.ts, 55, 18)) >Symbol.asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) >Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) >asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) return this; ->this : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 16)) +>this : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 16)) }, next() { ->next : Symbol(next, Decl(discriminateWithOptionalProperty2.ts, 55, 4)) +>next : Symbol(next, Decl(discriminateWithOptionalProperty2.ts, 58, 4)) const value = items[0]; ->value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 57, 9)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 60, 9)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) items.shift(); >items.shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) >shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --)) return Promise.resolve({ @@ -201,23 +216,23 @@ const iterable = { >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) done: items.length === 0, ->done : Symbol(done, Decl(discriminateWithOptionalProperty2.ts, 59, 28)) +>done : Symbol(done, Decl(discriminateWithOptionalProperty2.ts, 62, 28)) >items.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) >length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) value, ->value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 60, 31)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 63, 31)) }); }, }; const doubles = mapAsyncIterable(iterable, (x) => x + x); ->doubles : Symbol(doubles, Decl(discriminateWithOptionalProperty2.ts, 66, 5)) +>doubles : Symbol(doubles, Decl(discriminateWithOptionalProperty2.ts, 69, 5)) >mapAsyncIterable : Symbol(mapAsyncIterable, Decl(discriminateWithOptionalProperty2.ts, 2, 40)) ->iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 5)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) +>iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 5)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) diff --git a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).types b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).types index ef7c8c5ae73..e0c4f8568b6 100644 --- a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).types +++ b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=false).types @@ -125,8 +125,8 @@ function mapAsyncIterable( } return { ->{ async next() { return mapResult(await iterator.next()); }, async return(): Promise> { return typeof iterator.return === "function" ? mapResult(await iterator.return()) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { if (typeof iterator.throw === "function") { return mapResult(await iterator.throw(error)); } throw error; }, [Symbol.asyncIterator]() { return this; }, } : { next(): Promise>; return(): Promise>; throw(error?: unknown): Promise>; [Symbol.asyncIterator](): AsyncGenerator; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ async next() { return mapResult(await iterator.next()); }, async return(value: R): Promise> { return typeof iterator.return === "function" ? mapResult(await iterator.return(value)) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { if (typeof iterator.throw === "function") { return mapResult(await iterator.throw(error)); } throw error; }, [Symbol.asyncIterator]() { return this; }, async [Symbol.asyncDispose]() { await this.return(undefined!); } } : { next(): Promise>; return(value: R): Promise>; throw(error?: unknown): Promise>; [Symbol.asyncIterator](): AsyncGenerator; [Symbol.asyncDispose](): Promise; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^ ^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ async next() { >next : () => Promise> @@ -149,13 +149,15 @@ function mapAsyncIterable( > : ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }, - async return(): Promise> { ->return : () => Promise> -> : ^^^^^^ + async return(value: R): Promise> { +>return : (value: R) => Promise> +> : ^ ^^ ^^^^^ +>value : R +> : ^ return typeof iterator.return === "function" ->typeof iterator.return === "function" ? mapResult(await iterator.return()) : { value: undefined as any, done: true } : Promise> | { value: any; done: true; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>typeof iterator.return === "function" ? mapResult(await iterator.return(value)) : { value: undefined as any, done: true } : Promise> | { value: any; done: true; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ >typeof iterator.return === "function" : boolean > : ^^^^^^^ >typeof iterator.return : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" @@ -169,21 +171,23 @@ function mapAsyncIterable( >"function" : "function" > : ^^^^^^^^^^ - ? mapResult(await iterator.return()) ->mapResult(await iterator.return()) : Promise> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ? mapResult(await iterator.return(value)) +>mapResult(await iterator.return(value)) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >mapResult : (result: IteratorResult) => Promise> > : ^ ^^ ^^^^^ ->await iterator.return() : IteratorResult -> : ^^^^^^^^^^^^^^^^^^^^ ->iterator.return() : Promise> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>await iterator.return(value) : IteratorResult +> : ^^^^^^^^^^^^^^^^^^^^ +>iterator.return(value) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >iterator.return : (value?: R | PromiseLike | undefined) => Promise> > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >iterator : AsyncIterator > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >return : (value?: R | PromiseLike | undefined) => Promise> > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>value : R +> : ^ : { value: undefined as any, done: true }; >{ value: undefined as any, done: true } : { value: any; done: true; } @@ -256,6 +260,32 @@ function mapAsyncIterable( > : ^^^^^^^^^^^^^^^^^^^^^^^^^^ }, + async [Symbol.asyncDispose]() { +>[Symbol.asyncDispose] : () => Promise +> : ^^^^^^^^^^^^^^^^^^^ +>Symbol.asyncDispose : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol : SymbolConstructor +> : ^^^^^^^^^^^^^^^^^ +>asyncDispose : unique symbol +> : ^^^^^^^^^^^^^ + + await this.return(undefined!); +>await this.return(undefined!) : IteratorResult +> : ^^^^^^^^^^^^^^^^^^^^ +>this.return(undefined!) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.return : (value: R | PromiseLike) => Promise> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>return : (value: R | PromiseLike) => Promise> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>undefined! : never +> : ^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + } }; } diff --git a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).symbols b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).symbols index 92e1297495f..d0e1cd81e82 100644 --- a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).symbols +++ b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).symbols @@ -110,8 +110,10 @@ function mapAsyncIterable( >next : Symbol(AsyncIterator.next, Decl(lib.es2018.asynciterable.d.ts, --, --)) }, - async return(): Promise> { + async return(value: R): Promise> { >return : Symbol(return, Decl(discriminateWithOptionalProperty2.ts, 32, 6)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 33, 17)) +>R : Symbol(R, Decl(discriminateWithOptionalProperty2.ts, 4, 31)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) >IteratorResult : Symbol(IteratorResult, Decl(lib.es2015.iterable.d.ts, --, --)) >U : Symbol(U, Decl(discriminateWithOptionalProperty2.ts, 4, 28)) @@ -122,11 +124,12 @@ function mapAsyncIterable( >iterator : Symbol(iterator, Decl(discriminateWithOptionalProperty2.ts, 8, 7)) >return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) - ? mapResult(await iterator.return()) + ? mapResult(await iterator.return(value)) >mapResult : Symbol(mapResult, Decl(discriminateWithOptionalProperty2.ts, 8, 52)) >iterator.return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) >iterator : Symbol(iterator, Decl(discriminateWithOptionalProperty2.ts, 8, 7)) >return : Symbol(AsyncIterator.return, Decl(lib.es2018.asynciterable.d.ts, --, --)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 33, 17)) : { value: undefined as any, done: true }; >value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 36, 11)) @@ -164,35 +167,47 @@ function mapAsyncIterable( >this : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) }, + async [Symbol.asyncDispose]() { +>[Symbol.asyncDispose] : Symbol([Symbol.asyncDispose], Decl(discriminateWithOptionalProperty2.ts, 46, 6)) +>Symbol.asyncDispose : Symbol(SymbolConstructor.asyncDispose, Decl(lib.esnext.disposable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) +>asyncDispose : Symbol(SymbolConstructor.asyncDispose, Decl(lib.esnext.disposable.d.ts, --, --)) + + await this.return(undefined!); +>this.return : Symbol(AsyncGenerator.return, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>this : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>return : Symbol(AsyncGenerator.return, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) +>undefined : Symbol(undefined) + } }; } const items = [1, 2, 3]; ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) const iterable = { ->iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 5)) +>iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 5)) [Symbol.asyncIterator]() { ->[Symbol.asyncIterator] : Symbol([Symbol.asyncIterator], Decl(discriminateWithOptionalProperty2.ts, 52, 18)) +>[Symbol.asyncIterator] : Symbol([Symbol.asyncIterator], Decl(discriminateWithOptionalProperty2.ts, 55, 18)) >Symbol.asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) >Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) >asyncIterator : Symbol(SymbolConstructor.asyncIterator, Decl(lib.es2018.asynciterable.d.ts, --, --)) return this; ->this : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 16)) +>this : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 16)) }, next() { ->next : Symbol(next, Decl(discriminateWithOptionalProperty2.ts, 55, 4)) +>next : Symbol(next, Decl(discriminateWithOptionalProperty2.ts, 58, 4)) const value = items[0]; ->value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 57, 9)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 60, 9)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) items.shift(); >items.shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) >shift : Symbol(Array.shift, Decl(lib.es5.d.ts, --, --)) return Promise.resolve({ @@ -201,23 +216,23 @@ const iterable = { >resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) done: items.length === 0, ->done : Symbol(done, Decl(discriminateWithOptionalProperty2.ts, 59, 28)) +>done : Symbol(done, Decl(discriminateWithOptionalProperty2.ts, 62, 28)) >items.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) ->items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 50, 5)) +>items : Symbol(items, Decl(discriminateWithOptionalProperty2.ts, 53, 5)) >length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) value, ->value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 60, 31)) +>value : Symbol(value, Decl(discriminateWithOptionalProperty2.ts, 63, 31)) }); }, }; const doubles = mapAsyncIterable(iterable, (x) => x + x); ->doubles : Symbol(doubles, Decl(discriminateWithOptionalProperty2.ts, 66, 5)) +>doubles : Symbol(doubles, Decl(discriminateWithOptionalProperty2.ts, 69, 5)) >mapAsyncIterable : Symbol(mapAsyncIterable, Decl(discriminateWithOptionalProperty2.ts, 2, 40)) ->iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 52, 5)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) ->x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 66, 44)) +>iterable : Symbol(iterable, Decl(discriminateWithOptionalProperty2.ts, 55, 5)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) +>x : Symbol(x, Decl(discriminateWithOptionalProperty2.ts, 69, 44)) diff --git a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).types b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).types index ef7c8c5ae73..e0c4f8568b6 100644 --- a/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).types +++ b/tests/baselines/reference/discriminateWithOptionalProperty2(exactoptionalpropertytypes=true).types @@ -125,8 +125,8 @@ function mapAsyncIterable( } return { ->{ async next() { return mapResult(await iterator.next()); }, async return(): Promise> { return typeof iterator.return === "function" ? mapResult(await iterator.return()) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { if (typeof iterator.throw === "function") { return mapResult(await iterator.throw(error)); } throw error; }, [Symbol.asyncIterator]() { return this; }, } : { next(): Promise>; return(): Promise>; throw(error?: unknown): Promise>; [Symbol.asyncIterator](): AsyncGenerator; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ async next() { return mapResult(await iterator.next()); }, async return(value: R): Promise> { return typeof iterator.return === "function" ? mapResult(await iterator.return(value)) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { if (typeof iterator.throw === "function") { return mapResult(await iterator.throw(error)); } throw error; }, [Symbol.asyncIterator]() { return this; }, async [Symbol.asyncDispose]() { await this.return(undefined!); } } : { next(): Promise>; return(value: R): Promise>; throw(error?: unknown): Promise>; [Symbol.asyncIterator](): AsyncGenerator; [Symbol.asyncDispose](): Promise; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^ ^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ async next() { >next : () => Promise> @@ -149,13 +149,15 @@ function mapAsyncIterable( > : ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }, - async return(): Promise> { ->return : () => Promise> -> : ^^^^^^ + async return(value: R): Promise> { +>return : (value: R) => Promise> +> : ^ ^^ ^^^^^ +>value : R +> : ^ return typeof iterator.return === "function" ->typeof iterator.return === "function" ? mapResult(await iterator.return()) : { value: undefined as any, done: true } : Promise> | { value: any; done: true; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>typeof iterator.return === "function" ? mapResult(await iterator.return(value)) : { value: undefined as any, done: true } : Promise> | { value: any; done: true; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ >typeof iterator.return === "function" : boolean > : ^^^^^^^ >typeof iterator.return : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" @@ -169,21 +171,23 @@ function mapAsyncIterable( >"function" : "function" > : ^^^^^^^^^^ - ? mapResult(await iterator.return()) ->mapResult(await iterator.return()) : Promise> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ? mapResult(await iterator.return(value)) +>mapResult(await iterator.return(value)) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >mapResult : (result: IteratorResult) => Promise> > : ^ ^^ ^^^^^ ->await iterator.return() : IteratorResult -> : ^^^^^^^^^^^^^^^^^^^^ ->iterator.return() : Promise> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>await iterator.return(value) : IteratorResult +> : ^^^^^^^^^^^^^^^^^^^^ +>iterator.return(value) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >iterator.return : (value?: R | PromiseLike | undefined) => Promise> > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >iterator : AsyncIterator > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >return : (value?: R | PromiseLike | undefined) => Promise> > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>value : R +> : ^ : { value: undefined as any, done: true }; >{ value: undefined as any, done: true } : { value: any; done: true; } @@ -256,6 +260,32 @@ function mapAsyncIterable( > : ^^^^^^^^^^^^^^^^^^^^^^^^^^ }, + async [Symbol.asyncDispose]() { +>[Symbol.asyncDispose] : () => Promise +> : ^^^^^^^^^^^^^^^^^^^ +>Symbol.asyncDispose : unique symbol +> : ^^^^^^^^^^^^^ +>Symbol : SymbolConstructor +> : ^^^^^^^^^^^^^^^^^ +>asyncDispose : unique symbol +> : ^^^^^^^^^^^^^ + + await this.return(undefined!); +>await this.return(undefined!) : IteratorResult +> : ^^^^^^^^^^^^^^^^^^^^ +>this.return(undefined!) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this.return : (value: R | PromiseLike) => Promise> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>this : AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>return : (value: R | PromiseLike) => Promise> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>undefined! : never +> : ^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + } }; } diff --git a/tests/baselines/reference/usingDeclarationsWithIteratorObject.errors.txt b/tests/baselines/reference/usingDeclarationsWithIteratorObject.errors.txt new file mode 100644 index 00000000000..3737d17d3f3 --- /dev/null +++ b/tests/baselines/reference/usingDeclarationsWithIteratorObject.errors.txt @@ -0,0 +1,31 @@ +usingDeclarationsWithIteratorObject.ts(20,17): error TS2850: The initializer of a 'using' declaration must be either an object with a '[Symbol.dispose]()' method, or be 'null' or 'undefined'. + Property '[Symbol.dispose]' is missing in type 'Iterator' but required in type 'Disposable'. + + +==== usingDeclarationsWithIteratorObject.ts (1 errors) ==== + declare const i: Iterator; + declare const io: IteratorObject; + declare const g: Generator; + + class MyIterator extends Iterator { + next() { return { done: true, value: undefined }; } + } + + function f() { + // should pass + using it0 = io; + using it1 = g; + using it2 = Iterator.from(i) + using it3 = new MyIterator(); + using it4 = [].values(); + using it5 = new Map().entries(); + using it6 = new Set().keys(); + + // should fail + using it7 = i; + ~ +!!! error TS2850: The initializer of a 'using' declaration must be either an object with a '[Symbol.dispose]()' method, or be 'null' or 'undefined'. +!!! error TS2850: Property '[Symbol.dispose]' is missing in type 'Iterator' but required in type 'Disposable'. +!!! related TS2728 lib.esnext.disposable.d.ts:--:--: '[Symbol.dispose]' is declared here. + } + \ No newline at end of file diff --git a/tests/baselines/reference/usingDeclarationsWithIteratorObject.symbols b/tests/baselines/reference/usingDeclarationsWithIteratorObject.symbols new file mode 100644 index 00000000000..caf73d6c9ba --- /dev/null +++ b/tests/baselines/reference/usingDeclarationsWithIteratorObject.symbols @@ -0,0 +1,72 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts] //// + +=== usingDeclarationsWithIteratorObject.ts === +declare const i: Iterator; +>i : Symbol(i, Decl(usingDeclarationsWithIteratorObject.ts, 0, 13)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + +declare const io: IteratorObject; +>io : Symbol(io, Decl(usingDeclarationsWithIteratorObject.ts, 1, 13)) +>IteratorObject : Symbol(IteratorObject, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.disposable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + +declare const g: Generator; +>g : Symbol(g, Decl(usingDeclarationsWithIteratorObject.ts, 2, 13)) +>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --)) + +class MyIterator extends Iterator { +>MyIterator : Symbol(MyIterator, Decl(usingDeclarationsWithIteratorObject.ts, 2, 41)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) + + next() { return { done: true, value: undefined }; } +>next : Symbol(MyIterator.next, Decl(usingDeclarationsWithIteratorObject.ts, 4, 43)) +>done : Symbol(done, Decl(usingDeclarationsWithIteratorObject.ts, 5, 21)) +>value : Symbol(value, Decl(usingDeclarationsWithIteratorObject.ts, 5, 33)) +>undefined : Symbol(undefined) +} + +function f() { +>f : Symbol(f, Decl(usingDeclarationsWithIteratorObject.ts, 6, 1)) + + // should pass + using it0 = io; +>it0 : Symbol(it0, Decl(usingDeclarationsWithIteratorObject.ts, 10, 9)) +>io : Symbol(io, Decl(usingDeclarationsWithIteratorObject.ts, 1, 13)) + + using it1 = g; +>it1 : Symbol(it1, Decl(usingDeclarationsWithIteratorObject.ts, 11, 9)) +>g : Symbol(g, Decl(usingDeclarationsWithIteratorObject.ts, 2, 13)) + + using it2 = Iterator.from(i) +>it2 : Symbol(it2, Decl(usingDeclarationsWithIteratorObject.ts, 12, 9)) +>Iterator.from : Symbol(IteratorConstructor.from, Decl(lib.esnext.iterator.d.ts, --, --)) +>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.esnext.iterator.d.ts, --, --)) +>from : Symbol(IteratorConstructor.from, Decl(lib.esnext.iterator.d.ts, --, --)) +>i : Symbol(i, Decl(usingDeclarationsWithIteratorObject.ts, 0, 13)) + + using it3 = new MyIterator(); +>it3 : Symbol(it3, Decl(usingDeclarationsWithIteratorObject.ts, 13, 9)) +>MyIterator : Symbol(MyIterator, Decl(usingDeclarationsWithIteratorObject.ts, 2, 41)) + + using it4 = [].values(); +>it4 : Symbol(it4, Decl(usingDeclarationsWithIteratorObject.ts, 14, 9)) +>[].values : Symbol(Array.values, Decl(lib.es2015.iterable.d.ts, --, --)) +>values : Symbol(Array.values, Decl(lib.es2015.iterable.d.ts, --, --)) + + using it5 = new Map().entries(); +>it5 : Symbol(it5, Decl(usingDeclarationsWithIteratorObject.ts, 15, 9)) +>new Map().entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --)) + + using it6 = new Set().keys(); +>it6 : Symbol(it6, Decl(usingDeclarationsWithIteratorObject.ts, 16, 9)) +>new Set().keys : Symbol(Set.keys, Decl(lib.es2015.iterable.d.ts, --, --)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --)) +>keys : Symbol(Set.keys, Decl(lib.es2015.iterable.d.ts, --, --)) + + // should fail + using it7 = i; +>it7 : Symbol(it7, Decl(usingDeclarationsWithIteratorObject.ts, 19, 9)) +>i : Symbol(i, Decl(usingDeclarationsWithIteratorObject.ts, 0, 13)) +} + diff --git a/tests/baselines/reference/usingDeclarationsWithIteratorObject.types b/tests/baselines/reference/usingDeclarationsWithIteratorObject.types new file mode 100644 index 00000000000..ae0dcfe5b55 --- /dev/null +++ b/tests/baselines/reference/usingDeclarationsWithIteratorObject.types @@ -0,0 +1,123 @@ +//// [tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts] //// + +=== usingDeclarationsWithIteratorObject.ts === +declare const i: Iterator; +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const io: IteratorObject; +>io : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const g: Generator; +>g : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +class MyIterator extends Iterator { +>MyIterator : MyIterator +> : ^^^^^^^^^^ +>Iterator : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + next() { return { done: true, value: undefined }; } +>next : () => { done: boolean; value: any; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ done: true, value: undefined } : { done: boolean; value: undefined; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>done : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>value : undefined +> : ^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ +} + +function f() { +>f : () => void +> : ^^^^^^^^^^ + + // should pass + using it0 = io; +>it0 : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>io : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + using it1 = g; +>it1 : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + using it2 = Iterator.from(i) +>it2 : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Iterator.from(i) : IteratorObject +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Iterator.from : (value: Iterator | Iterable) => IteratorObject +> : ^ ^^ ^^ ^^^^^ +>Iterator : IteratorConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>from : (value: Iterator | Iterable) => IteratorObject +> : ^ ^^ ^^ ^^^^^ +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + using it3 = new MyIterator(); +>it3 : MyIterator +> : ^^^^^^^^^^ +>new MyIterator() : MyIterator +> : ^^^^^^^^^^ +>MyIterator : typeof MyIterator +> : ^^^^^^^^^^^^^^^^^ + + using it4 = [].values(); +>it4 : ArrayIterator +> : ^^^^^^^^^^^^^^^^^^ +>[].values() : ArrayIterator +> : ^^^^^^^^^^^^^^^^^^ +>[].values : () => ArrayIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>[] : undefined[] +> : ^^^^^^^^^^^ +>values : () => ArrayIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + using it5 = new Map().entries(); +>it5 : MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map().entries() : MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map().entries : () => MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Map() : Map +> : ^^^^^^^^^^^^^^^^^^^ +>Map : MapConstructor +> : ^^^^^^^^^^^^^^ +>entries : () => MapIterator<[string, string]> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + using it6 = new Set().keys(); +>it6 : SetIterator +> : ^^^^^^^^^^^^^^^^^^^ +>new Set().keys() : SetIterator +> : ^^^^^^^^^^^^^^^^^^^ +>new Set().keys : () => SetIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>new Set() : Set +> : ^^^^^^^^^^^ +>Set : SetConstructor +> : ^^^^^^^^^^^^^^ +>keys : () => SetIterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + // should fail + using it7 = i; +>it7 : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>i : Iterator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + diff --git a/tests/cases/compiler/discriminateWithOptionalProperty2.ts b/tests/cases/compiler/discriminateWithOptionalProperty2.ts index a8b36cb4974..3cf706f3b95 100644 --- a/tests/cases/compiler/discriminateWithOptionalProperty2.ts +++ b/tests/cases/compiler/discriminateWithOptionalProperty2.ts @@ -36,9 +36,9 @@ function mapAsyncIterable( async next() { return mapResult(await iterator.next()); }, - async return(): Promise> { + async return(value: R): Promise> { return typeof iterator.return === "function" - ? mapResult(await iterator.return()) + ? mapResult(await iterator.return(value)) : { value: undefined as any, done: true }; }, async throw(error?: unknown) { @@ -50,6 +50,9 @@ function mapAsyncIterable( [Symbol.asyncIterator]() { return this; }, + async [Symbol.asyncDispose]() { + await this.return(undefined!); + } }; } diff --git a/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts new file mode 100644 index 00000000000..f20f51eb46a --- /dev/null +++ b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithAsyncIteratorObject.ts @@ -0,0 +1,17 @@ +// @target: esnext +// @module: esnext +// @lib: esnext +// @noEmit: true + +declare const ai: AsyncIterator; +declare const aio: AsyncIteratorObject; +declare const ag: AsyncGenerator; + +async function f() { + // should pass + await using it0 = aio; + await using it1 = ag; + + // should fail + await using it2 = ai; +} diff --git a/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts new file mode 100644 index 00000000000..de8fdd378da --- /dev/null +++ b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsWithIteratorObject.ts @@ -0,0 +1,26 @@ +// @target: esnext +// @module: esnext +// @lib: esnext +// @noEmit: true + +declare const i: Iterator; +declare const io: IteratorObject; +declare const g: Generator; + +class MyIterator extends Iterator { + next() { return { done: true, value: undefined }; } +} + +async function f() { + // should pass + await using it0 = io; + await using it1 = g; + await using it2 = Iterator.from(i) + await using it3 = new MyIterator(); + await using it4 = [].values(); + await using it5 = new Map().entries(); + await using it6 = new Set().keys(); + + // should fail + await using it7 = i; +} diff --git a/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts new file mode 100644 index 00000000000..59ba2516fea --- /dev/null +++ b/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsWithIteratorObject.ts @@ -0,0 +1,26 @@ +// @target: esnext +// @module: esnext +// @lib: esnext +// @noEmit: true + +declare const i: Iterator; +declare const io: IteratorObject; +declare const g: Generator; + +class MyIterator extends Iterator { + next() { return { done: true, value: undefined }; } +} + +function f() { + // should pass + using it0 = io; + using it1 = g; + using it2 = Iterator.from(i) + using it3 = new MyIterator(); + using it4 = [].values(); + using it5 = new Map().entries(); + using it6 = new Set().keys(); + + // should fail + using it7 = i; +}