Bug 575399 - 'IndexedDB: Remove XPConnect slow paths from some IndexedDB methods'. r=sdwilsh

This commit is contained in:
Ben Turner 2010-06-28 15:22:41 -07:00
Родитель a6a3778b55
Коммит 7cca20c509
11 изменённых файлов: 254 добавлений и 401 удалений

Просмотреть файл

@ -324,65 +324,28 @@ IDBCursor::GetKey(nsIVariant** aKey)
}
NS_IMETHODIMP
IDBCursor::GetValue(nsIVariant** aValue)
IDBCursor::GetValue(JSContext* aCx,
jsval* aValue)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsresult rv;
if (mType == INDEX) {
nsCOMPtr<nsIWritableVariant> variant =
do_CreateInstance(NS_VARIANT_CONTRACTID);
if (!variant) {
NS_ERROR("Couldn't create variant!");
return NS_ERROR_FAILURE;
}
const Key& value = mKeyData[mDataIndex].value;
NS_ASSERTION(!value.IsUnset() && !value.IsNull(), "Bad key!");
if (value.IsInt()) {
rv = variant->SetAsInt64(value.IntValue());
}
else if (value.IsString()) {
rv = variant->SetAsAString(value.StringValue());
}
else {
NS_NOTREACHED("Bad key type!");
}
rv = IDBObjectStore::GetJSValFromKey(value, aCx, aValue);
NS_ENSURE_SUCCESS(rv, rv);
rv = variant->SetWritable(PR_FALSE);;
NS_ENSURE_SUCCESS(rv, rv);
nsIWritableVariant* result;
variant.forget(&result);
*aValue = result;
return NS_OK;
}
NS_WARNING("Using a slow path for GetValue! Fix this now!");
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
nsAXPCNativeCallContext* cc;
rv = xpc->GetCurrentNativeCallContext(&cc);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
jsval* retval;
rv = cc->GetRetValPtr(&retval);
NS_ENSURE_SUCCESS(rv, rv);
if (!mHaveCachedValue) {
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
JSAutoRequest ar(aCx);
if (!mJSRuntime) {
JSRuntime* rt = JS_GetRuntime(cx);
JSRuntime* rt = JS_GetRuntime(aCx);
JSBool ok = JS_AddNamedRootRT(rt, &mCachedValue,
"IDBCursor::mCachedValue");
@ -392,19 +355,19 @@ IDBCursor::GetValue(nsIVariant** aValue)
}
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->DecodeToJSVal(mData[mDataIndex].value, cx, &mCachedValue);
rv = json->DecodeToJSVal(mData[mDataIndex].value, aCx, &mCachedValue);
NS_ENSURE_SUCCESS(rv, rv);
mHaveCachedValue = true;
}
*retval = mCachedValue;
cc->SetReturnValueWasSet(PR_TRUE);
*aValue = mCachedValue;
return NS_OK;
}
NS_IMETHODIMP
IDBCursor::Continue(nsIVariant* aKey,
IDBCursor::Continue(jsval aKey,
JSContext* aCx,
PRUint8 aOptionalArgCount,
PRBool* _retval)
{
@ -419,7 +382,7 @@ IDBCursor::Continue(nsIVariant* aKey,
}
Key key;
nsresult rv = IDBObjectStore::GetKeyFromVariant(aKey, key);
nsresult rv = IDBObjectStore::GetKeyFromJSVal(aKey, key);
NS_ENSURE_SUCCESS(rv, rv);
if (key.IsNull()) {
@ -448,7 +411,8 @@ IDBCursor::Continue(nsIVariant* aKey,
}
NS_IMETHODIMP
IDBCursor::Update(nsIVariant* aValue,
IDBCursor::Update(jsval aValue,
JSContext* aCx,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -469,38 +433,11 @@ IDBCursor::Update(nsIVariant* aValue,
const Key& key = mData[mDataIndex].key;
NS_ASSERTION(!key.IsUnset() && !key.IsNull(), "Bad key!");
// This is the slow path, need to do this better once XPIDL can have raw
// jsvals as arguments.
NS_WARNING("Using a slow path for Update! Fix this now!");
JSAutoRequest ar(aCx);
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);
PRUint32 argc;
rv = cc->GetArgc(&argc);
NS_ENSURE_SUCCESS(rv, rv);
if (argc < 1) {
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
}
jsval* argv;
rv = cc->GetArgvPtr(&argv);
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.addr());
js::AutoValueRooter clone(aCx);
nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
clone.addr());
if (NS_FAILED(rv)) {
return rv;
}
@ -512,58 +449,26 @@ IDBCursor::Update(nsIVariant* aValue,
const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get());
const size_t keyPathLen = keyPath.Length();
js::AutoValueRooter prop(cx);
JSBool ok = JS_GetUCProperty(cx, JSVAL_TO_OBJECT(clone.value()),
js::AutoValueRooter prop(aCx);
JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(clone.value()),
keyPathChars, keyPathLen, prop.addr());
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
if (JSVAL_IS_VOID(prop.value())) {
if (key.IsInt()) {
ok = JS_NewNumberValue(cx, key.IntValue(), prop.addr());
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
}
else if (key.IsString()) {
const nsString& keyString = key.StringValue();
JSString* str =
JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(keyString.get()),
keyString.Length());
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
rv = IDBObjectStore::GetJSValFromKey(key, aCx, prop.addr());
NS_ENSURE_SUCCESS(rv, rv);
prop.set(STRING_TO_JSVAL(str));
}
else {
NS_NOTREACHED("Bad key!");
}
ok = JS_DefineUCProperty(cx, JSVAL_TO_OBJECT(clone.value()), keyPathChars,
keyPathLen, prop.value(), nsnull, nsnull,
JSPROP_ENUMERATE);
ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.value()),
keyPathChars, keyPathLen, prop.value(), nsnull,
nsnull, JSPROP_ENUMERATE);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
}
else {
Key newKey;
rv = IDBObjectStore::GetKeyFromJSVal(prop.value(), newKey);
NS_ENSURE_SUCCESS(rv, rv);
if (JSVAL_IS_NULL(prop.value())) {
return NS_ERROR_INVALID_ARG;
}
if (JSVAL_IS_INT(prop.value())) {
if (!key.IsInt() || JSVAL_TO_INT(prop.value()) != key.IntValue()) {
return NS_ERROR_INVALID_ARG;
}
}
if (JSVAL_IS_DOUBLE(prop.value())) {
if (!key.IsInt() || *JSVAL_TO_DOUBLE(prop.value()) != key.IntValue()) {
return NS_ERROR_INVALID_ARG;
}
}
if (JSVAL_IS_STRING(prop.value())) {
if (!key.IsString()) {
return NS_ERROR_INVALID_ARG;
}
if (key.StringValue() != nsDependentJSString(prop.value())) {
if (newKey.IsUnset() || newKey.IsNull() || newKey != key) {
return NS_ERROR_INVALID_ARG;
}
}
@ -571,14 +476,13 @@ IDBCursor::Update(nsIVariant* aValue,
nsTArray<IndexUpdateInfo> indexUpdateInfo;
rv = IDBObjectStore::GetIndexUpdateInfo(mObjectStore->GetObjectStoreInfo(),
cx, clone.value(),
indexUpdateInfo);
aCx, clone.value(), indexUpdateInfo);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIJSON> json(new nsJSON());
nsString jsonValue;
rv = json->EncodeFromJSVal(clone.addr(), cx, jsonValue);
rv = json->EncodeFromJSVal(clone.addr(), aCx, jsonValue);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<IDBRequest> request = GenerateWriteRequest();

Просмотреть файл

@ -43,8 +43,6 @@
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "nsIIDBCursor.h"
#include "jsapi.h"
class nsIRunnable;
BEGIN_INDEXEDDB_NAMESPACE

Просмотреть файл

@ -343,10 +343,24 @@ DOMCI_DATA(IDBSuccessEvent, IDBSuccessEvent)
DOMCI_DATA(IDBTransactionEvent, IDBSuccessEvent)
NS_IMETHODIMP
IDBSuccessEvent::GetResult(nsIVariant** aResult)
IDBSuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
nsCOMPtr<nsIVariant> result(mResult);
result.forget(aResult);
if (!mResult) {
*aResult = JSVAL_VOID;
return NS_OK;
}
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ENSURE_STATE(xpc);
JSAutoRequest ar(aCx);
JSObject* scope = JS_GetGlobalObject(aCx);
NS_ENSURE_STATE(scope);
nsresult rv = xpc->VariantToJS(aCx, scope, mResult, aResult);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -376,26 +390,11 @@ GetSuccessEvent::Init(IDBRequest* aRequest,
}
NS_IMETHODIMP
GetSuccessEvent::GetResult(nsIVariant** /* aResult */)
GetSuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
// This is the slow path, need to do this better once XPIDL can pass raw
// jsvals.
NS_WARNING("Using a slow path for GetResult! Fix this now!");
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);
jsval* retval;
rv = cc->GetRetValPtr(&retval);
NS_ENSURE_SUCCESS(rv, rv);
if (mValue.IsVoid()) {
*retval = JSVAL_VOID;
*aResult = JSVAL_VOID;
return NS_OK;
}
@ -403,13 +402,9 @@ GetSuccessEvent::GetResult(nsIVariant** /* aResult */)
nsString jsonValue = mValue;
mValue.Truncate();
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(aCx);
JSAutoRequest ar(cx);
JSRuntime* rt = JS_GetRuntime(cx);
JSRuntime* rt = JS_GetRuntime(aCx);
JSBool ok = JS_AddNamedRootRT(rt, &mCachedValue,
"GetSuccessEvent::mCachedValue");
@ -418,7 +413,7 @@ GetSuccessEvent::GetResult(nsIVariant** /* aResult */)
mJSRuntime = rt;
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->DecodeToJSVal(jsonValue, cx, &mCachedValue);
nsresult rv = json->DecodeToJSVal(jsonValue, aCx, &mCachedValue);
if (NS_FAILED(rv)) {
mCachedValue = JSVAL_VOID;
@ -427,38 +422,18 @@ GetSuccessEvent::GetResult(nsIVariant** /* aResult */)
}
}
*retval = mCachedValue;
cc->SetReturnValueWasSet(PR_TRUE);
*aResult = mCachedValue;
return NS_OK;
}
NS_IMETHODIMP
GetAllSuccessEvent::GetResult(nsIVariant** /* aResult */)
GetAllSuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
// This is the slow path, need to do this better once XPIDL can pass raw
// jsvals.
NS_WARNING("Using a slow path for GetResult! Fix this now!");
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);
jsval* retval;
rv = cc->GetRetValPtr(&retval);
NS_ENSURE_SUCCESS(rv, rv);
if (!mJSRuntime) {
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(aCx);
JSAutoRequest ar(cx);
JSRuntime* rt = JS_GetRuntime(cx);
JSRuntime* rt = JS_GetRuntime(aCx);
JSBool ok = JS_AddNamedRootRT(rt, &mCachedValue,
"GetSuccessEvent::mCachedValue");
@ -474,7 +449,7 @@ GetAllSuccessEvent::GetResult(nsIVariant** /* aResult */)
return NS_ERROR_FAILURE;
}
JSObject* array = JS_NewArrayObject(cx, 0, NULL);
JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
if (!array) {
NS_ERROR("Failed to make array!");
return NS_ERROR_FAILURE;
@ -483,14 +458,14 @@ GetAllSuccessEvent::GetResult(nsIVariant** /* aResult */)
mCachedValue = OBJECT_TO_JSVAL(array);
if (!values.IsEmpty()) {
if (!JS_SetArrayLength(cx, array, jsuint(values.Length()))) {
if (!JS_SetArrayLength(aCx, array, jsuint(values.Length()))) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array length!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIJSON> json(new nsJSON());
js::AutoValueRooter value(cx);
js::AutoValueRooter value(aCx);
jsint count = jsint(values.Length());
@ -498,14 +473,14 @@ GetAllSuccessEvent::GetResult(nsIVariant** /* aResult */)
nsString jsonValue = values[index];
values[index].Truncate();
rv = json->DecodeToJSVal(jsonValue, cx, value.addr());
nsresult rv = json->DecodeToJSVal(jsonValue, aCx, value.addr());
if (NS_FAILED(rv)) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to decode!");
return rv;
}
if (!JS_SetElement(cx, array, index, value.addr())) {
if (!JS_SetElement(aCx, array, index, value.addr())) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array element!");
return NS_ERROR_FAILURE;
@ -514,38 +489,18 @@ GetAllSuccessEvent::GetResult(nsIVariant** /* aResult */)
}
}
*retval = mCachedValue;
cc->SetReturnValueWasSet(PR_TRUE);
*aResult = mCachedValue;
return NS_OK;
}
NS_IMETHODIMP
GetAllKeySuccessEvent::GetResult(nsIVariant** /* aResult */)
GetAllKeySuccessEvent::GetResult(JSContext* aCx,
jsval* aResult)
{
// This is the slow path, need to do this better once XPIDL can pass raw
// jsvals.
NS_WARNING("Using a slow path for GetResult! Fix this now!");
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);
jsval* retval;
rv = cc->GetRetValPtr(&retval);
NS_ENSURE_SUCCESS(rv, rv);
if (!mJSRuntime) {
JSContext* cx;
rv = cc->GetJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(aCx);
JSAutoRequest ar(cx);
JSRuntime* rt = JS_GetRuntime(cx);
JSRuntime* rt = JS_GetRuntime(aCx);
JSBool ok = JS_AddNamedRootRT(rt, &mCachedValue,
"GetSuccessEvent::mCachedValue");
@ -561,7 +516,7 @@ GetAllKeySuccessEvent::GetResult(nsIVariant** /* aResult */)
return NS_ERROR_FAILURE;
}
JSObject* array = JS_NewArrayObject(cx, 0, NULL);
JSObject* array = JS_NewArrayObject(aCx, 0, NULL);
if (!array) {
NS_ERROR("Failed to make array!");
return NS_ERROR_FAILURE;
@ -570,13 +525,13 @@ GetAllKeySuccessEvent::GetResult(nsIVariant** /* aResult */)
mCachedValue = OBJECT_TO_JSVAL(array);
if (!keys.IsEmpty()) {
if (!JS_SetArrayLength(cx, array, jsuint(keys.Length()))) {
if (!JS_SetArrayLength(aCx, array, jsuint(keys.Length()))) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array length!");
return NS_ERROR_FAILURE;
}
js::AutoValueRooter value(cx);
js::AutoValueRooter value(aCx);
jsint count = jsint(keys.Length());
@ -584,40 +539,22 @@ GetAllKeySuccessEvent::GetResult(nsIVariant** /* aResult */)
const Key& key = keys[index];
NS_ASSERTION(!key.IsUnset() && !key.IsNull(), "Bad key!");
if (key.IsInt()) {
if (!JS_NewNumberValue(cx, key.IntValue(), value.addr())) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to make number value!");
return NS_ERROR_FAILURE;
}
}
else if (key.IsString()) {
const nsString& keyString = key.StringValue();
JSString* str = JS_NewUCStringCopyN(cx,
reinterpret_cast<const jschar*>(keyString.get()),
keyString.Length());
if (!str) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to make new string value!");
return NS_ERROR_FAILURE;
}
value.set(STRING_TO_JSVAL(str));
}
else {
NS_NOTREACHED("Bad key!");
}
if (!JS_SetElement(cx, array, index, value.addr())) {
nsresult rv = IDBObjectStore::GetJSValFromKey(key, aCx, value.addr());
if (NS_FAILED(rv)) {
mCachedValue = JSVAL_VOID;
NS_ERROR("Failed to set array element!");
NS_WARNING("Failed to get jsval for key!");
return rv;
}
if (!JS_SetElement(aCx, array, index, value.addr())) {
mCachedValue = JSVAL_VOID;
NS_WARNING("Failed to set array element!");
return NS_ERROR_FAILURE;
}
}
}
}
*retval = mCachedValue;
cc->SetReturnValueWasSet(PR_TRUE);
*aResult = mCachedValue;
return NS_OK;
}

