Bug 1321525 - FileReader.readAs* should throw if called nested, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 01 Dec 2016 18:57:36 +0100
changeset 325065 8083de7bddbc48c2cdf35c4810746b4e6ea9d13f
parent 325033 083ffc01652a13e80d12288074fd5dbc39621e93
child 325066 7de007e9921283029004cb7a274eb6a5b27a6f56
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerssmaug
bugs1321525
milestone53.0a1
Bug 1321525 - FileReader.readAs* should throw if called nested, r=smaug
dom/file/FileReader.cpp
dom/file/tests/test_fileapi.html
dom/workers/test/worker_fileReader.js
testing/web-platform/meta/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -344,31 +344,28 @@ FileReader::DoReadData(uint64_t aCount)
 // Helper methods
 
 void
 FileReader::ReadFileContent(Blob& aBlob,
                             const nsAString &aCharset,
                             eDataFormat aDataFormat,
                             ErrorResult& aRv)
 {
-  //Implicit abort to clear any other activity going on
-  ErrorResult error;
-  Abort(error);
-  error.SuppressException();
-
   if (mReadyState == LOADING) {
-    // A nested ReadAsSomething() as been called during one of the events
-    // dispatched by Abort(). We have to terminate this operation in order to
-    // continue the nested one.
-    aRv.Throw(NS_ERROR_ABORT);
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   mError = nullptr;
+
   SetDOMStringToNull(mResult);
+  mResultArrayBuffer = nullptr;
+
+  mAsyncStream = nullptr;
+
   mTransferred = 0;
   mTotal = 0;
   mReadyState = EMPTY;
   FreeFileData();
 
   mBlob = &aBlob;
   mDataFormat = aDataFormat;
   CopyUTF16toUTF8(aCharset, mCharset);
--- a/dom/file/tests/test_fileapi.html
+++ b/dom/file/tests/test_fileapi.html
@@ -351,28 +351,36 @@ function onFilesOpened(message) {
   r = new FileReader();
   r.onabort = function (event) {
     is(reuseAbortHasRun, false, "abort should only fire once");
     reuseAbortHasRun = true;
     is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort");
     is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads");
     is(event.target.result, null, "file data should be null on aborted reads");
   }
-  r.onload = function() { ok(false, "load should not fire for aborted reads") };
+  r.onload = function() { ok(false, "load should fire for nested reads"); };
+
   var abortThrew = false;
   try {
     r.abort();
   } catch(e) {
     abortThrew = true;
   }
   is(abortThrew, true, "abort() must throw if not loading");
   is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
   r.readAsText(asciiFile);
-  r.readAsText(asciiFile);
-  is(reuseAbortHasRun, true, "abort should fire sync");
+
+  var readThrew = false;
+  try {
+    r.readAsText(asciiFile);
+  } catch(e) {
+    readThrew = true;
+  }
+  is(readThrew, true, "readAsText() must throw if loading");
+  is(reuseAbortHasRun, false, "abort should not fire");
   r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading");
   expectedTestCount++;
 
 
   // Test reading from nonexistent files
   r = new FileReader();
   var didThrow = false;
   r.onerror = function (event) {
--- a/dom/workers/test/worker_fileReader.js
+++ b/dom/workers/test/worker_fileReader.js
@@ -299,41 +299,43 @@ onmessage = function(message) {
     r.abort();
   } catch(e) {
     abortThrew = true;
   }
   is(abortThrew, true, "abort() must throw if not loading");
   is(abortHasRun, false, "abort() is a no-op unless loading");
   r.readAsText(asciiFile);
   r.abort();
-  is(abortHasRun, true, "abort should fire sync");
+  is(abortHasRun, true, "1 abort should fire sync");
   is(loadEndHasRun, true, "loadend should fire sync");
 
   // Test calling readAsX to cause abort()
   var reuseAbortHasRun = false;
   r = new FileReader();
-  r.onabort = function (event) {
-    is(reuseAbortHasRun, false, "abort should only fire once");
-    reuseAbortHasRun = true;
-    is(event.target.readyState, FileReader.DONE, "should be DONE while firing onabort");
-    is(event.target.error.name, "AbortError", "error set to AbortError for aborted reads");
-    is(event.target.result, null, "file data should be null on aborted reads");
-  }
-  r.onload = function() { ok(false, "load should not fire for aborted reads") };
+  r.onabort = function (event) { reuseAbortHasRun = true; }
+  r.onload = function() { ok(true, "load should fire for aborted reads") };
   var abortThrew = false;
   try {
     r.abort();
   } catch(e) {
     abortThrew = true;
   }
   is(abortThrew, true, "abort() must throw if not loading");
   is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
   r.readAsText(asciiFile);
+
+  var readThrew = false;
+  try {
   r.readAsText(asciiFile);
-  is(reuseAbortHasRun, true, "abort should fire sync");
+  } catch(e) {
+    readThrew = true;
+  }
+
+  is(readThrew, true, "readAsText() must throw if loading");
+  is(reuseAbortHasRun, false, "2 abort should fire sync");
   r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading");
   expectedTestCount++;
 
 
   // Test reading from nonexistent files
   r = new FileReader();
   var didThrow = false;
   r.onerror = function (event) {
--- a/testing/web-platform/meta/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini
+++ b/testing/web-platform/meta/FileAPI/reading-data-section/FileReader-multiple-reads.html.ini
@@ -1,17 +1,5 @@
 [FileReader-multiple-reads.html]
   type: testharness
-  [test FileReader InvalidStateError exception for readAsText]
-    expected: FAIL
-
-  [test FileReader InvalidStateError exception for readAsDataURL]
-    expected: FAIL
-
-  [test FileReader InvalidStateError exception for readAsArrayBuffer]
-    expected: FAIL
-
-  [test FileReader InvalidStateError exception in onloadstart event for readAsArrayBuffer]
-    expected: FAIL
-
   [test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer]
     expected: FAIL