Skip to content

Commit

Permalink
Implement declarative shadow DOM (#568)
Browse files Browse the repository at this point in the history
  • Loading branch information
longvatrong111 authored Jan 13, 2025
1 parent feced06 commit 24df05e
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
41 changes: 41 additions & 0 deletions html5ever/src/tree_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,47 @@ where
}
//§ END

fn should_attach_declarative_shadow(&self, tag: &Tag) -> bool {
let adjusted_insertion_location = self.appropriate_place_for_insertion(None);

let (intended_parent, _node2) = match adjusted_insertion_location {
LastChild(ref p) | BeforeSibling(ref p) => (p.clone(), None),
TableFosterParenting {
ref element,
ref prev_element,
} => (element.clone(), Some(prev_element.clone())),
};

// template start tag's shadowrootmode is not in the none state
let is_shadow_root_mode = tag.attrs.iter().any(|attr| {
attr.name.local == local_name!("shadowrootmode")
&& (attr.value.to_string() == String::from("open") || attr.value.to_string() == String::from("close"))
});

// Check if intended_parent's document allows declarative shadow roots
let allow_declarative_shadow_roots = self.sink.allow_declarative_shadow_roots(&intended_parent);

// the adjusted current node is not the topmost element in the stack of open elements
let adjusted_current_node_not_topmost = match self.open_elems.borrow().first() {
// The stack grows downwards; the topmost node on the stack is the first one added to the stack
// The current node is the bottommost node in this stack of open elements.
//
// (1) The adjusted current node is the context element if the parser was created as part of the HTML fragment parsing algorithm
// and the stack of open elements has only one element in it (fragment case);
// (2) otherwise, the adjusted current node is the current node (the bottomost node)
//
// => adjusted current node != topmost element in the stack when the stack size > 1
Some(_) => self.open_elems.borrow().len() > 1,
None => true,
};

return is_shadow_root_mode && allow_declarative_shadow_roots && adjusted_current_node_not_topmost;
}

fn attach_declarative_shadow(&self, tag: &Tag) -> Result<(), String> {
self.sink.attach_declarative_shadow(self.open_elems.borrow().last().unwrap(), tag.attrs.clone())
}

fn create_formatting_element_for(&self, tag: Tag) -> Handle {
// FIXME: This really wants unit tests.
let mut first_match = None;
Expand Down
13 changes: 12 additions & 1 deletion html5ever/src/tree_builder/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ where
}),

//§ parsing-main-inhead
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead
InHead => match_token!(token {
CharacterTokens(NotSplit, text) => SplitWhitespace(text),
CharacterTokens(Whitespace, text) => self.append_text(text),
Expand Down Expand Up @@ -153,11 +154,21 @@ where
</body> </html> </br> => else,

tag @ <template> => {
self.insert_element_for(tag);
self.active_formatting.borrow_mut().push(Marker);
self.frameset_ok.set(false);
self.mode.set(InTemplate);
self.template_modes.borrow_mut().push(InTemplate);

if (self.should_attach_declarative_shadow(&tag)) {
if let Err(_) = self.attach_declarative_shadow(&tag) {
// TODO:
// insert at the adjusted insertion location
// with the result of insert a foreign element for template tag
}
} else {
self.insert_element_for(tag);
}

Done
}

Expand Down
13 changes: 13 additions & 0 deletions markup5ever/interface/tree_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,19 @@ pub trait TreeSink {
fn complete_script(&self, _node: &Self::Handle) -> NextParserState {
NextParserState::Continue
}

fn allow_declarative_shadow_roots(&self, _intended_parent: &Self::Handle) -> bool {
return true;
}

/// Attach declarative shadow
fn attach_declarative_shadow(
&self,
_location: &Self::Handle,
_attrs: Vec<Attribute>,
) -> Result<(), String> {
Err(String::from("No implementation for attach_declarative_shadow"))
}
}

/// Trace hooks for a garbage-collected DOM.
Expand Down
4 changes: 4 additions & 0 deletions markup5ever/local_names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,10 @@ separator
separators
set
setdiff
shadowrootclonable
shadowrootdelegatesfocus
shadowrootmode
shadowrootserializable
shape
shape-rendering
show
Expand Down

0 comments on commit 24df05e

Please sign in to comment.