Bug 1793920 - [wdspec] Don't serialize HTMLDocument as a WebElement reference. r=webdriver-reviewers,jgraham

As per WebDriver specification the document, which has a
nodeType of 9 needs to be handled as a plain object.

Differential Revision: https://phabricator.services.mozilla.com/D158766
This commit is contained in:
Henrik Skupin 2022-10-24 10:45:38 +00:00
Родитель 7653256174
Коммит a162d7481b
8 изменённых файлов: 177 добавлений и 58 удалений

Просмотреть файл

@ -18,7 +18,6 @@ const ORDERED_NODE_ITERATOR_TYPE = 5;
const FIRST_ORDERED_NODE_TYPE = 9;
const ELEMENT_NODE = 1;
const DOCUMENT_NODE = 9;
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -739,6 +738,7 @@ element.isStale = function(el, win = undefined) {
if (typeof win == "undefined") {
win = el.ownerGlobal;
}
if (el === null || !el.ownerGlobal || el.ownerDocument !== win.document) {
return true;
}
@ -1305,7 +1305,7 @@ element.isDOMElement = function(obj) {
typeof obj == "object" &&
obj !== null &&
"nodeType" in obj &&
[ELEMENT_NODE, DOCUMENT_NODE].includes(obj.nodeType) &&
obj.nodeType == ELEMENT_NODE &&
!element.isXULElement(obj)
);
};

Просмотреть файл

