UNPKG

mock-violentmonkey

Version:

Mock violentmonkey's globals for testing userscripts

65 lines 2.42 kB
import { Buffer } from 'node:buffer'; import { VMStorage } from '../vm-storage.js'; import { GM_xmlhttpRequest } from './xmlhttprequest.js'; const downloads = new VMStorage(() => new Map()); const download = (options, name) => { const options_ = typeof options === 'string' ? { url: options, name: name, } : options; const { url, name: name_ } = options_; if (typeof url !== 'string') { throw new TypeError('Expected url to be a string.'); } if (typeof name_ !== 'string') { throw new TypeError('Expected name to be a string.'); } // This is a fix for a race condition where onloadend is called before onload // Because all event handlers but onload were passed without any modification // this caused a race condition // Our onload was called. Because it is async, onloadend was called, before we could call options_.onload // To fix this, we intercept that call and call onloadend when we're ready // For errors, we call it right away // For onload, we wait until the buffer is loaded and then call their onload and then onloadend function overrideError(name) { return function (response) { void options_[`on${name}`]?.(response); void options_.onloadend?.(response); }; } GM_xmlhttpRequest({ ...options_, url, responseType: 'blob', async onload(response) { const blob = response.response; const buffer = Buffer.from(await blob.arrayBuffer()); downloads.get(true).set(name_, buffer); void options_.onload?.(response); void options_.onloadend?.(response); }, onloadend() { }, onerror: overrideError('error'), onabort: overrideError('abort'), ontimeout: overrideError('timeout'), }); }; const getDownloads = () => { const downloadsMap = downloads.get(false); const result = {}; for (const [name, buffer] of downloadsMap ?? []) { result[name] = Buffer.from(buffer); } return result; }; const getDownload = (name) => { const buffer = downloads.get(false)?.get(name); return buffer && Buffer.from(buffer); }; export { download as GM_download, getDownloads, getDownload }; Object.defineProperty(globalThis, 'GM_download', { value: download, }); //# sourceMappingURL=download.js.map