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