1#![cfg_attr(crown, expect(crown::unrooted_must_root))]
6#![cfg_attr(crown, allow(crown::jscontext_first_arg))]
7
8use std::borrow::Cow;
9use std::cell::{Cell, Ref, RefCell, RefMut};
10use std::collections::vec_deque::VecDeque;
11use std::rc::Rc;
12use std::thread;
13
14use crossbeam_channel::{Receiver, Sender, unbounded};
15use html5ever::buffer_queue::BufferQueue;
16use html5ever::tendril::fmt::UTF8;
17use html5ever::tendril::{SendTendril, StrTendril, Tendril};
18use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts};
19use html5ever::tree_builder::{
20 ElementFlags, NodeOrText as HtmlNodeOrText, QuirksMode, TreeBuilder, TreeBuilderOpts, TreeSink,
21};
22use html5ever::{Attribute as HtmlAttribute, ExpandedName, QualName, local_name, ns};
23use markup5ever::TokenizerResult;
24use rustc_hash::FxHashMap;
25use servo_url::ServoUrl;
26use style::context::QuirksMode as ServoQuirksMode;
27
28use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
29use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
30use crate::dom::bindings::inheritance::Castable;
31use crate::dom::bindings::root::{Dom, DomRoot};
32use crate::dom::bindings::str::DOMString;
33use crate::dom::comment::Comment;
34use crate::dom::customelementregistry::CustomElementReactionStack;
35use crate::dom::document::Document;
36use crate::dom::documenttype::DocumentType;
37use crate::dom::element::{Element, ElementCreator};
38use crate::dom::html::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
39use crate::dom::html::htmlscriptelement::HTMLScriptElement;
40use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
41use crate::dom::node::Node;
42use crate::dom::node::virtualmethods::vtable_for;
43use crate::dom::processinginstruction::ProcessingInstruction;
44use crate::dom::servoparser::{
45 ElementAttribute, ParsingAlgorithm, attach_declarative_shadow_inner, create_element_for_token,
46};
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 cx,
495 name,
496 attrs,
497 &self.document,
498 ElementCreator::ParserCreated(current_line),
499 ParsingAlgorithm::Normal,
500 &self.custom_element_reaction_stack,
501 had_duplicate_attributes,
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(cx, attr.name, DOMString::from(attr.value));
551 }
552 },
553 ParseOperation::RemoveFromParent { target } => {
554 if let Some(ref parent) = self.get_node(&target).GetParentNode() {
555 parent.RemoveChild(cx, &self.get_node(&target)).unwrap();
556 }
557 },
558 ParseOperation::MarkScriptAlreadyStarted { node } => {
559 let node = self.get_node(&node);
560 let script = node.downcast::<HTMLScriptElement>();
561 if let Some(script) = script {
562 script.set_already_started(true)
563 }
564 },
565 ParseOperation::ReparentChildren { parent, new_parent } => {
566 let parent = self.get_node(&parent);
567 let new_parent = self.get_node(&new_parent);
568 while let Some(child) = parent.GetFirstChild() {
569 new_parent.AppendChild(cx, &child).unwrap();
570 }
571 },
572 ParseOperation::AssociateWithForm {
573 target,
574 form,
575 element,
576 prev_element,
577 } => {
578 let tree_node = prev_element.map_or(element, |prev| {
579 if self.has_parent_node(element) {
580 element
581 } else {
582 prev
583 }
584 });
585
586 if !self.same_tree(tree_node, form) {
587 return;
588 }
589 let form = self.get_node(&form);
590 let form = DomRoot::downcast::<HTMLFormElement>(DomRoot::from_ref(&**form))
591 .expect("Owner must be a form element");
592
593 let node = self.get_node(&target);
594 let elem = node.downcast::<Element>();
595 let control = elem.and_then(|e| e.as_maybe_form_control());
596
597 if let Some(control) = control {
598 control.set_form_owner_from_parser(cx, &form);
599 }
600 },
601 ParseOperation::Pop { node } => {
602 vtable_for(&self.get_node(&node)).pop(cx);
603 },
604 ParseOperation::CreatePI { node, target, data } => {
605 let pi = ProcessingInstruction::new(
606 cx,
607 DOMString::from(target),
608 DOMString::from(data),
609 document,
610 );
611 self.insert_node(node, Dom::from_ref(pi.upcast()));
612 },
613 ParseOperation::SetQuirksMode { mode } => {
614 document.set_quirks_mode(mode);
615 },
616 ParseOperation::AttachDeclarativeShadowRoot {
617 location,
618 template,
619 attributes,
620 sender,
621 } => {
622 let location = self.get_node(&location);
623 let template = self.get_node(&template);
624 let attributes: Vec<_> = attributes
625 .into_iter()
626 .map(|attribute| HtmlAttribute {
627 name: attribute.name,
628 value: StrTendril::from(attribute.value),
629 })
630 .collect();
631
632 let did_succeed =
633 attach_declarative_shadow_inner(cx, &location, &template, &attributes);
634 sender.send(did_succeed).unwrap();
635 },
636 }
637 }
638}
639
640fn run(
647 sink: Sink,
648 fragment_context: Option<(ParseNode, bool)>,
649 form_parse_node: Option<ParseNode>,
650 sender: Sender<FromParserThreadMsg>,
651 receiver: Receiver<ToParserThreadMsg>,
652 scripting_enabled: bool,
653) {
654 let options = TreeBuilderOpts {
655 scripting_enabled,
656 ..Default::default()
657 };
658
659 let html_tokenizer = if let Some((context_node, context_scripting_enabled)) = fragment_context {
660 let tree_builder =
661 TreeBuilder::new_for_fragment(sink, context_node, form_parse_node, options);
662
663 let tok_options = TokenizerOpts {
664 initial_state: Some(
665 tree_builder.tokenizer_state_for_context_elem(context_scripting_enabled),
666 ),
667 ..Default::default()
668 };
669
670 HtmlTokenizer::new(tree_builder, tok_options)
671 } else {
672 HtmlTokenizer::new(TreeBuilder::new(sink, options), Default::default())
673 };
674
675 loop {
676 match receiver
677 .recv()
678 .expect("Unexpected channel panic in html parser thread")
679 {
680 ToParserThreadMsg::Feed { input } => {
681 let input = create_buffer_queue(input);
682 let res = html_tokenizer.feed(&input);
683
684 let mut updated_input = VecDeque::new();
687 while let Some(st) = input.pop_front() {
688 updated_input.push_back(SendTendril::from(st));
689 }
690
691 let res = match res {
692 TokenizerResult::Done => {
693 FromParserThreadMsg::TokenizerResultDone { updated_input }
694 },
695 TokenizerResult::Script(script) => FromParserThreadMsg::TokenizerResultScript {
696 script,
697 updated_input,
698 },
699 TokenizerResult::EncodingIndicator(encoding) => {
700 FromParserThreadMsg::EncodingIndicator {
701 encoding: SendTendril::from(encoding),
702 updated_input,
703 }
704 },
705 };
706 sender.send(res).unwrap();
707 },
708 ToParserThreadMsg::End => {
709 html_tokenizer.end();
710 sender.send(FromParserThreadMsg::End).unwrap();
711 break;
712 },
713 ToParserThreadMsg::SetPlainTextState => html_tokenizer.set_plaintext_state(),
714 };
715 }
716}
717
718#[derive(Default, JSTraceable, MallocSizeOf)]
719struct ParseNodeData {
720 contents: Option<ParseNode>,
721 is_integration_point: bool,
722}
723
724pub(crate) struct Sink {
725 current_line: Cell<u64>,
726 parse_node_data: RefCell<FxHashMap<ParseNodeId, ParseNodeData>>,
727 next_parse_node_id: Cell<ParseNodeId>,
728 document_node: ParseNode,
729 sender: Sender<FromParserThreadMsg>,
730 allow_declarative_shadow_roots: bool,
731}
732
733impl Sink {
734 fn new(sender: Sender<FromParserThreadMsg>, allow_declarative_shadow_roots: bool) -> Sink {
735 let sink = Sink {
736 current_line: Cell::new(1),
737 parse_node_data: RefCell::new(FxHashMap::default()),
738 next_parse_node_id: Cell::new(1),
739 document_node: ParseNode {
740 id: 0,
741 qual_name: None,
742 },
743 sender,
744 allow_declarative_shadow_roots,
745 };
746 let data = ParseNodeData::default();
747 sink.insert_parse_node_data(0, data);
748 sink
749 }
750
751 fn new_parse_node(&self) -> ParseNode {
752 let id = self.next_parse_node_id.get();
753 let data = ParseNodeData::default();
754 self.insert_parse_node_data(id, data);
755 self.next_parse_node_id.set(id + 1);
756 ParseNode {
757 id,
758 qual_name: None,
759 }
760 }
761
762 fn send_op(&self, op: ParseOperation) {
763 self.sender
764 .send(FromParserThreadMsg::ProcessOperation(op))
765 .unwrap();
766 }
767
768 fn insert_parse_node_data(&self, id: ParseNodeId, data: ParseNodeData) {
769 assert!(self.parse_node_data.borrow_mut().insert(id, data).is_none());
770 }
771
772 fn get_parse_node_data<'a>(&'a self, id: &'a ParseNodeId) -> Ref<'a, ParseNodeData> {
773 Ref::map(self.parse_node_data.borrow(), |data| {
774 data.get(id).expect("Parse Node data not found!")
775 })
776 }
777
778 fn get_parse_node_data_mut<'a>(&'a self, id: &'a ParseNodeId) -> RefMut<'a, ParseNodeData> {
779 RefMut::map(self.parse_node_data.borrow_mut(), |data| {
780 data.get_mut(id).expect("Parse Node data not found!")
781 })
782 }
783}
784
785impl TreeSink for Sink {
786 type Output = Self;
787 fn finish(self) -> Self {
788 self
789 }
790
791 type Handle = ParseNode;
792 type ElemName<'a>
793 = ExpandedName<'a>
794 where
795 Self: 'a;
796
797 fn get_document(&self) -> Self::Handle {
798 self.document_node.clone()
799 }
800
801 fn get_template_contents(&self, target: &Self::Handle) -> Self::Handle {
802 if let Some(ref contents) = self.get_parse_node_data(&target.id).contents {
803 return contents.clone();
804 }
805 let node = self.new_parse_node();
806 {
807 let mut data = self.get_parse_node_data_mut(&target.id);
808 data.contents = Some(node.clone());
809 }
810 self.send_op(ParseOperation::GetTemplateContents {
811 target: target.id,
812 contents: node.id,
813 });
814 node
815 }
816
817 fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
818 x.id == y.id
819 }
820
821 fn elem_name<'a>(&self, target: &'a Self::Handle) -> ExpandedName<'a> {
822 target
823 .qual_name
824 .as_ref()
825 .expect("Expected qual name of node!")
826 .expanded()
827 }
828
829 fn create_element(
830 &self,
831 name: QualName,
832 html_attrs: Vec<HtmlAttribute>,
833 flags: ElementFlags,
834 ) -> Self::Handle {
835 let mut node = self.new_parse_node();
836 node.qual_name = Some(name.clone());
837 {
838 let mut node_data = self.get_parse_node_data_mut(&node.id);
839 node_data.is_integration_point = html_attrs.iter().any(|attr| {
840 let attr_value = &String::from(attr.value.clone());
841 (attr.name.local == local_name!("encoding") && attr.name.ns == ns!()) &&
842 (attr_value.eq_ignore_ascii_case("text/html") ||
843 attr_value.eq_ignore_ascii_case("application/xhtml+xml"))
844 });
845 }
846 let attrs = html_attrs
847 .into_iter()
848 .map(|attr| Attribute {
849 name: attr.name,
850 value: String::from(attr.value),
851 })
852 .collect();
853
854 self.send_op(ParseOperation::CreateElement {
855 node: node.id,
856 name,
857 attrs,
858 current_line: self.current_line.get(),
859 had_duplicate_attributes: flags.had_duplicate_attributes,
860 });
861 node
862 }
863
864 fn create_comment(&self, text: StrTendril) -> Self::Handle {
865 let node = self.new_parse_node();
866 self.send_op(ParseOperation::CreateComment {
867 text: String::from(text),
868 node: node.id,
869 });
870 node
871 }
872
873 fn create_pi(&self, target: StrTendril, data: StrTendril) -> ParseNode {
874 let node = self.new_parse_node();
875 self.send_op(ParseOperation::CreatePI {
876 node: node.id,
877 target: String::from(target),
878 data: String::from(data),
879 });
880 node
881 }
882
883 fn associate_with_form(
884 &self,
885 target: &Self::Handle,
886 form: &Self::Handle,
887 nodes: (&Self::Handle, Option<&Self::Handle>),
888 ) {
889 let (element, prev_element) = nodes;
890 self.send_op(ParseOperation::AssociateWithForm {
891 target: target.id,
892 form: form.id,
893 element: element.id,
894 prev_element: prev_element.map(|p| p.id),
895 });
896 }
897
898 fn append_before_sibling(
899 &self,
900 sibling: &Self::Handle,
901 new_node: HtmlNodeOrText<Self::Handle>,
902 ) {
903 let new_node = match new_node {
904 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
905 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
906 };
907 self.send_op(ParseOperation::AppendBeforeSibling {
908 sibling: sibling.id,
909 node: new_node,
910 });
911 }
912
913 fn append_based_on_parent_node(
914 &self,
915 elem: &Self::Handle,
916 prev_elem: &Self::Handle,
917 child: HtmlNodeOrText<Self::Handle>,
918 ) {
919 let child = match child {
920 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
921 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
922 };
923 self.send_op(ParseOperation::AppendBasedOnParentNode {
924 element: elem.id,
925 prev_element: prev_elem.id,
926 node: child,
927 });
928 }
929
930 fn parse_error(&self, msg: Cow<'static, str>) {
931 debug!("Parse error: {}", msg);
932 }
933
934 fn set_quirks_mode(&self, mode: QuirksMode) {
935 let mode = match mode {
936 QuirksMode::Quirks => ServoQuirksMode::Quirks,
937 QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks,
938 QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks,
939 };
940 self.send_op(ParseOperation::SetQuirksMode { mode });
941 }
942
943 fn append(&self, parent: &Self::Handle, child: HtmlNodeOrText<Self::Handle>) {
944 let child = match child {
945 HtmlNodeOrText::AppendNode(node) => NodeOrText::Node(node),
946 HtmlNodeOrText::AppendText(text) => NodeOrText::Text(String::from(text)),
947 };
948 self.send_op(ParseOperation::Append {
949 parent: parent.id,
950 node: child,
951 });
952 }
953
954 fn append_doctype_to_document(
955 &self,
956 name: StrTendril,
957 public_id: StrTendril,
958 system_id: StrTendril,
959 ) {
960 self.send_op(ParseOperation::AppendDoctypeToDocument {
961 name: String::from(name),
962 public_id: String::from(public_id),
963 system_id: String::from(system_id),
964 });
965 }
966
967 fn add_attrs_if_missing(&self, target: &Self::Handle, html_attrs: Vec<HtmlAttribute>) {
968 let attrs = html_attrs
969 .into_iter()
970 .map(|attr| Attribute {
971 name: attr.name,
972 value: String::from(attr.value),
973 })
974 .collect();
975 self.send_op(ParseOperation::AddAttrsIfMissing {
976 target: target.id,
977 attrs,
978 });
979 }
980
981 fn remove_from_parent(&self, target: &Self::Handle) {
982 self.send_op(ParseOperation::RemoveFromParent { target: target.id });
983 }
984
985 fn mark_script_already_started(&self, node: &Self::Handle) {
986 self.send_op(ParseOperation::MarkScriptAlreadyStarted { node: node.id });
987 }
988
989 fn reparent_children(&self, parent: &Self::Handle, new_parent: &Self::Handle) {
990 self.send_op(ParseOperation::ReparentChildren {
991 parent: parent.id,
992 new_parent: new_parent.id,
993 });
994 }
995
996 fn is_mathml_annotation_xml_integration_point(&self, handle: &Self::Handle) -> bool {
999 let node_data = self.get_parse_node_data(&handle.id);
1000 node_data.is_integration_point
1001 }
1002
1003 fn set_current_line(&self, line_number: u64) {
1004 self.current_line.set(line_number);
1005 }
1006
1007 fn pop(&self, node: &Self::Handle) {
1008 self.send_op(ParseOperation::Pop { node: node.id });
1009 }
1010
1011 fn allow_declarative_shadow_roots(&self, _intended_parent: &Self::Handle) -> bool {
1012 self.allow_declarative_shadow_roots
1013 }
1014
1015 fn attach_declarative_shadow(
1016 &self,
1017 location: &Self::Handle,
1018 template: &Self::Handle,
1019 attributes: &[HtmlAttribute],
1020 ) -> bool {
1021 let attributes = attributes
1022 .iter()
1023 .map(|attribute| Attribute {
1024 name: attribute.name.clone(),
1025 value: String::from(attribute.value.clone()),
1026 })
1027 .collect();
1028
1029 let (sender, receiver) = unbounded();
1033 self.send_op(ParseOperation::AttachDeclarativeShadowRoot {
1034 location: location.id,
1035 template: template.id,
1036 attributes,
1037 sender,
1038 });
1039
1040 receiver.recv().unwrap()
1041 }
1042}