Skip to content

Commit

Permalink
Disambiguate BuiltinIterator/BuiltinIteratorReturn (#59506)
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton authored Aug 5, 2024
1 parent aafdfe5 commit a745d1b
Show file tree
Hide file tree
Showing 150 changed files with 1,407 additions and 1,237 deletions.
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 @@ -44951,18 +44992,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 @@ -45079,18 +45134,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

0 comments on commit a745d1b

Please sign in to comment.