Beispiel #1
0
NS_IMETHODIMP
IDBCursor::Continue(const jsval &aKey,
                    JSContext* aCx,
                    PRUint8 aOptionalArgCount,
                    PRBool* _retval)
{
  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

  if (!mObjectStore->TransactionIsOpen()) {
    return NS_ERROR_UNEXPECTED;
  }

  if (mContinueCalled) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  Key key;
  nsresult rv = IDBObjectStore::GetKeyFromJSVal(aKey, key);
  NS_ENSURE_SUCCESS(rv, rv);

  if (key.IsNull()) {
    if (aOptionalArgCount) {
      return NS_ERROR_INVALID_ARG;
    }
    else {
      key = Key::UNSETKEY;
    }
  }

  TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
  NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);

  nsRefPtr<ContinueRunnable> runnable(new ContinueRunnable(this, key));

  rv = pool->Dispatch(mTransaction, runnable, false, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);

  mTransaction->OnNewRequest();

  mContinueCalled = true;

  *_retval = PR_TRUE;
  return NS_OK;
}
Beispiel #2
0
NS_IMETHODIMP
ContinueRunnable::Run()
{
  nsresult rv;

  if (!NS_IsMainThread()) {
    rv = NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
    NS_ENSURE_SUCCESS(rv, rv);

    return NS_OK;
  }

  // Remove cached stuff from last time.
  mCursor->mCachedKey = nsnull;
  mCursor->mCachedValue = JSVAL_VOID;
  mCursor->mHaveCachedValue = false;
  mCursor->mContinueCalled = false;

  if (mCursor->mType == IDBCursor::INDEX) {
    mCursor->mKeyData.RemoveElementAt(mCursor->mDataIndex);
  }
  else {
    mCursor->mData.RemoveElementAt(mCursor->mDataIndex);
  }
  if (mCursor->mDataIndex) {
    mCursor->mDataIndex--;
  }

  nsCOMPtr<nsIWritableVariant> variant =
    do_CreateInstance(NS_VARIANT_CONTRACTID);
  if (!variant) {
    NS_ERROR("Couldn't create variant!");
    return NS_ERROR_FAILURE;
  }

  PRBool empty = mCursor->mType == IDBCursor::INDEX ?
                 mCursor->mKeyData.IsEmpty() :
                 mCursor->mData.IsEmpty();

  if (empty) {
    rv = variant->SetAsEmpty();
    NS_ENSURE_SUCCESS(rv, rv);
  }
  else {
    if (!mKey.IsUnset()) {
      NS_ASSERTION(!mKey.IsNull(), "Huh?!");

      NS_WARNING("Using a slow O(n) search for continue(key), do something "
                 "smarter!");

      // Skip ahead to our next key match.
      PRInt32 index = PRInt32(mCursor->mDataIndex);

      if (mCursor->mType == IDBCursor::INDEX) {
        while (index >= 0) {
          const Key& key = mCursor->mKeyData[index].key;
          if (mKey == key) {
            break;
          }
          if (key < mKey) {
            index--;
            continue;
          }
          index = -1;
          break;
        }

        if (index >= 0) {
          mCursor->mDataIndex = PRUint32(index);
          mCursor->mKeyData.RemoveElementsAt(index + 1,
                                             mCursor->mKeyData.Length() - index
                                             - 1);
        }
      }
      else {
        while (index >= 0) {
          const Key& key = mCursor->mData[index].key;
          if (mKey == key) {
            break;
          }
          if (key < mKey) {
            index--;
            continue;
          }
          index = -1;
          break;
        }

        if (index >= 0) {
          mCursor->mDataIndex = PRUint32(index);
          mCursor->mData.RemoveElementsAt(index + 1,
                                          mCursor->mData.Length() - index - 1);
        }
      }
    }

    rv = variant->SetAsISupports(static_cast<IDBRequest::Generator*>(mCursor));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  rv = variant->SetWritable(PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIDOMEvent> event =
    IDBSuccessEvent::Create(mCursor->mRequest, variant, mCursor->mTransaction);
  if (!event) {
    NS_ERROR("Failed to create event!");
    return NS_ERROR_FAILURE;
  }

  PRBool dummy;
  mCursor->mRequest->DispatchEvent(event, &dummy);

  mCursor->mTransaction->OnRequestFinished();

  mCursor = nsnull;

  return NS_OK;
}
Beispiel #3
0
NS_IMETHODIMP
IDBCursor::Update(const jsval &aValue,
                  JSContext* aCx,
                  nsIIDBRequest** _retval)
{
  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

  if (mType != OBJECTSTORE) {
    NS_NOTYETIMPLEMENTED("Implement me!");
    return NS_ERROR_NOT_IMPLEMENTED;
  }

  if (!mObjectStore->TransactionIsOpen()) {
    return NS_ERROR_UNEXPECTED;
  }

  if (!mObjectStore->IsWriteAllowed()) {
    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;
  }

  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();

    js::AutoValueRooter prop(aCx);
    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_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);
      NS_ENSURE_SUCCESS(rv, rv);

      if (newKey.IsUnset() || newKey.IsNull() || newKey != key) {
        return NS_ERROR_INVALID_ARG;
      }
    }
  }

  nsTArray<IndexUpdateInfo> indexUpdateInfo;
  rv = IDBObjectStore::GetIndexUpdateInfo(mObjectStore->GetObjectStoreInfo(),
                                          aCx, clone.jsval_value(), indexUpdateInfo);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIJSON> json(new nsJSON());

  nsString jsonValue;
  rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, jsonValue);
  NS_ENSURE_SUCCESS(rv, rv);

  nsRefPtr<IDBRequest> request =
    GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner());
  NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);

  nsRefPtr<UpdateHelper> helper =
    new UpdateHelper(mTransaction, request, mObjectStore->Id(), jsonValue, key,
                     mObjectStore->IsAutoIncrement(), indexUpdateInfo);
  rv = helper->DispatchToTransactionPool();
  NS_ENSURE_SUCCESS(rv, rv);

  request.forget(_retval);
  return NS_OK;
}