Make "seen" list of objects in "clone an object" compliant to the WebDriver spec
Categories
(Remote Protocol :: Marionette, defect, P1)
Tracking
(firefox110 fixed)
Tracking | Status | |
---|---|---|
firefox110 | --- | fixed |
People
(Reporter: whimboo, Assigned: whimboo)
References
(Blocks 2 open bugs, )
Details
(Whiteboard: [webdriver:m5][wptsync upstream][webdriver:relnote])
Attachments
(3 files, 1 obsolete file)
Our current implementation is at:
Note that we explicitly assert for acyclic and do not try to serialize the object at all. But even if we would remove this line the serialization we will end-up in an infinite recursion.
We should investigate what's wrong with our implementation for JSON.clone
Comment 1•8 months ago
|
||
It's not obvious to me that this is wrong.
In the spec we structure this as checking for circular references when serializing, and aborting if we find one. In the implementation we structure this as an upfront check for circular references, and a serializer which doesn't consider cycles at all. Intuitively those should be equivalent, as long as we are using the same properties for the circular reference check as we would when serializing (e.g. if a.foo = a
, but foo
wouldn't be reached by the serializer, but will by the cycle check, that's a bug).
Assignee | ||
Comment 2•8 months ago
|
||
Ok, so lets get into the details...
JSON close
is called as following:
To perform a JSON clone return the result of calling the internal JSON clone algorithm with arguments value and an empty List.
Here we have a value
, which is the to serializable objectand an empty list for
seen` elements. This is already the point where we have the bug because we pass in the list of known elements from the element cache.
Later under Otherwise
there is the following in the first step:
1. If value is in seen, return error with error code javascript error.
2. Append value to seen.
3. Let result be the value of running the clone an object algorithm with arguments value and seen, and the internal JSON clone algorithm as the clone algorithm.
4. Remove the last element of seen.
5. Return result.
We should only raise a javascript error
exception if the value has been seen and not all the time because the object has circular references. Also we never append value
to the seen
list and as such also wouldn't be able to recognize if we already have serialized the value
or not. The only thing that we pass around is the list of seen web element references
, and that is basically wrong.
So I'm fairly sure that with a fix for this we should be able to correctly handle objects with circular references.
Adding to the webdriver triage list so that we can discuss this today.
Comment 3•8 months ago
|
||
Can you give a concrete example of something that you think would serialize according to the spec but not in our implementation? I don't mind if you want to change the implementation to look more like the spec, but I'm still not understanding what specific case you think is currently wrong.
Assignee | ||
Comment 4•8 months ago
|
||
Any arbitrary object is currently affected that is not covered by the other cases above and which has cyclic references. As said we do not store already seen objects at all at the moment.
Comment 5•8 months ago
|
||
From matrix:
The classic spec just doesn't allow serializing cycles at all. It's not a "bug" as such; it's by design. That's because it tries to represent JS objects directly as JSON objects. That's great in simple cases, but it does have some limitations:
- No DOM types. For Element and Window we invent an "unlikely" looking JSON object to represent the remote value, but it's totally a hack.
- No references. This means we can't say that e.g.
a = [1,2,3]; {prop1: a, prop2: a}
has two copies of the same array; we just get it serialized as{"prop1": [1,2,3], "prop2": [1,2,3]}
. That also means no cycles: if we havea = {}; a.prop = a
then{prop1: a}
is impossible to represent because we can't say thatobj.prop1.prop === obj.prop1
. We could just cut the serialization at that point or something, but we don't: if we try to serialize such an object we just return a Javascript Error on the reasonable-ish basis that in normal testing use cases returning a JS object containing cycles is rare. Of course the DOM has cycles on pretty much everything since it's a tree with parent pointers, but a generic object representation of DOM nodes isn't that useful anyway.
In the spec the way we handle cycle detection is via a one-pass algorithm. Basically as we're serializing objects we put each source object into a set and as we recurse the object graph, if we come across an object we've seen before we abort serialization and return an error.
In the marionette implemenation we use a two-pass approach; first we traverse the object graph looking for objects we've seen before (this is isCyclic
in the code). If we find one we return an error without doing any serialization. Once we've passed that check we go on to serialize assuming there aren't cycles (seenElms
in the toJSON
implementation seems to be about handling Elements, not cycles).
In theory both approaches are equivalent. In practice there are some tradeoffs: doing an upfront check for cycles avoids the overhead of partial serialization if we find a cycle, but is slower in the case where there aren't cycles. It also requires that we visit the exact same properties on the two passes; if you can construct a case where we miss a property containing a cycle in the validation pass that we'll later use in the serialization it will lead to a hang.
So I think it might make sense to update the marionette code to look more like the spec. But absent a case where we get a hang in the code (or similarly fail to abort given a cyclic input to the spec algorithm), I don't think there's a bug, just different engineering tradeoffs.
Assignee | ||
Comment 6•8 months ago
|
||
As discussed with James it's basically any other DOM node beside Element
that should cause a cyclic value error. Windows are hereby handled differently.
Given that bug 1692468 introduces quite a good amount of changes lets wait with any work until this bug is done. Basically what's left to do here is the correct handling of seen
which is not spec compliant. Maybe I might already fix it with bug 1692468.
Comment 7•8 months ago
|
||
Henrik, can you add some details about what needs to be changed here? Or do we just wait for bug 1692468 before considering this again?
Assignee | ||
Comment 8•6 months ago
|
||
We need the changes from bug 1692468 first due to the amount of changes. What needs to be done in a nutshell:
- Access the elementReferenceStore directly from the appropriate places and do not pass a reference through fromJSON/toJSON calls
- Use
seenEls
for already seen objects for a call to fromJSON/toJSON - Try to get rid of the two-pass approach
Assignee | ||
Comment 9•5 months ago
|
||
Updated•5 months ago
|
Updated•5 months ago
|
Assignee | ||
Comment 10•5 months ago
|
||
Assignee | ||
Comment 11•5 months ago
|
||
Depends on D166032
Assignee | ||
Comment 12•5 months ago
|
||
Depends on D166033
Updated•5 months ago
|
Assignee | ||
Comment 13•5 months ago
|
||
See also https://github.com/w3c/webdriver/pull/1709 for the changes of the WebDriver classic specification.
Comment 14•5 months ago
|
||
Pushed by hskupin@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/319ebaa96be1 [wdspec] Enhance JSON serialization and deserialization tests for script execution. r=webdriver-reviewers,jdescottes https://hg.mozilla.org/integration/autoland/rev/0cf075766291 [marionette] Refactor evaluate's "fromJSON" and "toJSON" methods. r=jdescottes,webdriver-reviewers https://hg.mozilla.org/integration/autoland/rev/4e0fc592643f [marionette] Make "seen" list of objects in "clone an object" compliant to the WebDriver spec. r=webdriver-reviewers,jgraham,jdescottes
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/37779 for changes under testing/web-platform/tests
Updated•5 months ago
|
Comment 16•5 months ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/319ebaa96be1
https://hg.mozilla.org/mozilla-central/rev/0cf075766291
https://hg.mozilla.org/mozilla-central/rev/4e0fc592643f
Upstream PR merged by moz-wptsync-bot
Assignee | ||
Updated•4 months ago
|
Updated•4 months ago
|
Description
•