Skip to content

Disambiguate BuiltinIterator/BuiltinIteratorReturn #59506

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 83 additions & 14 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1181,8 +1181,9 @@ interface IterationTypesResolver {
getGlobalIteratorType: (reportErrors: boolean) => GenericType;
getGlobalIterableType: (reportErrors: boolean) => GenericType;
getGlobalIterableIteratorType: (reportErrors: boolean) => GenericType;
getGlobalBuiltinIteratorType: (reportErrors: boolean) => GenericType;
getGlobalIteratorObjectType: (reportErrors: boolean) => GenericType;
getGlobalGeneratorType: (reportErrors: boolean) => GenericType;
getGlobalBuiltinIteratorTypes: () => readonly GenericType[];
resolveIterationType: (type: Type, errorNode: Node | undefined) => Type | undefined;
mustHaveANextMethodDiagnostic: DiagnosticMessage;
mustBeAMethodDiagnostic: DiagnosticMessage;
Expand Down Expand Up @@ -2167,8 +2168,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getGlobalIteratorType: getGlobalAsyncIteratorType,
getGlobalIterableType: getGlobalAsyncIterableType,
getGlobalIterableIteratorType: getGlobalAsyncIterableIteratorType,
getGlobalBuiltinIteratorType: getGlobalBuiltinAsyncIteratorType,
getGlobalIteratorObjectType: getGlobalAsyncIteratorObjectType,
getGlobalGeneratorType: getGlobalAsyncGeneratorType,
getGlobalBuiltinIteratorTypes: getGlobalBuiltinAsyncIteratorTypes,
resolveIterationType: (type, errorNode) => getAwaitedType(type, errorNode, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member),
mustHaveANextMethodDiagnostic: Diagnostics.An_async_iterator_must_have_a_next_method,
mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method,
Expand All @@ -2182,8 +2184,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
getGlobalIteratorType,
getGlobalIterableType,
getGlobalIterableIteratorType,
getGlobalBuiltinIteratorType,
getGlobalIteratorObjectType,
getGlobalGeneratorType,
getGlobalBuiltinIteratorTypes,
resolveIterationType: (type, _errorNode) => type,
mustHaveANextMethodDiagnostic: Diagnostics.An_iterator_must_have_a_next_method,
mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_iterator_must_be_a_method,
Expand Down Expand Up @@ -2244,14 +2247,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
var deferredGlobalIterableType: GenericType | undefined;
var deferredGlobalIteratorType: GenericType | undefined;
var deferredGlobalIterableIteratorType: GenericType | undefined;
var deferredGlobalBuiltinIteratorType: GenericType | undefined;
var deferredGlobalIteratorObjectType: GenericType | undefined;
var deferredGlobalGeneratorType: GenericType | undefined;
var deferredGlobalIteratorYieldResultType: GenericType | undefined;
var deferredGlobalIteratorReturnResultType: GenericType | undefined;
var deferredGlobalAsyncIterableType: GenericType | undefined;
var deferredGlobalAsyncIteratorType: GenericType | undefined;
var deferredGlobalAsyncIterableIteratorType: GenericType | undefined;
var deferredGlobalBuiltinAsyncIteratorType: GenericType | undefined;
var deferredGlobalBuiltinIteratorTypes: readonly GenericType[] | undefined;
var deferredGlobalBuiltinAsyncIteratorTypes: readonly GenericType[] | undefined;
var deferredGlobalAsyncIteratorObjectType: GenericType | undefined;
var deferredGlobalAsyncGeneratorType: GenericType | undefined;
var deferredGlobalTemplateStringsArrayType: ObjectType | undefined;
var deferredGlobalImportMetaType: ObjectType;
Expand Down Expand Up @@ -12488,6 +12493,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
}

function isReferenceToSomeType(type: Type, targets: readonly Type[]) {
if (type === undefined || (getObjectFlags(type) & ObjectFlags.Reference) === 0) {
return false;
}
for (const target of targets) {
if ((type as TypeReference).target === target) {
return true;
}
}
return false;
}

