Vector<char> encodeIDBKeyPath(const IDBKeyPath& keyPath) { // May be typed, or may be a raw string. An invalid leading // byte is used to identify typed coding. New records are // always written as typed. Vector<char> ret; ret.append(IDBKeyPathTypeCodedByte1); ret.append(IDBKeyPathTypeCodedByte2); ret.append(static_cast<char>(keyPath.type())); switch (keyPath.type()) { case IDBKeyPath::NullType: break; case IDBKeyPath::StringType: ret.append(encodeStringWithLength(keyPath.string())); break; case IDBKeyPath::ArrayType: { const Vector<String>& array = keyPath.array(); size_t count = array.size(); ret.append(encodeVarInt(count)); for (size_t i = 0; i < count; ++i) ret.append(encodeStringWithLength(array[i])); break; } } return ret; }
bool injectIDBKeyIntoScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key, Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) { LOG(StorageAPI, "injectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; ExecState* exec = requestState->exec(); JSValue parent = ensureNthValueOnKeyPath(exec, value.jsValue(), keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; if (!set(exec, parent, keyPathElements.last(), idbKeyToJSValue(exec, exec->lexicalGlobalObject(), key.get()))) return false; return true; }
bool injectIDBKeyIntoScriptValue(JSC::ExecState& exec, const IDBKeyData& keyData, JSC::JSValue value, const IDBKeyPath& keyPath) { LOG(IndexedDB, "injectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; JSValue parent = ensureNthValueOnKeyPath(&exec, value, keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; auto key = keyData.maybeCreateIDBKey(); if (!key) return false; if (!set(&exec, parent, keyPathElements.last(), idbKeyToJSValue(&exec, exec.lexicalGlobalObject(), key.get()))) return false; return true; }
static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath) { RefPtr<KeyPath> keyPath; switch (idbKeyPath.type()) { case IDBKeyPath::NullType: keyPath = KeyPath::create().setType(KeyPath::Type::Null); break; case IDBKeyPath::StringType: keyPath = KeyPath::create().setType(KeyPath::Type::String); keyPath->setString(idbKeyPath.string()); break; case IDBKeyPath::ArrayType: { keyPath = KeyPath::create().setType(KeyPath::Type::Array); RefPtr<TypeBuilder::Array<String> > array = TypeBuilder::Array<String>::create(); const Vector<String>& stringArray = idbKeyPath.array(); for (size_t i = 0; i < stringArray.size(); ++i) array->addItem(stringArray[i]); keyPath->setArray(array); break; } default: ASSERT_NOT_REACHED(); } return keyPath.release(); }
bool injectIDBKeyIntoScriptValue(DOMRequestState*, PassRefPtr<IDBKey> key, ScriptValue& value, const IDBKeyPath& keyPath) { IDB_TRACE("injectIDBKeyIntoScriptValue"); ASSERT(v8::Context::InContext()); ASSERT(keyPath.type() == IDBKeyPath::StringType); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseErrorNone); if (!keyPathElements.size()) return 0; v8::HandleScope handleScope; v8::Handle<v8::Value> v8Value(value.v8Value()); v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size() - 1)); if (parent.IsEmpty()) return false; if (!set(parent, keyPathElements.last(), toV8(key.get()))) return false; return true; }
PassRefPtr<IDBIndex> IDBObjectStore::createIndex(const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionCode& ec) { IDB_TRACE("IDBObjectStore::createIndex"); if (!m_transaction->isVersionChange() || m_deleted) { ec = IDBDatabaseException::IDB_INVALID_STATE_ERR; return 0; } if (!keyPath.isValid()) { ec = IDBDatabaseException::IDB_SYNTAX_ERR; return 0; } bool unique = false; options.get("unique", unique); bool multiEntry = false; options.get("multiEntry", multiEntry); if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) { ec = IDBDatabaseException::IDB_NOT_SUPPORTED_ERR; return 0; } RefPtr<IDBIndexBackendInterface> indexBackend = m_backend->createIndex(name, keyPath, unique, multiEntry, m_transaction->backend(), ec); ASSERT(!indexBackend != !ec); // If we didn't get an index, we should have gotten an exception code. And vice versa. if (ec) return 0; RefPtr<IDBIndex> index = IDBIndex::create(indexBackend.release(), this, m_transaction.get()); m_indexMap.set(name, index); return index.release(); }
void ArgumentCoder<IDBKeyPath>::encode(ArgumentEncoder& encoder, const IDBKeyPath& keyPath) { encoder.encodeEnum(keyPath.type()); switch (keyPath.type()) { case IDBKeyPath::NullType: break; case IDBKeyPath::StringType: encoder << keyPath.string(); break; case IDBKeyPath::ArrayType: encoder << keyPath.array(); break; default: ASSERT_NOT_REACHED(); } }
RefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext&, const String& name, const IDBKeyPath& keyPath, const IndexParameters& parameters, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBObjectStore::createIndex %s", name.utf8().data()); ASSERT(currentThread() == m_transaction->database().originThreadID()); if (m_deleted) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The object store has been deleted."); return nullptr; } if (!m_transaction->isVersionChange()) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The database is not running a version change transaction."); return nullptr; } if (!m_transaction->isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; return nullptr; } if (!keyPath.isValid()) { ec.code = IDBDatabaseException::SyntaxError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The keyPath argument contains an invalid key path."); return nullptr; } if (name.isNull()) { ec.code = TypeError; return nullptr; } if (m_info.hasIndex(name)) { ec.code = IDBDatabaseException::ConstraintError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': An index with the specified name already exists."); return nullptr; } if (keyPath.type() == IDBKeyPath::Type::Array && parameters.multiEntry) { ec.code = IDBDatabaseException::InvalidAccessError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The keyPath argument was an array and the multiEntry option is true."); return nullptr; } // Install the new Index into the ObjectStore's info. IDBIndexInfo info = m_info.createNewIndex(name, keyPath, parameters.unique, parameters.multiEntry); m_transaction->database().didCreateIndexInfo(info); // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. auto index = m_transaction->createIndex(*this, info); RefPtr<IDBIndex> refIndex = index.get(); Locker<Lock> locker(m_referencedIndexLock); m_referencedIndexes.set(name, WTFMove(index)); return refIndex; }
RefPtr<WebCore::IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBObjectStore::createIndex %s", name.utf8().data()); if (!context) { ec.code = IDBDatabaseException::InvalidStateError; return nullptr; } if (m_deleted) { ec.code = IDBDatabaseException::InvalidStateError; return nullptr; } if (!m_transaction->isVersionChange()) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The database is not running a version change transaction."); return nullptr; } if (!m_transaction->isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; return nullptr; } if (!keyPath.isValid()) { ec.code = IDBDatabaseException::SyntaxError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The keyPath argument contains an invalid key path."); return nullptr; } if (name.isNull()) { ec.code = TypeError; return nullptr; } if (m_info.hasIndex(name)) { ec.code = IDBDatabaseException::ConstraintError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': An index with the specified name already exists."); return nullptr; } if (keyPath.type() == IndexedDB::KeyPathType::Array && multiEntry) { ec.code = IDBDatabaseException::InvalidAccessError; ec.message = ASCIILiteral("Failed to execute 'createIndex' on 'IDBObjectStore': The keyPath argument was an array and the multiEntry option is true."); return nullptr; } // Install the new Index into the ObjectStore's info. IDBIndexInfo info = m_info.createNewIndex(name, keyPath, unique, multiEntry); m_transaction->database().didCreateIndexInfo(info); // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. Ref<IDBIndex> index = m_transaction->createIndex(*this, info); m_referencedIndexes.set(name, &index.get()); return WTF::move(index); }
PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCode& ec) { IDB_TRACE("IDBObjectStore::createIndex"); if (!m_transaction->isVersionChange() || isDeleted()) { ec = IDBDatabaseException::InvalidStateError; return 0; } if (!m_transaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return 0; } if (!keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return 0; } if (name.isNull()) { ec = TypeError; return 0; } if (containsIndex(name)) { ec = IDBDatabaseException::ConstraintError; return 0; } if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) { ec = IDBDatabaseException::InvalidAccessError; return 0; } int64_t indexId = m_metadata.maxIndexId + 1; backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, unique, multiEntry); ++m_metadata.maxIndexId; IDBIndexMetadata metadata(name, indexId, keyPath, unique, multiEntry); RefPtr<IDBIndex> index = IDBIndex::create(metadata, this, m_transaction.get()); m_indexMap.set(name, index); m_metadata.indexes.set(indexId, metadata); m_transaction->db()->indexCreated(id(), metadata); ASSERT(!ec); if (ec) return 0; RefPtr<IDBRequest> indexRequest = openCursor(context, static_cast<IDBKeyRange*>(0), IDBCursor::directionNext(), IDBDatabaseBackendInterface::PreemptiveTask, ec); ASSERT(!ec); if (ec) return 0; indexRequest->preventPropagation(); // This is kept alive by being the success handler of the request, which is in turn kept alive by the owning transaction. RefPtr<IndexPopulator> indexPopulator = IndexPopulator::create(backendDB(), m_transaction->id(), id(), metadata); indexRequest->setOnsuccess(indexPopulator); return index.release(); }
RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) { ASSERT(!keyPath.isNull()); if (keyPath.type() == IndexedDB::KeyPathType::Array) { Vector<RefPtr<IDBKey>> result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); i++) { RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, array[i]); if (!key) return nullptr; result.append(key); } return IDBKey::createArray(result); } ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); return internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, keyPath.string()); }
PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const Dictionary& options, ExceptionCode& ec) { if (!m_versionChangeTransaction) { ec = IDBDatabaseException::IDB_INVALID_STATE_ERR; return 0; } if (!m_versionChangeTransaction->isActive()) { ec = IDBDatabaseException::TRANSACTION_INACTIVE_ERR; return 0; } IDBKeyPath keyPath; if (!options.isUndefinedOrNull()) { String keyPathString; Vector<String> keyPathArray; if (options.get("keyPath", keyPathArray)) keyPath = IDBKeyPath(keyPathArray); else if (options.getWithUndefinedOrNullCheck("keyPath", keyPathString)) keyPath = IDBKeyPath(keyPathString); } if (containsObjectStore(name)) { ec = IDBDatabaseException::CONSTRAINT_ERR; return 0; } if (!keyPath.isNull() && !keyPath.isValid()) { ec = IDBDatabaseException::IDB_SYNTAX_ERR; return 0; } bool autoIncrement = false; if (!options.isUndefinedOrNull()) options.get("autoIncrement", autoIncrement); if (autoIncrement && ((keyPath.type() == IDBKeyPath::StringType && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::ArrayType)) { ec = IDBDatabaseException::IDB_INVALID_ACCESS_ERR; return 0; } int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; RefPtr<IDBObjectStoreBackendInterface> objectStoreBackend = m_backend->createObjectStore(objectStoreId, name, keyPath, autoIncrement, m_versionChangeTransaction->backend(), ec); if (!objectStoreBackend) { ASSERT(ec); return 0; } IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, IDBObjectStoreBackendInterface::MinimumIndexId); RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(metadata, objectStoreBackend.release(), m_versionChangeTransaction.get()); m_metadata.objectStores.set(metadata.id, metadata); ++m_metadata.maxObjectStoreId; m_versionChangeTransaction->objectStoreCreated(name, objectStore); return objectStore.release(); }
RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSC::JSValue& value, const IDBKeyPath& keyPath) { ASSERT(!keyPath.isNull()); if (keyPath.type() == IndexedDB::KeyPathType::Array) { const Vector<String>& array = keyPath.array(); Vector<RefPtr<IDBKey>> result; result.reserveInitialCapacity(array.size()); for (auto& string : array) { RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, string); if (!key) return nullptr; result.uncheckedAppend(WTFMove(key)); } return IDBKey::createArray(WTFMove(result)); } ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); return internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, keyPath.string()); }
RefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(ExecState* exec, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) { LOG(StorageAPI, "createIDBKeyFromScriptValueAndKeyPath"); ASSERT(!keyPath.isNull()); if (keyPath.type() == IDBKeyPath::ArrayType) { Vector<RefPtr<IDBKey>> result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); i++) { RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, array[i]); if (!key) return nullptr; result.append(key); } return IDBKey::createArray(result); } ASSERT(keyPath.type() == IDBKeyPath::StringType); return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string()); }
RefPtr<WebCore::IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCode& ec) { LOG(IndexedDB, "IDBObjectStore::createIndex %s", name.utf8().data()); if (!context) { ec = INVALID_STATE_ERR; return nullptr; } if (m_deleted) { ec = static_cast<ExceptionCode>(IDBExceptionCode::InvalidStateError); return nullptr; } if (!m_transaction->isVersionChange()) { ec = static_cast<ExceptionCode>(IDBExceptionCode::InvalidStateError); return nullptr; } if (!m_transaction->isActive()) { ec = static_cast<ExceptionCode>(IDBExceptionCode::TransactionInactiveError); return nullptr; } if (!keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return nullptr; } if (name.isNull()) { ec = TypeError; return nullptr; } if (m_info.hasIndex(name)) { ec = IDBDatabaseException::ConstraintError; return nullptr; } if (keyPath.type() == IndexedDB::KeyPathType::Array && multiEntry) { ec = IDBDatabaseException::InvalidAccessError; return nullptr; } // Install the new Index into the ObjectStore's info. IDBIndexInfo info = m_info.createNewIndex(name, keyPath, unique, multiEntry); m_transaction->database().didCreateIndexInfo(info); // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. Ref<IDBIndex> index = m_transaction->createIndex(*this, info); return WTF::move(index); }
PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* state, const ScriptValue& value, const IDBKeyPath& keyPath) { IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); ASSERT(!keyPath.isNull()); v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); ASSERT(isolate->InContext()); v8::HandleScope handleScope(isolate); if (keyPath.type() == IDBKeyPath::ArrayType) { IDBKey::KeyArray result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); ++i) { RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(value, array[i], isolate); if (!key) return 0; result.append(key); } return IDBKey::createArray(result); } ASSERT(keyPath.type() == IDBKeyPath::StringType); return createIDBKeyFromScriptValueAndKeyPath(value, keyPath.string(), isolate); }
PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* requestState, const ScriptValue& value, const IDBKeyPath& keyPath) { IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); ASSERT(!keyPath.isNull()); ExecState* exec = requestState->exec(); if (keyPath.type() == IDBKeyPath::ArrayType) { IDBKey::KeyArray result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); i++) { RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(exec, value, array[i]); if (!key) return 0; result.append(key); } return IDBKey::createArray(result); } ASSERT(keyPath.type() == IDBKeyPath::StringType); return createIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string()); }
PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue> prpValue, const IDBKeyPath& keyPath) { IDB_TRACE("createIDBKeyFromSerializedValueAndKeyPath"); ASSERT(!keyPath.isNull()); RefPtr<SerializedScriptValue> value = prpValue; if (keyPath.type() == IDBKeyPath::ArrayType) { IDBKey::KeyArray result; const Vector<String>& array = keyPath.array(); for (size_t i = 0; i < array.size(); ++i) { RefPtr<IDBKey> key = createIDBKeyFromSerializedValueAndKeyPath(value, array[i]); if (!key) return 0; result.append(key); } return IDBKey::createArray(result); } ASSERT(keyPath.type() == IDBKeyPath::StringType); return createIDBKeyFromSerializedValueAndKeyPath(value, keyPath.string()); }
bool canInjectIDBKeyIntoScriptValue(DOMRequestState* state, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) { IDB_TRACE("canInjectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IDBKeyPath::StringType); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseErrorNone); if (!keyPathElements.size()) return false; v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); return canInjectNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size() - 1, state->context()->GetIsolate()); }
bool canInjectIDBKeyIntoScriptValue(JSC::ExecState& execState, const JSC::JSValue& scriptValue, const IDBKeyPath& keyPath) { LOG(StorageAPI, "canInjectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IndexedDB::KeyPathType::String); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseError::None); if (!keyPathElements.size()) return false; return canInjectNthValueOnKeyPath(&execState, scriptValue, keyPathElements, keyPathElements.size() - 1); }
bool canInjectIDBKeyIntoScriptValue(DOMRequestState* requestState, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) { IDB_TRACE("canInjectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IDBKeyPath::StringType); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseErrorNone); if (!keyPathElements.size()) return false; JSC::ExecState* exec = requestState->exec(); return canInjectNthValueOnKeyPath(exec, scriptValue.jsValue(), keyPathElements, keyPathElements.size() - 1); }
static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { switch (value.type()) { case IDBKeyPath::NullType: return v8::Null(isolate); case IDBKeyPath::StringType: return v8String(isolate, value.string()); case IDBKeyPath::ArrayType: RefPtr<DOMStringList> keyPaths = DOMStringList::create(); for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it) keyPaths->append(*it); return toV8(keyPaths.release(), creationContext, isolate); } ASSERT_NOT_REACHED(); return v8::Undefined(isolate); }
static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const IDBKeyPath& value) { switch (value.type()) { case IDBKeyPath::NullType: return jsNull(); case IDBKeyPath::StringType: return jsStringWithCache(exec, value.string()); case IDBKeyPath::ArrayType: RefPtr<DOMStringList> keyPaths = DOMStringList::create(); for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it) keyPaths->append(*it); return toJS(exec, globalObject, keyPaths.release()); } ASSERT_NOT_REACHED(); return jsUndefined(); }
PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCode& ec) { LOG(StorageAPI, "IDBObjectStore::createIndex"); if (!m_transaction->isVersionChange() || m_deleted) { ec = IDBDatabaseException::InvalidStateError; return 0; } if (!m_transaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return 0; } if (!keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return 0; } if (name.isNull()) { ec = TypeError; return 0; } if (containsIndex(name)) { ec = IDBDatabaseException::ConstraintError; return 0; } if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) { ec = IDBDatabaseException::InvalidAccessError; return 0; } int64_t indexId = m_metadata.maxIndexId + 1; backendDB()->createIndex(m_transaction->id(), id(), indexId, name, keyPath, unique, multiEntry); ++m_metadata.maxIndexId; IDBIndexMetadata metadata(name, indexId, keyPath, unique, multiEntry); RefPtr<IDBIndex> index = IDBIndex::create(metadata, this, m_transaction.get()); m_indexMap.set(name, index); m_metadata.indexes.set(indexId, metadata); ASSERT(!ec); if (ec) return 0; ASSERT_UNUSED(context, context); return index.release(); }
RefPtr<WebCore::IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBDatabase::createObjectStore - (%s %s)", m_info.name().utf8().data(), name.utf8().data()); ASSERT(currentThread() == originThreadID()); ASSERT(!m_versionChangeTransaction || m_versionChangeTransaction->isVersionChange()); if (!m_versionChangeTransaction) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to execute 'createObjectStore' on 'IDBDatabase': The database is not running a version change transaction."); return nullptr; } if (!m_versionChangeTransaction->isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; return nullptr; } if (m_info.hasObjectStore(name)) { ec.code = IDBDatabaseException::ConstraintError; ec.message = ASCIILiteral("Failed to execute 'createObjectStore' on 'IDBDatabase': An object store with the specified name already exists."); return nullptr; } if (!keyPath.isNull() && !keyPath.isValid()) { ec.code = IDBDatabaseException::SyntaxError; ec.message = ASCIILiteral("Failed to execute 'createObjectStore' on 'IDBDatabase': The keyPath option is not a valid key path."); return nullptr; } if (autoIncrement && !keyPath.isNull()) { if ((keyPath.type() == IDBKeyPath::Type::String && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::Type::Array) { ec.code = IDBDatabaseException::InvalidAccessError; ec.message = ASCIILiteral("Failed to execute 'createObjectStore' on 'IDBDatabase': The autoIncrement option was set but the keyPath option was empty or an array."); return nullptr; } } // Install the new ObjectStore into the connection's metadata. IDBObjectStoreInfo info = m_info.createNewObjectStore(name, keyPath, autoIncrement); // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. Ref<IDBObjectStore> objectStore = m_versionChangeTransaction->createObjectStore(info); return adoptRef(&objectStore.leakRef()); }
PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionState& exceptionState) { IDB_TRACE("IDBDatabase::createObjectStore"); blink::Platform::current()->histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBCreateObjectStoreCall, IDBMethodsMax); if (!m_versionChangeTransaction) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::notVersionChangeTransactionErrorMessage); return nullptr; } if (m_versionChangeTransaction->isFinished()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return nullptr; } if (!m_versionChangeTransaction->isActive()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); return nullptr; } if (containsObjectStore(name)) { exceptionState.throwDOMException(ConstraintError, "An object store with the specified name already exists."); return nullptr; } if (!keyPath.isNull() && !keyPath.isValid()) { exceptionState.throwDOMException(SyntaxError, "The keyPath option is not a valid key path."); return nullptr; } if (autoIncrement && ((keyPath.type() == IDBKeyPath::StringType && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::ArrayType)) { exceptionState.throwDOMException(InvalidAccessError, "The autoIncrement option was set but the keyPath option was empty or an array."); return nullptr; } int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId, name, keyPath, autoIncrement); IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, WebIDBDatabase::minimumIndexId); RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(metadata, m_versionChangeTransaction.get()); m_metadata.objectStores.set(metadata.id, metadata); ++m_metadata.maxObjectStoreId; m_versionChangeTransaction->objectStoreCreated(name, objectStore); return objectStore.release(); }
RefPtr<WebCore::IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionCode& ec) { LOG(IndexedDB, "IDBDatabase::createObjectStore"); ASSERT(!m_versionChangeTransaction || m_versionChangeTransaction->isVersionChange()); if (!m_versionChangeTransaction) { ec = IDBDatabaseException::InvalidStateError; return nullptr; } if (!m_versionChangeTransaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return nullptr; } if (m_info.hasObjectStore(name)) { ec = IDBDatabaseException::ConstraintError; return nullptr; } if (!keyPath.isNull() && !keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return nullptr; } if (autoIncrement && !keyPath.isNull()) { if ((keyPath.type() == IndexedDB::KeyPathType::String && keyPath.string().isEmpty()) || keyPath.type() == IndexedDB::KeyPathType::Array) { ec = IDBDatabaseException::InvalidAccessError; return nullptr; } } // Install the new ObjectStore into the connection's metadata. IDBObjectStoreInfo info = m_info.createNewObjectStore(name, keyPath, autoIncrement); // Create the actual IDBObjectStore from the transaction, which also schedules the operation server side. Ref<IDBObjectStore> objectStore = m_versionChangeTransaction->createObjectStore(info); return adoptRef(&objectStore.leakRef()); }
PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionCode& ec) { IDB_TRACE("IDBDatabase::createObjectStore"); HistogramSupport::histogramEnumeration("WebCore.IndexedDB.FrontEndAPICalls", IDBCreateObjectStoreCall, IDBMethodsMax); if (!m_versionChangeTransaction) { ec = IDBDatabaseException::InvalidStateError; return 0; } if (!m_versionChangeTransaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return 0; } if (containsObjectStore(name)) { ec = IDBDatabaseException::ConstraintError; return 0; } if (!keyPath.isNull() && !keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return 0; } if (autoIncrement && ((keyPath.type() == IDBKeyPath::StringType && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::ArrayType)) { ec = IDBDatabaseException::InvalidAccessError; return 0; } int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId, name, keyPath, autoIncrement); IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, IDBDatabaseBackendInterface::MinimumIndexId); RefPtr<IDBObjectStore> objectStore = IDBObjectStore::create(metadata, m_versionChangeTransaction.get()); m_metadata.objectStores.set(metadata.id, metadata); ++m_metadata.maxObjectStoreId; m_versionChangeTransaction->objectStoreCreated(name, objectStore); return objectStore.release(); }
RefPtr<IDBObjectStore> LegacyDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionCode& ec) { LOG(StorageAPI, "LegacyDatabase::createObjectStore"); if (!m_versionChangeTransaction) { ec = IDBDatabaseException::InvalidStateError; return 0; } if (!m_versionChangeTransaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return 0; } if (containsObjectStore(name)) { ec = IDBDatabaseException::ConstraintError; return 0; } if (!keyPath.isNull() && !keyPath.isValid()) { ec = IDBDatabaseException::SyntaxError; return 0; } if (autoIncrement && ((keyPath.type() == IDBKeyPath::StringType && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::ArrayType)) { ec = IDBDatabaseException::InvalidAccessError; return 0; } int64_t objectStoreId = m_metadata.maxObjectStoreId + 1; m_backend->createObjectStore(m_versionChangeTransaction->id(), objectStoreId, name, keyPath, autoIncrement); IDBObjectStoreMetadata metadata(name, objectStoreId, keyPath, autoIncrement, IDBDatabaseBackend::MinimumIndexId); RefPtr<LegacyObjectStore> objectStore = LegacyObjectStore::create(metadata, m_versionChangeTransaction.get()); m_metadata.objectStores.set(metadata.id, metadata); ++m_metadata.maxObjectStoreId; m_versionChangeTransaction->objectStoreCreated(name, objectStore); return objectStore.release(); }
bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value> value, const IDBKeyPath& keyPath, v8::Isolate* isolate) { IDB_TRACE("injectIDBV8KeyIntoV8Value"); ASSERT(isolate->InContext()); ASSERT(keyPath.type() == IDBKeyPath::StringType); Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath.string(), keyPathElements, error); ASSERT(error == IDBKeyPathParseErrorNone); if (!keyPathElements.size()) return false; v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(value, keyPathElements, keyPathElements.size() - 1, isolate)); if (parent.IsEmpty()) return false; if (!set(parent, keyPathElements.last(), key, isolate)) return false; return true; }