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