Download static/reader/core/reader-request-manager.js from VoiceOfML/Search: direct link, hf CLI and curl.
- Browser
- Download file 9.78 kB
-
https://huggingface.co/spaces/VoiceOfML/Search/resolve/main/static/reader/core/reader-request-manager.js
- Command line
-
hf download hf://spaces/VoiceOfML/Search/static/reader/core/reader-request-manager.js
-
curl -L -o reader-request-manager.js https://huggingface.co/spaces/VoiceOfML/Search/resolve/main/static/reader/core/reader-request-manager.js
9.78 kB
| (function (root) { | |
| "use strict"; | |
| function createReaderRequestManager(options = {}) { | |
| const fetchImpl = options.fetchImpl || root.fetch.bind(root); | |
| const AbortControllerImpl = options.AbortControllerImpl || root.AbortController; | |
| const setTimer = options.setTimer || root.setTimeout.bind(root); | |
| const clearTimer = options.clearTimer || root.clearTimeout.bind(root); | |
| const initialIdleMs = options.initialIdleMs || 10000; | |
| const pending = new Map(); | |
| const active = new Set(); | |
| let disposed = false; | |
| function settle(record) { | |
| if (record.settled) return; | |
| record.settled = true; | |
| clearTimer(record.timeout); | |
| record.clearAttempt?.(); | |
| record.removeCallerAbort?.(); | |
| active.delete(record); | |
| } | |
| function abort(record, reason) { | |
| if (record.settled) return; | |
| record.controller.abort(reason); | |
| record.abortBody?.(reason); | |
| settle(record); | |
| } | |
| function responseForCaller(record) { | |
| return record.promise.then((response) => { | |
| if (!record.responseClaimed) { | |
| record.responseClaimed = true; | |
| return response; | |
| } | |
| return typeof response?.clone === "function" ? response.clone() : response; | |
| }); | |
| } | |
| function wrapResponse(record, response, sourceReader = null, firstChunk = null) { | |
| const ResponseImpl = root.Response || (typeof Response === "function" ? Response : null); | |
| const ReadableStreamImpl = | |
| root.ReadableStream || (typeof ReadableStream === "function" ? ReadableStream : null); | |
| if (!response?.body?.getReader || !ResponseImpl || !ReadableStreamImpl) { | |
| settle(record); | |
| return response; | |
| } | |
| sourceReader ||= response.body.getReader(); | |
| const stream = new ReadableStreamImpl({ | |
| start(controller) { | |
| record.abortBody = (reason) => { | |
| controller.error(reason); | |
| sourceReader.cancel(reason).catch(() => {}); | |
| }; | |
| }, | |
| async pull(controller) { | |
| try { | |
| const result = firstChunk || await sourceReader.read(); | |
| firstChunk = null; | |
| if (record.settled) return; | |
| if (result.done) { | |
| settle(record); | |
| controller.close(); | |
| } else { | |
| controller.enqueue(result.value); | |
| } | |
| } catch (error) { | |
| if (record.settled) return; | |
| settle(record); | |
| controller.error(error); | |
| } | |
| }, | |
| cancel(reason) { | |
| settle(record); | |
| return sourceReader.cancel(reason); | |
| } | |
| }); | |
| return new ResponseImpl(stream, { | |
| status: response.status, | |
| statusText: response.statusText, | |
| headers: response.headers | |
| }); | |
| } | |
| function request(url, timeoutMs, requestInit = {}, bufferLimit = null) { | |
| if (disposed) return Promise.reject(new DOMException("Reader disposed", "AbortError")); | |
| const callerSignal = requestInit.signal; | |
| if (callerSignal?.aborted) return Promise.reject(callerSignal.reason); | |
| // Share plain GETs only. Other options can change the body, validators, | |
| // range or cancellation owner even when the URL is identical. | |
| const shareable = typeof url === "string" && Object.keys(requestInit).every((key) => key === "priority"); | |
| const key = shareable ? JSON.stringify([String(url), timeoutMs, bufferLimit]) : {}; | |
| if (pending.has(key)) return responseForCaller(pending.get(key)); | |
| const controller = new AbortControllerImpl(); | |
| const recoverInitial = typeof url === "string" && timeoutMs > initialIdleMs * 2 && | |
| Object.keys(requestInit).every(key => key === "priority" || key === "signal"); | |
| const record = { | |
| controller, | |
| timeout: null, | |
| promise: null, | |
| responseClaimed: false, | |
| settled: false, | |
| abortBody: null | |
| }; | |
| async function open() { | |
| for (let attempt = 0; ; attempt++) { | |
| controller.signal.throwIfAborted(); | |
| const transport = new AbortControllerImpl(); | |
| let idle, sourceReader = null; | |
| const cancel = () => transport.abort(controller.signal.reason); | |
| controller.signal.addEventListener("abort", cancel, { once: true }); | |
| record.clearAttempt = () => { | |
| clearTimer(idle); | |
| controller.signal.removeEventListener("abort", cancel); | |
| }; | |
| const arm = () => { | |
| clearTimer(idle); | |
| if (recoverInitial && attempt === 0) idle = setTimer(() => transport.abort( | |
| new DOMException("Reader initial response stalled", "TimeoutError") | |
| ), initialIdleMs); | |
| }; | |
| const owned = (promise, onLate) => new Promise((resolve, reject) => { | |
| const signal = transport.signal; | |
| const aborted = () => reject(signal.reason); | |
| signal.addEventListener("abort", aborted, { once: true }); | |
| if (signal.aborted) aborted(); | |
| Promise.resolve(promise).then(value => { | |
| if (signal.aborted) onLate?.(value); | |
| else resolve(value); | |
| }, reject).finally(() => signal.removeEventListener("abort", aborted)); | |
| }); | |
| try { | |
| arm(); | |
| const response = await owned(fetchImpl(url, { ...requestInit, | |
| ...(attempt ? { cache: "reload" } : {}), signal: transport.signal }), | |
| response => response.body?.cancel(transport.signal.reason).catch(() => {})); | |
| let firstChunk = null; | |
| // Bounded metadata is unpublished until EOF, so a failed body can | |
| // be replaced in full without replaying any caller-visible bytes. | |
| if (bufferLimit !== null && response.ok && response.body?.getReader) { | |
| const tooLarge = () => Object.assign(new Error("READER_RESOURCE_LIMIT"), {code:"READER_RESOURCE_LIMIT"}); | |
| if (Number(response.headers.get("Content-Length")) > bufferLimit) { | |
| response.body.cancel().catch(() => {}); | |
| throw tooLarge(); | |
| } | |
| sourceReader = response.body.getReader(); | |
| const chunks = []; | |
| let length = 0; | |
| while (true) { | |
| arm(); | |
| const chunk = await owned(sourceReader.read()); | |
| if (chunk.done) break; | |
| length += chunk.value.byteLength; | |
| if (length > bufferLimit) throw tooLarge(); | |
| chunks.push(chunk.value); | |
| } | |
| controller.signal.throwIfAborted(); | |
| sourceReader.releaseLock(); | |
| sourceReader = null; | |
| const bytes = new Uint8Array(length); | |
| let offset = 0; | |
| for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; } | |
| const complete = new root.Response(bytes, { | |
| status:response.status, statusText:response.statusText, headers:response.headers | |
| }); | |
| settle(record); | |
| return complete; | |
| } | |
| // Do not publish headers from a stalled attempt: a restart can then | |
| // replace the entire response without mixing versions or body bytes. | |
| if (recoverInitial && response.ok && response.body?.getReader) { | |
| sourceReader = response.body.getReader(); | |
| arm(); | |
| firstChunk = await owned(sourceReader.read()); | |
| } | |
| clearTimer(idle); | |
| controller.signal.throwIfAborted(); | |
| return wrapResponse(record, response, sourceReader, firstChunk); | |
| } catch (error) { | |
| record.clearAttempt(); | |
| transport.abort(error); | |
| if (sourceReader) { | |
| const reader = sourceReader; | |
| reader.cancel(error).catch(() => {}).finally(() => reader.releaseLock()); | |
| } | |
| controller.signal.throwIfAborted(); | |
| if (!recoverInitial || attempt || !["TimeoutError", "TypeError"].includes(error?.name)) throw error; | |
| } | |
| } | |
| } | |
| if (callerSignal) { | |
| const onAbort = () => abort(record, callerSignal.reason); | |
| callerSignal.addEventListener("abort", onAbort, { once: true }); | |
| record.removeCallerAbort = () => callerSignal.removeEventListener("abort", onAbort); | |
| } | |
| record.timeout = setTimer( | |
| () => abort(record, new DOMException("Reader request timed out", "TimeoutError")), | |
| timeoutMs | |
| ); | |
| active.add(record); | |
| record.promise = Promise.resolve() | |
| .then(open) | |
| .catch((error) => { | |
| settle(record); | |
| controller.signal.throwIfAborted(); | |
| throw error; | |
| }) | |
| .finally(() => { | |
| if (pending.get(key) === record) pending.delete(key); | |
| }); | |
| pending.set(key, record); | |
| return responseForCaller(record); | |
| } | |
| function dispose() { | |
| if (disposed) return; | |
| disposed = true; | |
| for (const record of active) abort(record, new DOMException("Reader disposed", "AbortError")); | |
| pending.clear(); | |
| } | |
| return Object.freeze({ | |
| request, | |
| requestBuffered(url, timeoutMs, limit, requestInit = {}) { | |
| if (!Number.isSafeInteger(limit) || limit < 0) return Promise.reject(new RangeError("Invalid response limit")); | |
| return request(url, timeoutMs, requestInit, limit); | |
| }, | |
| dispose, | |
| get pendingCount() { | |
| return pending.size; | |
| }, | |
| get activeCount() { | |
| return active.size; | |
| }, | |
| get disposed() { | |
| return disposed; | |
| } | |
| }); | |
| } | |
| root.VoiceOfMLReaderRequests = Object.freeze({ createReaderRequestManager }); | |
| })(typeof self !== "undefined" ? self : globalThis); | |