Skip to content

Instantly share code, notes, and snippets.

@trxcllnt
Created December 28, 2018 21:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trxcllnt/5b07d265334d97e37bd8a3659a7fc731 to your computer and use it in GitHub Desktop.
Save trxcllnt/5b07d265334d97e37bd8a3659a7fc731 to your computer and use it in GitHub Desktop.
if (typeof ReadableStream === 'undefined') {
(() => {
const mozFetch = require('fetch-readablestream');
const streams = require('@mattiasbuelens/web-streams-polyfill');
const { makeXhrTransport } = require('fetch-readablestream/lib/xhr');
const { createReadableStreamWrapper } = require('@mattiasbuelens/web-streams-adapter');
const toPolyfilledReadableStream = createReadableStreamWrapper(streams.ReadableStream);
const defaultFactory = require('fetch-readablestream/lib/defaultTransportFactory').default;
mozFetch.transportFactory = !supportsXhrResponseType('moz-chunked-arraybuffer') ? defaultFactory :
((transport) => () => transport)(makeXhrTransport({
responseType: 'moz-chunked-arraybuffer',
responseParserFactory() {
return (response) => protectArrayBufferFromWhatwgRefImpl(new Uint8Array(response));
}
}));
window.fetch = async function(...args) {
const res = await mozFetch(...args);
res.body = toPolyfilledReadableStream(res.body);
res.bodyUsed = false;
return res;
};
const kIsFakeBuffer = Symbol.for('isFakeBuffer');
// The Whatwg ReadableByteStream reference implementation[1] copies the
// underlying ArrayBuffer for any TypedArray that passes through it and
// redefines the original's byteLength to be 0, in order to mimic the
// unfinished ArrayBuffer "transfer" spec [2].
//
// This is problematic in node, where a number of APIs (like fs.ReadStream)
// internally allocate and share ArrayBuffers between unrelated operations.
// It's also problematic when using the reference implementation as a polyfill
// in the browser, since it leads to the same bytes being copied at every link
// in a bytestream pipeline.
//
// They do this because there are some web-platform tests that check whether
// byteLength has been set to zero to infer whether the buffer has been
// "transferred". We don't need to care about these tests in production, and
// we also wish to _not_ copy bytes as they pass through a stream, so this
// function fakes out the reference implementation to work around both these
// issues.
//
// 1. https://github.com/whatwg/streams/blob/0ebe4b042e467d9876d80ae045de3843092ad797/reference-implementation/lib/helpers.js#L126
// 2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer
function protectArrayBufferFromWhatwgRefImpl(value) {
const real = value.buffer;
if (!real[kIsFakeBuffer]) {
const fake = Object.create(real);
Object.defineProperty(fake, kIsFakeBuffer, { value: true });
Object.defineProperty(fake, 'slice', { value: () => real });
Object.defineProperty(value, 'buffer', { value: fake });
}
return value;
}
function supportsXhrResponseType(type) {
try {
const tmp = new XMLHttpRequest();
tmp.responseType = type;
return tmp.responseType === type;
} catch (e) {/* IE throws on setting responseType to an unsupported value */}
return false;
}
})();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment