|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904 |
- "use strict";
-
- var GlobalTextEncoder =
- typeof TextEncoder !== "undefined"
- ? TextEncoder
- : require("@sinonjs/text-encoding").TextEncoder;
- var globalObject = require("@sinonjs/commons").global;
- var configureLogError = require("../configure-logger");
- var sinonEvent = require("../event");
- var extend = require("just-extend");
-
- var supportsProgress = typeof ProgressEvent !== "undefined";
- var supportsCustomEvent = typeof CustomEvent !== "undefined";
- var supportsFormData = typeof FormData !== "undefined";
- var supportsArrayBuffer = typeof ArrayBuffer !== "undefined";
- var supportsBlob = require("./blob").isSupported;
-
- function getWorkingXHR(globalScope) {
- var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined";
- if (supportsXHR) {
- return globalScope.XMLHttpRequest;
- }
-
- var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined";
- if (supportsActiveX) {
- return function() {
- return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");
- };
- }
-
- return false;
- }
-
- // Ref: https://fetch.spec.whatwg.org/#forbidden-header-name
- var unsafeHeaders = {
- "Accept-Charset": true,
- "Access-Control-Request-Headers": true,
- "Access-Control-Request-Method": true,
- "Accept-Encoding": true,
- Connection: true,
- "Content-Length": true,
- Cookie: true,
- Cookie2: true,
- "Content-Transfer-Encoding": true,
- Date: true,
- DNT: true,
- Expect: true,
- Host: true,
- "Keep-Alive": true,
- Origin: true,
- Referer: true,
- TE: true,
- Trailer: true,
- "Transfer-Encoding": true,
- Upgrade: true,
- "User-Agent": true,
- Via: true
- };
-
- function EventTargetHandler() {
- var self = this;
- var events = [
- "loadstart",
- "progress",
- "abort",
- "error",
- "load",
- "timeout",
- "loadend"
- ];
-
- function addEventListener(eventName) {
- self.addEventListener(eventName, function(event) {
- var listener = self[`on${eventName}`];
-
- if (listener && typeof listener === "function") {
- listener.call(this, event);
- }
- });
- }
-
- events.forEach(addEventListener);
- }
-
- EventTargetHandler.prototype = sinonEvent.EventTarget;
-
- function normalizeHeaderValue(value) {
- // Ref: https://fetch.spec.whatwg.org/#http-whitespace-bytes
- /*eslint no-control-regex: "off"*/
- return value.replace(/^[\x09\x0A\x0D\x20]+|[\x09\x0A\x0D\x20]+$/g, "");
- }
-
- function getHeader(headers, header) {
- var foundHeader = Object.keys(headers).filter(function(h) {
- return h.toLowerCase() === header.toLowerCase();
- });
-
- return foundHeader[0] || null;
- }
-
- function excludeSetCookie2Header(header) {
- return !/^Set-Cookie2?$/i.test(header);
- }
-
- function verifyResponseBodyType(body, responseType) {
- var error = null;
- var isString = typeof body === "string";
-
- if (responseType === "arraybuffer") {
- if (!isString && !(body instanceof ArrayBuffer)) {
- error = new Error(
- `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string or ArrayBuffer.`
- );
- error.name = "InvalidBodyException";
- }
- } else if (!isString) {
- error = new Error(
- `Attempted to respond to fake XMLHttpRequest with ${body}, which is not a string.`
- );
- error.name = "InvalidBodyException";
- }
-
- if (error) {
- throw error;
- }
- }
-
- function convertToArrayBuffer(body, encoding) {
- if (body instanceof ArrayBuffer) {
- return body;
- }
-
- return new GlobalTextEncoder(encoding || "utf-8").encode(body).buffer;
- }
-
- function isXmlContentType(contentType) {
- return (
- !contentType ||
- /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType)
- );
- }
-
- function clearResponse(xhr) {
- if (xhr.responseType === "" || xhr.responseType === "text") {
- xhr.response = xhr.responseText = "";
- } else {
- xhr.response = xhr.responseText = null;
- }
- xhr.responseXML = null;
- }
-
- function fakeXMLHttpRequestFor(globalScope) {
- var isReactNative =
- globalScope.navigator &&
- globalScope.navigator.product === "ReactNative";
- var sinonXhr = { XMLHttpRequest: globalScope.XMLHttpRequest };
- sinonXhr.GlobalXMLHttpRequest = globalScope.XMLHttpRequest;
- sinonXhr.GlobalActiveXObject = globalScope.ActiveXObject;
- sinonXhr.supportsActiveX =
- typeof sinonXhr.GlobalActiveXObject !== "undefined";
- sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined";
- sinonXhr.workingXHR = getWorkingXHR(globalScope);
- sinonXhr.supportsTimeout =
- sinonXhr.supportsXHR &&
- "timeout" in new sinonXhr.GlobalXMLHttpRequest();
- sinonXhr.supportsCORS =
- isReactNative ||
- (sinonXhr.supportsXHR &&
- "withCredentials" in new sinonXhr.GlobalXMLHttpRequest());
-
- // Note that for FakeXMLHttpRequest to work pre ES5
- // we lose some of the alignment with the spec.
- // To ensure as close a match as possible,
- // set responseType before calling open, send or respond;
- function FakeXMLHttpRequest(config) {
- EventTargetHandler.call(this);
- this.readyState = FakeXMLHttpRequest.UNSENT;
- this.requestHeaders = {};
- this.requestBody = null;
- this.status = 0;
- this.statusText = "";
- this.upload = new EventTargetHandler();
- this.responseType = "";
- this.response = "";
- this.logError = configureLogError(config);
-
- if (sinonXhr.supportsTimeout) {
- this.timeout = 0;
- }
-
- if (sinonXhr.supportsCORS) {
- this.withCredentials = false;
- }
-
- if (typeof FakeXMLHttpRequest.onCreate === "function") {
- FakeXMLHttpRequest.onCreate(this);
- }
- }
-
- function verifyState(xhr) {
- if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
- throw new Error("INVALID_STATE_ERR");
- }
-
- if (xhr.sendFlag) {
- throw new Error("INVALID_STATE_ERR");
- }
- }
-
- // largest arity in XHR is 5 - XHR#open
- var apply = function(obj, method, args) {
- switch (args.length) {
- case 0:
- return obj[method]();
- case 1:
- return obj[method](args[0]);
- case 2:
- return obj[method](args[0], args[1]);
- case 3:
- return obj[method](args[0], args[1], args[2]);
- case 4:
- return obj[method](args[0], args[1], args[2], args[3]);
- case 5:
- return obj[method](args[0], args[1], args[2], args[3], args[4]);
- default:
- throw new Error("Unhandled case");
- }
- };
-
- FakeXMLHttpRequest.filters = [];
- FakeXMLHttpRequest.addFilter = function addFilter(fn) {
- this.filters.push(fn);
- };
- FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
- var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap
-
- [
- "open",
- "setRequestHeader",
- "abort",
- "getResponseHeader",
- "getAllResponseHeaders",
- "addEventListener",
- "overrideMimeType",
- "removeEventListener"
- ].forEach(function(method) {
- fakeXhr[method] = function() {
- return apply(xhr, method, arguments);
- };
- });
-
- fakeXhr.send = function() {
- // Ref: https://xhr.spec.whatwg.org/#the-responsetype-attribute
- if (xhr.responseType !== fakeXhr.responseType) {
- xhr.responseType = fakeXhr.responseType;
- }
- return apply(xhr, "send", arguments);
- };
-
- var copyAttrs = function(args) {
- args.forEach(function(attr) {
- fakeXhr[attr] = xhr[attr];
- });
- };
-
- var stateChangeStart = function() {
- fakeXhr.readyState = xhr.readyState;
- if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
- copyAttrs(["status", "statusText"]);
- }
- if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
- copyAttrs(["response"]);
- if (xhr.responseType === "" || xhr.responseType === "text") {
- copyAttrs(["responseText"]);
- }
- }
- if (
- xhr.readyState === FakeXMLHttpRequest.DONE &&
- (xhr.responseType === "" || xhr.responseType === "document")
- ) {
- copyAttrs(["responseXML"]);
- }
- };
-
- var stateChangeEnd = function() {
- if (fakeXhr.onreadystatechange) {
- // eslint-disable-next-line no-useless-call
- fakeXhr.onreadystatechange.call(fakeXhr, {
- target: fakeXhr,
- currentTarget: fakeXhr
- });
- }
- };
-
- var stateChange = function stateChange() {
- stateChangeStart();
- stateChangeEnd();
- };
-
- if (xhr.addEventListener) {
- xhr.addEventListener("readystatechange", stateChangeStart);
-
- Object.keys(fakeXhr.eventListeners).forEach(function(event) {
- /*eslint-disable no-loop-func*/
- fakeXhr.eventListeners[event].forEach(function(handler) {
- xhr.addEventListener(event, handler.listener, {
- capture: handler.capture,
- once: handler.once
- });
- });
- /*eslint-enable no-loop-func*/
- });
-
- xhr.addEventListener("readystatechange", stateChangeEnd);
- } else {
- xhr.onreadystatechange = stateChange;
- }
- apply(xhr, "open", xhrArgs);
- };
- FakeXMLHttpRequest.useFilters = false;
-
- function verifyRequestOpened(xhr) {
- if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
- throw new Error(`INVALID_STATE_ERR - ${xhr.readyState}`);
- }
- }
-
- function verifyRequestSent(xhr) {
- if (xhr.readyState === FakeXMLHttpRequest.DONE) {
- throw new Error("Request done");
- }
- }
-
- function verifyHeadersReceived(xhr) {
- if (
- xhr.async &&
- xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED
- ) {
- throw new Error("No headers received");
- }
- }
-
- function convertResponseBody(responseType, contentType, body) {
- if (responseType === "" || responseType === "text") {
- return body;
- } else if (supportsArrayBuffer && responseType === "arraybuffer") {
- return convertToArrayBuffer(body);
- } else if (responseType === "json") {
- try {
- return JSON.parse(body);
- } catch (e) {
- // Return parsing failure as null
- return null;
- }
- } else if (supportsBlob && responseType === "blob") {
- var blobOptions = {};
- if (contentType) {
- blobOptions.type = contentType;
- }
- return new Blob([convertToArrayBuffer(body)], blobOptions);
- } else if (responseType === "document") {
- if (isXmlContentType(contentType)) {
- return FakeXMLHttpRequest.parseXML(body);
- }
- return null;
- }
- throw new Error(`Invalid responseType ${responseType}`);
- }
-
- /**
- * Steps to follow when there is an error, according to:
- * https://xhr.spec.whatwg.org/#request-error-steps
- */
- function requestErrorSteps(xhr) {
- clearResponse(xhr);
- xhr.errorFlag = true;
- xhr.requestHeaders = {};
- xhr.responseHeaders = {};
-
- if (
- xhr.readyState !== FakeXMLHttpRequest.UNSENT &&
- xhr.sendFlag &&
- xhr.readyState !== FakeXMLHttpRequest.DONE
- ) {
- xhr.readyStateChange(FakeXMLHttpRequest.DONE);
- xhr.sendFlag = false;
- }
- }
-
- FakeXMLHttpRequest.parseXML = function parseXML(text) {
- // Treat empty string as parsing failure
- if (text !== "") {
- try {
- if (typeof DOMParser !== "undefined") {
- var parser = new DOMParser();
- var parsererrorNS = "";
-
- try {
- var parsererrors = parser
- .parseFromString("INVALID", "text/xml")
- .getElementsByTagName("parsererror");
- if (parsererrors.length) {
- parsererrorNS = parsererrors[0].namespaceURI;
- }
- } catch (e) {
- // passing invalid XML makes IE11 throw
- // so no namespace needs to be determined
- }
-
- var result;
- try {
- result = parser.parseFromString(text, "text/xml");
- } catch (err) {
- return null;
- }
-
- return result.getElementsByTagNameNS(
- parsererrorNS,
- "parsererror"
- ).length
- ? null
- : result;
- }
- var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
- xmlDoc.async = "false";
- xmlDoc.loadXML(text);
- return xmlDoc.parseError.errorCode !== 0 ? null : xmlDoc;
- } catch (e) {
- // Unable to parse XML - no biggie
- }
- }
-
- return null;
- };
-
- FakeXMLHttpRequest.statusCodes = {
- 100: "Continue",
- 101: "Switching Protocols",
- 200: "OK",
- 201: "Created",
- 202: "Accepted",
- 203: "Non-Authoritative Information",
- 204: "No Content",
- 205: "Reset Content",
- 206: "Partial Content",
- 207: "Multi-Status",
- 300: "Multiple Choice",
- 301: "Moved Permanently",
- 302: "Found",
- 303: "See Other",
- 304: "Not Modified",
- 305: "Use Proxy",
- 307: "Temporary Redirect",
- 400: "Bad Request",
- 401: "Unauthorized",
- 402: "Payment Required",
- 403: "Forbidden",
- 404: "Not Found",
- 405: "Method Not Allowed",
- 406: "Not Acceptable",
- 407: "Proxy Authentication Required",
- 408: "Request Timeout",
- 409: "Conflict",
- 410: "Gone",
- 411: "Length Required",
- 412: "Precondition Failed",
- 413: "Request Entity Too Large",
- 414: "Request-URI Too Long",
- 415: "Unsupported Media Type",
- 416: "Requested Range Not Satisfiable",
- 417: "Expectation Failed",
- 422: "Unprocessable Entity",
- 500: "Internal Server Error",
- 501: "Not Implemented",
- 502: "Bad Gateway",
- 503: "Service Unavailable",
- 504: "Gateway Timeout",
- 505: "HTTP Version Not Supported"
- };
-
- extend(FakeXMLHttpRequest.prototype, sinonEvent.EventTarget, {
- async: true,
-
- open: function open(method, url, async, username, password) {
- this.method = method;
- this.url = url;
- this.async = typeof async === "boolean" ? async : true;
- this.username = username;
- this.password = password;
- clearResponse(this);
- this.requestHeaders = {};
- this.sendFlag = false;
-
- if (FakeXMLHttpRequest.useFilters === true) {
- var xhrArgs = arguments;
- var defake = FakeXMLHttpRequest.filters.some(function(filter) {
- return filter.apply(this, xhrArgs);
- });
- if (defake) {
- FakeXMLHttpRequest.defake(this, arguments);
- return;
- }
- }
- this.readyStateChange(FakeXMLHttpRequest.OPENED);
- },
-
- readyStateChange: function readyStateChange(state) {
- this.readyState = state;
-
- var readyStateChangeEvent = new sinonEvent.Event(
- "readystatechange",
- false,
- false,
- this
- );
- if (typeof this.onreadystatechange === "function") {
- try {
- this.onreadystatechange(readyStateChangeEvent);
- } catch (e) {
- this.logError("Fake XHR onreadystatechange handler", e);
- }
- }
-
- if (this.readyState !== FakeXMLHttpRequest.DONE) {
- this.dispatchEvent(readyStateChangeEvent);
- } else {
- var event, progress;
-
- if (this.timedOut || this.aborted || this.status === 0) {
- progress = { loaded: 0, total: 0 };
- event =
- (this.timedOut && "timeout") ||
- (this.aborted && "abort") ||
- "error";
- } else {
- progress = { loaded: 100, total: 100 };
- event = "load";
- }
-
- if (supportsProgress) {
- this.upload.dispatchEvent(
- new sinonEvent.ProgressEvent("progress", progress, this)
- );
- this.upload.dispatchEvent(
- new sinonEvent.ProgressEvent(event, progress, this)
- );
- this.upload.dispatchEvent(
- new sinonEvent.ProgressEvent("loadend", progress, this)
- );
- }
-
- this.dispatchEvent(
- new sinonEvent.ProgressEvent("progress", progress, this)
- );
- this.dispatchEvent(
- new sinonEvent.ProgressEvent(event, progress, this)
- );
- this.dispatchEvent(readyStateChangeEvent);
- this.dispatchEvent(
- new sinonEvent.ProgressEvent("loadend", progress, this)
- );
- }
- },
-
- // Ref https://xhr.spec.whatwg.org/#the-setrequestheader()-method
- setRequestHeader: function setRequestHeader(header, value) {
- if (typeof value !== "string") {
- throw new TypeError(
- `By RFC7230, section 3.2.4, header values should be strings. Got ${typeof value}`
- );
- }
- verifyState(this);
-
- var checkUnsafeHeaders = true;
- if (typeof this.unsafeHeadersEnabled === "function") {
- checkUnsafeHeaders = this.unsafeHeadersEnabled();
- }
-
- if (
- checkUnsafeHeaders &&
- (getHeader(unsafeHeaders, header) !== null ||
- /^(Sec-|Proxy-)/i.test(header))
- ) {
- throw new Error(
- // eslint-disable-next-line quotes
- `Refused to set unsafe header "${header}"`
- );
- }
-
- // eslint-disable-next-line no-param-reassign
- value = normalizeHeaderValue(value);
-
- var existingHeader = getHeader(this.requestHeaders, header);
- if (existingHeader) {
- this.requestHeaders[existingHeader] += `, ${value}`;
- } else {
- this.requestHeaders[header] = value;
- }
- },
-
- setStatus: function setStatus(status) {
- var sanitizedStatus = typeof status === "number" ? status : 200;
-
- verifyRequestOpened(this);
- this.status = sanitizedStatus;
- this.statusText = FakeXMLHttpRequest.statusCodes[sanitizedStatus];
- },
-
- // Helps testing
- setResponseHeaders: function setResponseHeaders(headers) {
- verifyRequestOpened(this);
-
- var responseHeaders = (this.responseHeaders = {});
-
- Object.keys(headers).forEach(function(header) {
- responseHeaders[header] = headers[header];
- });
-
- if (this.async) {
- this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
- } else {
- this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
- }
- },
-
- // Currently treats ALL data as a DOMString (i.e. no Document)
- send: function send(data) {
- verifyState(this);
-
- if (!/^(head)$/i.test(this.method)) {
- var contentType = getHeader(
- this.requestHeaders,
- "Content-Type"
- );
- if (this.requestHeaders[contentType]) {
- var value = this.requestHeaders[contentType].split(";");
- this.requestHeaders[
- contentType
- ] = `${value[0]};charset=utf-8`;
- } else if (supportsFormData && !(data instanceof FormData)) {
- this.requestHeaders["Content-Type"] =
- "text/plain;charset=utf-8";
- }
-
- this.requestBody = data;
- }
-
- this.errorFlag = false;
- this.sendFlag = this.async;
- clearResponse(this);
-
- if (typeof this.onSend === "function") {
- this.onSend(this);
- }
-
- // Only listen if setInterval and Date are a stubbed.
- if (
- sinonXhr.supportsTimeout &&
- typeof setInterval.clock === "object" &&
- typeof Date.clock === "object"
- ) {
- var initiatedTime = Date.now();
- var self = this;
-
- // Listen to any possible tick by fake timers and check to see if timeout has
- // been exceeded. It's important to note that timeout can be changed while a request
- // is in flight, so we must check anytime the end user forces a clock tick to make
- // sure timeout hasn't changed.
- // https://xhr.spec.whatwg.org/#dfnReturnLink-2
- var clearIntervalId = setInterval(function() {
- // Check if the readyState has been reset or is done. If this is the case, there
- // should be no timeout. This will also prevent aborted requests and
- // fakeServerWithClock from triggering unnecessary responses.
- if (
- self.readyState === FakeXMLHttpRequest.UNSENT ||
- self.readyState === FakeXMLHttpRequest.DONE
- ) {
- clearInterval(clearIntervalId);
- } else if (
- typeof self.timeout === "number" &&
- self.timeout > 0
- ) {
- if (Date.now() >= initiatedTime + self.timeout) {
- self.triggerTimeout();
- clearInterval(clearIntervalId);
- }
- }
- }, 1);
- }
-
- this.dispatchEvent(
- new sinonEvent.Event("loadstart", false, false, this)
- );
- },
-
- abort: function abort() {
- this.aborted = true;
- requestErrorSteps(this);
- this.readyState = FakeXMLHttpRequest.UNSENT;
- },
-
- error: function() {
- clearResponse(this);
- this.errorFlag = true;
- this.requestHeaders = {};
- this.responseHeaders = {};
-
- this.readyStateChange(FakeXMLHttpRequest.DONE);
- },
-
- triggerTimeout: function triggerTimeout() {
- if (sinonXhr.supportsTimeout) {
- this.timedOut = true;
- requestErrorSteps(this);
- }
- },
-
- getResponseHeader: function getResponseHeader(header) {
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
- return null;
- }
-
- if (/^Set-Cookie2?$/i.test(header)) {
- return null;
- }
-
- // eslint-disable-next-line no-param-reassign
- header = getHeader(this.responseHeaders, header);
-
- return this.responseHeaders[header] || null;
- },
-
- getAllResponseHeaders: function getAllResponseHeaders() {
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
- return "";
- }
-
- var responseHeaders = this.responseHeaders;
- var headers = Object.keys(responseHeaders)
- .filter(excludeSetCookie2Header)
- .reduce(function(prev, header) {
- var value = responseHeaders[header];
-
- return `${prev}${header}: ${value}\r\n`;
- }, "");
-
- return headers;
- },
-
- setResponseBody: function setResponseBody(body) {
- verifyRequestSent(this);
- verifyHeadersReceived(this);
- verifyResponseBodyType(body, this.responseType);
- var contentType =
- this.overriddenMimeType ||
- this.getResponseHeader("Content-Type");
-
- var isTextResponse =
- this.responseType === "" || this.responseType === "text";
- clearResponse(this);
- if (this.async) {
- var chunkSize = this.chunkSize || 10;
- var index = 0;
-
- do {
- this.readyStateChange(FakeXMLHttpRequest.LOADING);
-
- if (isTextResponse) {
- this.responseText = this.response += body.substring(
- index,
- index + chunkSize
- );
- }
- index += chunkSize;
- } while (index < body.length);
- }
-
- this.response = convertResponseBody(
- this.responseType,
- contentType,
- body
- );
- if (isTextResponse) {
- this.responseText = this.response;
- }
-
- if (this.responseType === "document") {
- this.responseXML = this.response;
- } else if (
- this.responseType === "" &&
- isXmlContentType(contentType)
- ) {
- this.responseXML = FakeXMLHttpRequest.parseXML(
- this.responseText
- );
- }
- this.readyStateChange(FakeXMLHttpRequest.DONE);
- },
-
- respond: function respond(status, headers, body) {
- this.responseURL = this.url;
-
- this.setStatus(status);
- this.setResponseHeaders(headers || {});
- this.setResponseBody(body || "");
- },
-
- uploadProgress: function uploadProgress(progressEventRaw) {
- if (supportsProgress) {
- this.upload.dispatchEvent(
- new sinonEvent.ProgressEvent(
- "progress",
- progressEventRaw,
- this.upload
- )
- );
- }
- },
-
- downloadProgress: function downloadProgress(progressEventRaw) {
- if (supportsProgress) {
- this.dispatchEvent(
- new sinonEvent.ProgressEvent(
- "progress",
- progressEventRaw,
- this
- )
- );
- }
- },
-
- uploadError: function uploadError(error) {
- if (supportsCustomEvent) {
- this.upload.dispatchEvent(
- new sinonEvent.CustomEvent("error", { detail: error })
- );
- }
- },
-
- overrideMimeType: function overrideMimeType(type) {
- if (this.readyState >= FakeXMLHttpRequest.LOADING) {
- throw new Error("INVALID_STATE_ERR");
- }
- this.overriddenMimeType = type;
- }
- });
-
- var states = {
- UNSENT: 0,
- OPENED: 1,
- HEADERS_RECEIVED: 2,
- LOADING: 3,
- DONE: 4
- };
-
- extend(FakeXMLHttpRequest, states);
- extend(FakeXMLHttpRequest.prototype, states);
-
- function useFakeXMLHttpRequest() {
- FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
- if (sinonXhr.supportsXHR) {
- globalScope.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
- }
-
- if (sinonXhr.supportsActiveX) {
- globalScope.ActiveXObject = sinonXhr.GlobalActiveXObject;
- }
-
- delete FakeXMLHttpRequest.restore;
-
- if (keepOnCreate !== true) {
- delete FakeXMLHttpRequest.onCreate;
- }
- };
- if (sinonXhr.supportsXHR) {
- globalScope.XMLHttpRequest = FakeXMLHttpRequest;
- }
-
- if (sinonXhr.supportsActiveX) {
- globalScope.ActiveXObject = function ActiveXObject(objId) {
- if (
- objId === "Microsoft.XMLHTTP" ||
- /^Msxml2\.XMLHTTP/i.test(objId)
- ) {
- return new FakeXMLHttpRequest();
- }
-
- return new sinonXhr.GlobalActiveXObject(objId);
- };
- }
-
- return FakeXMLHttpRequest;
- }
-
- return {
- xhr: sinonXhr,
- FakeXMLHttpRequest: FakeXMLHttpRequest,
- useFakeXMLHttpRequest: useFakeXMLHttpRequest
- };
- }
-
- module.exports = extend(fakeXMLHttpRequestFor(globalObject), {
- fakeXMLHttpRequestFor: fakeXMLHttpRequestFor
- });
|