Pathologic was missing because of a .git folder inside.
[yaffs-website] / node_modules / xhr / index.js
1 "use strict";
2 var window = require("global/window")
3 var isFunction = require("is-function")
4 var parseHeaders = require("parse-headers")
5 var xtend = require("xtend")
6
7 module.exports = createXHR
8 createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
9 createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
10
11 forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
12     createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
13         options = initParams(uri, options, callback)
14         options.method = method.toUpperCase()
15         return _createXHR(options)
16     }
17 })
18
19 function forEachArray(array, iterator) {
20     for (var i = 0; i < array.length; i++) {
21         iterator(array[i])
22     }
23 }
24
25 function isEmpty(obj){
26     for(var i in obj){
27         if(obj.hasOwnProperty(i)) return false
28     }
29     return true
30 }
31
32 function initParams(uri, options, callback) {
33     var params = uri
34
35     if (isFunction(options)) {
36         callback = options
37         if (typeof uri === "string") {
38             params = {uri:uri}
39         }
40     } else {
41         params = xtend(options, {uri: uri})
42     }
43
44     params.callback = callback
45     return params
46 }
47
48 function createXHR(uri, options, callback) {
49     options = initParams(uri, options, callback)
50     return _createXHR(options)
51 }
52
53 function _createXHR(options) {
54     if(typeof options.callback === "undefined"){
55         throw new Error("callback argument missing")
56     }
57
58     var called = false
59     var callback = function cbOnce(err, response, body){
60         if(!called){
61             called = true
62             options.callback(err, response, body)
63         }
64     }
65
66     function readystatechange() {
67         if (xhr.readyState === 4) {
68             loadFunc()
69         }
70     }
71
72     function getBody() {
73         // Chrome with requestType=blob throws errors arround when even testing access to responseText
74         var body = undefined
75
76         if (xhr.response) {
77             body = xhr.response
78         } else {
79             body = xhr.responseText || getXml(xhr)
80         }
81
82         if (isJson) {
83             try {
84                 body = JSON.parse(body)
85             } catch (e) {}
86         }
87
88         return body
89     }
90
91     var failureResponse = {
92                 body: undefined,
93                 headers: {},
94                 statusCode: 0,
95                 method: method,
96                 url: uri,
97                 rawRequest: xhr
98             }
99
100     function errorFunc(evt) {
101         clearTimeout(timeoutTimer)
102         if(!(evt instanceof Error)){
103             evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
104         }
105         evt.statusCode = 0
106         return callback(evt, failureResponse)
107     }
108
109     // will load the data & process the response in a special response object
110     function loadFunc() {
111         if (aborted) return
112         var status
113         clearTimeout(timeoutTimer)
114         if(options.useXDR && xhr.status===undefined) {
115             //IE8 CORS GET successful response doesn't have a status field, but body is fine
116             status = 200
117         } else {
118             status = (xhr.status === 1223 ? 204 : xhr.status)
119         }
120         var response = failureResponse
121         var err = null
122
123         if (status !== 0){
124             response = {
125                 body: getBody(),
126                 statusCode: status,
127                 method: method,
128                 headers: {},
129                 url: uri,
130                 rawRequest: xhr
131             }
132             if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
133                 response.headers = parseHeaders(xhr.getAllResponseHeaders())
134             }
135         } else {
136             err = new Error("Internal XMLHttpRequest Error")
137         }
138         return callback(err, response, response.body)
139     }
140
141     var xhr = options.xhr || null
142
143     if (!xhr) {
144         if (options.cors || options.useXDR) {
145             xhr = new createXHR.XDomainRequest()
146         }else{
147             xhr = new createXHR.XMLHttpRequest()
148         }
149     }
150
151     var key
152     var aborted
153     var uri = xhr.url = options.uri || options.url
154     var method = xhr.method = options.method || "GET"
155     var body = options.body || options.data || null
156     var headers = xhr.headers = options.headers || {}
157     var sync = !!options.sync
158     var isJson = false
159     var timeoutTimer
160
161     if ("json" in options) {
162         isJson = true
163         headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
164         if (method !== "GET" && method !== "HEAD") {
165             headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
166             body = JSON.stringify(options.json)
167         }
168     }
169
170     xhr.onreadystatechange = readystatechange
171     xhr.onload = loadFunc
172     xhr.onerror = errorFunc
173     // IE9 must have onprogress be set to a unique function.
174     xhr.onprogress = function () {
175         // IE must die
176     }
177     xhr.ontimeout = errorFunc
178     xhr.open(method, uri, !sync, options.username, options.password)
179     //has to be after open
180     if(!sync) {
181         xhr.withCredentials = !!options.withCredentials
182     }
183     // Cannot set timeout with sync request
184     // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
185     // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
186     if (!sync && options.timeout > 0 ) {
187         timeoutTimer = setTimeout(function(){
188             aborted=true//IE9 may still call readystatechange
189             xhr.abort("timeout")
190             var e = new Error("XMLHttpRequest timeout")
191             e.code = "ETIMEDOUT"
192             errorFunc(e)
193         }, options.timeout )
194     }
195
196     if (xhr.setRequestHeader) {
197         for(key in headers){
198             if(headers.hasOwnProperty(key)){
199                 xhr.setRequestHeader(key, headers[key])
200             }
201         }
202     } else if (options.headers && !isEmpty(options.headers)) {
203         throw new Error("Headers cannot be set on an XDomainRequest object")
204     }
205
206     if ("responseType" in options) {
207         xhr.responseType = options.responseType
208     }
209
210     if ("beforeSend" in options &&
211         typeof options.beforeSend === "function"
212     ) {
213         options.beforeSend(xhr)
214     }
215
216     xhr.send(body)
217
218     return xhr
219
220
221 }
222
223 function getXml(xhr) {
224     if (xhr.responseType === "document") {
225         return xhr.responseXML
226     }
227     var firefoxBugTakenEffect = xhr.status === 204 && xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
228     if (xhr.responseType === "" && !firefoxBugTakenEffect) {
229         return xhr.responseXML
230     }
231
232     return null
233 }
234
235 function noop() {}