Skip to content

Fix panic when a selector deposits parent flags on the Document - #648

Open
latentharbor wants to merge 1 commit into
DioxusLabs:mainfrom
latentharbor:fix-selector-flags-document-parent
Open

Fix panic when a selector deposits parent flags on the Document#648
latentharbor wants to merge 1 commit into
DioxusLabs:mainfrom
latentharbor:fix-selector-flags-document-parent

Conversation

@latentharbor

Copy link
Copy Markdown

Node::selector_flags() is generated by element_accessors!, so it exists only on Element and AnonymousBlock nodes. Stylo's apply_selector_flags deposits the for_parent() half of a match on the raw parent node:

if let Some(parent) = self.parent_node() {
    parent.selector_flags().set(parent.selector_flags().get() | parent_flags);
}

For the root <html> that parent is the Document node, where the field does not exist, and the accessor panics with ```selector_flags is not available on this node kind.

for_parent() covers :first-child, :last-child, :only-child, :nth-child(), :nth-last-child(), ~ and +, so the minimal reproduction needs no script, no network and no shadow DOM:

<style>*:first-child { color: red }</style><p>hello</p>

universal_accessors! already carries a Document arm for element_state and snapshot_handled for exactly this reason; selector_flags was missed. This moves it to the same macro.

Found while running the Web Platform Tests against blitz-dom in OpenKitesurf, where it was breaking real pages — react.dev among them.

`Node::selector_flags()` is generated by `element_accessors!`, so it
exists only on Element and AnonymousBlock nodes. Stylo's
`apply_selector_flags` deposits the `for_parent()` half of a match on the
raw parent node:

    if let Some(parent) = self.parent_node() {
        parent.selector_flags().set(parent.selector_flags().get() | parent_flags);
    }

For the root `<html>` that parent is the Document node, where the field
does not exist, and the accessor panics with

    `selector_flags` is not available on this node kind

`for_parent()` covers `:first-child`, `:last-child`, `:only-child`,
`:nth-child()`, `:nth-last-child()`, `~` and `+`, so the minimal
reproduction needs no script, no network and no shadow DOM:

    <style>*:first-child { color: red }</style><p>hello</p>

`universal_accessors!` already carries a Document arm for `element_state`
and `snapshot_handled` for exactly this reason; `selector_flags` was
missed. This moves it to the same macro.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant