mirror of
https://github.com/servo/servo.git
synced 2025-08-02 04:00:32 +01:00
Refactor fragment parsing
This commit is contained in:
parent
3c5c2f416b
commit
63ced23fca
3 changed files with 74 additions and 55 deletions
|
@ -10,13 +10,11 @@ use dom::attr::AttrValue;
|
||||||
use dom::namednodemap::NamedNodeMap;
|
use dom::namednodemap::NamedNodeMap;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding;
|
use dom::bindings::codegen::Bindings::ElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
|
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
|
||||||
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, EventTargetCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, EventTargetCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLInputElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLInputElementCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLTableElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLTableElementCast};
|
||||||
|
@ -24,7 +22,6 @@ use dom::bindings::codegen::InheritTypes::{HTMLTableElementDerived, HTMLTableCel
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, HTMLTextAreaElementDerived};
|
use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, HTMLTextAreaElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLTableSectionElementDerived, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLTableSectionElementDerived, NodeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
|
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast;
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
|
|
||||||
use dom::bindings::error::{ErrorResult, Fallible};
|
use dom::bindings::error::{ErrorResult, Fallible};
|
||||||
use dom::bindings::error::Error;
|
use dom::bindings::error::Error;
|
||||||
use dom::bindings::error::Error::{InvalidCharacter, Syntax};
|
use dom::bindings::error::Error::{InvalidCharacter, Syntax};
|
||||||
|
@ -37,7 +34,6 @@ use dom::create::create_element;
|
||||||
use dom::domrect::DOMRect;
|
use dom::domrect::DOMRect;
|
||||||
use dom::domrectlist::DOMRectList;
|
use dom::domrectlist::DOMRectList;
|
||||||
use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
|
use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
|
||||||
use dom::document::{DocumentSource, IsHTMLDocument};
|
|
||||||
use dom::domtokenlist::DOMTokenList;
|
use dom::domtokenlist::DOMTokenList;
|
||||||
use dom::event::{Event, EventHelpers};
|
use dom::event::{Event, EventHelpers};
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
|
@ -55,10 +51,9 @@ use dom::node::{CLICK_IN_PROGRESS, LayoutNodeHelpers, Node, NodeHelpers, NodeTyp
|
||||||
use dom::node::{document_from_node, NodeDamage};
|
use dom::node::{document_from_node, NodeDamage};
|
||||||
use dom::node::{window_from_node};
|
use dom::node::{window_from_node};
|
||||||
use dom::nodelist::NodeList;
|
use dom::nodelist::NodeList;
|
||||||
use dom::servohtmlparser::FragmentContext;
|
|
||||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||||
use devtools_traits::AttrInfo;
|
use devtools_traits::AttrInfo;
|
||||||
use parse::html::{HTMLInput, parse_html};
|
use parse::html::HTMLInput;
|
||||||
use style::legacy::{SimpleColorAttribute, UnsignedIntegerAttribute, IntegerAttribute, LengthAttribute};
|
use style::legacy::{SimpleColorAttribute, UnsignedIntegerAttribute, IntegerAttribute, LengthAttribute};
|
||||||
use selectors::matching::matches;
|
use selectors::matching::matches;
|
||||||
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, parse_style_attribute};
|
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, parse_style_attribute};
|
||||||
|
@ -1169,61 +1164,20 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
rect.origin.x + rect.size.width)
|
rect.origin.x + rect.size.width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#extensions-to-the-element-interface
|
||||||
fn GetInnerHTML(self) -> Fallible<DOMString> {
|
fn GetInnerHTML(self) -> Fallible<DOMString> {
|
||||||
//XXX TODO: XML case
|
//XXX TODO: XML case
|
||||||
self.serialize(ChildrenOnly)
|
self.serialize(ChildrenOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetInnerHTML(self, value: DOMString) -> Fallible<()> {
|
fn SetInnerHTML(self, value: DOMString) -> Fallible<()> {
|
||||||
let window = window_from_node(self).root();
|
// 1. Let fragment be the result of invoking the fragment parsing algorithm
|
||||||
let context_document = document_from_node(self).root();
|
// with the new value as markup, and the context object as the context element.
|
||||||
|
// 2. Replace all with fragment within the context object.
|
||||||
let context_node: JSRef<Node> = NodeCast::from_ref(self);
|
let context_node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
let url = context_document.r().url();
|
context_node.parse_fragment(HTMLInput::InputString(value))
|
||||||
|
.and_then(|frag| Ok(Node::replace_all(Some(NodeCast::from_ref(frag.root().r())),
|
||||||
// Follows https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
|
context_node)))
|
||||||
|
|
||||||
// 1. Create a new Document node, and mark it as being an HTML document.
|
|
||||||
let document = Document::new(window.r(), Some(url.clone()),
|
|
||||||
IsHTMLDocument::HTMLDocument,
|
|
||||||
None, None,
|
|
||||||
DocumentSource::FromParser).root();
|
|
||||||
|
|
||||||
// 2. If the node document of the context element is in quirks mode,
|
|
||||||
// then let the Document be in quirks mode. Otherwise,
|
|
||||||
// the node document of the context element is in limited-quirks mode,
|
|
||||||
// then let the Document be in limited-quirks mode. Otherwise,
|
|
||||||
// leave the Document in no-quirks mode.
|
|
||||||
document.r().set_quirks_mode(context_document.r().quirks_mode());
|
|
||||||
|
|
||||||
// 11. Set the parser's form element pointer to the nearest node to
|
|
||||||
// the context element that is a form element (going straight up
|
|
||||||
// the ancestor chain, and including the element itself, if it
|
|
||||||
// is a form element), if any. (If there is no such form element,
|
|
||||||
// the form element pointer keeps its initial value, null.)
|
|
||||||
let form = context_node.inclusive_ancestors()
|
|
||||||
.find(|element| element.is_htmlformelement());
|
|
||||||
let fragment_context = FragmentContext {
|
|
||||||
context_elem: context_node,
|
|
||||||
form_elem: form,
|
|
||||||
};
|
|
||||||
parse_html(document.r(), HTMLInput::InputString(value), &url, Some(fragment_context));
|
|
||||||
|
|
||||||
// "14. Return the child nodes of root, in tree order."
|
|
||||||
// We do this by deleting all nodes of the context node,
|
|
||||||
// and then moving all nodes parsed into the new root_node
|
|
||||||
// into the context node.
|
|
||||||
while let Some(child) = context_node.GetFirstChild() {
|
|
||||||
try!(context_node.RemoveChild(child.root().r()));
|
|
||||||
}
|
|
||||||
let root_element = document.r().GetDocumentElement().expect("no document element").root();
|
|
||||||
let root_node: JSRef<Node> = NodeCast::from_ref(root_element.r());
|
|
||||||
while let Some(child) = root_node.GetFirstChild() {
|
|
||||||
let child = child.root();
|
|
||||||
try!(root_node.RemoveChild(child.r()));
|
|
||||||
try!(context_node.AppendChild(child.r()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetOuterHTML(self) -> Fallible<DOMString> {
|
fn GetOuterHTML(self) -> Fallible<DOMString> {
|
||||||
|
|
|
@ -46,6 +46,7 @@ use dom::window::{Window, WindowHelpers};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use layout_interface::{LayoutChan, Msg};
|
use layout_interface::{LayoutChan, Msg};
|
||||||
use devtools_traits::NodeInfo;
|
use devtools_traits::NodeInfo;
|
||||||
|
use parse::html::{HTMLInput, parse_html_fragment};
|
||||||
use script_traits::UntrustedNodeAddress;
|
use script_traits::UntrustedNodeAddress;
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
use util::str::{DOMString, null_str_as_empty};
|
use util::str::{DOMString, null_str_as_empty};
|
||||||
|
@ -502,6 +503,8 @@ pub trait NodeHelpers<'a> {
|
||||||
fn summarize(self) -> NodeInfo;
|
fn summarize(self) -> NodeInfo;
|
||||||
|
|
||||||
fn teardown(self);
|
fn teardown(self);
|
||||||
|
|
||||||
|
fn parse_fragment(self, markup: HTMLInput) -> Fallible<Temporary<DocumentFragment>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
|
@ -929,6 +932,24 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-parse-fragment
|
||||||
|
fn parse_fragment(self, markup: HTMLInput) -> Fallible<Temporary<DocumentFragment>> {
|
||||||
|
let context_node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
|
let context_document = document_from_node(self).root();
|
||||||
|
let new_children =
|
||||||
|
if context_document.r().is_html_document() {
|
||||||
|
parse_html_fragment(context_node, markup)
|
||||||
|
} else {
|
||||||
|
// FIXME: XML case
|
||||||
|
unimplemented!()
|
||||||
|
};
|
||||||
|
let fragment = DocumentFragment::new(context_document.r()).root();
|
||||||
|
let fragment_node: JSRef<Node> = NodeCast::from_ref(fragment.r());
|
||||||
|
for node in new_children {
|
||||||
|
try!(fragment_node.AppendChild(node.root().r()));
|
||||||
|
}
|
||||||
|
Ok(Temporary::from_rooted(fragment.r()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
/// If the given untrusted node address represents a valid DOM node in the given runtime,
|
||||||
|
@ -1456,7 +1477,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#concept-node-replace-all
|
// http://dom.spec.whatwg.org/#concept-node-replace-all
|
||||||
fn replace_all(node: Option<JSRef<Node>>, parent: JSRef<Node>) {
|
pub fn replace_all(node: Option<JSRef<Node>>, parent: JSRef<Node>) {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
match node {
|
match node {
|
||||||
Some(node) => {
|
Some(node) => {
|
||||||
|
|
|
@ -5,18 +5,22 @@
|
||||||
#![allow(unsafe_code, unrooted_must_root)]
|
#![allow(unsafe_code, unrooted_must_root)]
|
||||||
|
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast};
|
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, TextCast, CommentCast};
|
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, TextCast, CommentCast};
|
||||||
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
|
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
|
||||||
|
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
|
||||||
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
|
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::document::{Document, DocumentHelpers};
|
use dom::document::{Document, DocumentHelpers};
|
||||||
|
use dom::document::{DocumentSource, IsHTMLDocument};
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{Element, AttributeHandlers, ElementHelpers, ElementCreator};
|
use dom::element::{Element, AttributeHandlers, ElementHelpers, ElementCreator};
|
||||||
use dom::htmlscriptelement::HTMLScriptElement;
|
use dom::htmlscriptelement::HTMLScriptElement;
|
||||||
use dom::htmlscriptelement::HTMLScriptElementHelpers;
|
use dom::htmlscriptelement::HTMLScriptElementHelpers;
|
||||||
use dom::node::{Node, NodeHelpers, NodeTypeId};
|
use dom::node::{Node, NodeHelpers, NodeTypeId};
|
||||||
|
use dom::node::{document_from_node, window_from_node};
|
||||||
use dom::processinginstruction::ProcessingInstruction;
|
use dom::processinginstruction::ProcessingInstruction;
|
||||||
use dom::servohtmlparser;
|
use dom::servohtmlparser;
|
||||||
use dom::servohtmlparser::{ServoHTMLParser, FragmentContext};
|
use dom::servohtmlparser::{ServoHTMLParser, FragmentContext};
|
||||||
|
@ -324,3 +328,43 @@ pub fn parse_html(document: JSRef<Document>,
|
||||||
|
|
||||||
debug!("finished parsing");
|
debug!("finished parsing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
|
||||||
|
pub fn parse_html_fragment(context_node: JSRef<Node>, input: HTMLInput) -> Vec<Temporary<Node>> {
|
||||||
|
let window = window_from_node(context_node).root();
|
||||||
|
let context_document = document_from_node(context_node).root();
|
||||||
|
let url = context_document.r().url();
|
||||||
|
|
||||||
|
// 1. Create a new Document node, and mark it as being an HTML document.
|
||||||
|
let document = Document::new(window.r(), Some(url.clone()),
|
||||||
|
IsHTMLDocument::HTMLDocument,
|
||||||
|
None, None,
|
||||||
|
DocumentSource::FromParser).root();
|
||||||
|
|
||||||
|
// 2. If the node document of the context element is in quirks mode,
|
||||||
|
// then let the Document be in quirks mode. Otherwise,
|
||||||
|
// the node document of the context element is in limited-quirks mode,
|
||||||
|
// then let the Document be in limited-quirks mode. Otherwise,
|
||||||
|
// leave the Document in no-quirks mode.
|
||||||
|
document.r().set_quirks_mode(context_document.r().quirks_mode());
|
||||||
|
|
||||||
|
// 11. Set the parser's form element pointer to the nearest node to
|
||||||
|
// the context element that is a form element (going straight up
|
||||||
|
// the ancestor chain, and including the element itself, if it
|
||||||
|
// is a form element), if any. (If there is no such form element,
|
||||||
|
// the form element pointer keeps its initial value, null.)
|
||||||
|
let form = context_node.inclusive_ancestors()
|
||||||
|
.find(|element| element.is_htmlformelement());
|
||||||
|
let fragment_context = FragmentContext {
|
||||||
|
context_elem: context_node,
|
||||||
|
form_elem: form,
|
||||||
|
};
|
||||||
|
parse_html(document.r(), input, &url, Some(fragment_context));
|
||||||
|
|
||||||
|
// "14. Return the child nodes of root, in tree order."
|
||||||
|
let root_element = document.r().GetDocumentElement().expect("no document element").root();
|
||||||
|
let root_node: JSRef<Node> = NodeCast::from_ref(root_element.r());
|
||||||
|
root_node.children()
|
||||||
|
.map(|node| Temporary::from_rooted(node))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue