Title: [279767] trunk
Revision
279767
Author
cdu...@apple.com
Date
2021-07-08 17:11:20 -0700 (Thu, 08 Jul 2021)

Log Message

[IndexedDB] KeyPath validity checks should happen on the cloned value, not the original one
https://bugs.webkit.org/show_bug.cgi?id=227813

Reviewed by Geoffrey Garen.

LayoutTests/imported/w3c:

Rebaseline WPT test that is now passing.

* web-platform-tests/IndexedDB/clone-before-keypath-eval-expected.txt:

Source/WebCore:

KeyPath validity checks should happen on the cloned value, not the original one:
- https://www.w3.org/TR/IndexedDB/#add-or-put (Step 11.1)
- https://www.w3.org/TR/IndexedDB/#dom-idbcursor-update (Step 9.1)

This was causing the following WPT test to fail in WebKit:
https://wpt.live/IndexedDB/clone-before-keypath-eval.html

This test is passing in Chrome and Gecko.

No new tests, rebaselined existing test.

* Modules/indexeddb/IDBCursor.cpp:
(WebCore::IDBCursor::update):
* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::putForCursorUpdate):
(WebCore::IDBObjectStore::putOrAdd):
* Modules/indexeddb/IDBObjectStore.h:

LayoutTests:

Unskip test as it should no longer be flaky.

* TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (279766 => 279767)


--- trunk/LayoutTests/ChangeLog	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/LayoutTests/ChangeLog	2021-07-09 00:11:20 UTC (rev 279767)
@@ -1,3 +1,14 @@
+2021-07-08  Chris Dumez  <cdu...@apple.com>
+
+        [IndexedDB] KeyPath validity checks should happen on the cloned value, not the original one
+        https://bugs.webkit.org/show_bug.cgi?id=227813
+
+        Reviewed by Geoffrey Garen.
+
+        Unskip test as it should no longer be flaky.
+
+        * TestExpectations:
+
 2021-07-08  Carlos Alberto Lopez Perez  <clo...@igalia.com>
 
         [GTK][WPE] Gardening of tests after r279585 and 279705

Modified: trunk/LayoutTests/TestExpectations (279766 => 279767)


--- trunk/LayoutTests/TestExpectations	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/LayoutTests/TestExpectations	2021-07-09 00:11:20 UTC (rev 279767)
@@ -1431,7 +1431,6 @@
 # Flaky tests at import time
 imported/w3c/web-platform-tests/css/css-scoping/css-scoping-shadow-host-namespace.html [ ImageOnlyFailure ]
 imported/w3c/web-platform-tests/IndexedDB/abort-in-initial-upgradeneeded.html [ Pass Failure ]
-imported/w3c/web-platform-tests/IndexedDB/clone-before-keypath-eval.html [ Pass Failure ]
 
 # Those WPT tests are flaky when failing.
 imported/w3c/web-platform-tests/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html [ Pass Failure ]

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (279766 => 279767)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-07-09 00:11:20 UTC (rev 279767)
@@ -1,3 +1,14 @@
+2021-07-08  Chris Dumez  <cdu...@apple.com>
+
+        [IndexedDB] KeyPath validity checks should happen on the cloned value, not the original one
+        https://bugs.webkit.org/show_bug.cgi?id=227813
+
+        Reviewed by Geoffrey Garen.
+
+        Rebaseline WPT test that is now passing.
+
+        * web-platform-tests/IndexedDB/clone-before-keypath-eval-expected.txt:
+
 2021-07-08  Alex Christensen  <achristen...@webkit.org>
 
         Fix some whitespace handling issues in URL setters

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/clone-before-keypath-eval-expected.txt (279766 => 279767)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/clone-before-keypath-eval-expected.txt	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/clone-before-keypath-eval-expected.txt	2021-07-09 00:11:20 UTC (rev 279767)
@@ -1,7 +1,7 @@
 
-FAIL Key generator and key path validity check operates on a clone assert_equals: put() operation should access primary key property once expected 1 but got 2
-FAIL Failing key path validity check operates on a clone assert_equals: put() operation should access primary key property once expected 1 but got 2
+PASS Key generator and key path validity check operates on a clone
+PASS Failing key path validity check operates on a clone
 PASS Index key path evaluations operate on a clone
-FAIL Store and index key path evaluations operate on the same clone assert_equals: put() should access primary key property once expected 1 but got 2
-FAIL Cursor update checks and keypath evaluations operate on a clone Failed to execute 'update' on 'IDBCursor': The effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key.
+PASS Store and index key path evaluations operate on the same clone
+PASS Cursor update checks and keypath evaluations operate on a clone
 

