Diff
Modified: trunk/LayoutTests/ChangeLog (192797 => 192798)
--- trunk/LayoutTests/ChangeLog 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/LayoutTests/ChangeLog 2015-11-30 18:11:34 UTC (rev 192798)
@@ -1,3 +1,12 @@
+2015-11-30 Brady Eidson <beid...@apple.com>
+
+ Modern IDB: Support keyPath injection into object store records.
+ https://bugs.webkit.org/show_bug.cgi?id=151640
+
+ Reviewed by Andy Estes.
+
+ * platform/mac-wk1/TestExpectations:
+
2015-11-29 Antoine Quint <grao...@apple.com>
Browser does not fall back to SVG attribute value when CSS style value is invalid or not supported
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (192797 => 192798)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2015-11-30 18:11:34 UTC (rev 192798)
@@ -73,6 +73,7 @@
# But Modern IndexedDB is.
storage/indexeddb/modern [ Pass ]
storage/indexeddb/mozilla/add-twice-failure.html [ Pass ]
+storage/indexeddb/mozilla/autoincrement-indexes.html [ Pass ]
storage/indexeddb/mozilla/bad-keypath.html [ Pass ]
storage/indexeddb/mozilla/create-index-unique.html [ Pass ]
storage/indexeddb/mozilla/create-index-with-integer-keys.html [ Pass ]
Modified: trunk/Source/WebCore/ChangeLog (192797 => 192798)
--- trunk/Source/WebCore/ChangeLog 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/ChangeLog 2015-11-30 18:11:34 UTC (rev 192798)
@@ -1,3 +1,35 @@
+2015-11-30 Brady Eidson <beid...@apple.com>
+
+ Modern IDB: Support keyPath injection into object store records.
+ https://bugs.webkit.org/show_bug.cgi?id=151640
+
+ Reviewed by Andy Estes.
+
+ No new tests (At least one existing failure now passes and is unskipped,
+ while many other existing failures are now closer to passing).
+
+ * Modules/indexeddb/server/MemoryObjectStore.cpp:
+ (WebCore::IDBServer::MemoryObjectStore::updateIndexesForPutRecord): Use the new UniqueIDBDatabase VM/ExecState.
+ (WebCore::IDBServer::MemoryObjectStore::populateIndexWithExistingRecords): Ditto
+ (WebCore::IDBServer::indexVM): Deleted.
+ (WebCore::IDBServer::indexGlobalExec): Deleted.
+
+ * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+ (WebCore::IDBServer::UniqueIDBDatabase::databaseThreadVM):
+ (WebCore::IDBServer::UniqueIDBDatabase::databaseThreadExecState):
+ (WebCore::IDBServer::UniqueIDBDatabase::performPutOrAdd): If appropriate, inject the key that will be used into
+ the value before storing the record.
+ * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
+ Add modern JSValue/ExecState& version of some binding utilities, for use today and in preparation of getting
+ rid of the DOMRequestState and Deprecated::ScriptValue versions later:
+ * bindings/js/IDBBindingUtilities.cpp:
+ (WebCore::idbKeyToJSValue):
+ (WebCore::injectIDBKeyIntoScriptValue):
+ (WebCore::deserializeIDBValueData):
+ (WebCore::deserializeIDBValueDataToJSValue):
+ * bindings/js/IDBBindingUtilities.h:
+
2015-11-25 Andy Estes <aes...@apple.com>
[Content Filtering] Avoid creating a ContentFilter when loading the empty document
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp (192797 => 192798)
--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp 2015-11-30 18:11:34 UTC (rev 192798)
@@ -35,6 +35,7 @@
#include "IndexKey.h"
#include "Logging.h"
#include "MemoryBackingStoreTransaction.h"
+#include "UniqueIDBDatabase.h"
#include <wtf/NeverDestroyed.h>
@@ -267,27 +268,6 @@
return error;
}
-static VM& indexVM()
-{
- ASSERT(!isMainThread());
- static NeverDestroyed<RefPtr<VM>> vm = VM::create();
- return *vm.get();
-}
-
-static ExecState& indexGlobalExec()
-{
- ASSERT(!isMainThread());
- static NeverDestroyed<Strong<JSGlobalObject>> globalObject;
- static bool initialized = false;
- if (!initialized) {
- globalObject.get().set(indexVM(), JSGlobalObject::create(indexVM(), JSGlobalObject::createStructure(indexVM(), jsNull())));
- initialized = true;
- }
-
- RELEASE_ASSERT(globalObject.get()->globalExec());
- return *globalObject.get()->globalExec();
-}
-
void MemoryObjectStore::updateCursorsForPutRecord(std::set<IDBKeyData>::iterator iterator)
{
for (auto& cursor : m_cursors.values())
@@ -308,9 +288,9 @@
IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value)
{
- JSLockHolder locker(indexVM());
+ JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
- auto jsValue = idbValueDataToJSValue(indexGlobalExec(), value);
+ auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), value);
if (jsValue.isUndefinedOrNull())
return { };
@@ -319,7 +299,7 @@
for (auto* index : m_indexesByName.values()) {
IndexKey indexKey;
- generateIndexKeyForValue(indexGlobalExec(), index->info(), jsValue, indexKey);
+ generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index->info(), jsValue, indexKey);
if (indexKey.isNull())
continue;
@@ -340,21 +320,20 @@
return error;
}
-
IDBError MemoryObjectStore::populateIndexWithExistingRecords(MemoryIndex& index)
{
if (!m_keyValueStore)
return { };
- JSLockHolder locker(indexVM());
+ JSLockHolder locker(UniqueIDBDatabase::databaseThreadVM());
for (auto iterator : *m_keyValueStore) {
- auto jsValue = idbValueDataToJSValue(indexGlobalExec(), iterator.value);
+ auto jsValue = idbValueDataToJSValue(UniqueIDBDatabase::databaseThreadExecState(), iterator.value);
if (jsValue.isUndefinedOrNull())
return { };
IndexKey indexKey;
- generateIndexKeyForValue(indexGlobalExec(), index.info(), jsValue, indexKey);
+ generateIndexKeyForValue(UniqueIDBDatabase::databaseThreadExecState(), index.info(), jsValue, indexKey);
if (indexKey.isNull())
continue;
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (192797 => 192798)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2015-11-30 18:11:34 UTC (rev 192798)
@@ -36,8 +36,11 @@
#include "Logging.h"
#include "UniqueIDBDatabaseConnection.h"
#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/ThreadSafeRefCounted.h>
+using namespace JSC;
+
namespace WebCore {
namespace IDBServer {
@@ -479,9 +482,26 @@
m_server.postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, valueData, overwriteMode));
}
-void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& valueData, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
+VM& UniqueIDBDatabase::databaseThreadVM()
{
ASSERT(!isMainThread());
+ static VM* vm = &VM::create().leakRef();
+ return *vm;
+}
+
+ExecState& UniqueIDBDatabase::databaseThreadExecState()
+{
+ ASSERT(!isMainThread());
+
+ static NeverDestroyed<Strong<JSGlobalObject>> globalObject(databaseThreadVM(), JSGlobalObject::create(databaseThreadVM(), JSGlobalObject::createStructure(databaseThreadVM(), jsNull())));
+
+ RELEASE_ASSERT(globalObject.get()->globalExec());
+ return *globalObject.get()->globalExec();
+}
+
+void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const ThreadSafeDataBuffer& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
+{
+ ASSERT(!isMainThread());
LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
ASSERT(m_backingStore);
@@ -497,6 +517,7 @@
return;
}
+ bool usedKeyIsGenerated = false;
if (objectStoreInfo->autoIncrement() && !keyData.isValid()) {
uint64_t keyNumber;
error = m_backingStore->generateKeyNumber(transactionIdentifier, objectStoreIdentifier, keyNumber);
@@ -506,6 +527,7 @@
}
usedKey.setNumberValue(keyNumber);
+ usedKeyIsGenerated = true;
} else
usedKey = keyData;
@@ -521,6 +543,33 @@
}
}
+ // 3.4.1.2 Object Store Storage Operation
+ // If ObjectStore has a key path and the key is autogenerated, then inject the key into the value
+ // using steps to assign a key to a value using a key path.
+ ThreadSafeDataBuffer injectedRecordValue;
+ if (usedKeyIsGenerated && !objectStoreInfo->keyPath().isNull()) {
+ JSLockHolder locker(databaseThreadVM());
+
+ JSValue value = deserializeIDBValueDataToJSValue(databaseThreadExecState(), originalRecordValue);
+ if (value.isUndefined()) {
+ m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBExceptionCode::ConstraintError, ASCIILiteral("Unable to deserialize record value for record key injection")), usedKey));
+ return;
+ }
+
+ if (!injectIDBKeyIntoScriptValue(databaseThreadExecState(), usedKey, value, objectStoreInfo->keyPath())) {
+ m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBExceptionCode::ConstraintError, ASCIILiteral("Unable to inject record key into record value")), usedKey));
+ return;
+ }
+
+ auto serializedValue = SerializedScriptValue::create(&databaseThreadExecState(), value, nullptr, nullptr);
+ if (databaseThreadExecState().hadException()) {
+ m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(IDBExceptionCode::ConstraintError, ASCIILiteral("Unable to serialize record value after injecting record key")), usedKey));
+ return;
+ }
+
+ injectedRecordValue = ThreadSafeDataBuffer::copyVector(serializedValue->data());
+ }
+
// 3.4.1 Object Store Storage Operation
// ...If a record already exists in store ...
// then remove the record from store using the steps for deleting records from an object store...
@@ -531,7 +580,7 @@
return;
}
- error = m_backingStore->addRecord(transactionIdentifier, objectStoreIdentifier, usedKey, valueData);
+ error = m_backingStore->addRecord(transactionIdentifier, objectStoreIdentifier, usedKey, injectedRecordValue.data() ? injectedRecordValue : originalRecordValue);
m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, error, usedKey));
}
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h (192797 => 192798)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2015-11-30 18:11:34 UTC (rev 192798)
@@ -29,6 +29,7 @@
#if ENABLE(INDEXED_DATABASE)
#include "IDBBackingStore.h"
+#include "IDBBindingUtilities.h"
#include "IDBDatabaseIdentifier.h"
#include "IDBDatabaseInfo.h"
#include "IDBGetResult.h"
@@ -97,6 +98,9 @@
void handleDelete(IDBConnectionToClient&, const IDBRequestData&);
bool deletePending() const { return m_deletePending; }
+ static JSC::VM& databaseThreadVM();
+ static JSC::ExecState& databaseThreadExecState();
+
private:
UniqueIDBDatabase(IDBServer&, const IDBDatabaseIdentifier&);
Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp (192797 => 192798)
--- trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp 2015-11-30 18:11:34 UTC (rev 192798)
@@ -115,7 +115,7 @@
}
-static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject, IDBKey* key)
+static JSValue idbKeyToJSValue(ExecState* exec, JSGlobalObject* globalObject, IDBKey* key)
{
if (!key || !exec) {
// This should be undefined, not null.
@@ -294,12 +294,40 @@
if (parent.isUndefined())
return false;
- if (!set(exec, parent, keyPathElements.last(), idbKeyToJSValue(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), key.get())))
+ 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;
+}
+
RefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(ExecState* exec, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath)
{
LOG(StorageAPI, "createIDBKeyFromScriptValueAndKeyPath");
@@ -409,21 +437,26 @@
if (!execState)
return Deprecated::ScriptValue();
+ return Deprecated::ScriptValue(execState->vm(), deserializeIDBValueDataToJSValue(*execState, valueData));
+}
+
+JSC::JSValue deserializeIDBValueDataToJSValue(JSC::ExecState& exec, const ThreadSafeDataBuffer& valueData)
+{
if (!valueData.data())
- return Deprecated::ScriptValue(execState->vm(), jsUndefined());
+ return jsUndefined();
const Vector<uint8_t>& data = ""
JSValue result;
if (data.size()) {
RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(data);
- execState->vm().apiLock().lock();
- result = serializedValue->deserialize(execState, execState->lexicalGlobalObject(), 0, NonThrowing);
- execState->vm().apiLock().unlock();
+ exec.vm().apiLock().lock();
+ result = serializedValue->deserialize(&exec, exec.lexicalGlobalObject(), 0, NonThrowing);
+ exec.vm().apiLock().unlock();
} else
result = jsNull();
- return Deprecated::ScriptValue(execState->vm(), result);
+ return result;
}
Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState* requestState, PassRefPtr<SharedBuffer> prpBuffer, bool keyIsDefined)
Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h (192797 => 192798)
--- trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h 2015-11-30 18:06:23 UTC (rev 192797)
+++ trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h 2015-11-30 18:11:34 UTC (rev 192798)
@@ -48,6 +48,7 @@
IDBKeyPath idbKeyPathFromValue(JSC::ExecState*, JSC::JSValue);
bool injectIDBKeyIntoScriptValue(DOMRequestState*, PassRefPtr<IDBKey>, Deprecated::ScriptValue&, const IDBKeyPath&);
+bool injectIDBKeyIntoScriptValue(JSC::ExecState&, const IDBKeyData&, JSC::JSValue, const IDBKeyPath&);
RefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(JSC::ExecState*, const Deprecated::ScriptValue&, const IDBKeyPath&);
RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(JSC::ExecState&, const Deprecated::ScriptValue&, const IDBKeyPath&);
@@ -61,6 +62,8 @@
Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState*, PassRefPtr<SharedBuffer>, bool keyIsDefined);
WEBCORE_EXPORT Deprecated::ScriptValue deserializeIDBValueBuffer(JSC::ExecState*, const Vector<uint8_t>&, bool keyIsDefined);
+JSC::JSValue deserializeIDBValueDataToJSValue(JSC::ExecState&, const ThreadSafeDataBuffer& valueData);
+
Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>);
RefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const JSC::JSValue&);
RefPtr<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);