culture commited on
Commit
a3b2395
·
1 Parent(s): 046501f

Upload fetch.js

Browse files
Files changed (1) hide show
  1. tests/fetch.js +467 -0
tests/fetch.js ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(self) {
2
+ 'use strict';
3
+
4
+ if (self.fetch) {
5
+ return
6
+ }
7
+
8
+ var support = {
9
+ searchParams: 'URLSearchParams' in self,
10
+ iterable: 'Symbol' in self && 'iterator' in Symbol,
11
+ blob: 'FileReader' in self && 'Blob' in self && (function() {
12
+ try {
13
+ new Blob()
14
+ return true
15
+ } catch(e) {
16
+ return false
17
+ }
18
+ })(),
19
+ formData: 'FormData' in self,
20
+ arrayBuffer: 'ArrayBuffer' in self
21
+ }
22
+
23
+ if (support.arrayBuffer) {
24
+ var viewClasses = [
25
+ '[object Int8Array]',
26
+ '[object Uint8Array]',
27
+ '[object Uint8ClampedArray]',
28
+ '[object Int16Array]',
29
+ '[object Uint16Array]',
30
+ '[object Int32Array]',
31
+ '[object Uint32Array]',
32
+ '[object Float32Array]',
33
+ '[object Float64Array]'
34
+ ]
35
+
36
+ var isDataView = function(obj) {
37
+ return obj && DataView.prototype.isPrototypeOf(obj)
38
+ }
39
+
40
+ var isArrayBufferView = ArrayBuffer.isView || function(obj) {
41
+ return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
42
+ }
43
+ }
44
+
45
+ function normalizeName(name) {
46
+ if (typeof name !== 'string') {
47
+ name = String(name)
48
+ }
49
+ if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
50
+ throw new TypeError('Invalid character in header field name')
51
+ }
52
+ return name.toLowerCase()
53
+ }
54
+
55
+ function normalizeValue(value) {
56
+ if (typeof value !== 'string') {
57
+ value = String(value)
58
+ }
59
+ return value
60
+ }
61
+
62
+ // Build a destructive iterator for the value list
63
+ function iteratorFor(items) {
64
+ var iterator = {
65
+ next: function() {
66
+ var value = items.shift()
67
+ return {done: value === undefined, value: value}
68
+ }
69
+ }
70
+
71
+ if (support.iterable) {
72
+ iterator[Symbol.iterator] = function() {
73
+ return iterator
74
+ }
75
+ }
76
+
77
+ return iterator
78
+ }
79
+
80
+ function Headers(headers) {
81
+ this.map = {}
82
+
83
+ if (headers instanceof Headers) {
84
+ headers.forEach(function(value, name) {
85
+ this.append(name, value)
86
+ }, this)
87
+ } else if (Array.isArray(headers)) {
88
+ headers.forEach(function(header) {
89
+ this.append(header[0], header[1])
90
+ }, this)
91
+ } else if (headers) {
92
+ Object.getOwnPropertyNames(headers).forEach(function(name) {
93
+ this.append(name, headers[name])
94
+ }, this)
95
+ }
96
+ }
97
+
98
+ Headers.prototype.append = function(name, value) {
99
+ name = normalizeName(name)
100
+ value = normalizeValue(value)
101
+ var oldValue = this.map[name]
102
+ this.map[name] = oldValue ? oldValue+','+value : value
103
+ }
104
+
105
+ Headers.prototype['delete'] = function(name) {
106
+ delete this.map[normalizeName(name)]
107
+ }
108
+
109
+ Headers.prototype.get = function(name) {
110
+ name = normalizeName(name)
111
+ return this.has(name) ? this.map[name] : null
112
+ }
113
+
114
+ Headers.prototype.has = function(name) {
115
+ return this.map.hasOwnProperty(normalizeName(name))
116
+ }
117
+
118
+ Headers.prototype.set = function(name, value) {
119
+ this.map[normalizeName(name)] = normalizeValue(value)
120
+ }
121
+
122
+ Headers.prototype.forEach = function(callback, thisArg) {
123
+ for (var name in this.map) {
124
+ if (this.map.hasOwnProperty(name)) {
125
+ callback.call(thisArg, this.map[name], name, this)
126
+ }
127
+ }
128
+ }
129
+
130
+ Headers.prototype.keys = function() {
131
+ var items = []
132
+ this.forEach(function(value, name) { items.push(name) })
133
+ return iteratorFor(items)
134
+ }
135
+
136
+ Headers.prototype.values = function() {
137
+ var items = []
138
+ this.forEach(function(value) { items.push(value) })
139
+ return iteratorFor(items)
140
+ }
141
+
142
+ Headers.prototype.entries = function() {
143
+ var items = []
144
+ this.forEach(function(value, name) { items.push([name, value]) })
145
+ return iteratorFor(items)
146
+ }
147
+
148
+ if (support.iterable) {
149
+ Headers.prototype[Symbol.iterator] = Headers.prototype.entries
150
+ }
151
+
152
+ function consumed(body) {
153
+ if (body.bodyUsed) {
154
+ return Promise.reject(new TypeError('Already read'))
155
+ }
156
+ body.bodyUsed = true
157
+ }
158
+
159
+ function fileReaderReady(reader) {
160
+ return new Promise(function(resolve, reject) {
161
+ reader.onload = function() {
162
+ resolve(reader.result)
163
+ }
164
+ reader.onerror = function() {
165
+ reject(reader.error)
166
+ }
167
+ })
168
+ }
169
+
170
+ function readBlobAsArrayBuffer(blob) {
171
+ var reader = new FileReader()
172
+ var promise = fileReaderReady(reader)
173
+ reader.readAsArrayBuffer(blob)
174
+ return promise
175
+ }
176
+
177
+ function readBlobAsText(blob) {
178
+ var reader = new FileReader()
179
+ var promise = fileReaderReady(reader)
180
+ reader.readAsText(blob)
181
+ return promise
182
+ }
183
+
184
+ function readArrayBufferAsText(buf) {
185
+ var view = new Uint8Array(buf)
186
+ var chars = new Array(view.length)
187
+
188
+ for (var i = 0; i < view.length; i++) {
189
+ chars[i] = String.fromCharCode(view[i])
190
+ }
191
+ return chars.join('')
192
+ }
193
+
194
+ function bufferClone(buf) {
195
+ if (buf.slice) {
196
+ return buf.slice(0)
197
+ } else {
198
+ var view = new Uint8Array(buf.byteLength)
199
+ view.set(new Uint8Array(buf))
200
+ return view.buffer
201
+ }
202
+ }
203
+
204
+ function Body() {
205
+ this.bodyUsed = false
206
+
207
+ this._initBody = function(body) {
208
+ this._bodyInit = body
209
+ if (!body) {
210
+ this._bodyText = ''
211
+ } else if (typeof body === 'string') {
212
+ this._bodyText = body
213
+ } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
214
+ this._bodyBlob = body
215
+ } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
216
+ this._bodyFormData = body
217
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
218
+ this._bodyText = body.toString()
219
+ } else if (support.arrayBuffer && support.blob && isDataView(body)) {
220
+ this._bodyArrayBuffer = bufferClone(body.buffer)
221
+ // IE 10-11 can't handle a DataView body.
222
+ this._bodyInit = new Blob([this._bodyArrayBuffer])
223
+ } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
224
+ this._bodyArrayBuffer = bufferClone(body)
225
+ } else {
226
+ throw new Error('unsupported BodyInit type')
227
+ }
228
+
229
+ if (!this.headers.get('content-type')) {
230
+ if (typeof body === 'string') {
231
+ this.headers.set('content-type', 'text/plain;charset=UTF-8')
232
+ } else if (this._bodyBlob && this._bodyBlob.type) {
233
+ this.headers.set('content-type', this._bodyBlob.type)
234
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
235
+ this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
236
+ }
237
+ }
238
+ }
239
+
240
+ if (support.blob) {
241
+ this.blob = function() {
242
+ var rejected = consumed(this)
243
+ if (rejected) {
244
+ return rejected
245
+ }
246
+
247
+ if (this._bodyBlob) {
248
+ return Promise.resolve(this._bodyBlob)
249
+ } else if (this._bodyArrayBuffer) {
250
+ return Promise.resolve(new Blob([this._bodyArrayBuffer]))
251
+ } else if (this._bodyFormData) {
252
+ throw new Error('could not read FormData body as blob')
253
+ } else {
254
+ return Promise.resolve(new Blob([this._bodyText]))
255
+ }
256
+ }
257
+
258
+ this.arrayBuffer = function() {
259
+ if (this._bodyArrayBuffer) {
260
+ return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
261
+ } else {
262
+ return this.blob().then(readBlobAsArrayBuffer)
263
+ }
264
+ }
265
+ }
266
+
267
+ this.text = function() {
268
+ var rejected = consumed(this)
269
+ if (rejected) {
270
+ return rejected
271
+ }
272
+
273
+ if (this._bodyBlob) {
274
+ return readBlobAsText(this._bodyBlob)
275
+ } else if (this._bodyArrayBuffer) {
276
+ return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
277
+ } else if (this._bodyFormData) {
278
+ throw new Error('could not read FormData body as text')
279
+ } else {
280
+ return Promise.resolve(this._bodyText)
281
+ }
282
+ }
283
+
284
+ if (support.formData) {
285
+ this.formData = function() {
286
+ return this.text().then(decode)
287
+ }
288
+ }
289
+
290
+ this.json = function() {
291
+ return this.text().then(JSON.parse)
292
+ }
293
+
294
+ return this
295
+ }
296
+
297
+ // HTTP methods whose capitalization should be normalized
298
+ var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
299
+
300
+ function normalizeMethod(method) {
301
+ var upcased = method.toUpperCase()
302
+ return (methods.indexOf(upcased) > -1) ? upcased : method
303
+ }
304
+
305
+ function Request(input, options) {
306
+ options = options || {}
307
+ var body = options.body
308
+
309
+ if (input instanceof Request) {
310
+ if (input.bodyUsed) {
311
+ throw new TypeError('Already read')
312
+ }
313
+ this.url = input.url
314
+ this.credentials = input.credentials
315
+ if (!options.headers) {
316
+ this.headers = new Headers(input.headers)
317
+ }
318
+ this.method = input.method
319
+ this.mode = input.mode
320
+ if (!body && input._bodyInit != null) {
321
+ body = input._bodyInit
322
+ input.bodyUsed = true
323
+ }
324
+ } else {
325
+ this.url = String(input)
326
+ }
327
+
328
+ this.credentials = options.credentials || this.credentials || 'omit'
329
+ if (options.headers || !this.headers) {
330
+ this.headers = new Headers(options.headers)
331
+ }
332
+ this.method = normalizeMethod(options.method || this.method || 'GET')
333
+ this.mode = options.mode || this.mode || null
334
+ this.referrer = null
335
+
336
+ if ((this.method === 'GET' || this.method === 'HEAD') && body) {
337
+ throw new TypeError('Body not allowed for GET or HEAD requests')
338
+ }
339
+ this._initBody(body)
340
+ }
341
+
342
+ Request.prototype.clone = function() {
343
+ return new Request(this, { body: this._bodyInit })
344
+ }
345
+
346
+ function decode(body) {
347
+ var form = new FormData()
348
+ body.trim().split('&').forEach(function(bytes) {
349
+ if (bytes) {
350
+ var split = bytes.split('=')
351
+ var name = split.shift().replace(/\+/g, ' ')
352
+ var value = split.join('=').replace(/\+/g, ' ')
353
+ form.append(decodeURIComponent(name), decodeURIComponent(value))
354
+ }
355
+ })
356
+ return form
357
+ }
358
+
359
+ function parseHeaders(rawHeaders) {
360
+ var headers = new Headers()
361
+ // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
362
+ // https://tools.ietf.org/html/rfc7230#section-3.2
363
+ var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
364
+ preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
365
+ var parts = line.split(':')
366
+ var key = parts.shift().trim()
367
+ if (key) {
368
+ var value = parts.join(':').trim()
369
+ headers.append(key, value)
370
+ }
371
+ })
372
+ return headers
373
+ }
374
+
375
+ Body.call(Request.prototype)
376
+
377
+ function Response(bodyInit, options) {
378
+ if (!options) {
379
+ options = {}
380
+ }
381
+
382
+ this.type = 'default'
383
+ this.status = options.status === undefined ? 200 : options.status
384
+ this.ok = this.status >= 200 && this.status < 300
385
+ this.statusText = 'statusText' in options ? options.statusText : 'OK'
386
+ this.headers = new Headers(options.headers)
387
+ this.url = options.url || ''
388
+ this._initBody(bodyInit)
389
+ }
390
+
391
+ Body.call(Response.prototype)
392
+
393
+ Response.prototype.clone = function() {
394
+ return new Response(this._bodyInit, {
395
+ status: this.status,
396
+ statusText: this.statusText,
397
+ headers: new Headers(this.headers),
398
+ url: this.url
399
+ })
400
+ }
401
+
402
+ Response.error = function() {
403
+ var response = new Response(null, {status: 0, statusText: ''})
404
+ response.type = 'error'
405
+ return response
406
+ }
407
+
408
+ var redirectStatuses = [301, 302, 303, 307, 308]
409
+
410
+ Response.redirect = function(url, status) {
411
+ if (redirectStatuses.indexOf(status) === -1) {
412
+ throw new RangeError('Invalid status code')
413
+ }
414
+
415
+ return new Response(null, {status: status, headers: {location: url}})
416
+ }
417
+
418
+ self.Headers = Headers
419
+ self.Request = Request
420
+ self.Response = Response
421
+
422
+ self.fetch = function(input, init) {
423
+ return new Promise(function(resolve, reject) {
424
+ var request = new Request(input, init)
425
+ var xhr = new XMLHttpRequest()
426
+
427
+ xhr.onload = function() {
428
+ var options = {
429
+ status: xhr.status,
430
+ statusText: xhr.statusText,
431
+ headers: parseHeaders(xhr.getAllResponseHeaders() || '')
432
+ }
433
+ options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
434
+ var body = 'response' in xhr ? xhr.response : xhr.responseText
435
+ resolve(new Response(body, options))
436
+ }
437
+
438
+ xhr.onerror = function() {
439
+ reject(new TypeError('Network request failed'))
440
+ }
441
+
442
+ xhr.ontimeout = function() {
443
+ reject(new TypeError('Network request failed'))
444
+ }
445
+
446
+ xhr.open(request.method, request.url, true)
447
+
448
+ if (request.credentials === 'include') {
449
+ xhr.withCredentials = true
450
+ } else if (request.credentials === 'omit') {
451
+ xhr.withCredentials = false
452
+ }
453
+
454
+ if ('responseType' in xhr && support.blob) {
455
+ xhr.responseType = 'blob'
456
+ }
457
+
458
+ request.headers.forEach(function(value, name) {
459
+ xhr.setRequestHeader(name, value)
460
+ })
461
+
462
+ xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
463
+ })
464
+ }
465
+ self.fetch.polyfill = true
466
+ })(typeof self !== 'undefined' ? self : this);
467
+