Browse Source

Fix Blob and XMLHttpRequest behavior #44

Ben Hsieh 8 years ago
parent
commit
9f20d2f816
2 changed files with 42 additions and 15 deletions
  1. 4
    1
      src/polyfill/Blob.js
  2. 38
    14
      src/polyfill/XMLHttpRequest.js

+ 4
- 1
src/polyfill/Blob.js View File

@@ -130,7 +130,10 @@ export default class Blob {
130 130
    */
131 131
   onCreated(fn:() => void) {
132 132
     log.verbose('register blob onCreated', this._onCreated.length)
133
-    this._onCreated.push(fn)
133
+    if(!this._blobCreated)
134
+      this._onCreated.push(fn)
135
+    else
136
+      fn(this)
134 137
   }
135 138
 
136 139
   /**

+ 38
- 14
src/polyfill/XMLHttpRequest.js View File

@@ -24,13 +24,13 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
24 24
   _readyState : number = UNSENT;
25 25
   _response : any = '';
26 26
   _responseText : any = '';
27
-  _responseHeaders : any = '';
27
+  _responseHeaders : any = {};
28 28
   _responseType : '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' = '';
29 29
   // TODO : not suppoted for now
30 30
   _responseURL : null = '';
31 31
   _responseXML : null = '';
32
-  _status : number;
33
-  _statusText : string;
32
+  _status : number = 0;
33
+  _statusText : string = '';
34 34
   _timeout : number = 0;
35 35
   _upload : XMLHttpRequestEventTarget;
36 36
   _sendFlag : boolean = false;
@@ -74,11 +74,21 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
74 74
     this._headers = {}
75 75
   }
76 76
 
77
-  // XMLHttpRequest.open, always async, user and password not supported.
77
+
78
+  /**
79
+   * XMLHttpRequest.open, always async, user and password not supported. When
80
+   * this method invoked, headers should becomes empty again.
81
+   * @param  {string} method Request method
82
+   * @param  {string} url Request URL
83
+   * @param  {true} async Always async
84
+   * @param  {any} user NOT SUPPORTED
85
+   * @param  {any} password NOT SUPPORTED
86
+   */
78 87
   open(method:string, url:string, async:true, user:any, password:any) {
79 88
     log.verbose('XMLHttpRequest open ', method, url, async, user, password)
80 89
     this._method = method
81 90
     this._url = url
91
+    this._headers = {}
82 92
     this.readyState = XMLHttpRequest.OPENED
83 93
   }
84 94
 
@@ -87,6 +97,10 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
87 97
    * @param  {any} body Body in RNfetchblob flavor
88 98
    */
89 99
   send(body) {
100
+
101
+    if(this._readyState !== XMLHttpRequest.OPENED)
102
+      throw 'InvalidStateError : XMLHttpRequest is not opened yet.'
103
+
90 104
     this._sendFlag = true
91 105
     log.verbose('XMLHttpRequest send ', body)
92 106
     let {_method, _url, _headers } = this
@@ -123,8 +137,19 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
123 137
     if(this._readyState !== OPENED && this._sendFlag) {
124 138
       throw `InvalidStateError : Calling setRequestHeader in wrong state  ${this._readyState}`
125 139
     }
126
-    if(/[^\u0000-\u00ff]/.test(name) || typeof name !== 'string') {
127
-      throw `TypeError : Invalid header field name ${name}`
140
+    // UNICODE SHOULD NOT PASS
141
+    if(typeof name !== 'string' || /[^\u0000-\u00ff]/.test(name)) {
142
+      throw 'TypeError : header field name should be a string'
143
+    }
144
+    //
145
+    let invalidPatterns = [
146
+      /[\(\)\>\<\@\,\:\\\/\[\]\?\=\}\{\s\ \u007f\;\t\0\v\r]/,
147
+      /tt/
148
+    ]
149
+    for(let i in invalidPatterns) {
150
+      if(invalidPatterns[i].test(name) || typeof name !== 'string') {
151
+        throw `SyntaxError : Invalid header field name ${name}`
152
+      }
128 153
     }
129 154
     this._headers[name] = value
130 155
   }
@@ -160,9 +185,9 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
160 185
   }
161 186
 
162 187
   getAllResponseHeaders():string | null {
163
-    log.verbose('XMLHttpRequest get all headers',this._task.taskId, this._responseHeaders)
188
+    log.verbose('XMLHttpRequest get all headers', this._responseHeaders)
164 189
     if(!this._responseHeaders)
165
-      return null
190
+      return ''
166 191
     let result = ''
167 192
     let respHeaders = this.responseHeaders
168 193
     for(let i in respHeaders) {
@@ -202,10 +227,10 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
202 227
 
203 228
   _onError(err) {
204 229
     log.verbose('XMLHttpRequest error', err)
205
-    this.statusText = err
206
-    this.status = String(err).match(/\d+/)
207
-    this.status = this.status ? Math.floor(this.status) : 404
208
-    this.readyState = XMLHttpRequest.DONE
230
+    this._statusText = err
231
+    this._status = String(err).match(/\d+/)
232
+    this._status = this._status ? Math.floor(this.status) : 404
233
+    this._readyState = XMLHttpRequest.DONE
209 234
     if(String(err).match('timeout') !== null) {
210 235
       this.dispatchEvent('timeout')
211 236
       if(this.ontimeout)
@@ -223,7 +248,6 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
223 248
   _onDone(resp) {
224 249
     log.verbose('XMLHttpRequest done', this._task.taskId, this)
225 250
     this.statusText = '200 OK'
226
-    this._status = 200
227 251
     switch(resp.type) {
228 252
       case 'base64' :
229 253
         if(this.responseType === 'json') {
@@ -306,7 +330,7 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
306 330
   }
307 331
 
308 332
   get responseHeaders() {
309
-    log.verbose('get responseHeaders', this._task.taskId, this._responseHeaders)
333
+    log.verbose('get responseHeaders', this._responseHeaders)
310 334
     return this._responseHeaders
311 335
   }
312 336