GM_fetch
code:scrapbox.user.js
// ==UserScript==
// @name GM_fetch
// @version 0.1.7
// @description An implementation of the fetch API which leverages GM_xmlhttpRequest
// @author takker
// @connect *
// @grant GM_xmlhttpRequest
// @license MIT
// @copyright Copyright (c) 2023 takker
// ==/UserScript==
var u=i=>new Headers(i.replace(/\r?\n\t +/g," ").split(/\r\n|\r|\n/).flatMap(n=>{letr,t=n.split(":").map(e=>e.trim());return r?r,t:[]})),l=(i,n)=>new Promise((r,t)=>{let e=new Request(i,n),s=Object.fromEntries(e.headers.entries());if(n?.referrer&&(s.Referer=n.referrer),e.signal?.aborted){t(new DOMException("Aborted","AbortError"));return}let{abort:a}=GM_xmlhttpRequest({method:e.method,url:e.url,headers:s,...n?.body?{data:n.body}:{},anonymous:e.credentials==="omit",responseType:"stream",onerror:()=>{t(new TypeError("Network request failed"))},ontimeout:()=>{t(new TypeError("Network request timeout"))},onabort:()=>{t(new DOMException("Aborted","AbortError"))},onreadystatechange:o=>{switch(o.readyState){case 2:{let d=new Response(o.response,{status:o.status,statusText:o.statusText,headers:u(o.responseHeaders)});Object.defineProperty(d,"url",{value:o.finalUrl}),r(d);break}case 4:e.signal?.removeEventListener?.("abort",a);break;default:break}}});e.signal?.addEventListener?.("abort",a)});unsafeWindow.GM_fetch=l;