Bug 1161063; r=bent
authorJan Varga <jan.varga@gmail.com>
Thu, 11 Jun 2015 22:34:30 +0200
changeset 248562 be976c7cb4b1ff8d4f26c0f33d780950ec491f3b
parent 248561 c1afb1408755ad1794c5055a595eed8dce9e73ef
child 248563 c0ef8de6093e757f2d7be874ae5840ee7a99a1ba
push id28899
push userryanvm@gmail.com
push dateFri, 12 Jun 2015 18:57:39 +0000
treeherdermozilla-central@203e1025a826 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs1161063
milestone41.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 1161063; r=bent
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/test/dummy_worker.js
dom/indexedDB/test/mochitest.ini
dom/indexedDB/test/test_filehandle_workers.html
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -571,21 +571,23 @@ class ValueDeserializationHelper
 public:
   static bool
   CreateAndWrapMutableFile(JSContext* aCx,
                            IDBDatabase* aDatabase,
                            StructuredCloneFile& aFile,
                            const MutableFileData& aData,
                            JS::MutableHandle<JSObject*> aResult)
   {
-    MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
-    MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aDatabase);
     MOZ_ASSERT(aFile.mFileInfo);
 
+    if (!IndexedDatabaseManager::IsMainProcess() || !NS_IsMainThread()) {
+      return false;
+    }
+
     nsRefPtr<IDBMutableFile> mutableFile =
       IDBMutableFile::Create(aDatabase,
                              aData.name,
                              aData.type,
                              aFile.mFileInfo.forget());
     MOZ_ASSERT(mutableFile);
 
     JS::Rooted<JSObject*> result(aCx, mutableFile->WrapObject(aCx, nullptr));
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -357,23 +357,30 @@ IDBRequest::SetResultCallback(ResultCall
 
   JSContext* cx = autoJS.cx();
 
   AssertIsRooted();
 
   JS::Rooted<JS::Value> result(cx);
   nsresult rv = aCallback->GetResult(cx, &result);
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    SetError(rv);
-    mResultVal.setUndefined();
-  } else {
-    mError = nullptr;
-    mResultVal = result;
+    // This can only fail if the structured clone contains a mutable file
+    // and the child is not in the main thread and main process.
+    // In that case CreateAndWrapMutableFile() returns false which shows up
+    // as NS_ERROR_DOM_DATA_CLONE_ERR here.
+    MOZ_ASSERT(rv == NS_ERROR_DOM_DATA_CLONE_ERR);
+
+    // We are not setting a result or an error object here since we want to
+    // throw an exception when the 'result' property is being touched.
+    return;
   }
 
+  mError = nullptr;
+  mResultVal = result;
+
   mHaveResultOrErrorCode = true;
 }
 
 DOMError*
 IDBRequest::GetError(ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
deleted file mode 100644
--- a/dom/indexedDB/test/dummy_worker.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-onmessage = function(event) {
-  throw("Shouldn't be called!");
-}
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -1,14 +1,13 @@
 [DEFAULT]
 support-files =
   bfcache_iframe1.html
   bfcache_iframe2.html
   blob_worker_crash_iframe.html
-  dummy_worker.js
   error_events_abort_transactions_iframe.html
   event_propagation_iframe.html
   exceptions_in_events_iframe.html
   file.js
   file_app_isolation.html
   file_app_isolation.js
   helpers.js
   leaving_page_iframe.html
--- a/dom/indexedDB/test/test_filehandle_workers.html
+++ b/dom/indexedDB/test/test_filehandle_workers.html
@@ -9,58 +9,137 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
   <script type="text/javascript;version=1.7">
   function testSteps()
   {
     const name = window.location.pathname;
 
-    var testBuffer = getRandomBuffer(100000);
+    let testBuffer = getRandomBuffer(100000);
 
     let request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
-    request.onsuccess = grabEventAndContinueHandler;
+    request.onupgradeneeded = grabEventAndContinueHandler;
+    request.onsuccess = errorHandler;
     let event = yield undefined;
 
+    is(event.type, "upgradeneeded", "Got correct event type");
+
     let db = event.target.result;
     db.onerror = errorHandler;
 
+    db.createObjectStore("Foo", { });
+
+    request.onupgradeneeded = errorHandler;
+    request.onsuccess = grabEventAndContinueHandler;
+    event = yield undefined;
+
+    is(event.type, "success", "Got correct event type");
+
     request = db.createMutableFile("test.txt");
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     event = yield undefined;
 
     let mutableFile = event.target.result;
+
+    function dummyWorkerScript() {
+      onmessage = function(event) {
+        throw("Shouldn't be called!");
+      }
+    }
+
+    let url =
+      URL.createObjectURL(new Blob(["(", dummyWorkerScript.toSource(), ")()"]));
+
+    let worker = new Worker(url);
+    try {
+      worker.postMessage(mutableFile);
+      ok(false, "Should have thrown!");
+    }
+    catch (e) {
+      ok(e instanceof DOMException, "Got exception.");
+      is(e.name, "DataCloneError", "Good error.");
+      is(e.code, DOMException.DATA_CLONE_ERR, "Good error code.")
+    }
+    worker.terminate();
+
     mutableFile.onerror = errorHandler;
 
     let fileHandle = mutableFile.open("readwrite");
 
     request = fileHandle.write(testBuffer);
     request.onsuccess = grabEventAndContinueHandler;
     event = yield undefined;
 
     request = mutableFile.getFile();
     request.onsuccess = grabEventAndContinueHandler;
     event = yield undefined;
 
     let file = event.target.result;
 
-    var worker = new Worker("dummy_worker.js");
+    worker = new Worker(url);
+    URL.revokeObjectURL(url);
     try {
       worker.postMessage(file);
       ok(false, "Should have thrown!");
     }
     catch (e) {
       ok(e instanceof DOMException, "Got exception.");
       is(e.name, "DataCloneError", "Good error.");
       is(e.code, DOMException.DATA_CLONE_ERR, "Good error code.")
     }
     worker.terminate();
 
+    let objectStore =
+      db.transaction("Foo", "readwrite").objectStore("Foo");
+
+    request = objectStore.add(mutableFile, 42);
+    request.onsuccess = grabEventAndContinueHandler;
+    event = yield undefined;
+
+    function workerScript() {
+      onmessage = function(event) {
+        var name = event.data;
+        var request = indexedDB.open(name, 1);
+        request.onsuccess = function(event) {
+          var db = event.target.result;
+          let objectStore = db.transaction("Foo").objectStore("Foo");
+          request = objectStore.get(42);
+          request.onsuccess = function(event) {
+            try {
+              let result = request.result;
+              postMessage("error");
+            }
+            catch (e) {
+              postMessage("success");
+            }
+          }
+          request.onerror = function(event) {
+            postMessage("error");
+          }
+        }
+        request.onerror = function(event) {
+          postMessage("error");
+        }
+      }
+    }
+
+    url = URL.createObjectURL(new Blob(["(", workerScript.toSource(), ")()"]));
+
+    worker = new Worker(url);
+    URL.revokeObjectURL(url);
+    worker.postMessage(name);
+    worker.onmessage = grabEventAndContinueHandler;
+    event = yield undefined;
+
+    is(event.data, "success", "Good response.");
+    worker.terminate();
+
     finishTest();
     yield undefined;
   }
   </script>
   <script type="text/javascript;version=1.7" src="file.js"></script>
   <script type="text/javascript;version=1.7" src="helpers.js"></script>
 
 </head>