1
+ ( function ( ) {
2
+ 'use strict' ;
3
+
4
+ var self = exports ;
5
+
6
+ if ( self . fetch ) {
7
+ return
8
+ }
9
+
10
+ function normalizeName ( name ) {
11
+ if ( typeof name !== 'string' ) {
12
+ name = name . toString ( ) ;
13
+ }
14
+ if ( / [ ^ a - z 0 - 9 \- # $ % & ' * + . \^ _ ` | ~ ] / i. test ( name ) ) {
15
+ throw new TypeError ( 'Invalid character in header field name' )
16
+ }
17
+ return name . toLowerCase ( )
18
+ }
19
+
20
+ function normalizeValue ( value ) {
21
+ if ( typeof value !== 'string' ) {
22
+ value = value . toString ( ) ;
23
+ }
24
+ return value
25
+ }
26
+
27
+ function Headers ( headers ) {
28
+ this . map = { }
29
+
30
+ if ( headers instanceof Headers ) {
31
+ headers . forEach ( function ( value , name ) {
32
+ this . append ( name , value )
33
+ } , this )
34
+
35
+ } else if ( headers ) {
36
+ Object . getOwnPropertyNames ( headers ) . forEach ( function ( name ) {
37
+ this . append ( name , headers [ name ] )
38
+ } , this )
39
+ }
40
+ }
41
+
42
+ Headers . prototype . append = function ( name , value ) {
43
+ name = normalizeName ( name )
44
+ value = normalizeValue ( value )
45
+ var list = this . map [ name ]
46
+ if ( ! list ) {
47
+ list = [ ]
48
+ this . map [ name ] = list
49
+ }
50
+ list . push ( value )
51
+ }
52
+
53
+ Headers . prototype [ 'delete' ] = function ( name ) {
54
+ delete this . map [ normalizeName ( name ) ]
55
+ }
56
+
57
+ Headers . prototype . get = function ( name ) {
58
+ var values = this . map [ normalizeName ( name ) ]
59
+ return values ? values [ 0 ] : null
60
+ }
61
+
62
+ Headers . prototype . getAll = function ( name ) {
63
+ return this . map [ normalizeName ( name ) ] || [ ]
64
+ }
65
+
66
+ Headers . prototype . has = function ( name ) {
67
+ return this . map . hasOwnProperty ( normalizeName ( name ) )
68
+ }
69
+
70
+ Headers . prototype . set = function ( name , value ) {
71
+ this . map [ normalizeName ( name ) ] = [ normalizeValue ( value ) ]
72
+ }
73
+
74
+ Headers . prototype . forEach = function ( callback , thisArg ) {
75
+ Object . getOwnPropertyNames ( this . map ) . forEach ( function ( name ) {
76
+ this . map [ name ] . forEach ( function ( value ) {
77
+ callback . call ( thisArg , value , name , this )
78
+ } , this )
79
+ } , this )
80
+ }
81
+
82
+ function consumed ( body ) {
83
+ if ( body . bodyUsed ) {
84
+ return Promise . reject ( new TypeError ( 'Already read' ) )
85
+ }
86
+ body . bodyUsed = true
87
+ }
88
+
89
+ function fileReaderReady ( reader ) {
90
+ return new Promise ( function ( resolve , reject ) {
91
+ reader . onload = function ( ) {
92
+ resolve ( reader . result )
93
+ }
94
+ reader . onerror = function ( ) {
95
+ reject ( reader . error )
96
+ }
97
+ } )
98
+ }
99
+
100
+ function readBlobAsArrayBuffer ( blob ) {
101
+ var reader = new FileReader ( )
102
+ reader . readAsArrayBuffer ( blob )
103
+ return fileReaderReady ( reader )
104
+ }
105
+
106
+ function readBlobAsText ( blob ) {
107
+ var reader = new FileReader ( )
108
+ reader . readAsText ( blob )
109
+ return fileReaderReady ( reader )
110
+ }
111
+
112
+ var support = {
113
+ blob : 'FileReader' in self && 'Blob' in self && ( function ( ) {
114
+ try {
115
+ new Blob ( ) ;
116
+ return true
117
+ } catch ( e ) {
118
+ return false
119
+ }
120
+ } ) ( ) ,
121
+ formData : 'FormData' in self
122
+ }
123
+
124
+ function Body ( ) {
125
+ this . bodyUsed = false
126
+
127
+
128
+ this . _initBody = function ( body ) {
129
+ this . _bodyInit = body
130
+ if ( typeof body === 'string' ) {
131
+ this . _bodyText = body
132
+ } else if ( support . blob && Blob . prototype . isPrototypeOf ( body ) ) {
133
+ this . _bodyBlob = body
134
+ } else if ( support . formData && FormData . prototype . isPrototypeOf ( body ) ) {
135
+ this . _bodyFormData = body
136
+ } else if ( ! body ) {
137
+ this . _bodyText = ''
138
+ } else {
139
+ throw new Error ( 'unsupported BodyInit type' )
140
+ }
141
+ }
142
+
143
+ if ( support . blob ) {
144
+ this . blob = function ( ) {
145
+ var rejected = consumed ( this )
146
+ if ( rejected ) {
147
+ return rejected
148
+ }
149
+
150
+ if ( this . _bodyBlob ) {
151
+ return Promise . resolve ( this . _bodyBlob )
152
+ } else if ( this . _bodyFormData ) {
153
+ throw new Error ( 'could not read FormData body as blob' )
154
+ } else {
155
+ return Promise . resolve ( new Blob ( [ this . _bodyText ] ) )
156
+ }
157
+ }
158
+
159
+ this . arrayBuffer = function ( ) {
160
+ return this . blob ( ) . then ( readBlobAsArrayBuffer )
161
+ }
162
+
163
+ this . text = function ( ) {
164
+ var rejected = consumed ( this )
165
+ if ( rejected ) {
166
+ return rejected
167
+ }
168
+
169
+ if ( this . _bodyBlob ) {
170
+ return readBlobAsText ( this . _bodyBlob )
171
+ } else if ( this . _bodyFormData ) {
172
+ throw new Error ( 'could not read FormData body as text' )
173
+ } else {
174
+ return Promise . resolve ( this . _bodyText )
175
+ }
176
+ }
177
+ } else {
178
+ this . text = function ( ) {
179
+ var rejected = consumed ( this )
180
+ return rejected ? rejected : Promise . resolve ( this . _bodyText )
181
+ }
182
+ }
183
+
184
+ if ( support . formData ) {
185
+ this . formData = function ( ) {
186
+ return this . text ( ) . then ( decode )
187
+ }
188
+ }
189
+
190
+ this . json = function ( ) {
191
+ return this . text ( ) . then ( JSON . parse )
192
+ }
193
+
194
+ return this
195
+ }
196
+
197
+ // HTTP methods whose capitalization should be normalized
198
+ var methods = [ 'DELETE' , 'GET' , 'HEAD' , 'OPTIONS' , 'POST' , 'PUT' ]
199
+
200
+ function normalizeMethod ( method ) {
201
+ var upcased = method . toUpperCase ( )
202
+ return ( methods . indexOf ( upcased ) > - 1 ) ? upcased : method
203
+ }
204
+
205
+ function Request ( url , options ) {
206
+ options = options || { }
207
+ this . url = url
208
+
209
+ this . credentials = options . credentials || 'omit'
210
+ this . headers = new Headers ( options . headers )
211
+ this . method = normalizeMethod ( options . method || 'GET' )
212
+ this . mode = options . mode || null
213
+ this . referrer = null
214
+
215
+ if ( ( this . method === 'GET' || this . method === 'HEAD' ) && options . body ) {
216
+ throw new TypeError ( 'Body not allowed for GET or HEAD requests' )
217
+ }
218
+ this . _initBody ( options . body )
219
+ }
220
+
221
+ function decode ( body ) {
222
+ var form = new FormData ( )
223
+ body . trim ( ) . split ( '&' ) . forEach ( function ( bytes ) {
224
+ if ( bytes ) {
225
+ var split = bytes . split ( '=' )
226
+ var name = split . shift ( ) . replace ( / \+ / g, ' ' )
227
+ var value = split . join ( '=' ) . replace ( / \+ / g, ' ' )
228
+ form . append ( decodeURIComponent ( name ) , decodeURIComponent ( value ) )
229
+ }
230
+ } )
231
+ return form
232
+ }
233
+
234
+ function headers ( xhr ) {
235
+ var head = new Headers ( )
236
+ var pairs = xhr . getAllResponseHeaders ( ) . trim ( ) . split ( '\n' )
237
+ pairs . forEach ( function ( header ) {
238
+ var split = header . trim ( ) . split ( ':' )
239
+ var key = split . shift ( ) . trim ( )
240
+ var value = split . join ( ':' ) . trim ( )
241
+ head . append ( key , value )
242
+ } )
243
+ return head
244
+ }
245
+
246
+ Body . call ( Request . prototype )
247
+
248
+ function Response ( bodyInit , options ) {
249
+ if ( ! options ) {
250
+ options = { }
251
+ }
252
+
253
+ this . _initBody ( bodyInit )
254
+ this . type = 'default'
255
+ this . url = null
256
+ this . status = options . status
257
+ this . ok = this . status >= 200 && this . status < 300
258
+ this . statusText = options . statusText
259
+ this . headers = options . headers instanceof Headers ? options . headers : new Headers ( options . headers )
260
+ this . url = options . url || ''
261
+ }
262
+
263
+ Body . call ( Response . prototype )
264
+
265
+ self . Headers = Headers ;
266
+ self . Request = Request ;
267
+ self . Response = Response ;
268
+
269
+ self . fetch = function ( input , init ) {
270
+ // TODO: Request constructor should accept input, init
271
+ var request
272
+ if ( Request . prototype . isPrototypeOf ( input ) && ! init ) {
273
+ request = input
274
+ } else {
275
+ request = new Request ( input , init )
276
+ }
277
+
278
+ return new Promise ( function ( resolve , reject ) {
279
+ var xhr = new XMLHttpRequest ( )
280
+
281
+ function responseURL ( ) {
282
+ if ( 'responseURL' in xhr ) {
283
+ return xhr . responseURL
284
+ }
285
+
286
+ // Avoid security warnings on getResponseHeader when not allowed by CORS
287
+ if ( / ^ X - R e q u e s t - U R L : / m. test ( xhr . getAllResponseHeaders ( ) ) ) {
288
+ return xhr . getResponseHeader ( 'X-Request-URL' )
289
+ }
290
+
291
+ return ;
292
+ }
293
+
294
+ xhr . onload = function ( ) {
295
+ var status = ( xhr . status === 1223 ) ? 204 : xhr . status
296
+ if ( status < 100 || status > 599 ) {
297
+ reject ( new TypeError ( 'Network request failed' ) )
298
+ return
299
+ }
300
+ var options = {
301
+ status : status ,
302
+ statusText : xhr . statusText ,
303
+ headers : headers ( xhr ) ,
304
+ url : responseURL ( )
305
+ }
306
+ //var body = 'response' in xhr ? xhr.response : xhr.responseText;
307
+ resolve ( new Response ( xhr . responseText , options ) )
308
+ }
309
+
310
+ xhr . onerror = function ( ) {
311
+ reject ( new TypeError ( 'Network request failed' ) )
312
+ }
313
+
314
+ xhr . open ( request . method , request . url , true )
315
+
316
+ if ( request . credentials === 'include' ) {
317
+ xhr . withCredentials = true
318
+ }
319
+
320
+ if ( 'responseType' in xhr && support . blob ) {
321
+ xhr . responseType = 'blob'
322
+ }
323
+
324
+ request . headers . forEach ( function ( value , name ) {
325
+ xhr . setRequestHeader ( name , value )
326
+ } )
327
+
328
+ xhr . send ( typeof request . _bodyInit === 'undefined' ? null : request . _bodyInit )
329
+ } )
330
+ }
331
+ self . fetch . polyfill = true
332
+
333
+ } ) ( ) ;
0 commit comments