Title: [124361] trunk
Revision
124361
Author
[email protected]
Date
2012-08-01 13:20:53 -0700 (Wed, 01 Aug 2012)

Log Message

IndexedDB: IDBCursor.continue(key) does not throw for key "behind" cursor
https://bugs.webkit.org/show_bug.cgi?id=92562

Reviewed by Ojan Vafai.

Source/WebCore:

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.

LayoutTests:

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):

Modified Paths

Added Paths

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());
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to