Changeset 109271 in webkit
- Timestamp:
- Feb 29, 2012 3:03:19 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r109270 r109271 1 2012-02-29 Joshua Bell <jsbell@chromium.org> 2 3 IndexedDB: Resource leak with IDBObjectStore.openCursor 4 https://bugs.webkit.org/show_bug.cgi?id=79835 5 6 Ensure that IDBCursor.continue() throws the right exception when transaction is finished. 7 8 Reviewed by Tony Chang. 9 10 * storage/indexeddb/cursor-continue-expected.txt: 11 * storage/indexeddb/cursor-continue.html: 12 1 13 2012-02-29 Adam Klein <adamk@chromium.org> 2 14 -
trunk/LayoutTests/storage/indexeddb/cursor-continue-expected.txt
r104865 r109271 109 109 event.target.result.continue('A bit2') 110 110 PASS event.target.result.primaryKey is 15 111 cursor = event.target.result 111 112 Expecting exception from event.target.result.continue('A bit2') 112 113 PASS Exception was thrown. 113 114 PASS code is IDBDatabaseException.DATA_ERR 115 Expecting exception from cursor.continue() 116 PASS Exception was thrown. 117 PASS code is IDBDatabaseException.TRANSACTION_INACTIVE_ERR 114 118 PASS successfullyParsed is true 115 119 -
trunk/LayoutTests/storage/indexeddb/cursor-continue.html
r104865 r109271 263 263 } else if (window.stage == 1) { 264 264 shouldBe("event.target.result.primaryKey", "15"); 265 evalAndLog("cursor = event.target.result"); 265 266 evalAndExpectException("event.target.result.continue('A bit2')", "IDBDatabaseException.DATA_ERR"); 266 done(); 267 return; 268 } else { 269 testFailed("Illegal stage."); 270 } 271 window.stage++; 272 }; 267 window.trans.oncomplete = onTransactionComplete; 268 return; 269 } else { 270 testFailed("Illegal stage."); 271 } 272 window.stage++; 273 }; 274 } 275 276 function onTransactionComplete() 277 { 278 evalAndExpectException("cursor.continue()", "IDBDatabaseException.TRANSACTION_INACTIVE_ERR"); 279 done(); 273 280 } 274 281 -
trunk/Source/WebCore/ChangeLog
r109267 r109271 1 2012-02-29 Joshua Bell <jsbell@chromium.org> 2 3 IndexedDB: Resource leak with IDBObjectStore.openCursor 4 https://bugs.webkit.org/show_bug.cgi?id=79835 5 6 IDBCursor object that were never continue()'d to the end would leak due to a 7 reference cycle with IDBRequest. In addition, the IDBRequest would never be 8 marked "finished" which would prevent GC from reclaiming it. IDBTransactions 9 now track and notify IDBCursors to break these references when the transaction 10 can no longer not process requests. 11 12 Reviewed by Tony Chang. 13 14 Tests: storage/indexeddb/cursor-continue.html 15 16 * storage/IDBCursor.cpp: 17 (WebCore::IDBCursor::IDBCursor): Register with IDBTransaction bookkeeping. 18 (WebCore::IDBCursor::continueFunction): Early error if transaction has finished. 19 (WebCore::IDBCursor::close): Break the reference cycle with IDBRequest, and notify it 20 that the cursor is finished. 21 (WebCore): 22 * storage/IDBCursor.h: 23 (WebCore): 24 (IDBCursor): 25 * storage/IDBRequest.cpp: 26 (WebCore::IDBRequest::IDBRequest): 27 (WebCore::IDBRequest::finishCursor): If there is no request in flight, mark itself as 28 finished to allow GC. 29 (WebCore): 30 (WebCore::IDBRequest::dispatchEvent): Once an in-flight request has been processed, 31 mark the request as finished if the cursor is finished, to allow GC. 32 * storage/IDBRequest.h: 33 (IDBRequest): 34 * storage/IDBTransaction.cpp: Track open cursors, close them when finished. 35 (WebCore::IDBTransaction::OpenCursorNotifier::OpenCursorNotifier): 36 (WebCore): 37 (WebCore::IDBTransaction::OpenCursorNotifier::~OpenCursorNotifier): 38 (WebCore::IDBTransaction::registerOpenCursor): 39 (WebCore::IDBTransaction::unregisterOpenCursor): 40 (WebCore::IDBTransaction::closeOpenCursors): 41 (WebCore::IDBTransaction::onAbort): 42 (WebCore::IDBTransaction::onComplete): 43 * storage/IDBTransaction.h: 44 (WebCore): 45 (OpenCursorNotifier): 46 (IDBTransaction): 47 1 48 2012-02-29 David Hyatt <hyatt@apple.com> 2 49 -
trunk/Source/WebCore/storage/IDBCursor.cpp
r108520 r109271 51 51 , m_source(source) 52 52 , m_transaction(transaction) 53 , m_transactionNotifier(transaction, this) 53 54 { 54 55 ASSERT(m_backend); … … 111 112 } 112 113 114 if (!m_request) { 115 ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; 116 return; 117 } 113 118 // FIXME: We're not using the context from when continue was called, which means the callback 114 119 // will be on the original context openCursor was called on. Is this right? … … 137 142 } 138 143 144 void IDBCursor::close() 145 { 146 ASSERT(m_request); 147 m_request->finishCursor(); 148 m_request.clear(); 149 } 150 139 151 } // namespace WebCore 140 152 -
trunk/Source/WebCore/storage/IDBCursor.h
r101645 r109271 30 30 31 31 #include "IDBKey.h" 32 #include "IDBTransaction.h" 32 33 #include <wtf/PassRefPtr.h> 33 34 #include <wtf/RefCounted.h> … … 40 41 class IDBCursorBackendInterface; 41 42 class IDBRequest; 42 class IDBTransaction;43 43 class ScriptExecutionContext; 44 44 class SerializedScriptValue; … … 72 72 73 73 void postSuccessHandlerCallback(); 74 void close(); 74 75 75 76 protected: … … 81 82 RefPtr<IDBAny> m_source; 82 83 RefPtr<IDBTransaction> m_transaction; 84 IDBTransaction::OpenCursorNotifier m_transactionNotifier; 83 85 }; 84 86 -
trunk/Source/WebCore/storage/IDBRequest.cpp
r108520 r109271 59 59 , m_readyState(LOADING) 60 60 , m_requestFinished(false) 61 , m_cursorFinished(false) 61 62 , m_contextStopped(false) 62 63 , m_cursorType(IDBCursorBackendInterface::InvalidCursorType) … … 181 182 ASSERT(!m_cursor); 182 183 m_cursor = cursor; 184 } 185 186 void IDBRequest::finishCursor() 187 { 188 m_cursorFinished = true; 189 if (m_readyState != LOADING) 190 m_requestFinished = true; 183 191 } 184 192 … … 365 373 366 374 // If the result was of type IDBCursor, or a onBlocked event, then we'll fire again. 367 if (event->type() != eventNames().blockedEvent && m_result && m_result->type() != IDBAny::IDBCursorType && m_result->type() != IDBAny::IDBCursorWithValueType)375 if (event->type() != eventNames().blockedEvent && (!cursorToNotify || m_cursorFinished)) 368 376 m_requestFinished = true; 369 377 -
trunk/Source/WebCore/storage/IDBRequest.h
r101645 r109271 73 73 void setCursorType(IDBCursorBackendInterface::CursorType); 74 74 void setCursor(PassRefPtr<IDBCursor>); 75 void finishCursor(); 75 76 IDBAny* source(); 76 77 void abort(); … … 123 124 ReadyState m_readyState; 124 125 bool m_requestFinished; // Is it possible that we'll fire any more events? If not, we're finished. 126 bool m_cursorFinished; 125 127 bool m_contextStopped; 126 128 Vector<RefPtr<Event> > m_enqueuedEvents; -
trunk/Source/WebCore/storage/IDBTransaction.cpp
r108520 r109271 127 127 } 128 128 129 IDBTransaction::OpenCursorNotifier::OpenCursorNotifier(PassRefPtr<IDBTransaction> transaction, IDBCursor* cursor) 130 : m_transaction(transaction), 131 m_cursor(cursor) 132 { 133 m_transaction->registerOpenCursor(m_cursor); 134 } 135 136 IDBTransaction::OpenCursorNotifier::~OpenCursorNotifier() 137 { 138 m_transaction->unregisterOpenCursor(m_cursor); 139 } 140 141 void IDBTransaction::registerOpenCursor(IDBCursor* cursor) 142 { 143 m_openCursors.add(cursor); 144 } 145 146 void IDBTransaction::unregisterOpenCursor(IDBCursor* cursor) 147 { 148 m_openCursors.remove(cursor); 149 } 150 151 void IDBTransaction::closeOpenCursors() 152 { 153 HashSet<IDBCursor*> cursors; 154 cursors.swap(m_openCursors); 155 for (HashSet<IDBCursor*>::iterator i = cursors.begin(); i != cursors.end(); ++i) 156 (*i)->close(); 157 } 158 129 159 void IDBTransaction::registerRequest(IDBRequest* request) 130 160 { … … 149 179 if (m_mode == IDBTransaction::VERSION_CHANGE) 150 180 m_database->clearVersionChangeTransaction(this); 181 closeOpenCursors(); 151 182 152 183 if (m_contextStopped || !scriptExecutionContext()) … … 161 192 if (m_mode == IDBTransaction::VERSION_CHANGE) 162 193 m_database->clearVersionChangeTransaction(this); 194 closeOpenCursors(); 163 195 164 196 if (m_contextStopped || !scriptExecutionContext()) -
trunk/Source/WebCore/storage/IDBTransaction.h
r103283 r109271 37 37 #include "IDBTransactionBackendInterface.h" 38 38 #include "IDBTransactionCallbacks.h" 39 #include <wtf/HashSet.h> 39 40 #include <wtf/RefCounted.h> 40 41 41 42 namespace WebCore { 42 43 44 class IDBCursor; 43 45 class IDBDatabase; 44 46 class IDBObjectStore; … … 62 64 PassRefPtr<IDBObjectStore> objectStore(const String& name, ExceptionCode&); 63 65 void abort(); 66 67 class OpenCursorNotifier { 68 public: 69 OpenCursorNotifier(PassRefPtr<IDBTransaction>, IDBCursor*); 70 ~OpenCursorNotifier(); 71 private: 72 RefPtr<IDBTransaction> m_transaction; 73 IDBCursor* m_cursor; 74 }; 64 75 65 76 void registerRequest(IDBRequest*); … … 94 105 95 106 void enqueueEvent(PassRefPtr<Event>); 107 void closeOpenCursors(); 108 109 void registerOpenCursor(IDBCursor*); 110 void unregisterOpenCursor(IDBCursor*); 96 111 97 112 // EventTarget … … 112 127 IDBObjectStoreMap m_objectStoreMap; 113 128 129 HashSet<IDBCursor*> m_openCursors; 130 114 131 EventTargetData m_eventTargetData; 115 132 };
Note: See TracChangeset
for help on using the changeset viewer.