@ -0,0 +1,8 @@
[node.py]
[test_element_reference[frame\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL
[test_element_reference[window\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL

Просмотреть файл

@ -1,12 +1,13 @@
[json_serialize_windowproxy.py]
[test_initial_window]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected:
if (os == "linux") and not swgl and not debug: [FAIL, ERROR]
if (os == "linux") and not swgl and debug: [FAIL, ERROR]
FAIL
[test_window_open]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL
[test_frame]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL

Просмотреть файл

@ -0,0 +1,12 @@
[node.py]
[test_element_reference[frame\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL
[test_element_reference[shadow-root\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1489490
expected: FAIL
[test_element_reference[window\]]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1274251
expected: FAIL

Просмотреть файл

@ -24,33 +24,6 @@ def test_no_browsing_context(session, closed_frame):
assert_error(response, "no such window")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_argument(session, stale_element, as_frame):
element = stale_element("<div>", "div", as_frame=as_frame)
result = execute_async_script(session, "arguments[0](1);", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_returned_value(session, iframe, inline, as_frame):
if as_frame:
session.url = inline(iframe("<div>"))
frame = session.find.css("iframe", all=False)
session.switch_frame(frame)
else:
session.url = inline("<div>")
element = session.find.css("div", all=False)
result = execute_async_script(session, """
const [elem, resolve] = arguments;
elem.remove();
resolve(elem);
""", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("dialog_type", ["alert", "confirm", "prompt"])
def test_abort_by_user_prompt(session, dialog_type):
response = execute_async_script(

Просмотреть файл

@ -0,0 +1,76 @@
import pytest
from webdriver.client import Element, Frame, ShadowRoot, Window
from tests.support.asserts import assert_error, assert_success
from . import execute_async_script
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_argument(session, stale_element, as_frame):
element = stale_element("<div>", "div", as_frame=as_frame)
result = execute_async_script(session, "arguments[0](1);", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_returned_value(session, iframe, inline, as_frame):
if as_frame:
session.url = inline(iframe("<div>"))
frame = session.find.css("iframe", all=False)
session.switch_frame(frame)
else:
session.url = inline("<div>")
element = session.find.css("div", all=False)
result = execute_async_script(session, """
const [elem, resolve] = arguments;
elem.remove();
resolve(elem);
""", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("expression, type, name", [
("window.frames[0]", Frame, "Frame"),
("document.getElementById('foo')", Element, "HTMLDivElement"),
("document.getElementById('checkbox').shadowRoot", ShadowRoot, "ShadowRoot"),
("window", Window, "Window")
], ids=["frame", "node", "shadow-root", "window"])
def test_element_reference(session, iframe, inline, expression, type, name):
session.url = inline(f"""
<style>
custom-checkbox-element {{
display:block; width:20px; height:20px;
}}
</style>
<custom-checkbox-element id='checkbox'></custom-checkbox-element>
<script>
customElements.define('custom-checkbox-element',
class extends HTMLElement {{
constructor() {{
super();
this.attachShadow({{mode: 'open'}}).innerHTML = `
<div><input type="checkbox"/></div>
`;
}}
}});
</script>
<div id="foo"/>
{iframe("<p>")}""")
result = execute_async_script(session, f"arguments[0]({expression})")
reference = assert_success(result)
assert isinstance(reference, type)
result = execute_async_script(session, "arguments[1](arguments[0].constructor.name)", [reference])
name = assert_success(result, name)
def test_document_as_object(session, inline):
session.url = inline("")
# Retrieving the HTMLDocument is not possible due to cyclic references
result = execute_async_script(session, "arguments[0](document)")
assert_error(result, "javascript error")

Просмотреть файл

@ -23,33 +23,6 @@ def test_no_browsing_context(session, closed_frame):
assert_error(response, "no such window")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_argument(session, stale_element, as_frame):
element = stale_element("<div>", "div", as_frame=as_frame)
result = execute_script(session, "return 1;", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_returned_value(session, iframe, inline, as_frame):
if as_frame:
session.url = inline(iframe("<div>"))
frame = session.find.css("iframe", all=False)
session.switch_frame(frame)
else:
session.url = inline("<div>")
element = session.find.css("div", all=False)
result = execute_script(session, """
const elem = arguments[0];
elem.remove();
return elem;
""", args=[element])
assert_error(result, "stale element reference")
def test_opening_new_window_keeps_current_window_handle(session, inline):
original_handle = session.window_handle
original_handles = session.handles

Просмотреть файл

@ -0,0 +1,76 @@
import pytest
from webdriver.client import Element, Frame, ShadowRoot, Window
from tests.support.asserts import assert_error, assert_success
from . import execute_script
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_argument(session, stale_element, as_frame):
element = stale_element("<div>", "div", as_frame=as_frame)
result = execute_script(session, "return 1;", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"])
def test_stale_element_reference_as_returned_value(session, iframe, inline, as_frame):
if as_frame:
session.url = inline(iframe("<div>"))
frame = session.find.css("iframe", all=False)
session.switch_frame(frame)
else:
session.url = inline("<div>")
element = session.find.css("div", all=False)
result = execute_script(session, """
const elem = arguments[0];
elem.remove();
return elem;
""", args=[element])
assert_error(result, "stale element reference")
@pytest.mark.parametrize("expression, type, name", [
("window.frames[0]", Frame, "Frame"),
("document.getElementById('foo')", Element, "HTMLDivElement"),
("document.getElementById('checkbox').shadowRoot", ShadowRoot, "ShadowRoot"),
("window", Window, "Window")
], ids=["frame", "node", "shadow-root", "window"])
def test_element_reference(session, iframe, inline, expression, type, name):
session.url = inline(f"""
<style>
custom-checkbox-element {{
display:block; width:20px; height:20px;
}}
</style>
<custom-checkbox-element id='checkbox'></custom-checkbox-element>
<script>
customElements.define('custom-checkbox-element',
class extends HTMLElement {{
constructor() {{
super();
this.attachShadow({{mode: 'open'}}).innerHTML = `
<div><input type="checkbox"/></div>
`;
}}
}});
</script>
<div id="foo"/>
{iframe("<p>")}""")
result = execute_script(session, f"return {expression}")
reference = assert_success(result)
assert isinstance(reference, type)
result = execute_script(session, "return arguments[0].constructor.name", [reference])
name = assert_success(result, name)
def test_document_as_object(session, inline):
session.url = inline("")
# Retrieving the HTMLDocument is not possible due to cyclic references
result = execute_script(session, "arguments[0](document)")
assert_error(result, "javascript error")