function isReferenceToType(type: Type, target: Type) {
return type !== undefined
&& target !== undefined
Expand Down Expand Up @@ -13001,7 +13018,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
links.instantiations.set(getTypeListId(typeParameters), type);
}
if (type === intrinsicMarkerType && symbol.escapedName === "BuiltinIteratorReturn") {
type = strictBuiltinIteratorReturn ? undefinedType : anyType;
type = getBuiltinIteratorReturnType();
}
}
else {
Expand Down Expand Up @@ -16868,6 +16885,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined;
}

function getGlobalBuiltinTypes(typeNames: readonly string[], arity: 0): ObjectType[];
function getGlobalBuiltinTypes(typeNames: readonly string[], arity: number): GenericType[];
function getGlobalBuiltinTypes(typeNames: readonly string[], arity: number) {
let types: Type[] | undefined;
for (const typeName of typeNames) {
types = append(types, getGlobalType(typeName as __String, arity, /*reportErrors*/ false));
}
return types ?? emptyArray;
}

function getGlobalTypedPropertyDescriptorType() {
// We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType;
Expand Down Expand Up @@ -16949,8 +16976,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}

function getGlobalBuiltinAsyncIteratorType(reportErrors: boolean) {
return (deferredGlobalBuiltinAsyncIteratorType ||= getGlobalType("BuiltinAsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
function getGlobalBuiltinAsyncIteratorTypes() {
// NOTE: This list does not include all built-in async iterator types, only those that are likely to be encountered frequently.
return deferredGlobalBuiltinAsyncIteratorTypes ??= getGlobalBuiltinTypes(["ReadableStreamAsyncIterator"], 1);
}

function getGlobalAsyncIteratorObjectType(reportErrors: boolean) {
return (deferredGlobalAsyncIteratorObjectType ||= getGlobalType("AsyncIteratorObject" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}

function getGlobalAsyncGeneratorType(reportErrors: boolean) {
Expand All @@ -16969,8 +17001,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}

function getGlobalBuiltinIteratorType(reportErrors: boolean) {
return (deferredGlobalBuiltinIteratorType ||= getGlobalType("BuiltinIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
function getBuiltinIteratorReturnType() {
return strictBuiltinIteratorReturn ? undefinedType : anyType;
}

function getGlobalBuiltinIteratorTypes() {
// NOTE: This list does not include all built-in iterator types, only those that are likely to be encountered frequently.
return deferredGlobalBuiltinIteratorTypes ??= getGlobalBuiltinTypes(["ArrayIterator", "MapIterator", "SetIterator", "StringIterator"], 1);
}

function getGlobalIteratorObjectType(reportErrors: boolean) {
return (deferredGlobalIteratorObjectType ||= getGlobalType("IteratorObject" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}

function getGlobalGeneratorType(reportErrors: boolean) {
Expand Down Expand Up @@ -44939,18 +44980,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// As an optimization, if the type is an instantiation of the following global type, then
// just grab its related type arguments:
// - `Iterable<T, TReturn, TNext>` or `AsyncIterable<T, TReturn, TNext>`
// - `BuiltinIterator<T, TReturn, TNext>` or `BuiltinAsyncIterator<T, TReturn, TNext>`
// - `IteratorObject<T, TReturn, TNext>` or `AsyncIteratorObject<T, TReturn, TNext>`
// - `IterableIterator<T, TReturn, TNext>` or `AsyncIterableIterator<T, TReturn, TNext>`
// - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
if (
isReferenceToType(type, resolver.getGlobalIterableType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalBuiltinIteratorType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalIteratorObjectType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalIterableIteratorType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))
) {
const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType);
return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
}

// As an optimization, if the type is an instantiation of one of the following global types, then
// just grab the related type argument:
// - `ArrayIterator<T>`
// - `MapIterator<T>`
// - `SetIterator<T>`
// - `StringIterator<T>`
// - `ReadableStreamAsyncIterator<T>`
if (isReferenceToSomeType(type, resolver.getGlobalBuiltinIteratorTypes())) {
const [yieldType] = getTypeArguments(type as GenericType);
const returnType = getBuiltinIteratorReturnType();
const nextType = unknownType;
return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
}
}

function getPropertyNameForKnownSymbolName(symbolName: string): __String {
Expand Down Expand Up @@ -45067,18 +45122,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// As an optimization, if the type is an instantiation of one of the following global types,
// then just grab its related type arguments:
// - `IterableIterator<T, TReturn, TNext>` or `AsyncIterableIterator<T, TReturn, TNext>`
// - `BuiltinIterator<T, TReturn, TNext>` or `BuiltinAsyncIterator<T, TReturn, TNext>`
// - `IteratorObject<T, TReturn, TNext>` or `AsyncIteratorObject<T, TReturn, TNext>`
// - `Iterator<T, TReturn, TNext>` or `AsyncIterator<T, TReturn, TNext>`
// - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
if (
isReferenceToType(type, resolver.getGlobalBuiltinIteratorType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalIterableIteratorType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalIteratorType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalIteratorObjectType(/*reportErrors*/ false)) ||
isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))
) {
const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType);
return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType));
}

// As an optimization, if the type is an instantiation of one of the following global types, then
// just grab the related type argument:
// - `ArrayIterator<T>`
// - `MapIterator<T>`
// - `SetIterator<T>`
// - `StringIterator<T>`
// - `ReadableStreamAsyncIterator<T>`
if (isReferenceToSomeType(type, resolver.getGlobalBuiltinIteratorTypes())) {
const [yieldType] = getTypeArguments(type as GenericType);
const returnType = getBuiltinIteratorReturnType();
const nextType = unknownType;
return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType));
}
}

function isIteratorResult(type: Type, kind: IterationTypeKind.Yield | IterationTypeKind.Return) {
Expand Down
20 changes: 14 additions & 6 deletions src/lib/dom.asynciterable.generated.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
/// Window Async Iterable APIs
/////////////////////////////

interface FileSystemDirectoryHandleAsyncIterator<T> extends AsyncIteratorObject<T, BuiltinIteratorReturn, unknown> {
[Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator<T>;
}

interface FileSystemDirectoryHandle {
[Symbol.asyncIterator](): BuiltinAsyncIterator<[string, FileSystemHandle], BuiltinIteratorReturn>;
entries(): BuiltinAsyncIterator<[string, FileSystemHandle], BuiltinIteratorReturn>;
keys(): BuiltinAsyncIterator<string, BuiltinIteratorReturn>;
values(): BuiltinAsyncIterator<FileSystemHandle, BuiltinIteratorReturn>;
[Symbol.asyncIterator](): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>;
entries(): FileSystemDirectoryHandleAsyncIterator<[string, FileSystemHandle]>;
keys(): FileSystemDirectoryHandleAsyncIterator<string>;
values(): FileSystemDirectoryHandleAsyncIterator<FileSystemHandle>;
}

interface ReadableStreamAsyncIterator<T> extends AsyncIteratorObject<T, BuiltinIteratorReturn, unknown> {
[Symbol.asyncIterator](): ReadableStreamAsyncIterator<T>;
}

interface ReadableStream<R = any> {
[Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): BuiltinAsyncIterator<R, BuiltinIteratorReturn>;
values(options?: ReadableStreamIteratorOptions): BuiltinAsyncIterator<R, BuiltinIteratorReturn>;
[Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
}
58 changes: 35 additions & 23 deletions src/lib/dom.iterable.d.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
/// <reference lib="dom" />

interface DOMTokenList {
[Symbol.iterator](): BuiltinIterator<string, BuiltinIteratorReturn>;
[Symbol.iterator](): ArrayIterator<string>;
}

interface HeadersIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
[Symbol.iterator](): HeadersIterator<T>;
}

interface Headers {
[Symbol.iterator](): BuiltinIterator<[string, string], BuiltinIteratorReturn>;
[Symbol.iterator](): HeadersIterator<[string, string]>;
/**
* Returns an iterator allowing to go through all key/value pairs contained in this object.
*/
entries(): BuiltinIterator<[string, string], BuiltinIteratorReturn>;
entries(): HeadersIterator<[string, string]>;
/**
* Returns an iterator allowing to go through all keys f the key/value pairs contained in this object.
*/
keys(): BuiltinIterator<string, BuiltinIteratorReturn>;
keys(): HeadersIterator<string>;
/**
* Returns an iterator allowing to go through all values of the key/value pairs contained in this object.
*/
values(): BuiltinIterator<string, BuiltinIteratorReturn>;
values(): HeadersIterator<string>;
}

interface NodeList {
/**
* Returns an array of key, value pairs for every entry in the list
*/
entries(): BuiltinIterator<[number, Node], BuiltinIteratorReturn>;
entries(): ArrayIterator<[number, Node]>;
/**
* Performs the specified action for each node in an list.
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
Expand All @@ -34,21 +38,21 @@ interface NodeList {
/**
* Returns an list of keys in the list
*/
keys(): BuiltinIterator<number, BuiltinIteratorReturn>;
keys(): ArrayIterator<number>;

/**
* Returns an list of values in the list
*/
values(): BuiltinIterator<Node, BuiltinIteratorReturn>;
values(): ArrayIterator<Node>;

[Symbol.iterator](): BuiltinIterator<Node, BuiltinIteratorReturn>;
[Symbol.iterator](): ArrayIterator<Node>;
}

interface NodeListOf<TNode extends Node> {
/**
* Returns an array of key, value pairs for every entry in the list
*/
entries(): BuiltinIterator<[number, TNode], BuiltinIteratorReturn>;
entries(): ArrayIterator<[number, TNode]>;

/**
* Performs the specified action for each node in an list.
Expand All @@ -59,55 +63,63 @@ interface NodeListOf<TNode extends Node> {
/**
* Returns an list of keys in the list
*/
keys(): BuiltinIterator<number, BuiltinIteratorReturn>;
keys(): ArrayIterator<number>;
/**
* Returns an list of values in the list
*/
values(): BuiltinIterator<TNode, BuiltinIteratorReturn>;
values(): ArrayIterator<TNode>;

[Symbol.iterator](): BuiltinIterator<TNode, BuiltinIteratorReturn>;
[Symbol.iterator](): ArrayIterator<TNode>;
}

interface HTMLCollectionBase {
[Symbol.iterator](): BuiltinIterator<Element, BuiltinIteratorReturn>;
[Symbol.iterator](): ArrayIterator<Element>;
}

interface HTMLCollectionOf<T extends Element> {
[Symbol.iterator](): BuiltinIterator<T, BuiltinIteratorReturn>;
[Symbol.iterator](): ArrayIterator<T>;
}

interface FormDataIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
[Symbol.iterator](): FormDataIterator<T>;
}

interface FormData {
/**
* Returns an array of key, value pairs for every entry in the list
*/
entries(): BuiltinIterator<[string, string | File], BuiltinIteratorReturn>;
entries(): FormDataIterator<[string, string | File]>;
/**
* Returns a list of keys in the list
*/
keys(): BuiltinIterator<string, BuiltinIteratorReturn>;
keys(): FormDataIterator<string>;
/**
* Returns a list of values in the list
*/
values(): BuiltinIterator<string | File, BuiltinIteratorReturn>;
values(): FormDataIterator<string | File>;

[Symbol.iterator](): FormDataIterator<string | File>;
}

[Symbol.iterator](): BuiltinIterator<string | File, BuiltinIteratorReturn>;
interface URLSearchParamsIterator<T> extends IteratorObject<T, BuiltinIteratorReturn, unknown> {
[Symbol.iterator](): URLSearchParamsIterator<T>;
}

interface URLSearchParams {
/**
* Returns an array of key, value pairs for every entry in the search params
*/
entries(): BuiltinIterator<[string, string], BuiltinIteratorReturn>;
entries(): URLSearchParamsIterator<[string, string]>;
/**
* Returns a list of keys in the search params
*/
keys(): BuiltinIterator<string, BuiltinIteratorReturn>;
keys(): URLSearchParamsIterator<string>;
/**
* Returns a list of values in the search params
*/
values(): BuiltinIterator<string, BuiltinIteratorReturn>;
values(): URLSearchParamsIterator<string>;
/**
* iterate over key/value pairs
*/
[Symbol.iterator](): BuiltinIterator<[string, string], BuiltinIteratorReturn>;
[Symbol.iterator](): URLSearchParamsIterator<[string, string]>;
}
Loading