Bug 301705: Don't throw when XMLHttpRequest.status is gotten too early. r=bz
authorJonas Sicking <jonas@sicking.cc>
Mon, 26 Mar 2012 01:40:09 -0700
changeset 93605 ddb88db53379eba20b5f44149ca262fce8b3435e
parent 93604 3018a98a65b2fd63c9121f22f6b78dbcc429af7b
child 93606 9d156f164c8e9ea6adf957d16540d123283df0b2
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs301705
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 301705: Don't throw when XMLHttpRequest.status is gotten too early. r=bz
content/base/src/nsXMLHttpRequest.cpp
content/base/test/test_XHR.html
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1205,33 +1205,28 @@ nsXMLHttpRequest::GetStatus(PRUint32 *aS
       nsresult status;
       mChannel->GetStatus(&status);
       if (NS_FAILED(status)) {
         return NS_OK;
       }
     }
   }
 
+  PRUint16 readyState;
+  GetReadyState(&readyState);
+  if (readyState == UNSENT || readyState == OPENED || mErrorLoad) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIHttpChannel> httpChannel = GetCurrentHttpChannel();
-
   if (httpChannel) {
     nsresult rv = httpChannel->GetResponseStatus(aStatus);
-    if (rv == NS_ERROR_NOT_AVAILABLE) {
-      // Someone's calling this before we got a response... Check our
-      // ReadyState.  If we're at 3 or 4, then this means the connection
-      // errored before we got any data; return 0 in that case.
-      PRUint16 readyState;
-      GetReadyState(&readyState);
-      if (readyState >= LOADING) {
-        *aStatus = 0;
-        return NS_OK;
-      }
+    if (NS_FAILED(rv)) {
+      *aStatus = 0;
     }
-
-    return rv;
   }
 
   return NS_OK;
 }
 
 /* readonly attribute AUTF8String statusText; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetStatusText(nsACString& aStatusText)
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -214,22 +214,41 @@ xhr.onloadend = continueTest;
 xhr.send("{");
 yield;
 is(xhr.status, 200, "wrong status");
 checkResponseTextAccessThrows(xhr);
 checkResponseXMLAccessThrows(xhr);
 is(xhr.response, null, "Bad JSON should result in null response.");
 is(xhr.response, null, "Bad JSON should result in null response even 2nd time.");
 
+// Test status/statusText in all readyStates
+xhr = new XMLHttpRequest();
+function checkXHRStatus() {
+  if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) {
+    is(xhr.status, 0, "should be 0 before getting data");
+    is(xhr.statusText, "", "should be empty before getting data");
+  }
+  else {
+    is(xhr.status, 200, "should be 200 when we have data");
+    is(xhr.statusText, "OK", "should be OK when we have data");
+  }
+}
+checkXHRStatus();
+xhr.open("GET", 'file_XHR_binary1.bin'); 
+checkXHRStatus();
+xhr.responseType = 'arraybuffer';
+xhr.onreadystatechange = continueTest;
+xhr.send(null);
+while (xhr.readyState != 4) {
+  checkXHRStatus();
+  yield;
+}
+checkXHRStatus();
+
 // test response (responseType='blob')
-var onloadCount = 0;
-function checkOnloadCount() {
-  if (++onloadCount >= 6) SimpleTest.finish();
-};
-
 var responseTypes = ['blob', 'moz-blob'];
 for (var i = 0; i < responseTypes.length; i++) {
   var t = responseTypes[i];
   // with a simple text file
   xhr = new XMLHttpRequest();
   xhr.open("GET", 'file_XHR_pass2.txt'); 
   xhr.responseType = t;
   xhr.onloadend = continueTest;
@@ -239,83 +258,82 @@ for (var i = 0; i < responseTypes.length
   checkResponseTextAccessThrows(xhr);
   checkResponseXMLAccessThrows(xhr);
   var b = xhr.response;
   ok(b, "should have a non-null blob");
   ok(b instanceof Blob, "should be a Blob");
   ok(!(b instanceof File), "should not be a File");
   is(b.size, "hello pass\n".length, "wrong blob size");
 
-  (function(){
-    var fr = new FileReader();
-    fr.onload = function() {
-      ok(fr.result, "hello pass\n", "wrong values");
-      checkOnloadCount();
-    };
-    fr.readAsBinaryString(b);
-  })();
+  var fr = new FileReader();
+  fr.onload = continueTest;
+  fr.readAsBinaryString(b);
+  yield;
+  ok(fr.result, "hello pass\n", "wrong values");
 
   // with a binary file
-  (function(){
-    var xhr = new XMLHttpRequest();
-    xhr.onreadystatechange = function() {
-      switch (xhr.readyState) {
-      case 2:
-        is(xhr.status, 200, "wrong status");
-        xhr.responseType = t;
-        break;
-      case 4:
-        b = xhr.response;
-        ok(b != null, "should have a non-null blob");
-        is(b.size, 12, "wrong blob size");
+  xhr = new XMLHttpRequest();
+  xhr.onreadystatechange = continueTest;
+  xhr.open("GET", 'file_XHR_binary1.bin', true);
+  xhr.send(null);
+  while(xhr.readyState != 2)
+    yield;
+
+  is(xhr.status, 200, "wrong status");
+  xhr.responseType = t;
 
-        var fr = new FileReader();
-        fr.onload = function() {
-          is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values");
-          checkOnloadCount();
-        };
-        xhr = null; // kill the XHR object
-        SpecialPowers.gc();
-        fr.readAsBinaryString(b);
-        break;
-      }
-    };
-    xhr.open("GET", 'file_XHR_binary1.bin', true);
-    xhr.send(null);
-  })();
+  while(xhr.readyState != 4)
+    yield;
+  
+  xhr.onreadystatechange = null;
+
+  b = xhr.response;
+  ok(b != null, "should have a non-null blob");
+  is(b.size, 12, "wrong blob size");
+
+  fr = new FileReader();
+  fr.readAsBinaryString(b);
+  xhr = null; // kill the XHR object
+  b = null;
+  SpecialPowers.gc();
+  fr.onload = continueTest;
+  yield;
+  is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values");
 
-  (function(){
-    // with a larger binary file
-    var xhr = new XMLHttpRequest();
-    xhr.onreadystatechange = function() {
-      if (xhr.readyState == 4) {
-        b = xhr.response;
-        ok(b != null, "should have a non-null blob");
-        is(b.size, 65536, "wrong blob size");
+  // with a larger binary file
+  xhr = new XMLHttpRequest();
+  xhr.onreadystatechange = continueTest;
+  xhr.open("GET", 'file_XHR_binary2.bin', true);
+  xhr.responseType = t;
+  xhr.send(null);
+
+  while (xhr.readyState != 4)
+    yield;
+
+  xhr.onreadystatechange = null;
+
+  var b = xhr.response;
+  ok(b != null, "should have a non-null blob");
+  is(b.size, 65536, "wrong blob size");
 
-        var fr = new FileReader();
-        fr.onload = function() {
-          var u8 = new Uint8Array(fr.result);
-          for (var i = 0; i < 65536; i++) {
-            if (u8[i] !== (i & 255)) {
-              break;
-            }
-          }
-          is(i, 65536, "wrong value at offset " + i);
-          checkOnloadCount();
-        };
-        xhr = null; // kill the XHR object
-        SpecialPowers.gc();
-        fr.readAsArrayBuffer(b);
-      }
-    };
-    xhr.open("GET", 'file_XHR_binary2.bin', true);
-    xhr.responseType = t;
-    xhr.send(null);
-  })();
+  fr = new FileReader();
+  fr.readAsArrayBuffer(b);
+  fr.onload = continueTest;
+  xhr = null; // kill the XHR object
+  b = null;
+  SpecialPowers.gc();
+  yield;
+
+  var u8 = new Uint8Array(fr.result);
+  for (var i = 0; i < 65536; i++) {
+    if (u8[i] !== (i & 255)) {
+      break;
+    }
+  }
+  is(i, 65536, "wrong value at offset " + i);
 }
 
 var client = new XMLHttpRequest();
 client.onreadystatechange = function() {
   if(client.readyState == 4) {
     try {
       is(client.responseXML, null, "responseXML should be null.");
       is(client.responseText, "", "responseText should be empty string.");
@@ -328,14 +346,16 @@ client.onreadystatechange = function() {
       ok(false, "Shouldn't throw! [" + ex + "]");
     }
   }
 }
 client.open("GET", "file_XHR_pass1.xml", true);
 client.send();
 client.abort();
 
+SimpleTest.finish();
 yield;
+
 } /* runTests */
 </script>
 </pre>
 </body>
 </html>