Skip to content
Merged
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
26 changes: 17 additions & 9 deletions packages/utils/src/supports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ export function supportsFetch(): boolean {
return false;
}
}
/**
* isNativeFetch checks if the given function is a native implementation of fetch()
*/
function isNativeFetch(func: Function): boolean {
return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
}


/**
* Tells whether current environment supports Fetch API natively
Expand All @@ -88,30 +95,31 @@ export function supportsNativeFetch(): boolean {
return false;
}

const isNativeFunc = (func: Function) => func.toString().indexOf('native') !== -1;
const global = getGlobalObject<Window>();
let result = null;

// Fast path to avoid DOM I/O
if (isNativeFetch(global.fetch)) {
return true;
}

// window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
// so create a "pure" iframe to see if that has native fetch
let result = false;
const doc = global.document;
if (doc) {
const sandbox = doc.createElement('iframe');
sandbox.hidden = true;
try {
doc.head.appendChild(sandbox);
if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
// tslint:disable-next-line no-unbound-method
result = isNativeFunc(sandbox.contentWindow.fetch);
result = isNativeFetch(sandbox.contentWindow.fetch);
}
doc.head.removeChild(sandbox);
} catch (err) {
logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
}
}

if (result === null) {
// tslint:disable-next-line no-unbound-method
result = isNativeFunc(global.fetch);
}

return result;
}

Expand Down