void IDBRequest::checkForReferenceCycle() { // If this request and its cursor have the only references // to each other, then explicitly break the cycle. IDBCursor* cursor = getResultCursor(); if (!cursor || cursor->request() != this) return; if (!hasOneRef() || !cursor->hasOneRef()) return; m_result.clear(); }
void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor) { ASSERT(m_readyState == DONE); ASSERT(executionContext()); ASSERT(m_transaction); ASSERT(!m_pendingCursor); ASSERT(cursor == getResultCursor()); m_hasPendingActivity = true; m_pendingCursor = cursor; m_result.clear(); m_readyState = PENDING; m_error.clear(); m_transaction->registerRequest(this); }
void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor) { ASSERT(m_readyState == DONE); ASSERT(scriptExecutionContext()); ASSERT(m_transaction); ASSERT(!m_pendingCursor); ASSERT(cursor == getResultCursor()); m_pendingCursor = cursor; m_result.clear(); m_readyState = PENDING; m_errorCode = 0; m_error.clear(); m_errorMessage = String(); m_transaction->registerRequest(this); }
void LegacyRequest::setPendingCursor(PassRefPtr<LegacyCursor> cursor) { ASSERT(m_readyState == IDBRequestReadyState::Done); ASSERT(scriptExecutionContext()); ASSERT(m_transaction); ASSERT(!m_pendingCursor); ASSERT(cursor == getResultCursor()); m_pendingCursor = cursor; m_result = nullptr; m_readyState = IDBRequestReadyState::Pending; m_errorCode = 0; m_error = nullptr; m_errorMessage = String(); m_transaction->registerRequest(this); }
bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) { IDB_TRACE("IDBRequest::dispatchEvent"); ASSERT(m_readyState == PENDING); ASSERT(!m_contextStopped); ASSERT(m_hasPendingActivity); ASSERT(m_enqueuedEvents.size()); ASSERT(scriptExecutionContext()); ASSERT(event->target() == this); ASSERT_WITH_MESSAGE(m_readyState < DONE, "When dispatching event %s, m_readyState < DONE(%d), was %d", event->type().string().utf8().data(), DONE, m_readyState); if (event->type() != eventNames().blockedEvent) m_readyState = DONE; for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { if (m_enqueuedEvents[i].get() == event.get()) m_enqueuedEvents.remove(i); } Vector<RefPtr<EventTarget> > targets; targets.append(this); if (m_transaction) { targets.append(m_transaction); // If there ever are events that are associated with a database but // that do not have a transaction, then this will not work and we need // this object to actually hold a reference to the database (to ensure // it stays alive). targets.append(m_transaction->db()); } // Cursor properties should not updated until the success event is being dispatched. RefPtr<IDBCursor> cursorToNotify; if (event->type() == eventNames().successEvent) { cursorToNotify = getResultCursor(); if (cursorToNotify) cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue); } if (event->type() == eventNames().upgradeneededEvent) { ASSERT(!m_didFireUpgradeNeededEvent); m_didFireUpgradeNeededEvent = true; } // FIXME: When we allow custom event dispatching, this will probably need to change. ASSERT_WITH_MESSAGE(event->type() == eventNames().successEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().blockedEvent || event->type() == eventNames().upgradeneededEvent, "event type was %s", event->type().string().utf8().data()); const bool setTransactionActive = m_transaction && (event->type() == eventNames().successEvent || event->type() == eventNames().upgradeneededEvent || (event->type() == eventNames().errorEvent && m_errorCode != IDBDatabaseException::IDB_ABORT_ERR)); if (setTransactionActive) m_transaction->setActive(true); bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets); if (setTransactionActive) m_transaction->setActive(false); if (cursorToNotify) cursorToNotify->postSuccessHandlerCallback(); if (m_readyState == DONE && (!cursorToNotify || m_cursorFinished) && event->type() != eventNames().upgradeneededEvent) m_hasPendingActivity = false; if (m_transaction) { if (event->type() == eventNames().errorEvent && dontPreventDefault && !m_requestAborted) { m_transaction->setError(m_error); ExceptionCode unused; m_transaction->abort(unused); } if (event->type() != eventNames().blockedEvent) m_transaction->backend()->didCompleteTaskEvents(); if (m_readyState == DONE) m_transaction->unregisterRequest(this); } return dontPreventDefault; }
bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) { IDB_TRACE("IDBRequest::dispatchEvent"); if (m_contextStopped || !executionContext()) return false; ASSERT(m_requestState.isValid()); ASSERT(m_readyState == PENDING); ASSERT(m_hasPendingActivity); ASSERT(m_enqueuedEvents.size()); ASSERT(event->target() == this); DOMRequestState::Scope scope(m_requestState); if (event->type() != EventTypeNames::blocked) m_readyState = DONE; dequeueEvent(event.get()); Vector<RefPtr<EventTarget> > targets; targets.append(this); if (m_transaction && !m_preventPropagation) { targets.append(m_transaction); // If there ever are events that are associated with a database but // that do not have a transaction, then this will not work and we need // this object to actually hold a reference to the database (to ensure // it stays alive). targets.append(m_transaction->db()); } // Cursor properties should not be updated until the success event is being dispatched. RefPtr<IDBCursor> cursorToNotify; if (event->type() == EventTypeNames::success) { cursorToNotify = getResultCursor(); if (cursorToNotify) cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release()); } if (event->type() == EventTypeNames::upgradeneeded) { ASSERT(!m_didFireUpgradeNeededEvent); m_didFireUpgradeNeededEvent = true; } // FIXME: When we allow custom event dispatching, this will probably need to change. ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type() == EventTypeNames::error || event->type() == EventTypeNames::blocked || event->type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().string().utf8().data()); const bool setTransactionActive = m_transaction && (event->type() == EventTypeNames::success || event->type() == EventTypeNames::upgradeneeded || (event->type() == EventTypeNames::error && !m_requestAborted)); if (setTransactionActive) m_transaction->setActive(true); bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets); if (m_transaction) { if (m_readyState == DONE) m_transaction->unregisterRequest(this); // Possibly abort the transaction. This must occur after unregistering (so this request // doesn't receive a second error) and before deactivating (which might trigger commit). if (event->type() == EventTypeNames::error && dontPreventDefault && !m_requestAborted) { m_transaction->setError(m_error); m_transaction->abort(IGNORE_EXCEPTION); } // If this was the last request in the transaction's list, it may commit here. if (setTransactionActive) m_transaction->setActive(false); } if (cursorToNotify) cursorToNotify->postSuccessHandlerCallback(); // An upgradeneeded event will always be followed by a success or error event, so must // be kept alive. if (m_readyState == DONE && event->type() != EventTypeNames::upgradeneeded) m_hasPendingActivity = false; return dontPreventDefault; }
bool IDBRequest::dispatchEvent(PassRefPtr<Event> event) { LOG(StorageAPI, "IDBRequest::dispatchEvent"); ASSERT(m_readyState == PENDING); ASSERT(!m_contextStopped); ASSERT(m_hasPendingActivity); ASSERT(m_enqueuedEvents.size()); ASSERT(scriptExecutionContext()); ASSERT(event->target() == this); ASSERT_WITH_MESSAGE(m_readyState < DONE, "When dispatching event %s, m_readyState < DONE(%d), was %d", event->type().string().utf8().data(), DONE, m_readyState); DOMRequestState::Scope scope(m_requestState); if (event->type() != eventNames().blockedEvent) m_readyState = DONE; for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) { if (m_enqueuedEvents[i].get() == event.get()) m_enqueuedEvents.remove(i); } Vector<RefPtr<EventTarget>> targets; targets.append(this); if (m_transaction && !m_preventPropagation) { targets.append(m_transaction); // If there ever are events that are associated with a database but // that do not have a transaction, then this will not work and we need // this object to actually hold a reference to the database (to ensure // it stays alive). targets.append(m_transaction->db()); } // Cursor properties should not updated until the success event is being dispatched. RefPtr<IDBCursor> cursorToNotify; if (event->type() == eventNames().successEvent) { cursorToNotify = getResultCursor(); if (cursorToNotify) { cursorToNotify->setValueReady(requestState(), m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue); m_cursorValue.clear(); } } if (event->type() == eventNames().upgradeneededEvent) { ASSERT(!m_didFireUpgradeNeededEvent); m_didFireUpgradeNeededEvent = true; } // FIXME: When we allow custom event dispatching, this will probably need to change. ASSERT_WITH_MESSAGE(event->type() == eventNames().successEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().blockedEvent || event->type() == eventNames().upgradeneededEvent, "event type was %s", event->type().string().utf8().data()); const bool setTransactionActive = m_transaction && (event->type() == eventNames().successEvent || event->type() == eventNames().upgradeneededEvent || (event->type() == eventNames().errorEvent && m_errorCode != IDBDatabaseException::AbortError)); if (setTransactionActive) m_transaction->setActive(true); bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets); if (m_transaction) { if (m_readyState == DONE) m_transaction->unregisterRequest(this); // Possibly abort the transaction. This must occur after unregistering (so this request // doesn't receive a second error) and before deactivating (which might trigger commit). if (event->type() == eventNames().errorEvent && dontPreventDefault && !m_requestAborted) { m_transaction->setError(m_error, m_errorMessage); m_transaction->abort(IGNORE_EXCEPTION); } // If this was the last request in the transaction's list, it may commit here. if (setTransactionActive) m_transaction->setActive(false); } if (cursorToNotify) cursorToNotify->postSuccessHandlerCallback(); if (m_readyState == DONE && (!cursorToNotify || m_cursorFinished) && event->type() != eventNames().upgradeneededEvent) m_hasPendingActivity = false; return dontPreventDefault; }