1 // Copyright 2014-2017 The html5ever Project Developers. See the
2 // COPYRIGHT file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 mod types;
11 
12 use log::{debug, warn};
13 use mac::{matches, _tt_as_expr_hack, unwrap_or_return};
14 use markup5ever::{local_name, namespace_prefix, namespace_url, ns};
15 use std::borrow::Cow;
16 use std::borrow::Cow::Borrowed;
17 use std::collections::btree_map::Iter;
18 use std::collections::{BTreeMap, HashSet, VecDeque};
19 use std::fmt::{Debug, Error, Formatter};
20 use std::mem;
21 use std::result::Result;
22 
23 pub use self::interface::{NextParserState, NodeOrText, Tracer, TreeSink};
24 use self::types::*;
25 use crate::interface::{self, create_element, AppendNode, Attribute, QualName};
26 use crate::interface::{AppendText, ExpandedName};
27 use crate::tokenizer::states::Quiescent;
28 use crate::tokenizer::{self, EndTag, StartTag, Tag, TokenSink};
29 use crate::tokenizer::{Doctype, EmptyTag, Pi, ShortTag};
30 use crate::{LocalName, Namespace, Prefix};
31 
32 use crate::tendril::{StrTendril, Tendril};
33 
34 static XML_URI: &'static str = "http://www.w3.org/XML/1998/namespace";
35 static XMLNS_URI: &'static str = "http://www.w3.org/2000/xmlns/";
36 
37 type InsResult = Result<(), Cow<'static, str>>;
38 
39 #[derive(Debug)]
40 struct NamespaceMapStack(Vec<NamespaceMap>);
41 
42 impl NamespaceMapStack {
new() -> NamespaceMapStack43     fn new() -> NamespaceMapStack {
44         NamespaceMapStack({
45             let mut vec = Vec::new();
46             vec.push(NamespaceMap::default());
47             vec
48         })
49     }
50 
push(&mut self, map: NamespaceMap)51     fn push(&mut self, map: NamespaceMap) {
52         self.0.push(map);
53     }
54 
55     #[doc(hidden)]
pop(&mut self)56     pub fn pop(&mut self) {
57         self.0.pop();
58     }
59 }
60 
61 #[doc(hidden)]
62 pub struct NamespaceMap {
63     // Map that maps prefixes to URI.
64     //
65     // Key denotes namespace prefix, and value denotes
66     // URI it maps to.
67     //
68     // If value of value is None, that means the namespace
69     // denoted by key has been undeclared.
70     scope: BTreeMap<Option<Prefix>, Option<Namespace>>,
71 }
72 
73 impl Debug for NamespaceMap {
fmt(&self, f: &mut Formatter) -> Result<(), Error>74     fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
75         write!(f, "\nNamespaceMap[")?;
76         for (key, value) in &self.scope {
77             write!(f, "   {:?} : {:?}\n", key, value)?;
78         }
79         write!(f, "]")
80     }
81 }
82 
83 impl NamespaceMap {
84     // Returns an empty namespace.
85     #[doc(hidden)]
empty() -> NamespaceMap86     pub fn empty() -> NamespaceMap {
87         NamespaceMap {
88             scope: BTreeMap::new(),
89         }
90     }
91 
default() -> NamespaceMap92     fn default() -> NamespaceMap {
93         NamespaceMap {
94             scope: {
95                 let mut map = BTreeMap::new();
96                 map.insert(None, None);
97                 map.insert(Some(namespace_prefix!("xml")), Some(ns!(xml)));
98                 map.insert(Some(namespace_prefix!("xmlns")), Some(ns!(xmlns)));
99                 map
100             },
101         }
102     }
103 
104     #[doc(hidden)]
get(&self, prefix: &Option<Prefix>) -> Option<&Option<Namespace>>105     pub fn get(&self, prefix: &Option<Prefix>) -> Option<&Option<Namespace>> {
106         self.scope.get(prefix)
107     }
108 
109     #[doc(hidden)]
get_scope_iter(&self) -> Iter<Option<Prefix>, Option<Namespace>>110     pub fn get_scope_iter(&self) -> Iter<Option<Prefix>, Option<Namespace>> {
111         self.scope.iter()
112     }
113 
114     #[doc(hidden)]
insert(&mut self, name: &QualName)115     pub fn insert(&mut self, name: &QualName) {
116         let prefix = if let Some(ref p) = name.prefix {
117             Some(p.clone())
118         } else {
119             None
120         };
121         let namespace = Some(Namespace::from(&*name.ns));
122         self.scope.insert(prefix, namespace);
123     }
124 
insert_ns(&mut self, attr: &Attribute) -> InsResult125     fn insert_ns(&mut self, attr: &Attribute) -> InsResult {
126         if &*attr.value == XMLNS_URI {
127             return Err(Borrowed("Can't declare XMLNS URI"));
128         };
129 
130         let opt_uri = if attr.value.is_empty() {
131             None
132         } else {
133             Some(Namespace::from(&*attr.value))
134         };
135 
136         let result = match (&attr.name.prefix, &*attr.name.local) {
137             (&Some(namespace_prefix!("xmlns")), "xml") => {
138                 if &*attr.value != XML_URI {
139                     Err(Borrowed("XML namespace can't be redeclared"))
140                 } else {
141                     Ok(())
142                 }
143             },
144 
145             (&Some(namespace_prefix!("xmlns")), "xmlns") => {
146                 Err(Borrowed("XMLNS namespaces can't be changed"))
147             },
148 
149             (&Some(namespace_prefix!("xmlns")), _) | (&None, "xmlns") => {
150                 // We can have two cases of properly defined xmlns
151                 // First with default namespace e.g.
152                 //
153                 //     <a xmlns = "www.uri.org" />
154                 let ns_prefix = if &*attr.name.local == "xmlns" {
155                     None
156 
157                 // Second is with named namespace e.g.
158                 //
159                 //     <a xmlns:a = "www.uri.org" />
160                 } else {
161                     Some(Prefix::from(&*attr.name.local))
162                 };
163 
164                 if opt_uri.is_some() && self.scope.contains_key(&ns_prefix) {
165                     Err(Borrowed("Namespace already defined"))
166                 } else {
167                     self.scope.insert(ns_prefix, opt_uri);
168                     Ok(())
169                 }
170             },
171 
172             (_, _) => Err(Borrowed("Invalid namespace declaration.")),
173         };
174         result
175     }
176 }
177 
178 /// Tree builder options, with an impl for Default.
179 #[derive(Copy, Clone)]
180 pub struct XmlTreeBuilderOpts {}
181 
182 impl Default for XmlTreeBuilderOpts {
default() -> XmlTreeBuilderOpts183     fn default() -> XmlTreeBuilderOpts {
184         XmlTreeBuilderOpts {}
185     }
186 }
187 
188 /// The XML tree builder.
189 pub struct XmlTreeBuilder<Handle, Sink> {
190     /// Configuration options for XmlTreeBuilder
191     _opts: XmlTreeBuilderOpts,
192 
193     /// Consumer of tree modifications.
194     pub sink: Sink,
195 
196     /// The document node, which is created by the sink.
197     doc_handle: Handle,
198 
199     /// Next state change for the tokenizer, if any.
200     next_tokenizer_state: Option<tokenizer::states::XmlState>,
201 
202     /// Stack of open elements, most recently added at end.
203     open_elems: Vec<Handle>,
204 
205     /// Current element pointer.
206     curr_elem: Option<Handle>,
207 
208     /// Stack of namespace identifiers and namespaces.
209     namespace_stack: NamespaceMapStack,
210 
211     /// Current namespace identifier
212     current_namespace: NamespaceMap,
213 
214     /// List of already present namespace local name attribute pairs.
215     present_attrs: HashSet<(Namespace, LocalName)>,
216 
217     /// Current tree builder phase.
218     phase: XmlPhase,
219 }
220 impl<Handle, Sink> XmlTreeBuilder<Handle, Sink>
221 where
222     Handle: Clone,
223     Sink: TreeSink<Handle = Handle>,
224 {
225     /// Create a new tree builder which sends tree modifications to a particular `TreeSink`.
226     ///
227     /// The tree builder is also a `TokenSink`.
new(mut sink: Sink, opts: XmlTreeBuilderOpts) -> XmlTreeBuilder<Handle, Sink>228     pub fn new(mut sink: Sink, opts: XmlTreeBuilderOpts) -> XmlTreeBuilder<Handle, Sink> {
229         let doc_handle = sink.get_document();
230         XmlTreeBuilder {
231             _opts: opts,
232             sink: sink,
233             doc_handle: doc_handle,
234             next_tokenizer_state: None,
235             open_elems: vec![],
236             curr_elem: None,
237             namespace_stack: NamespaceMapStack::new(),
238             current_namespace: NamespaceMap::empty(),
239             present_attrs: HashSet::new(),
240             phase: StartPhase,
241         }
242     }
243 
244     /// Call the `Tracer`'s `trace_handle` method on every `Handle` in the tree builder's
245     /// internal state.  This is intended to support garbage-collected DOMs.
trace_handles(&self, tracer: &dyn Tracer<Handle = Handle>)246     pub fn trace_handles(&self, tracer: &dyn Tracer<Handle = Handle>) {
247         tracer.trace_handle(&self.doc_handle);
248         for e in self.open_elems.iter() {
249             tracer.trace_handle(&e);
250         }
251         self.curr_elem.as_ref().map(|h| tracer.trace_handle(&h));
252     }
253 
254     // Debug helper
255     #[cfg(not(for_c))]
256     #[allow(dead_code)]
dump_state(&self, label: String)257     fn dump_state(&self, label: String) {
258         debug!("dump_state on {}", label);
259         debug!("    open_elems:");
260         for node in self.open_elems.iter() {
261             debug!(" {:?}", self.sink.elem_name(node));
262         }
263         debug!("");
264     }
265 
266     #[cfg(for_c)]
debug_step(&self, _mode: XmlPhase, _token: &Token)267     fn debug_step(&self, _mode: XmlPhase, _token: &Token) {}
268 
269     #[cfg(not(for_c))]
debug_step(&self, mode: XmlPhase, token: &Token)270     fn debug_step(&self, mode: XmlPhase, token: &Token) {
271         debug!(
272             "processing {:?} in insertion mode {:?}",
273             format!("{:?}", token),
274             mode
275         );
276     }
277 
declare_ns(&mut self, attr: &mut Attribute)278     fn declare_ns(&mut self, attr: &mut Attribute) {
279         if let Err(msg) = self.current_namespace.insert_ns(&attr) {
280             self.sink.parse_error(msg);
281         } else {
282             attr.name.ns = ns!(xmlns);
283         }
284     }
285 
find_uri(&self, prefix: &Option<Prefix>) -> Result<Option<Namespace>, Cow<'static, str>>286     fn find_uri(&self, prefix: &Option<Prefix>) -> Result<Option<Namespace>, Cow<'static, str>> {
287         let mut uri = Err(Borrowed("No appropriate namespace found"));
288 
289         for ns in self
290             .namespace_stack
291             .0
292             .iter()
293             .chain(Some(&self.current_namespace))
294             .rev()
295         {
296             if let Some(el) = ns.get(prefix) {
297                 uri = Ok(el.clone());
298                 break;
299             }
300         }
301         uri
302     }
303 
bind_qname(&mut self, name: &mut QualName)304     fn bind_qname(&mut self, name: &mut QualName) {
305         match self.find_uri(&name.prefix) {
306             Ok(uri) => {
307                 let ns_uri = match uri {
308                     Some(e) => e,
309                     None => ns!(),
310                 };
311                 name.ns = ns_uri;
312             },
313             Err(msg) => {
314                 self.sink.parse_error(msg);
315             },
316         }
317     }
318 
319     // This method takes in name qualified name and binds it to the
320     // existing namespace context.
321     //
322     // Returns false if the attribute is a duplicate, returns true otherwise.
bind_attr_qname(&mut self, name: &mut QualName) -> bool323     fn bind_attr_qname(&mut self, name: &mut QualName) -> bool {
324         // Attributes don't have default namespace
325         let mut not_duplicate = true;
326 
327         if name.prefix.is_some() {
328             self.bind_qname(name);
329             not_duplicate = self.check_duplicate_attr(name);
330         }
331         not_duplicate
332     }
333 
check_duplicate_attr(&mut self, name: &QualName) -> bool334     fn check_duplicate_attr(&mut self, name: &QualName) -> bool {
335         let pair = (name.ns.clone(), name.local.clone());
336 
337         if self.present_attrs.contains(&pair) {
338             return false;
339         }
340         self.present_attrs.insert(pair);
341         true
342     }
343 
process_namespaces(&mut self, tag: &mut Tag)344     fn process_namespaces(&mut self, tag: &mut Tag) {
345         let mut new_attr = vec![];
346         // First we extract all namespace declarations
347         for mut attr in tag.attrs.iter_mut().filter(|attr| {
348             attr.name.prefix == Some(namespace_prefix!("xmlns")) ||
349                 attr.name.local == local_name!("xmlns")
350         }) {
351             self.declare_ns(&mut attr);
352         }
353 
354         // Then we bind those namespace declarations to attributes
355         for attr in tag.attrs.iter_mut().filter(|attr| {
356             attr.name.prefix != Some(namespace_prefix!("xmlns")) &&
357                 attr.name.local != local_name!("xmlns")
358         }) {
359             if self.bind_attr_qname(&mut attr.name) {
360                 new_attr.push(attr.clone());
361             }
362         }
363         mem::replace(&mut tag.attrs, new_attr);
364         // Then we bind the tags namespace.
365         self.bind_qname(&mut tag.name);
366 
367         // Finally, we dump current namespace if its unneeded.
368         let x = mem::replace(&mut self.current_namespace, NamespaceMap::empty());
369 
370         // Only start tag doesn't dump current namespace. However, <script /> is treated
371         // differently than every other empty tag, so it needs to retain the current
372         // namespace as well.
373         if tag.kind == StartTag || (tag.kind == EmptyTag && tag.name.local == local_name!("script"))
374         {
375             self.namespace_stack.push(x);
376         }
377     }
378 
process_to_completion(&mut self, mut token: Token)379     fn process_to_completion(&mut self, mut token: Token) {
380         // Queue of additional tokens yet to be processed.
381         // This stays empty in the common case where we don't split whitespace.
382         let mut more_tokens = VecDeque::new();
383 
384         loop {
385             let phase = self.phase;
386             match self.step(phase, token) {
387                 Done => {
388                     token = unwrap_or_return!(more_tokens.pop_front(), ());
389                 },
390                 Reprocess(m, t) => {
391                     self.phase = m;
392                     token = t;
393                 },
394             }
395         }
396     }
397 }
398 
399 impl<Handle, Sink> TokenSink for XmlTreeBuilder<Handle, Sink>
400 where
401     Handle: Clone,
402     Sink: TreeSink<Handle = Handle>,
403 {
process_token(&mut self, token: tokenizer::Token)404     fn process_token(&mut self, token: tokenizer::Token) {
405         // Handle `ParseError` and `DoctypeToken`; convert everything else to the local `Token` type.
406         let token = match token {
407             tokenizer::ParseError(e) => {
408                 self.sink.parse_error(e);
409                 return;
410             },
411 
412             tokenizer::DoctypeToken(d) => DoctypeToken(d),
413             tokenizer::PIToken(x) => PIToken(x),
414             tokenizer::TagToken(x) => TagToken(x),
415             tokenizer::CommentToken(x) => CommentToken(x),
416             tokenizer::NullCharacterToken => NullCharacterToken,
417             tokenizer::EOFToken => EOFToken,
418             tokenizer::CharacterTokens(x) => CharacterTokens(x),
419         };
420 
421         self.process_to_completion(token);
422     }
423 
end(&mut self)424     fn end(&mut self) {
425         for node in self.open_elems.drain(..).rev() {
426             self.sink.pop(&node);
427         }
428     }
429 
query_state_change(&mut self) -> Option<tokenizer::states::XmlState>430     fn query_state_change(&mut self) -> Option<tokenizer::states::XmlState> {
431         self.next_tokenizer_state.take()
432     }
433 }
434 
current_node<Handle>(open_elems: &[Handle]) -> &Handle435 fn current_node<Handle>(open_elems: &[Handle]) -> &Handle {
436     open_elems.last().expect("no current element")
437 }
438 
439 #[doc(hidden)]
440 impl<Handle, Sink> XmlTreeBuilder<Handle, Sink>
441 where
442     Handle: Clone,
443     Sink: TreeSink<Handle = Handle>,
444 {
current_node(&self) -> &Handle445     fn current_node(&self) -> &Handle {
446         self.open_elems.last().expect("no current element")
447     }
448 
insert_appropriately(&mut self, child: NodeOrText<Handle>)449     fn insert_appropriately(&mut self, child: NodeOrText<Handle>) {
450         let target = current_node(&self.open_elems);
451         self.sink.append(target, child);
452     }
453 
insert_tag(&mut self, tag: Tag) -> XmlProcessResult454     fn insert_tag(&mut self, tag: Tag) -> XmlProcessResult {
455         let child = create_element(&mut self.sink, tag.name, tag.attrs);
456         self.insert_appropriately(AppendNode(child.clone()));
457         self.add_to_open_elems(child)
458     }
459 
append_tag(&mut self, tag: Tag) -> XmlProcessResult460     fn append_tag(&mut self, tag: Tag) -> XmlProcessResult {
461         let child = create_element(&mut self.sink, tag.name, tag.attrs);
462         self.insert_appropriately(AppendNode(child.clone()));
463         self.sink.pop(&child);
464         Done
465     }
466 
append_tag_to_doc(&mut self, tag: Tag) -> Handle467     fn append_tag_to_doc(&mut self, tag: Tag) -> Handle {
468         let child = create_element(&mut self.sink, tag.name, tag.attrs);
469 
470         self.sink
471             .append(&self.doc_handle, AppendNode(child.clone()));
472         child
473     }
474 
add_to_open_elems(&mut self, el: Handle) -> XmlProcessResult475     fn add_to_open_elems(&mut self, el: Handle) -> XmlProcessResult {
476         self.open_elems.push(el);
477 
478         Done
479     }
480 
append_comment_to_doc(&mut self, text: StrTendril) -> XmlProcessResult481     fn append_comment_to_doc(&mut self, text: StrTendril) -> XmlProcessResult {
482         let comment = self.sink.create_comment(text);
483         self.sink.append(&self.doc_handle, AppendNode(comment));
484         Done
485     }
486 
append_comment_to_tag(&mut self, text: StrTendril) -> XmlProcessResult487     fn append_comment_to_tag(&mut self, text: StrTendril) -> XmlProcessResult {
488         let target = current_node(&self.open_elems);
489         let comment = self.sink.create_comment(text);
490         self.sink.append(target, AppendNode(comment));
491         Done
492     }
493 
append_doctype_to_doc(&mut self, doctype: Doctype) -> XmlProcessResult494     fn append_doctype_to_doc(&mut self, doctype: Doctype) -> XmlProcessResult {
495         fn get_tendril(opt: Option<StrTendril>) -> StrTendril {
496             match opt {
497                 Some(expr) => expr,
498                 None => Tendril::new(),
499             }
500         };
501         self.sink.append_doctype_to_document(
502             get_tendril(doctype.name),
503             get_tendril(doctype.public_id),
504             get_tendril(doctype.system_id),
505         );
506         Done
507     }
508 
append_pi_to_doc(&mut self, pi: Pi) -> XmlProcessResult509     fn append_pi_to_doc(&mut self, pi: Pi) -> XmlProcessResult {
510         let pi = self.sink.create_pi(pi.target, pi.data);
511         self.sink.append(&self.doc_handle, AppendNode(pi));
512         Done
513     }
514 
append_pi_to_tag(&mut self, pi: Pi) -> XmlProcessResult515     fn append_pi_to_tag(&mut self, pi: Pi) -> XmlProcessResult {
516         let target = current_node(&self.open_elems);
517         let pi = self.sink.create_pi(pi.target, pi.data);
518         self.sink.append(target, AppendNode(pi));
519         Done
520     }
521 
append_text(&mut self, chars: StrTendril) -> XmlProcessResult522     fn append_text(&mut self, chars: StrTendril) -> XmlProcessResult {
523         self.insert_appropriately(AppendText(chars));
524         Done
525     }
526 
tag_in_open_elems(&self, tag: &Tag) -> bool527     fn tag_in_open_elems(&self, tag: &Tag) -> bool {
528         self.open_elems
529             .iter()
530             .any(|a| self.sink.elem_name(a) == tag.name.expanded())
531     }
532 
533     // Pop elements until an element from the set has been popped.  Returns the
534     // number of elements popped.
pop_until<P>(&mut self, pred: P) where P: Fn(ExpandedName) -> bool,535     fn pop_until<P>(&mut self, pred: P)
536     where
537         P: Fn(ExpandedName) -> bool,
538     {
539         loop {
540             if self.current_node_in(|x| pred(x)) {
541                 break;
542             }
543             self.pop();
544         }
545     }
546 
current_node_in<TagSet>(&self, set: TagSet) -> bool where TagSet: Fn(ExpandedName) -> bool,547     fn current_node_in<TagSet>(&self, set: TagSet) -> bool
548     where
549         TagSet: Fn(ExpandedName) -> bool,
550     {
551         // FIXME: take namespace into consideration:
552         set(self.sink.elem_name(self.current_node()))
553     }
554 
close_tag(&mut self, tag: Tag) -> XmlProcessResult555     fn close_tag(&mut self, tag: Tag) -> XmlProcessResult {
556         debug!(
557             "Close tag: current_node.name {:?} \n Current tag {:?}",
558             self.sink.elem_name(self.current_node()),
559             &tag.name
560         );
561 
562         if *self.sink.elem_name(self.current_node()).local != tag.name.local {
563             self.sink
564                 .parse_error(Borrowed("Current node doesn't match tag"));
565         }
566 
567         let is_closed = self.tag_in_open_elems(&tag);
568 
569         if is_closed {
570             self.pop_until(|p| p == tag.name.expanded());
571             self.pop();
572         }
573 
574         Done
575     }
576 
no_open_elems(&self) -> bool577     fn no_open_elems(&self) -> bool {
578         self.open_elems.is_empty()
579     }
580 
pop(&mut self) -> Handle581     fn pop(&mut self) -> Handle {
582         self.namespace_stack.pop();
583         let node = self.open_elems.pop().expect("no current element");
584         self.sink.pop(&node);
585         node
586     }
587 
stop_parsing(&mut self) -> XmlProcessResult588     fn stop_parsing(&mut self) -> XmlProcessResult {
589         warn!("stop_parsing for XML5 not implemented, full speed ahead!");
590         Done
591     }
592 
complete_script(&mut self)593     fn complete_script(&mut self) {
594         let current = current_node(&self.open_elems);
595         if self.sink.complete_script(current) == NextParserState::Suspend {
596             self.next_tokenizer_state = Some(Quiescent);
597         }
598     }
599 }
600 
any_not_whitespace(x: &StrTendril) -> bool601 fn any_not_whitespace(x: &StrTendril) -> bool {
602     !x.bytes()
603         .all(|b| matches!(b, b'\t' | b'\r' | b'\n' | b'\x0C' | b' '))
604 }
605 
606 #[doc(hidden)]
607 impl<Handle, Sink> XmlTreeBuilder<Handle, Sink>
608 where
609     Handle: Clone,
610     Sink: TreeSink<Handle = Handle>,
611 {
step(&mut self, mode: XmlPhase, token: Token) -> XmlProcessResult612     fn step(&mut self, mode: XmlPhase, token: Token) -> XmlProcessResult {
613         self.debug_step(mode, &token);
614 
615         match mode {
616             StartPhase => match token {
617                 TagToken(Tag {
618                     kind: StartTag,
619                     name,
620                     attrs,
621                 }) => {
622                     let tag = {
623                         let mut tag = Tag {
624                             kind: StartTag,
625                             name: name,
626                             attrs: attrs,
627                         };
628                         self.process_namespaces(&mut tag);
629                         tag
630                     };
631                     self.phase = MainPhase;
632                     let handle = self.append_tag_to_doc(tag);
633                     self.add_to_open_elems(handle)
634                 },
635                 TagToken(Tag {
636                     kind: EmptyTag,
637                     name,
638                     attrs,
639                 }) => {
640                     let tag = {
641                         let mut tag = Tag {
642                             kind: EmptyTag,
643                             name: name,
644                             attrs: attrs,
645                         };
646                         self.process_namespaces(&mut tag);
647                         tag
648                     };
649                     self.phase = EndPhase;
650                     let handle = self.append_tag_to_doc(tag);
651                     self.sink.pop(&handle);
652                     Done
653                 },
654                 CommentToken(comment) => self.append_comment_to_doc(comment),
655                 PIToken(pi) => self.append_pi_to_doc(pi),
656                 CharacterTokens(ref chars) if !any_not_whitespace(chars) => Done,
657                 EOFToken => {
658                     self.sink
659                         .parse_error(Borrowed("Unexpected EOF in start phase"));
660                     Reprocess(EndPhase, EOFToken)
661                 },
662                 DoctypeToken(d) => {
663                     self.append_doctype_to_doc(d);
664                     Done
665                 },
666                 _ => {
667                     self.sink
668                         .parse_error(Borrowed("Unexpected element in start phase"));
669                     Done
670                 },
671             },
672             MainPhase => match token {
673                 CharacterTokens(chs) => self.append_text(chs),
674                 TagToken(Tag {
675                     kind: StartTag,
676                     name,
677                     attrs,
678                 }) => {
679                     let tag = {
680                         let mut tag = Tag {
681                             kind: StartTag,
682                             name: name,
683                             attrs: attrs,
684                         };
685                         self.process_namespaces(&mut tag);
686                         tag
687                     };
688                     self.insert_tag(tag)
689                 },
690                 TagToken(Tag {
691                     kind: EmptyTag,
692                     name,
693                     attrs,
694                 }) => {
695                     let tag = {
696                         let mut tag = Tag {
697                             kind: EmptyTag,
698                             name: name,
699                             attrs: attrs,
700                         };
701                         self.process_namespaces(&mut tag);
702                         tag
703                     };
704                     if tag.name.local == local_name!("script") {
705                         self.insert_tag(tag.clone());
706                         self.complete_script();
707                         self.close_tag(tag)
708                     } else {
709                         self.append_tag(tag)
710                     }
711                 },
712                 TagToken(Tag {
713                     kind: EndTag,
714                     name,
715                     attrs,
716                 }) => {
717                     let tag = {
718                         let mut tag = Tag {
719                             kind: EndTag,
720                             name: name,
721                             attrs: attrs,
722                         };
723                         self.process_namespaces(&mut tag);
724                         tag
725                     };
726                     if tag.name.local == local_name!("script") {
727                         self.complete_script();
728                     }
729                     let retval = self.close_tag(tag);
730                     if self.no_open_elems() {
731                         self.phase = EndPhase;
732                     }
733                     retval
734                 },
735                 TagToken(Tag { kind: ShortTag, .. }) => {
736                     self.pop();
737                     if self.no_open_elems() {
738                         self.phase = EndPhase;
739                     }
740                     Done
741                 },
742                 CommentToken(comment) => self.append_comment_to_tag(comment),
743                 PIToken(pi) => self.append_pi_to_tag(pi),
744                 EOFToken | NullCharacterToken => Reprocess(EndPhase, EOFToken),
745                 DoctypeToken(_) => {
746                     self.sink
747                         .parse_error(Borrowed("Unexpected element in main phase"));
748                     Done
749                 },
750             },
751             EndPhase => match token {
752                 CommentToken(comment) => self.append_comment_to_doc(comment),
753                 PIToken(pi) => self.append_pi_to_doc(pi),
754                 CharacterTokens(ref chars) if !any_not_whitespace(chars) => Done,
755                 EOFToken => self.stop_parsing(),
756                 _ => {
757                     self.sink
758                         .parse_error(Borrowed("Unexpected element in end phase"));
759                     Done
760                 },
761             },
762         }
763     }
764 }
765