Modified: trunk/Source/WebCore/ChangeLog (279766 => 279767)


--- trunk/Source/WebCore/ChangeLog	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/Source/WebCore/ChangeLog	2021-07-09 00:11:20 UTC (rev 279767)
@@ -1,3 +1,28 @@
+2021-07-08  Chris Dumez  <cdu...@apple.com>
+
+        [IndexedDB] KeyPath validity checks should happen on the cloned value, not the original one
+        https://bugs.webkit.org/show_bug.cgi?id=227813
+
+        Reviewed by Geoffrey Garen.
+
+        KeyPath validity checks should happen on the cloned value, not the original one:
+        - https://www.w3.org/TR/IndexedDB/#add-or-put (Step 11.1)
+        - https://www.w3.org/TR/IndexedDB/#dom-idbcursor-update (Step 9.1)
+
+        This was causing the following WPT test to fail in WebKit:
+        https://wpt.live/IndexedDB/clone-before-keypath-eval.html
+
+        This test is passing in Chrome and Gecko.
+
+        No new tests, rebaselined existing test.
+
+        * Modules/indexeddb/IDBCursor.cpp:
+        (WebCore::IDBCursor::update):
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::putForCursorUpdate):
+        (WebCore::IDBObjectStore::putOrAdd):
+        * Modules/indexeddb/IDBObjectStore.h:
+
 2021-07-08  Simon Fraser  <simon.fra...@apple.com>
 
         Make backingProviderLayerCanIncludeLayer() a member function of BackingSharingState

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (279766 => 279767)


--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp	2021-07-09 00:11:20 UTC (rev 279767)
@@ -36,6 +36,7 @@
 #include "IDBTransaction.h"
 #include "Logging.h"
 #include "ScriptExecutionContext.h"
+#include "SerializedScriptValue.h"
 #include <_javascript_Core/HeapInlines.h>
 #include <_javascript_Core/JSCJSValueInlines.h>
 #include <_javascript_Core/StrongInlines.h>
@@ -119,17 +120,30 @@
     if (!isKeyCursorWithValue())
         return Exception { InvalidStateError, "Failed to execute 'update' on 'IDBCursor': The cursor is a key cursor."_s };
 
+    VM& vm = state.vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
+    // Transaction should be inactive during structured clone.
+    Ref transaction = effectiveObjectStore().transaction();
+    transaction->deactivate();
+    auto serializedValue = SerializedScriptValue::create(state, value);
+    transaction->activate();
+
+    if (UNLIKELY(scope.exception()))
+        return Exception { DataCloneError, "Failed to store record in an IDBObjectStore: An object could not be cloned."_s };
+
     auto& objectStore = effectiveObjectStore();
     auto& optionalKeyPath = objectStore.info().keyPath();
     const bool usesInLineKeys = !!optionalKeyPath;
     if (usesInLineKeys) {
-        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, optionalKeyPath.value());
+        auto clonedValue = serializedValue->deserialize(state, &state, SerializationErrorMode::NonThrowing);
+        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, clonedValue, optionalKeyPath.value());
         IDBKeyData keyPathKeyData(keyPathKey.get());
         if (!keyPathKey || keyPathKeyData != m_primaryKeyData)
             return Exception { DataError, "Failed to execute 'update' on 'IDBCursor': The effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key."_s };
     }
 
-    auto putResult = effectiveObjectStore().putForCursorUpdate(state, value, m_primaryKey.copyRef());
+    auto putResult = effectiveObjectStore().putForCursorUpdate(state, value, m_primaryKey.copyRef(), WTFMove(serializedValue));
     if (putResult.hasException())
         return putResult.releaseException();
 

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp (279766 => 279767)


--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp	2021-07-09 00:11:20 UTC (rev 279767)
@@ -309,12 +309,12 @@
     return putOrAdd(execState, value, idbKey, IndexedDB::ObjectStoreOverwriteMode::Overwrite, InlineKeyCheck::Perform);
 }
 
-ExceptionOr<Ref<IDBRequest>> IDBObjectStore::putForCursorUpdate(JSGlobalObject& state, JSValue value, RefPtr<IDBKey> key)
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::putForCursorUpdate(JSGlobalObject& state, JSValue value, RefPtr<IDBKey>&& key, RefPtr<SerializedScriptValue>&& serializedValue)
 {
-    return putOrAdd(state, value, WTFMove(key), IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor, InlineKeyCheck::DoNotPerform);
+    return putOrAdd(state, value, WTFMove(key), IndexedDB::ObjectStoreOverwriteMode::OverwriteForCursor, InlineKeyCheck::DoNotPerform, WTFMove(serializedValue));
 }
 
-ExceptionOr<Ref<IDBRequest>> IDBObjectStore::putOrAdd(JSGlobalObject& state, JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, InlineKeyCheck inlineKeyCheck)
+ExceptionOr<Ref<IDBRequest>> IDBObjectStore::putOrAdd(JSGlobalObject& state, JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, InlineKeyCheck inlineKeyCheck, RefPtr<SerializedScriptValue>&& serializedValue)
 {
     VM& vm = state.vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
@@ -335,10 +335,12 @@
     if (m_transaction.isReadOnly())
         return Exception { ReadonlyError, "Failed to store record in an IDBObjectStore: The transaction is read-only."_s };
 
-    // Transaction should be inactive during structured clone.
-    m_transaction.deactivate();
-    auto serializedValue = SerializedScriptValue::create(state, value);
-    m_transaction.activate();
+    if (!serializedValue) {
+        // Transaction should be inactive during structured clone.
+        m_transaction.deactivate();
+        serializedValue = SerializedScriptValue::create(state, value);
+        m_transaction.activate();
+    }
 
     if (UNLIKELY(scope.exception()))
         return Exception { DataCloneError, "Failed to store record in an IDBObjectStore: An object could not be cloned."_s };
@@ -363,7 +365,8 @@
         if (key)
             return Exception { DataError, "Failed to store record in an IDBObjectStore: The object store uses in-line keys and the key parameter was provided."_s };
 
-        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath().value());
+        auto clonedValue = serializedValue->deserialize(state, &state, SerializationErrorMode::NonThrowing);
+        RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, clonedValue, m_info.keyPath().value());
         if (keyPathKey && !keyPathKey->isValid())
             return Exception { DataError, "Failed to store record in an IDBObjectStore: Evaluating the object store's key path yielded a value that is not a valid key."_s };
 
@@ -370,7 +373,7 @@
         if (!keyPathKey) {
             if (!usesKeyGenerator)
                 return Exception { DataError, "Failed to store record in an IDBObjectStore: Evaluating the object store's key path did not yield a value."_s };
-            if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath().value()))
+            if (!canInjectIDBKeyIntoScriptValue(state, clonedValue, m_info.keyPath().value()))
                 return Exception { DataError };
         }
 

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h (279766 => 279767)


--- trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h	2021-07-09 00:09:23 UTC (rev 279766)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h	2021-07-09 00:11:20 UTC (rev 279767)
@@ -48,6 +48,7 @@
 class IDBKeyRange;
 class IDBRequest;
 class IDBTransaction;
+class SerializedScriptValue;
 
 struct IDBKeyRangeData;
 
@@ -96,7 +97,7 @@
     ExceptionOr<Ref<IDBRequest>> getAllKeys(JSC::JSGlobalObject&, RefPtr<IDBKeyRange>&&, std::optional<uint32_t> count);
     ExceptionOr<Ref<IDBRequest>> getAllKeys(JSC::JSGlobalObject&, JSC::JSValue key, std::optional<uint32_t> count);
 
-    ExceptionOr<Ref<IDBRequest>> putForCursorUpdate(JSC::JSGlobalObject&, JSC::JSValue, RefPtr<IDBKey>);
+    ExceptionOr<Ref<IDBRequest>> putForCursorUpdate(JSC::JSGlobalObject&, JSC::JSValue, RefPtr<IDBKey>&&, RefPtr<SerializedScriptValue>&&);
 
     void markAsDeleted();
     bool isDeleted() const { return m_deleted; }
@@ -113,7 +114,7 @@
 
 private:
     enum class InlineKeyCheck { Perform, DoNotPerform };
-    ExceptionOr<Ref<IDBRequest>> putOrAdd(JSC::JSGlobalObject&, JSC::JSValue, RefPtr<IDBKey>, IndexedDB::ObjectStoreOverwriteMode, InlineKeyCheck);
+    ExceptionOr<Ref<IDBRequest>> putOrAdd(JSC::JSGlobalObject&, JSC::JSValue, RefPtr<IDBKey>, IndexedDB::ObjectStoreOverwriteMode, InlineKeyCheck, RefPtr<SerializedScriptValue>&& = nullptr);
     ExceptionOr<Ref<IDBRequest>> doCount(JSC::JSGlobalObject&, const IDBKeyRangeData&);
     ExceptionOr<Ref<IDBRequest>> doDelete(JSC::JSGlobalObject&, WTF::Function<ExceptionOr<RefPtr<IDBKeyRange>>()> &&);
     ExceptionOr<Ref<IDBRequest>> doOpenCursor(JSC::JSGlobalObject&, IDBCursorDirection, WTF::Function<ExceptionOr<RefPtr<IDBKeyRange>>()>&&);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to