already_AddRefed<IDBObjectStore> IDBTransaction::CreateObjectStore(const ObjectStoreSpec& aSpec) { AssertIsOnOwningThread(); MOZ_ASSERT(aSpec.metadata().id()); MOZ_ASSERT(VERSION_CHANGE == mMode); MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor); MOZ_ASSERT(IsOpen()); #ifdef DEBUG { const nsString& name = aSpec.metadata().name(); for (uint32_t count = mObjectStores.Length(), index = 0; index < count; index++) { MOZ_ASSERT(mObjectStores[index]->Name() != name); } } #endif MOZ_ALWAYS_TRUE(mBackgroundActor.mVersionChangeBackgroundActor-> SendCreateObjectStore(aSpec.metadata())); nsRefPtr<IDBObjectStore> objectStore = IDBObjectStore::Create(this, aSpec); MOZ_ASSERT(objectStore); mObjectStores.AppendElement(objectStore); return objectStore.forget(); }
already_AddRefed<IDBObjectStore> IDBDatabase::CreateObjectStore( const nsAString& aName, const IDBObjectStoreParameters& aOptionalParameters, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = IDBTransaction::GetCurrent(); if (!transaction || transaction->Database() != this || transaction->GetMode() != IDBTransaction::VERSION_CHANGE) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } KeyPath keyPath(0); if (NS_FAILED(KeyPath::Parse(aOptionalParameters.mKeyPath, &keyPath))) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores(); for (uint32_t count = objectStores.Length(), index = 0; index < count; index++) { if (aName == objectStores[index].metadata().name()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR); return nullptr; } } if (!keyPath.IsAllowedForObjectStore(aOptionalParameters.mAutoIncrement)) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return nullptr; } const ObjectStoreSpec* oldSpecElements = objectStores.IsEmpty() ? nullptr : objectStores.Elements(); ObjectStoreSpec* newSpec = objectStores.AppendElement(); newSpec->metadata() = ObjectStoreMetadata(transaction->NextObjectStoreId(), nsString(aName), keyPath, aOptionalParameters.mAutoIncrement); if (oldSpecElements && oldSpecElements != objectStores.Elements()) { MOZ_ASSERT(objectStores.Length() > 1); // Array got moved, update the spec pointers for all live objectStores and // indexes. RefreshSpec(/* aMayDelete */ false); } RefPtr<IDBObjectStore> objectStore = transaction->CreateObjectStore(*newSpec); MOZ_ASSERT(objectStore); // Don't do this in the macro because we always need to increment the serial // number to keep in sync with the parent. const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).createObjectStore(%s)", "IndexedDB %s: C T[%lld] R[%llu]: " "IDBDatabase.createObjectStore()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(objectStore)); return objectStore.forget(); }