From f8070affdbc776a3e2bd8629089215a8f04aa850 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Fri, 24 Apr 2015 14:34:08 -0700 Subject: [PATCH 1/2] Merge adjacent text nodes while appending Fixes #5828. --- components/script/parse/html.rs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index 735018093009..bafa18e9a161 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -5,12 +5,13 @@ #![allow(unsafe_code, unrooted_must_root)] use dom::attr::AttrHelpers; +use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentTypeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLScriptElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, NodeCast}; -use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; +use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; use dom::bindings::js::RootedReference; use dom::bindings::trace::RootedVec; @@ -126,6 +127,7 @@ impl<'a> TreeSink for servohtmlparser::Sink { None => return Err(new_node), }; + // FIXME: Merge adjacent text nodes. let child = self.get_or_create(new_node).root(); assert!(parent.r().InsertBefore(child.r(), Some(sibling.r())).is_ok()); Ok(()) @@ -141,11 +143,32 @@ impl<'a> TreeSink for servohtmlparser::Sink { } fn append(&mut self, parent: JS, child: NodeOrText>) { + // FIXME(#3701): Use a simpler algorithm let parent: Root = parent.root(); - let child = self.get_or_create(child).root(); - - // FIXME(#3701): Use a simpler algorithm and merge adjacent text nodes - assert!(parent.r().AppendChild(child.r()).is_ok()); + match child { + AppendNode(n) => { + let node = Temporary::new(n).root(); + assert!(parent.r().AppendChild(node.r()).is_ok()); + }, + AppendText(t) => { + match parent.r().GetLastChild() { + // Append to an existing text node if possible. + Some(ref prev_sibling) if prev_sibling.root().r().is_text() => { + let node = prev_sibling.root(); + let text = TextCast::to_ref(node.r()).unwrap(); + let data = CharacterDataCast::from_ref(text); + data.AppendData(t); + }, + // Otherwise, insert a new text node. + _ => { + let doc = self.document.root(); + let text = Text::new(t, doc.r()); + let node = NodeCast::from_temporary(text).root(); + assert!(parent.r().AppendChild(node.r()).is_ok()); + } + } + } + } } fn append_doctype_to_document(&mut self, name: String, public_id: String, system_id: String) { From 776255f036245f26d5f5fd8e7c8a50adeca66e2b Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Fri, 24 Apr 2015 14:59:47 -0700 Subject: [PATCH 2/2] fixup! Merge adjacent text nodes while appending --- components/script/parse/html.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index bafa18e9a161..ac8ad1d060b4 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentTypeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLScriptElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, NodeCast}; -use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast}; +use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; use dom::bindings::js::RootedReference; use dom::bindings::trace::RootedVec; @@ -155,8 +155,7 @@ impl<'a> TreeSink for servohtmlparser::Sink { // Append to an existing text node if possible. Some(ref prev_sibling) if prev_sibling.root().r().is_text() => { let node = prev_sibling.root(); - let text = TextCast::to_ref(node.r()).unwrap(); - let data = CharacterDataCast::from_ref(text); + let data = CharacterDataCast::to_ref(node.r()).unwrap(); data.AppendData(t); }, // Otherwise, insert a new text node.