Diff
Modified: trunk/LayoutTests/ChangeLog (124360 => 124361)
--- trunk/LayoutTests/ChangeLog 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/LayoutTests/ChangeLog 2012-08-01 20:20:53 UTC (rev 124361)
@@ -1,3 +1,25 @@
+2012-08-01 Joshua Bell <[email protected]>
+
+ IndexedDB: IDBCursor.continue(key) does not throw for key "behind" cursor
+ https://bugs.webkit.org/show_bug.cgi?id=92562
+
+ Reviewed by Ojan Vafai.
+
+ Ensure cursor.continue(key) throws if key is "behind" the cursor.
+
+ * storage/indexeddb/cursor-continue-dir-expected.txt: Added.
+ * storage/indexeddb/cursor-continue-dir.html: Added.
+ * storage/indexeddb/resources/cursor-continue-dir.js: Added.
+ (test.request.onsuccess.request.onsuccess.request.onsuccess):
+ (test.request.onsuccess.request.onsuccess):
+ (test.request.onsuccess):
+ (test):
+ (testCursors):
+ (testForwardCursor.request.onsuccess):
+ (testForwardCursor):
+ (testReverseCursor.request.onsuccess):
+ (testReverseCursor):
+
2012-08-01 Rick Byers <[email protected]>
Make Gesture click test validate click count in UIEvent.detail
Added: trunk/LayoutTests/storage/indexeddb/cursor-continue-dir-expected.txt (0 => 124361)
--- trunk/LayoutTests/storage/indexeddb/cursor-continue-dir-expected.txt (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/cursor-continue-dir-expected.txt 2012-08-01 20:20:53 UTC (rev 124361)
@@ -0,0 +1,47 @@
+Test that continue() calls against cursors are validated by direction.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+dbname = self.location.pathname
+indexedDB.deleteDatabase(dbname)
+request = indexedDB.open(dbname)
+db = request.result
+db.setVersion('1')
+store = db.createObjectStore('store')
+store.put(1,1)
+store.put(2,2)
+store.put(3,3)
+store.put(4,4)
+store.put(5,5)
+store.put(6,6)
+store.put(7,7)
+store.put(8,8)
+store.put(9,9)
+store.put(10,10)
+trans = db.transaction('store')
+store = trans.objectStore('store')
+request = store.openCursor(IDBKeyRange.bound(-Infinity, Infinity), 'next')
+cursor = request.result
+PASS cursor is non-null.
+Expect DataError if: The parameter is less than or equal to this cursor's position and this cursor's direction is "next" or "nextunique".
+PASS cursor.key is 1
+Expecting exception from cursor.continue(-1)
+PASS Exception was thrown.
+PASS code is IDBDatabaseException.DATA_ERR
+PASS ename is 'DataError'
+request = store.openCursor(IDBKeyRange.bound(-Infinity, Infinity), 'prev')
+cursor = request.result
+PASS cursor is non-null.
+Expect DataError if: The parameter is greater than or equal to this cursor's position and this cursor's direction is "prev" or "prevunique".
+PASS cursor.key is 10
+Expecting exception from cursor.continue(11)
+PASS Exception was thrown.
+PASS code is IDBDatabaseException.DATA_ERR
+PASS ename is 'DataError'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/storage/indexeddb/cursor-continue-dir.html (0 => 124361)
--- trunk/LayoutTests/storage/indexeddb/cursor-continue-dir.html (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/cursor-continue-dir.html 2012-08-01 20:20:53 UTC (rev 124361)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/storage/indexeddb/resources/cursor-continue-dir.js (0 => 124361)
--- trunk/LayoutTests/storage/indexeddb/resources/cursor-continue-dir.js (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/cursor-continue-dir.js 2012-08-01 20:20:53 UTC (rev 124361)
@@ -0,0 +1,75 @@
+if (this.importScripts) {
+ importScripts('../../../fast/js/resources/js-test-pre.js');
+ importScripts('shared.js');
+}
+
+description("Test that continue() calls against cursors are validated by direction.");
+
+function test()
+{
+ removeVendorPrefixes();
+ evalAndLog("dbname = self.location.pathname");
+ request = evalAndLog("indexedDB.deleteDatabase(dbname)");
+ request._onerror_ = unexpectedErrorCallback;
+ request._onblocked_ = unexpectedBlockedCallback;
+ request._onsuccess_ = function() {
+ evalAndLog("request = indexedDB.open(dbname)");
+ request._onerror_ = unexpectedErrorCallback;
+ request._onsuccess_ = function() {
+ evalAndLog("db = request.result");
+ request = evalAndLog("db.setVersion('1')");
+ request._onerror_ = unexpectedErrorCallback;
+ request._onblocked_ = unexpectedBlockedCallback;
+ request._onsuccess_ = function() {
+ trans = request.result;
+ trans._onabort_ = unexpectedAbortCallback;
+
+ evalAndLog("store = db.createObjectStore('store')");
+ for (i = 1; i <= 10; ++i) {
+ evalAndLog("store.put(" + i + "," + i + ")");
+ }
+
+ trans._oncomplete_ = testCursors;
+ };
+ };
+ };
+}
+
+function testCursors()
+{
+ evalAndLog("trans = db.transaction('store')");
+ evalAndLog("store = trans.objectStore('store')");
+ testForwardCursor();
+}
+
+function testForwardCursor()
+{
+ evalAndLog("request = store.openCursor(IDBKeyRange.bound(-Infinity, Infinity), 'next')");
+ request._onerror_ = unexpectedErrorCallback;
+ request._onsuccess_ = function() {
+ evalAndLog("cursor = request.result");
+ shouldBeNonNull("cursor");
+ debug("Expect DataError if: The parameter is less than or equal to this cursor's position and this cursor's direction is \"next\" or \"nextunique\".");
+ shouldBe("cursor.key", "1");
+ evalAndExpectException("cursor.continue(-1)", "IDBDatabaseException.DATA_ERR", "'DataError'");
+
+ testReverseCursor();
+ };
+}
+
+function testReverseCursor()
+{
+ evalAndLog("request = store.openCursor(IDBKeyRange.bound(-Infinity, Infinity), 'prev')");
+ request._onerror_ = unexpectedErrorCallback;
+ request._onsuccess_ = function() {
+ evalAndLog("cursor = request.result");
+ shouldBeNonNull("cursor");
+ debug("Expect DataError if: The parameter is greater than or equal to this cursor's position and this cursor's direction is \"prev\" or \"prevunique\".");
+ shouldBe("cursor.key", "10");
+ evalAndExpectException("cursor.continue(11)", "IDBDatabaseException.DATA_ERR", "'DataError'");
+
+ finishJSTest();
+ };
+}
+
+test();
Modified: trunk/Source/WebCore/ChangeLog (124360 => 124361)
--- trunk/Source/WebCore/ChangeLog 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/ChangeLog 2012-08-01 20:20:53 UTC (rev 124361)
@@ -1,3 +1,31 @@
+2012-08-01 Joshua Bell <[email protected]>
+
+ IndexedDB: IDBCursor.continue(key) does not throw for key "behind" cursor
+ https://bugs.webkit.org/show_bug.cgi?id=92562
+
+ Reviewed by Ojan Vafai.
+
+ Per spec, IDBCursor.continue(key) should throw for forward cursors
+ if key <= current key, and for reverse cursors if key >= current key.
+ Code was present on the back end but the error code was ignored, possibly
+ broken in a recent refactor, and there were no tests for this case.
+
+ Test: storage/indexeddb/cursor-continue-dir.html
+
+ * Modules/indexeddb/IDBCursor.cpp:
+ (WebCore::IDBCursor::advance): Handle async transaction termination.
+ (WebCore::IDBCursor::continueFunction): Move checks here from backend.
+ * Modules/indexeddb/IDBCursorBackendImpl.cpp:
+ (WebCore::IDBCursorBackendImpl::IDBCursorBackendImpl): Don't need direction param.
+ (WebCore::IDBCursorBackendImpl::continueFunction): Remove checks.
+ * Modules/indexeddb/IDBCursorBackendImpl.h: Only IDBBackingStore::cursor needs direction now.
+ (WebCore::IDBCursorBackendImpl::create):
+ (IDBCursorBackendImpl):
+ * Modules/indexeddb/IDBIndexBackendImpl.cpp:
+ (WebCore::IDBIndexBackendImpl::openCursorInternal): Drop unused param.
+ * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp:
+ (WebCore::IDBObjectStoreBackendImpl::openCursorInternal): Ditto.
+
2012-08-01 Rick Byers <[email protected]>
Don't request a clickCount of 1 on mouseMove event generated by tap gestures
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (124360 => 124361)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp 2012-08-01 20:20:53 UTC (rev 124361)
@@ -183,6 +183,8 @@
m_request->setPendingCursor(this);
m_gotValue = false;
m_backend->advance(count, m_request, ec);
+ if (ec)
+ m_request->markEarlyDeath();
}
void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionCode& ec)
@@ -203,11 +205,28 @@
return;
}
+ if (key) {
+ ASSERT(m_currentKey);
+ if (m_direction == IDBCursor::NEXT || m_direction == IDBCursor::NEXT_NO_DUPLICATE) {
+ if (!m_currentKey->isLessThan(key.get())) {
+ ec = IDBDatabaseException::DATA_ERR;
+ return;
+ }
+ } else {
+ if (!key->isLessThan(m_currentKey.get())) {
+ ec = IDBDatabaseException::DATA_ERR;
+ return;
+ }
+ }
+ }
+
// FIXME: We're not using the context from when continue was called, which means the callback
// will be on the original context openCursor was called on. Is this right?
m_request->setPendingCursor(this);
m_gotValue = false;
m_backend->continueFunction(key, m_request, ec);
+ if (ec)
+ m_request->markEarlyDeath();
}
PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ScriptExecutionContext* context, ExceptionCode& ec)
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp (124360 => 124361)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.cpp 2012-08-01 20:20:53 UTC (rev 124361)
@@ -42,9 +42,8 @@
namespace WebCore {
-IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor> cursor, IDBCursor::Direction direction, CursorType cursorType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore)
+IDBCursorBackendImpl::IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore)
: m_cursor(cursor)
- , m_direction(direction)
, m_cursorType(cursorType)
, m_transaction(transaction)
, m_objectStore(objectStore)
@@ -88,21 +87,6 @@
IDB_TRACE("IDBCursorBackendImpl::continue");
RefPtr<IDBKey> key = prpKey;
- if (m_cursor && key) {
- ASSERT(m_cursor->key());
- if (m_direction == IDBCursor::NEXT || m_direction == IDBCursor::NEXT_NO_DUPLICATE) {
- if (!m_cursor->key()->isLessThan(key.get())) {
- ec = IDBDatabaseException::DATA_ERR;
- return;
- }
- } else {
- if (!key->isLessThan(m_cursor->key().get())) {
- ec = IDBDatabaseException::DATA_ERR;
- return;
- }
- }
- }
-
if (!m_transaction->scheduleTask(createCallbackTask(&IDBCursorBackendImpl::continueFunctionInternal, this, key, prpCallbacks)))
ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR;
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.h (124360 => 124361)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.h 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursorBackendImpl.h 2012-08-01 20:20:53 UTC (rev 124361)
@@ -47,9 +47,9 @@
class IDBCursorBackendImpl : public IDBCursorBackendInterface {
public:
- static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBBackingStore::Cursor> cursor, IDBCursor::Direction direction, CursorType cursorType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore)
+ static PassRefPtr<IDBCursorBackendImpl> create(PassRefPtr<IDBBackingStore::Cursor> cursor, CursorType cursorType, IDBTransactionBackendImpl* transaction, IDBObjectStoreBackendImpl* objectStore)
{
- return adoptRef(new IDBCursorBackendImpl(cursor, direction, cursorType, transaction, objectStore));
+ return adoptRef(new IDBCursorBackendImpl(cursor, cursorType, transaction, objectStore));
}
virtual ~IDBCursorBackendImpl();
@@ -67,7 +67,7 @@
void close();
private:
- IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor>, IDBCursor::Direction, CursorType, IDBTransactionBackendImpl*, IDBObjectStoreBackendImpl*);
+ IDBCursorBackendImpl(PassRefPtr<IDBBackingStore::Cursor>, CursorType, IDBTransactionBackendImpl*, IDBObjectStoreBackendImpl*);
static void advanceInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, unsigned long, PassRefPtr<IDBCallbacks>);
static void continueFunctionInternal(ScriptExecutionContext*, PassRefPtr<IDBCursorBackendImpl>, PassRefPtr<IDBKey>, PassRefPtr<IDBCallbacks>);
@@ -75,7 +75,6 @@
RefPtr<IDBBackingStore::Cursor> m_cursor;
RefPtr<IDBBackingStore::Cursor> m_savedCursor;
- IDBCursor::Direction m_direction;
CursorType m_cursorType;
RefPtr<IDBTransactionBackendImpl> m_transaction;
RefPtr<IDBObjectStoreBackendImpl> m_objectStore;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBIndexBackendImpl.cpp (124360 => 124361)
--- trunk/Source/WebCore/Modules/indexeddb/IDBIndexBackendImpl.cpp 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBIndexBackendImpl.cpp 2012-08-01 20:20:53 UTC (rev 124361)
@@ -99,7 +99,7 @@
return;
}
- RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.get(), direction, cursorType, transaction.get(), index->m_objectStoreBackend);
+ RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.get(), cursorType, transaction.get(), index->m_objectStoreBackend);
callbacks->onSuccess(cursor.release());
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp (124360 => 124361)
--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp 2012-08-01 20:14:01 UTC (rev 124360)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp 2012-08-01 20:20:53 UTC (rev 124361)
@@ -539,7 +539,7 @@
return;
}
- RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), direction, IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
+ RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(backingStoreCursor.release(), IDBCursorBackendInterface::ObjectStoreCursor, transaction.get(), objectStore.get());
callbacks->onSuccess(cursor.release());
}