EncodedJSValue JSC_HOST_CALL jsIDBCursorPrototypeFunctionContinue(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBCursor::s_info)) return throwVMTypeError(exec); JSIDBCursor* castedThis = static_cast<JSIDBCursor*>(asObject(thisValue)); ASSERT_GC_OBJECT_INHERITS(castedThis, &JSIDBCursor::s_info); IDBCursor* imp = static_cast<IDBCursor*>(castedThis->impl()); ExceptionCode ec = 0; size_t argsCount = exec->argumentCount(); if (argsCount <= 0) { imp->continueFunction(ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); } RefPtr<IDBKey> key(createIDBKeyFromValue(exec, exec->argument(0))); if (exec->hadException()) return JSValue::encode(jsUndefined()); imp->continueFunction(key, ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); }
JSValue jsIDBCursorSource(ExecState* exec, JSValue slotBase, const Identifier&) { JSIDBCursor* castedThis = static_cast<JSIDBCursor*>(asObject(slotBase)); UNUSED_PARAM(exec); IDBCursor* imp = static_cast<IDBCursor*>(castedThis->impl()); JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->source())); return result; }
JSValue jsIDBCursorDirection(ExecState* exec, JSValue slotBase, const Identifier&) { JSIDBCursor* castedThis = static_cast<JSIDBCursor*>(asObject(slotBase)); UNUSED_PARAM(exec); IDBCursor* imp = static_cast<IDBCursor*>(castedThis->impl()); JSValue result = jsNumber(imp->direction()); return result; }
void IDBTransaction::iterateCursor(IDBCursor& cursor, const IDBKeyData& key, unsigned long count) { LOG(IndexedDB, "IDBTransaction::iterateCursor"); ASSERT(isActive()); ASSERT(cursor.request()); addRequest(*cursor.request()); auto operation = createTransactionOperation(*this, *cursor.request(), &IDBTransaction::didIterateCursorOnServer, &IDBTransaction::iterateCursorOnServer, key, count); scheduleOperation(WTFMove(operation)); }
IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBCursor& cursor, IDBTransaction& transaction) : IDBOpenDBRequest(&context) , m_transaction(&transaction) , m_connection(transaction.serverConnection()) , m_resourceIdentifier(transaction.serverConnection()) , m_source(cursor.source()) , m_pendingCursor(&cursor) { suspendIfNeeded(); cursor.setRequest(*this); }
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(); }
IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBCursor& cursor, IDBTransaction& transaction) : IDBOpenDBRequest(&context) , m_transaction(&transaction) , m_connection(transaction.serverConnection()) , m_resourceIdentifier(transaction.serverConnection()) , m_pendingCursor(&cursor) { suspendIfNeeded(); cursor.setRequest(*this); auto* cursorSource = cursor.source(); ASSERT(cursorSource); ASSERT(cursorSource->type() == IDBAny::Type::IDBObjectStore || cursorSource->type() == IDBAny::Type::IDBIndex); m_source = cursorSource; }
IDBRequest::IDBRequest(ScriptExecutionContext& context, IDBCursor& cursor, IDBTransaction& transaction) : IDBActiveDOMObject(&context) , m_transaction(&transaction) , m_resourceIdentifier(transaction.connectionProxy()) , m_pendingCursor(&cursor) , m_connectionProxy(transaction.database().connectionProxy()) { suspendIfNeeded(); WTF::switchOn(cursor.source(), [this] (const auto& value) { this->m_source = IDBRequest::Source { value }; } ); m_result = NullResultType::Empty; cursor.setRequest(*this); }
EncodedJSValue JSC_HOST_CALL jsIDBCursorPrototypeFunctionDelete(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBCursor::s_info)) return throwVMTypeError(exec); JSIDBCursor* castedThis = static_cast<JSIDBCursor*>(asObject(thisValue)); ASSERT_GC_OBJECT_INHERITS(castedThis, &JSIDBCursor::s_info); IDBCursor* imp = static_cast<IDBCursor*>(castedThis->impl()); ExceptionCode ec = 0; ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); if (!scriptContext) return JSValue::encode(jsUndefined()); JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->deleteFunction(scriptContext, ec))); setDOMException(exec, ec); return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL jsIDBCursorPrototypeFunctionUpdate(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSIDBCursor::s_info)) return throwVMTypeError(exec); JSIDBCursor* castedThis = static_cast<JSIDBCursor*>(asObject(thisValue)); ASSERT_GC_OBJECT_INHERITS(castedThis, &JSIDBCursor::s_info); IDBCursor* imp = static_cast<IDBCursor*>(castedThis->impl()); if (exec->argumentCount() < 1) return throwVMError(exec, createTypeError(exec, "Not enough arguments")); ExceptionCode ec = 0; ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); if (!scriptContext) return JSValue::encode(jsUndefined()); RefPtr<SerializedScriptValue> value(SerializedScriptValue::create(exec, exec->argument(0))); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->update(scriptContext, value, ec))); setDOMException(exec, ec); return JSValue::encode(result); }
bool IDBRequest::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) { IDB_TRACE("IDBRequest::dispatchEvent"); if (m_contextStopped || !executionContext()) return false; ASSERT(m_readyState == PENDING); ASSERT(m_hasPendingActivity); ASSERT(m_enqueuedEvents.size()); ASSERT(event->target() == this); ScriptState::Scope scope(m_scriptState.get()); if (event->type() != EventTypeNames::blocked) m_readyState = DONE; dequeueEvent(event.get()); WillBeHeapVector<RefPtrWillBeMember<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. IDBCursor* cursorToNotify = 0; if (event->type() == EventTypeNames::success) { cursorToNotify = getResultCursor(); if (cursorToNotify) { if (m_blobInfo && m_blobInfo->size() > 0) V8PerIsolateData::from(scriptState()->isolate())->ensureIDBPendingTransactionMonitor()->unregisterRequest(*this); cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release(), m_blobInfo.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().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; }