fix(frontend): binder le fetch global à globalThis (pairing Firefox) (#13)
Firefox exige que fetch soit appelé sur Window : passer la référence nue `fetch` en dépendance déclenchait « 'fetch' called on an object that does not implement interface Window » au pairing. Nouveau helper defaultFetch() qui binde globalThis.fetch, utilisé par webSession. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -41,6 +41,29 @@ export type FetchLike = (
|
||||
text(): Promise<string>;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Resolves the default `fetch`, **bound to `globalThis`**.
|
||||
*
|
||||
* WHATWG `fetch` is a method of the global object and checks its receiver: once
|
||||
* stored in a field and called as `this.fetchImpl(…)`, its `this` is the owning
|
||||
* adapter instance, not `window`. A real browser rejects that — Firefox with
|
||||
* `TypeError: 'fetch' called on an object that does not implement interface
|
||||
* Window`, Chrome with "Illegal invocation". jsdom does not enforce the receiver,
|
||||
* so the unit tests never caught it; the bind is what keeps the fallback callable
|
||||
* from a field. An *injected* `fetchImpl` is left untouched (a test stub is a
|
||||
* plain function and needs no receiver).
|
||||
*
|
||||
* When there is no global `fetch` (SSR / bare Node), the value is returned as-is
|
||||
* so the failure still happens at call time, exactly as before, rather than
|
||||
* throwing during construction.
|
||||
*/
|
||||
export function defaultFetch(): FetchLike {
|
||||
const globalFetch = globalThis.fetch;
|
||||
return (
|
||||
typeof globalFetch === "function" ? globalFetch.bind(globalThis) : globalFetch
|
||||
) as unknown as FetchLike;
|
||||
}
|
||||
|
||||
/** Configuration for the HTTP invoker. */
|
||||
export interface HttpInvokerConfig {
|
||||
/** Absolute base URL of the backend, e.g. `https://host:port`. No trailing slash. */
|
||||
@ -85,10 +108,8 @@ export class HttpInvoker {
|
||||
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
||||
this.token = config.token;
|
||||
this.onUnauthorized = config.onUnauthorized;
|
||||
// `globalThis.fetch` exists in the browser (and jsdom); the cast narrows it
|
||||
// to the minimal shape used here.
|
||||
this.fetchImpl =
|
||||
config.fetchImpl ?? (globalThis.fetch as unknown as FetchLike);
|
||||
// The global fallback must stay bound to `globalThis` — see `defaultFetch`.
|
||||
this.fetchImpl = config.fetchImpl ?? defaultFetch();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user