Modified: trunk/Source/WebCore/ChangeLog (114040 => 114041)
--- trunk/Source/WebCore/ChangeLog 2012-04-12 21:54:21 UTC (rev 114040)
+++ trunk/Source/WebCore/ChangeLog 2012-04-12 22:19:15 UTC (rev 114041)
@@ -1,3 +1,17 @@
+2012-04-12 Alec Flett <[email protected]>
+
+ IndexedDB: Refactor cursor iteration to remove duplicate code
+ https://bugs.webkit.org/show_bug.cgi?id=83302
+
+ Reviewed by Ojan Vafai.
+
+ No new tests, no behavior changes.
+
+ * Modules/indexeddb/IDBBackingStore.h:
+ (Cursor):
+ * Modules/indexeddb/IDBLevelDBBackingStore.cpp:
+ (WebCore):
+
2012-04-12 Erik Arvidsson <[email protected]>
Add support for [ArrayClass] and use that on NodeList
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h (114040 => 114041)
--- trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h 2012-04-12 21:54:21 UTC (rev 114040)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h 2012-04-12 22:19:15 UTC (rev 114041)
@@ -88,8 +88,13 @@
class Cursor : public RefCounted<Cursor> {
public:
+ enum IteratorState {
+ Ready = 0,
+ Seek
+ };
+
virtual PassRefPtr<Cursor> clone() = 0;
- virtual bool continueFunction(const IDBKey* = 0) = 0;
+ virtual bool continueFunction(const IDBKey* = 0, IteratorState nextState = Seek) = 0;
virtual PassRefPtr<IDBKey> key() = 0;
virtual PassRefPtr<IDBKey> primaryKey() = 0;
virtual String value() = 0;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp (114040 => 114041)
--- trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp 2012-04-12 21:54:21 UTC (rev 114040)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp 2012-04-12 22:19:15 UTC (rev 114041)
@@ -980,7 +980,7 @@
class CursorImplCommon : public IDBBackingStore::Cursor {
public:
// IDBBackingStore::Cursor
- virtual bool continueFunction(const IDBKey*);
+ virtual bool continueFunction(const IDBKey*, IteratorState);
virtual PassRefPtr<IDBKey> key() { return m_currentKey; }
virtual PassRefPtr<IDBKey> primaryKey() { return m_currentKey; }
virtual String value() = 0;
@@ -1015,6 +1015,9 @@
virtual ~CursorImplCommon() {}
+ bool isPastBounds() const;
+ bool haveEnteredRange() const;
+
LevelDBTransaction* m_transaction;
CursorOptions m_cursorOptions;
OwnPtr<LevelDBIterator> m_iterator;
@@ -1024,63 +1027,27 @@
bool CursorImplCommon::firstSeek()
{
m_iterator = m_transaction->createIterator();
-
if (m_cursorOptions.forward)
m_iterator->seek(m_cursorOptions.lowKey);
else
m_iterator->seek(m_cursorOptions.highKey);
- for (;;) {
- if (!m_iterator->isValid())
- return false;
+ return continueFunction(0, Ready);
+}
- if (m_cursorOptions.forward && m_cursorOptions.highOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) >= 0)
- return false;
- if (m_cursorOptions.forward && !m_cursorOptions.highOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) > 0)
- return false;
- if (!m_cursorOptions.forward && m_cursorOptions.lowOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) <= 0)
- return false;
- if (!m_cursorOptions.forward && !m_cursorOptions.lowOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) < 0)
- return false;
+bool CursorImplCommon::continueFunction(const IDBKey* key, IteratorState nextState)
+{
+ RefPtr<IDBKey> previousKey = m_currentKey;
- if (m_cursorOptions.forward && m_cursorOptions.lowOpen) {
- // lowKey not included in the range.
- if (compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) <= 0) {
- m_iterator->next();
- continue;
- }
- }
- if (!m_cursorOptions.forward && m_cursorOptions.highOpen) {
- // highKey not included in the range.
- if (compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) >= 0) {
- m_iterator->prev();
- continue;
- }
- }
-
- if (!loadCurrentRow()) {
+ for (;;) {
+ if (nextState == Seek) {
if (m_cursorOptions.forward)
m_iterator->next();
else
m_iterator->prev();
- continue;
- }
+ } else
+ nextState = Seek; // for subsequent iterations
- return true;
- }
-}
-
-bool CursorImplCommon::continueFunction(const IDBKey* key)
-{
- // FIXME: This shares a lot of code with firstSeek.
- RefPtr<IDBKey> previousKey = m_currentKey;
-
- for (;;) {
- if (m_cursorOptions.forward)
- m_iterator->next();
- else
- m_iterator->prev();
-
if (!m_iterator->isValid())
return false;
@@ -1088,15 +1055,14 @@
if (!m_transaction->get(m_iterator->key(), trash))
continue;
- if (m_cursorOptions.forward && m_cursorOptions.highOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) >= 0) // high key not included in range
+ if (isPastBounds())
return false;
- if (m_cursorOptions.forward && !m_cursorOptions.highOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) > 0)
- return false;
- if (!m_cursorOptions.forward && m_cursorOptions.lowOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) <= 0) // low key not included in range
- return false;
- if (!m_cursorOptions.forward && !m_cursorOptions.lowOpen && compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) < 0)
- return false;
+ if (!haveEnteredRange())
+ continue;
+
+ // The row may not load because there's a stale entry in the
+ // index. This is not fatal.
if (!loadCurrentRow())
continue;
@@ -1119,6 +1085,33 @@
return true;
}
+bool CursorImplCommon::haveEnteredRange() const
+{
+ if (m_cursorOptions.forward) {
+ if (m_cursorOptions.lowOpen)
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) > 0;
+
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) >= 0;
+ }
+ if (m_cursorOptions.highOpen)
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) < 0;
+
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) <= 0;
+}
+
+bool CursorImplCommon::isPastBounds() const
+{
+ if (m_cursorOptions.forward) {
+ if (m_cursorOptions.highOpen)
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) >= 0;
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.highKey) > 0;
+ }
+
+ if (m_cursorOptions.lowOpen)
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) <= 0;
+ return compareIndexKeys(m_iterator->key(), m_cursorOptions.lowKey) < 0;
+}
+
class ObjectStoreCursorImpl : public CursorImplCommon {
public:
static PassRefPtr<ObjectStoreCursorImpl> create(LevelDBTransaction* transaction, const CursorOptions& cursorOptions)