LCOV - code coverage report
Current view: top level - lib - whatwg-xhr.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 3213 3260 98.6 %
Date: 2025-01-24 02:02:48 Functions: 85 89 95.5 %
Branches: 390 449 86.9 %

           Branch data     Line data    Source code
       1            [ + ]:        229 : /**
       2                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
       3                 :        229 :  * url: https://xhr.spec.whatwg.org/
       4                 :        229 :  *
       5                 :        229 :  * class XMLHttpRequestEventTarget extends EventTarget
       6                 :        229 :  * class XMLHttpRequestUpload      extends XMLHttpRequestEventTarget
       7                 :        229 :  * const XMLHttpRequestResponseType
       8                 :        229 :  * export class XMLHttpRequest extends XMLHttpRequestEventTarget
       9                 :        229 :  * export class ProgressEvent  extends Event
      10                 :        229 :  * export class FormData
      11                 :        229 :  *
      12                 :        229 :  * function makeEntry
      13                 :        229 :  * function readBlobSync
      14                 :        229 :  * function handleError
      15                 :        229 :  * function requestErrorSteps
      16                 :        229 :  * function setResponseToNetworkError
      17                 :        229 :  *
      18                 :        229 :  * function getResponseMimeType
      19                 :        229 :  * function getFinalMimeType
      20                 :        229 :  * function getFinalEncoding
      21                 :        229 :  * function setDocumentResponse
      22                 :        229 :  * function getTextResponse
      23                 :        229 :  *
      24                 :        229 :  * class ClientRequestData
      25                 :        229 :  * function requestDataURL
      26                 :        229 :  *
      27                 :        229 :  * @module  whatwg-xhr
      28                 :        229 :  * @desc    Main module - A Node.js implementation of the {@link https://xhr.spec.whatwg.org/ WHATWG XMLHttpRequest Living Standard} for non-browser environments.
      29                 :        229 :  * @version 1.0.0
      30                 :        229 :  * @author  Essam A. El-Sherif
      31                 :        229 :  */
      32                 :        229 : 
      33                 :        229 : /* Import nodeJS core modules */
      34                 :        229 : import fs                  from 'node:fs';
      35                 :        229 : import http                from 'node:http';
      36                 :        229 : import https               from 'node:https';
      37                 :        229 : import process             from 'node:process';
      38                 :        229 : import threads             from 'node:worker_threads';
      39                 :        229 : import { spawn, spawnSync} from 'node:child_process';
      40                 :        229 : import { dirname }         from 'node:path';
      41                 :        229 : import { fileURLToPath }   from 'node:url';
      42                 :        229 : import { Readable }        from 'node:stream';
      43                 :        229 : 
      44                 :        229 : /**
      45                 :        229 :  * Global object available in all node modules >= v17.0.0
      46                 :        229 :  *
      47                 :        229 :  * DOMException  Added in: node v17.0.0
      48                 :        229 :  *
      49                 :        229 :  * @external DOMException
      50                 :        229 :  * @desc Global object available in all node modules >= v17.0.0, defined by {@link https://webidl.spec.whatwg.org/#idl-DOMException WHATWG IDL Living Standard} and implemented by {@link https://nodejs.org/docs/latest/api/globals.html#domexception node.js}.
      51                 :        229 :  */
      52                 :        229 : 
      53                 :        229 : /**
      54                 :        229 :  * Global object available in all node modules >= v15.4.0.
      55                 :        229 :  *
      56                 :        229 :  * @interface EventTarget
      57                 :        229 :  * @desc A browser-compatible implementation of the EventTarget class, defined by {@link https://dom.spec.whatwg.org/#eventtarget WHATWG DOM Living Standard} and implemented by {@link https://nodejs.org/docs/latest/api/globals.html#eventtarget node.js}.
      58                 :        229 :  */
      59                 :        229 : 
      60                 :        229 : /**
      61                 :        229 :  * Global object available in all node modules >= v15.4.0.
      62                 :        229 :  *
      63                 :        229 :  * @interface Event
      64                 :        229 :  * @desc A browser-compatible implementation of the Event class, defined by {@link https://dom.spec.whatwg.org/#event WHATWG DOM Living Standard} and implemented by {@link https://nodejs.org/docs/latest/api/globals.html#event node.js}.
      65                 :        229 :  */
      66                 :        229 : 
      67                 :        229 : /* Import npm-packages dependencies */
      68                 :        229 : import whatwgEncoding      from 'whatwg-encoding';
      69                 :        229 : import htmlEncodingSniffer from 'html-encoding-sniffer';
      70                 :        229 : 
      71                 :        229 : /* Import from local helper modules */
      72                 :        229 : import {
      73                 :        229 :         parse  as contentTypeParse,
      74                 :        229 :         format as contentTypeFormat
      75                 :        229 : } from './helper/content-type.js';
      76                 :        229 : 
      77                 :        229 : import {
      78                 :        229 :         dataURLProcessor,
      79                 :        229 :         parseMIMEType,
      80                 :        229 :         serializeAMimeType
      81                 :        229 : } from './helper/whatwg-misc.js';
      82                 :        229 : 
      83                 :        229 : import {
      84                 :        229 :         forbiddenRequestHeader,
      85                 :        229 :         forbiddenHttpRequestMethod,
      86                 :        229 :         safelyExtractBodyWithType
      87                 :        229 : } from './helper/whatwg-fetch.js';
      88                 :        229 : 
      89                 :        229 : import {
      90                 :        229 :         xmlEncodingSniffer
      91                 :        229 : } from './helper/xml-encoding-sniffer.js';
      92                 :        229 : 
      93                 :        229 : import {
      94                 :        229 :         File as FilePolyfill
      95                 :        229 : } from './helper/file-polyfill.js';
      96                 :        229 : 
      97                 :        229 : /* Emulate commonJS __filename & __dirname global constants */
      98                 :        229 : const __filename = fileURLToPath(import.meta.url);
      99                 :        229 : const __dirname  = dirname(__filename);
     100                 :        229 : 
     101                 :        229 : /**
     102                 :        229 :  * Global object added in node modules v20.0.0.
     103                 :        229 :  *
     104                 :        229 :  * @const {object} File
     105                 :        229 :  * @desc  The File interface provides information about files and allows JavaScript in a web page to access their content.
     106                 :        229 :  * @see   module:file-polyfill.File
     107                 :        229 :  */
     108                 :        229 : const File = FilePolyfill;
     109                 :        229 : 
     110                 :        229 : /**
     111                 :        229 :  * @const {boolean} disableHeaderCheck
     112                 :        229 :  * @static
     113                 :        229 :  * @desc  Allow request-headers forbidden by {@link https://xhr.spec.whatwg.org/ XHR Specs}.
     114                 :        229 :  */
     115                 :        229 : export const disableHeaderCheck = false;
     116                 :        229 : 
     117                 :        229 : /**
     118                 :        229 :  * @func   defaultHeaders
     119                 :        229 :  * @return {object} Default headers to include in each XMLHttpRequest.
     120                 :        229 :  */
     121            [ + ]:        229 : const defaultHeaders = () => ({
     122                 :       2970 :         'User-Agent' : 'whatwg-xhr',
     123                 :       2970 :         'Accept': '*/*',
     124                 :       2970 :         'Accept-Language': 'en-US,en;q=0.5'
     125                 :        229 : });
     126                 :        229 : /****/
     127                 :        229 : 
     128                 :        229 : /** @const {WeakMap} xmlHttpRequestEventTarget - Map any XMLHttpRequestEventTarget object created to an associated data object. */
     129                 :        229 : const xmlHttpRequestEventTarget = new WeakMap();
     130                 :        229 : 
     131                 :        229 : /** @const {WeakMap} xmlHttpRequest - Map any XMLHttpRequest object created to an associated data object. */
     132                 :        229 : const xmlHttpRequest = new WeakMap();
     133                 :        229 : 
     134                 :        229 : /** @const {WeakMap} progressEvent - Map any ProgressEvent object created to an associated data object. */
     135                 :        229 : const progressEvent = new WeakMap();
     136                 :        229 : 
     137                 :        229 : /** @const {WeakMap} formData - Map any FormData object created to an associated data object. */
     138                 :        229 : const formData  = new WeakMap();
     139                 :        229 : 
     140                 :        229 : let allowXMLHttpRequestUploadConstructor = false;
     141                 :        229 : 
     142                 :        229 : /**
     143                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     144                 :        229 :  * url: https://xhr.spec.whatwg.org/#interface-xmlhttprequest
     145                 :        229 :  *
     146                 :        229 :  * interface XMLHttpRequestEventTarget : EventTarget{
     147                 :        229 :  *   // event handlers
     148                 :        229 :  *   attribute EventHandler onloadstart;
     149                 :        229 :  *   attribute EventHandler onprogress;
     150                 :        229 :  *   attribute EventHandler onabort;
     151                 :        229 :  *   attribute EventHandler onerror;
     152                 :        229 :  *   attribute EventHandler onload;
     153                 :        229 :  *   attribute EventHandler ontimeout;
     154                 :        229 :  *   attribute EventHandler onloadend;
     155                 :        229 :  * };
     156                 :        229 :  *
     157                 :        229 :  * @class     XMLHttpRequestEventTarget
     158                 :        229 :  * @extends   module:whatwg-xhr~EventTarget
     159                 :        229 :  * @desc      Interface that describes the event handlers shared on XMLHttpRequest and XMLHttpRequestUpload interfaces.
     160                 :        229 :  */
     161                 :        229 : class XMLHttpRequestEventTarget extends EventTarget{
     162            [ + ]:        229 :         constructor(){
     163                 :       1506 :                 super();
     164                 :       1506 : 
     165                 :       1506 :                 const eventHandlers = {};
     166                 :       1506 : 
     167                 :       1506 :                 eventHandlers['onloadstart'] = null;    // xhr.spec. attribute EventHandler
     168                 :       1506 :                 eventHandlers['onprogress' ] = null;    // xhr.spec. attribute EventHandler
     169                 :       1506 :                 eventHandlers['onabort'    ] = null;    // xhr.spec. attribute EventHandler
     170                 :       1506 :                 eventHandlers['onerror'    ] = null;    // xhr.spec. attribute EventHandler
     171                 :       1506 :                 eventHandlers['onload'     ] = null;    // xhr.spec. attribute EventHandler
     172                 :       1506 :                 eventHandlers['ontimeout'  ] = null;    // xhr.spec. attribute EventHandler
     173                 :       1506 :                 eventHandlers['onloadend'  ] = null;    // xhr.spec. attribute EventHandler
     174                 :       1506 : 
     175                 :       1506 :                 // Map any XMLHttpRequestEventTarget object created to an associated data object.
     176                 :       1506 :                 xmlHttpRequestEventTarget.set(this, eventHandlers);
     177                 :       1506 :         }
     178                 :        229 : 
     179                 :        229 :         /**
     180                 :        229 :          * @member   {function} onloadstart
     181                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     182                 :        229 :          * @instance
     183                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'loadstart' event is emitted.
     184                 :        229 :          */
     185            [ + ]:        229 :         get onloadstart(){ return xmlHttpRequestEventTarget.get(this)['onloadstart']; }
     186                 :        229 : 
     187            [ + ]:        229 :         set onloadstart(callback){
     188                 :        248 :                 this.removeEventListener('loadstart', xmlHttpRequestEventTarget.get(this)['onloadstart']);
     189                 :        248 :                 xmlHttpRequestEventTarget.get(this)['onloadstart'] = null;
     190                 :        248 : 
     191            [ + ]:        248 :                 if(typeof callback === 'function'){
     192                 :         32 :                         this.addEventListener('loadstart', callback);
     193                 :         32 :                         xmlHttpRequestEventTarget.get(this)['onloadstart'] = callback;
     194                 :         32 :                 }
     195                 :        248 :         }
     196                 :        229 : 
     197                 :        229 :         /**
     198                 :        229 :          * @member   {function} onprogress
     199                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     200                 :        229 :          * @instance
     201                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'progress' event is emitted.
     202                 :        229 :          */
     203            [ + ]:        229 :         get onprogress(){ return xmlHttpRequestEventTarget.get(this)['onprogress']; }
     204                 :        229 : 
     205            [ + ]:        229 :         set onprogress(callback){
     206                 :        135 :                 this.removeEventListener('progress', xmlHttpRequestEventTarget.get(this)['onprogress']);
     207                 :        135 :                 xmlHttpRequestEventTarget.get(this)['onprogress'] = null;
     208                 :        135 : 
     209            [ + ]:        135 :                 if(typeof callback === 'function'){
     210                 :         19 :                         this.addEventListener('progress', callback);
     211                 :         19 :                         xmlHttpRequestEventTarget.get(this)['onprogress'] = callback;
     212                 :         19 :                 }
     213                 :        135 :         }
     214                 :        229 : 
     215                 :        229 :         /**
     216                 :        229 :          * @member   {function} onabort
     217                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     218                 :        229 :          * @instance
     219                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'abort' event is emitted.
     220                 :        229 :          */
     221            [ + ]:        229 :         get onabort(){ return xmlHttpRequestEventTarget.get(this)['onabort']; }
     222                 :        229 : 
     223            [ + ]:        229 :         set onabort(callback){
     224                 :        105 :                 this.removeEventListener('abort', xmlHttpRequestEventTarget.get(this)['onabort']);
     225                 :        105 :                 xmlHttpRequestEventTarget.get(this)['onabort'] = null;
     226                 :        105 : 
     227            [ + ]:        105 :                 if(typeof callback === 'function'){
     228                 :          3 :                         this.addEventListener('abort', callback);
     229                 :          3 :                         xmlHttpRequestEventTarget.get(this)['onabort'] = callback;
     230                 :          3 :                 }
     231                 :        105 :         }
     232                 :        229 : 
     233                 :        229 :         /**
     234                 :        229 :          * @member   {function} onerror
     235                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     236                 :        229 :          * @instance
     237                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'error' event is emitted.
     238                 :        229 :          */
     239            [ + ]:        229 :         get onerror(){ return xmlHttpRequestEventTarget.get(this)['onerror']; }
     240                 :        229 : 
     241            [ + ]:        229 :         set onerror(callback){
     242                 :        357 :                 this.removeEventListener('error', xmlHttpRequestEventTarget.get(this)['onerror']);
     243                 :        357 :                 xmlHttpRequestEventTarget.get(this)['onerror'] = null;
     244                 :        357 : 
     245            [ + ]:        357 :                 if(typeof callback === 'function'){
     246                 :         32 :                         this.addEventListener('error', callback);
     247                 :         32 :                         xmlHttpRequestEventTarget.get(this)['onerror'] = callback;
     248                 :         32 :                 }
     249                 :        357 :         }
     250                 :        229 : 
     251                 :        229 :         /**
     252                 :        229 :          * @member   {function} onload
     253                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     254                 :        229 :          * @instance
     255                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'load' event is emitted.
     256                 :        229 :          */
     257            [ + ]:        229 :         get onload(){ return xmlHttpRequestEventTarget.get(this)['onload']; }
     258                 :        229 : 
     259            [ + ]:        229 :         set onload(callback){
     260                 :        409 :                 this.removeEventListener('load', xmlHttpRequestEventTarget.get(this)['onload']);
     261                 :        409 :                 xmlHttpRequestEventTarget.get(this)['onload'] = null;
     262                 :        409 : 
     263            [ + ]:        409 :                 if(typeof callback === 'function'){
     264                 :         71 :                         this.addEventListener('load', callback);
     265                 :         71 :                         xmlHttpRequestEventTarget.get(this)['onload'] = callback;
     266                 :         71 :                 }
     267                 :        409 :         }
     268                 :        229 : 
     269                 :        229 :         /**
     270                 :        229 :          * @member   {function} ontimeout
     271                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     272                 :        229 :          * @instance
     273                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'timeout' event is emitted.
     274                 :        229 :          */
     275            [ + ]:        229 :         get ontimeout(){ return xmlHttpRequestEventTarget.get(this)['ontimeout']; }
     276                 :        229 : 
     277            [ + ]:        229 :         set ontimeout(callback){
     278                 :        106 :                 this.removeEventListener('timeout', xmlHttpRequestEventTarget.get(this)['ontimeout']);
     279                 :        106 :                 xmlHttpRequestEventTarget.get(this)['ontimeout'] = null;
     280                 :        106 : 
     281            [ + ]:        106 :                 if(typeof callback === 'function'){
     282                 :          3 :                         this.addEventListener('timeout', callback);
     283                 :          3 :                         xmlHttpRequestEventTarget.get(this)['ontimeout'] = callback;
     284                 :          3 :                 }
     285                 :        106 :         }
     286                 :        229 : 
     287                 :        229 :         /**
     288                 :        229 :          * @member   {function} onloadend
     289                 :        229 :          * @memberof module:whatwg-xhr~XMLHttpRequestEventTarget
     290                 :        229 :          * @instance
     291                 :        229 :          * @desc     Get/Set the event handler fired whenever the 'loadend' event is emitted.
     292                 :        229 :          */
     293            [ + ]:        229 :         get onloadend(){ return xmlHttpRequestEventTarget.get(this)['onloadend']; }
     294                 :        229 : 
     295            [ + ]:        229 :         set onloadend(callback){
     296                 :        383 :                 this.removeEventListener('loadend', xmlHttpRequestEventTarget.get(this)['onloadend']);
     297                 :        383 :                 xmlHttpRequestEventTarget.get(this)['onloadend'] = null;
     298                 :        383 : 
     299            [ + ]:        383 :                 if(typeof callback === 'function'){
     300                 :         43 :                         this.addEventListener('loadend', callback);
     301                 :         43 :                         xmlHttpRequestEventTarget.get(this)['onloadend'] = callback;
     302                 :         43 :                 }
     303                 :        383 :         }
     304                 :        229 : }
     305                 :        229 : 
     306                 :        229 : /**
     307                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     308                 :        229 :  * url: https://xhr.spec.whatwg.org/#interface-xmlhttprequest
     309                 :        229 :  *
     310                 :        229 :  * interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
     311                 :        229 :  * };
     312                 :        229 :  *
     313                 :        229 :  * @class     XMLHttpRequestUpload
     314                 :        229 :  * @extends   module:whatwg-xhr~XMLHttpRequestEventTarget
     315                 :        229 :  * @desc      Interface that represents the upload process for a specific XMLHttpRequest.
     316                 :        229 :  */
     317                 :        229 : class XMLHttpRequestUpload extends XMLHttpRequestEventTarget{
     318            [ + ]:        229 :         constructor(){
     319                 :        753 :                 super();
     320                 :        753 :                 if(!allowXMLHttpRequestUploadConstructor)
     321            [ - ]:        753 :                         throw new TypeError(`Illegal constructor.`);
     322                 :        753 :         }
     323                 :        229 : }
     324                 :        229 : 
     325                 :        229 : /**
     326                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     327                 :        229 :  * url: https://xhr.spec.whatwg.org/#interface-xmlhttprequest
     328                 :        229 :  *
     329                 :        229 :  * enum XMLHttpRequestResponseType{
     330                 :        229 :  *   "",
     331                 :        229 :  *   "arraybuffer",
     332                 :        229 :  *   "blob",
     333                 :        229 :  *   "document",
     334                 :        229 :  *   "json",
     335                 :        229 :  *   "text"
     336                 :        229 :  * };
     337                 :        229 :  *
     338                 :        229 :  * @const    {object} XMLHttpRequestResponseType
     339                 :        229 :  * @readonly
     340                 :        229 :  * @desc     Enumerated set of response types.
     341                 :        229 :  */
     342                 :        229 : const XMLHttpRequestResponseType = {
     343                 :        229 :         '': null,
     344                 :        229 :         'arraybuffer': null,
     345                 :        229 :         'blob': null,
     346                 :        229 :         'document': null,
     347                 :        229 :         'json': null,
     348                 :        229 :         'text': null,
     349                 :        229 : };
     350                 :        229 : 
     351                 :        229 : Object.preventExtensions(XMLHttpRequestResponseType);
     352                 :        229 : Object.freeze(XMLHttpRequestResponseType);
     353                 :        229 : 
     354                 :        229 : /**
     355                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     356                 :        229 :  * url: https://xhr.spec.whatwg.org/#interface-xmlhttprequest
     357                 :        229 :  *
     358                 :        229 :  * interface XMLHttpRequest : XMLHttpRequestEventTarget{
     359                 :        229 :  *   constructor();
     360                 :        229 :  *
     361                 :        229 :  *   // event handler
     362                 :        229 :  *   attribute EventHandler onreadystatechange;
     363                 :        229 :  *
     364                 :        229 :  *   // states
     365                 :        229 :  *   const unsigned short UNSENT = 0;
     366                 :        229 :  *   const unsigned short OPENED = 1;
     367                 :        229 :  *   const unsigned short HEADERS_RECEIVED = 2;
     368                 :        229 :  *   const unsigned short LOADING = 3;
     369                 :        229 :  *   const unsigned short DONE = 4;
     370                 :        229 :  *
     371                 :        229 :  *   readonly attribute unsigned short readyState;
     372                 :        229 :  *
     373                 :        229 :  *   // request
     374                 :        229 :  *   undefined open(ByteString method, USVString url);
     375                 :        229 :  *   undefined open(ByteString method, USVString url, boolean async,
     376                 :        229 :  *                  optional USVString? username = null, optional USVString? password = null);
     377                 :        229 :  *   undefined setRequestHeader(ByteString name, ByteString value);
     378                 :        229 :  *
     379                 :        229 :  *   attribute unsigned long timeout;
     380                 :        229 :  *   attribute boolean       withCredentials;
     381                 :        229 :  *
     382                 :        229 :  *   [SameObject] readonly attribute XMLHttpRequestUpload upload;
     383                 :        229 :  *
     384                 :        229 :  *   undefined send(optional (Document or XMLHttpRequestBodyInit)? body = null);
     385                 :        229 :  *   undefined abort();
     386                 :        229 :  *
     387                 :        229 :  *   // response
     388                 :        229 :  *   readonly attribute USVString      responseURL;
     389                 :        229 :  *   readonly attribute unsigned short status;
     390                 :        229 :  *   readonly attribute ByteString     statusText;
     391                 :        229 :  *
     392                 :        229 :  *   ByteString  getResponseHeader(ByteString name);
     393                 :        229 :  *   ByteString  getAllResponseHeaders();
     394                 :        229 :  *   undefined   overrideMimeType(DOMString mime);
     395                 :        229 :  *
     396                 :        229 :  *   attribute XMLHttpRequestResponseType responseType;
     397                 :        229 :  *
     398                 :        229 :  *   readonly attribute any       response;
     399                 :        229 :  *   readonly attribute USVString responseText;
     400                 :        229 :  *
     401                 :        229 :  *   [Exposed=Window] readonly attribute Document? responseXML;
     402                 :        229 :  * };
     403                 :        229 :  *
     404                 :        229 :  * @class     XMLHttpRequest
     405                 :        229 :  * @extends   module:whatwg-xhr~XMLHttpRequestEventTarget
     406                 :        229 :  * @static
     407                 :        229 :  * @desc      Interface that represents the objects used to interact with a server.
     408                 :        229 :  */
     409                 :        229 : export class XMLHttpRequest extends XMLHttpRequestEventTarget{
     410            [ + ]:        229 :         constructor(){
     411                 :        753 :                 super();
     412                 :        753 : 
     413                 :        753 :                 const requestData = {};
     414                 :        753 : 
     415                 :        753 :                 // event handler
     416                 :        753 :                 requestData['onreadystatechange'] = null;              // xhr.spec. attribute EventHandler
     417                 :        753 : 
     418                 :        753 :                 // states - An XMLHttpRequest object has an associated:
     419                 :        753 :                 requestData['readyState'] = this.UNSENT;               // xhr.spec. readonly attribute unsigned short state: initially unsent.
     420                 :        753 : 
     421                 :        753 :                 // request - An XMLHttpRequest object has an associated:
     422                 :        753 :                 requestData['timeout'] = 0;                            // xhr.spec. attribute unsigned long timeout: An unsigned integer, initially 0.
     423                 :        753 :                 requestData['withCredentials'] = false;                // xhr.spec. attribute boolean cross-origin credentials: A boolean, initially false.
     424                 :        753 : 
     425                 :        753 :                 allowXMLHttpRequestUploadConstructor = true;           //
     426                 :        753 :                 requestData['upload'] = new XMLHttpRequestUpload();    // xhr.spec. readonly attribute XMLHttpRequestUpload upload object:
     427                 :        753 :                 allowXMLHttpRequestUploadConstructor = false;          //           an XMLHttpRequestUpload object.
     428                 :        753 : 
     429                 :        753 :                 // response - An XMLHttpRequest object has an associated:
     430                 :        753 :                 requestData['status'    ] = 0;      // xhr.spec. readonly attribute unsigned short status;
     431                 :        753 :                 requestData['statusText'] = '';     // xhr.spec. readonly attribute ByteString statusText;
     432                 :        753 : 
     433                 :        753 :                 requestData['response'    ] = '';   // xhr.spec. readonly attribute any response: a response, initially a network error.
     434                 :        753 :                 requestData['responseText'] = '';   // xhr.spec. readonly attribute ByteString responseText.
     435                 :        753 :                 requestData['responseType'] = '';   // xhr.spec. response type: one of "","arraybuffer","blob","document","json" and "text"; initially "".
     436                 :        753 :                 requestData['responseURL' ] = '';   // xhr.spec. readonly attribute USVString responseURL;
     437                 :        753 :                 requestData['responseXML' ] = null; // xhr.spec. [Exposed=Window] readonly attribute Document? responseXML;
     438                 :        753 : 
     439                 :        753 :                 // associated data - An XMLHttpRequest object has an associated:
     440                 :        753 :                 requestData['sendFlag'] = false;               // xhr.spec. send() flag: a flag, initially unset.
     441                 :        753 :                 requestData['method'  ] = '';                  // xhr.spec. request method: a method.
     442                 :        753 :                 requestData['url'     ] = null;                // xhr.spec. request URL: A URL.
     443                 :        753 :                 requestData['async'   ] = true;                // xhr.spec. synchronous flag: a flag, initially unset.
     444                 :        753 : 
     445                 :        753 :                 requestData['user'    ] = null;
     446                 :        753 :                 requestData['password'] = null;
     447                 :        753 : 
     448                 :        753 :                 requestData['requestHeaders'    ] = {};        // xhr.spec. author request headers: a header list, initially empty.
     449                 :        753 :                 requestData['requestHeadersCase'] = {};
     450                 :        753 : 
     451                 :        753 :                 requestData['requestBody'       ] = null;      // xhr.spec. request body: initially null.
     452                 :        753 :                 requestData['uploadCompleteFlag'] = false;     // xhr.spec. upload complete flag: a flag, initially unset.
     453                 :        753 :                 requestData['uploadListenerFlag'] = false;     // xhr.spec. upload listener flag: a flag, initially unset.
     454                 :        753 :                 requestData['timeoutFlag'       ] = false;     // xhr.spec. timeout flag: a flag, initially unset.
     455                 :        753 :                 requestData['receivedBytes'     ] = Buffer.alloc(0);   // xhr.spec. received bytes: a byte sequence, initially the empty byte sequence.
     456                 :        753 :                 requestData['responseObject'    ] = null;      // xhr.spec. response object: an object, failure, or null, initially null.
     457                 :        753 :                 requestData['fetchController'   ] = null;      // xhr.spec. fetch controller: a fetch controller, initially a new fetch controller.
     458                 :        753 :                 requestData['overrideMimeType'  ] = null;      // xhr.spec. A MIME type or null, initially null. Can get a value when overrideMimeType() is invoked.
     459                 :        753 : 
     460                 :        753 :                 requestData['_redirectCount'       ] = 0;     // fetch.spec.2.2.5. A request has an associated redirect count. Unless stated otherwise, it is zero.
     461                 :        753 :                 requestData['_responseAbort'       ] = false; // fetch.spec.2.2.6. A response can have an associated aborted flag, which is initially unset.
     462                 :        753 :                 requestData['_responseNetworkError'] = false;
     463                 :        753 :                 requestData['_responseBody'        ] = null;  // fetch.spec.2.2.6. A response has an associated body (null or a body). Unless stated otherwise it is null.
     464                 :        753 : 
     465                 :        753 :                 // Map any XMLHttpRequest object created to an associated data object.
     466                 :        753 :                 xmlHttpRequest.set(this, requestData);
     467                 :        753 :         }
     468                 :        229 : 
     469                 :        229 :         /**
     470                 :        229 :          * @member   {function} onreadystatechange
     471                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     472                 :        229 :          * @instance
     473                 :        229 :          * @desc     Get/Set the event handler fired whenever there's change in readyState.
     474                 :        229 :          */
     475                 :        229 :         get onreadystatechange(){ return xmlHttpRequest.get(this)['onreadystatechange']; }
     476                 :        229 : 
     477            [ + ]:        229 :         set onreadystatechange(callback){
     478                 :        231 :                 this.removeEventListener('readystatechange', xmlHttpRequest.get(this)['onreadystatechange']);
     479                 :        231 :                 xmlHttpRequest.get(this)['onreadystatechange'] = null;
     480                 :        231 : 
     481            [ + ]:        231 :                 if(typeof callback === 'function'){
     482                 :        142 :                         this.addEventListener('readystatechange', callback);
     483                 :        142 :                         xmlHttpRequest.get(this)['onreadystatechange'] = callback;
     484                 :        142 :                 }
     485                 :        231 :         }
     486                 :        229 : 
     487                 :        229 :         /**
     488                 :        229 :          * @member   {number} readyState
     489                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     490                 :        229 :          * @readonly
     491                 :        229 :          * @instance
     492                 :        229 :          * @desc     Get the state an XMLHttpRequest client is in.
     493                 :        229 :          */
     494            [ + ]:        229 :         get readyState(){ return xmlHttpRequest.get(this)['readyState']; }
     495                 :        229 : 
     496                 :        229 :         /**
     497                 :        229 :          * @member   {object} upload
     498                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     499                 :        229 :          * @readonly
     500                 :        229 :          * @instance
     501                 :        229 :          * @desc     Get an XMLHttpRequestUpload object that can be observed to monitor an upload's progress.
     502                 :        229 :          */
     503            [ + ]:        229 :         get upload(){ return xmlHttpRequest.get(this)['upload']; }
     504                 :        229 : 
     505                 :        229 :         /**
     506                 :        229 :          * @member   {number} status
     507                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     508                 :        229 :          * @readonly
     509                 :        229 :          * @instance
     510                 :        229 :          * @desc     Get the numerical HTTP status code of the server response.
     511                 :        229 :          */
     512            [ + ]:        229 :         get status(){ return xmlHttpRequest.get(this)['status']; }
     513                 :        229 : 
     514                 :        229 :         /**
     515                 :        229 :          * @member   {string} statusText
     516                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     517                 :        229 :          * @readonly
     518                 :        229 :          * @instance
     519                 :        229 :          * @desc     Get the HTTP status message of the server response.
     520                 :        229 :          */
     521            [ + ]:        229 :         get statusText(){ return xmlHttpRequest.get(this)['statusText']; }
     522                 :        229 : 
     523                 :        229 :         /**
     524                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     525                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-response-attribute
     526                 :        229 :          *
     527                 :        229 :          * client.response
     528                 :        229 :          *
     529                 :        229 :          *   Returns the response body.
     530                 :        229 :          *
     531                 :        229 :          * The response getter steps are:
     532                 :        229 :          * 1. If this’s response type is the empty string or "text", then:
     533                 :        229 :          *     1. If this’s state is not loading or done, then return the empty string.
     534                 :        229 :          *     2. Return the result of getting a text response for this.
     535                 :        229 :          * 2. If this’s state is not done, then return null.
     536                 :        229 :          * 3. If this’s response object is failure, then return null.
     537                 :        229 :          * 4. If this’s response object is non-null, then return it.
     538                 :        229 :          * 5. If this’s response type is "arraybuffer", then set this’s response object to a new ArrayBuffer object representing this’s received bytes.
     539                 :        229 :          *    If this throws an exception, then set this’s response object to failure and return null.
     540                 :        229 :          *    Note: Allocating an ArrayBuffer object is not guaranteed to succeed. [ECMASCRIPT]
     541                 :        229 :          * 6. Otherwise, if this’s response type is "blob", set this’s response object to a new Blob object representing this’s received bytes with type
     542                 :        229 :          *    set to the result of get a final MIME type for this.
     543                 :        229 :          * 7. Otherwise, if this’s response type is "document", set a document response for this.
     544                 :        229 :          * 8. Otherwise:
     545                 :        229 :          *    1. Assert: this’s response type is "json".
     546                 :        229 :          *    2. If this’s response’s body is null, then return null.
     547                 :        229 :          *    3. Let jsonObject be the result of running parse JSON from bytes on this’s received bytes. If that threw an exception, then return null.
     548                 :        229 :          *    4. Set this’s response object to jsonObject.
     549                 :        229 :          * 9. Return this’s response object.
     550                 :        229 :          *
     551                 :        229 :          * @member   {ArrayBuffer|Blob|Document|object|string} response
     552                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     553                 :        229 :          * @readonly
     554                 :        229 :          * @instance
     555                 :        229 :          * @desc     Get the response's body content received from a server following a request being sent.
     556                 :        229 :          */
     557            [ + ]:        229 :         get response(){
     558                 :        297 : 
     559                 :        297 :                 const requestData = xmlHttpRequest.get(this);
     560                 :        297 : 
     561                 :        297 :                 // xhr.spec.1. If this’s response type is the empty string or "text", then:
     562       [ + ][ + ]:        297 :                 if(requestData['responseType'] === '' || requestData['responseType'] === 'text'){
     563                 :         57 : 
     564                 :         57 :                         // xhr.spec.1.1. If this’s state is not loading or done, then return the empty string.
     565            [ + ]:         57 :                         if(requestData['readyState'] !== this.LOADING && requestData['readyState'] !== this.DONE){
     566                 :         19 :                                 return '';
     567            [ + ]:         19 :                         }
     568                 :         38 : 
     569                 :         38 :                         // xhr.spec.1.2. Return the result of getting a text response for this.
     570                 :         38 :                         return getTextResponse.call(this);
     571            [ + ]:         38 :                 }
     572                 :         28 : 
     573                 :         28 :                 // xhr.spec.2. If this’s state is not done, then return null.
     574                 :         28 :                 if(requestData['readyState'] !== this.DONE)
     575       [ + ][ - ]:        297 :                         return null;
     576                 :         28 : 
     577                 :         28 :                 // xhr.spec.3. If this’s response object is failure, then return null.
     578                 :         28 :                 if(requestData['responseObject'] === 'failure')
     579       [ + ][ - ]:        297 :                         return null;
     580                 :         28 : 
     581                 :         28 :                 // xhr.spec.4. If this’s response object is non-null, then return it.
     582                 :         28 :                 if(requestData['responseObject'] !== null)
     583       [ + ][ + ]:        297 :                         return requestData['responseObject'];
     584                 :         13 : 
     585                 :         13 :                 // xhr.spec.5. If this’s response type is "arraybuffer"
     586            [ + ]:        297 :                 if(requestData['responseType'] === 'arraybuffer'){
     587                 :          1 :                         // xhr.spec.5. set this’s response object to a new ArrayBuffer object representing this’s received bytes.
     588                 :          1 :                         try{
     589                 :          1 :                                 requestData['responseObject'] = new Uint8Array(requestData['receivedBytes']).buffer;
     590                 :          1 :                         }
     591                 :          1 :                         /* node:coverage disable */
     592            [ - ]:            :                         catch(e){
     593                 :            :                                 // xhr.spec.5. If this throws an exception, then set this’s response object to failure and return null.
     594                 :            :                                 requestData['responseObject'] = 'failure';
     595                 :            :                                 return null;
     596                 :            :                         }
     597                 :            :                         /* node:coverage enable */
     598            [ + ]:          1 :                 }
     599                 :         12 :                 else
     600                 :         12 :                 // xhr.spec.6. Otherwise, if this’s response type is "blob",
     601            [ + ]:         12 :                 if(requestData['responseType'] === 'blob'){
     602                 :          2 : 
     603                 :          2 :                         // xhr.spec.6. set this’s response object to a new Blob object representing this’s received bytes with type
     604                 :          2 :                         // set to the result of get a final MIME type for this.
     605                 :          2 : 
     606                 :          2 :                         if(!(requestData['responseObject'] instanceof Blob)){
     607                 :          2 : 
     608                 :          2 :                                 requestData['responseObject'] = new Blob([requestData['receivedBytes']], {
     609                 :          2 :                                                 endings: 'native',
     610                 :          2 :                                                 type: getFinalMimeType.call(this)
     611                 :          2 :                                         });
     612                 :          2 :                         }
     613            [ + ]:          2 :                 }
     614                 :         10 :                 else
     615                 :         10 :                 /* node:coverage disable */
     616                 :            :                 // xhr.spec.7. Otherwise, if this’s response type is "document", set a document response for this.
     617            [ - ]:            :                 if(requestData['responseType'] === 'document'){
     618                 :            :                         // @todo...
     619                 :            :                 }
     620                 :            :                 /* node:coverage enable */
     621                 :         10 :                 // xhr.spec.8. Otherwise:
     622                 :         10 :                 else{
     623                 :         10 :                         // xhr.spec.8.1. Assert: this’s response type is "json".
     624                 :         10 :                         if(requestData['responseType'] === 'json'){
     625                 :         10 : 
     626                 :         10 :                                 // xhr.spec.8.2. If this’s response’s body is null, then return null.
     627                 :         10 :                                 // @author. if(requestData['_responseBody'] === null)
     628                 :         10 :                                 if(requestData['receivedBytes'].length === 0)
     629       [ + ][ + ]:         10 :                                         return null;
     630                 :          6 : 
     631                 :          6 :                                 // xhr.spec.8.3. Let jsonObject be the result of running parse JSON from bytes on this’s received bytes.
     632                 :          6 :                                 // If that threw an exception, then return null.
     633                 :          6 :                                 try{
     634                 :          6 :                                         let jsonObject = JSON.parse(requestData['receivedBytes']);
     635                 :          6 : 
     636                 :          6 :                                         // xhr.spec.8.4. Set this’s response object to jsonObject.
     637                 :          6 :                                         requestData['responseObject'] = jsonObject;
     638            [ + ]:         10 :                                 }catch(e){
     639                 :          4 :                                         return null;
     640                 :          4 :                                 }
     641                 :         10 :                         }
     642            [ + ]:         10 :                 }
     643                 :          5 :                 // xhr.spec.9. Return this’s response object.
     644                 :          5 :                 return requestData['responseObject'];
     645                 :        297 :         }
     646                 :        229 : 
     647                 :        229 :         /**
     648                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     649                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-responsetext-attribute
     650                 :        229 :          *
     651                 :        229 :          * client.responseText
     652                 :        229 :          *
     653                 :        229 :          *    Returns response as text.
     654                 :        229 :          *    Throws an "InvalidStateError" DOMException if responseType is not the empty string or "text".
     655                 :        229 :          *
     656                 :        229 :          * The responseText getter steps are:
     657                 :        229 :          * 1. If this’s response type is not the empty string or "text", then throw an "InvalidStateError" DOMException.
     658                 :        229 :          * 2. If this’s state is not loading or done, then return the empty string.
     659                 :        229 :          * 3. Return the result of <getting a text response> for this.
     660                 :        229 :          *
     661                 :        229 :          * @member   {string} responseText
     662                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     663                 :        229 :          * @readonly
     664                 :        229 :          * @instance
     665                 :        229 :          * @desc     Get the text received from a server following a request being sent.
     666                 :        229 :          */
     667            [ + ]:        229 :         get responseText(){
     668                 :        476 :                 const requestData = xmlHttpRequest.get(this);
     669                 :        476 : 
     670                 :        476 :                 // xhr.spec.1. If this’s response type is not the empty string or "text", then throw an "InvalidStateError" DOMException.
     671            [ + ]:        476 :                 if(requestData['responseType'] !== '' && requestData['responseType'] !== 'text')
     672            [ - ]:        476 :                         throw new DOMException(`XMLHttpRequest.responseText getter: responseText is only available if responseType is '' or 'text'.`, 'InvalidAccessError');
     673                 :        476 : 
     674                 :        476 :                 // xhr.spec.2. If this’s state is not loading or done, then return the empty string.
     675       [ + ][ + ]:        476 :                 if(requestData['readyState'] !== this.LOADING && requestData['readyState'] !== this.DONE){
     676                 :          3 :                         return '';
     677            [ + ]:          3 :                 }
     678                 :        261 : 
     679                 :        261 :                 // xhr.spec.3. Return the result of <getting a text response> for this.
     680                 :        261 :                 return getTextResponse.call(this);
     681                 :        476 :         }
     682                 :        229 : 
     683                 :        229 :         /**
     684                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     685                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-responsetype-attribute
     686                 :        229 :          *
     687                 :        229 :          * client.responseType[ = value ]
     688                 :        229 :          *
     689                 :        229 :          *   Returns the response type.
     690                 :        229 :          *   Can be set to change the response type. Values are: the empty string (default), "arraybuffer", "blob", "document", "json", and "text".
     691                 :        229 :          *   When set: setting to "document" is ignored if the current global object is not a Window object.
     692                 :        229 :          *   When set: throws an "InvalidStateError" DOMException if state is loading or done.
     693                 :        229 :          *   When set: throws an "InvalidAccessError" DOMException if the synchronous flag is set and the current global object is a Window object.
     694                 :        229 :          *
     695                 :        229 :          * The responseType getter steps are to return this’s response type.
     696                 :        229 :          * The responseType setter steps are:
     697                 :        229 :          * 1. If the current global object is not a Window object and the given value is "document", then return.
     698                 :        229 :          * 2. If this’s state is loading or done, then throw an "InvalidStateError" DOMException.
     699                 :        229 :          * 3. If the current global object is a Window object and this’s synchronous flag is set, then throw an "InvalidAccessError" DOMException.
     700                 :        229 :          * 4. Set this’s response type to the given value.
     701                 :        229 :          *
     702                 :        229 :          * @member   {string} responseType
     703                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     704                 :        229 :          * @instance
     705                 :        229 :          * @desc     Get/Set an enumerated string value specifying the type of data contained in the response.
     706                 :        229 :          */
     707            [ + ]:        229 :         get responseType(){
     708                 :        456 :                 return xmlHttpRequest.get(this)['responseType'];
     709                 :        456 :         }
     710                 :        229 : 
     711            [ + ]:        229 :         set responseType(type){
     712            [ + ]:         39 :                 if(String(type) in XMLHttpRequestResponseType){
     713                 :         31 :                         const requestData = xmlHttpRequest.get(this);
     714                 :         31 : 
     715                 :         31 :                         // xhr.spec.3. If the current global object is a Window object and this’s synchronous flag is set,
     716                 :         31 :                         // then throw an "InvalidAccessError" DOMException.
     717                 :         31 : 
     718                 :         31 :                         // @author. xhr.spec.3. will also be applicable to main thread
     719                 :         31 :                         if(threads.isMainThread){
     720                 :         31 :                                 if(!requestData['async'])
     721            [ - ]:         31 :                                         throw new DOMException(
     722                 :          0 :                                                                 `XMLHttpRequest.responseType setter: synchronous XMLHttpRequests do not support timeout and responseType`,
     723                 :          0 :                                                                 'InvalidAccessError'
     724                 :          0 :                                         );
     725            [ - ]:         31 :                         }
     726                 :          0 :                         /* node:coverage disable */
     727                 :            :                         else{
     728                 :            :                                 // xhr.spec.1. If the current global object is not a Window object and the given value is "document", then return.
     729                 :            :                                 if(String(type).toLowerCase() === 'document')
     730                 :            :                                         return;
     731                 :            :                         }
     732                 :            :                         /* node:coverage enable */
     733                 :         31 : 
     734                 :         31 :                         // xhr.spec.2. If this’s state is loading or done, then throw an "InvalidStateError" DOMException.
     735                 :         31 :                         if(requestData['readyState'] === this.LOADING || requestData['readyState'] === this.DONE)
     736            [ - ]:         31 :                                 throw new DOMException(`XMLHttpRequest.responseType setter: Cannot set 'responseType' property on XMLHttpRequest after 'send()' (when its state is LOADING or DONE).`, 'InvalidStateError');
     737                 :         31 : 
     738                 :         31 :                         requestData['responseType'] = String(type).toLowerCase();
     739                 :         31 :                 }
     740                 :         39 :         }
     741                 :        229 : 
     742                 :        229 :         /**
     743                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     744                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-responsexml-attribute
     745                 :        229 :          *
     746                 :        229 :          * The responseXML getter
     747                 :        229 :          *
     748                 :        229 :          * client . responseXML
     749                 :        229 :          *
     750                 :        229 :          *  Returns the response as document.
     751                 :        229 :          *  Throws an "InvalidStateError" DOMException if responseType is not the empty string or "document".
     752                 :        229 :          *
     753                 :        229 :          * The responseXML getter steps are:
     754                 :        229 :          * 1. If this’s response type is not the empty string or "document", then throw an "InvalidStateError" DOMException.
     755                 :        229 :          * 2. If this’s state is not done, then return null.
     756                 :        229 :          * 3. Assert: this’s response object is not failure.
     757                 :        229 :          * 4. If this’s response object is non-null, then return it.
     758                 :        229 :          * 5. Set a document response for this.
     759                 :        229 :          * 6. Return this’s response object.
     760                 :        229 :          *
     761                 :        229 :          * @member   {Document|null} responseXML
     762                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     763                 :        229 :          * @readonly
     764                 :        229 :          * @instance
     765                 :        229 :          * @desc     Get a Document containing the HTML or XML retrieved by the request, or null.
     766                 :        229 :          */
     767            [ + ]:        229 :         get responseXML(){
     768                 :        219 : 
     769                 :        219 :                 const requestData = xmlHttpRequest.get(this);
     770                 :        219 : 
     771                 :        219 :                 /* node:coverage disable */
     772                 :            :                 // xhr.spec.1. If this’s response type is not the empty string or "document", then throw an "InvalidStateError" DOMException.
     773       [ - ][ - ]:            :                 if(this.responseType !== '' && this.responseType !== 'document'){
     774                 :            :                         throw new DOMException(
     775                 :            :                                 `XMLHttpRequest.responseXML getter: responseXML is only available if responseType is '' or 'document'.`, 'InvalidStateError');  // firefox 102
     776                 :            :                 }
     777                 :            :                 /* node:coverage enable */
     778                 :        219 : 
     779                 :        219 :                 // xhr.spec.2. If this’s state is not done, then return null.
     780                 :        219 :                 if(xmlHttpRequest.get(this)['readyState'] !== this.DONE)
     781       [ + ][ + ]:        219 :                         return null;
     782                 :          4 : 
     783                 :          4 :                 // xhr.spec.3. Assert: this’s response object is not failure.
     784                 :          4 :                 if(requestData['responseObject'] === 'failure')
     785       [ + ][ - ]:        219 :                         return null;
     786                 :          4 : 
     787                 :          4 :                 // xhr.spec.4. If this’s response object is non-null, then return it.
     788                 :          4 :                 if(requestData['responseObject'] !== null)
     789       [ + ][ - ]:        219 :                         return requestData['responseObject'];
     790                 :          4 : 
     791                 :          4 :                 // xhr.spec.5. Set a document response for this.
     792                 :          4 :                 setDocumentResponse.call(this);
     793                 :          4 : 
     794                 :          4 :                 // xhr.spec.6. Return this’s response object.
     795                 :          4 :                 return xmlHttpRequest.get(this)['responseObject'];
     796                 :        219 :         }
     797                 :        229 : 
     798                 :        229 :         /**
     799                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     800                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-responseurl-attribute
     801                 :        229 :          *
     802                 :        229 :          * The responseURL getter
     803                 :        229 :          *
     804                 :        229 :          * The responseURL getter steps are to return the empty string if this’s response’s URL is null;
     805                 :        229 :          * otherwise its serialization with the exclude fragment flag set.
     806                 :        229 :          *
     807                 :        229 :          * @member   {string} responseURL
     808                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     809                 :        229 :          * @readonly
     810                 :        229 :          * @instance
     811                 :        229 :          * @desc     Get the serialized URL of the response or the empty string if the URL is null.
     812                 :        229 :          */
     813            [ + ]:        229 :         get responseURL(){
     814                 :        212 :                 const requestData = xmlHttpRequest.get(this);
     815                 :        212 : 
     816            [ - ]:        212 :                 if(requestData['response'] && requestData['response'].url){
     817                 :          0 :                         return requestData['response'].url.replace(/#.*$/, '');
     818                 :          0 :                 }
     819                 :        212 : 
     820                 :        212 :                 return '';
     821                 :        212 :         }
     822                 :        229 : 
     823                 :        229 :         /**
     824                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     825                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-timeout-attribute
     826                 :        229 :          * client.timeout
     827                 :        229 :          *
     828                 :        229 :          *   Can be set to a time in milliseconds. When set to a non-zero value will cause fetching to terminate after the given time has passed.
     829                 :        229 :          *   When the time has passed, the request has not yet completed, and this’s synchronous flag is unset, a timeout event will then be dispatched,
     830                 :        229 :          *   or a "TimeoutError" DOMException will be thrown otherwise (for the send() method).
     831                 :        229 :          *   When set: throws an "InvalidAccessError" DOMException if the synchronous flag is set and the current global object is a Window object.
     832                 :        229 :          *
     833                 :        229 :          * The timeout getter steps are to return this’s timeout.
     834                 :        229 :          * The timeout setter steps are:
     835                 :        229 :          * 1. If the current global object is a Window object and this’s synchronous flag is set, then throw an "InvalidAccessError" DOMException.
     836                 :        229 :          * 2. Set this’s timeout to the given value.
     837                 :        229 :          * Note: This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative
     838                 :        229 :          *       to the start of fetching.
     839                 :        229 :          *
     840                 :        229 :          * @member   {number} timeout
     841                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     842                 :        229 :          * @instance
     843                 :        229 :          * @desc     Get/Set an unsigned long representing the number of milliseconds a request can take before automatically being terminated.
     844                 :        229 :          */
     845                 :        229 :         get timeout(){ return xmlHttpRequest.get(this)['timeout']; }
     846                 :        229 : 
     847            [ + ]:        229 :         set timeout(int){
     848                 :          3 : 
     849                 :          3 :                 // xhr.spec.1. If the current global object is a Window object and this’s synchronous flag is set, then throw an "InvalidAccessError" DOMException.
     850            [ - ]:          3 :                 if(globalThis.Window && !xmlHttpRequest.get(this)['async'])
     851            [ - ]:          3 :                         throw new DOMException(`XMLHttpRequest.timeout setter: synchronous XMLHttpRequests do not support timeout and responseType`, 'InvalidAccessError');
     852                 :          3 : 
     853                 :          3 :                 // @author. xhr.spec.1. will also be applicable to main thread
     854                 :          3 :                 if(threads.isMainThread && !xmlHttpRequest.get(this)['async'])
     855            [ - ]:          3 :                         throw new DOMException(`XMLHttpRequest.timeout setter: synchronous XMLHttpRequests do not support timeout and responseType`, 'InvalidAccessError');
     856                 :          3 : 
     857                 :          3 :                 // xhr.spec.2. Set this’s timeout to the given value.
     858            [ - ]:          3 :                 xmlHttpRequest.get(this)['timeout'] = isNaN(int) ? 0 : int;
     859                 :          3 :         }
     860                 :        229 : 
     861                 :        229 :         /**
     862                 :        229 :          * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     863                 :        229 :          * url: https://xhr.spec.whatwg.org/#the-withcredentials-attribute
     864                 :        229 :          * client.withCredentials
     865                 :        229 :          *
     866                 :        229 :          *   True when credentials are to be included in a cross-origin request.
     867                 :        229 :          *   False when they are to be excluded in a cross-origin request and when cookies are to be ignored in its response. Initially false.
     868                 :        229 :          *   When set: throws an "InvalidStateError" DOMException if state is not unsent or opened, or if the send() flag is set.
     869                 :        229 :          *
     870                 :        229 :          * The withCredentials getter steps are to return this’s cross-origin credentials.
     871                 :        229 :          * The withCredentials setter steps are:
     872                 :        229 :          * 1. If this’s state is not unsent or opened, then throw an "InvalidStateError" DOMException.
     873                 :        229 :          * 2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
     874                 :        229 :          * 3. Set this’s cross-origin credentials to the given value.
     875                 :        229 :          *
     876                 :        229 :          * @member   {boolean} withCredentials
     877                 :        229 :          * @memberof module:whatwg-xhr.XMLHttpRequest
     878                 :        229 :          * @instance
     879                 :        229 :          * @desc     Get/Set a boolean value that indicates whether or not cross-site Access-Control requests should be made using credentials.
     880                 :        229 :          */
     881                 :        229 :         get withCredentials(){ return xmlHttpRequest.get(this)['withCredentials']; }
     882                 :        229 : 
     883            [ + ]:        229 :         set withCredentials(cred = false){
     884                 :          1 :                 const requestData = xmlHttpRequest.get(this);
     885                 :          1 : 
     886                 :          1 :                 // xhr.spec.1. If this’s state is not unsent or opened, then throw an "InvalidStateError" DOMException.
     887                 :          1 :                 // xhr.spec.2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
     888                 :          1 :                 if(requestData['readyState'] > this.OPENED || requestData['sendFlag'])
     889            [ - ]:          1 :                         throw new DOMException(`XMLHttpRequest.withCredentials setter: XMLHttpRequest must not be sending.`, 'InvalidStateError');
     890                 :          0 : 
     891                 :          0 :                 // xhr.spec.3. Set this’s cross-origin credentials to the given value.
     892                 :          0 :                 xmlHttpRequest.get(this)['withCredentials'] = Boolean(cred);
     893                 :          1 :         }
     894                 :        229 : } // @endof class XMLHttpRequest extends XMLHttpRequestEventTarget
     895                 :        229 : 
     896                 :        229 : /**
     897                 :        229 :  * @const    {number} UNSENT
     898                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     899                 :        229 :  * @instance
     900                 :        229 :  * @default  0
     901                 :        229 :  * @desc     State of XMLHttpRequest object, client has been created, open() not called yet.
     902                 :        229 :  */
     903                 :        229 : Object.defineProperty(XMLHttpRequest.prototype, 'UNSENT', {value: 0, writable: false, enumerable: true, configurable: false});
     904                 :        229 : 
     905                 :        229 : /**
     906                 :        229 :  * @const    {number} OPENED
     907                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     908                 :        229 :  * @instance
     909                 :        229 :  * @default  1
     910                 :        229 :  * @desc     State of XMLHttpRequest object, open() has been called.
     911                 :        229 :  */
     912                 :        229 : Object.defineProperty(XMLHttpRequest.prototype, 'OPENED', {value: 1, writable: false, enumerable: true, configurable: false});
     913                 :        229 : 
     914                 :        229 : /**
     915                 :        229 :  * @const    {number} HEADERS_RECEIVED
     916                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     917                 :        229 :  * @instance
     918                 :        229 :  * @default  2
     919                 :        229 :  * @desc     State of XMLHttpRequest object, send() has been called, headers and status are available.
     920                 :        229 :  */
     921                 :        229 : Object.defineProperty(XMLHttpRequest.prototype, 'HEADERS_RECEIVED', {value: 2, writable: false, enumerable: true, configurable: false});
     922                 :        229 : 
     923                 :        229 : /**
     924                 :        229 :  * @const    {number} LOADING
     925                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     926                 :        229 :  * @instance
     927                 :        229 :  * @default  3
     928                 :        229 :  * @desc     State of XMLHttpRequest object, downloading, responseText holds partial data.
     929                 :        229 :  */
     930                 :        229 : Object.defineProperty(XMLHttpRequest.prototype, 'LOADING', {value: 3, writable: false, enumerable: true, configurable: false});
     931                 :        229 : 
     932                 :        229 : /**
     933                 :        229 :  * @const    {number} DONE
     934                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     935                 :        229 :  * @instance
     936                 :        229 :  * @default  4
     937                 :        229 :  * @desc     State of XMLHttpRequest object, the operation is complete.
     938                 :        229 :  */
     939                 :        229 : Object.defineProperty(XMLHttpRequest.prototype, 'DONE', {value: 4, writable: false, enumerable: true, configurable: false});
     940                 :        229 : 
     941                 :        229 : /**
     942                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
     943                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-open()-method
     944                 :        229 :  *
     945                 :        229 :  * client.open(method, url [, async = true [, username = null [, password = null]]])
     946                 :        229 :  *
     947                 :        229 :  *   Sets the request method, request URL, and synchronous flag.
     948                 :        229 :  *   Throws a  "SyntaxError"        DOMException if either method is not a valid method or url cannot be parsed.
     949                 :        229 :  *   Throws a  "SecurityError"      DOMException if method is a case-insensitive match for `CONNECT`, `TRACE`, or `TRACK`.
     950                 :        229 :  *   Throws an "InvalidAccessError" DOMException if async is false, the current global object is a Window object, and the timeout attribute is not zero
     951                 :        229 :  *                                  or the responseType attribute is not the empty string.
     952                 :        229 :  *
     953                 :        229 :  * Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user’s
     954                 :        229 :  * experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when the current global object is a
     955                 :        229 :  * Window object. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an "InvalidAccessError"
     956                 :        229 :  * DOMException when it occurs.
     957                 :        229 :  *
     958                 :        229 :  * The open(method, url) and open(method, url, async, username, password) method steps are:
     959                 :        229 :  *
     960                 :        229 :  *   1. If this’s relevant global object is a Window object and its associated Document is not fully active, then throw an "InvalidStateError" DOMException.
     961                 :        229 :  *   2. If method is not a method, then throw a "SyntaxError" DOMException.
     962                 :        229 :  *   3. If method is a forbidden method, then throw a "SecurityError" DOMException.
     963                 :        229 :  *   4. Normalize method.
     964                 :        229 :  *   5. Let parsedURL be the result of parsing url with this’s relevant settings object’s API base URL and this’s relevant settings object’s API URL
     965                 :        229 :  *      character encoding.
     966                 :        229 :  *   6. If parsedURL is failure, then throw a "SyntaxError" DOMException.
     967                 :        229 :  *   7. If the async argument is omitted, set async to true, and set username and password to null.
     968                 :        229 :  *      Note: Unfortunately legacy content prevents treating the async argument being undefined identical from it being omitted.
     969                 :        229 :  *   8. If parsedURL’s host is non-null, then:
     970                 :        229 :  *      1. If the username argument is not null, set the username given parsedURL and username.
     971                 :        229 :  *      2. If the password argument is not null, set the password given parsedURL and password.
     972                 :        229 :  *   9. If async is false, the current global object is a Window object, and either this’s timeout is not 0 or this’s response type is not the empty
     973                 :        229 :  *      string, then throw an "InvalidAccessError" DOMException.
     974                 :        229 :  *  10. Terminate this’s fetch controller.
     975                 :        229 :  *      Note: A fetch can be ongoing at this point.
     976                 :        229 :  *  11. Set variables associated with the object as follows:
     977                 :        229 :  *        Unset this’s send() flag.
     978                 :        229 :  *        Unset this’s upload listener flag.
     979                 :        229 :  *        Set   this’s request method to method.
     980                 :        229 :  *        Set   this’s request URL to parsedURL.
     981                 :        229 :  *        Set   this’s synchronous flag if async is false; otherwise unset this’s synchronous flag.
     982                 :        229 :  *        Empty this’s author request headers.
     983                 :        229 :  *        Set   this’s response to a network error.
     984                 :        229 :  *        Set   this’s received bytes to the empty byte sequence.
     985                 :        229 :  *        Set   this’s response object to null.
     986                 :        229 :  *      Note: Override MIME type is not overridden here as the overrideMimeType() method can be invoked before the open() method.
     987                 :        229 :  *  12. If this’s state is not opened, then:
     988                 :        229 :  *      1. Set this’s state to opened.
     989                 :        229 :  *      2. Fire an event named readystatechange at this.
     990                 :        229 :  *
     991                 :        229 :  * @method   open
     992                 :        229 :  * @instance
     993                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
     994                 :        229 :  * @param    {string}  method   - The HTTP request method to use, such as "GET", "POST", "PUT", "DELETE", etc. Ignored for non-HTTP(S) URLs.
     995                 :        229 :  * @param    {string}  url      - A string or any other object with a stringifier that provides the URL of the resource to request.
     996                 :        229 :  * @param    {boolean} is_async - (Optional) Boolean parameter, defaulting to true, indicating whether or not to perform the operation asynchronously.
     997                 :        229 :  * @param    {string}  username - (Optional) user name to use for authentication purposes; by default, this is the null value.
     998                 :        229 :  * @param    {string}  password - (Optional) password to use for authentication purposes; by default, this is the null value.
     999                 :        229 :  * @desc     XMLHttpRequest method that initializes a newly-created request, or re-initializes an existing one.
    1000                 :        229 :  * @requires module:whatwg-fetch.forbiddenHttpRequestMethod
    1001                 :        229 :  */
    1002            [ + ]:        229 : XMLHttpRequest.prototype.open = function open(method, url, is_async = true, username = null, password = null){
    1003                 :        772 : 
    1004                 :        772 :         // xhr.spec.1. If this’s relevant global object is a Window object and its associated Document is not fully active, then throw an "InvalidStateError" DOMException.
    1005            [ - ]:        772 :         if(globalThis.Window && !document.isConnected)
    1006            [ - ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: ......`, 'InvalidStateError');
    1007                 :        772 : 
    1008                 :        772 :         // xhr.spec.2. If method is not a method, then throw a "SyntaxError" DOMException
    1009                 :        772 :         if(typeof method === 'function')
    1010            [ - ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: an invalid or illegal method string was specified`, 'SyntaxError');
    1011                 :        772 : 
    1012                 :        772 :         // xhr.spec.2. If method is not a method, then throw a "SyntaxError" DOMException
    1013                 :        772 :         method = String(method);
    1014                 :        772 :         if(/[^\w]/.test(method))
    1015       [ + ][ + ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: an invalid or illegal method string was specified`, 'SyntaxError');
    1016                 :        537 : 
    1017                 :        537 :         // xhr.spec.3. If method is a forbidden method, then throw a "SecurityError" DOMException
    1018                 :        537 :         if(forbiddenHttpRequestMethod.has(String(method).toLowerCase()))
    1019       [ + ][ + ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: the operation is insecure.`, 'SecurityError');
    1020                 :        528 : 
    1021                 :        528 :         // xhr.spec.4. Normalize method.
    1022                 :        528 :         // fetch.spec. To normalize a method, if it is a byte-case-insensitive match for `DELETE`, `GET`, `HEAD`, `OPTIONS`, `POST`, or `PUT`, byte-uppercase it.
    1023       [ + ][ + ]:        772 :         method = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'].find(m => m === String(method).toUpperCase()) || String(method);
    1024                 :        772 : 
    1025                 :        772 :         // xhr.spec.5. Let parsedURL be the result of parsing url with this’s relevant settings object’s API base URL and
    1026                 :        772 :         //             this’s relevant settings object’s API URL character encoding.
    1027                 :        772 :         let parsedURL;
    1028                 :        772 :         try{
    1029                 :        772 :                 parsedURL = new URL(url);
    1030                 :        772 :         }
    1031            [ + ]:        772 :         catch(e){
    1032                 :          1 :                 // xhr.spec.6. If parsedURL is failure, then throw a "SyntaxError" DOMException
    1033                 :          1 :                 throw new DOMException(`XMLHttpRequest.open: an invalid or illegal url string was specified`, 'SyntaxError');
    1034            [ + ]:          1 :         }
    1035                 :        527 : 
    1036                 :        527 :         // xhr.spec.7. If the async argument is omitted, set async to true, and set username and password to null.
    1037                 :        527 :         // @author. already handled by default arguments: open(method, url, is_async = true, username = null, password = null)
    1038                 :        527 : 
    1039                 :        527 :         // xhr.spec.8. If parsedURL’s host is non-null, then:
    1040            [ + ]:        772 :         if(parsedURL.host){
    1041                 :        511 :                 // xhr.spec.8.1. If the username argument is not null, set the username given parsedURL and username.
    1042            [ + ]:        511 :                 if(username){
    1043                 :          1 :                 /*
    1044                 :          1 :                  * URL Living Standard — Last Updated 24 May 2023
    1045                 :          1 :                  * url: https://url.spec.whatwg.org/#set-the-username
    1046                 :          1 :                  *
    1047                 :          1 :                  * To set the username given a url and username, set url’s username to the result of running UTF-8 percent-encode on username
    1048                 :          1 :                  * using the userinfo percent-encode set.
    1049                 :          1 :                  */
    1050                 :          1 :                         parsedURL.username = username;
    1051                 :          1 :                 }
    1052                 :        511 :                 // xhr.spec.8.2. If the password argument is not null, set the password given parsedURL and password.
    1053            [ + ]:        511 :                 if(password){
    1054                 :          1 :                 /*
    1055                 :          1 :                  * URL Living Standard — Last Updated 24 May 2023
    1056                 :          1 :                  * url: https://url.spec.whatwg.org/#set-the-password
    1057                 :          1 :                  *
    1058                 :          1 :                  * To set the password given a url and password, set url’s password to the result of running UTF-8 percent-encode on password
    1059                 :          1 :                  * using the userinfo percent-encode set.
    1060                 :          1 :                  */
    1061                 :          1 :                         parsedURL.password = password;
    1062                 :          1 :                 }
    1063            [ + ]:        511 :         }
    1064                 :        527 : 
    1065                 :        527 :         const requestData = xmlHttpRequest.get(this);
    1066                 :        527 : 
    1067                 :        527 :         // xhr.spec.9. If async is false, the current global object is a Window object, and either this’s timeout is not 0 or this’s response type is not the empty
    1068                 :        527 :         //             string, then throw an "InvalidAccessError" DOMException.
    1069       [ - ][ - ]:        772 :         if(globalThis.Window && is_async === false && (requestData['timeout'] || requestData['responseType']))
    1070       [ + ][ - ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: synchronous XMLHttpRequests do not support timeout and responseType`, 'InvalidAccessError');
    1071                 :        527 : 
    1072                 :        527 :         // @author. xhr.spec.9. will also be applicable to main thread
    1073            [ + ]:        772 :         if(threads.isMainThread && is_async === false && (requestData['timeout'] || requestData['responseType']))
    1074       [ + ][ + ]:        772 :                 throw new DOMException(`XMLHttpRequest.open: synchronous XMLHttpRequests do not support timeout and responseType`, 'InvalidAccessError');
    1075                 :        522 : 
    1076                 :        522 :         // xhr.spec.10. Terminate this’s fetch controller. Note: A fetch can be ongoing at this point.
    1077            [ + ]:        772 :         if(requestData['fetchController']){
    1078                 :          2 :                 requestData['fetchController'].destroy();
    1079                 :          2 :                 requestData['fetchController'] = null;
    1080            [ + ]:          2 :         }
    1081                 :        522 : 
    1082                 :        522 :         // xhr.spec.11. Set variables associated with the object as follows:
    1083                 :        522 :         // xhr.spec.11. Unset this’s send() flag.
    1084                 :        522 :         requestData['sendFlag'] = false;
    1085                 :        522 : 
    1086                 :        522 :         // xhr.spec.11. Unset this’s upload listener flag.
    1087                 :        522 :         requestData['uploadListenerFlag'] = false;
    1088                 :        522 : 
    1089                 :        522 :         // xhr.spec.11. Set this’s request method to method.
    1090                 :        522 :         requestData['method'] = method;
    1091                 :        522 : 
    1092                 :        522 :         // xhr.spec.11. Set this’s request URL to parsedURL.
    1093                 :        522 :         requestData['url'] = parsedURL.href;
    1094                 :        522 : 
    1095                 :        522 :         // xhr.spec.11. Set this’s synchronous flag if async is false; otherwise unset this’s synchronous flag.
    1096                 :        522 :         requestData['async'] = !(is_async === false);
    1097                 :        522 : 
    1098                 :        522 :         // xhr.spec.11. Empty this’s author request headers.
    1099                 :        522 : 
    1100                 :        522 :         requestData['requestHeaders'    ] = {};
    1101                 :        522 :         requestData['requestHeadersCase'] = {};
    1102                 :        522 : 
    1103                 :        522 :         // xhr.spec.11. Set this’s response to a network error.
    1104                 :        522 :         setResponseToNetworkError.call(this);
    1105                 :        522 : 
    1106                 :        522 :         // xhr.spec.11. Set this’s received bytes to the empty byte sequence.
    1107                 :        522 :         requestData['receivedBytes'] = Buffer.alloc(0);
    1108                 :        522 : 
    1109                 :        522 :         // xhr.spec.11. Set this’s response object to null.
    1110                 :        522 :         requestData['responseObject'] = null;
    1111                 :        522 : 
    1112                 :        522 :         // xhr.spec.12. If this’s state is not opened, then:
    1113            [ + ]:        772 :         if(requestData['readyState'] !== this.OPENED){
    1114                 :        514 : 
    1115                 :        514 :                 // xhr.spec.12.1. Set this’s state to opened.
    1116                 :        514 :                 requestData['readyState'] = this.OPENED;
    1117                 :        514 : 
    1118                 :        514 :                 // xhr.spec.12.2. Fire an event named readystatechange at this.
    1119                 :        514 :                 this.dispatchEvent(new Event('readystatechange'));
    1120                 :        514 :         }
    1121                 :        229 : }; // @endof method XMLHttpRequest.prototype.open
    1122                 :        229 : 
    1123                 :        229 : /**
    1124                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    1125                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-abort()-method
    1126                 :        229 :  *
    1127                 :        229 :  * client.abort()
    1128                 :        229 :  *   Cancels any network activity.
    1129                 :        229 :  *
    1130                 :        229 :  * The abort() method steps are:
    1131                 :        229 :  * 1. Abort this’s fetch controller.
    1132                 :        229 :  * 2. If this’s state is opened with this’s send() flag set, headers received, or loading, then run the request error steps for this and abort.
    1133                 :        229 :  * 3. If this’s state is done, then set this’s state to unsent and this’s response to a network error.
    1134                 :        229 :  * Note: No readystatechange event is dispatched.
    1135                 :        229 :  *
    1136                 :        229 :  * @method   abort
    1137                 :        229 :  * @instance
    1138                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
    1139                 :        229 :  * @desc     XMLHttpRequest method that aborts the request if it has already been sent.
    1140                 :        229 :  */
    1141            [ + ]:        229 : XMLHttpRequest.prototype.abort = function abort(){
    1142                 :          6 : 
    1143                 :          6 :         const requestData = xmlHttpRequest.get(this);
    1144                 :          6 : 
    1145                 :          6 :         // xhr.spec.1. Abort this’s fetch controller
    1146            [ + ]:          6 :         if(requestData['fetchController']){
    1147                 :          3 :                 requestData['fetchController'].destroy();
    1148                 :          3 :                 requestData['fetchController'] = null;
    1149                 :          3 :         }
    1150                 :          6 : 
    1151                 :          6 :         // xhr.spec.2. If this’s state is opened with this’s send() flag set, headers received,
    1152                 :          6 :         //             or loading, then run the request error steps for this and abort.
    1153                 :          6 :         if(
    1154       [ + ][ + ]:          6 :                 requestData['readyState'] === this.OPENED && requestData['sendFlag'] ||
    1155            [ + ]:          6 :                 requestData['readyState'] === this.HEADERS_RECEIVED ||
    1156                 :          1 :                 requestData['readyState'] === this.LOADING
    1157            [ + ]:          6 :         ){
    1158                 :          5 :                 requestErrorSteps.call(this, 'abort');
    1159                 :          5 :         }
    1160                 :          6 : 
    1161                 :          6 :         // xhr.spec.3. If this’s state is done, then set this’s state to unsent and this’s response to a network error.
    1162            [ + ]:          6 :         if(requestData['readyState'] === this.DONE){
    1163                 :          5 : 
    1164                 :          5 :                 requestData['readyState'] = this.UNSENT;
    1165                 :          5 :                 setResponseToNetworkError.call(this);
    1166                 :          5 :         }
    1167                 :        229 : }; // @endof method XMLHttpRequest.prototype.abort
    1168                 :        229 : 
    1169                 :        229 : /**
    1170                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    1171                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-setrequestheader()-method
    1172                 :        229 :  *
    1173                 :        229 :  * client.setRequestHeader(name, value)
    1174                 :        229 :  *   Appends a value to an existing request header or adds a new request header.
    1175                 :        229 :  *   Throws an "InvalidStateError" DOMException if either state is not opened or the send() flag is set.
    1176                 :        229 :  *   Throws a "SyntaxError" DOMException if name is not a header name or if value is not a header value.
    1177                 :        229 :  *
    1178                 :        229 :  * The setRequestHeader(name, value) method must run these steps:
    1179                 :        229 :  *   1. If this’s state is not opened, then throw an "InvalidStateError" DOMException.
    1180                 :        229 :  *   2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
    1181                 :        229 :  *   3. Normalize value.
    1182                 :        229 :  *   4. If name is not a header name or value is not a header value, then throw a "SyntaxError" DOMException.
    1183                 :        229 :  *   5. An empty byte sequence represents an empty header value.
    1184                 :        229 :  *   6. If (name, value) is a forbidden request-header, then return.
    1185                 :        229 :  *   7. Combine (name, value) in this’s author request headers.
    1186                 :        229 :  *
    1187                 :        229 :  * @method   setRequestHeader
    1188                 :        229 :  * @instance
    1189                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
    1190                 :        229 :  * @param    {string}  name  - The name of the header whose value is to be set.
    1191                 :        229 :  * @param    {string}  value - The value to set as the body of the header.
    1192                 :        229 :  * @desc     XMLHttpRequest method that sets the value of an HTTP request header.
    1193                 :        229 :  * @requires module:whatwg-fetch.forbiddenRequestHeader
    1194                 :        229 :  */
    1195            [ + ]:        229 : XMLHttpRequest.prototype.setRequestHeader = function setRequestHeader(name, value){
    1196                 :       2436 : 
    1197                 :       2436 :         // @author. validate the number of arguments
    1198                 :       2436 :         if(arguments.length < 2)
    1199       [ + ][ + ]:       2436 :                 throw new TypeError(`XMLHttpRequest.setRequestHeader: At least 2 arguments required, but only ${arguments.length} passed`);     // firefox 102
    1200                 :       1610 : 
    1201                 :       1610 :         const requestData = xmlHttpRequest.get(this);
    1202                 :       1610 : 
    1203                 :       1610 :         // xhr.spec.1. If this’s state is not opened, then throw an "InvalidStateError" DOMException.
    1204                 :       1610 :         if(requestData['readyState'] !== this.OPENED)
    1205       [ + ][ + ]:       2436 :                 throw new DOMException(`XMLHttpRequest.send: XMLHttpRequest state must be OPENED.`, 'InvalidStateError');       // firefox 102
    1206                 :       1605 : 
    1207                 :       1605 :         // xhr.spec.2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
    1208                 :       1605 :         if(requestData['sendFlag'])
    1209       [ + ][ + ]:       2436 :                 throw new DOMException(`XMLHttpRequest.send: XMLHttpRequest must not be sending.`, 'InvalidStateError');        // firefox 102
    1210                 :       1604 : 
    1211                 :       1604 :         // xhr.spec.3. Normalize value.
    1212                 :       1604 :         // fetch.spec. To normalize a byte sequence potentialValue, remove any leading and trailing HTTP whitespace bytes from potentialValue.
    1213                 :       1604 :         value = String(value).trim();
    1214                 :       1604 : 
    1215                 :       1604 :         // xhr.spec.4. If name is not a header name or value is not a header value, then throw a "SyntaxError" DOMException.
    1216                 :       1604 :         try{
    1217                 :       1604 :                 http.validateHeaderName(name);
    1218                 :       1604 :         }
    1219            [ + ]:       2436 :         catch(err){
    1220                 :         71 : 
    1221                 :         71 :                 name = String(name);
    1222            [ + ]:         71 :                 for(let i = 0; i < name.length; i++){
    1223            [ + ]:        110 :                         if(name[i].codePointAt(0) > 0xFF){
    1224                 :          2 :                                 let msg = '';
    1225                 :          2 : 
    1226                 :          2 :                                 msg += `XMLHttpRequest.setRequestHeader: `;
    1227                 :          2 :                                 msg += `Cannot convert argument 1 to ByteString because the character at index ${i} `;
    1228                 :          2 :                                 msg += `has value ${name[i].codePointAt(0)} which is greater than 255.`
    1229                 :          2 : 
    1230                 :          2 :                                 throw new TypeError(msg); // firefox 102
    1231                 :          2 :                         }
    1232            [ + ]:        110 :                 }
    1233                 :         69 : 
    1234                 :         69 :                 throw new DOMException(`XMLHttpRequest.setRequestHeader: Invalid header name.`, 'SyntaxError'); // firefox 102
    1235            [ + ]:         69 :         }
    1236                 :       1533 : 
    1237                 :       1533 :         try{
    1238                 :       1533 :                 http.validateHeaderValue(name, value);
    1239                 :       1533 :         }
    1240            [ + ]:       2436 :         catch(err){
    1241                 :          4 : 
    1242            [ + ]:          4 :                 for(let i = 0; i < value.length; i++){
    1243            [ + ]:         10 :                         if(value[i].codePointAt(0) > 0xFF){
    1244                 :          1 :                                 let msg = '';
    1245                 :          1 : 
    1246                 :          1 :                                 msg += `XMLHttpRequest.setRequestHeader: `;
    1247                 :          1 :                                 msg += `Cannot convert argument 2 to ByteString because the character at index ${i} `;
    1248                 :          1 :                                 msg += `has value ${value[i].codePointAt(0)} which is greater than 255.`
    1249                 :          1 : 
    1250                 :          1 :                                 throw new TypeError(msg); // firefox 102
    1251                 :          1 :                         }
    1252            [ + ]:         10 :                 }
    1253                 :          3 : 
    1254                 :          3 :                 throw new DOMException(`XMLHttpRequest.setRequestHeader: Invalid header value.`, 'SyntaxError'); // firefox 102
    1255            [ + ]:          3 :         }
    1256                 :       1529 : 
    1257                 :       1529 :         // xhr.spec.6. If (name, value) is a forbidden request-header, then return.
    1258            [ + ]:       2436 :         if(forbiddenRequestHeader(name, value)){
    1259                 :         22 :                 return;
    1260            [ + ]:         22 :         }
    1261                 :       1507 : 
    1262                 :       1507 :         const headers     = requestData['requestHeaders'];
    1263                 :       1507 :         const headersCase = requestData['requestHeadersCase'];
    1264                 :       1507 : 
    1265                 :       1507 :         // xhr.spec.7. Combine (name, value) in this’s author request headers.
    1266            [ + ]:       2436 :         if(headersCase[name.toLowerCase()]){
    1267                 :         13 :                 let nameCase = headersCase[name.toLowerCase()];
    1268                 :         13 :                 headers[nameCase] = headers[nameCase] ? headers[nameCase] + ', ' + value : value;
    1269            [ + ]:         13 :         }
    1270                 :       1494 :         else{
    1271                 :       1494 :                 headersCase[name.toLowerCase()] = name;
    1272                 :       1494 :                 headers[name] = value;
    1273                 :       1494 :         }
    1274                 :        229 : }; // @endof method XMLHttpRequest.prototype.setRequestHeader
    1275                 :        229 : 
    1276                 :        229 : /**
    1277                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    1278                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-send()-method
    1279                 :        229 :  *
    1280                 :        229 :  * client.send([body = null])
    1281                 :        229 :  *   Initiates the request. The body argument provides the request body, if any, and is ignored if the request method is GET or HEAD.
    1282                 :        229 :  *   Throws an "InvalidStateError" DOMException if either state is not opened or the send() flag is set.
    1283                 :        229 :  *
    1284                 :        229 :  * The send(body) method steps are:
    1285                 :        229 :  *   1. If this’s state is not opened, then throw an "InvalidStateError" DOMException.
    1286                 :        229 :  *   2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
    1287                 :        229 :  *   3. If this’s request method is `GET` or `HEAD`, then set body to null.
    1288                 :        229 :  *   4. If body is not null, then:
    1289                 :        229 :  *      1. Let extractedContentType be null.
    1290                 :        229 :  *      2. If body is a Document, then set this’s request body to body, serialized, converted, and UTF-8 encoded.
    1291                 :        229 :  *      3. Otherwise:
    1292                 :        229 :  *         1. Let bodyWithType be the result of safely extracting body.
    1293                 :        229 :  *         2. Set this’s request body to bodyWithType’s body.
    1294                 :        229 :  *         3. Set extractedContentType to bodyWithType’s type.
    1295                 :        229 :  *      4. Let originalAuthorContentType be the result of getting `Content-Type` from this’s author request headers.
    1296                 :        229 :  *      5. If originalAuthorContentType is non-null, then:
    1297                 :        229 :  *         1. If body is a Document or a USVString, then:
    1298                 :        229 :  *            1. Let contentTypeRecord be the result of parsing originalAuthorContentType.
    1299                 :        229 :  *            2. If contentTypeRecord is not failure, contentTypeRecord’s parameters["charset"] exists, and parameters["charset"] is not an ASCII case-insensitive
    1300                 :        229 :  *               match for "UTF-8", then:
    1301                 :        229 :  *               1. Set contentTypeRecord’s parameters["charset"] to "UTF-8".
    1302                 :        229 :  *               2. Let newContentTypeSerialized be the result of serializing contentTypeRecord.
    1303                 :        229 :  *               3. Set (`Content-Type`, newContentTypeSerialized) in this’s author request headers.
    1304                 :        229 :  *      6. Otherwise:
    1305                 :        229 :  *         1. If body is an HTML document, then set (`Content-Type`, `text/html;charset=UTF-8`) in this’s author request headers.
    1306                 :        229 :  *         2. Otherwise, if body is an XML document, set (`Content-Type`, `application/xml;charset=UTF-8`) in this’s author request headers.
    1307                 :        229 :  *         3. Otherwise, if extractedContentType is not null, set (`Content-Type`, extractedContentType) in this’s author request headers.
    1308                 :        229 :  *   5. If one or more event listeners are registered on this’s upload object, then set this’s upload listener flag.
    1309                 :        229 :  *   6. Let req be a new request, initialized as follows:
    1310                 :        229 :  *        method                    This’s request method.
    1311                 :        229 :  *        URL                       This’s request URL.
    1312                 :        229 :  *        header list               This’s author request headers.
    1313                 :        229 :  *        unsafe-request flag       Set.
    1314                 :        229 :  *        body                      This’s request body.
    1315                 :        229 :  *        client                    This’s relevant settings object.
    1316                 :        229 :  *        mode                      "cors".
    1317                 :        229 :  *        use-CORS-preflight flag   Set if this’s upload listener flag is set.
    1318                 :        229 :  *        credentials mode          If this’s cross-origin credentials is true, then "include"; otherwise "same-origin".
    1319                 :        229 :  *        use-URL-credentials flag  Set if this’s request URL includes credentials.
    1320                 :        229 :  *        initiator type            "xmlhttprequest".
    1321                 :        229 :  *   7. Unset this’s upload complete flag.
    1322                 :        229 :  *   8. Unset this’s timed out flag.
    1323                 :        229 :  *   9. If req’s body is null, then set this’s upload complete flag.
    1324                 :        229 :  *  10. Set this’s send() flag.
    1325                 :        229 :  *  11. If this’s synchronous flag is unset, then:
    1326                 :        229 :  *      1. Fire a progress event named loadstart at this with 0 and 0.
    1327                 :        229 :  *      2. Let requestBodyTransmitted be 0.
    1328                 :        229 :  *      3. Let requestBodyLength be req’s body’s length, if req’s body is non-null; otherwise 0.
    1329                 :        229 :  *      4. Assert: requestBodyLength is an integer.
    1330                 :        229 :  *      5. If this’s upload complete flag is unset and this’s upload listener flag is set, then fire a progress event named loadstart at this’s upload object
    1331                 :        229 :  *         with requestBodyTransmitted and requestBodyLength.
    1332                 :        229 :  *      6. If this’s state is not opened or this’s send() flag is unset, then return.
    1333                 :        229 :  *      7. Let processRequestBodyChunkLength, given a bytesLength, be these steps:
    1334                 :        229 :  *         1. Increase requestBodyTransmitted by bytesLength.
    1335                 :        229 :  *         2. If not roughly 50ms have passed since these steps were last invoked, then return.
    1336                 :        229 :  *         3. If this’s upload listener flag is set, then fire a progress event named progress at this’s upload object with requestBodyTransmitted and
    1337                 :        229 :  *            requestBodyLength.
    1338                 :        229 :  *         Note: These steps are only invoked when new bytes are transmitted.
    1339                 :        229 :  *      8. Let processRequestEndOfBody be these steps:
    1340                 :        229 :  *         1. Set this’s upload complete flag.
    1341                 :        229 :  *         2. If this’s upload listener flag is unset, then return.
    1342                 :        229 :  *         3. Fire a progress event named progress at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1343                 :        229 :  *         4. Fire a progress event named load at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1344                 :        229 :  *         5. Fire a progress event named loadend at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1345                 :        229 :  *      9. Let processResponse, given a response, be these steps:
    1346                 :        229 :  *         1. Set this’s response to response.
    1347                 :        229 :  *         2. Handle errors for this.
    1348                 :        229 :  *         3. If this’s response is a network error, then return.
    1349                 :        229 :  *         4. Set this’s state to headers received.
    1350                 :        229 :  *         5. Fire an event named readystatechange at this.
    1351                 :        229 :  *         6. If this’s state is not headers received, then return.
    1352                 :        229 :  *         7. If this’s response’s body is null, then run handle response end-of-body for this and return.
    1353                 :        229 :  *         8. Let length be the result of extracting a length from this’s response’s header list.
    1354                 :        229 :  *         9. If length is not an integer, then set it to 0.
    1355                 :        229 :  *        10. Let processBodyChunk given bytes be these steps:
    1356                 :        229 :  *            1. Append bytes to this’s received bytes.
    1357                 :        229 :  *            2. If not roughly 50ms have passed since these steps were last invoked, then return.
    1358                 :        229 :  *            3. If this’s state is headers received, then set this’s state to loading.
    1359                 :        229 :  *            4. Fire an event named readystatechange at this.
    1360                 :        229 :  *               Note: Web compatibility is the reason readystatechange fires more often than this’s state changes.
    1361                 :        229 :  *            5. Fire a progress event named progress at this with this’s received bytes’s length and length.
    1362                 :        229 :  *        11. Let processEndOfBody be this step: run handle response end-of-body for this.
    1363                 :        229 :  *        12. Let processBodyError be these steps:
    1364                 :        229 :  *            1. Set this’s response to a network error.
    1365                 :        229 :  *            2.  Run handle errors for this.
    1366                 :        229 :  *        13. Incrementally read this’s response’s body, given processBodyChunk, processEndOfBody, processBodyError, and this’s relevant global object.
    1367                 :        229 :  *     10. Set this’s fetch controller to the result of fetching req with processRequestBodyChunkLength set to processRequestBodyChunkLength,
    1368                 :        229 :  *         processRequestEndOfBody set to processRequestEndOfBody, and processResponse set to processResponse.
    1369                 :        229 :  *     11. Let now be the present time.
    1370                 :        229 :  *     12. Run these steps in parallel:
    1371                 :        229 :  *         1. Wait until either req’s done flag is set or this’s timeout is not 0 and this’s timeout milliseconds have passed since now.
    1372                 :        229 :  *         2. If req’s done flag is unset, then set this’s timed out flag and terminate this’s fetch controller.
    1373                 :        229 :  *  12. Otherwise, if this’s synchronous flag is set:
    1374                 :        229 :  *      1. Let processedResponse be false.
    1375                 :        229 :  *      2. Let processResponseConsumeBody, given a response and nullOrFailureOrBytes, be these steps:
    1376                 :        229 :  *         1. If nullOrFailureOrBytes is not failure, then set this’s response to response.
    1377                 :        229 :  *         2. If nullOrFailureOrBytes is a byte sequence, then append nullOrFailureOrBytes to this’s received bytes.
    1378                 :        229 :  *         3. Set processedResponse to true.
    1379                 :        229 :  *      3. Set this’s fetch controller to the result of fetching req with processResponseConsumeBody set to processResponseConsumeBody and
    1380                 :        229 :  *         useParallelQueue set to true.
    1381                 :        229 :  *      4. Let now be the present time.
    1382                 :        229 :  *      5. Pause until either processedResponse is true or this’s timeout is not 0 and this’s timeout milliseconds have passed since now.
    1383                 :        229 :  *      6. If processedResponse is false, then set this’s timed out flag and terminate this’s fetch controller.
    1384                 :        229 :  *      7. Report timing for this’s fetch controller given the current global object.
    1385                 :        229 :  *      8. Run handle response end-of-body for this.
    1386                 :        229 :  *
    1387                 :        229 :  * To handle response end-of-body for an XMLHttpRequest object xhr, run these steps:
    1388                 :        229 :  *      1. Handle errors for xhr.
    1389                 :        229 :  *      2. If xhr’s response is a network error, then return.
    1390                 :        229 :  *      3. Let transmitted be xhr’s received bytes’s length.
    1391                 :        229 :  *      4. Let length be the result of extracting a length from this’s response’s header list.
    1392                 :        229 :  *      5. If length is not an integer, then set it to 0.
    1393                 :        229 :  *      6. If xhr’s synchronous flag is unset, then fire a progress event named progress at xhr with transmitted and length.
    1394                 :        229 :  *      7. Set xhr’s state to done.
    1395                 :        229 :  *      8. Unset xhr’s send() flag.
    1396                 :        229 :  *      9. Fire an event named readystatechange at xhr.
    1397                 :        229 :  *     10. Fire a progress event named load at xhr with transmitted and length.
    1398                 :        229 :  *     11. Fire a progress event named loadend at xhr with transmitted and length.
    1399                 :        229 :  *
    1400                 :        229 :  * @method   send
    1401                 :        229 :  * @instance
    1402                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
    1403                 :        229 :  * @param    {Document| Blob|ArrayBuffer|TypedArray|DataView|FormData|URLSearchParams|string|null} body - The request body.
    1404                 :        229 :  * @desc     XMLHttpRequest method that sends the request to the server.
    1405                 :        229 :  * @requires module:whatwg-fetch.safelyExtractBodyWithType
    1406                 :        229 :  * @requires module:helper-content-type.parse
    1407                 :        229 :  * @requires module:helper-content-type.format
    1408                 :        229 :  */
    1409            [ + ]:        229 : XMLHttpRequest.prototype.send = function send(body = null){
    1410                 :        766 : 
    1411                 :        766 :         const xhr = this;
    1412                 :        766 :         const requestData = xmlHttpRequest.get(xhr);
    1413                 :        766 : 
    1414                 :        766 :         // xhr.spec.1. If this’s state is not opened, then throw an "InvalidStateError" DOMException.
    1415                 :        766 :         if(requestData['readyState'] !== xhr.OPENED)
    1416       [ + ][ + ]:        766 :                 throw new DOMException(`XMLHttpRequest.send: XMLHttpRequest state must be OPENED.`, 'InvalidStateError');       // firefox 102
    1417                 :        492 : 
    1418                 :        492 :         // xhr.spec.2. If this’s send() flag is set, then throw an "InvalidStateError" DOMException.
    1419                 :        492 :         if(requestData['sendFlag'])
    1420       [ + ][ + ]:        766 :                 throw new DOMException(`XMLHttpRequest.send: XMLHttpRequest must not be sending.`, 'InvalidStateError');        // firefox 102
    1421                 :        491 : 
    1422                 :        491 :         // xhr.spec.3. If this’s request method is `GET` or `HEAD`, then set body to null.
    1423       [ + ][ + ]:        766 :         if(requestData['method'].toUpperCase() === 'GET' || requestData['method'].toUpperCase() === 'HEAD'){
    1424                 :        263 :                 body = null;
    1425            [ + ]:        263 :         }
    1426                 :        491 : 
    1427                 :        491 :         // xhr.spec.4. If body is not null, then:
    1428       [ + ][ + ]:        766 :         if(body !== null && body !== ''){
    1429                 :         85 : 
    1430                 :         85 :                 // xhr.spec.4.1. Let extractedContentType be null.
    1431                 :         85 :                 let extractedContentType = null;
    1432                 :         85 : 
    1433                 :         85 :                 // xhr.spec.4.2. If body is a Document, then set this’s request body to body, serialized, converted, and UTF-8 encoded.
    1434                 :         85 :                 if(globalThis.Document && body instanceof globalThis.Document){
    1435                 :         85 :                         // @todo. xhr.spec.4.2. set this’s request body to body, serialized, converted, and UTF-8 encoded.
    1436                 :         85 :                 }
    1437                 :         85 :                 // xhr.spec.4.3. Otherwise:
    1438                 :         85 :                 else{
    1439                 :         85 :                         // xhr.spec.4.3.1. Let bodyWithType be the result of safely extracting body.
    1440                 :         85 :                         let bodyWithType = safelyExtractBodyWithType(body);
    1441                 :         85 : 
    1442                 :         85 :                         // xhr.spec.4.3.2. Set this’s request body to bodyWithType’s body.
    1443                 :         85 :                         requestData['requestBody'] = bodyWithType.body;
    1444                 :         85 : 
    1445                 :         85 :                         // xhr.spec.4.3.3. Set extractedContentType to bodyWithType’s type.
    1446                 :         85 :                         extractedContentType = bodyWithType.type;
    1447                 :         85 :                 }
    1448                 :         85 : 
    1449                 :         85 :                 // xhr.spec.4.4. Let originalAuthorContentType be the result of getting `Content-Type` from this’s author request headers.
    1450                 :         85 :                 let originalAuthorContentType = null;
    1451                 :         85 : 
    1452                 :         85 :                 if(requestData['requestHeadersCase']['content-type'])
    1453            [ + ]:         85 :                         originalAuthorContentType = requestData['requestHeaders'][requestData['requestHeadersCase']['content-type']];
    1454                 :         85 : 
    1455                 :         85 :                 // xhr.spec.4.5. If originalAuthorContentType is non-null, then:
    1456            [ + ]:         85 :                 if(originalAuthorContentType !== null){
    1457                 :         31 : 
    1458                 :         31 :                         // xhr.spec.4.5.1. If body is a Document or a USVString, then:
    1459                 :         31 :                         if(
    1460                 :         31 :                                 (globalThis.Document && body instanceof globalThis.Document) ||
    1461       [ + ][ + ]:         31 :                                 typeof body === 'string' || typeof requestData['requestBody'].source === 'string'){
    1462                 :         21 :                                 try{
    1463                 :         21 :                                         // xhr.spec.4.5.1.1. Let contentTypeRecord be the result of parsing originalAuthorContentType.
    1464                 :         21 :                                         const contentTypeRecord = contentTypeParse(originalAuthorContentType);
    1465                 :         21 : 
    1466                 :         21 :                                         // xhr.spec.4.5.1.2. If contentTypeRecord is not failure,
    1467                 :         21 :                                         //                   contentTypeRecord’s parameters["charset"] exists,
    1468                 :         21 :                                         //                   and parameters["charset"] is not an ASCII case-insensitive match for "UTF-8", then:
    1469                 :         21 :                                         let charset = contentTypeRecord.parameters['charset'];
    1470       [ + ][ + ]:         21 :                                         if(charset && charset.toUpperCase() !== 'UTF-8'){
    1471                 :          6 : 
    1472                 :          6 :                                                 // xhr.spec.4.5.1.2.1. Set contentTypeRecord’s parameters["charset"] to "UTF-8".
    1473                 :          6 :                                                 contentTypeRecord.parameters['charset'] = 'UTF-8';
    1474                 :          6 : 
    1475                 :          6 :                                                 // xhr.spec.4.5.1.2.2. Let newContentTypeSerialized be the result of serializing contentTypeRecord.
    1476                 :          6 :                                                 let newContentTypeSerialized = contentTypeFormat(contentTypeRecord);
    1477                 :          6 : 
    1478                 :          6 :                                                 // xhr.spec.4.5.1.2.3. Set (`Content-Type`, newContentTypeSerialized) in this’s author request headers.
    1479                 :          6 :                                                 // @author. first delete the existing Content-Type header
    1480                 :          6 :                                                 delete requestData['requestHeaders'][requestData['requestHeadersCase']['content-type']];
    1481                 :          6 :                                                 delete requestData['requestHeadersCase']['content-type'];
    1482                 :          6 : 
    1483                 :          6 :                                                 this.setRequestHeader('Content-Type', newContentTypeSerialized);
    1484                 :          6 :                                         }
    1485            [ + ]:         21 :                                 }catch(e){}
    1486                 :         21 :                         }
    1487            [ + ]:         31 :                 }
    1488                 :         54 :                 // xhr.spec.4.6. Otherwise:
    1489                 :         54 :                 else{
    1490                 :         54 :                         // xhr.spec.4.6.1. If body is an HTML document, then set (`Content-Type`, `text/html;charset=UTF-8`) in this’s author request headers.
    1491                 :         54 :                         if(globalThis.Document && body instanceof globalThis.Document && body.type === 'html')
    1492                 :         54 :                                 this.setRequestHeader('Content-Type', 'text/html;charset=UTF-8');
    1493                 :         54 :                         else
    1494                 :         54 :                         // xhr.spec.4.6.2. Otherwise, if body is an XML document, set (`Content-Type`, `application/xml;charset=UTF-8`) in this’s author request headers.
    1495                 :         54 :                         if(globalThis.Document && body instanceof globalThis.Document && body.type === 'xml')
    1496                 :         54 :                                 this.setRequestHeader('Content-Type', 'application/xml;charset=UTF-8');
    1497                 :         54 :                         else
    1498                 :         54 :                         // xhr.spec.4.6.3. Otherwise, if extractedContentType is not null, set (`Content-Type`, extractedContentType) in this’s author request headers.
    1499            [ + ]:         54 :                         if(extractedContentType){
    1500                 :         41 :                                 this.setRequestHeader('Content-Type', extractedContentType);
    1501                 :         41 :                         }
    1502                 :         54 :                 }
    1503            [ + ]:        766 :         } // @endof if(body !== null && body !== undefined)
    1504                 :        491 : 
    1505                 :        491 :         // xhr.spec.5. If one or more event listeners are registered on this’s upload object, then set this’s upload listener flag.
    1506                 :        491 :         if(
    1507            [ + ]:        766 :                 requestData['upload']['onloadstart'] !== null ||
    1508            [ + ]:        766 :                 requestData['upload']['onprogress' ] !== null ||
    1509            [ + ]:        766 :                 requestData['upload']['onabort'    ] !== null ||
    1510            [ + ]:        766 :                 requestData['upload']['onerror'    ] !== null ||
    1511            [ + ]:        766 :                 requestData['upload']['onload'     ] !== null ||
    1512            [ + ]:        766 :                 requestData['upload']['ontimeout'  ] !== null ||
    1513                 :        470 :                 requestData['upload']['onloadend'  ] !== null
    1514            [ + ]:        766 :         ){
    1515                 :         25 :                 requestData['uploadListenerFlag'] = true;
    1516            [ + ]:         25 :         }
    1517                 :        466 :         else
    1518                 :        466 :         // @author. an implementation dependent method to inspect if any event listeners had been registered by calling addEventListener.
    1519                 :        466 :         // @todo.   suggest an implementation independent method
    1520       [ + ][ + ]:        466 :         if(Object.getOwnPropertySymbols(requestData['upload']).filter(e => requestData['upload'][e].size).length){
    1521                 :          3 :                 requestData['uploadListenerFlag'] = true;
    1522            [ + ]:          3 :         }
    1523                 :        491 : 
    1524                 :        491 :         // xhr.spec.6. Let req be a new request, initialized as follows:
    1525       [ + ][ - ]:        766 :         let req_auth = requestData['user'] ? `${requestData['user']}:${requestData['password'] === undefined ? '' : requestData['password']}` : undefined;
    1526                 :        766 : 
    1527                 :        766 :         // xhr.spec.6. method: This’s request method.
    1528                 :        766 :         let req_method = requestData['method'];
    1529                 :        766 : 
    1530                 :        766 :         // xhr.spec.6. URL: This’s request URL.
    1531                 :        766 :         let req_url = new URL(requestData['url']);
    1532                 :        766 : 
    1533                 :        766 :         let req_host     = req_url.hostname;
    1534            [ + ]:        766 :         let req_port     = req_url.port || (req_url.protocol === 'https:' ? 443 : 80);
    1535       [ + ][ + ]:        766 :         let req_url_path = req_url.pathname + (req_url.search ? req_url.search : '');
    1536                 :        766 :         let req_protocol = req_url.protocol;
    1537                 :        766 : 
    1538                 :        766 :         // xhr.spec.6. header list: This’s author request headers.
    1539                 :        766 :         const req_headers     = requestData['requestHeaders'];
    1540                 :        766 :         const req_headersCase = requestData['requestHeadersCase'];
    1541                 :        766 : 
    1542            [ + ]:        766 :         for(let name in defaultHeaders()){
    1543            [ + ]:       2292 :                 if(!req_headersCase[name.toLowerCase()]){
    1544                 :       1324 :                         xhr.setRequestHeader(name, defaultHeaders()[name]);
    1545                 :       1324 :                 }
    1546            [ + ]:       2292 :         }
    1547                 :        491 : 
    1548                 :        491 :         // xhr.spec.6. unsafe-request flag: Set.
    1549                 :        491 :         // xhr.spec.6. body: This’s request body.
    1550                 :        491 :         // xhr.spec.6. client: This’s relevant settings object.
    1551                 :        491 :         // xhr.spec.6. mode: "cors".
    1552                 :        491 :         // xhr.spec.6. use-CORS-preflight flag: Set if this’s upload listener flag is set.
    1553                 :        491 :         // xhr.spec.6. credentials mode: If this’s cross-origin credentials is true, then "include"; otherwise "same-origin".
    1554                 :        491 :         // xhr.spec.6. use-URL-credentials flag:  Set if this’s request URL includes credentials.
    1555                 :        491 :         // xhr.spec.6. initiator type: "xmlhttprequest".
    1556                 :        491 : 
    1557                 :        491 :         // @author. use http.request(url[, options][, callback])
    1558                 :        491 :         const clientRequestOptions = {
    1559                 :        491 :                 agent:           false,
    1560                 :        491 :                 auth:            req_auth,
    1561                 :        491 :                 headers:         req_headers,
    1562                 :        491 :                 host:            req_host,
    1563                 :        491 :                 port:            req_port,
    1564                 :        491 :                 method:          req_method,
    1565                 :        491 :                 path:            req_url_path,
    1566                 :        491 :                 protocol:        req_url.protocol,
    1567                 :        491 :                 setHost:         true,
    1568                 :        491 :                 timeout:         requestData['timeout'],
    1569                 :        491 :                 withCredentials: requestData['withCredentials'],
    1570                 :        491 :                 // insecureHTTPParser: true,
    1571                 :        491 :                 url:             requestData['url'],
    1572                 :        491 :         };
    1573                 :        491 : 
    1574                 :        491 :         // @author. choose the proper protocol
    1575                 :        491 :         let doClientRequest;
    1576                 :        491 : 
    1577                 :        491 :         if(req_protocol === 'https:')
    1578       [ + ][ - ]:        766 :                 doClientRequest = https.request;
    1579                 :        491 :         else
    1580                 :        491 :         if(req_protocol === 'http:')
    1581  [ + ][ + ][ + ]:        491 :                 doClientRequest = http.request;
    1582                 :          3 :         else
    1583                 :          3 :         if(req_protocol === 'data:')
    1584       [ + ][ + ]:          3 :                 doClientRequest = requestDataURL;
    1585                 :          3 :         else
    1586            [ + ]:          3 :                 doClientRequest = http.request;
    1587                 :        491 : 
    1588                 :        491 :         // xhr.spec.7. Unset this’s upload complete flag.
    1589                 :        491 :         requestData['uploadCompleteFlag'] = false;
    1590                 :        491 : 
    1591                 :        491 :         // xhr.spec.8. Unset this’s timed out flag.
    1592                 :        491 :         requestData['timeoutFlag'] = false;
    1593                 :        491 : 
    1594                 :        491 :         // xhr.spec.9. If req’s body is null, then set this’s upload complete flag.
    1595                 :        491 :         if(requestData['requestBody'] === null)
    1596       [ + ][ + ]:        766 :                 requestData['uploadCompleteFlag'] = true;
    1597                 :        491 : 
    1598                 :        491 :         // xhr.spec.10. Set this’s send() flag.
    1599                 :        491 :         requestData['sendFlag'] = true;
    1600                 :        491 : 
    1601                 :        491 :         // xhr.spec.11. If this’s synchronous flag is unset, then:
    1602            [ + ]:        766 :         if(requestData['async']){
    1603                 :        263 : 
    1604                 :        263 :                 // xhr.spec.11.1. Fire a progress event named loadstart at this with 0 and 0.
    1605                 :        263 :                 xhr.dispatchEvent(new ProgressEvent('loadstart', {loaded: 0, total: 0}));
    1606                 :        263 : 
    1607                 :        263 :                 // xhr.spec.11.2. Let requestBodyTransmitted be 0.
    1608                 :        263 :                 let requestBodyTransmitted = 0;
    1609                 :        263 : 
    1610                 :        263 :                 // xhr.spec.11.3. Let requestBodyLength be req’s body’s length, if req’s body is non-null; otherwise 0.
    1611       [ + ][ + ]:        263 :                 let requestBodyLength = requestData['requestBody'] ? requestData['requestBody'].length : 0;
    1612                 :        263 : 
    1613                 :        263 :                 // xhr.spec.11.4. Assert: requestBodyLength is an integer.
    1614                 :        263 :                 if(isNaN(requestBodyLength))
    1615            [ - ]:        263 :                         requestBodyLength = 0;
    1616                 :        263 : 
    1617                 :        263 :                 // xhr.spec.11.5. If this’s upload complete flag is unset and this’s upload listener flag is set,
    1618                 :        263 :                 // then fire a progress event named loadstart at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1619            [ + ]:        263 :                 if(!requestData['uploadCompleteFlag'] && requestData['uploadListenerFlag'])
    1620            [ + ]:        263 :                         requestData['upload'].dispatchEvent(new ProgressEvent('loadstart', {loaded: requestBodyTransmitted, total: requestBodyLength}));
    1621                 :        263 : 
    1622                 :        263 :                 // xhr.spec.11.6. If this’s state is not opened or this’s send() flag is unset, then return.
    1623            [ + ]:        263 :                 if(requestData['readyState'] !== xhr.OPENED || !requestData['sendFlag'])
    1624       [ + ][ + ]:        263 :                         return;
    1625                 :        260 : 
    1626                 :        260 :                 // xhr.spec.11.7. Let processRequestBodyChunkLength, given a bytesLength, be these steps:
    1627                 :        260 :                 //                Note: These steps are only invoked when new bytes are transmitted.
    1628            [ + ]:        260 :                 const processRequestBodyChunkLength = () => {
    1629                 :         84 :                         let bytesLength = requestData['requestBody'].length; // @?????
    1630                 :         84 : 
    1631                 :         84 :                         // xhr.spec.11.7.1. Increase requestBodyTransmitted by bytesLength.
    1632                 :         84 :                         requestBodyTransmitted += bytesLength;
    1633                 :         84 : 
    1634                 :         84 :                         // xhr.spec.11.7.2. If not roughly 50ms have passed since these steps were last invoked, then return.
    1635                 :         84 :                         // @todo...
    1636                 :         84 : 
    1637                 :         84 :                         // xhr.spec.11.7.3. If this’s upload listener flag is set, then fire a progress event named progress at this’s upload object
    1638                 :         84 :                         //                  with requestBodyTransmitted and requestBodyLength.
    1639            [ + ]:         84 :                         if(requestData['uploadListenerFlag']){
    1640                 :         19 :                                 requestData['upload'].dispatchEvent(new ProgressEvent('progress', {loaded: requestBodyTransmitted, total: requestBodyLength}));
    1641                 :         19 :                         }
    1642                 :         84 :                 }
    1643                 :        260 : 
    1644                 :        260 :                 // xhr.spec.11.8. Let processRequestEndOfBody be these steps:
    1645            [ + ]:        260 :                 const processRequestEndOfBody = () => {
    1646                 :         79 : 
    1647                 :         79 :                         // xhr.spec.11.8.1. Set this’s upload complete flag.
    1648                 :         79 :                         requestData['uploadCompleteFlag'] = true;
    1649                 :         79 : 
    1650                 :         79 :                         // xhr.spec.11.8.2. If this’s upload listener flag is unset, then return.
    1651       [ + ][ + ]:         79 :                         if(!requestData['uploadListenerFlag']) return;
    1652                 :         15 : 
    1653                 :         15 :                         // xhr.spec.11.8.3. Fire a progress event named progress at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1654                 :         15 :                         // requestData['upload'].dispatchEvent(new ProgressEvent('progress', {loaded: requestBodyTransmitted, total: requestBodyLength}));
    1655                 :         15 : 
    1656                 :         15 :                         // xhr.spec.11.8.4. Fire a progress event named load at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1657                 :         15 :                         requestData['upload'].dispatchEvent(new ProgressEvent('load', {loaded: requestBodyTransmitted, total: requestBodyLength}));
    1658                 :         15 : 
    1659                 :         15 :                         // xhr.spec.11.8.5. Fire a progress event named loadend at this’s upload object with requestBodyTransmitted and requestBodyLength.
    1660                 :         15 :                         requestData['upload'].dispatchEvent(new ProgressEvent('loadend', {loaded: requestBodyTransmitted, total: requestBodyLength}));
    1661                 :         79 :                 }
    1662                 :        260 : 
    1663                 :        260 :                 // xhr.spec.11.9. Let processResponse, given a response, be these steps:
    1664            [ + ]:        260 :                 const processResponse = (response) => {
    1665                 :        505 : 
    1666                 :        505 :                         // xhr.spec.11.9.1. Set this’s response to response.
    1667                 :        505 :                         requestData['response'] = response;
    1668                 :        505 : 
    1669                 :        505 :                         // xhr.spec.11.9.2. Handle errors for this. // @?????
    1670                 :        505 :                         handleError.call(xhr);
    1671                 :        505 : 
    1672                 :        505 :                         // xhr.spec.11.9.3. If this’s response is a network error, then return. // @?????
    1673            [ + ]:        505 :                         if(!response.statusCode){
    1674                 :          1 :                                 setResponseToNetworkError.call(this);
    1675                 :          1 :                                 return;
    1676            [ + ]:          1 :                         }
    1677                 :        243 :                         else
    1678            [ + ]:        243 :                         if( response.headers['location'] &&
    1679                 :         67 :                                 (
    1680            [ + ]:         67 :                                         response.statusCode === 301 ||
    1681            [ + ]:         67 :                                         response.statusCode === 302 ||
    1682            [ + ]:         67 :                                         response.statusCode === 303 ||
    1683            [ + ]:         67 :                                         response.statusCode === 307 ||
    1684                 :          9 :                                         response.statusCode === 308
    1685                 :         67 :                                 )
    1686            [ + ]:        243 :                         ){
    1687            [ + ]:         59 :                                 if(requestData['_redirectCount'] >= 20){
    1688                 :          4 : 
    1689                 :          4 :                                         setResponseToNetworkError.call(xhr);
    1690                 :          4 :                                         handleError.call(xhr);
    1691                 :          4 : 
    1692                 :          4 :                                         return;
    1693            [ + ]:          4 :                                 }
    1694                 :         97 :                                 requestData['_redirectCount']++;
    1695                 :         97 : 
    1696                 :         97 :                                 let loc = response.headers['location'];
    1697                 :         97 : 
    1698                 :         97 :                                 let parsedURL;
    1699                 :         97 :                                 try{
    1700                 :         97 :                                         parsedURL = new URL(loc, new URL(requestData['url']).origin);
    1701                 :         97 :                                 }
    1702                 :         59 :                                 catch(e){
    1703                 :         59 :                                         // xhr.spec.open.6. If parsedURL is failure, then throw a "SyntaxError" DOMException
    1704                 :         59 :                                         throw new DOMException(`XMLHttpRequest.open: an invalid or illegal url string was specified`, 'SyntaxError');
    1705            [ + ]:         59 :                                 }
    1706                 :         97 : 
    1707                 :         97 :                                 requestData['url'] = parsedURL.href;
    1708                 :         97 :                                 requestData['receivedBytes'] = Buffer.alloc(0);
    1709                 :         97 :                                 requestData['responseObject'] = null;
    1710                 :         97 :                                 requestData['sendFlag'] = false;
    1711                 :         97 :                                 requestData['async'] = true;
    1712                 :         97 : 
    1713                 :         97 :                                 if(
    1714                 :         97 :                                         response.statusCode >= 301                    &&
    1715            [ + ]:         59 :                                         response.statusCode <= 303                    &&
    1716            [ + ]:         59 :                                         requestData['method'].toUpperCase() !== 'GET' &&
    1717                 :          4 :                                         requestData['method'].toUpperCase() !== 'HEAD'
    1718            [ + ]:         59 :                                 ){
    1719                 :          4 :                                         requestData['method'] = 'GET';
    1720                 :          4 :                                         requestData['requestBody'] = body = null;
    1721                 :          4 : 
    1722                 :          4 :                                         for(let headerCase in requestData['requestHeadersCase'])
    1723            [ + ]:          4 :                                                 if(
    1724            [ + ]:         15 :                                                         headerCase === 'content-type'     ||
    1725            [ + ]:         15 :                                                         headerCase === 'content-length'   ||
    1726            [ + ]:         15 :                                                         headerCase === 'content-encoding' ||
    1727            [ + ]:         15 :                                                         headerCase === 'content-location' ||
    1728                 :         12 :                                                         headerCase === 'content-language'
    1729            [ + ]:         15 :                                                 ){
    1730                 :          3 :                                                         let header = requestData['requestHeadersCase'][headerCase];
    1731                 :          3 : 
    1732                 :          3 :                                                         delete requestData['requestHeaders'][header];
    1733                 :          3 :                                                         delete requestData['requestHeadersCase'][headerCase];
    1734                 :          3 :                                                 }
    1735            [ + ]:          4 :                                 }
    1736                 :         97 : 
    1737                 :         97 :                                 xhr.onloadstart = null;
    1738                 :         97 : 
    1739                 :         97 :                                 xhr.upload.onloadstart = null;
    1740                 :         97 :                                 xhr.upload.onprogress  = null;
    1741                 :         97 :                                 xhr.upload.onabort     = null;
    1742                 :         97 :                                 xhr.upload.onerror     = null;
    1743                 :         97 :                                 xhr.upload.onload      = null;
    1744                 :         97 :                                 xhr.upload.ontimeout   = null;
    1745                 :         97 :                                 xhr.upload.onloadend   = null;
    1746                 :         97 : 
    1747                 :         97 :                                 xhr.send(body);
    1748                 :         97 : 
    1749                 :         97 :                                 return;
    1750            [ + ]:         97 :                         }
    1751                 :        184 : 
    1752                 :        184 :                         requestData['status']     =  response.statusCode;
    1753                 :        184 :                         requestData['statusText'] =  response.statusMessage;
    1754                 :        184 : 
    1755                 :        184 :                         // xhr.spec.11.9.4. Set this’s state to headers received.
    1756                 :        184 :                         requestData['readyState'] = xhr.HEADERS_RECEIVED;
    1757                 :        184 : 
    1758                 :        184 :                         // xhr.spec.11.9.5. Fire an event named readystatechange at this.
    1759                 :        184 :                         xhr.dispatchEvent(new Event('readystatechange'));
    1760                 :        184 : 
    1761                 :        184 :                         // xhr.spec.11.9.6. If this’s state is not headers received, then return.
    1762       [ + ][ - ]:        505 :                         if(requestData['readyState'] !== xhr.HEADERS_RECEIVED) return;
    1763                 :        184 : 
    1764                 :        184 :                         // xhr.spec.11.9.7. If this’s response’s body is null, then run handle response end-of-body for this and return.
    1765                 :        184 : 
    1766                 :        184 : 
    1767                 :        184 :                         // xhr.spec.11.9.8. Let length be the result of extracting a length from this’s response’s header list.
    1768                 :        184 :                         // xhr.spec.11.9.9. If length is not an integer, then set it to 0.
    1769                 :        184 :                         let length = 0;
    1770                 :        184 : 
    1771            [ + ]:        505 :                         if(response.headers['content-length'] && !isNaN(+response.headers['content-length']))
    1772       [ + ][ + ]:        505 :                                 length = +response.headers['content-length'];
    1773                 :        184 : 
    1774                 :        184 :                         // xhr.spec.11.9.10. Let processBodyChunk given bytes be these steps:
    1775            [ + ]:        184 :                         response.on('data', (chunk) => {
    1776                 :        318 : 
    1777                 :        318 :                                 // xhr.spec.11.9.10.1. Append bytes to this’s received bytes.
    1778                 :        318 :                                 requestData['receivedBytes'] = Buffer.concat([requestData['receivedBytes'], chunk]);
    1779                 :        318 : 
    1780                 :        318 :                                 // xhr.spec.11.9.10.2. If not roughly 50ms have passed since these steps were last invoked, then return.
    1781                 :        318 :                                 // @todo...
    1782                 :        318 : 
    1783                 :        318 :                                 // xhr.spec.11.9.10.3. If this’s state is headers received, then set this’s state to loading.
    1784                 :        318 :                                 if(requestData['readyState'] === xhr.HEADERS_RECEIVED)
    1785            [ + ]:        318 :                                         requestData['readyState'] = xhr.LOADING;
    1786                 :        318 : 
    1787                 :        318 :                                 // xhr.spec.11.9.10.4. Fire an event named readystatechange at this.
    1788                 :        318 :                                 xhr.dispatchEvent(new Event('readystatechange'));
    1789                 :        318 : 
    1790                 :        318 :                                 // xhr.spec.11.9.10.5. Fire a progress event named progress at this with this’s received bytes’s length and length.
    1791                 :        318 :                                 xhr.dispatchEvent(new ProgressEvent('progress', {loaded: requestData['receivedBytes'].length, total: length}));
    1792                 :        184 :                         });
    1793                 :        184 : 
    1794                 :        184 :                         // xhr.spec.11.9.11. Let processEndOfBody be this step: run handle response end-of-body for this.
    1795            [ + ]:        184 :                         response.on('end', () => {
    1796                 :        394 : 
    1797                 :        394 :                                 // xhr.spec.11.9.11.1. Handle errors for this. // @?????
    1798                 :        394 :                                 handleError.call(xhr);
    1799                 :        394 : 
    1800                 :        394 :                                 // xhr.spec.11.9.11.2. If xhr’s response is a network error, then return. // @?????
    1801            [ - ]:        394 :                                 if(!response.statusCode) return;
    1802                 :        394 : 
    1803                 :        394 :                                 // xhr.spec.11.9.11.3. Let transmitted be xhr’s received bytes’s length.
    1804                 :        394 :                                 let transmitted = requestData['receivedBytes'].length;
    1805                 :        394 : 
    1806                 :        394 :                                 // xhr.spec.11.9.11.4. Let length be the result of extracting a length from this’s response’s header list.
    1807                 :        394 :                                 // xhr.spec.11.9.11.5. If length is not an integer, then set it to 0.
    1808                 :        394 :                                 let length = 0;
    1809                 :        394 : 
    1810            [ + ]:        394 :                                 if(response.headers['content-length'] && !isNaN(+response.headers['content-length']))
    1811            [ + ]:        394 :                                         length = +response.headers['content-length'];
    1812                 :        394 : 
    1813                 :        394 :                                 // xhr.spec.11.9.11.6. If xhr’s synchronous flag is unset, then fire a progress event named progress at xhr with transmitted and length.
    1814                 :        394 :                                 // @?????
    1815                 :        394 :                                 if(requestData['async'] && transmitted === 0)
    1816            [ + ]:        394 :                                         xhr.dispatchEvent(new ProgressEvent('progress', {loaded: transmitted, total: length}));
    1817                 :        394 : 
    1818                 :        394 :                                 // xhr.spec.11.9.11.7. Set xhr’s state to done.
    1819                 :        394 :                                 requestData['readyState'] = xhr.DONE;
    1820                 :        394 : 
    1821                 :        394 :                                 // xhr.spec.11.9.11.8. Unset xhr’s send() flag.
    1822                 :        394 :                                 requestData['sendFlag'] = false;
    1823                 :        394 : 
    1824                 :        394 :                                 // xhr.spec.11.9.11.9. Fire an event named readystatechange at xhr.
    1825                 :        394 :                                 xhr.dispatchEvent(new Event('readystatechange'));
    1826                 :        394 : 
    1827                 :        394 :                                 // xhr.spec.11.9.11.10. Fire a progress event named "load" at xhr with transmitted and length.
    1828                 :        394 :                                 xhr.dispatchEvent(new ProgressEvent('load', {loaded: transmitted, total: length}));
    1829                 :        394 : 
    1830                 :        394 :                                 // xhr.spec.11.9.11.11. Fire a progress event named loadend at xhr with transmitted and length.
    1831                 :        394 :                                 xhr.dispatchEvent(new ProgressEvent('loadend', {loaded: transmitted, total: length}));
    1832                 :        184 :                         });
    1833                 :        184 : 
    1834                 :        184 :                         // xhr.spec.11.9.12. Let processBodyError be these steps:
    1835            [ + ]:        184 :                         response.on('error', (error) => {
    1836                 :          3 : 
    1837                 :          3 :                                 // xhr.spec.11.9.12.1. Set this’s response to a network error.
    1838                 :          3 :                                 setResponseToNetworkError.call(xhr);
    1839                 :          3 : 
    1840                 :          3 :                                 // xhr.spec.11.9.12.2  Run handle errors for this.
    1841                 :          3 :                                 handleError.call(xhr, error);
    1842                 :        184 :                         });
    1843                 :        260 :                 }; // @endof const processResponse = (response) => {  ... }
    1844                 :        260 : 
    1845                 :        260 :                 // xhr.spec.11.10. Set this’s fetch controller to the result of fetching req ... ???????????????????????????????????????????????????
    1846                 :        260 :                 let clientRequest = null;
    1847                 :        260 : 
    1848                 :        260 :                 try{
    1849                 :        260 :                         clientRequest = requestData['fetchController'] = doClientRequest(clientRequestOptions);
    1850       [ + ][ + ]:        263 :                 }catch(err){
    1851                 :          3 : 
    1852                 :          3 :                         // xhr.spec.11.9.12.1. Set this’s response to a network error.
    1853                 :          3 :                         setResponseToNetworkError.call(xhr);
    1854                 :          3 : 
    1855                 :          3 :                         // xhr.spec.11.9.12.2  Run handle errors for this.
    1856                 :          3 :                         handleError.call(xhr, err);
    1857                 :          3 : 
    1858                 :          3 :                         return;
    1859            [ + ]:          3 :                 }
    1860                 :          3 : 
    1861            [ + ]:          3 :                 clientRequest.on('close', () => {
    1862                 :          3 :                 });
    1863                 :          3 : 
    1864            [ + ]:          3 :                 clientRequest.on('error', (err) => {
    1865                 :         27 :                         setResponseToNetworkError.call(xhr);
    1866                 :         27 :                         handleError.call(xhr, err);
    1867                 :          3 :                 });
    1868                 :          3 : 
    1869                 :          3 :                 // xhr.spec.11.7. Note: These steps are only invoked when new bytes are transmitted.
    1870            [ + ]:        263 :                 if(requestData['requestBody']){
    1871                 :         35 :                         clientRequest.setHeader('Content-Length', requestData['requestBody'].length);
    1872                 :         35 : 
    1873            [ + ]:         35 :                         (async () => {
    1874                 :         84 :                                 let buffer = Buffer.alloc(0);
    1875                 :         84 : 
    1876            [ + ]:         84 :                                 if(requestData['requestBody'].source instanceof Blob){
    1877                 :          7 :                                         buffer = Buffer.from (await requestData['requestBody'].source.arrayBuffer());
    1878            [ + ]:          7 :                                 }
    1879                 :         28 :                                 else
    1880            [ + ]:         28 :                                 if(requestData['requestBody'].source instanceof FormData){
    1881            [ + ]:          5 :                                         await new Promise((resolve, reject) => {
    1882            [ + ]:          5 :                                                 requestData['requestBody'].stream.on('data', (chunk) => {
    1883                 :         15 :                                                         buffer = Buffer.concat([buffer, Buffer.from(chunk)]);
    1884                 :          5 :                                                 });
    1885                 :          5 : 
    1886            [ + ]:          5 :                                                 requestData['requestBody'].stream.on('end', () => {
    1887                 :          5 :                                                         resolve();
    1888                 :          5 :                                                 });
    1889                 :          5 :                                         });
    1890            [ + ]:          5 :                                 }
    1891                 :         23 :                                 else{
    1892                 :         23 :                                         buffer = await Promise.resolve(requestData['requestBody'].source);
    1893                 :         23 :                                 }
    1894                 :         84 : 
    1895                 :         84 :                                 clientRequest.write(buffer, processRequestBodyChunkLength); // ?????????????????????????????
    1896                 :         84 : 
    1897                 :         84 :                                 // xhr.spec.11.8. Let processRequestEndOfBody be these steps:
    1898                 :         84 :                                 clientRequest.end(processRequestEndOfBody);
    1899                 :         35 :                         })();
    1900       [ + ][ + ]:         35 :                 }
    1901                 :          3 :                 else{
    1902                 :          3 :                         clientRequest.end();
    1903            [ + ]:          3 :                 }
    1904                 :          3 : 
    1905                 :          3 :                 // xhr.spec.11.9. Let processResponse, given a response, be these steps:
    1906                 :          3 :                 clientRequest.on('response', processResponse);
    1907                 :          3 : 
    1908                 :          3 :                 // xhr.spec.11.11. Let now be the present time.
    1909                 :          3 :                 let now = Date.now();
    1910                 :          3 : 
    1911                 :          3 :                 // xhr.spec.11.12. Run these steps in parallel:
    1912                 :          3 :                 // xhr.spec.11.12.1. Wait until either req’s done flag is set or this’s timeout is not 0 and this’s timeout milliseconds have passed since now.
    1913                 :          3 :                 // xhr.spec.11.12.2. If req’s done flag is unset, then set this’s timed out flag and terminate this’s fetch controller.
    1914                 :          3 : 
    1915            [ + ]:        263 :                 if(requestData['timeout']){
    1916            [ + ]:          3 :                         setTimeout(() => {
    1917                 :          3 :                                 if(requestData['readyState'] !== xhr.DONE){
    1918                 :          3 :                                         requestData['timeoutFlag'] = true;
    1919                 :          3 :                                         handleError.call(xhr);
    1920                 :          3 :                                 }
    1921                 :          3 :                         }, requestData['timeout']);
    1922                 :          3 :                 }
    1923            [ + ]:        263 :         }
    1924                 :        228 :         // xhr.spec.12. Otherwise, if this’s synchronous flag is set:
    1925                 :        228 :         else
    1926                 :        228 :         {
    1927                 :        228 :                 // xhr.spec.12.1. Let <processedResponse> be false.
    1928                 :        228 :                 // xhr.spec.12.2. Let <processResponseConsumeBody>, given a <response> and <nullOrFailureOrBytes>, be these steps:
    1929                 :        228 :                 // xhr.spec.12.2.1. If <nullOrFailureOrBytes> is not failure, then set this’s response to response.
    1930                 :        228 :                 // xhr.spec.12.2.2. If <nullOrFailureOrBytes> is a byte sequence, then append nullOrFailureOrBytes to this’s received bytes.
    1931                 :        228 :                 // xhr.spec.12.2.3. Set <processedResponse> to true.
    1932                 :        228 : 
    1933                 :        228 :                 // xhr.spec.12.3. Set this’s fetch controller to the result of fetching req with <processResponseConsumeBody> set to processResponseConsumeBody
    1934                 :        228 :                 //                and useParallelQueue set to true.
    1935                 :        228 :                 // xhr.spec.12.4. Let now be the present time.
    1936                 :        228 :                 // xhr.spec.12.5. Pause until either processedResponse is true or this’s timeout is not 0 and this’s timeout milliseconds have passed since now.
    1937                 :        228 :                 // xhr.spec.12.6. If processedResponse is false, then set this’s timed out flag and terminate this’s fetch controller.
    1938                 :        228 :                 // xhr.spec.12.7. Report timing for this’s fetch controller given the current global object.
    1939                 :        228 :                 // xhr.spec.12.8. Run handle response end-of-body for this.
    1940                 :        228 : 
    1941                 :        228 :                 const contentFile = '.whatwg-xhr-content-' + process.pid;
    1942                 :        228 :                 const syncFile    = '.whatwg-xhr-sync-'    + process.pid;
    1943                 :        228 :                 const filename    = __filename.replace(/\\/g, '\\\\');
    1944                 :        228 : 
    1945                 :        228 :                 fs.writeFileSync(syncFile, '', 'utf8');
    1946                 :        228 : 
    1947                 :        228 :                 let defaultHeadersObj = defaultHeaders();
    1948                 :        228 : 
    1949            [ + ]:        228 :                 for(let name in defaultHeadersObj){
    1950            [ + ]:        684 :                         if(req_headers[name] && req_headers[name] === defaultHeadersObj[name]){
    1951                 :        681 :                                 delete req_headers[name];
    1952                 :        681 :                                 delete req_headersCase[name.toLowerCase()];
    1953                 :        681 :                         }
    1954                 :        684 :                 }
    1955                 :        228 : 
    1956                 :        228 :                 let headersJSON = JSON.stringify(req_headers);
    1957                 :        228 : 
    1958            [ + ]:        228 :                 let bodyFlag = body !== null && body !== '';
    1959                 :        228 : 
    1960                 :        228 : const execString = `
    1961                 :        228 :         (async () => {
    1962                 :        228 :                 let fs                 = await import('node:fs');
    1963                 :        228 :                 let { XMLHttpRequest } = await import('file:${filename}');
    1964                 :        228 : 
    1965                 :        228 :                 let xhr = new XMLHttpRequest;
    1966                 :        228 : 
    1967                 :        228 :                 let requestData = {};
    1968                 :        228 : 
    1969                 :        228 :                 xhr.onload = () => {
    1970                 :        228 :                         requestData['error'] = null;
    1971                 :        228 : 
    1972                 :        228 :                         requestData['status']     = xhr.status;
    1973                 :        228 :                         requestData['statusText'] = xhr.statusText;
    1974                 :        228 : 
    1975                 :        228 :                         requestData['response'       ] = xhr.response;
    1976                 :        228 :                         requestData['responseText'   ] = xhr.responseText;
    1977                 :        228 :                         requestData['responseType'   ] = xhr.responseType;
    1978                 :        228 :                         requestData['responseURL'    ] = xhr.responseURL;
    1979                 :        228 :                         requestData['responseXML'    ] = xhr.responseXML;
    1980                 :        228 :                         requestData['responseHeaders'] = xhr.getAllResponseHeaders();
    1981                 :        228 :                 };
    1982                 :        228 : 
    1983                 :        228 :                 xhr.onerror = (e) => {
    1984                 :        228 :                         requestData['error'] = e;
    1985                 :        228 :                 }
    1986                 :        228 : 
    1987                 :        228 :                 xhr.onloadend = () => {
    1988                 :        228 :                         fs.writeFileSync('${contentFile}', JSON.stringify(requestData, null, 2), 'utf8');
    1989                 :        228 :                         fs.unlinkSync('${syncFile}');
    1990                 :        228 :                 }
    1991                 :        228 : 
    1992                 :        228 :                 xhr.open('${req_method}', '${req_url}');
    1993                 :        228 : 
    1994                 :        228 :                 let headers = JSON.parse(process.argv[1]);
    1995                 :        228 :                 for(let k in headers){
    1996                 :        228 :                         xhr.setRequestHeader(k, headers[k]);
    1997                 :        228 :                 }
    1998                 :        228 : 
    1999                 :        228 :                 if(!${bodyFlag})
    2000                 :        228 :                         xhr.send();
    2001                 :        228 : 
    2002                 :        228 :                 let body = Buffer.alloc(0);
    2003                 :        228 : 
    2004                 :        228 :                 process.stdin.on('data', (chunk) => {
    2005                 :        228 :                         body = Buffer.concat([body, chunk]);
    2006                 :        228 :                         xhr.send(body);
    2007                 :        228 :                 });
    2008                 :        228 :         })();
    2009                 :        228 : `;
    2010                 :        228 : 
    2011                 :        228 :                 let syncProc = spawn(process.argv[0], ['-e', execString, headersJSON]);
    2012                 :        228 : 
    2013       [ + ][ + ]:        228 :                 if(bodyFlag && requestData['requestBody'].source instanceof Blob){
    2014                 :         10 : 
    2015                 :         10 :                         requestData['requestBody'].source = readBlobSync(requestData['requestBody'].source);
    2016                 :         10 :                         syncProc.stdin.write(requestData['requestBody'].source);
    2017            [ + ]:         10 :                 }
    2018                 :        218 :                 else
    2019       [ + ][ + ]:        218 :                 if(bodyFlag && requestData['requestBody'].source instanceof FormData){
    2020                 :          3 : 
    2021                 :          3 :                         let buffer = Buffer.alloc(0);
    2022                 :          3 :                         if(requestData['requestBody'].blobs){
    2023                 :          3 :                                 for(let part of requestData['requestBody'].blobs){
    2024                 :          3 :                                         if(part instanceof Blob){
    2025                 :          3 :                                                 buffer = Buffer.concat([buffer, readBlobSync(part)]);
    2026                 :          3 :                                         }
    2027                 :          3 :                                         else
    2028                 :          3 :                                         if(part instanceof Uint8Array){
    2029                 :          3 :                                                 buffer = Buffer.concat([buffer, part]);
    2030                 :          3 :                                         }
    2031                 :          3 :                                 }
    2032                 :          3 :                         }
    2033                 :          3 : 
    2034                 :          3 :                         requestData['requestBody'].source = buffer;
    2035                 :          3 :                         syncProc.stdin.write(requestData['requestBody'].source);
    2036            [ + ]:          3 :                 }
    2037                 :        215 :                 else
    2038            [ + ]:        215 :                 if(bodyFlag){
    2039                 :         36 :                         syncProc.stdin.write(requestData['requestBody'].source);
    2040                 :         36 :                 }
    2041                 :        228 : 
    2042                 :        228 :                 /* node:coverage disable */
    2043                 :            :                 syncProc.stderr.on('data', (chunk) => {
    2044                 :            :                         let msg = chunk.toString();
    2045                 :            : 
    2046                 :            :                         setResponseToNetworkError.call(xhr);
    2047                 :            :                         handleError.call(xhr, new Error(msg));
    2048                 :            : 
    2049                 :            :                         process.exit(1);
    2050                 :            :                 });
    2051                 :            :                 /* node:coverage enable */
    2052                 :        228 : 
    2053            [ + ]:        228 :                 while(fs.existsSync(syncFile));
    2054                 :        228 :                 syncProc.stdin.end();
    2055                 :        228 :                 processResult();
    2056                 :        228 : 
    2057            [ + ]:        228 :                 function processResult(){
    2058                 :        228 : 
    2059            [ - ]:        228 :                         let _requestData = JSON.parse(fs.readFileSync(contentFile, 'utf8')) || {};
    2060                 :        228 :                         fs.unlinkSync(contentFile);
    2061                 :        228 : 
    2062            [ + ]:        228 :                         if(_requestData['status']){
    2063                 :        212 : 
    2064                 :        212 :                                 let response = {};
    2065                 :        212 : 
    2066                 :        212 :                                 requestData['status']     = response.statusCode    = _requestData['status'];
    2067                 :        212 :                                 requestData['statusText'] = response.statusMessage = _requestData['statusText'];
    2068                 :        212 : 
    2069                 :        212 :                                 requestData['responseType'] = _requestData['responseType'];
    2070                 :        212 :                                 requestData['responseURL' ] = _requestData['responseURL' ];
    2071                 :        212 :                                 requestData['responseXML' ] = _requestData['responseXML' ];
    2072                 :        212 : 
    2073                 :        212 :                                 response.url = _requestData['responseURL'];
    2074                 :        212 : 
    2075                 :        212 :                                 _requestData['responseHeaders'] = _requestData['responseHeaders'].split('\r\n');
    2076                 :        212 :                                 _requestData['responseHeaders'].pop();
    2077                 :        212 : 
    2078                 :        212 :                                 response.headers = {};
    2079            [ + ]:        212 :                                 for(let header of _requestData['responseHeaders']){
    2080                 :       1062 :                                         let [name, value] = header.split('\x3A\x20');
    2081                 :       1062 :                                         response.headers[name] = value;
    2082                 :       1062 :                                 }
    2083                 :        212 : 
    2084                 :        212 :                                 response.rawHeaders = [];
    2085            [ + ]:        212 :                                 for(let k in response.headers){
    2086                 :       1062 :                                         response.rawHeaders.push(k);
    2087                 :       1062 :                                         response.rawHeaders.push(response.headers[k]);
    2088                 :       1062 :                                 }
    2089                 :        212 : 
    2090            [ + ]:        212 :                                 if(_requestData['response']){
    2091                 :        109 :                                         let chunk = Buffer.from(_requestData['response']);
    2092                 :        109 :                                         requestData['receivedBytes'] = Buffer.concat([requestData['receivedBytes'], chunk]);
    2093                 :        109 :                                 }
    2094                 :        212 : 
    2095                 :        212 :                                 requestData['response'] = response;
    2096                 :        212 : 
    2097                 :        212 :                                 // xhr.spec.11.9.11.7. Set xhr’s state to done.
    2098                 :        212 :                                 requestData['readyState'] = xhr.DONE;
    2099                 :        212 : 
    2100                 :        212 :                                 // xhr.spec.11.9.11.8. Unset xhr’s send() flag.
    2101                 :        212 :                                 requestData['sendFlag'] = false;
    2102                 :        212 : 
    2103                 :        212 :                                 // xhr.spec.11.9.11.9. Fire an event named readystatechange at xhr.
    2104                 :        212 :                                 xhr.dispatchEvent(new Event('readystatechange'));
    2105                 :        212 : 
    2106                 :        212 :                                 // xhr.spec.11.9.11.10. Fire a progress event named "load" at xhr with transmitted and length.
    2107                 :        212 :                                 xhr.dispatchEvent(new ProgressEvent('load', {loaded: requestData['receivedBytes'].length, total: requestData['receivedBytes'].length}));
    2108                 :        212 : 
    2109                 :        212 :                                 // xhr.spec.11.9.11.11. Fire a progress event named loadend at xhr with transmitted and length.
    2110                 :        212 :                                 xhr.dispatchEvent(new ProgressEvent('loadend', {loaded: requestData['receivedBytes'].length, total: requestData['receivedBytes'].length}));
    2111            [ + ]:        212 :                         }
    2112                 :         16 :                         else{
    2113                 :         16 :                                 // xhr.spec.11.9.12.1. Set this’s response to a network error.
    2114                 :         16 :                                 setResponseToNetworkError.call(xhr);
    2115                 :         16 : 
    2116                 :         16 :                                 // xhr.spec.11.9.12.2  Run handle errors for this.
    2117                 :         16 :                                 handleError.call(xhr);
    2118                 :         16 :                         }
    2119                 :        228 :                 }
    2120                 :        228 :         }
    2121                 :        229 : }; // @endof method XMLHttpRequest.prototype.send
    2122                 :        229 : 
    2123                 :        229 : /**
    2124                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2125                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-getresponseheader()-method
    2126                 :        229 :  *
    2127                 :        229 :  * client.getResponseHeader(name)
    2128                 :        229 :  *   The getResponseHeader(name) method steps are to return the result of getting name from this’s response’s header list.
    2129                 :        229 :  *
    2130                 :        229 :  * @method   getResponseHeader
    2131                 :        229 :  * @instance
    2132                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
    2133                 :        229 :  * @param    {string} name - The name of the header whose text value is required.
    2134                 :        229 :  * @return   {string|null} The header text value or null.
    2135                 :        229 :  * @desc     XMLHttpRequest method that returns the string containing the text of a particular header's value.
    2136                 :        229 :  */
    2137            [ + ]:        229 : XMLHttpRequest.prototype.getResponseHeader = function getResponseHeader(name){
    2138                 :        263 : 
    2139                 :        263 :         // @author. validate the number of arguments
    2140                 :        263 :         if(arguments.length < 1)
    2141            [ - ]:        263 :                 throw new TypeError(`XMLHttpRequest.getResponseHeader: At least 1 argument required, but only ${arguments.length} passed`);     // firefox 102
    2142                 :        263 : 
    2143                 :        263 :         const requestData = xmlHttpRequest.get(this);
    2144                 :        263 : 
    2145       [ + ][ + ]:        263 :         if(!requestData['response']) return null;
    2146                 :        248 : 
    2147                 :        248 :         if(typeof name === 'symbol')
    2148       [ - ][ + ]:        263 :                 throw new TypeError(`can't convert symbol to string`);
    2149                 :        248 : 
    2150                 :        248 :         let headerName = String(name).toLowerCase();
    2151                 :        248 :         let responseHeaders = {};
    2152                 :        248 : 
    2153                 :        248 :         for(let headerName in requestData['response'].headers)
    2154       [ + ][ + ]:        263 :                 responseHeaders[headerName.toLowerCase()] = requestData['response'].headers[headerName];
    2155                 :        248 : 
    2156            [ + ]:        263 :         if(headerName in responseHeaders && !headerName.startsWith('set-cookie'))
    2157       [ + ][ + ]:        263 :                 return responseHeaders[headerName];
    2158                 :         31 : 
    2159                 :         31 :         return null;
    2160                 :         31 : 
    2161                 :        229 : }; // @endof method XMLHttpRequest.prototype.getResponseHeader
    2162                 :        229 : 
    2163                 :        229 : /**
    2164                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2165                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method
    2166                 :        229 :  *
    2167                 :        229 :  * client.getAllResponseHeaders()
    2168                 :        229 :  *   The getAllResponseHeaders() method steps are:
    2169                 :        229 :  *   1. Let <output> be an empty byte sequence.
    2170                 :        229 :  *   2. Let <initialHeaders> be the result of running <sort and combine> with this’s response’s header list.
    2171                 :        229 :  *   3. Let <headers> be the result of sorting initialHeaders in ascending order, with a being less than b if a’s name is legacy-uppercased-byte less than b’s name.
    2172                 :        229 :  *      Note: Unfortunately, this is needed for compatibility with deployed content.
    2173                 :        229 :  *   4. For each <header> in <headers>, append <header>’s name, followed by a 0x3A 0x20 byte pair, followed by <header>’s value,
    2174                 :        229 :  *      followed by a 0x0D 0x0A byte pair, to <output>.
    2175                 :        229 :  *   5. Return <output>.
    2176                 :        229 :  *
    2177                 :        229 :  * @method   getAllResponseHeaders
    2178                 :        229 :  * @instance
    2179                 :        229 :  * @memberof module:whatwg-xhr.XMLHttpRequest
    2180                 :        229 :  * @return   {string|null} A string representing all of the response's headers, or null if no response has been received.
    2181                 :        229 :  * @desc     XMLHttpRequest method that returns all the response headers, separated by CRLF, as a string, or null if no response.
    2182                 :        229 :  */
    2183            [ + ]:        229 : XMLHttpRequest.prototype.getAllResponseHeaders = function getAllResponseHeaders(){
    2184                 :        239 : 
    2185                 :        239 :         const requestData = xmlHttpRequest.get(this);
    2186                 :        239 : 
    2187       [ + ][ + ]:        239 :         if(!requestData['response']) return '';
    2188                 :         18 : 
    2189                 :         18 :         // xhr.spec.1. Let <output> be an empty byte sequence.
    2190                 :         18 :         let output = '';
    2191                 :         18 : 
    2192                 :         18 :         // xhr.spec.2. Let <initialHeaders> be the result of running <sort and combine>...
    2193                 :         18 :         let initialHeaders = requestData['response'].headers;
    2194                 :         18 : 
    2195                 :         18 :         // xhr.spec.3. Let <headers> be the result of sorting initialHeaders in ascending order...
    2196                 :         18 :         let headers = Object.entries(initialHeaders);
    2197                 :         18 : 
    2198            [ + ]:         18 :         headers.sort((a, b) => {
    2199                 :       1979 :                 if(a[0].toUpperCase() > b[0].toUpperCase())
    2200  [ + ][ + ][ + ]:       1979 :                         return 1;
    2201                 :          8 :                 else
    2202                 :          8 :                         return -1;
    2203                 :         18 :         });
    2204                 :         18 : 
    2205                 :         18 :         // xhr.spec.4. For each <header> in <headers>, append <header>’s name, followed by a 0x3A 0x20 byte pair, followed by <header>’s value,
    2206                 :         18 :         //             followed by a 0x0D 0x0A byte pair, to output.
    2207                 :         18 : 
    2208            [ + ]:        239 :         for(let header of headers){
    2209                 :       1142 :                 if(!header[0].toLowerCase().startsWith('set-cookie'))
    2210            [ + ]:       1142 :                         output += header[0] + '\x3A' + '\x20' + header[1] + '\x0D' + '\x0A';
    2211            [ + ]:       1142 :         }
    2212                 :         18 :         return output;
    2213                 :         18 : 
    2214                 :        229 : }; // @endof method XMLHttpRequest.prototype.getAllResponseHeaders
    2215                 :        229 : 
    2216                 :        229 : /**
    2217                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2218                 :        229 :  * url: https://xhr.spec.whatwg.org/#the-overridemimetype()-method
    2219                 :        229 :  *
    2220                 :        229 :  * client.overrideMimeType(mime)
    2221                 :        229 :  * Acts as if the `Content-Type` header value for a response is mime. (It does not change the header.)
    2222                 :        229 :  * Throws an "InvalidStateError" DOMException if state is loading or done.
    2223                 :        229 :  *
    2224                 :        229 :  * The overrideMimeType(mime) method steps are:
    2225                 :        229 :  *   1. If this’s state is loading or done, then throw an "InvalidStateError" DOMException.
    2226                 :        229 :  *   2. Set this’s override MIME type to the result of parsing mime.
    2227                 :        229 :  *   3. If this’s override MIME type is failure, then set this’s override MIME type to application/octet-stream.
    2228                 :        229 :  *
    2229                 :        229 :  * @method    overrideMimeType
    2230                 :        229 :  * @instance
    2231                 :        229 :  * @memberof  module:whatwg-xhr.XMLHttpRequest
    2232                 :        229 :  * @param     {string} mime - MIME type to use instead of the one specified by the server.
    2233                 :        229 :  * @desc      XMLHttpRequest method that specifies a MIME type other than the one provided by the server.
    2234                 :        229 :  * @requires  module:whatwg-misc.parseMIMEType
    2235                 :        229 :  * @requires  module:whatwg-misc.serializeAMimeType
    2236                 :        229 :  */
    2237            [ + ]:        229 : XMLHttpRequest.prototype.overrideMimeType = function overrideMimeType(mime){
    2238                 :          6 : 
    2239                 :          6 :         // @author. validate the number of arguments
    2240                 :          6 :         if(arguments.length < 1)
    2241            [ - ]:          6 :                 throw new TypeError(`XMLHttpRequest.overrideMimeType: At least 1 argument required, but only 0 passed`);        // firefox 102
    2242                 :          6 : 
    2243                 :          6 :         const requestData = xmlHttpRequest.get(this);
    2244                 :          6 : 
    2245                 :          6 :         // xhr.spec.1. If this’s state is loading or done, then throw an "InvalidStateError" DOMException.
    2246            [ + ]:          6 :         if(requestData['readyState'] === this.LOADING || requestData['readyState'] === this.DONE)
    2247       [ + ][ + ]:          6 :                 throw new DOMException(`XMLHttpRequest.overrideMimeType: Cannot call 'overrideMimeType()' on XMLHttpRequest after 'send()' (when its state is LOADING or DONE).`, 'InvalidStateError'); // firefox 102
    2248                 :          5 : 
    2249                 :          5 :         let parsedMime = parseMIMEType(String(mime));
    2250                 :          5 : 
    2251            [ + ]:          6 :         if(parsedMime !== 'failure'){
    2252                 :          2 :                 // xhr.spec.2. Set this’s override MIME type to the result of parsing mime.
    2253                 :          2 :                 requestData['overrideMimeType'] = serializeAMimeType(parsedMime);
    2254            [ + ]:          2 :         }
    2255                 :          3 :         else{
    2256                 :          3 :                 // xhr.spec.3. If this’s override MIME type is failure, then set this’s override MIME type to application/octet-stream.
    2257                 :          3 :                 requestData['overrideMimeType'] = 'application/octet-stream';
    2258                 :          3 :         }
    2259                 :        229 : }; // @endof method XMLHttpRequest.prototype.overrideMimeType
    2260                 :        229 : 
    2261                 :        229 : /**
    2262                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2263                 :        229 :  * url: https://xhr.spec.whatwg.org/#interface-progressevent
    2264                 :        229 :  *
    2265                 :        229 :  * interface ProgressEvent : Event {
    2266                 :        229 :  *   constructor(DOMString type, optional ProgressEventInit eventInitDict = {});
    2267                 :        229 :  *
    2268                 :        229 :  *   readonly attribute boolean lengthComputable;
    2269                 :        229 :  *   readonly attribute unsigned long long loaded;
    2270                 :        229 :  *   readonly attribute unsigned long long total;
    2271                 :        229 :  * };
    2272                 :        229 :  *
    2273                 :        229 :  * dictionary ProgressEventInit : EventInit {
    2274                 :        229 :  *   boolean lengthComputable = false;
    2275                 :        229 :  *   unsigned long long loaded = 0;
    2276                 :        229 :  *   unsigned long long total = 0;
    2277                 :        229 :  * };
    2278                 :        229 :  *
    2279                 :        229 :  * @class     ProgressEvent
    2280                 :        229 :  * @extends   module:whatwg-xhr~Event
    2281                 :        229 :  * @static
    2282                 :        229 :  * @desc      Interface that represents events measuring progress of an underlying process, like an HTTP request for an XMLHttpRequest client.
    2283                 :        229 :  */
    2284                 :        229 : export class ProgressEvent extends Event{
    2285                 :        229 : 
    2286                 :        229 :         /**
    2287                 :        229 :          * @method   constructor
    2288                 :        229 :          * @instance
    2289                 :        229 :          * @memberof module:whatwg-xhr.ProgressEvent
    2290                 :        229 :          * @param    {string} type - A case-sensitive name of the event.
    2291                 :        229 :          * @param    {object} eventInitDict - (Optional) An object that, in addition to the properties defined in Event(), can have lengthComputable, loaded and total.
    2292                 :        229 :          * @desc     Constructs a new ProfressEvent object.
    2293                 :        229 :          */
    2294            [ + ]:        229 :         constructor(type, eventInitDict = {}){
    2295                 :       2380 :                 if(arguments.length < 1)
    2296            [ - ]:       2380 :                         throw new TypeError(`ProgressEvent constructor: At least 1 argument required, but only 0 passed`);      // firefox 102
    2297                 :       2380 : 
    2298                 :       2380 :                 const progressEventData = {};
    2299                 :       2380 : 
    2300                 :       2380 :                 progressEventData['type']             = String(type);
    2301                 :       2380 :                 progressEventData['lengthComputable'] = false;
    2302                 :       2380 :                 progressEventData['loaded']           = 0;
    2303                 :       2380 :                 progressEventData['total']            = 0;
    2304                 :       2380 : 
    2305                 :       2380 :                 if(eventInitDict !== undefined && eventInitDict !== null){
    2306            [ - ]:       2380 :                         if(typeof eventInitDict !== 'object' && typeof eventInitDict !== 'function')
    2307            [ - ]:       2380 :                                 throw new TypeError(`ProgressEvent constructor: Value can't be converted to a dictionary.`);    // firefox 102
    2308                 :       2380 : 
    2309                 :       2380 :                         if(eventInitDict.loaded !== undefined)
    2310       [ + ][ - ]:       2380 :                                 progressEventData['loaded'] = isNaN(eventInitDict.loaded) ? 0 : Number(eventInitDict.loaded);
    2311                 :       2380 : 
    2312                 :       2380 :                         if(eventInitDict.total !== undefined)
    2313       [ + ][ - ]:       2380 :                                 progressEventData['total'] = isNaN(eventInitDict.total) ? 0 : Number(eventInitDict.total);
    2314                 :       2380 : 
    2315                 :       2380 :                         if(eventInitDict.lengthComputable !== undefined)
    2316       [ + ][ + ]:       2380 :                                 progressEventData['lengthComputable'] = Boolean(eventInitDict.lengthComputable);
    2317                 :       1437 :                         else
    2318                 :       1437 :                                 progressEventData['lengthComputable'] = progressEventData['total'] !== 0;
    2319                 :       2380 : 
    2320                 :       2380 :                         let eventInit = {
    2321                 :       2380 :                                 bubbles:    Boolean(eventInitDict['bubbles']),
    2322                 :       2380 :                                 cancelable: Boolean(eventInitDict['cancelable']),
    2323                 :       2380 :                                 composed:   Boolean(eventInitDict['composed'])
    2324                 :       2380 :                         };
    2325                 :       2380 : 
    2326                 :       2380 :                         super(type, eventInit);
    2327            [ - ]:       2380 :                 }
    2328                 :          0 :                 else
    2329                 :          0 :                         super(type);
    2330                 :       2380 : 
    2331                 :       2380 :                 // Map any ProgressEvent object created to an associated data object.
    2332                 :       2380 :                 progressEvent.set(this, progressEventData);
    2333                 :       2380 :         }
    2334                 :        229 : 
    2335                 :        229 :         /**
    2336                 :        229 :          * @member   {boolean} lengthComputable
    2337                 :        229 :          * @memberof module:whatwg-xhr.ProgressEvent
    2338                 :        229 :          * @readonly
    2339                 :        229 :          * @default  false
    2340                 :        229 :          * @instance
    2341                 :        229 :          * @desc     A boolean value indicating if the total work to be done, and the amount of work already done, by the underlying process is calculable.
    2342                 :        229 :          */
    2343            [ + ]:        229 :         get lengthComputable(){ return progressEvent.get(this)['lengthComputable']; }
    2344                 :        229 : 
    2345                 :        229 :         /**
    2346                 :        229 :          * @member   {number} loaded
    2347                 :        229 :          * @memberof module:whatwg-xhr.ProgressEvent
    2348                 :        229 :          * @readonly
    2349                 :        229 :          * @default  0
    2350                 :        229 :          * @instance
    2351                 :        229 :          * @desc     A number representing the amount of work already performed by the underlying process.
    2352                 :        229 :          */
    2353            [ + ]:        229 :         get loaded(){ return progressEvent.get(this)['loaded']; }
    2354                 :        229 : 
    2355                 :        229 :         /**
    2356                 :        229 :          * @member   {number} total
    2357                 :        229 :          * @memberof module:whatwg-xhr.ProgressEvent
    2358                 :        229 :          * @readonly
    2359                 :        229 :          * @default  0
    2360                 :        229 :          * @instance
    2361                 :        229 :          * @desc     A number representing the total amount of work that the underlying process is in the progress of performing.
    2362                 :        229 :          */
    2363            [ + ]:        229 :         get total(){ return progressEvent.get(this)['total']; }
    2364                 :        229 : 
    2365                 :        229 : } // @endOf class ProgressEvent extends Event
    2366                 :        229 : 
    2367                 :        229 : Object.defineProperty(ProgressEvent.prototype, 'lengthComputable', {enumerable: true});
    2368                 :        229 : Object.defineProperty(ProgressEvent.prototype, 'loaded', {enumerable: true});
    2369                 :        229 : Object.defineProperty(ProgressEvent.prototype, 'total', {enumerable: true});
    2370                 :        229 : 
    2371                 :        229 : Object.defineProperty(ProgressEvent.prototype, Symbol.toStringTag, {value: 'ProgressEvent', writable: false, enumerable: false, configurable: true});
    2372                 :        229 : 
    2373                 :        229 : /**
    2374                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2375                 :        229 :  * url: https://xhr.spec.whatwg.org/#formdata
    2376                 :        229 :  *
    2377                 :        229 :  * interface FormData {
    2378                 :        229 :  *   constructor(optional HTMLFormElement form, optional HTMLElement? submitter = null);
    2379                 :        229 :  *
    2380                 :        229 :  *   undefined append(USVString name, USVString value);
    2381                 :        229 :  *   undefined append(USVString name, Blob blobValue, optional USVString filename);
    2382                 :        229 :  *   undefined delete(USVString name);
    2383                 :        229 :  *
    2384                 :        229 :  *   FormDataEntryValue?          get(USVString name);
    2385                 :        229 :  *   sequence<FormDataEntryValue> getAll(USVString name);
    2386                 :        229 :  *
    2387                 :        229 :  *   boolean   has(USVString name);
    2388                 :        229 :  *   undefined set(USVString name, USVString value);
    2389                 :        229 :  *   undefined set(USVString name, Blob blobValue, optional USVString filename);
    2390                 :        229 :  *
    2391                 :        229 :  *   iterable<USVString, FormDataEntryValue>;
    2392                 :        229 :  * };
    2393                 :        229 :  *
    2394                 :        229 :  * @class FormData
    2395                 :        229 :  * @static
    2396                 :        229 :  * @desc  An interface that provides a way to construct a set of key/value pairs representing form fields and their values.
    2397                 :        229 :  */
    2398                 :        229 : export class FormData{
    2399                 :        229 :         /**
    2400                 :        229 :          * @method   constructor
    2401                 :        229 :          * @instance
    2402                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2403                 :        229 :          * @param    {FormData}    form     - (Optional) The FormData object will be populated with the form's current keys/values.
    2404                 :        229 :          * @param    {string|Blob} value    - (Optional) A submit button that is a member of the form.
    2405                 :        229 :          * @desc     Constructs a new FormData object.
    2406                 :        229 :          */
    2407            [ + ]:        229 :         constructor(form, submitter){
    2408                 :         41 : 
    2409            [ - ]:         41 :                 if(globalThis.HTMLFormElement){
    2410                 :          0 :                         /* node:coverage disable *
    2411                 :          0 : 
    2412                 :          0 :                         if(form === null || typeof form !== 'object')
    2413                 :          0 :                                 throw new TypeError('FormData constructor: Argument 1 is not an object.');      // firefox 102
    2414                 :          0 : 
    2415                 :          0 :                         if(!(form instanceof globalThis.HTMLFormElement))
    2416                 :          0 :                                 throw new TypeError(' FormData constructor: Argument 1 does not implement interface HTMLFormElement.'); // firefox 102
    2417                 :          0 : 
    2418                 :          0 :                         const entryList = [];
    2419                 :          0 :                         formData.set(this, entryList);
    2420                 :          0 : 
    2421                 :          0 :                         ** node:coverage enable */
    2422                 :          0 :                 }
    2423                 :         41 :                 else
    2424       [ + ][ + ]:         41 :                 if(arguments.length === 0 || form === undefined){
    2425                 :         39 :                         const entryList = [];
    2426                 :         39 : 
    2427                 :         39 :                         // Map any FormData object created to an associated data object.
    2428                 :         39 :                         formData.set(this, entryList);
    2429            [ + ]:         39 :                 }
    2430                 :          2 :                 else
    2431                 :          2 :                 if(form !== undefined){
    2432                 :          2 :                         throw new TypeError('FormData constructor: Argument 1 could not be converted to: undefined.');  // node.js
    2433                 :          2 :                 }
    2434                 :         41 :         }
    2435                 :        229 : 
    2436                 :        229 :         /**
    2437                 :        229 :          * @method   append
    2438                 :        229 :          * @instance
    2439                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2440                 :        229 :          * @param    {string}      name     - The name of the field whose data is contained in value.
    2441                 :        229 :          * @param    {string|Blob} value    - The field's value, can be a string or Blob, otherwise the value is converted to a string.
    2442                 :        229 :          * @param    {string}      filename - (Optional) The filename reported to the server (a string), when a Blob or File is passed as the second parameter.
    2443                 :        229 :          * @desc     Appends a new value onto an existing key inside a FormData object, or adds the key if it does not already exist.
    2444                 :        229 :          */
    2445            [ + ]:        229 :         append(name, value, filename = undefined){
    2446                 :         51 : 
    2447            [ - ]:         51 :                 if(globalThis.HTMLFormElement){
    2448                 :          0 :                         /* node:coverage disable *
    2449                 :          0 : 
    2450                 :          0 :                         if(arguments.length < 2)
    2451                 :          0 :                                 throw new TypeError(`FormData.append: ${arguments.length} is not a valid argument count for any overload.`);    // firefox 102
    2452                 :          0 :                         else
    2453                 :          0 :                         if(arguments.length === 3){
    2454                 :          0 :                                 if(typeof value !== 'object')
    2455                 :          0 :                                         throw new TypeError(`FormData.append: Argument 2 is not an object.`);   // firefox 102
    2456                 :          0 :                                 else
    2457                 :          0 :                                 if(!(value instanceof Blob))
    2458                 :          0 :                                         throw new TypeError(`FormData.append: Argument 2 does not implement interface Blob.`);  // firefox 102
    2459                 :          0 :                         }
    2460                 :          0 : 
    2461                 :          0 :                         ** node:coverage enable */
    2462                 :          0 :                 }
    2463                 :         51 :                 else
    2464                 :         51 :                 if(arguments.length === 0)
    2465            [ - ]:         51 :                         throw new TypeError(`FormData.append: 2 arguments required, but 0 found.`);     // node.js
    2466                 :         51 :                 else
    2467                 :         51 :                 if(arguments.length === 1)
    2468            [ - ]:         51 :                         throw new TypeError(`FormData.append: 2 arguments required, but only 1 found.`);        // node.js
    2469                 :         51 :                 else
    2470            [ + ]:         51 :                 if(arguments.length === 3 && !(value instanceof Blob))
    2471            [ - ]:         51 :                         throw new TypeError(`Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'`);     // node.js
    2472                 :         51 : 
    2473                 :         51 :                 name = String(name);
    2474                 :         51 : 
    2475       [ + ][ + ]:         51 :                 value = value instanceof Blob ? value : String(value);
    2476       [ + ][ + ]:         51 :                 filename = arguments.length === 3 ? String(filename) : undefined;
    2477                 :         51 : 
    2478                 :         51 :                 const entryList = formData.get(this);
    2479                 :         51 : 
    2480                 :         51 :                 const entry = makeEntry(name, value, filename);
    2481                 :         51 :                 entryList.push(entry);
    2482                 :         51 :         }
    2483                 :        229 : 
    2484                 :        229 :         /**
    2485                 :        229 :          * @method   delete
    2486                 :        229 :          * @instance
    2487                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2488                 :        229 :          * @param    {string} name - The name of the key to be deleted.
    2489                 :        229 :          * @desc     Deletes a key and its value(s) from a FormData object.
    2490                 :        229 :          */
    2491            [ + ]:        229 :         delete(name){
    2492                 :          7 :                 // validate the arguments
    2493                 :          7 :                 if(arguments.length < 1)
    2494            [ - ]:          7 :                         throw new TypeError(`FormData.delete: At least 1 argument required, but only ${arguments.length} passed`);
    2495                 :          7 : 
    2496                 :          7 :                 const entryList = formData.get(this);
    2497                 :          7 :                 for(let i = 0; i < entryList.length; i++)
    2498            [ + ]:          7 :                         if(entryList[i][name] !== undefined)
    2499            [ + ]:         21 :                                 entryList.splice(i--, 1);
    2500                 :          7 :         }
    2501                 :        229 : 
    2502                 :        229 :         /**
    2503                 :        229 :          * @method   get
    2504                 :        229 :          * @instance
    2505                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2506                 :        229 :          * @param    {string} name - The name of the key to be retrieved.
    2507                 :        229 :          * @return   {string|Blob} Form data entry value.
    2508                 :        229 :          * @desc     Returns the first value associated with a given key from within a FormData object.
    2509                 :        229 :          */
    2510            [ + ]:        229 :         get(name){
    2511                 :         28 :                 // validate the arguments
    2512                 :         28 :                 if(arguments.length < 1)
    2513            [ - ]:         28 :                         throw new TypeError(`FormData.delete: At least 1 argument required, but only ${arguments.length} passed`);
    2514                 :         28 : 
    2515                 :         28 :                 const entryList = formData.get(this);
    2516                 :         28 :                 for(let i = 0; i < entryList.length; i++)
    2517            [ + ]:         28 :                         if(entryList[i][name] !== undefined)
    2518       [ + ][ + ]:         37 :                                 return entryList[i][name];
    2519                 :          4 : 
    2520                 :          4 :                 return null;
    2521                 :         28 :         }
    2522                 :        229 : 
    2523                 :        229 :         /**
    2524                 :        229 :          * @method   getAll
    2525                 :        229 :          * @instance
    2526                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2527                 :        229 :          * @param    {string} name - The name of the key to be retrieved.
    2528                 :        229 :          * @return   {Array} An array of values whose key matches the specified name, otherwise, an empty list.
    2529                 :        229 :          * @desc     Returns all the values associated with a given key from within a FormData object.
    2530                 :        229 :          */
    2531            [ + ]:        229 :         getAll(name){
    2532                 :          3 :                 // validate the arguments
    2533                 :          3 :                 if(arguments.length < 1)
    2534            [ - ]:          3 :                         throw new TypeError(`FormData.delete: At least 1 argument required, but only ${arguments.length} passed`);
    2535                 :          3 : 
    2536                 :          3 :                 const result = [];
    2537                 :          3 :                 const entryList = formData.get(this);
    2538                 :          3 :                 for(let i = 0; i < entryList.length; i++)
    2539            [ + ]:          3 :                         if(entryList[i][name] !== undefined)
    2540            [ + ]:          4 :                                 result.push(entryList[i][name]);
    2541                 :          3 : 
    2542                 :          3 :                 return result;
    2543                 :          3 :         }
    2544                 :        229 : 
    2545                 :        229 :         /**
    2546                 :        229 :          * @method   has
    2547                 :        229 :          * @instance
    2548                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2549                 :        229 :          * @param    {string} name - The name of the key to be retrieved.
    2550                 :        229 :          * @return   {boolean} true if a key of FormData matches the specified name, otherwise, false.
    2551                 :        229 :          * @desc     Returns whether a FormData object contains a certain key.
    2552                 :        229 :          */
    2553            [ + ]:        229 :         has(name){
    2554                 :          3 :                 // validate the arguments
    2555                 :          3 :                 if(arguments.length < 1)
    2556            [ - ]:          3 :                         throw new TypeError(`FormData.delete: At least 1 argument required, but only ${arguments.length} passed`);
    2557                 :          3 : 
    2558                 :          3 :                 const entryList = formData.get(this);
    2559                 :          3 :                 for(let i = 0; i < entryList.length; i++)
    2560                 :          3 :                         if(entryList[i][name] !== undefined)
    2561       [ + ][ + ]:          3 :                                 return true;
    2562                 :          2 : 
    2563                 :          2 :                 return false;
    2564                 :          3 :         }
    2565                 :        229 : 
    2566                 :        229 :         /**
    2567                 :        229 :          * @method   set
    2568                 :        229 :          * @instance
    2569                 :        229 :          * @memberof module:whatwg-xhr.FormData
    2570                 :        229 :          * @param    {string}      name     - The name of the field whose data is contained in value.
    2571                 :        229 :          * @param    {string|Blob} value    - The field's value, can be a string or Blob, otherwise the value is converted to a string.
    2572                 :        229 :          * @param    {string}      filename - (Optional) The filename reported to the server (a string), when a Blob or File is passed as the second parameter.
    2573                 :        229 :          * @desc     Sets a new value for an existing key inside a FormData object, or adds the key/value if it does not already exist.
    2574                 :        229 :          */
    2575            [ + ]:        229 :         set(name, value, filename){
    2576                 :         15 : 
    2577                 :         15 :                 if(arguments.length === 0)
    2578            [ - ]:         15 :                         throw new TypeError(`FormData.set: 2 arguments required, but 0 found.`); // node.js
    2579                 :         15 : 
    2580                 :         15 :                 if(arguments.length === 1)
    2581            [ - ]:         15 :                         throw new TypeError(`FormData.set: 2 arguments required, but only 1 found.`); // node.js
    2582                 :         15 : 
    2583            [ + ]:         15 :                 if(arguments.length === 3 && !(value instanceof Blob))
    2584            [ - ]:         15 :                         throw new TypeError(`Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'`); // node.js
    2585                 :         15 : 
    2586                 :         15 :                 name = String(name);
    2587                 :         15 : 
    2588       [ + ][ + ]:         15 :                 value = value instanceof Blob ? value : String(value);
    2589       [ + ][ + ]:         15 :                 filename = arguments.length === 3 ? String(filename) : undefined;
    2590                 :         15 : 
    2591                 :         15 :                 const entryList = formData.get(this);
    2592                 :         15 :                 for(let i = 0; i < entryList.length; i++)
    2593            [ + ]:         15 :                         if(entryList[i][name] !== undefined)
    2594            [ + ]:         13 :                                 entryList.splice(i, 1);
    2595                 :         15 : 
    2596                 :         15 :                 const entry = makeEntry(name, value, filename);
    2597                 :         15 :                 entryList.push(entry);
    2598                 :         15 :         }
    2599                 :        229 : 
    2600            [ + ]:        229 :         entries(){
    2601                 :          1 :                 const entryList = formData.get(this);
    2602                 :          1 : 
    2603                 :          1 :                 let i = 0;
    2604                 :          1 :                 let iterator = {
    2605            [ + ]:          1 :                         next(){
    2606            [ + ]:          6 :                                 return i < entryList.length ?
    2607            [ + ]:          6 :                                         { value: Object.entries(entryList[i++])[0], done: false} :
    2608                 :          6 :                                         { value: undefined, done: true};
    2609                 :          1 :                         },
    2610                 :          1 :                 };
    2611                 :          1 :                 Object.defineProperty(iterator, Symbol.toStringTag, { value: 'FormData Iterator', writable: false, enumerable: false, configurable: true});
    2612                 :          1 : 
    2613                 :          1 :                 const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
    2614                 :          1 :                 Object.setPrototypeOf(iterator, esIteratorPrototype);
    2615                 :          1 : 
    2616                 :          1 :                 return Object.create(iterator);
    2617                 :          1 :         }
    2618                 :        229 : 
    2619            [ + ]:        229 :         keys(){
    2620                 :          1 :                 const entryList = formData.get(this);
    2621                 :          1 : 
    2622                 :          1 :                 let i = 0;
    2623                 :          1 :                 let iterator = {
    2624            [ + ]:          1 :                         next(){
    2625            [ + ]:          6 :                                 return i < entryList.length ?
    2626            [ + ]:          6 :                                         { value: Object.keys(entryList[i++])[0], done: false} :
    2627                 :          6 :                                         { value: undefined, done: true};
    2628                 :          1 :                         },
    2629                 :          1 :                 };
    2630                 :          1 :                 Object.defineProperty(iterator, Symbol.toStringTag, { value: 'FormData Iterator', writable: false, enumerable: false, configurable: true});
    2631                 :          1 : 
    2632                 :          1 :                 const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
    2633                 :          1 :                 Object.setPrototypeOf(iterator, esIteratorPrototype);
    2634                 :          1 : 
    2635                 :          1 :                 return Object.create(iterator);
    2636                 :          1 :         }
    2637                 :        229 : 
    2638            [ + ]:        229 :         values(){
    2639                 :          1 :                 const entryList = formData.get(this);
    2640                 :          1 : 
    2641                 :          1 :                 let i = 0;
    2642                 :          1 :                 let iterator = {
    2643            [ + ]:          1 :                         next(){
    2644            [ + ]:          6 :                                 return i < entryList.length ?
    2645            [ + ]:          6 :                                         { value: Object.values(entryList[i++])[0], done: false} :
    2646                 :          6 :                                         { value: undefined, done: true};
    2647                 :          1 :                         },
    2648                 :          1 :                 };
    2649                 :          1 :                 Object.defineProperty(iterator, Symbol.toStringTag, { value: 'FormData Iterator', writable: false, enumerable: false, configurable: true});
    2650                 :          1 : 
    2651                 :          1 :                 const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
    2652                 :          1 :                 Object.setPrototypeOf(iterator, esIteratorPrototype);
    2653                 :          1 : 
    2654                 :          1 :                 return Object.create(iterator);
    2655                 :          1 :         }
    2656                 :        229 : 
    2657                 :        229 : } // @endof class FormData
    2658                 :        229 : 
    2659                 :        229 : Object.defineProperty(FormData.prototype, Symbol.toStringTag, { value: 'FormData', writable: false, enumerable: false, configurable: true});
    2660                 :        229 : Object.defineProperty(FormData.prototype, Symbol.iterator, {
    2661            [ + ]:        229 :         value: function entries(){
    2662                 :         12 :                 const entryList = formData.get(this);
    2663                 :         12 : 
    2664                 :         12 :                 let i = 0;
    2665                 :         12 : 
    2666                 :         12 :                 let iterator = {
    2667            [ + ]:         12 :                         next(){
    2668            [ + ]:         31 :                                 return i < entryList.length ?
    2669            [ + ]:         31 :                                         { value: Object.entries(entryList[i++])[0], done: false} :
    2670                 :         31 :                                         { value: undefined, done: true};
    2671                 :         12 :                         },
    2672                 :         12 :                 };
    2673                 :         12 :                 Object.defineProperty(iterator, Symbol.toStringTag, { value: 'FormData Iterator', writable: false, enumerable: false, configurable: true});
    2674                 :         12 : 
    2675                 :         12 :                 return Object.create(iterator);
    2676                 :        229 :         },
    2677                 :        229 :         writable: false, enumerable: false, configurable: true
    2678                 :        229 : });
    2679                 :        229 : 
    2680                 :        229 : /**
    2681                 :        229 :  * HTML Living Standard — Last Updated 7 January 2025
    2682                 :        229 :  * url: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
    2683                 :        229 :  *
    2684                 :        229 :  * To create an entry given a string name, a string or Blob object value, and optionally a scalar value string filename:
    2685                 :        229 :  *   1. Set name to the result of converting name into a scalar value string.
    2686                 :        229 :  *   2. If value is a string, then set value to the result of converting value into a scalar value string.
    2687                 :        229 :  *   3. Otherwise:
    2688                 :        229 :  *      1. If value is not a File object, then set value to a new File object, representing the same bytes, whose name attribute value is "blob".
    2689                 :        229 :  *      2. If filename is given, then set value to a new File object, representing the same bytes, whose name attribute is filename.
    2690                 :        229 :  *   4. Return an entry whose name is name and whose value is value.
    2691                 :        229 :  *   Note:  These operations will create a new File object if either filename is given or the passed Blob is not a File object.
    2692                 :        229 :  *          In those cases, the identity of the passed Blob object is not kept.
    2693                 :        229 :  *
    2694                 :        229 :  * function makeEntry
    2695                 :        229 :  * @param   {string} name
    2696                 :        229 :  * @param   {string|Blob} value
    2697                 :        229 :  * @param   {?string} filename
    2698                 :        229 :  * @return  {object} Return an entry whose name is name and whose value is value.
    2699                 :        229 :  * @desc    To create an entry given a string name, a string or Blob object value, and optionally a scalar value string filename.
    2700                 :        229 :  * @see     https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry
    2701                 :        229 :  */
    2702            [ + ]:         66 : function makeEntry(name, value, filename) {
    2703                 :         66 : 
    2704                 :         66 :         // html.spec.1. Set name to the result of converting name into a scalar value string.
    2705                 :         66 :         name = Buffer.from(name).toString('utf8');
    2706                 :         66 : 
    2707                 :         66 :         // html.spec.2. If value is a string, then set value to the result of converting value into a scalar value string.
    2708            [ + ]:         66 :         if(typeof value === 'string'){
    2709                 :         55 :                 value = Buffer.from(value).toString('utf8')
    2710            [ + ]:         55 :         }
    2711                 :         11 :         // html.spec.3. Otherwise:
    2712                 :         11 :         else {
    2713                 :         11 :                 // html.spec.3.1. If value is not a File object, then set value to a new File object,
    2714                 :         11 :                 //                representing the same bytes, whose name attribute value is "blob".
    2715            [ + ]:         11 :                 if(!(value instanceof File)){
    2716                 :          8 :                         value = new File([value], 'blob', { type: value.type });
    2717                 :          8 :                 }
    2718                 :         11 : 
    2719                 :         11 :                 // html.spec.3.2. If filename is given, then set value to a new File object,
    2720                 :         11 :                 //                representing the same bytes, whose name attribute is filename.
    2721            [ + ]:         11 :                 if(filename !== undefined){
    2722                 :          6 :                         const options = {
    2723                 :          6 :                                 type: value.type,
    2724                 :          6 :                                 lastModified: value.lastModified
    2725                 :          6 :                         };
    2726                 :          6 : 
    2727                 :          6 :                         value = new File([value], filename, options);
    2728                 :          6 :                 }
    2729                 :         11 :         }
    2730                 :         66 : 
    2731                 :         66 :         // html.spec.4. Return an entry whose name is name and whose value is value.
    2732                 :         66 :         return { [name]: value };
    2733                 :         66 : }
    2734                 :        229 : 
    2735                 :        229 : /**
    2736                 :        229 :  * function readBlobSync
    2737                 :        229 :  * @param   {Blob|File} blob
    2738                 :        229 :  * @return  {Buffer} Return a buffer object with the contents of the Blob or File given.
    2739                 :        229 :  * @desc    Reads the contents of the Blob or File object synchronously, thus blocking the Node.js event loop and further JavaScript execution until return.
    2740                 :        229 :  */
    2741            [ + ]:         10 : function readBlobSync(blob){
    2742                 :         10 : 
    2743                 :         10 :         const contentBlob = '.whatwg-xhr-contentBlob-' + process.pid;
    2744                 :         10 :         const syncBlob    = '.whatwg-xhr-syncBlob-'    + process.pid;
    2745                 :         10 : 
    2746                 :         10 :         fs.writeFileSync(syncBlob, '', 'utf8');
    2747                 :         10 : 
    2748                 :         10 :         let threadCode = `\
    2749                 :         10 :                 const fs      = require('node:fs');
    2750                 :         10 :                 const threads = require('node:worker_threads');
    2751                 :         10 : 
    2752                 :         10 :                 threads.parentPort.once('message', (data) => {
    2753                 :         10 :                         data.arrayBuffer()
    2754                 :         10 :                                 .then(arrayBuffer => Buffer.from(arrayBuffer))
    2755                 :         10 :                                 .then(buf => {
    2756                 :         10 :                                         fs.writeFileSync('${contentBlob}', buf);
    2757                 :         10 :                                         fs.unlinkSync('${syncBlob}');
    2758                 :         10 :                                 });
    2759                 :         10 :                 });`;
    2760                 :         10 : 
    2761                 :         10 :         let worker = new threads.Worker(threadCode, {eval: true});
    2762                 :         10 : 
    2763                 :         10 :         worker.postMessage(blob);
    2764                 :         10 : 
    2765            [ + ]:         10 :         while(fs.existsSync(syncBlob));
    2766                 :         10 :         let buffer = fs.readFileSync(contentBlob);
    2767                 :         10 :         fs.unlinkSync(contentBlob);
    2768                 :         10 : 
    2769                 :         10 :         return buffer;
    2770                 :         10 : }
    2771                 :        229 : 
    2772                 :        229 : /**
    2773                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2774                 :        229 :  * url: https://xhr.spec.whatwg.org/#handle-errors
    2775                 :        229 :  *
    2776                 :        229 :  * To handle errors for an XMLHttpRequest object xhr, run these steps:
    2777                 :        229 :  * 1. If xhr’s send() flag is unset, then return.
    2778                 :        229 :  * 2. If xhr’s timed out flag is set, then run the request error steps for xhr, "timeout", and "TimeoutError" DOMException.
    2779                 :        229 :  * 3. Otherwise, if xhr’s response’s aborted flag is set, run the request error steps for xhr, "abort", and "AbortError" DOMException.
    2780                 :        229 :  * 4. Otherwise, if xhr’s response is a network error, then run the request error steps for xhr, error, and "NetworkError" DOMException.
    2781                 :        229 :  *
    2782                 :        229 :  * @func   handleError
    2783                 :        229 :  * @this   module:whatwg-xhr.XMLHttpRequest
    2784                 :        229 :  * @param  {object} Error object.
    2785                 :        229 :  * @desc   Handle errors for an XMLHttpRequest object, as given by {@link https://xhr.spec.whatwg.org/#handle-errors XHR specs}.
    2786                 :        229 :  */
    2787            [ + ]:        959 : function handleError(error){
    2788                 :        959 : 
    2789                 :        959 :         const requestData = xmlHttpRequest.get(this);
    2790                 :        959 : 
    2791                 :        959 :         // xhr.spec.1. If xhr’s send() flag is unset, then return.
    2792       [ + ][ + ]:        959 :         if(!requestData['sendFlag']){
    2793                 :          1 :                 return;
    2794            [ + ]:          1 :         }
    2795                 :          1 : 
    2796                 :          1 :         // xhr.spec.2. If xhr’s timed out flag is set, then run the request error steps for xhr, "timeout", and "TimeoutError" DOMException.
    2797            [ + ]:        959 :         if(requestData['timeoutFlag']){
    2798                 :          3 :                 requestErrorSteps.call(this, 'timeout', new DOMException('Timeout error', 'TimeoutError'));
    2799            [ + ]:          3 :         }
    2800                 :        457 :         else
    2801                 :        457 :         // xhr.spec.3. If xhr’s response’s aborted flag is set, run the request error steps for xhr, "abort", and "AbortError" DOMException.
    2802       [ + ][ - ]:        457 :         if(requestData['response'] && requestData['_responseAbort']){
    2803                 :          0 :                 requestErrorSteps.call(this, 'abort', new DOMException('Abort error', 'AbortError'));
    2804                 :          0 :         }
    2805                 :        457 :         else
    2806                 :        457 :         // xhr.spec.4. if xhr’s response is a network error, then run the request error steps for xhr, "error", and "NetworkError" DOMException.
    2807            [ + ]:        457 :         if(requestData['response'] === ''){
    2808                 :         38 :                 requestErrorSteps.call(this, 'error', new DOMException('Network error', 'NetworkError'));
    2809                 :         38 :         }
    2810                 :        959 : 
    2811                 :        229 : } // @endof function handleError
    2812                 :        229 : 
    2813                 :        229 : /**
    2814                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2815                 :        229 :  * url: https://xhr.spec.whatwg.org/#request-error-steps
    2816                 :        229 :  *
    2817                 :        229 :  * The request error steps for an XMLHttpRequest object <xhr>, <event>, and optionally <exception> are:
    2818                 :        229 :  * 1. Set <xhr>’s state to done.
    2819                 :        229 :  * 2. Unset <xhr>’s send() flag.
    2820                 :        229 :  * 3. Set <xhr>’s response to a network error.
    2821                 :        229 :  * 4. If <xhr>’s synchronous flag is set, then throw <exception>.
    2822                 :        229 :  * 5. Fire an event named readystatechange at <xhr>.
    2823                 :        229 :  *    Note: At this point it is clear that <xhr>’s synchronous flag is unset.
    2824                 :        229 :  * 6. If <xhr>’s upload complete flag is unset, then:
    2825                 :        229 :  *    1. Set <xhr>’s upload complete flag.
    2826                 :        229 :  *    2. If <xhr>’s upload listener flag is set, then:
    2827                 :        229 :  *       1. Fire a progress event named <event> at <xhr>’s upload object with 0 and 0.
    2828                 :        229 :  *       2. Fire a progress event named 'loadend' at <xhr>’s upload object with 0 and 0.
    2829                 :        229 :  * 7. Fire a progress event named <event> at <xhr> with 0 and 0.
    2830                 :        229 :  * 8. Fire a progress event named 'loadend' at <xhr> with 0 and 0.
    2831                 :        229 :  *
    2832                 :        229 :  * @func   requestErrorSteps
    2833                 :        229 :  * @this   module:whatwg-xhr.XMLHttpRequest
    2834                 :        229 :  * @param  {string} Event type
    2835                 :        229 :  * @param  {object|string} Exception
    2836                 :        229 :  * @desc   Request error steps for an XMLHttpRequest object <xhr>, <event>, and optionally <exception>, as given by {@link https://xhr.spec.whatwg.org/#request-error-steps XHR specs}.
    2837                 :        229 :  */
    2838            [ + ]:         54 : function requestErrorSteps(event, exception){
    2839                 :         54 : 
    2840                 :         54 :         const xhr = this;
    2841                 :         54 :         const requestData = xmlHttpRequest.get(xhr);
    2842                 :         54 : 
    2843                 :         54 :         // xhr.spec.1. Set <xhr>’s state to done.
    2844                 :         54 :         requestData['readyState'] = xhr.DONE;
    2845                 :         54 : 
    2846                 :         54 :         // xhr.spec.2. Unset <xhr>’s send() flag.
    2847                 :         54 :         requestData['sendFlag'] = false;
    2848                 :         54 : 
    2849                 :         54 :         // xhr.spec.3. Set <xhr>’s response to a network error.
    2850                 :         54 :         setResponseToNetworkError.call(xhr);
    2851                 :         54 : 
    2852                 :         54 :         // xhr.spec.4. If <xhr>’s synchronous flag is set, then throw <exception>.
    2853            [ + ]:         54 :         if(!requestData['async']){
    2854                 :         16 :                 throw exception;
    2855            [ + ]:         16 :         }
    2856                 :         22 : 
    2857                 :         22 :         // xhr.spec.5. Fire an event named readystatechange at <xhr>.
    2858                 :         22 :         xhr.dispatchEvent(new Event('readystatechange'));
    2859                 :         22 : 
    2860                 :         22 :         // xhr.spec.6. If <xhr>’s upload complete flag is unset, then:
    2861            [ + ]:         54 :         if(!requestData['uploadCompleteFlag']){
    2862                 :          5 : 
    2863                 :          5 :                 // xhr.spec.6.1. Set <xhr>’s upload complete flag.
    2864                 :          5 :                 requestData['uploadCompleteFlag'] = true;
    2865                 :          5 : 
    2866                 :          5 :                 // xhr.spec.6.2. If <xhr>’s upload listener flag is set, then:
    2867                 :          5 :                 if(requestData['uploadListenerFlag']){
    2868                 :          5 :                         const upload = requestData['upload'];
    2869                 :          5 : 
    2870                 :          5 :                         // xhr.spec.6.2.1. Fire a progress event named <event> at <xhr>’s upload object with 0 and 0.
    2871                 :          5 :                         upload.dispatchEvent(new ProgressEvent(event, {loaded: 0, total: 0}));
    2872                 :          5 : 
    2873                 :          5 :                         // xhr.spec.6.2.2. Fire a progress event named 'loadend' at <xhr>’s upload object with 0 and 0.
    2874                 :          5 :                         upload.dispatchEvent(new ProgressEvent('loadend', {loaded: 0, total: 0}));
    2875                 :          5 :                 }
    2876            [ + ]:          5 :         }
    2877                 :         22 : 
    2878                 :         22 :         // xhr.spec.7. Fire a progress event named <event> at <xhr> with 0 and 0.
    2879                 :         22 :         xhr.dispatchEvent(new ProgressEvent(event, {loaded: 0, total: 0}));
    2880                 :         22 : 
    2881                 :         22 :         // xhr.spec.7. Fire a progress event named 'loadend' at <xhr> with 0 and 0.
    2882                 :         22 :         xhr.dispatchEvent(new ProgressEvent('loadend', {loaded: 0, total: 0}));
    2883                 :         22 : 
    2884                 :        229 : } // @endof function requestErrorSteps
    2885                 :        229 : 
    2886                 :        229 : /**
    2887                 :        229 :  * Fetch Living Standard — Last Updated 17 June 2024
    2888                 :        229 :  * url: https://fetch.spec.whatwg.org/#concept-network-error
    2889                 :        229 :  *
    2890                 :        229 :  * A network error is a response whose type is "error", status is 0, status message is the empty byte sequence, header list is « »,
    2891                 :        229 :  * body is null, and body info is a new response body info.
    2892                 :        229 :  *
    2893                 :        229 :  * @func   setResponseToNetworkError
    2894                 :        229 :  * @this   module:whatwg-xhr.XMLHttpRequest
    2895                 :        229 :  * @desc   Network error is a response whose type is "error", as defined by {@link https://fetch.spec.whatwg.org/#concept-network-error Fetch specs}.
    2896                 :        229 :  */
    2897            [ + ]:        868 : function setResponseToNetworkError(){
    2898                 :        868 : 
    2899                 :        868 :         const requestData = xmlHttpRequest.get(this);
    2900                 :        868 : 
    2901            [ + ]:        868 :         if(requestData['fetchController']){
    2902                 :         31 :                 requestData['fetchController'].destroy();
    2903                 :         31 :                 requestData['fetchController'] = null;
    2904                 :         31 :         }
    2905                 :        868 : 
    2906                 :        868 :         requestData['response'] = '';
    2907                 :        868 : 
    2908                 :        868 :         //      requestData['status'] = 0;
    2909                 :        868 :         //      requestData['statusText'] = '';
    2910                 :        868 : 
    2911                 :        868 :         requestData['requestHeaders'    ] = {};
    2912                 :        868 :         requestData['requestHeadersCase'] = {};
    2913                 :        868 : 
    2914                 :        868 :         requestData['receivedBytes'] = Buffer.alloc(0);
    2915                 :        868 :         requestData['_responseBody'] = null;
    2916                 :        868 : 
    2917                 :        229 : } // @endof function setResponseToNetworkError
    2918                 :        229 : 
    2919                 :        229 : /*
    2920                 :        229 :  * XMLHttpRequest Living Standard — Last Updated 20 February 2023
    2921                 :        229 :  * url: https://xhr.spec.whatwg.org/#response-body
    2922                 :        229 :  *
    2923                 :        229 :  * 3.6.6. Response body
    2924                 :        229 :  *
    2925                 :        229 :  * To get a response MIME type for an XMLHttpRequest object xhr, run these steps:
    2926                 :        229 :  *  1. Let mimeType be the result of <extracting a MIME type> from xhr’s response’s header list.
    2927                 :        229 :  *  2. If mimeType is failure, then set mimeType to text/xml.
    2928                 :        229 :  *  3. Return mimeType.
    2929                 :        229 :  *
    2930                 :        229 :  * To get a final MIME type for an XMLHttpRequest object xhr, run these steps:
    2931                 :        229 :  *  1. If xhr’s <override MIME type> is null, return the result of get a response MIME type for xhr.
    2932                 :        229 :  *  2. Return xhr’s override MIME type.
    2933                 :        229 :  *
    2934                 :        229 :  * To get a final encoding for an XMLHttpRequest object xhr, run these steps:
    2935                 :        229 :  *  1. Let label be null.
    2936                 :        229 :  *  2. Let responseMIME be the result of <get a response MIME type> for xhr.
    2937                 :        229 :  *  3. If responseMIME’s parameters["charset"] exists, then set label to it.
    2938                 :        229 :  *  4. If xhr’s override MIME type’s parameters["charset"] exists, then set label to it.
    2939                 :        229 :  *  5. If label is null, then return null.
    2940                 :        229 :  *  6. Let encoding be the result of getting an encoding from label.
    2941                 :        229 :  *  7. If encoding is failure, then return null.
    2942                 :        229 :  *  8. Return encoding.
    2943                 :        229 :  * The above steps intentionally do not use the get a final MIME type as it would not be web compatible.
    2944                 :        229 :  *
    2945                 :        229 :  * To set a document response for an XMLHttpRequest object xhr, run these steps:
    2946                 :        229 :  *  1. If xhr’s response’s body is null, then return.
    2947                 :        229 :  *  2. Let finalMIME be the result of get a final MIME type for xhr.
    2948                 :        229 :  *  3. If finalMIME is not an HTML MIME type or an XML MIME type, then return.
    2949                 :        229 :  *  4. If xhr’s response type is the empty string and finalMIME is an HTML MIME type, then return.
    2950                 :        229 :  *     Note: This is restricted to xhr’s response type being "document" in order to prevent breaking legacy content.
    2951                 :        229 :  *  5. If finalMIME is an HTML MIME type, then:
    2952                 :        229 :  *     1. Let charset be the result of get a final encoding for xhr.
    2953                 :        229 :  *     2. If charset is null, prescan the first 1024 bytes of xhr’s received bytes and if that does not terminate
    2954                 :        229 :  *        unsuccessfully then let charset be the return value.
    2955                 :        229 :  *     3. If charset is null, then set charset to UTF-8.
    2956                 :        229 :  *     4. Let document be a document that represents the result parsing xhr’s received bytes
    2957                 :        229 :  *        following the rules set forth in the HTML Standard for an HTML parser with scripting
    2958                 :        229 :  *        disabled and a known definite encoding charset. [HTML]
    2959                 :        229 :  *     5. Flag document as an HTML document.
    2960                 :        229 :  *  6. Otherwise, let document be a document that represents the result of running the XML parser
    2961                 :        229 :  *     with XML scripting support disabled on xhr’s received bytes.
    2962                 :        229 :  *     If that fails (unsupported character encoding, namespace well-formedness error, etc.),
    2963                 :        229 :  *     then return null. [HTML]
    2964                 :        229 :  *     Note: Resources referenced will not be loaded and no associated XSLT will be applied.
    2965                 :        229 :  *  7. If charset is null, then set charset to UTF-8.
    2966                 :        229 :  *  8. Set document’s encoding to charset.
    2967                 :        229 :  *  9. Set document’s content type to finalMIME.
    2968                 :        229 :  * 10. Set document’s URL to xhr’s response’s URL.
    2969                 :        229 :  * 11. Set document’s origin to xhr’s relevant settings object’s origin.
    2970                 :        229 :  * 12. Set xhr’s response object to document.
    2971                 :        229 :  *
    2972                 :        229 :  * To get a text response for an XMLHttpRequest object xhr, run these steps:
    2973                 :        229 :  *  1. If xhr’s response’s body is null, then return the empty string.
    2974                 :        229 :  *  2. Let charset be the result of get a final encoding for xhr.
    2975                 :        229 :  *  3. If xhr’s response type is the empty string, charset is null, and the result of get a final MIME type for xhr is an XML MIME type,
    2976                 :        229 :  *     then use the rules set forth in the XML specifications to determine the encoding. Let charset be the determined encoding. [XML] [XML-NAMES]
    2977                 :        229 :  *     This is restricted to xhr’s response type being the empty string to keep the non-legacy response type value "text" simple.
    2978                 :        229 :  *  4. If charset is null, then set charset to UTF-8.
    2979                 :        229 :  *  5. Return the result of running decode on xhr’s received bytes using fallback encoding charset.
    2980                 :        229 :  *  Authors are strongly encouraged to always encode their resources using UTF-8.
    2981                 :        229 :  */
    2982                 :        229 : 
    2983                 :        229 : /**
    2984                 :        229 :  * @func     getResponseMimeType
    2985                 :        229 :  * @this     module:whatwg-xhr.XMLHttpRequest
    2986                 :        229 :  * @return   {string} MIME type.
    2987                 :        229 :  * @desc     Get a response MIME type for an XMLHttpRequest object xhr, as given by {@link https://xhr.spec.whatwg.org/#response-body XHR specs}.
    2988                 :        229 :  * @requires module:helper-content-type.parse
    2989                 :        229 :  */
    2990            [ + ]:        908 : function getResponseMimeType(){
    2991                 :        908 : 
    2992                 :        908 :         const requestData = xmlHttpRequest.get(this);
    2993                 :        908 :         const response = requestData['response'];
    2994                 :        908 : 
    2995                 :        908 :         let mimeType = '';
    2996                 :        908 : 
    2997                 :        908 :         // xhr.spec.1. Let mimeType be the result of <extracting a MIME type> from xhr’s response’s header list.
    2998                 :        908 :         try{
    2999                 :        908 :                 let obj = contentTypeParse(response.headers['content-type']);
    3000                 :        908 :                 mimeType = response.headers['content-type'];
    3001                 :        908 :         }
    3002                 :        908 :         // xhr.spec.2. If mimeType is failure, then set mimeType to text/xml.
    3003            [ + ]:        908 :         catch(e){
    3004                 :         48 :                 mimeType = 'text/xml';
    3005                 :         48 :         }
    3006                 :        908 : 
    3007                 :        908 :         // xhr.spec.3. Return mimeType.
    3008                 :        908 :         return mimeType;
    3009                 :        908 : 
    3010                 :        229 : } // @endof function getResponseMimeType
    3011                 :        229 : 
    3012                 :        229 : /**
    3013                 :        229 :  * @func   getFinalMimeType
    3014                 :        229 :  * @this   module:whatwg-xhr.XMLHttpRequest
    3015                 :        229 :  * @return {string} MIME type.
    3016                 :        229 :  * @desc   Get a final MIME type for an XMLHttpRequest object xhr, as given by {@link https://xhr.spec.whatwg.org/#response-body XHR specs}.
    3017                 :        229 :  */
    3018            [ + ]:        496 : function getFinalMimeType(){
    3019                 :        496 : 
    3020                 :        496 :         const requestData = xmlHttpRequest.get(this);
    3021                 :        496 : 
    3022                 :        496 :         // xhr.spec.1. If xhr’s <override MIME type> is null, return the result of get a response MIME type for xhr.
    3023                 :        496 :         if(requestData['overrideMimeType'] === null)
    3024       [ + ][ + ]:        496 :                 return getResponseMimeType.call(this);
    3025                 :          1 : 
    3026                 :          1 :         // xhr.spec.2. Return xhr’s override MIME type.
    3027                 :          1 :         return requestData['overrideMimeType'];
    3028                 :          1 : 
    3029                 :        229 : } // @endof function getFinalMimeType
    3030                 :        229 : 
    3031                 :        229 : /**
    3032                 :        229 :  * @func     getFinalEncoding
    3033                 :        229 :  * @this     module:whatwg-xhr.XMLHttpRequest
    3034                 :        229 :  * @return   {string|null} Final encoding.
    3035                 :        229 :  * @desc     Get a final encoding for an XMLHttpRequest object xhr, as given by {@link https://xhr.spec.whatwg.org/#response-body XHR specs}.
    3036                 :        229 :  * @requires module:helper-content-type.parse
    3037                 :        229 :  */
    3038            [ + ]:        413 : function getFinalEncoding(){
    3039                 :        413 : 
    3040                 :        413 :         const requestData = xmlHttpRequest.get(this);
    3041                 :        413 : 
    3042                 :        413 :         // xhr.spec.1. Let label be null.
    3043                 :        413 :         let label = null;
    3044                 :        413 : 
    3045                 :        413 :         // xhr.spec.2. Let responseMIME be the result of <get a response MIME type> for xhr.
    3046                 :        413 :         let responseMIME = getResponseMimeType.call(this);
    3047                 :        413 : 
    3048                 :        413 :         let obj = null;
    3049                 :        413 :         // xhr.spec.3. If responseMIME’s parameters["charset"] exists, then set label to it.
    3050                 :        413 :         try{
    3051                 :        413 :                 obj = contentTypeParse(responseMIME);
    3052                 :        413 :                 if(obj.parameters && obj.parameters.charset)
    3053            [ + ]:        413 :                         label = obj.parameters.charset;
    3054            [ - ]:        413 :         }catch(e){}
    3055                 :        413 : 
    3056                 :        413 :         // xhr.spec.4. If xhr’s override MIME type’s parameters["charset"] exists, then set label to it.
    3057            [ + ]:        413 :         if(requestData['overrideMimeType']){
    3058                 :          4 :                 try{
    3059                 :          4 :                         obj = contentTypeParse(requestData['overrideMimeType']);
    3060                 :          4 :                         if(obj.parameters && obj.parameters.charset)
    3061            [ + ]:          4 :                                 label = obj.parameters.charset;
    3062                 :          4 :                 }catch(e){}
    3063                 :          4 :         }
    3064                 :        413 : 
    3065                 :        413 :         // xhr.spec.5. If label is null, then return null.
    3066       [ + ][ + ]:        413 :         if(label === null) return null;
    3067                 :         17 : 
    3068                 :         17 :         // xhr.spec.6. Let encoding be the result of getting an encoding from label.
    3069                 :         17 :         let encoding = whatwgEncoding.labelToName(label);
    3070                 :         17 : 
    3071                 :         17 :         // xhr.spec.7. If encoding is failure, then return null.
    3072                 :         17 :         // xhr.spec.8. Return encoding.
    3073                 :         17 :         return encoding;
    3074                 :         17 : 
    3075                 :        229 : } // @endof function getFinalEncoding
    3076                 :        229 : 
    3077                 :        229 : /**
    3078                 :        229 :  * @func     setDocumentResponse
    3079                 :        229 :  * @this     module:whatwg-xhr.XMLHttpRequest
    3080                 :        229 :  * @desc     Set a document response for an XMLHttpRequest object xhr, as given by {@link https://xhr.spec.whatwg.org/#response-body XHR specs}.
    3081                 :        229 :  * @requires module:helper-content-type.parse
    3082                 :        229 :  */
    3083            [ + ]:        216 : function setDocumentResponse(){
    3084                 :        216 : 
    3085                 :        216 :         const requestData = xmlHttpRequest.get(this);
    3086                 :        216 : 
    3087                 :        216 :         // xhr.spec.1. If xhr’s response’s body is null, then return.
    3088            [ + ]:        216 :         if(requestData['receivedBytes'].length === 0) return;
    3089                 :          2 : 
    3090                 :          2 :         // xhr.spec.2. Let <finalMIME> be the result of get a final MIME type for xhr.
    3091                 :          2 :         let finalMIME = getFinalMimeType.call(this);
    3092                 :          2 :         let obj;
    3093                 :          2 : 
    3094                 :          2 :         try{
    3095                 :          2 :                 obj = contentTypeParse(finalMIME);
    3096                 :          2 : 
    3097                 :          2 :                 // xhr.spec.3. If <finalMIME> is not an HTML MIME type or an XML MIME type, then return.
    3098                 :          2 :                 if(
    3099                 :          2 :                         obj.type !== 'text/xml'        &&
    3100            [ + ]:        216 :                         obj.type !== 'application/xml' &&
    3101            [ + ]:        216 :                         !obj.type.endsWith('+xml')     &&
    3102                 :          2 :                         obj.type !== 'text/html'
    3103                 :        216 :                 )
    3104            [ + ]:        216 :                         return;
    3105                 :          1 : 
    3106                 :          1 :                 // xhr.spec.4. If xhr’s response type is the empty string and <finalMIME> is an HTML MIME type, then return.
    3107                 :        216 :                 if(obj.type === 'text/html' && this.responseType === '')
    3108            [ + ]:        216 :                         return;
    3109                 :        216 : 
    3110                 :        216 :                 // xhr.spec.5. If finalMIME is an HTML MIME type, then:
    3111            [ - ]:        216 :                 if(obj.type === 'text/html'){
    3112                 :          0 :                         /* node:coverage disable */
    3113                 :            : 
    3114                 :            :                         // xhr.spec.5.1. Let <charset> be the result of get a final encoding for xhr.
    3115                 :            :                         let charset = getFinalEncoding.call(this);
    3116                 :            : 
    3117                 :            :                         // xhr.spec.5.2. If <charset> is null, prescan the first 1024 bytes of xhr’s received bytes and if that does not terminate
    3118                 :            :                         //               unsuccessfully then let <charset> be the return value.
    3119                 :            :                         if(charset === null){
    3120                 :            :                                 charset = htmlEncodingSniffer(requestData['receivedBytes'].subarray(0, 1024));
    3121                 :            :                         }
    3122                 :            : 
    3123                 :            :                         // xhr.spec.5.3. If <charset> is null, then set <charset> to UTF-8.
    3124                 :            :                         if(charset === null) charset = 'UTF-8';
    3125                 :            : 
    3126                 :            :                         // xhr.spec.5.4. Let <document> be a document that represents the result parsing xhr’s received bytes
    3127                 :            :                         //               following the rules set forth in the HTML Standard for an HTML parser with scripting
    3128                 :            :                         //               disabled and a known definite encoding charset. [HTML]
    3129                 :            :                         // xhr.spec.5.5. Flag document as an HTML document.
    3130                 :            : 
    3131                 :            :                         // @todo...
    3132                 :            : 
    3133                 :            :                         /* node:coverage enable */
    3134                 :          0 :                 }
    3135                 :        216 :                 else{
    3136                 :        216 :                         // xhr.spec.6. Otherwise, let document be a document that represents the result of running the XML parser
    3137                 :        216 :                         //             with XML scripting support disabled on xhr’s received bytes.
    3138                 :        216 :                         //             If that fails (unsupported character encoding, namespace well-formedness error, etc.),
    3139                 :        216 :                         //             then return null. [HTML]
    3140                 :        216 :                         // Note: Resources referenced will not be loaded and no associated XSLT will be applied.
    3141                 :        216 : 
    3142                 :        216 :                         // @todo...
    3143                 :        216 :                 }
    3144            [ - ]:        216 :         }catch(e){
    3145                 :          0 :                 return;
    3146                 :          0 :         }
    3147                 :        216 : 
    3148                 :        216 :         // xhr.spec.7. If charset is null, then set charset to UTF-8.
    3149                 :        216 :         // xhr.spec.8. Set document’s encoding to charset.
    3150                 :        216 :         // xhr.spec.9. Set document’s content type to finalMIME.
    3151                 :        216 :         // xhr.spec.10. Set document’s URL to xhr’s response’s URL.
    3152                 :        216 :         // xhr.spec.11. Set document’s origin to xhr’s relevant settings object’s origin.
    3153                 :        216 : 
    3154                 :        216 :         // @todo...
    3155                 :        216 : 
    3156                 :        216 :         // xhr.spec.12. Set xhr’s response object to document.
    3157                 :        216 :         requestData['responseObject'] = null;
    3158                 :        216 : 
    3159                 :        229 : } // @endof function setDocumentResponse
    3160                 :        229 : 
    3161                 :        229 : /**
    3162                 :        229 :  * @func     getTextResponse
    3163                 :        229 :  * @this     module:whatwg-xhr.XMLHttpRequest
    3164                 :        229 :  * @return   {string} Text response.
    3165                 :        229 :  * @desc     Get a text for an XMLHttpRequest object xhr, as given by {@link https://xhr.spec.whatwg.org/#response-body XHR specs}.
    3166                 :        229 :  * @requires module:helper-content-type.parse
    3167                 :        229 :  * @requires module:helper-xml-encoding-sniffer.xmlEncodingSniffer
    3168                 :        229 :  */
    3169            [ + ]:        723 : function getTextResponse(){
    3170                 :        723 : 
    3171                 :        723 :         const requestData = xmlHttpRequest.get(this);
    3172                 :        723 : 
    3173                 :        723 :         // xhr.spec.1. If xhr’s response’s body is null, then return the empty string.
    3174                 :        723 :         // @author. if(requestData['_responseBody'] === null)
    3175            [ + ]:        723 :         if(requestData['receivedBytes'].length === 0){
    3176                 :        104 :                 return '';
    3177            [ + ]:        104 :         }
    3178                 :        195 : 
    3179                 :        195 :         // xhr.spec.2. Let charset be the result of get a final encoding for xhr.
    3180                 :        195 :         let charset = getFinalEncoding.call(this);
    3181                 :        195 : 
    3182                 :        195 :         // xhr.spec.3. If xhr’s response type is the empty string, charset is null, and the result of get a final MIME type for xhr is an XML MIME type,
    3183                 :        195 :         //             then use the rules set forth in the XML specifications to determine the encoding. Let charset be the determined encoding. [XML] [XML-NAMES]
    3184                 :        195 :         //             This is restricted to xhr’s response type being the empty string to keep the non-legacy response type value "text" simple.
    3185       [ + ][ + ]:        723 :         if(requestData['responseType'] === '' && charset === null){
    3186                 :        165 :                 let finalMimeType = getFinalMimeType.call(this);
    3187                 :        165 :                 try{
    3188                 :        165 :                         let obj = contentTypeParse(finalMimeType);
    3189  [ + ][ + ][ + ]:        165 :                         if(obj.type === 'text/xml' || obj.type === 'application/xml' || obj.type.endsWith('+xml')){
    3190                 :         29 :                                 // @todo. use the rules set forth in the XML specifications to determine the encoding. Let charset be the determined encoding.
    3191                 :         29 :                                 charset = xmlEncodingSniffer(requestData['receivedBytes']);
    3192                 :         29 :                         }
    3193            [ - ]:        165 :                 }catch(e){}
    3194            [ + ]:        165 :         }
    3195                 :        195 : 
    3196                 :        195 :         // xhr.spec.4. If charset is null, then set charset to UTF-8.
    3197       [ + ][ + ]:        723 :         if(charset === null) charset = 'UTF-8';
    3198                 :        195 : 
    3199                 :        195 :         // xhr.spec.5. Return the result of running decode on xhr’s received bytes using fallback encoding charset.
    3200                 :        195 :         return whatwgEncoding.decode(requestData['receivedBytes'], charset);
    3201                 :        195 : 
    3202                 :        229 : } // @endof function getTextResponse
    3203                 :        229 : 
    3204                 :        229 : /**
    3205                 :        229 :  * @class ClientRequestData
    3206                 :        229 :  * @desc Emulates the node http.ClientRequest for processing data url's.
    3207                 :        229 :  */
    3208                 :        229 : class ClientRequestData{
    3209                 :        229 : 
    3210                 :        229 :         /**
    3211                 :        229 :          * @method   constructor
    3212                 :        229 :          * @instance
    3213                 :        229 :          * @memberof module:whatwg-xhr~ClientRequestData
    3214                 :        229 :          * @param    {object} response - Emulates the http.IncomingMessage object.
    3215                 :        229 :          * @return   {object} ClientRequestData object.
    3216                 :        229 :          * @desc     Constructs a new ClientRequestData object.
    3217                 :        229 :          */
    3218            [ + ]:        229 :         constructor(response){
    3219                 :         13 :                 this.response = response;
    3220                 :         13 :         }
    3221                 :        229 : 
    3222                 :        229 :         /**
    3223                 :        229 :          * @method   destroy
    3224                 :        229 :          * @instance
    3225                 :        229 :          * @memberof module:whatwg-xhr~ClientRequestData
    3226                 :        229 :          * @return   {object} ClientRequestData object.
    3227                 :        229 :          * @desc     Emulates the node http.ClientRequest destroy() method.
    3228                 :        229 :          */
    3229            [ + ]:        229 :         destroy(){
    3230                 :          2 :                 return this;
    3231                 :          2 :         }
    3232                 :        229 : 
    3233                 :        229 :         /**
    3234                 :        229 :          * @method   end
    3235                 :        229 :          * @instance
    3236                 :        229 :          * @memberof module:whatwg-xhr~ClientRequestData
    3237                 :        229 :          * @param    {function} callback - Callback function to invoke.
    3238                 :        229 :          * @return   {object} ClientRequestData object.
    3239                 :        229 :          * @desc     Emulates the node http.ClientRequest end() method.
    3240                 :        229 :          */
    3241            [ + ]:        229 :         end(callback){
    3242                 :         13 :                 if(typeof callback === 'function')
    3243            [ - ]:         13 :                         callback();
    3244                 :         13 : 
    3245                 :         13 :                 return this;
    3246                 :         13 :         }
    3247                 :        229 : 
    3248                 :        229 :         /**
    3249                 :        229 :          * @method   on
    3250                 :        229 :          * @instance
    3251                 :        229 :          * @memberof module:whatwg-xhr~ClientRequestData
    3252                 :        229 :          * @param    {string} type - The event to invoke.
    3253                 :        229 :          * @param    {function} callback - Callback function to invoke.
    3254                 :        229 :          * @return   {object} ClientRequestData object.
    3255                 :        229 :          * @desc     Emulates the node http.ClientRequest on() method.
    3256                 :        229 :          */
    3257            [ + ]:        229 :         on(type, callback){
    3258            [ + ]:         39 :                 if(type === 'response' && typeof callback === 'function')
    3259       [ + ][ + ]:         39 :                         callback(this.response);
    3260                 :         26 :                 else
    3261       [ + ][ + ]:         26 :                 if(type === 'error' && typeof callback === 'function' && this.response.statusCode === 0)
    3262            [ + ]:         26 :                         callback(new ProgressEvent('error'));
    3263                 :         39 : 
    3264                 :         39 :                 return this;
    3265                 :         39 :         }
    3266                 :        229 : } // @endof class ClientRequestData
    3267                 :        229 : 
    3268                 :        229 : /**
    3269                 :        229 :  * @func     requestDataURL
    3270                 :        229 :  * @param    {object} options - Options passed to the node http.request function.
    3271                 :        229 :  * @return   {object} ClientRequestData object.
    3272                 :        229 :  * @desc     Emulates the node http.request function for processing data url's.
    3273                 :        229 :  * @requires module:whatwg-misc.dataURLProcessor
    3274                 :        229 :  * @requires module:whatwg-misc.serializeAMimeType
    3275                 :        229 :  */
    3276            [ + ]:         13 : function requestDataURL(options){
    3277                 :         13 : 
    3278                 :         13 :         let urlStruct = null;
    3279                 :         13 :         let responseDataURL = null;
    3280                 :         13 : 
    3281                 :         13 :         try{
    3282                 :         13 :                 urlStruct = dataURLProcessor(new URL(options.url));
    3283            [ - ]:         13 :         }catch(e){
    3284                 :          0 :                 urlStruct = 'failure';
    3285                 :          0 :         }
    3286                 :         13 : 
    3287            [ + ]:         13 :         if(urlStruct !== 'failure'){
    3288                 :         11 : 
    3289                 :         11 :                 if(options.method.toUpperCase() === 'HEAD')
    3290       [ + ][ + ]:         11 :                         responseDataURL = Readable.from(Buffer.alloc(0));
    3291                 :         10 :                 else
    3292                 :         10 :                         responseDataURL = Readable.from(Buffer.from(urlStruct.body));
    3293                 :         11 : 
    3294                 :         11 :                 responseDataURL.statusCode = 200;
    3295                 :         11 :                 responseDataURL.statusMessage = 'OK';
    3296                 :         11 :                 responseDataURL.url = options.url;
    3297                 :         11 : 
    3298                 :         11 :                 responseDataURL.headers = {
    3299                 :         11 :                         'Content-Type': serializeAMimeType(urlStruct.mimeType),
    3300                 :         11 :                 }
    3301            [ + ]:         11 :         }
    3302                 :          1 :         else{
    3303                 :          1 :                 responseDataURL = Readable.from(Buffer.alloc(0));
    3304                 :          1 : 
    3305                 :          1 :                 responseDataURL.statusCode = 0;
    3306                 :          1 :                 responseDataURL.statusMessage = '';
    3307                 :          1 : 
    3308                 :          1 :                 responseDataURL.headers = {};
    3309                 :          1 :         }
    3310                 :         13 : 
    3311                 :         13 :         return new ClientRequestData(responseDataURL);
    3312                 :         13 : 
    3313                 :        229 : } // @endof function requestDataURL

Generated by: LCOV version 1.14