mirror of
https://github.com/servo/servo.git
synced 2025-09-04 03:58:23 +01:00
script: Support decomposing ShadowRoot from mozjs HandleValue
(#38984)
- Add `ShadowRoot` to `JSValue` to avoid `WebDriverJSError::UnknownType`, and `JavaScriptEvaluationError::SerializationError` when execute JS from embedder. - Add unit test. - Move [is_detached](https://w3c.github.io/webdriver/#dfn-is-detached) to `fn is_detached` to be reused. - Other random simplification. Testing: WebDriver conformance tests. --------- Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
parent
5308228436
commit
3ac226e841
12 changed files with 43 additions and 39 deletions
|
@ -617,7 +617,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
// Note: the element can pass this check without yet being a custom
|
||||
// element, as long as there is a registered definition
|
||||
// that could upgrade it to one later.
|
||||
let registry = self.owner_document().window().CustomElements();
|
||||
let registry = self.owner_window().CustomElements();
|
||||
let definition = registry.lookup_definition(self.as_element().local_name(), None);
|
||||
|
||||
// Step 3: If definition is null, then throw an "NotSupportedError" DOMException
|
||||
|
|
|
@ -1282,7 +1282,7 @@ impl Node {
|
|||
pub(crate) fn summarize(&self, can_gc: CanGc) -> NodeInfo {
|
||||
let USVString(base_uri) = self.BaseURI();
|
||||
let node_type = self.NodeType();
|
||||
let pipeline = self.owner_document().window().pipeline_id();
|
||||
let pipeline = self.owner_window().pipeline_id();
|
||||
|
||||
let maybe_shadow_root = self.downcast::<ShadowRoot>();
|
||||
let shadow_root_mode = maybe_shadow_root
|
||||
|
|
|
@ -95,6 +95,13 @@ fn is_stale(element: &Element) -> bool {
|
|||
!element.owner_document().is_active() || !element.is_connected()
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-is-detached>
|
||||
fn is_detached(shadow_root: &ShadowRoot) -> bool {
|
||||
// A shadow root is detached if its node document is not the active document
|
||||
// or if the element node referred to as its host is stale.
|
||||
!shadow_root.owner_document().is_active() || is_stale(&shadow_root.Host())
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-disabled>
|
||||
fn is_disabled(element: &Element) -> bool {
|
||||
// Step 1. If element is an option element or element is an optgroup element
|
||||
|
@ -173,12 +180,7 @@ fn get_known_shadow_root(
|
|||
// A shadow root is detached if its node document is not the active document
|
||||
// or if the element node referred to as its host is stale.
|
||||
let shadow_root = DomRoot::downcast::<ShadowRoot>(node).unwrap();
|
||||
if !shadow_root.owner_document().is_active() {
|
||||
return Err(ErrorStatus::DetachedShadowRoot);
|
||||
}
|
||||
|
||||
let host = shadow_root.Host();
|
||||
if is_stale(&host) {
|
||||
if is_detached(&shadow_root) {
|
||||
return Err(ErrorStatus::DetachedShadowRoot);
|
||||
}
|
||||
// Step 5. Return success with data node.
|
||||
|
@ -396,15 +398,27 @@ unsafe fn jsval_to_webdriver_inner(
|
|||
});
|
||||
let _ac = JSAutoRealm::new(cx, *object);
|
||||
|
||||
// TODO: special handling for ShadowRoot
|
||||
if let Ok(element) = root_from_object::<Element>(*object, cx) {
|
||||
// If the element is stale, return error with error code stale element reference.
|
||||
if is_stale(&element) {
|
||||
Err(WebDriverJSError::StaleElementReference)
|
||||
} else {
|
||||
Ok(JSValue::Element(element.upcast::<Node>().unique_id(
|
||||
element.owner_document().window().pipeline_id(),
|
||||
)))
|
||||
Ok(JSValue::Element(
|
||||
element
|
||||
.upcast::<Node>()
|
||||
.unique_id(element.owner_window().pipeline_id()),
|
||||
))
|
||||
}
|
||||
} else if let Ok(shadow_root) = root_from_object::<ShadowRoot>(*object, cx) {
|
||||
// If the shadow root is detached, return error with error code detached shadow root.
|
||||
if is_detached(&shadow_root) {
|
||||
Err(WebDriverJSError::DetachedShadowRoot)
|
||||
} else {
|
||||
Ok(JSValue::ShadowRoot(
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.unique_id(shadow_root.owner_window().pipeline_id()),
|
||||
))
|
||||
}
|
||||
} else if let Ok(window) = root_from_object::<Window>(*object, cx) {
|
||||
let window_proxy = window.window_proxy();
|
||||
|
|
|
@ -80,6 +80,16 @@ fn test_evaluate_javascript_basic(servo_test: &ServoTest) -> Result<(), anyhow::
|
|||
let result = evaluate_javascript(servo_test, webview.clone(), "document.body");
|
||||
ensure!(matches!(result, Ok(JSValue::Element(..))));
|
||||
|
||||
let result = evaluate_javascript(
|
||||
servo_test,
|
||||
webview.clone(),
|
||||
"document.body.attachShadow({mode: 'open'})",
|
||||
);
|
||||
ensure!(matches!(result, Ok(JSValue::ShadowRoot(..))));
|
||||
|
||||
let result = evaluate_javascript(servo_test, webview.clone(), "document.body.shadowRoot");
|
||||
ensure!(matches!(result, Ok(JSValue::ShadowRoot(..))));
|
||||
|
||||
let result = evaluate_javascript(
|
||||
servo_test,
|
||||
webview.clone(),
|
||||
|
|
|
@ -1047,6 +1047,7 @@ pub enum JSValue {
|
|||
Number(f64),
|
||||
String(String),
|
||||
Element(String),
|
||||
ShadowRoot(String),
|
||||
Frame(String),
|
||||
Window(String),
|
||||
Array(Vec<JSValue>),
|
||||
|
|
|
@ -256,6 +256,7 @@ pub enum WebDriverJSError {
|
|||
/// Occurs when handler received an event message for a layout channel that is not
|
||||
/// associated with the current script thread
|
||||
BrowsingContextNotFound,
|
||||
DetachedShadowRoot,
|
||||
JSException(JSValue),
|
||||
JSError,
|
||||
StaleElementReference,
|
||||
|
|
|
@ -260,6 +260,7 @@ impl Serialize for SendableJSValue {
|
|||
JSValue::Number(x) => serializer.serialize_f64(x),
|
||||
JSValue::String(ref x) => serializer.serialize_str(x),
|
||||
JSValue::Element(ref x) => WebElement(x.clone()).serialize(serializer),
|
||||
JSValue::ShadowRoot(ref x) => ShadowRoot(x.clone()).serialize(serializer),
|
||||
JSValue::Frame(ref x) => WebFrame(x.clone()).serialize(serializer),
|
||||
JSValue::Window(ref x) => WebWindow(x.clone()).serialize(serializer),
|
||||
JSValue::Array(ref x) => x
|
||||
|
@ -2066,6 +2067,10 @@ impl Handler {
|
|||
ErrorStatus::StaleElementReference,
|
||||
"Stale element",
|
||||
)),
|
||||
Err(WebDriverJSError::DetachedShadowRoot) => Err(WebDriverError::new(
|
||||
ErrorStatus::DetachedShadowRoot,
|
||||
"Detached shadow root",
|
||||
)),
|
||||
Err(WebDriverJSError::Timeout) => {
|
||||
Err(WebDriverError::new(ErrorStatus::ScriptTimeout, ""))
|
||||
},
|
||||
|
|
|
@ -35,8 +35,5 @@
|
|||
[test_element_reference[frame\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[window\]]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
[node.py]
|
||||
[test_detached_shadow_root[top_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_detached_shadow_root[child_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_not_supported_nodes[attribute\]]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -35,8 +35,5 @@
|
|||
[test_element_reference[frame\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[window\]]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
[node.py]
|
||||
[test_detached_shadow_root[top_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_detached_shadow_root[child_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_web_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_not_supported_nodes[attribute\]]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
[get.py]
|
||||
[test_no_browsing_context]
|
||||
expected: FAIL
|
||||
|
||||
[test_web_reference[shadowRoot-ShadowRoot\]]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue