1#![cfg_attr(crown, expect(crown::unrooted_must_root))]
6
7use std::borrow::Cow;
8use std::cell::{Cell, Ref, RefCell, RefMut};
9use std::collections::vec_deque::VecDeque;
10use std::rc::Rc;
11use std::thread;
12
13use crossbeam_channel::{Receiver, Sender, unbounded};
14use html5ever::buffer_queue::BufferQueue;
15use html5ever::tendril::fmt::UTF8;
16use html5ever::tendril::{SendTendril, StrTendril, Tendril};
17use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts};
18use html5ever::tree_builder::{
19 ElementFlags, NodeOrText as HtmlNodeOrText, QuirksMode, TreeBuilder, TreeBuilderOpts, TreeSink,
20};
21use html5ever::{Attribute as HtmlAttribute, ExpandedName, QualName, local_name, ns};
22use markup5ever::TokenizerResult;
23use rustc_hash::FxHashMap;
24use servo_url::ServoUrl;
25use style::context::QuirksMode as ServoQuirksMode;
26
27use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
28use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
29use crate::dom::bindings::inheritance::Castable;
30use crate::dom::bindings::root::{Dom, DomRoot};
31use crate::dom::bindings::str::DOMString;
32use crate::dom::comment::Comment;
33use crate::dom::customelementregistry::CustomElementReactionStack;
34use crate::dom::document::Document;
35use crate::dom::documenttype::DocumentType;
36use crate::dom::element::{Element, ElementCreator};
37use crate::dom::html::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
38use crate::dom::html::htmlscriptelement::HTMLScriptElement;
39use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
40use crate::dom::node::Node;
41use crate::dom::node::virtualmethods::vtable_for;
42use crate::dom::processinginstruction::ProcessingInstruction;
43use crate::dom::servoparser::{
44 ElementAttribute, ParsingAlgorithm, attach_declarative_shadow_inner, create_element_for_token,
45};
46
47type ParseNodeId = usize;
48
49#[derive(Clone, Debug, JSTraceable, MallocSizeOf)]
50pub(crate) struct ParseNode {
51 id: ParseNodeId,
52 #[no_trace]
53 qual_name: Option<QualName>,
54}
55
56#[derive(Debug, JSTraceable, MallocSizeOf)]
57enum NodeOrText {
58 Node(ParseNode),
59 Text(String),
60}
61
62#[derive(Debug, JSTraceable, MallocSizeOf)]
63struct Attribute {
64 #[no_trace]
65 name: QualName,
66 value: String,
67}
68
69#[derive(Debug, JSTraceable, MallocSizeOf)]
70enum ParseOperation {
71 GetTemplateContents {
72 target: ParseNodeId,
73 contents: ParseNodeId,
74 },
75 CreateElement {
76 node: ParseNodeId,
77 #[no_trace]
78 name: QualName,
79 attrs: Vec<Attribute>,
80 current_line: u64,
81 had_duplicate_attributes: bool,
82 },
83 CreateComment {
84 text: String,
85 node: ParseNodeId,
86 },
87 AppendBeforeSibling {
88 sibling: ParseNodeId,
89 node: NodeOrText,
90 },
91 AppendBasedOnParentNode {
92 element: ParseNodeId,
93 prev_element: ParseNodeId,
94 node: NodeOrText,
95 },
96 Append {
97 parent: ParseNodeId,
98 node: NodeOrText,
99 },
100 AppendDoctypeToDocument {
101 name: String,
102 public_id: String,
103 system_id: String,
104 },
105 AddAttrsIfMissing {
106 target: ParseNodeId,
107 attrs: Vec<Attribute>,
108 },
109 RemoveFromParent {
110 target: ParseNodeId,
111 },
112 MarkScriptAlreadyStarted {
113 node: ParseNodeId,
114 },
115 ReparentChildren {
116 parent: ParseNodeId,
117 new_parent: ParseNodeId,
118 },
119 AssociateWithForm {
120 target: ParseNodeId,
121 form: ParseNodeId,
122 element: ParseNodeId,
123 prev_element: Option<ParseNodeId>,
124 },
125 CreatePI {
126 node: ParseNodeId,
127 target: String,
128 data: String,
129 },
130 Pop {
131 node: ParseNodeId,
132 },
133 SetQuirksMode {
134 #[ignore_malloc_size_of = "Defined in style"]
135 #[no_trace]
136 mode: ServoQuirksMode,
137 },
138 AttachDeclarativeShadowRoot {
139 location: ParseNodeId,
140 template: ParseNodeId,
141 attributes: Vec<Attribute>,
142 #[no_trace]
144 sender: Sender<bool>,
145 },
146}
147
148#[derive(MallocSizeOf)]
149enum FromParserThreadMsg {
150 TokenizerResultDone {
151 updated_input: VecDeque<SendTendril<UTF8>>,
152 },
153 TokenizerResultScript {
154 script: ParseNode,
155 updated_input: VecDeque<SendTendril<UTF8>>,
156 },
157 EncodingIndicator {
158 encoding: SendTendril<UTF8>,
159 updated_input: VecDeque<SendTendril<UTF8>>,
160 },
161 End,
163 ProcessOperation(ParseOperation),
164}
165
166#[derive(MallocSizeOf)]
167enum ToParserThreadMsg {
168 Feed { input: VecDeque<SendTendril<UTF8>> },
169 End,
170 SetPlainTextState,
171}
172
173fn create_buffer_queue(mut buffers: VecDeque<SendTendril<UTF8>>) -> BufferQueue {
174 let buffer_queue = BufferQueue::default();
175 while let Some(st) = buffers.pop_front() {
176 buffer_queue.push_back(StrTendril::from(st));
177 }
178 buffer_queue
179}
180
181#[derive(JSTraceable, MallocSizeOf)]
207#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
208pub(crate) struct Tokenizer {
209 document: Dom<Document>,
210 #[no_trace]
211 from_parser_thread_receiver: Receiver<FromParserThreadMsg>,
212 #[no_trace]
214 to_parser_thread_sender: Sender<ToParserThreadMsg>,
215 nodes: RefCell<FxHashMap<ParseNodeId, Dom<Node>>>,
216 #[no_trace]
217 url: ServoUrl,
218 parsing_algorithm: ParsingAlgorithm,
219 #[conditional_malloc_size_of]
220 custom_element_reaction_stack: Rc<CustomElementReactionStack>,
221 current_line: Cell<u64>,
222 has_ended: Cell<bool>,
223}
224
225impl Tokenizer {
226 pub(crate) fn new(
227 document: &Document,
228 url: ServoUrl,
229 fragment_context: Option<super::FragmentContext>,
230 ) -> Self {
231 let (to_parser_thread_sender, from_main_thread_receiver) = unbounded();
233 let (to_main_thread_sender, from_parser_thread_receiver) = unbounded();
235
236 let algorithm = match fragment_context {
237 Some(_) => ParsingAlgorithm::Fragment,
238 None => ParsingAlgorithm::Normal,
239 };
240
241 let custom_element_reaction_stack = document.custom_element_reaction_stack();
242 let tokenizer = Tokenizer {
243 document: Dom::from_ref(document),
244 from_parser_thread_receiver,
245 to_parser_thread_sender,
246 nodes: RefCell::new(FxHashMap::default()),
247 url,
248 parsing_algorithm: algorithm,
249 custom_element_reaction_stack,
250 current_line: Cell::new(1),
251 has_ended: Cell::new(false),
252 };
253 tokenizer.insert_node(0, Dom::from_ref(document.upcast()));
254
255 let sink = Sink::new(
256 to_main_thread_sender.clone(),
257 document.allow_declarative_shadow_roots(),
258 );
259 let mut form_parse_node = None;
260 let mut parser_fragment_context = None;
261 if let Some(fragment_context) = fragment_context {
262 let node = sink.new_parse_node();
263 tokenizer.insert_node(node.id, Dom::from_ref(fragment_context.context_elem));
264 parser_fragment_context =
265 Some((node, fragment_context.context_element_allows_scripting));
266
267 form_parse_node = fragment_context.form_elem.map(|form_elem| {
268 let node = sink.new_parse_node();
269 tokenizer.insert_node(node.id, Dom::from_ref(form_elem));
270 node
271 });
272 };
273
274 let scripting_enabled = document.has_browsing_context();
278 thread::Builder::new()
279 .name(format!("Parse:{}", tokenizer.url.debug_compact()))
280 .spawn(move || {
281 run(
282 sink,
283 parser_fragment_context,
284 form_parse_node,
285 to_main_thread_sender,
286 from_main_thread_receiver,
287 scripting_enabled,
288 );
289 })
290 .expect("HTML Parser thread spawning failed");
291
292 tokenizer
293 }
294
295 pub(crate) fn feed(
296 &self,
297 input: &BufferQueue,
298 cx: &mut js::context::JSContext,
299 ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
300 let mut send_tendrils = VecDeque::new();
301 while let Some(str) = input.pop_front() {
302 send_tendrils.push_back(SendTendril::from(str));
303 }
304
305 self.to_parser_thread_sender
308 .send(ToParserThreadMsg::Feed {
309 input: send_tendrils,
310 })
311 .unwrap();
312
313 loop {
314 debug_assert!(!self.has_ended.get());
315
316 match self
317 .from_parser_thread_receiver
318 .recv()
319 .expect("Unexpected channel panic in main thread.")
320 {
321 FromParserThreadMsg::ProcessOperation(parse_op) => {
322 self.process_operation(parse_op, cx);
323
324 if self.has_ended.get() {
327 return TokenizerResult::Done;
328 }
329 },
330 FromParserThreadMsg::TokenizerResultDone { updated_input } => {
331 let buffer_queue = create_buffer_queue(updated_input);
332 input.replace_with(buffer_queue);
333 return TokenizerResult::Done;
334 },
335 FromParserThreadMsg::TokenizerResultScript {
336 script,
337 updated_input,
338 } => {
339 let buffer_queue = create_buffer_queue(updated_input);
340 input.replace_with(buffer_queue);
341 let script = self.get_node(&script.id);
342 return TokenizerResult::Script(DomRoot::from_ref(script.downcast().unwrap()));
343 },
344 FromParserThreadMsg::EncodingIndicator { updated_input, .. } => {
345 self.to_parser_thread_sender
348 .send(ToParserThreadMsg::Feed {
349 input: updated_input,
350 })
351 .unwrap();
352 },
353 _ => unreachable!(),
354 };
355 }
356 }
357
358 pub(crate) fn end(&self, cx: &mut js::context::JSContext) {
359 if self.has_ended.replace(true) {
360 return;
361 }
362
363 self.to_parser_thread_sender
364 .send(ToParserThreadMsg::End)
365 .unwrap();
366
367 loop {
368 match self
369 .from_parser_thread_receiver
370 .recv()
371 .expect("Unexpected channel panic in main thread.")
372 {
373 FromParserThreadMsg::ProcessOperation(parse_op) => {
374 self.process_operation(parse_op, cx);
375 },
376 FromParserThreadMsg::TokenizerResultDone { updated_input: _ } |
377 FromParserThreadMsg::TokenizerResultScript { .. } |
378 FromParserThreadMsg::EncodingIndicator { .. } => continue,
379 FromParserThreadMsg::End => return,
380 };
381 }
382 }
383
384 pub(crate) fn url(&self) -> &ServoUrl {
385 &self.url
386 }
387
388 pub(crate) fn set_plaintext_state(&self) {
389 self.to_parser_thread_sender
390 .send(ToParserThreadMsg::SetPlainTextState)
391 .unwrap();
392 }
393
394 pub(crate) fn get_current_line(&self) -> u32 {
395 self.current_line.get() as u32
396 }
397
398 fn insert_node(&self, id: ParseNodeId, node: Dom<Node>) {
399 assert!(self.nodes.borrow_mut().insert(id, node).is_none());
400 }
401
402 fn get_node<'a>(&'a self, id: &ParseNodeId) -> Ref<'a, Dom<Node>> {
403 Ref::map(self.nodes.borrow(), |nodes| {
404 nodes.get(id).expect("Node not found!")
405 })
406 }
407
408 fn append_before_sibling(
409 &self,
410 cx: &mut js::context::JSContext,
411 sibling: ParseNodeId,
412 node: NodeOrText,
413 ) {
414 let node = match node {
415 NodeOrText::Node(n) => {
416 HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
417 },
418 NodeOrText::Text(text) => HtmlNodeOrText::AppendText(Tendril::from(text)),
419 };
420 let sibling = &**self.get_node(&sibling);
421 let parent = &*sibling
422 .GetParentNode()
423 .expect("append_before_sibling called on node without parent");
424
425 super::insert(
426 cx,
427 parent,
428 Some(sibling),
429 node,
430 self.parsing_algorithm,
431 &self.custom_element_reaction_stack,
432 );
433 }
434
435 fn append(&self, cx: &mut js::context::JSContext, parent: ParseNodeId, node: NodeOrText) {
436 let node = match node {
437 NodeOrText::Node(n) => {
438 HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
439 },
440 NodeOrText::Text(text) => HtmlNodeOrText::AppendText(Tendril::from(text)),
441 };
442
443 let parent = &**self.get_node(&parent);
444 super::insert(
445 cx,
446 parent,
447 None,
448 node,
449 self.parsing_algorithm,
450 &self.custom_element_reaction_stack,
451 );
452 }
453
454 fn has_parent_node(&self, node: ParseNodeId) -> bool {
455 self.get_node(&node).GetParentNode().is_some()
456 }
457
458 fn same_tree(&self, x: ParseNodeId, y: ParseNodeId) -> bool {
459 let x = self.get_node(&x);
460 let y = self.get_node(&y);
461
462 let x = x.downcast::<Element>().expect("Element node expected");
463 let y = y.downcast::<Element>().expect("Element node expected");
464 x.is_in_same_home_subtree(y)
465 }
466
467 fn process_operation(&self, op: ParseOperation, cx: &mut js::context::JSContext) {
468 let document = DomRoot::from_ref(&**self.get_node(&0));
469 let document = document
470 .downcast::<Document>()
471 .expect("Document node should be downcasted!");
472 match op {
473 ParseOperation::GetTemplateContents { target, contents } => {
474 let target = DomRoot::from_ref(&**self.get_node(&target));
475 let template = target
476 .downcast::<HTMLTemplateElement>()
477 .expect("Tried to extract contents from non-template element while parsing");
478 self.insert_node(contents, Dom::from_ref(template.Content(cx).upcast()));
479 },
480 ParseOperation::CreateElement {
481 node,
482 name,
483 attrs,
484 current_line,
485 had_duplicate_attributes,
486 } => {
487 self.current_line.set(current_line);
488 let attrs = attrs
489 .into_iter()
490 .map(|attr| ElementAttribute::new(attr.name, DOMString::from(attr.value)))
491 .collect();
492 let element = create_element_for_token(
493 cx,
494 name,
495 attrs,
496 &self.document,
497 ElementCreator::ParserCreated(current_line),
498 ParsingAlgorithm::Normal,
499 &self.custom_element_reaction_stack,
500 had_duplicate_attributes,
501 );
502 self.insert_node(node, Dom::from_ref(element.upcast()));
503 },
504 ParseOperation::CreateComment { text, node } => {
505 let comment = Comment::new(cx, DOMString::from(text), document, None);
506 self.insert_node(node, Dom::from_ref(comment.upcast()));
507 },
508 ParseOperation::AppendBeforeSibling { sibling, node } => {
509 self.append_before_sibling(cx, sibling, node);
510 },
511 ParseOperation::Append { parent, node } => {
512 self.append(cx, parent, node);
513 },
514 ParseOperation::AppendBasedOnParentNode {
515 element,
516 prev_element,
517 node,
518 } => {
519 if self.has_parent_node(element) {
520 self.append_before_sibling(cx, element, node);
521 } else {
522 self.append(cx, prev_element, node);
523 }
524 },
525 ParseOperation::AppendDoctypeToDocument {
526 name,
527 public_id,
528 system_id,
529 } => {
530 let doctype = DocumentType::new(
531 cx,
532 DOMString::from(name),
533 Some(DOMString::from(public_id)),
534 Some(DOMString::from(system_id)),
535 document,
536 );
537
538 document
539 .upcast::<Node>()
540 .AppendChild(cx, doctype.upcast())
541 .expect("Appending failed");
542 },
543 ParseOperation::AddAttrsIfMissing { target, attrs } => {
544 let node = self.get_node(&target);
545 let elem = node
546 .downcast::<Element>()
547 .expect("tried to set attrs on non-Element in HTML parsing");
548 for attr in attrs {
549 elem.set_attribute_from_parser(cx, attr.name, DOMString::from(attr.value));
550 }
551 },
552 ParseOperation::RemoveFromParent { target } => {
553 if let Some(ref parent) = self.get_node(&target).GetParentNode() {
554 parent.RemoveChild(cx, &self.get_node(&target)).unwrap();
555 }
556 },
557 ParseOperation::MarkScriptAlreadyStarted { node } => {
558 let node = self.get_node(&node);
559 let script = node.downcast::<HTMLScriptElement>();
560 if let Some(script) = script {
561 script.set_already_started(true)
562 }
563 },
564 ParseOperation::ReparentChildren { parent, new_parent } => {
565 let parent = self.get_node(&parent);
566 let new_parent = self.get_node(&new_parent);
567 while let Some(child) = parent.GetFirstChild() {
568 new_parent.AppendChild(cx, &child).unwrap();
569 }
570 },
571 ParseOperation::AssociateWithForm {
572 target,
573 form,
574 element,
575 prev_element,
576 } => {
577 let tree_node = prev_element.map_or(element, |prev| {
578 if self.has_parent_node(element) {
579 element
580 } else {
581 prev
582 }
583 });
584
585 if !self.same_tree(tree_node, form) {
586 return;
587 }
588 let form = self.get_node(&form);
589 let form = DomRoot::downcast::<HTMLFormElement>(DomRoot::from_ref(&**form))
590 .expect("Owner must be a form element");
591
592 let node = self.get_node(&target);
593 let elem = node.downcast::<Element>();
594 let control = elem.and_then(|e| e.as_maybe_form_control());
595
596 if let Some(control) = control {
597 control.set_form_owner_from_parser(cx, &form);
598 }
599 },
600 ParseOperation::Pop { node } => {
601 vtable_for(&self.get_node(&node)).pop(cx);
602 },
603 ParseOperation::CreatePI { node, target, data } => {
604 let pi = ProcessingInstruction::new(
605 cx,
606 DOMString::from(target),
607 DOMString::from(data),
608 document,
609 );
610 self.insert_node(node, Dom::from_ref(pi.upcast()));
611 },
612 ParseOperation::SetQuirksMode { mode } => {
613 document.set_quirks_mode(mode);
614 },
615 ParseOperation::AttachDeclarativeShadowRoot {
616 location,
617 template,
618 attributes,
619 sender,
620 } => {
621 let location = self.get_node(&location);
622 let template = self.get_node(&template);
623 let attributes: Vec<_> = attributes
624 .into_iter()
625 .map(|attribute| HtmlAttribute {
626 name: attribute.name,
627 value: StrTendril::from(attribute.value),
628 })
629 .collect();
630
631 let did_succeed =
632 attach_declarative_shadow_inner(cx, &location, &template, &attributes);
633 sender.send(did_succeed).unwrap();
634 },
635 }
636 }
637}
638
639fn run(
646 sink: Sink,
647 fragment_context: Option<(ParseNode, bool)>,
648 form_parse_node: Option<ParseNode>,
649 sender: Sender<FromParserThreadMsg>,
650 receiver: Receiver<ToParserThreadMsg>,
651 scripting_enabled: bool,
652) {
653 let options = TreeBuilderOpts {
654 scripting_enabled,
655 ..Default::default()
656 };
657
658 let html_tokenizer = if let Some((context_node, context_scripting_enabled)) = fragment_context {
659 let tree_builder =
660 TreeBuilder::new_for_fragment(sink, context_node, form_parse_node, options);
661
662 let tok_options = TokenizerOpts {
663 initial_state: Some(
664 tree_builder.tokenizer_state_for_context_elem(context_scripting_enabled),
665 ),
666 ..Default::default()
667 };
668
669 HtmlTokenizer::new(tree_builder, tok_options)
670 } else {
671 HtmlTokenizer::new(TreeBuilder::new(sink, options), Default::default())
672 };
673
674 loop {
675 match receiver
676 .recv()
677 .expect("Unexpected channel panic in html parser thread")
678 {
679 ToParserThreadMsg::Feed { input } => {
680 let input = create_buffer_queue(input);
681 let res = html_tokenizer.feed(&input);
682
683 let mut updated_input = VecDeque::new();
686 while let Some(st) = input.pop_front() {
687 updated_input.push_back(SendTendril::from(st));
688 }
689
690 let res = match res {
691 TokenizerResult::Done => {
692 FromParserThreadMsg::TokenizerResultDone { updated_input }
693 },
694 TokenizerResult::Script(script) => FromParserThreadMsg::TokenizerResultScript {
695 script,
696 updated_input,
697 },
698 TokenizerResult::EncodingIndicator(encoding) => {
699 FromParserThreadMsg::EncodingIndicator {
700 encoding: SendTendril::from(encoding),
701 updated_input,
702 }
703 },
704 };
705 sender.send(res).unwrap();
706 },
707 ToParserThreadMsg::End => {
708 html_tokenizer.end();
709 sender.send(FromParserThreadMsg::End).unwrap();
710 break;
711 },
712 ToParserThreadMsg::SetPlainTextState => html_tokenizer.set_plaintext_state(),
713 };
714 }
715}
716
717#[derive(Default, JSTraceable, MallocSizeOf)]
718struct ParseNodeData {
719 contents: Option<ParseNode>,
720 is_integration_point: bool,
721}
722
723pub(crate) struct Sink {
724 current_line: Cell<u64>,
725 parse_node_data: RefCell<FxHashMap<ParseNodeId, ParseNodeData>>,
726 next_parse_node_id: Cell<ParseNodeId>,
727 document_node: ParseNode,
728 sender: Sender<FromParserThreadMsg>,
729 allow_declarative_shadow_roots: bool,
730}
731
732impl Sink {
733 fn new(sender: Sender<FromParserThreadMsg>, allow_declarative_shadow_roots: bool) -> Sink {
734 let sink = Sink {
735 current_line: Cell::new(1),
736 parse_node_data: RefCell::new(FxHashMap::default()),
737 next_parse_node_id: Cell::new(1),
738 document_node: ParseNode {
739 id: 0,
740 qual_name: None,
741 },
742 sender,
743 allow_declarative_shadow_roots,
744 };
745 let data = ParseNodeData::default();
746 sink.insert_parse_node_data(0, data);
747 sink
748 }
749
750 fn new_parse_node(&self) -> ParseNode {
751 let id = self.next_parse_node_id.get();
752 let data = ParseNodeData::default();
753 self.insert_parse_node_data(id, data);
754 self.next_parse_node_id.set(id + 1);
755 ParseNode {
756 id,
757 qual_name: None,
758 }
759 }
760
761 fn send_op(&self, op: ParseOperation) {
762 self.sender
763 .send(FromParserThreadMsg::ProcessOperation(op))
764 .unwrap();
765 }
766
767 fn insert_parse_node_data(&self, id: ParseNodeId, data: ParseNodeData) {
768 assert!(self.parse_node_data.borrow_mut().insert(id, data).is_none());
769 }
770
771 fn get_parse_node_data<'a>(&'a self, id: &'a ParseNodeId) -> Ref<'a, ParseNodeData> {
772 Ref::map(self.parse_node_data.borrow(), |data| {
773 data.get(id).expect("Parse Node data not found!")
774 })
775 }
776
777 fn get_parse_node_data_mut<'a>(&'a self, id: &'a ParseNodeId) -> RefMut<'a, ParseNodeData> {
778 RefMut::map(self.parse_node_data.borrow_mut(), |data| {
779 data.get_mut(id).expect("Parse Node data not found!")
780 })
781 }
782}
783
784impl TreeSink for Sink {
785 type Output = Self;
786 fn finish(self) -> Self {
787 self
788 }
789
790 type Handle = ParseNode;
791 type ElemName<'a>
792 = ExpandedName<'a>
793 where
794 Self: 'a;
795
796 fn get_document(&self) -> Self::Handle {
797 self.document_node.clone()
798 }
799
800 fn get_template_contents(&self, target: &Self::Handle) -> Self::Handle {
801 if let Some(ref contents) = self.get_parse_node_data(&target.id).contents {
802 return contents.clone();
803 }
804 let node = self.new_parse_node();
805 {
806 let mut data = self.get_parse_node_data_mut(&target.id);
807 data.contents = Some(node.clone());
808 }
809 self.send_op(ParseOperation::GetTemplateContents {
810 target: target.id,
811 contents: node.id,
812 });
813 node
814 }
815
816 fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
817 x.id == y.id
818 }
819
820 fn elem_name<'a>(&self, target: &'a Self::Handle) -> ExpandedName<'a> {
821 target
822 .qual_name
823 .as_ref()
824 .expect("Expected qual name of node!")
825 .expanded()
826 }
827
828 fn create_element(
829 &self,
830 name: QualName,
831 html_attrs: Vec<HtmlAttribute>,
832 flags: ElementFlags,
833 ) -> Self::Handle {
834 let mut node = self.new_parse_node();
835 node.qual_name = Some(name.clone());
836 {
837 let mut node_data = self.get_parse_node_data_mut(&node.id);
838 node_data.is_integration_point = html_attrs.iter().any(|attr| {
839 let attr_value = &String::from(attr.value.clone());
840 (attr.name.local == local_name!("encoding") && attr.name.ns == ns!()) &&
841 (attr_value.eq_ignore_ascii_case("text/html") ||
842 attr_value.eq_ignore_ascii_case("application/xhtml+xml"))
843 });
844 }
845 let attrs = html_attrs
846 .into_iter()
847 .map(|attr| Attribute {
848 name: attr.name,
849 value: String::from(attr.value),
850 })
851 .collect();
852
853 self.send_op(ParseOperation::CreateElement {
854 node: node.id,
855 name,
856 attrs,
857 current_line: self.current_line.get(),
858 had_duplicate_attributes: flags.had_duplicate_attributes,
859 });
860 node
861 }
862
863 fn create_comment(&self, text: StrTendril) -> Self::Handle {
864 let node = self.new_parse_node();
865 self.send_op(ParseOperation::CreateComment {
866 text: String::from(text),
867 node: node.id,
868 });
869 node
870 }
871
872 fn create_pi(&self, target: StrTendril, data: StrTendril) -> ParseNode {
873 let node = self.new_parse_node();
874 self.send_op(ParseOperation::CreatePI {
875 node: node.id,
876 target: String::from(target),
877 data: String::from(data),
878 });
879 node
880 }
881
882 fn associate_with_form(
883 &self,
884 target: &Self::Handle,
885 form: &Self::Handle,
886 nodes: (&Self::Handle, Option<&Self::Handle>),
887 ) {
888 let (element, prev_element) = nodes;
889 self.send_op(ParseOperation::AssociateWithForm {
890 target: target.id,
891 form: form.id,
892 element: element.id,
893 prev_element: prev_element.map(|p| p.id),
894 });
895 }
896
897 fn append_before_sibling(
898 &self,
899 sibling: &Self::Handle,
900 new_node: HtmlNodeOrText<Self::Handle>,
901 ) {
902 let new_node = match new_node {
903 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
904 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
905 };
906 self.send_op(ParseOperation::AppendBeforeSibling {
907 sibling: sibling.id,
908 node: new_node,
909 });
910 }
911
912 fn append_based_on_parent_node(
913 &self,
914 elem: &Self::Handle,
915 prev_elem: &Self::Handle,
916 child: HtmlNodeOrText<Self::Handle>,
917 ) {
918 let child = match child {
919 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
920 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
921 };
922 self.send_op(ParseOperation::AppendBasedOnParentNode {
923 element: elem.id,
924 prev_element: prev_elem.id,
925 node: child,
926 });
927 }
928
929 fn parse_error(&self, msg: Cow<'static, str>) {
930 debug!("Parse error: {}", msg);
931 }
932
933 fn set_quirks_mode(&self, mode: QuirksMode) {
934 let mode = match mode {
935 QuirksMode::Quirks => ServoQuirksMode::Quirks,
936 QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks,
937 QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks,
938 };
939 self.send_op(ParseOperation::SetQuirksMode { mode });
940 }
941
942 fn append(&self, parent: &Self::Handle, child: HtmlNodeOrText<Self::Handle>) {
943 let child = match child {
944 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
945 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
946 };
947 self.send_op(ParseOperation::Append {
948 parent: parent.id,
949 node: child,
950 });
951 }
952
953 fn append_doctype_to_document(
954 &self,
955 name: StrTendril,
956 public_id: StrTendril,
957 system_id: StrTendril,
958 ) {
959 self.send_op(ParseOperation::AppendDoctypeToDocument {
960 name: String::from(name),
961 public_id: String::from(public_id),
962 system_id: String::from(system_id),
963 });
964 }
965
966 fn add_attrs_if_missing(&self, target: &Self::Handle, html_attrs: Vec<HtmlAttribute>) {
967 let attrs = html_attrs
968 .into_iter()
969 .map(|attr| Attribute {
970 name: attr.name,
971 value: String::from(attr.value),
972 })
973 .collect();
974 self.send_op(ParseOperation::AddAttrsIfMissing {
975 target: target.id,
976 attrs,
977 });
978 }
979
980 fn remove_from_parent(&self, target: &Self::Handle) {
981 self.send_op(ParseOperation::RemoveFromParent { target: target.id });
982 }
983
984 fn mark_script_already_started(&self, node: &Self::Handle) {
985 self.send_op(ParseOperation::MarkScriptAlreadyStarted { node: node.id });
986 }
987
988 fn reparent_children(&self, parent: &Self::Handle, new_parent: &Self::Handle) {
989 self.send_op(ParseOperation::ReparentChildren {
990 parent: parent.id,
991 new_parent: new_parent.id,
992 });
993 }
994
995 fn is_mathml_annotation_xml_integration_point(&self, handle: &Self::Handle) -> bool {
998 let node_data = self.get_parse_node_data(&handle.id);
999 node_data.is_integration_point
1000 }
1001
1002 fn set_current_line(&self, line_number: u64) {
1003 self.current_line.set(line_number);
1004 }
1005
1006 fn pop(&self, node: &Self::Handle) {
1007 self.send_op(ParseOperation::Pop { node: node.id });
1008 }
1009
1010 fn allow_declarative_shadow_roots(&self, _intended_parent: &Self::Handle) -> bool {
1011 self.allow_declarative_shadow_roots
1012 }
1013
1014 fn attach_declarative_shadow(
1015 &self,
1016 location: &Self::Handle,
1017 template: &Self::Handle,
1018 attributes: &[HtmlAttribute],
1019 ) -> bool {
1020 let attributes = attributes
1021 .iter()
1022 .map(|attribute| Attribute {
1023 name: attribute.name.clone(),
1024 value: String::from(attribute.value.clone()),
1025 })
1026 .collect();
1027
1028 let (sender, receiver) = unbounded();
1032 self.send_op(ParseOperation::AttachDeclarativeShadowRoot {
1033 location: location.id,
1034 template: template.id,
1035 attributes,
1036 sender,
1037 });
1038
1039 receiver.recv().unwrap()
1040 }
1041}