From 875a5fa8272fe635cfac9a82d7769a6d52702b4d Mon Sep 17 00:00:00 2001 From: Gefei Hou Date: Mon, 11 May 2026 00:13:51 -0700 Subject: [PATCH 1/3] Fix global fetch this issue --- graphql/codegen/src/core/codegen/templates/orm-client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql/codegen/src/core/codegen/templates/orm-client.ts b/graphql/codegen/src/core/codegen/templates/orm-client.ts index ab9c99ced..d7c5c578f 100644 --- a/graphql/codegen/src/core/codegen/templates/orm-client.ts +++ b/graphql/codegen/src/core/codegen/templates/orm-client.ts @@ -63,7 +63,7 @@ export class FetchAdapter implements GraphQLAdapter { fetchFn?: typeof globalThis.fetch, ) { this.headers = headers ?? {}; - this.fetchFn = fetchFn ?? createFetch(); + this.fetchFn = (fetchFn ?? createFetch()).bind(globalThis); } async execute( From db5ba45a52b8ace72dc90b7e9240da97ef88f0e8 Mon Sep 17 00:00:00 2001 From: Gefei Hou Date: Mon, 11 May 2026 00:18:20 -0700 Subject: [PATCH 2/3] Update snapshot --- .../codegen/__snapshots__/client-generator.test.ts.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap b/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap index a088b8860..41c85c7c3 100644 --- a/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap +++ b/graphql/codegen/src/__tests__/codegen/__snapshots__/client-generator.test.ts.snap @@ -159,7 +159,7 @@ export class FetchAdapter implements GraphQLAdapter { fetchFn?: typeof globalThis.fetch, ) { this.headers = headers ?? {}; - this.fetchFn = fetchFn ?? createFetch(); + this.fetchFn = (fetchFn ?? createFetch()).bind(globalThis); } async execute( From d18c0429917762fd70f9cb232134b11f1787494f Mon Sep 17 00:00:00 2001 From: Gefei Hou Date: Mon, 11 May 2026 00:51:27 -0700 Subject: [PATCH 3/3] Added test case --- .../codegen/client-generator.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts index a2526c8b9..2badd5af4 100644 --- a/graphql/codegen/src/__tests__/codegen/client-generator.test.ts +++ b/graphql/codegen/src/__tests__/codegen/client-generator.test.ts @@ -76,6 +76,34 @@ describe('client-generator', () => { ); expect(result.content).toContain('createFetch()'); }); + + it('binds fetchFn to globalThis to avoid Illegal invocation in browsers', () => { + const result = generateOrmClientFile(); + + // The generated FetchAdapter must .bind(globalThis) to prevent + // "Illegal invocation" when native window.fetch is stored as + // an instance property (which detaches it from its original this). + expect(result.content).toContain('.bind(globalThis)'); + }); + + it('bind(globalThis) prevents Illegal invocation for this-sensitive fetch', () => { + // Simulate a native browser fetch that requires this === globalThis + // (calling window.fetch with any other this throws TypeError) + function thisSensitiveFetch(this: unknown): Promise { + if (this !== globalThis) { + throw new TypeError('Illegal invocation'); + } + return Promise.resolve(new Response(JSON.stringify({ data: null }))); + } + + // Without bind: storing on an object and calling detaches this + const broken = { fetchFn: thisSensitiveFetch }; + expect(() => broken.fetchFn()).toThrow('Illegal invocation'); + + // With bind: the pattern used in FetchAdapter keeps correct this + const fixed = { fetchFn: thisSensitiveFetch.bind(globalThis) }; + expect(() => fixed.fetchFn()).not.toThrow(); + }); }); describe('generateQueryBuilderFile', () => {