From 2614ce8c6387c89496ae34e489349eab91cdec53 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 12 Dec 2024 14:09:39 +0100 Subject: [PATCH 1/2] prevent infinite recursion of `ContainsFragmentsRefs` type --- src/masking/__benches__/types.bench.ts | 15 +++++++++++++++ src/masking/internal/types.ts | 17 ++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/masking/__benches__/types.bench.ts b/src/masking/__benches__/types.bench.ts index c96231a96a..0ae97b7edc 100644 --- a/src/masking/__benches__/types.bench.ts +++ b/src/masking/__benches__/types.bench.ts @@ -577,3 +577,18 @@ test("detects `$fragmentRefs` on types with index signatures", (prefix) => { }>(); }); }); + +test("recursive types: no error 'Type instantiation is excessively deep and possibly infinite.'", (prefix) => { + // this type is self-recursive + type Source = import("graphql").IntrospectionQuery; + + bench(prefix + "instantiations", () => { + return {} as MaybeMasked; + }).types([6, "instantiations"]); + + bench(prefix + "functionality", () => { + const x = {} as MaybeMasked; + + expectTypeOf(x).branded.toEqualTypeOf(); + }); +}); diff --git a/src/masking/internal/types.ts b/src/masking/internal/types.ts index 4c769de426..828734a893 100644 --- a/src/masking/internal/types.ts +++ b/src/masking/internal/types.ts @@ -182,10 +182,13 @@ export type RemoveMaskedMarker = Omit; export type RemoveFragmentName = T extends any ? Omit : T; -export type ContainsFragmentsRefs = - true extends IsAny ? false - : TData extends object ? - " $fragmentRefs" extends keyof RemoveIndexSignature ? - true - : ContainsFragmentsRefs - : false; +type Exact = (x: T) => T; +export type ContainsFragmentsRefs = true extends ( + IsAny +) ? + false +: TData extends object ? + Exact extends Seen ? false + : " $fragmentRefs" extends keyof RemoveIndexSignature ? true + : ContainsFragmentsRefs> +: false; From 39ba96e17e4e20c076b1cc63b617de3197cd55f1 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Thu, 12 Dec 2024 14:11:49 +0100 Subject: [PATCH 2/2] api-reports & changeset --- .api-reports/api-report-cache.api.md | 6 +++++- .api-reports/api-report-core.api.md | 6 +++++- .api-reports/api-report-masking.api.md | 6 +++++- .api-reports/api-report-react.api.md | 6 +++++- .api-reports/api-report-react_components.api.md | 6 +++++- .api-reports/api-report-react_context.api.md | 6 +++++- .api-reports/api-report-react_hoc.api.md | 6 +++++- .api-reports/api-report-react_hooks.api.md | 6 +++++- .api-reports/api-report-react_internal.api.md | 6 +++++- .api-reports/api-report-react_ssr.api.md | 6 +++++- .api-reports/api-report-testing.api.md | 6 +++++- .api-reports/api-report-testing_core.api.md | 6 +++++- .api-reports/api-report-utilities.api.md | 6 +++++- .api-reports/api-report.api.md | 6 +++++- .changeset/chilly-icons-shave.md | 5 +++++ 15 files changed, 75 insertions(+), 14 deletions(-) create mode 100644 .changeset/chilly-icons-shave.md diff --git a/.api-reports/api-report-cache.api.md b/.api-reports/api-report-cache.api.md index 0e90e2b82f..908176a26c 100644 --- a/.api-reports/api-report-cache.api.md +++ b/.api-reports/api-report-cache.api.md @@ -237,10 +237,11 @@ type CombineIntersection = Exclude>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export function createFragmentRegistry(...fragments: DocumentNode[]): FragmentRegistryAPI; @@ -465,6 +466,9 @@ export namespace EntityStore { } } +// @public (undocumented) +type Exact = (x: T) => T; + // @public type ExtractByMatchingTypeNames = Iterable>; export const concat: typeof ApolloLink.concat; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export const createHttpLink: (linkOptions?: HttpOptions) => ApolloLink; @@ -790,6 +791,9 @@ namespace EntityStore { // @public export type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // @public (undocumented) export const execute: typeof ApolloLink.execute; diff --git a/.api-reports/api-report-masking.api.md b/.api-reports/api-report-masking.api.md index 12d24672ff..fffd2efb2e 100644 --- a/.api-reports/api-report-masking.api.md +++ b/.api-reports/api-report-masking.api.md @@ -221,10 +221,11 @@ type CombineIntersection = Exclude>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export interface DataMasking { @@ -360,6 +361,9 @@ export const disableWarningsSlot: { // @public (undocumented) type DistributedRequiredExclude = T extends any ? Required extends Required ? Required extends Required ? never : T : T : T; +// @public (undocumented) +type Exact = (x: T) => T; + // @public type ExtractByMatchingTypeNames extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export interface Context extends Record { @@ -779,6 +780,9 @@ export { DocumentType_2 as DocumentType } // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_components.api.md b/.api-reports/api-report-react_components.api.md index 739af65d3b..051470cb15 100644 --- a/.api-reports/api-report-react_components.api.md +++ b/.api-reports/api-report-react_components.api.md @@ -524,10 +524,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) interface DataMasking { @@ -711,6 +712,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_context.api.md b/.api-reports/api-report-react_context.api.md index 812f228974..703cfb4825 100644 --- a/.api-reports/api-report-react_context.api.md +++ b/.api-reports/api-report-react_context.api.md @@ -518,10 +518,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) interface DataMasking { @@ -705,6 +706,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_hoc.api.md b/.api-reports/api-report-react_hoc.api.md index e05e2f6112..3f86735051 100644 --- a/.api-reports/api-report-react_hoc.api.md +++ b/.api-reports/api-report-react_hoc.api.md @@ -507,10 +507,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) interface DataMasking { @@ -703,6 +704,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_hooks.api.md b/.api-reports/api-report-react_hooks.api.md index da083a0abd..b252b2a672 100644 --- a/.api-reports/api-report-react_hooks.api.md +++ b/.api-reports/api-report-react_hooks.api.md @@ -547,10 +547,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) interface DataMasking { @@ -734,6 +735,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_internal.api.md b/.api-reports/api-report-react_internal.api.md index dd6f0073fe..3e43a1dafb 100644 --- a/.api-reports/api-report-react_internal.api.md +++ b/.api-reports/api-report-react_internal.api.md @@ -526,10 +526,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // Warning: (ae-forgotten-export) The symbol "PreloadQueryFunction" needs to be exported by the entry point index.d.ts // @@ -718,6 +719,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-react_ssr.api.md b/.api-reports/api-report-react_ssr.api.md index b122eff81c..d0560e817d 100644 --- a/.api-reports/api-report-react_ssr.api.md +++ b/.api-reports/api-report-react_ssr.api.md @@ -487,10 +487,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) interface DataMasking { @@ -674,6 +675,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-testing.api.md b/.api-reports/api-report-testing.api.md index c38f15e8bf..0c7b64d8ee 100644 --- a/.api-reports/api-report-testing.api.md +++ b/.api-reports/api-report-testing.api.md @@ -477,10 +477,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @internal (undocumented) type CovariantUnaryFunction = { @@ -675,6 +676,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-testing_core.api.md b/.api-reports/api-report-testing_core.api.md index 884f6b1315..d46a9f55d1 100644 --- a/.api-reports/api-report-testing_core.api.md +++ b/.api-reports/api-report-testing_core.api.md @@ -476,10 +476,11 @@ class Concast extends Observable { type ConcastSourcesIterable = Iterable>; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @internal (undocumented) type CovariantUnaryFunction = { @@ -674,6 +675,9 @@ interface DocumentTransformOptions { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report-utilities.api.md b/.api-reports/api-report-utilities.api.md index 5cb19b3c19..a09ee2ed13 100644 --- a/.api-reports/api-report-utilities.api.md +++ b/.api-reports/api-report-utilities.api.md @@ -607,9 +607,10 @@ export type ConcastSourcesIterable = Iterable>; export function concatPagination(keyArgs?: KeyArgs): FieldPolicy; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export function createFragmentMap(fragments?: FragmentDefinitionNode[]): FragmentMap; @@ -981,6 +982,9 @@ namespace EntityStore { // @public type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts // // @public (undocumented) diff --git a/.api-reports/api-report.api.md b/.api-reports/api-report.api.md index e91fa9f983..850d6e603b 100644 --- a/.api-reports/api-report.api.md +++ b/.api-reports/api-report.api.md @@ -577,10 +577,11 @@ type ConcastSourcesIterable = Iterable>; export const concat: typeof ApolloLink.concat; // Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts // // @public (undocumented) -type ContainsFragmentsRefs = true extends IsAny ? false : TData extends object ? " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs : false; +type ContainsFragmentsRefs = true extends (IsAny) ? false : TData extends object ? Exact extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature ? true : ContainsFragmentsRefs> : false; // @public (undocumented) export const createHttpLink: (linkOptions?: HttpOptions) => ApolloLink; @@ -903,6 +904,9 @@ namespace EntityStore { // @public export type ErrorPolicy = "none" | "ignore" | "all"; +// @public (undocumented) +type Exact = (x: T) => T; + // @public (undocumented) export const execute: typeof ApolloLink.execute; diff --git a/.changeset/chilly-icons-shave.md b/.changeset/chilly-icons-shave.md new file mode 100644 index 0000000000..d550c5a48f --- /dev/null +++ b/.changeset/chilly-icons-shave.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +Data masking: prevent infinite recursion of `ContainsFragmentsRefs` type