Просмотреть файл

@ -50,7 +50,6 @@
#include "nsIRunnable.h"
#include "nsIVariant.h"
#include "jsapi.h"
#include "nsDOMEvent.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
@ -155,7 +154,8 @@ public:
}
}
NS_IMETHOD GetResult(nsIVariant** aResult);
NS_IMETHOD GetResult(JSContext* aCx,
jsval* aResult);
nsresult Init(IDBRequest* aRequest,
IDBTransaction* aTransaction);
@ -179,7 +179,8 @@ public:
}
}
NS_IMETHOD GetResult(nsIVariant** aResult);
NS_IMETHOD GetResult(JSContext* aCx,
jsval* aResult);
private:
nsTArray<nsString> mValues;
@ -196,7 +197,8 @@ public:
}
}
NS_IMETHOD GetResult(nsIVariant** aResult);
NS_IMETHOD GetResult(JSContext* aCx,
jsval* aResult);
private:
nsTArray<Key> mKeys;

Просмотреть файл

@ -311,8 +311,6 @@ IDBIndex::Get(nsIVariant* aKey,
{
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
NS_WARNING("Using a slow path for Get! Fix this now!");
Key key;
nsresult rv = IDBObjectStore::GetKeyFromVariant(aKey, key);
NS_ENSURE_SUCCESS(rv, rv);
@ -340,8 +338,6 @@ IDBIndex::GetObject(nsIVariant* aKey,
{
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
NS_WARNING("Using a slow path for Get! Fix this now!");
Key key;
nsresult rv = IDBObjectStore::GetKeyFromVariant(aKey, key);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -37,29 +37,26 @@
*
* ***** END LICENSE BLOCK ***** */
// XXX remove once we can get jsvals out of XPIDL
#include "jscntxt.h"
#include "jsapi.h"
#include "nsContentUtils.h"
#include "nsJSON.h"
#include "IDBEvents.h"
#include "IDBObjectStore.h"
#include "IDBIndex.h"
#include "nsIIDBDatabaseException.h"
#include "nsIJSContextStack.h"
#include "nsIUUIDGenerator.h"
#include "nsIVariant.h"
#include "jscntxt.h"
#include "mozilla/storage.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfo.h"
#include "nsJSON.h"
#include "nsJSUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "mozilla/storage.h"
#include "AsyncConnectionHelper.h"
#include "IDBCursor.h"
#include "IDBEvents.h"
#include "IDBIndex.h"
#include "IDBKeyRange.h"
#include "IDBTransaction.h"
#include "DatabaseInfo.h"
@ -67,10 +64,6 @@
USING_INDEXEDDB_NAMESPACE
BEGIN_INDEXEDDB_NAMESPACE
END_INDEXEDDB_NAMESPACE
namespace {
class AddHelper : public AsyncConnectionHelper
@ -289,33 +282,10 @@ GetKeyFromObject(JSContext* aCx,
JSBool ok = JS_GetUCProperty(aCx, aObj, keyPathChars, keyPathLen, &key);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
if (JSVAL_IS_VOID(key)) {
aKey = Key::UNSETKEY;
return NS_OK;
}
nsresult rv = IDBObjectStore::GetKeyFromJSVal(key, aKey);
NS_ENSURE_SUCCESS(rv, rv);
if (JSVAL_IS_NULL(key)) {
aKey = Key::NULLKEY;
return NS_OK;
}
if (JSVAL_IS_INT(key)) {
aKey = JSVAL_TO_INT(key);
return NS_OK;
}
if (JSVAL_IS_DOUBLE(key)) {
aKey = *JSVAL_TO_DOUBLE(key);
return NS_OK;
}
if (JSVAL_IS_STRING(key)) {
aKey = nsDependentJSString(key);
return NS_OK;
}
// We only support those types.
return NS_ERROR_INVALID_ARG;
return NS_OK;
}
} // anonymous namespace
@ -385,6 +355,71 @@ IDBObjectStore::GetKeyFromVariant(nsIVariant* aKeyVariant,
return NS_OK;
}
// static
nsresult
IDBObjectStore::GetKeyFromJSVal(jsval aKeyVal,
Key& aKey)
{
if (JSVAL_IS_VOID(aKeyVal)) {
aKey = Key::UNSETKEY;
}
else if (JSVAL_IS_NULL(aKeyVal)) {
aKey = Key::NULLKEY;
}
else if (JSVAL_IS_STRING(aKeyVal)) {
aKey = nsDependentJSString(aKeyVal);
}
else if (JSVAL_IS_INT(aKeyVal)) {
aKey = JSVAL_TO_INT(aKeyVal);
}
else if (JSVAL_IS_DOUBLE(aKeyVal)) {
aKey = *JSVAL_TO_DOUBLE(aKeyVal);
}
else {
return NS_ERROR_INVALID_ARG;
}
return NS_OK;
}
// static
nsresult
IDBObjectStore::GetJSValFromKey(const Key& aKey,
JSContext* aCx,
jsval* aKeyVal)
{
if (aKey.IsUnset()) {
*aKeyVal = JSVAL_VOID;
return NS_OK;
}
if (aKey.IsNull()) {
*aKeyVal = JSVAL_NULL;
return NS_OK;
}
if (aKey.IsInt()) {
JSBool ok = JS_NewNumberValue(aCx, aKey.IntValue(), aKeyVal);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
return NS_OK;
}
if (aKey.IsString()) {
const nsString& keyString = aKey.StringValue();
JSString* str =
JS_NewUCStringCopyN(aCx,
reinterpret_cast<const jschar*>(keyString.get()),
keyString.Length());
NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
*aKeyVal = STRING_TO_JSVAL(str);
return NS_OK;
}
NS_NOTREACHED("Unknown key type!");
return NS_ERROR_INVALID_ARG;
}
// static
nsresult
IDBObjectStore::GetJSONFromArg0(/* jsval arg0, */
@ -473,17 +508,10 @@ IDBObjectStore::GetKeyPathValueFromJSON(const nsAString& aJSON,
value.addr());
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
if (JSVAL_IS_INT(value.value())) {
aValue = JSVAL_TO_INT(value.value());
}
else if (JSVAL_IS_DOUBLE(value.value())) {
aValue = *JSVAL_TO_DOUBLE(value.value());
}
else if (JSVAL_IS_STRING(value.value())) {
aValue = nsDependentJSString(value.value());
}
else {
// If the object doesn't have a value for our index then we leave it unset.
rv = GetKeyFromJSVal(value.value(), aValue);
if (NS_FAILED(rv) || aValue.IsNull()) {
// If the object doesn't have a value that we can use for our index then we
// leave it unset.
aValue = Key::UNSETKEY;
}
@ -521,26 +549,8 @@ IDBObjectStore::GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo,
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
Key value;
if (JSVAL_IS_INT(keyPathValue)) {
value = JSVAL_TO_INT(keyPathValue);
}
else if (JSVAL_IS_DOUBLE(keyPathValue)) {
value = *JSVAL_TO_DOUBLE(keyPathValue);
}
else if (JSVAL_IS_STRING(keyPathValue)) {
JSString* str = JSVAL_TO_STRING(keyPathValue);
size_t len = JS_GetStringLength(str);
if (len) {
const PRUnichar* chars =
reinterpret_cast<PRUnichar*>(JS_GetStringChars(str));
value = nsDependentString(chars, len);
}
else {
value = EmptyString();
}
}
else {
nsresult rv = GetKeyFromJSVal(keyPathValue, value);
if (NS_FAILED(rv) || value.IsUnset() || value.IsNull()) {
// Not a value we can do anything with, ignore it.
continue;
}
@ -708,58 +718,25 @@ IDBObjectStore::~IDBObjectStore()
}
nsresult
IDBObjectStore::GetAddInfo(/* jsval aValue, */
nsIVariant* aKeyVariant,
IDBObjectStore::GetAddInfo(JSContext* aCx,
jsval aValue,
jsval aKeyVal,
nsString& aJSON,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
{
// This is the slow path, need to do this better once XPIDL can have raw
// jsvals as arguments.
NS_WARNING("Using a slow path for Add! Fix this now!");
JSAutoRequest ar(aCx);
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);
PRUint32 argc;
rv = cc->GetArgc(&argc);
NS_ENSURE_SUCCESS(rv, rv);
if (argc < 1) {
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
}
jsval* argv;
rv = cc->GetArgvPtr(&argv);
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.addr());
js::AutoValueRooter clone(aCx);
nsresult rv = nsContentUtils::CreateStructuredClone(aCx, aValue,
clone.addr());
if (NS_FAILED(rv)) {
return rv;
}
if (mKeyPath.IsEmpty()) {
// Key was passed in.
if (argc < 2) {
// Actually, nothing was passed in, and we can skip this.
aKey = Key::UNSETKEY;
}
else {
rv = GetKeyFromVariant(aKeyVariant, aKey);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = GetKeyFromJSVal(aKeyVal, aKey);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// Inline keys live on the object. Make sure it is an object.
@ -767,12 +744,12 @@ IDBObjectStore::GetAddInfo(/* jsval aValue, */
return NS_ERROR_INVALID_ARG;
}
rv = GetKeyFromObject(cx, JSVAL_TO_OBJECT(clone.value()), mKeyPath, aKey);
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(clone.value()), 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() && argc >= 2 && JSVAL_IS_NULL(argv[1])) {
if (aKey.IsUnset() && JSVAL_IS_NULL(aKeyVal)) {
aKey = Key::NULLKEY;
}
}
@ -785,11 +762,11 @@ IDBObjectStore::GetAddInfo(/* jsval aValue, */
ObjectStoreInfo* objectStoreInfo = GetObjectStoreInfo();
NS_ENSURE_TRUE(objectStoreInfo, NS_ERROR_FAILURE);
rv = GetIndexUpdateInfo(objectStoreInfo, cx, clone.value(), aUpdateInfoArray);
rv = GetIndexUpdateInfo(objectStoreInfo, aCx, clone.value(), aUpdateInfoArray);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIJSON> json(new nsJSON());
rv = json->EncodeFromJSVal(clone.addr(), cx, aJSON);
rv = json->EncodeFromJSVal(clone.addr(), aCx, aJSON);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -927,8 +904,10 @@ IDBObjectStore::GetAll(nsIIDBKeyRange* aKeyRange,
}
NS_IMETHODIMP
IDBObjectStore::Add(nsIVariant* /* aValue */,
nsIVariant* aKey,
IDBObjectStore::Add(jsval aValue,
jsval aKey,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -941,11 +920,15 @@ IDBObjectStore::Add(nsIVariant* /* aValue */,
return NS_ERROR_OBJECT_IS_IMMUTABLE;
}
if (aOptionalArgCount < 1) {
aKey = JSVAL_VOID;
}
nsString jsonValue;
Key key;
nsTArray<IndexUpdateInfo> updateInfo;
nsresult rv = GetAddInfo(aKey, jsonValue, key, updateInfo);
nsresult rv = GetAddInfo(aCx, aValue, aKey, jsonValue, key, updateInfo);
if (NS_FAILED(rv)) {
return rv;
}
@ -968,8 +951,10 @@ IDBObjectStore::Add(nsIVariant* /* aValue */,
}
NS_IMETHODIMP
IDBObjectStore::Modify(nsIVariant* /* aValue */,
nsIVariant* aKey,
IDBObjectStore::Modify(jsval aValue,
jsval aKey,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -982,11 +967,15 @@ IDBObjectStore::Modify(nsIVariant* /* aValue */,
return NS_ERROR_OBJECT_IS_IMMUTABLE;
}
if (aOptionalArgCount < 1) {
aKey = JSVAL_VOID;
}
nsString jsonValue;
Key key;
nsTArray<IndexUpdateInfo> updateInfo;
nsresult rv = GetAddInfo(aKey, jsonValue, key, updateInfo);
nsresult rv = GetAddInfo(aCx, aValue, aKey, jsonValue, key, updateInfo);
if (NS_FAILED(rv)) {
return rv;
}
@ -1009,8 +998,10 @@ IDBObjectStore::Modify(nsIVariant* /* aValue */,
}
NS_IMETHODIMP
IDBObjectStore::AddOrModify(nsIVariant* /* aValue */,
nsIVariant* aKey,
IDBObjectStore::AddOrModify(jsval aValue,
jsval aKey,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -1023,11 +1014,15 @@ IDBObjectStore::AddOrModify(nsIVariant* /* aValue */,
return NS_ERROR_OBJECT_IS_IMMUTABLE;
}
if (aOptionalArgCount < 1) {
aKey = JSVAL_VOID;
}
nsString jsonValue;
Key key;
nsTArray<IndexUpdateInfo> updateInfo;
nsresult rv = GetAddInfo(aKey, jsonValue, key, updateInfo);
nsresult rv = GetAddInfo(aCx, aValue, aKey, jsonValue, key, updateInfo);
if (NS_FAILED(rv)) {
return rv;
}

Просмотреть файл

@ -125,6 +125,11 @@ public:
return false;
}
bool operator!=(const Key& aOther) const
{
return !(*this == aOther);
}
bool operator<(const Key& aOther) const
{
switch (mType) {
@ -222,6 +227,15 @@ public:
GetKeyFromVariant(nsIVariant* aKeyVariant,
Key& aKey);
static nsresult
GetKeyFromJSVal(jsval aKeyVal,
Key& aKey);
static nsresult
GetJSValFromKey(const Key& aKey,
JSContext* aCx,
jsval* aKeyVal);
static nsresult
GetJSONFromArg0(/* jsval arg0, */
nsAString& aJSON);
@ -284,8 +298,9 @@ protected:
IDBObjectStore();
~IDBObjectStore();
nsresult GetAddInfo(/* jsval aValue, */
nsIVariant* aKeyVariant,
nsresult GetAddInfo(JSContext* aCx,
jsval aValue,
jsval aKeyVal,
nsString& aJSON,
Key& aKey,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);

Просмотреть файл

@ -42,6 +42,10 @@
interface nsIIDBRequest;
interface nsIVariant;
%{C++
#include "jsapi.h"
%}
/**
* IDBCursor interface. See
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
@ -58,7 +62,8 @@ interface nsIIDBCursor : nsISupports
readonly attribute nsIVariant key;
readonly attribute nsIVariant value;
[implicit_jscontext]
readonly attribute jsval value;
// Returns true always for non-preloaded cursors. Calling continue means that
// the same onsuccess function will be called again with the new key/value
@ -67,11 +72,12 @@ interface nsIIDBCursor : nsISupports
// For preloaded cursors returns true if key/value have been set to new
// values. If false then no more matches are available and getting the key,
// value property will throw, as will calling update() and remove().
[optional_argc]
boolean continue([optional /* null */] in nsIVariant key);
[implicit_jscontext, optional_argc]
boolean continue([optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == key
nsIIDBRequest update(in nsIVariant value);
[implicit_jscontext]
nsIIDBRequest update(in jsval value);
// Success fires IDBTransactionEvent, result == null
nsIIDBRequest remove();

Просмотреть файл

@ -45,6 +45,10 @@ interface nsIIDBRequest;
interface nsIVariant;
interface nsIDOMDOMStringList;
%{C++
#include "jsapi.h"
%}
/**
* nsIIDBObjectStore interface. See
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
@ -70,19 +74,22 @@ interface nsIIDBObjectStore : nsISupports
[optional /* unlimited */] in unsigned long limit);
// Success fires IDBTransactionEvent, result == key
[implicit_jscontext, optional_argc]
nsIIDBRequest
add(in nsIVariant value,
[optional /* null */] in nsIVariant key);
add(in jsval value,
[optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == key
[implicit_jscontext, optional_argc]
nsIIDBRequest
modify(in nsIVariant value,
[optional /* null */] in nsIVariant key);
modify(in jsval value,
[optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == key
[implicit_jscontext, optional_argc]
nsIIDBRequest
addOrModify(in nsIVariant value,
[optional /* null */] in nsIVariant key);
addOrModify(in jsval value,
[optional /* undefined */] in jsval key);
// Success fires IDBTransactionEvent, result == null
nsIIDBRequest

Просмотреть файл

@ -39,10 +39,13 @@
#include "nsIIDBEvent.idl"
interface nsIVariant;
%{C++
#include "jsapi.h"
%}
[scriptable, uuid(9275d34f-54e1-4ab0-b4ca-f8d4359eec9c)]
interface nsIIDBSuccessEvent : nsIIDBEvent
{
readonly attribute nsIVariant result;
[implicit_jscontext]
readonly attribute jsval result;
};

Просмотреть файл

@ -469,20 +469,10 @@ members = [
'nsIIDBKeyRange.*',
'nsIIDBObjectStore.*',
'nsIIDBRequest.*',
# Remove once XPIDL can handle jsvals
# 'nsIIDBSuccessEvent.*',
'nsIIDBSuccessEvent.*',
'nsIIDBTransaction.*',
'nsIIDBTransactionEvent.*',
'nsIIDBFactory.*',
# Remove once XPIDL can handle jsvals
'-nsIIDBObjectStore.add',
'-nsIIDBObjectStore.modify',
'-nsIIDBObjectStore.addOrModify',
'-nsIIDBCursor.continue',
'-nsIIDBCursor.value',
'-nsIIDBCursor.update',
'-nsIIDBIndex.openCursor',
'-nsIIDBIndex.openObjectCursor'
]
# Most interfaces can be found by searching the includePath; to find