Bug 580128 - Make IndexedDB work with compartments. r=jst
authorBen Turner <bent.mozilla@gmail.com>
Sun, 10 Oct 2010 15:35:42 -0700
changeset 55618 810cfd3c2c91eb8690ea429eed3614c9bb010087
parent 55617 080a9074195cdb445d71b63e8576a46419eb9495
child 55619 7d0cbf2893bc61c6e8e76a70dda955107f9e1bb9
push id16269
push userjst@mozilla.com
push dateThu, 14 Oct 2010 01:40:35 +0000
treeherdermozilla-central@29c228a4d7eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs580128
milestone2.0b8pre
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 580128 - Make IndexedDB work with compartments. r=jst
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/src/threads/nsDOMWorker.cpp
dom/src/threads/nsDOMWorkerEvents.cpp
dom/src/threads/nsDOMWorkerEvents.h
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -460,16 +460,18 @@ IDBCursor::Continue(const jsval &aKey,
 
 NS_IMETHODIMP
 IDBCursor::Update(const jsval &aValue,
                   JSContext* aCx,
                   nsIIDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
+  nsresult rv;
+
   if (mType != OBJECTSTORE) {
     NS_NOTYETIMPLEMENTED("Implement me!");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   if (!mObjectStore->TransactionIsOpen()) {
     return NS_ERROR_UNEXPECTED;
   }
@@ -478,22 +480,17 @@ IDBCursor::Update(const jsval &aValue,
     return NS_ERROR_OBJECT_IS_IMMUTABLE;
   }
 
   const Key& key = mData[mDataIndex].key;
   NS_ASSERTION(!key.IsUnset() && !key.IsNull(), "Bad key!");
 
   JSAutoRequest ar(aCx);
 
-  js::AutoValueRooter clone(aCx);
-  nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
-                                                      clone.jsval_addr());
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  js::AutoValueRooter clone(aCx, aValue);
 
   if (!mObjectStore->KeyPath().IsEmpty()) {
     // Make sure the object given has the correct keyPath value set on it or
     // we will add it.
     const nsString& keyPath = mObjectStore->KeyPath();
     const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get());
     const size_t keyPathLen = keyPath.Length();
 
@@ -501,16 +498,19 @@ IDBCursor::Update(const jsval &aValue,
     JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
                                  keyPathChars, keyPathLen, prop.jsval_addr());
     NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
 
     if (JSVAL_IS_VOID(prop.jsval_value())) {
       rv = IDBObjectStore::GetJSValFromKey(key, aCx, prop.jsval_addr());
       NS_ENSURE_SUCCESS(rv, rv);
 
+      ok = JS_StructuredClone(aCx, clone.jsval_value(), clone.jsval_addr());
+      NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
+
       ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
                                keyPathChars, keyPathLen, prop.jsval_value(), nsnull,
                                nsnull, JSPROP_ENUMERATE);
       NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
     }
     else {
       Key newKey;
       rv = IDBObjectStore::GetKeyFromJSVal(prop.jsval_value(), newKey);
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -492,25 +492,19 @@ IDBObjectStore::GetJSONFromArg0(/* jsval
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSContext* cx;
   rv = cc->GetJSContext(&cx);
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSAutoRequest ar(cx);
 
-  js::AutoValueRooter clone(cx);
-  rv = nsContentUtils::CreateStructuredClone(cx, argv[0], clone.jsval_addr());
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
   nsCOMPtr<nsIJSON> json(new nsJSON());
 
-  rv = json->EncodeFromJSVal(clone.jsval_addr(), cx, aJSON);
+  rv = json->EncodeFromJSVal(&argv[0], cx, aJSON);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 // static
 nsresult
 IDBObjectStore::GetKeyPathValueFromJSON(const nsAString& aJSON,
@@ -770,36 +764,31 @@ IDBObjectStore::~IDBObjectStore()
 nsresult
 IDBObjectStore::GetAddInfo(JSContext* aCx,
                            jsval aValue,
                            jsval aKeyVal,
                            nsString& aJSON,
                            Key& aKey,
                            nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
 {
-  JSAutoRequest ar(aCx);
+  nsresult rv;
 
-  js::AutoValueRooter clone(aCx);
-  nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
-                                                      clone.jsval_addr());
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  JSAutoRequest ar(aCx);
 
   if (mKeyPath.IsEmpty()) {
     rv = GetKeyFromJSVal(aKeyVal, aKey);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else {
     // Inline keys live on the object. Make sure it is an object.
-    if (JSVAL_IS_PRIMITIVE(clone.jsval_value())) {
+    if (JSVAL_IS_PRIMITIVE(aValue)) {
       return NS_ERROR_INVALID_ARG;
     }
 
-    rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(clone.jsval_value()), mKeyPath, aKey);
+    rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Except if null was passed, in which case we're supposed to generate the
     // key.
     if (aKey.IsUnset() && JSVAL_IS_NULL(aKeyVal)) {
       aKey = Key::NULLKEY;
     }
   }
@@ -807,21 +796,21 @@ IDBObjectStore::GetAddInfo(JSContext* aC
   if (aKey.IsUnset() && !mAutoIncrement) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Figure out indexes and the index values to update here.
   ObjectStoreInfo* objectStoreInfo = GetObjectStoreInfo();
   NS_ENSURE_TRUE(objectStoreInfo, NS_ERROR_FAILURE);
 
-  rv = GetIndexUpdateInfo(objectStoreInfo, aCx, clone.jsval_value(), aUpdateInfoArray);
+  rv = GetIndexUpdateInfo(objectStoreInfo, aCx, aValue, aUpdateInfoArray);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIJSON> json(new nsJSON());
-  rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, aJSON);
+  rv = json->EncodeFromJSVal(&aValue, aCx, aJSON);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBObjectStore)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBObjectStore,
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -1534,35 +1534,32 @@ nsDOMWorker::PostMessageInternal(PRBool 
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSContext* cx;
   rv = cc->GetJSContext(&cx);
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSAutoRequest ar(cx);
 
-  nsAutoJSValHolder val;
-  if (!val.Hold(cx)) {
+  JSAutoStructuredCloneBuffer buffer(cx);
+
+  if (!buffer.write(argv[0])) {
+    NS_WARNING("Failed to serialize!");
     return NS_ERROR_FAILURE;
   }
 
-  rv = nsContentUtils::CreateStructuredClone(cx, argv[0], val.ToJSValPtr());
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
   nsRefPtr<nsDOMWorkerMessageEvent> message = new nsDOMWorkerMessageEvent();
   NS_ENSURE_TRUE(message, NS_ERROR_OUT_OF_MEMORY);
 
   rv = message->InitMessageEvent(NS_LITERAL_STRING("message"), PR_FALSE,
                                  PR_FALSE, EmptyString(), EmptyString(),
                                  nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = message->SetJSVal(cx, val);
+  rv = message->SetJSData(cx, buffer);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsDOMFireEventRunnable> runnable =
     new nsDOMFireEventRunnable(this, message, aToInner);
   NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
 
   // If aToInner is true then we want to target the runnable at this worker's
   // thread. Otherwise we need to target the parent's thread.
--- a/dom/src/threads/nsDOMWorkerEvents.cpp
+++ b/dom/src/threads/nsDOMWorkerEvents.cpp
@@ -259,52 +259,56 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorker
                                                       nsIWorkerMessageEvent)
 
 NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
                                                       nsIWorkerMessageEvent)
 
 NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
 
 nsresult
-nsDOMWorkerMessageEvent::SetJSVal(JSContext* aCx,
-                                  jsval aData)
+nsDOMWorkerMessageEvent::SetJSData(JSContext* aCx,
+                                   JSAutoStructuredCloneBuffer& aBuffer)
 {
+  NS_ASSERTION(aCx, "Null context!");
+
   if (!mDataVal.Hold(aCx)) {
     NS_WARNING("Failed to hold jsval!");
     return NS_ERROR_FAILURE;
   }
 
-  mDataVal = aData;
+  aBuffer.steal(&mData, &mDataLen);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWorkerMessageEvent::GetData(nsAString& aData)
 {
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
 
   nsAXPCNativeCallContext* cc;
   nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
 
-  if (!mDataValWasReparented) {
-    if (JSVAL_IS_OBJECT(mDataVal) && !JSVAL_IS_NULL(mDataVal)) {
-      JSContext* cx;
-      rv = cc->GetJSContext(&cx);
-      NS_ENSURE_SUCCESS(rv, rv);
+  if (mData) {
+    JSContext* cx;
+    rv = cc->GetJSContext(&cx);
+    NS_ENSURE_SUCCESS(rv, rv);
 
-      rv =
-        nsContentUtils::ReparentClonedObjectToScope(cx,
-                                                    JSVAL_TO_OBJECT(mDataVal),
-                                                    JS_GetGlobalObject(cx));
-      NS_ENSURE_SUCCESS(rv, rv);
+    JSAutoRequest ar(cx);
+    JSAutoStructuredCloneBuffer buffer(cx);
+    buffer.adopt(mData, mDataLen);
+    mData = nsnull;
+    mDataLen = 0;
+
+    if (!buffer.read(mDataVal.ToJSValPtr())) {
+      NS_WARNING("Failed to deserialize!");
+      return NS_ERROR_FAILURE;
     }
-    mDataValWasReparented = PR_TRUE;
   }
 
   jsval* retval;
   rv = cc->GetRetValPtr(&retval);
   NS_ENSURE_SUCCESS(rv, rv);
 
   cc->SetReturnValueWasSet(PR_TRUE);
   *retval = mDataVal;
--- a/dom/src/threads/nsDOMWorkerEvents.h
+++ b/dom/src/threads/nsDOMWorkerEvents.h
@@ -42,16 +42,17 @@
 #include "nsIClassInfo.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMProgressEvent.h"
 #include "nsIDOMWorkers.h"
 #include "nsIRunnable.h"
 
 #include "jsapi.h"
+#include "jsutil.h"
 #include "nsAutoJSValHolder.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsStringGlue.h"
 
 #include "nsDOMWorkerMacros.h"
 
 class nsDOMWorkerXHRProxy;
@@ -205,27 +206,28 @@ class nsDOMWorkerMessageEvent : public n
                                 public nsIWorkerMessageEvent
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
   NS_DECL_NSIWORKERMESSAGEEVENT
   NS_DECL_NSICLASSINFO_GETINTERFACES
 
-  nsDOMWorkerMessageEvent() : mDataValWasReparented(PR_FALSE) { }
+  nsDOMWorkerMessageEvent() : mData(nsnull) { }
 
-  nsresult SetJSVal(JSContext* aCx,
-                    jsval aData);
+  nsresult SetJSData(JSContext* aCx,
+                     JSAutoStructuredCloneBuffer& aBuffer);
 
 protected:
   nsString mOrigin;
   nsCOMPtr<nsISupports> mSource;
 
   nsAutoJSValHolder mDataVal;
-  PRBool mDataValWasReparented;
+  uint64* mData;
+  size_t mDataLen;
 };
 
 class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
                                  public nsIDOMProgressEvent
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
@@ -264,21 +266,16 @@ public:
   nsresult readyStateResult;
 
 protected:
   virtual ~nsDOMWorkerXHRState() { }
 
   nsAutoRefCnt mRefCnt;
 };
 
-enum SnapshotChoice {
-  WANT_SNAPSHOT,
-  NO_SNAPSHOT
-};
-
 class nsDOMWorkerXHREvent : public nsDOMWorkerProgressEvent,
                             public nsIRunnable
 {
   friend class nsDOMWorkerXHRProxy;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIRUNNABLE