indexeddb: implement "inject a key into a value using a key path with value"#42727
Conversation
|
🔨 Triggering try run (#22224222289) for Linux (WPT) |
|
Test results for linux-wpt from try job (#22224222289): Flaky unexpected result (31)
Stable unexpected results that are known to be intermittent (27)
Stable unexpected results (12)
|
|
|
|
🔨 Triggering try run (#22226175278) for Linux (WPT) |
|
Test results for linux-wpt from try job (#22226175278): Flaky unexpected result (26)
Stable unexpected results that are known to be intermittent (19)
|
|
✨ Try run (#22226175278) succeeded. |
| // be injected into a value with clone and store’s key path return | ||
| // false, throw a "DataError" DOMException. | ||
| // TODO | ||
| let generated_key = self.generate_key()?; |
There was a problem hiding this comment.
I need to refresh my memory here a bit. Also, if we really need to synchronously ask backend to generate a key and what happens when the whole add/put operation fails (or the transaction is aborted).
There was a problem hiding this comment.
on failure or abort spec expects transaction rollback to undo both record changes and key generator effects,
ccurrently backend has TODO in abort/rollback, so this is not fully spec correct yet.
| match extraction_result { | ||
| Some(Ok(ExtractionResult::Failure)) | None => { | ||
| Some(Ok(ExtractionResult::Failure)) => { | ||
| // Step 11.4. Otherwise: |
There was a problem hiding this comment.
It looks to me that the injection happens on the original object. Can you clarify if this is done on purpose (like having initial support to make more WPT pass and it will be fixed later?)
The current order of steps seem to confirm wrong order as well (8, 11, 10).
Also, I think this was discussed quite a bit in "Fixing indexeddb intermittency (architecture)" on Zulip, Gregory provided very useful info there.
gterzian
left a comment
There was a problem hiding this comment.
LGTM with some comments, mostly for follow-ups.
| } | ||
|
|
||
| fn generate_key(&self) -> Fallible<IndexedDBKeyType> { | ||
| // FIXME: blocking IPC call ? how ? |
There was a problem hiding this comment.
I think the generator itself can be in script, but the effect needs to be stored in the database as part of finalizing the transaction. See https://w3c.github.io/IndexedDB/#key-generator
Modifying a key generator’s current number is considered part of a database operation. This means that if the operation fails and the operation is reverted, the current number is reverted to the value it had before the operation started.
and when a dom object store is created from one existing already in the database, then it would need to start with the number stored in the db.
Interesting follow-up.
There was a problem hiding this comment.
Well, the sync/blocking IPC could be avoided, if the backend would be able to inject the key, if I read the spec correctly it says that script should only "check that a key could be injected into a value", actual injection happens as part of the operation executed in the backend.
| rooted!(&in(cx) let mut o_value = UndefinedValue()); | ||
| o.safe_to_jsval(cx, o_value.handle_mut()); | ||
|
|
||
| // Step 4.3.2 Let status be CreateDataProperty(value, identifier, o). |
There was a problem hiding this comment.
For CreateDataProperty I have in the past used:
servo/components/script/dom/messageport.rs
Line 225 in 7dcfdcc
There was a problem hiding this comment.
I think should be JS_DefineProperty and I defined define_dictionary_property for that
| // Step 4.3.3 Assert: status is true. | ||
| } | ||
|
|
||
| // Step 4.3 Let value be ! Get(value, identifier). |
There was a problem hiding this comment.
servo/components/script_bindings/utils.rs
Line 245 in 7dcfdcc
You can try to use the above.
| // Step 4.2 Let hop be ! HasOwnProperty(value, identifier). | ||
| let mut hop = false; | ||
| if !unsafe { | ||
| JS_HasOwnProperty( |
There was a problem hiding this comment.
We could add safe variants to this in script_bindings/utils.rs I think since the context is safe. Probably more for a follow-up.
|
Let me double check the injection one more time ... |
5b7e8c3 to
f35d21c
Compare
|
🔨 Triggering try run (#22490194289) for Linux (WPT) |
| // Step 10. Let clone be a clone of value in targetRealm during transaction. Rethrow any exceptions. | ||
| let mut cloned_value = structuredclone::write(cx.into(), value, None)?; | ||
|
|
||
| // Step 8: If key was given, then: convert a value to a key with key |
| // a "DataError" DOMException. | ||
| match self.key_path.as_ref() { | ||
| Some(key_path) => { | ||
| rooted!(&in(cx) let mut cloned_js_value = NullValue()); |
There was a problem hiding this comment.
Looks like the extra deserialization and serialization could be avoided in future, maybe add a TODO for that?
| } | ||
|
|
||
| fn generate_key(&self) -> Fallible<IndexedDBKeyType> { | ||
| // FIXME: blocking IPC call ? how ? |
There was a problem hiding this comment.
Well, the sync/blocking IPC could be avoided, if the backend would be able to inject the key, if I read the spec correctly it says that script should only "check that a key could be injected into a value", actual injection happens as part of the operation executed in the backend.
| let KeyPath::String(key_path) = key_path else { | ||
| return Err(Error::Data(None)); | ||
| }; | ||
| if !inject_key_into_value( |
There was a problem hiding this comment.
This is ok for now, but I think 11.4.2. is just about checking if a key can injected. Maybe add a TODO comment for that?
| } | ||
| serialized_key = Some(generated_key); | ||
| }, | ||
| // Step 11.2. If kpk is invalid, throw a "DataError" DOMException. |
There was a problem hiding this comment.
Super NIT: these arms could be moved above, so the comments "Step 11.2, Step 11.3, Step 11.4" would be in order
|
Test results for linux-wpt from try job (#22490194289): Flaky unexpected result (32)
Stable unexpected results that are known to be intermittent (16)
Stable unexpected results (11)
|
|
|
…value Signed-off-by: Taym Haddadi <[email protected]>
Signed-off-by: Taym Haddadi <[email protected]>
…not on the original JS object Signed-off-by: Taym Haddadi <[email protected]>
Signed-off-by: Taym Haddadi <[email protected]>
…helpers Signed-off-by: Taym Haddadi <[email protected]>
f35d21c to
e435447
Compare
|
🔨 Triggering try run (#22595193968) for Linux (WPT) |
|
Test results for linux-wpt from try job (#22595193968): Flaky unexpected result (36)
Stable unexpected results that are known to be intermittent (17)
Stable unexpected results (2)
|
|
|
…perty paths Signed-off-by: Taym Haddadi <[email protected]>
… value" (servo#42727) implement "inject a key into a value using a key path with value" following he spec: https://w3c.github.io/IndexedDB/#inject-a-key-into-a-value-using-a-key-path Testing: More indexeddb tests should pass. part of servo#40983 --------- Signed-off-by: Taym Haddadi <[email protected]>
… value" (servo#42727) implement "inject a key into a value using a key path with value" following he spec: https://w3c.github.io/IndexedDB/#inject-a-key-into-a-value-using-a-key-path Testing: More indexeddb tests should pass. part of servo#40983 --------- Signed-off-by: Taym Haddadi <[email protected]>
implement "inject a key into a value using a key path with value" following he spec:
https://w3c.github.io/IndexedDB/#inject-a-key-into-a-value-using-a-key-path
Testing: More indexeddb tests should pass.
part of #40983