author | Bevis Tseng <btseng@mozilla.com> |
Thu, 21 Jul 2016 16:31:59 +0800 | |
changeset 351544 | 91c0b3e808250c412e99012540e766a551e69483 |
parent 351543 | cc4286c4da37de45da2de785bb2a314ea4fba083 |
child 351545 | b531c8bff6e905a1255936f057cad47760c364a9 |
push id | 1324 |
push user | mtabara@mozilla.com |
push date | Mon, 16 Jan 2017 13:07:44 +0000 |
treeherder | mozilla-release@a01c49833940 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | khuey |
bugs | 1271506 |
milestone | 51.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
|
--- a/dom/indexedDB/ActorsChild.cpp +++ b/dom/indexedDB/ActorsChild.cpp @@ -2486,16 +2486,20 @@ BackgroundRequestChild::Recv__delete__(c case RequestResponse::TObjectStorePutResponse: HandleResponse(aResponse.get_ObjectStorePutResponse().key()); break; case RequestResponse::TObjectStoreGetResponse: HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo()); break; + case RequestResponse::TObjectStoreGetKeyResponse: + HandleResponse(aResponse.get_ObjectStoreGetKeyResponse().key()); + break; + case RequestResponse::TObjectStoreGetAllResponse: HandleResponse(aResponse.get_ObjectStoreGetAllResponse().cloneInfos()); break; case RequestResponse::TObjectStoreGetAllKeysResponse: HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys()); break;
--- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -8180,33 +8180,34 @@ private: virtual nsresult DoDatabaseWork(DatabaseConnection* aConnection) override; virtual void GetResponse(RequestResponse& aResponse) override; }; -class ObjectStoreGetAllKeysRequestOp final +class ObjectStoreGetKeyRequestOp final : public NormalTransactionOp { friend class TransactionBase; - const ObjectStoreGetAllKeysParams mParams; + const uint32_t mObjectStoreId; + const OptionalKeyRange mOptionalKeyRange; + const uint32_t mLimit; + const bool mGetAll; FallibleTArray<Key> mResponse; private: // Only created by TransactionBase. - ObjectStoreGetAllKeysRequestOp(TransactionBase* aTransaction, - const ObjectStoreGetAllKeysParams& aParams) - : NormalTransactionOp(aTransaction) - , mParams(aParams) - { } - - ~ObjectStoreGetAllKeysRequestOp() + ObjectStoreGetKeyRequestOp(TransactionBase* aTransaction, + const RequestParams& aParams, + bool aGetAll); + + ~ObjectStoreGetKeyRequestOp() { } virtual nsresult DoDatabaseWork(DatabaseConnection* aConnection) override; virtual void GetResponse(RequestResponse& aResponse) override; }; @@ -14524,16 +14525,32 @@ TransactionBase::VerifyRequestParams(con } if (NS_WARN_IF(!VerifyRequestParams(params.keyRange()))) { ASSERT_UNLESS_FUZZING(); return false; } break; } + case RequestParams::TObjectStoreGetKeyParams: { + const ObjectStoreGetKeyParams& params = + aParams.get_ObjectStoreGetKeyParams(); + const RefPtr<FullObjectStoreMetadata> objectStoreMetadata = + GetMetadataForObjectStoreId(params.objectStoreId()); + if (NS_WARN_IF(!objectStoreMetadata)) { + ASSERT_UNLESS_FUZZING(); + return false; + } + if (NS_WARN_IF(!VerifyRequestParams(params.keyRange()))) { + ASSERT_UNLESS_FUZZING(); + return false; + } + break; + } + case RequestParams::TObjectStoreGetAllParams: { const ObjectStoreGetAllParams& params = aParams.get_ObjectStoreGetAllParams(); const RefPtr<FullObjectStoreMetadata> objectStoreMetadata = GetMetadataForObjectStoreId(params.objectStoreId()); if (NS_WARN_IF(!objectStoreMetadata)) { ASSERT_UNLESS_FUZZING(); return false; @@ -14986,20 +15003,24 @@ TransactionBase::AllocRequest(const Requ new ObjectStoreGetRequestOp(this, aParams, /* aGetAll */ false); break; case RequestParams::TObjectStoreGetAllParams: actor = new ObjectStoreGetRequestOp(this, aParams, /* aGetAll */ true); break; + case RequestParams::TObjectStoreGetKeyParams: + actor = + new ObjectStoreGetKeyRequestOp(this, aParams, /* aGetAll */ false); + break; + case RequestParams::TObjectStoreGetAllKeysParams: actor = - new ObjectStoreGetAllKeysRequestOp(this, - aParams.get_ObjectStoreGetAllKeysParams()); + new ObjectStoreGetKeyRequestOp(this, aParams, /* aGetAll */ true); break; case RequestParams::TObjectStoreDeleteParams: actor = new ObjectStoreDeleteRequestOp(this, aParams.get_ObjectStoreDeleteParams()); break; @@ -25887,67 +25908,88 @@ ObjectStoreGetRequestOp::GetResponse(Req nsresult rv = ConvertResponse(0, serializedInfo); if (NS_WARN_IF(NS_FAILED(rv))) { aResponse = rv; } } } -nsresult -ObjectStoreGetAllKeysRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) +ObjectStoreGetKeyRequestOp::ObjectStoreGetKeyRequestOp( + TransactionBase* aTransaction, + const RequestParams& aParams, + bool aGetAll) + : NormalTransactionOp(aTransaction) + , mObjectStoreId(aGetAll ? + aParams.get_ObjectStoreGetAllKeysParams().objectStoreId() : + aParams.get_ObjectStoreGetKeyParams().objectStoreId()) + , mOptionalKeyRange(aGetAll ? + aParams.get_ObjectStoreGetAllKeysParams() + .optionalKeyRange() : + OptionalKeyRange(aParams.get_ObjectStoreGetKeyParams() + .keyRange())) + , mLimit(aGetAll ? aParams.get_ObjectStoreGetAllKeysParams().limit() : 1) + , mGetAll(aGetAll) +{ + MOZ_ASSERT(aParams.type() == RequestParams::TObjectStoreGetKeyParams || + aParams.type() == RequestParams::TObjectStoreGetAllKeysParams); + MOZ_ASSERT(mObjectStoreId); + MOZ_ASSERT_IF(!aGetAll, + mOptionalKeyRange.type() == + OptionalKeyRange::TSerializedKeyRange); +} + +nsresult +ObjectStoreGetKeyRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) { MOZ_ASSERT(aConnection); aConnection->AssertIsOnConnectionThread(); PROFILER_LABEL("IndexedDB", - "ObjectStoreGetAllKeysRequestOp::DoDatabaseWork", + "ObjectStoreGetKeyRequestOp::DoDatabaseWork", js::ProfileEntry::Category::STORAGE); const bool hasKeyRange = - mParams.optionalKeyRange().type() == OptionalKeyRange::TSerializedKeyRange; + mOptionalKeyRange.type() == OptionalKeyRange::TSerializedKeyRange; nsAutoCString keyRangeClause; if (hasKeyRange) { - GetBindingClauseForKeyRange( - mParams.optionalKeyRange().get_SerializedKeyRange(), - NS_LITERAL_CSTRING("key"), - keyRangeClause); + GetBindingClauseForKeyRange(mOptionalKeyRange.get_SerializedKeyRange(), + NS_LITERAL_CSTRING("key"), + keyRangeClause); } nsAutoCString limitClause; - if (uint32_t limit = mParams.limit()) { + if (mLimit) { limitClause.AssignLiteral(" LIMIT "); - limitClause.AppendInt(limit); + limitClause.AppendInt(mLimit); } nsCString query = NS_LITERAL_CSTRING("SELECT key " "FROM object_data " "WHERE object_store_id = :osid") + keyRangeClause + NS_LITERAL_CSTRING(" ORDER BY key ASC") + limitClause; DatabaseConnection::CachedStatement stmt; nsresult rv = aConnection->GetCachedStatement(query, &stmt); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), - mParams.objectStoreId()); + rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mObjectStoreId); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (hasKeyRange) { - rv = BindKeyRangeToStatement( - mParams.optionalKeyRange().get_SerializedKeyRange(), - stmt); + rv = BindKeyRangeToStatement(mOptionalKeyRange.get_SerializedKeyRange(), + stmt); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } bool hasResult; while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { Key* key = mResponse.AppendElement(fallible); @@ -25960,28 +26002,42 @@ ObjectStoreGetAllKeysRequestOp::DoDataba return rv; } } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - return NS_OK; -} - -void -ObjectStoreGetAllKeysRequestOp::GetResponse(RequestResponse& aResponse) -{ - aResponse = ObjectStoreGetAllKeysResponse(); + MOZ_ASSERT_IF(!mGetAll, mResponse.Length() <= 1); + + return NS_OK; +} + +void +ObjectStoreGetKeyRequestOp::GetResponse(RequestResponse& aResponse) +{ + MOZ_ASSERT_IF(mLimit, mResponse.Length() <= mLimit); + + if (mGetAll) { + aResponse = ObjectStoreGetAllKeysResponse(); + + if (!mResponse.IsEmpty()) { + nsTArray<Key>& response = + aResponse.get_ObjectStoreGetAllKeysResponse().keys(); + mResponse.SwapElements(response); + } + + return; + } + + aResponse = ObjectStoreGetKeyResponse(); if (!mResponse.IsEmpty()) { - nsTArray<Key>& response = - aResponse.get_ObjectStoreGetAllKeysResponse().keys(); - mResponse.SwapElements(response); + aResponse.get_ObjectStoreGetKeyResponse().key() = Move(mResponse[0]); } } ObjectStoreDeleteRequestOp::ObjectStoreDeleteRequestOp( TransactionBase* aTransaction, const ObjectStoreDeleteParams& aParams) : NormalTransactionOp(aTransaction) , mParams(aParams)
--- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -1697,19 +1697,20 @@ IDBObjectStore::IndexNames() listNames.InsertElementSorted(indexes[index].name()); } } return list.forget(); } already_AddRefed<IDBRequest> -IDBObjectStore::Get(JSContext* aCx, - JS::Handle<JS::Value> aKey, - ErrorResult& aRv) +IDBObjectStore::GetInternal(bool aKeyOnly, + JSContext* aCx, + JS::Handle<JS::Value> aKey, + ErrorResult& aRv) { AssertIsOnOwningThread(); if (mDeletedSpec) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } @@ -1725,19 +1726,27 @@ IDBObjectStore::Get(JSContext* aCx, } if (!keyRange) { // Must specify a key or keyRange for get(). aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return nullptr; } - ObjectStoreGetParams params; - params.objectStoreId() = Id(); - keyRange->ToSerialized(params.keyRange()); + const int64_t id = Id(); + + SerializedKeyRange serializedKeyRange; + keyRange->ToSerialized(serializedKeyRange); + + RequestParams params; + if (aKeyOnly) { + params = ObjectStoreGetKeyParams(id, serializedKeyRange); + } else { + params = ObjectStoreGetParams(id, serializedKeyRange); + } RefPtr<IDBRequest> request = GenerateRequest(aCx, this); MOZ_ASSERT(request); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).get(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.get()", IDB_LOG_ID_STRING(),
--- a/dom/indexedDB/IDBObjectStore.h +++ b/dom/indexedDB/IDBObjectStore.h @@ -198,17 +198,34 @@ public: ErrorResult& aRv) { AssertIsOnOwningThread(); return DeleteInternal(aCx, aKey, /* aFromCursor */ false, aRv); } already_AddRefed<IDBRequest> - Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv); + Get(JSContext* aCx, + JS::Handle<JS::Value> aKey, + ErrorResult& aRv) + { + AssertIsOnOwningThread(); + + return GetInternal(/* aKeyOnly */ false, aCx, aKey, aRv); + } + + already_AddRefed<IDBRequest> + GetKey(JSContext* aCx, + JS::Handle<JS::Value> aKey, + ErrorResult& aRv) + { + AssertIsOnOwningThread(); + + return GetInternal(/* aKeyOnly */ true, aCx, aKey, aRv); + } already_AddRefed<IDBRequest> Clear(JSContext* aCx, ErrorResult& aRv); already_AddRefed<IDBIndex> CreateIndex(const nsAString& aName, const StringOrStringSequence& aKeyPath, const IDBIndexParameters& aOptionalParameters, @@ -329,16 +346,22 @@ private: already_AddRefed<IDBRequest> DeleteInternal(JSContext* aCx, JS::Handle<JS::Value> aKey, bool aFromCursor, ErrorResult& aRv); already_AddRefed<IDBRequest> + GetInternal(bool aKeyOnly, + JSContext* aCx, + JS::Handle<JS::Value> aKey, + ErrorResult& aRv); + + already_AddRefed<IDBRequest> GetAllInternal(bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aKey, const Optional<uint32_t>& aLimit, ErrorResult& aRv); already_AddRefed<IDBRequest> OpenCursorInternal(bool aKeysOnly,
--- a/dom/indexedDB/PBackgroundIDBRequest.ipdl +++ b/dom/indexedDB/PBackgroundIDBRequest.ipdl @@ -31,16 +31,21 @@ struct ObjectStorePutResponse Key key; }; struct ObjectStoreGetResponse { SerializedStructuredCloneReadInfo cloneInfo; }; +struct ObjectStoreGetKeyResponse +{ + Key key; +}; + struct ObjectStoreGetAllResponse { SerializedStructuredCloneReadInfo[] cloneInfos; }; struct ObjectStoreGetAllKeysResponse { Key[] keys; @@ -81,16 +86,17 @@ struct IndexCountResponse { uint64_t count; }; union RequestResponse { nsresult; ObjectStoreGetResponse; + ObjectStoreGetKeyResponse; ObjectStoreAddResponse; ObjectStorePutResponse; ObjectStoreDeleteResponse; ObjectStoreClearResponse; ObjectStoreCountResponse; ObjectStoreGetAllResponse; ObjectStoreGetAllKeysResponse; IndexGetResponse;
--- a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh +++ b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh @@ -182,16 +182,22 @@ struct ObjectStorePutParams }; struct ObjectStoreGetParams { int64_t objectStoreId; SerializedKeyRange keyRange; }; +struct ObjectStoreGetKeyParams +{ + int64_t objectStoreId; + SerializedKeyRange keyRange; +}; + struct ObjectStoreGetAllParams { int64_t objectStoreId; OptionalKeyRange optionalKeyRange; uint32_t limit; }; struct ObjectStoreGetAllKeysParams @@ -255,16 +261,17 @@ struct IndexCountParams OptionalKeyRange optionalKeyRange; }; union RequestParams { ObjectStoreAddParams; ObjectStorePutParams; ObjectStoreGetParams; + ObjectStoreGetKeyParams; ObjectStoreGetAllParams; ObjectStoreGetAllKeysParams; ObjectStoreDeleteParams; ObjectStoreClearParams; ObjectStoreCountParams; IndexGetParams; IndexGetKeyParams; IndexGetAllParams;
--- a/dom/webidl/IDBObjectStore.webidl +++ b/dom/webidl/IDBObjectStore.webidl @@ -32,16 +32,19 @@ interface IDBObjectStore { [Throws] IDBRequest delete (any key); [Throws] IDBRequest get (any key); [Throws] + IDBRequest getKey (any key); + + [Throws] IDBRequest clear (); [Throws] IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next"); [Throws] IDBIndex createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters);
--- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -12201,16 +12201,24 @@ "path": "IndexedDB/idbobjectstore_get7.htm", "url": "/IndexedDB/idbobjectstore_get7.htm" }, { "path": "IndexedDB/idbobjectstore_getAll.html", "url": "/IndexedDB/idbobjectstore_getAll.html" }, { + "path": "IndexedDB/idbobjectstore_getKey.htm", + "url": "/IndexedDB/idbobjectstore_getKey.htm" + }, + { + "path": "IndexedDB/idbobjectstore_getKey_exception_order.htm", + "url": "/IndexedDB/idbobjectstore_getKey_exception_order.htm" + }, + { "path": "IndexedDB/idbobjectstore_getAllKeys.html", "url": "/IndexedDB/idbobjectstore_getAllKeys.html" }, { "path": "IndexedDB/idbobjectstore_index.htm", "url": "/IndexedDB/idbobjectstore_index.htm" }, {
new file mode 100644 --- /dev/null +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey.htm @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>IDBObjectStore.getKey()</title> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="http://w3c.github.io/IndexedDB/#dom-idbobjectstore-getkey"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support.js"></script> + +<script> +indexeddb_test( + function(t, db, txn) { + var os = db.createObjectStore("store"); + + for(var i = 3; i < 6; i++) { + os.add("data" + i, i); + } + }, + function(t, db) { + var os = db.transaction("store").objectStore("store"); + var req1 = os.getKey(IDBKeyRange.lowerBound(6)); + + req1.onerror = t.unreached_func('getKey request should succeed'); + req1.onsuccess = t.step_func(function(e) { + assert_equals(e.target.result, undefined, "Record should not exist - lowerBound(6)"); + }); + + var req2 = os.getKey(IDBKeyRange.upperBound(2)); + + req2.onerror = t.unreached_func('getKey request should succeed'); + req2.onsuccess = t.step_func(function(e) { + assert_equals(e.target.result, undefined, "Record should not exist - upperBound(2)"); + t.done(); + }); + }, + "Attempt to retrieve a record that doesn't exist" +); + +indexeddb_test( + function(t, db, txn) { + var os = db.createObjectStore("store"); + + for(var i = 3; i < 6; i++) { + os.add("data" + i, i); + } + }, + function(t, db) { + var os = db.transaction("store").objectStore("store"); + var req = os.getKey(IDBKeyRange.bound(0, 10)); + + req.onerror = t.unreached_func('getKey request should succeed'); + req.onsuccess = t.step_func(function(e) { + assert_equals(e.target.result, 3, "getKey(0-10)"); + t.done(); + }); + }, + "Returns the first key in the range" +); +</script> + +<div id="log"></div> \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getKey_exception_order.htm @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>IDBObjectStore.getKey() - Exception Orders</title> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="http://w3c.github.io/IndexedDB/#dom-idbobjectstore-getkey"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support.js"></script> + +<script> +indexeddb_test( + function(t, db, txn) { + var deletedObjectStore = db.createObjectStore("s"); + db.deleteObjectStore("s"); + txn.oncomplete = function() { + assert_throws("InvalidStateError", function() { + deletedObjectStore.getKey(1); + }, "Deletion check should precede transaction-state check"); + t.done(); + }; + }, + null, + "InvalidStateError(Deleted ObjectStore) vs. TransactionInactiveError" +); + +indexeddb_test( + function(t, db, txn) { + var store = db.createObjectStore("s"); + txn.oncomplete = function() { + assert_throws("TransactionInactiveError", function() { + store.getKey(null); + }, "Transaction-state check should precede key range check"); + t.done(); + }; + }, + null, + "TransactionInactiveError vs. DataError" +); + +indexeddb_test( + function(t, db, txn) { + var store = db.createObjectStore("s"); + assert_throws("DataError", function() { + store.getKey(null); + }, "key range check"); + t.done(); + }, + null, + "DataError" +); +</script> + +<div id="log"></div>
--- a/testing/web-platform/tests/IndexedDB/interfaces.idl +++ b/testing/web-platform/tests/IndexedDB/interfaces.idl @@ -93,16 +93,17 @@ interface IDBObjectStore { readonly attribute any keyPath; readonly attribute DOMStringList indexNames; readonly attribute IDBTransaction transaction; readonly attribute boolean autoIncrement; IDBRequest put (any value, optional any key); IDBRequest add (any value, optional any key); IDBRequest delete (any key); IDBRequest get (any key); + IDBRequest getKey (any key); IDBRequest clear (); IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next"); IDBIndex createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters); IDBIndex index (DOMString name); void deleteIndex (DOMString indexName); IDBRequest count (optional any key); };