From d1ca38048210ee214d6335156bd546069ee81fea Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 24 May 2014 21:29:52 +0200 Subject: [PATCH 1/2] Use StrBuf more efficiently in htmlserializer. --- src/components/script/dom/htmlserializer.rs | 134 +++++++++++--------- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index 2021762f96d..ebda79fe416 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -25,51 +25,53 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { for node in *iterator { while open_elements.len() > iterator.depth { - html.push_str(""); + html.push_str(""); } - html.push_str( - match node.type_id() { - ElementNodeTypeId(..) => { - let elem: &JSRef = ElementCast::to_ref(&node).unwrap(); - serialize_elem(elem, &mut open_elements) - } - CommentNodeTypeId => { - let comment: &JSRef = CommentCast::to_ref(&node).unwrap(); - serialize_comment(comment) - } - TextNodeTypeId => { - let text: &JSRef = TextCast::to_ref(&node).unwrap(); - serialize_text(text) - } - DoctypeNodeTypeId => { - let doctype: &JSRef = DocumentTypeCast::to_ref(&node).unwrap(); - serialize_doctype(doctype) - } - ProcessingInstructionNodeTypeId => { - let processing_instruction: &JSRef = - ProcessingInstructionCast::to_ref(&node).unwrap(); - serialize_processing_instruction(processing_instruction) - } - DocumentFragmentNodeTypeId => { - "".to_owned() - } - DocumentNodeTypeId => { - fail!("It shouldn't be possible to serialize a document node") - } + match node.type_id() { + ElementNodeTypeId(..) => { + let elem: &JSRef = ElementCast::to_ref(&node).unwrap(); + serialize_elem(elem, &mut open_elements, &mut html) } - ); + CommentNodeTypeId => { + let comment: &JSRef = CommentCast::to_ref(&node).unwrap(); + serialize_comment(comment, &mut html) + } + TextNodeTypeId => { + let text: &JSRef = TextCast::to_ref(&node).unwrap(); + serialize_text(text, &mut html) + } + DoctypeNodeTypeId => { + let doctype: &JSRef = DocumentTypeCast::to_ref(&node).unwrap(); + serialize_doctype(doctype, &mut html) + } + ProcessingInstructionNodeTypeId => { + let processing_instruction: &JSRef = + ProcessingInstructionCast::to_ref(&node).unwrap(); + serialize_processing_instruction(processing_instruction, &mut html) + } + DocumentFragmentNodeTypeId => {} + DocumentNodeTypeId => { + fail!("It shouldn't be possible to serialize a document node") + } + } } while open_elements.len() > 0 { - html.push_str(""); + html.push_str(""); } html.into_owned() } -fn serialize_comment(comment: &JSRef) -> ~str { - "" +fn serialize_comment(comment: &JSRef, html: &mut StrBuf) { + html.push_str(""); } -fn serialize_text(text: &JSRef) -> ~str { +fn serialize_text(text: &JSRef, html: &mut StrBuf) { let text_node: &JSRef = NodeCast::from_ref(text); match text_node.parent_node().map(|node| node.root()) { Some(ref parent) if parent.is_element() => { @@ -77,33 +79,39 @@ fn serialize_text(text: &JSRef) -> ~str { match elem.deref().local_name.as_slice() { "style" | "script" | "xmp" | "iframe" | "noembed" | "noframes" | "plaintext" | - "noscript" if elem.deref().namespace == namespace::HTML => { - text.deref().characterdata.data.clone() - }, - _ => escape(text.deref().characterdata.data, false) + "noscript" if elem.deref().namespace == namespace::HTML + => html.push_str(text.deref().characterdata.data), + _ => html.push_str(escape(text.deref().characterdata.data, false)) } } - _ => escape(text.deref().characterdata.data, false) + _ => html.push_str(escape(text.deref().characterdata.data, false)) } } -fn serialize_processing_instruction(processing_instruction: &JSRef) -> ~str { - "" +fn serialize_processing_instruction(processing_instruction: &JSRef, + html: &mut StrBuf) { + html.push_str(""); } -fn serialize_doctype(doctype: &JSRef) -> ~str { - "" +fn serialize_doctype(doctype: &JSRef, html: &mut StrBuf) { + html.push_str("'); } -fn serialize_elem(elem: &JSRef, open_elements: &mut Vec<~str>) -> ~str { - let mut rv = StrBuf::new(); - rv.push_str("<"); - rv.push_str(elem.deref().local_name); +fn serialize_elem(elem: &JSRef, open_elements: &mut Vec<~str>, html: &mut StrBuf) { + html.push_char('<'); + html.push_str(elem.deref().local_name); for attr in elem.deref().attrs.iter() { let attr = attr.root(); - rv.push_str(serialize_attr(&*attr)); + serialize_attr(&*attr, html); }; - rv.push_str(">"); + html.push_char('>'); + match elem.deref().local_name.as_slice() { "pre" | "listing" | "textarea" if elem.deref().namespace == namespace::HTML => { let node: &JSRef = NodeCast::from_ref(elem); @@ -111,7 +119,7 @@ fn serialize_elem(elem: &JSRef, open_elements: &mut Vec<~str>) -> ~str Some(ref child) if child.is_text() => { let text: &JSRef = CharacterDataCast::to_ref(&**child).unwrap(); if text.deref().data.len() > 0 && text.deref().data[0] == 0x0A as u8 { - rv.push_str("\x0A"); + html.push_char('\x0A'); } }, _ => {} @@ -119,26 +127,32 @@ fn serialize_elem(elem: &JSRef, open_elements: &mut Vec<~str>) -> ~str }, _ => {} } + if !elem.deref().is_void() { open_elements.push(elem.deref().local_name.clone()); } - rv.into_owned() } -fn serialize_attr(attr: &JSRef) -> ~str { - let attr_name = if attr.deref().namespace == namespace::XML { - "xml:".to_owned() + attr.deref().local_name.clone() +fn serialize_attr(attr: &JSRef, html: &mut StrBuf) { + html.push_char(' '); + if attr.deref().namespace == namespace::XML { + html.push_str("xml:"); + html.push_str(attr.deref().local_name); } else if attr.deref().namespace == namespace::XMLNS && attr.deref().local_name.as_slice() == "xmlns" { - "xmlns".to_owned() + html.push_str("xmlns"); } else if attr.deref().namespace == namespace::XMLNS { - "xmlns:".to_owned() + attr.deref().local_name.clone() + html.push_str("xmlns:"); + html.push_str(attr.deref().local_name); } else if attr.deref().namespace == namespace::XLink { - "xlink:".to_owned() + attr.deref().local_name.clone() + html.push_str("xlink:"); + html.push_str(attr.deref().local_name); } else { - attr.deref().name.clone() + html.push_str(attr.deref().name); }; - " ".to_owned() + attr_name + "=\"" + escape(attr.deref().value, true) + "\"" + html.push_str("=\""); + html.push_str(escape(attr.deref().value, true)); + html.push_char('"'); } fn escape(string: &str, attr_mode: bool) -> ~str { From ce45afac0c61d624064e7777b8b02ea0f9e50bdf Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 24 May 2014 21:48:01 +0200 Subject: [PATCH 2/2] Rewrite escape() in htmlserializer to push onto a StrBuf. --- src/components/script/dom/htmlserializer.rs | 23 +++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index ebda79fe416..817f84f91a6 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -81,10 +81,10 @@ fn serialize_text(text: &JSRef, html: &mut StrBuf) { "noembed" | "noframes" | "plaintext" | "noscript" if elem.deref().namespace == namespace::HTML => html.push_str(text.deref().characterdata.data), - _ => html.push_str(escape(text.deref().characterdata.data, false)) + _ => escape(text.deref().characterdata.data, false, html) } } - _ => html.push_str(escape(text.deref().characterdata.data, false)) + _ => escape(text.deref().characterdata.data, false, html) } } @@ -151,18 +151,19 @@ fn serialize_attr(attr: &JSRef, html: &mut StrBuf) { html.push_str(attr.deref().name); }; html.push_str("=\""); - html.push_str(escape(attr.deref().value, true)); + escape(attr.deref().value, true, html); html.push_char('"'); } -fn escape(string: &str, attr_mode: bool) -> ~str { - let replaced = string.replace("&", "&").replace("\xA0", " "); - match attr_mode { - true => { - replaced.replace("\"", """) - }, - false => { - replaced.replace("<", "<").replace(">", ">") +fn escape(string: &str, attr_mode: bool, html: &mut StrBuf) { + for c in string.chars() { + match c { + '&' => html.push_str("&"), + '\xA0' => html.push_str(" "), + '"' if attr_mode => html.push_str("""), + '<' if !attr_mode => html.push_str("<"), + '>' if !attr_mode => html.push_str(">"), + c => html.push_char(c), } } }