1use std::borrow::Cow;
6use std::cell::{Cell, RefCell};
7use std::mem;
8use std::rc::Rc;
9
10use base::cross_process_instant::CrossProcessInstant;
11use base::id::{PipelineId, WebViewId};
12use base64::Engine as _;
13use base64::engine::general_purpose;
14use content_security_policy::sandboxing_directive::SandboxingFlagSet;
15use devtools_traits::ScriptToDevtoolsControlMsg;
16use dom_struct::dom_struct;
17use embedder_traits::resources::{self, Resource};
18use encoding_rs::{Encoding, UTF_8};
19use html5ever::buffer_queue::BufferQueue;
20use html5ever::tendril::StrTendril;
21use html5ever::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
22use html5ever::{Attribute, ExpandedName, LocalName, QualName, local_name, ns};
23use hyper_serde::Serde;
24use markup5ever::TokenizerResult;
25use mime::{self, Mime};
26use net_traits::mime_classifier::{ApacheBugFlag, MediaType, MimeClassifier, NoSniffFlag};
27use net_traits::policy_container::PolicyContainer;
28use net_traits::request::RequestId;
29use net_traits::{
30 FetchMetadata, LoadContext, Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming,
31};
32use profile_traits::time::{
33 ProfilerCategory, ProfilerChan, TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType,
34};
35use profile_traits::time_profile;
36use script_traits::DocumentActivity;
37use servo_config::pref;
38use servo_url::ServoUrl;
39use style::context::QuirksMode as ServoQuirksMode;
40use tendril::stream::LossyDecoder;
41use tendril::{ByteTendril, TendrilSink};
42
43use crate::document_loader::{DocumentLoader, LoadType};
44use crate::dom::bindings::cell::DomRefCell;
45use crate::dom::bindings::codegen::Bindings::DocumentBinding::{
46 DocumentMethods, DocumentReadyState,
47};
48use crate::dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
49use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementMethods;
50use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
51use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
52use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
53 ShadowRootMode, SlotAssignmentMode,
54};
55use crate::dom::bindings::inheritance::Castable;
56use crate::dom::bindings::refcounted::Trusted;
57use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
58use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
59use crate::dom::bindings::settings_stack::is_execution_stack_empty;
60use crate::dom::bindings::str::{DOMString, USVString};
61use crate::dom::characterdata::CharacterData;
62use crate::dom::comment::Comment;
63use crate::dom::csp::{GlobalCspReporting, Violation, parse_csp_list_from_metadata};
64use crate::dom::customelementregistry::CustomElementReactionStack;
65use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
66use crate::dom::documentfragment::DocumentFragment;
67use crate::dom::documenttype::DocumentType;
68use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator};
69use crate::dom::globalscope::GlobalScope;
70use crate::dom::html::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
71use crate::dom::html::htmlimageelement::HTMLImageElement;
72use crate::dom::html::htmlscriptelement::{HTMLScriptElement, ScriptResult};
73use crate::dom::html::htmltemplateelement::HTMLTemplateElement;
74use crate::dom::node::{Node, ShadowIncluding};
75use crate::dom::performance::performanceentry::PerformanceEntry;
76use crate::dom::performance::performancenavigationtiming::PerformanceNavigationTiming;
77use crate::dom::processinginstruction::ProcessingInstruction;
78use crate::dom::processingoptions::{
79 LinkHeader, LinkProcessingPhase, extract_links_from_headers, process_link_headers,
80};
81use crate::dom::reportingendpoint::ReportingEndpoint;
82use crate::dom::shadowroot::IsUserAgentWidget;
83use crate::dom::text::Text;
84use crate::dom::types::{HTMLElement, HTMLMediaElement, HTMLOptionElement};
85use crate::dom::virtualmethods::vtable_for;
86use crate::network_listener::FetchResponseListener;
87use crate::realms::enter_realm;
88use crate::script_runtime::{CanGc, IntroductionType};
89use crate::script_thread::ScriptThread;
90
91mod async_html;
92pub(crate) mod encoding;
93pub(crate) mod html;
94mod prefetch;
95mod xml;
96
97use encoding::{NetworkDecoderState, NetworkSink};
98pub(crate) use html::serialize_html_fragment;
99
100#[dom_struct]
101pub(crate) struct ServoParser {
114 reflector: Reflector,
115 document: Dom<Document>,
117 network_decoder: DomRefCell<NetworkDecoderState>,
119 #[ignore_malloc_size_of = "Defined in html5ever"]
121 #[no_trace]
122 network_input: BufferQueue,
123 #[ignore_malloc_size_of = "Defined in html5ever"]
125 #[no_trace]
126 script_input: BufferQueue,
127 tokenizer: Tokenizer,
129 last_chunk_received: Cell<bool>,
131 suspended: Cell<bool>,
133 script_nesting_level: Cell<usize>,
135 aborted: Cell<bool>,
137 script_created_parser: bool,
139 #[no_trace]
144 prefetch_decoder: RefCell<LossyDecoder<NetworkSink>>,
145 prefetch_tokenizer: prefetch::Tokenizer,
149 #[ignore_malloc_size_of = "Defined in html5ever"]
150 #[no_trace]
151 prefetch_input: BufferQueue,
152 content_for_devtools: Option<DomRefCell<String>>,
155}
156
157pub(crate) struct ElementAttribute {
158 name: QualName,
159 value: DOMString,
160}
161
162#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)]
163pub(crate) enum ParsingAlgorithm {
164 Normal,
165 Fragment,
166}
167
168impl ElementAttribute {
169 pub(crate) fn new(name: QualName, value: DOMString) -> ElementAttribute {
170 ElementAttribute { name, value }
171 }
172}
173
174impl ServoParser {
175 pub(crate) fn parser_is_not_active(&self) -> bool {
176 self.can_write()
177 }
178
179 pub(crate) fn parse_html_document(
181 document: &Document,
182 input: Option<DOMString>,
183 url: ServoUrl,
184 encoding_hint_from_content_type: Option<&'static Encoding>,
185 encoding_of_container_document: Option<&'static Encoding>,
186 can_gc: CanGc,
187 ) {
188 assert!(document.is_html_document());
192
193 let parser = if pref!(dom_servoparser_async_html_tokenizer_enabled) {
195 ServoParser::new(
196 document,
197 Tokenizer::AsyncHtml(self::async_html::Tokenizer::new(document, url, None)),
198 ParserKind::Normal,
199 encoding_hint_from_content_type,
200 encoding_of_container_document,
201 can_gc,
202 )
203 } else {
204 ServoParser::new(
205 document,
206 Tokenizer::Html(self::html::Tokenizer::new(
207 document,
208 url,
209 None,
210 ParsingAlgorithm::Normal,
211 )),
212 ParserKind::Normal,
213 encoding_hint_from_content_type,
214 encoding_of_container_document,
215 can_gc,
216 )
217 };
218 if let Some(input) = input {
224 parser.parse_complete_string_chunk(String::from(input), can_gc);
225 } else {
226 parser.document.set_current_parser(Some(&parser));
227 }
228 }
229
230 pub(crate) fn parse_html_fragment(
232 context: &Element,
233 input: DOMString,
234 allow_declarative_shadow_roots: bool,
235 can_gc: CanGc,
236 ) -> impl Iterator<Item = DomRoot<Node>> + use<'_> {
237 let context_node = context.upcast::<Node>();
238 let context_document = context_node.owner_doc();
239 let window = context_document.window();
240 let url = context_document.url();
241
242 let loader = DocumentLoader::new_with_threads(
244 context_document.loader().resource_threads().clone(),
245 Some(url.clone()),
246 );
247 let document = Document::new(
248 window,
249 HasBrowsingContext::No,
250 Some(url.clone()),
251 context_document.about_base_url(),
252 context_document.origin().clone(),
253 IsHTMLDocument::HTMLDocument,
254 None,
255 None,
256 DocumentActivity::Inactive,
257 DocumentSource::FromParser,
258 loader,
259 None,
260 None,
261 Default::default(),
262 false,
263 allow_declarative_shadow_roots,
264 Some(context_document.insecure_requests_policy()),
265 context_document.has_trustworthy_ancestor_or_current_origin(),
266 context_document.custom_element_reaction_stack(),
267 context_document.creation_sandboxing_flag_set(),
268 can_gc,
269 );
270
271 document.set_quirks_mode(context_document.quirks_mode());
275
276 let form = context_node
283 .inclusive_ancestors(ShadowIncluding::No)
284 .find(|element| element.is::<HTMLFormElement>());
285
286 let fragment_context = FragmentContext {
287 context_elem: context_node,
288 form_elem: form.as_deref(),
289 context_element_allows_scripting: context_document.scripting_enabled(),
290 };
291
292 let parser = ServoParser::new(
293 &document,
294 Tokenizer::Html(self::html::Tokenizer::new(
295 &document,
296 url,
297 Some(fragment_context),
298 ParsingAlgorithm::Fragment,
299 )),
300 ParserKind::Normal,
301 None,
302 None,
303 can_gc,
304 );
305 parser.parse_complete_string_chunk(String::from(input), can_gc);
306
307 let root_element = document.GetDocumentElement().expect("no document element");
309 FragmentParsingResult {
310 inner: root_element.upcast::<Node>().children(),
311 }
312 }
313
314 pub(crate) fn parse_html_script_input(document: &Document, url: ServoUrl) {
315 let parser = ServoParser::new(
316 document,
317 Tokenizer::Html(self::html::Tokenizer::new(
318 document,
319 url,
320 None,
321 ParsingAlgorithm::Normal,
322 )),
323 ParserKind::ScriptCreated,
324 None,
325 None,
326 CanGc::note(),
327 );
328 document.set_current_parser(Some(&parser));
329 }
330
331 pub(crate) fn parse_xml_document(
332 document: &Document,
333 input: Option<DOMString>,
334 url: ServoUrl,
335 encoding_hint_from_content_type: Option<&'static Encoding>,
336 can_gc: CanGc,
337 ) {
338 let parser = ServoParser::new(
339 document,
340 Tokenizer::Xml(self::xml::Tokenizer::new(document, url)),
341 ParserKind::Normal,
342 encoding_hint_from_content_type,
343 None,
344 can_gc,
345 );
346
347 if let Some(input) = input {
349 parser.parse_complete_string_chunk(String::from(input), can_gc);
350 } else {
351 parser.document.set_current_parser(Some(&parser));
352 }
353 }
354
355 pub(crate) fn script_nesting_level(&self) -> usize {
356 self.script_nesting_level.get()
357 }
358
359 pub(crate) fn is_script_created(&self) -> bool {
360 self.script_created_parser
361 }
362
363 pub(crate) fn resume_with_pending_parsing_blocking_script(
378 &self,
379 script: &HTMLScriptElement,
380 result: ScriptResult,
381 can_gc: CanGc,
382 ) {
383 assert!(self.suspended.get());
384 self.suspended.set(false);
385
386 self.script_input.swap_with(&self.network_input);
387 while let Some(chunk) = self.script_input.pop_front() {
388 self.network_input.push_back(chunk);
389 }
390
391 let script_nesting_level = self.script_nesting_level.get();
392 assert_eq!(script_nesting_level, 0);
393
394 self.script_nesting_level.set(script_nesting_level + 1);
395 script.execute(result, can_gc);
396 self.script_nesting_level.set(script_nesting_level);
397
398 if !self.suspended.get() && !self.aborted.get() {
399 self.parse_sync(can_gc);
400 }
401 }
402
403 pub(crate) fn can_write(&self) -> bool {
404 self.script_created_parser || self.script_nesting_level.get() > 0
405 }
406
407 pub(crate) fn write(&self, text: DOMString, can_gc: CanGc) {
409 assert!(self.can_write());
410
411 if self.document.has_pending_parsing_blocking_script() {
412 self.script_input.push_back(String::from(text).into());
416 return;
417 }
418
419 assert!(self.script_input.is_empty());
423
424 let input = BufferQueue::default();
425 input.push_back(String::from(text).into());
426
427 let profiler_chan = self
428 .document
429 .window()
430 .as_global_scope()
431 .time_profiler_chan()
432 .clone();
433 let profiler_metadata = TimerMetadata {
434 url: self.document.url().as_str().into(),
435 iframe: TimerMetadataFrameType::RootWindow,
436 incremental: TimerMetadataReflowType::FirstReflow,
437 };
438 self.tokenize(
439 |tokenizer| {
440 tokenizer.feed(
441 &input,
442 can_gc,
443 profiler_chan.clone(),
444 profiler_metadata.clone(),
445 )
446 },
447 can_gc,
448 );
449
450 if self.suspended.get() {
451 while let Some(chunk) = input.pop_front() {
455 self.script_input.push_back(chunk);
456 }
457 return;
458 }
459
460 assert!(input.is_empty());
461 }
462
463 pub(crate) fn close(&self, can_gc: CanGc) {
465 assert!(self.script_created_parser);
466
467 self.last_chunk_received.set(true);
469
470 if self.suspended.get() {
471 return;
473 }
474
475 self.parse_sync(can_gc);
477 }
478
479 pub(crate) fn abort(&self, can_gc: CanGc) {
481 assert!(!self.aborted.get());
482 self.aborted.set(true);
483
484 self.script_input.replace_with(BufferQueue::default());
486 self.network_input.replace_with(BufferQueue::default());
487
488 self.document
490 .set_ready_state(DocumentReadyState::Interactive, can_gc);
491
492 self.tokenizer.end(can_gc);
494 self.document.set_current_parser(None);
495
496 self.document
498 .set_ready_state(DocumentReadyState::Complete, can_gc);
499 }
500
501 pub(crate) fn is_active(&self) -> bool {
503 self.script_nesting_level() > 0 && !self.aborted.get()
504 }
505
506 pub(crate) fn get_current_line(&self) -> u32 {
507 self.tokenizer.get_current_line()
508 }
509
510 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
511 fn new_inherited(
512 document: &Document,
513 tokenizer: Tokenizer,
514 kind: ParserKind,
515 encoding_hint_from_content_type: Option<&'static Encoding>,
516 encoding_of_container_document: Option<&'static Encoding>,
517 ) -> Self {
518 let content_for_devtools = (document.global().devtools_chan().is_some() &&
522 document.has_browsing_context())
523 .then_some(DomRefCell::new(String::new()));
524
525 ServoParser {
526 reflector: Reflector::new(),
527 document: Dom::from_ref(document),
528 network_decoder: DomRefCell::new(NetworkDecoderState::new(
529 encoding_hint_from_content_type,
530 encoding_of_container_document,
531 )),
532 network_input: BufferQueue::default(),
533 script_input: BufferQueue::default(),
534 tokenizer,
535 last_chunk_received: Cell::new(false),
536 suspended: Default::default(),
537 script_nesting_level: Default::default(),
538 aborted: Default::default(),
539 script_created_parser: kind == ParserKind::ScriptCreated,
540 prefetch_decoder: RefCell::new(LossyDecoder::new_encoding_rs(
541 encoding_hint_from_content_type.unwrap_or(UTF_8),
542 Default::default(),
543 )),
544 prefetch_tokenizer: prefetch::Tokenizer::new(document),
545 prefetch_input: BufferQueue::default(),
546 content_for_devtools,
547 }
548 }
549
550 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
551 fn new(
552 document: &Document,
553 tokenizer: Tokenizer,
554 kind: ParserKind,
555 encoding_hint_from_content_type: Option<&'static Encoding>,
556 encoding_of_container_document: Option<&'static Encoding>,
557 can_gc: CanGc,
558 ) -> DomRoot<Self> {
559 reflect_dom_object(
560 Box::new(ServoParser::new_inherited(
561 document,
562 tokenizer,
563 kind,
564 encoding_hint_from_content_type,
565 encoding_of_container_document,
566 )),
567 document.window(),
568 can_gc,
569 )
570 }
571
572 fn push_tendril_input_chunk(&self, chunk: StrTendril) {
573 if let Some(mut content_for_devtools) = self
574 .content_for_devtools
575 .as_ref()
576 .map(|content| content.borrow_mut())
577 {
578 content_for_devtools.push_str(chunk.as_ref());
580 }
581
582 if chunk.is_empty() {
583 return;
584 }
585
586 self.network_input.push_back(chunk);
589 }
590
591 fn push_bytes_input_chunk(&self, chunk: Vec<u8>) {
592 if let Some(decoded_chunk) = self
594 .network_decoder
595 .borrow_mut()
596 .push(&chunk, &self.document)
597 {
598 self.push_tendril_input_chunk(decoded_chunk);
599 }
600
601 if self.should_prefetch() {
602 let mut prefetch_decoder = self.prefetch_decoder.borrow_mut();
608 prefetch_decoder.process(ByteTendril::from(&*chunk));
609
610 self.prefetch_input
611 .push_back(mem::take(&mut prefetch_decoder.inner_sink_mut().output));
612 self.prefetch_tokenizer.feed(&self.prefetch_input);
613 }
614 }
615
616 fn should_prefetch(&self) -> bool {
617 self.document.browsing_context().is_some()
625 }
626
627 fn push_string_input_chunk(&self, chunk: String) {
628 let chunk = StrTendril::from(chunk);
631 self.push_tendril_input_chunk(chunk);
632 }
633
634 fn parse_sync(&self, can_gc: CanGc) {
635 assert!(self.script_input.is_empty());
636
637 if self.last_chunk_received.get() {
641 let chunk = self.network_decoder.borrow_mut().finish(&self.document);
642 if !chunk.is_empty() {
643 self.push_tendril_input_chunk(chunk);
644 }
645 }
646
647 if self.aborted.get() {
648 return;
649 }
650
651 let profiler_chan = self
652 .document
653 .window()
654 .as_global_scope()
655 .time_profiler_chan()
656 .clone();
657 let profiler_metadata = TimerMetadata {
658 url: self.document.url().as_str().into(),
659 iframe: TimerMetadataFrameType::RootWindow,
660 incremental: TimerMetadataReflowType::FirstReflow,
661 };
662 self.tokenize(
663 |tokenizer| {
664 tokenizer.feed(
665 &self.network_input,
666 can_gc,
667 profiler_chan.clone(),
668 profiler_metadata.clone(),
669 )
670 },
671 can_gc,
672 );
673
674 if self.suspended.get() {
675 return;
676 }
677
678 assert!(self.network_input.is_empty());
679
680 if self.last_chunk_received.get() {
681 self.finish(can_gc);
682 }
683 }
684
685 fn parse_complete_string_chunk(&self, input: String, can_gc: CanGc) {
686 self.document.set_current_parser(Some(self));
687 self.push_string_input_chunk(input);
688 self.last_chunk_received.set(true);
689 if !self.suspended.get() {
690 self.parse_sync(can_gc);
691 }
692 }
693
694 fn parse_bytes_chunk(&self, input: Vec<u8>, can_gc: CanGc) {
695 let _realm = enter_realm(&*self.document);
696 self.document.set_current_parser(Some(self));
697 self.push_bytes_input_chunk(input);
698 if !self.suspended.get() {
699 self.parse_sync(can_gc);
700 }
701 }
702
703 fn tokenize<F>(&self, feed: F, can_gc: CanGc)
704 where
705 F: Fn(&Tokenizer) -> TokenizerResult<DomRoot<HTMLScriptElement>>,
706 {
707 loop {
708 assert!(!self.suspended.get());
709 assert!(!self.aborted.get());
710
711 self.document.window().reflow_if_reflow_timer_expired();
712 let script = match feed(&self.tokenizer) {
713 TokenizerResult::Done => return,
714 TokenizerResult::EncodingIndicator(_) => continue,
715 TokenizerResult::Script(script) => script,
716 };
717
718 if is_execution_stack_empty() {
725 self.document
726 .window()
727 .perform_a_microtask_checkpoint(can_gc);
728 }
729
730 let script_nesting_level = self.script_nesting_level.get();
731
732 self.script_nesting_level.set(script_nesting_level + 1);
733 script.set_initial_script_text();
734 let introduction_type_override =
735 (script_nesting_level > 0).then_some(IntroductionType::INJECTED_SCRIPT);
736 script.prepare(introduction_type_override, can_gc);
737 self.script_nesting_level.set(script_nesting_level);
738
739 if self.document.has_pending_parsing_blocking_script() {
740 self.suspended.set(true);
741 return;
742 }
743 if self.aborted.get() {
744 return;
745 }
746 }
747 }
748
749 fn finish(&self, can_gc: CanGc) {
751 assert!(!self.suspended.get());
752 assert!(self.last_chunk_received.get());
753 assert!(self.script_input.is_empty());
754 assert!(self.network_input.is_empty());
755 assert!(self.network_decoder.borrow().is_finished());
756
757 self.document
759 .set_ready_state(DocumentReadyState::Interactive, can_gc);
760
761 self.tokenizer.end(can_gc);
763 self.document.set_current_parser(None);
764
765 let url = self.tokenizer.url().clone();
767 self.document.finish_load(LoadType::PageSource(url), can_gc);
768
769 if let Some(content_for_devtools) = self
771 .content_for_devtools
772 .as_ref()
773 .map(|content| content.take())
774 {
775 let global = self.document.global();
776 let chan = global.devtools_chan().expect("Guaranteed by new");
777 let pipeline_id = self.document.global().pipeline_id();
778 let _ = chan.send(ScriptToDevtoolsControlMsg::UpdateSourceContent(
779 pipeline_id,
780 content_for_devtools,
781 ));
782 }
783 }
784}
785
786struct FragmentParsingResult<I>
787where
788 I: Iterator<Item = DomRoot<Node>>,
789{
790 inner: I,
791}
792
793impl<I> Iterator for FragmentParsingResult<I>
794where
795 I: Iterator<Item = DomRoot<Node>>,
796{
797 type Item = DomRoot<Node>;
798
799 fn next(&mut self) -> Option<DomRoot<Node>> {
800 let next = self.inner.next()?;
801 next.remove_self(CanGc::note());
802 Some(next)
803 }
804
805 fn size_hint(&self) -> (usize, Option<usize>) {
806 self.inner.size_hint()
807 }
808}
809
810#[derive(JSTraceable, MallocSizeOf, PartialEq)]
811enum ParserKind {
812 Normal,
813 ScriptCreated,
814}
815
816#[derive(JSTraceable, MallocSizeOf)]
817#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
818enum Tokenizer {
819 Html(self::html::Tokenizer),
820 AsyncHtml(self::async_html::Tokenizer),
821 Xml(self::xml::Tokenizer),
822}
823
824impl Tokenizer {
825 fn feed(
826 &self,
827 input: &BufferQueue,
828 can_gc: CanGc,
829 profiler_chan: ProfilerChan,
830 profiler_metadata: TimerMetadata,
831 ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
832 match *self {
833 Tokenizer::Html(ref tokenizer) => time_profile!(
834 ProfilerCategory::ScriptParseHTML,
835 Some(profiler_metadata),
836 profiler_chan,
837 || tokenizer.feed(input),
838 ),
839 Tokenizer::AsyncHtml(ref tokenizer) => time_profile!(
840 ProfilerCategory::ScriptParseHTML,
841 Some(profiler_metadata),
842 profiler_chan,
843 || tokenizer.feed(input, can_gc),
844 ),
845 Tokenizer::Xml(ref tokenizer) => time_profile!(
846 ProfilerCategory::ScriptParseXML,
847 Some(profiler_metadata),
848 profiler_chan,
849 || tokenizer.feed(input),
850 ),
851 }
852 }
853
854 fn end(&self, can_gc: CanGc) {
855 match *self {
856 Tokenizer::Html(ref tokenizer) => tokenizer.end(),
857 Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.end(can_gc),
858 Tokenizer::Xml(ref tokenizer) => tokenizer.end(),
859 }
860 }
861
862 fn url(&self) -> &ServoUrl {
863 match *self {
864 Tokenizer::Html(ref tokenizer) => tokenizer.url(),
865 Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.url(),
866 Tokenizer::Xml(ref tokenizer) => tokenizer.url(),
867 }
868 }
869
870 fn set_plaintext_state(&self) {
871 match *self {
872 Tokenizer::Html(ref tokenizer) => tokenizer.set_plaintext_state(),
873 Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.set_plaintext_state(),
874 Tokenizer::Xml(_) => unimplemented!(),
875 }
876 }
877
878 fn get_current_line(&self) -> u32 {
879 match *self {
880 Tokenizer::Html(ref tokenizer) => tokenizer.get_current_line(),
881 Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.get_current_line(),
882 Tokenizer::Xml(ref tokenizer) => tokenizer.get_current_line(),
883 }
884 }
885}
886
887struct NavigationParams {
891 policy_container: PolicyContainer,
893 content_type: Option<Mime>,
895 link_headers: Vec<LinkHeader>,
897 final_sandboxing_flag_set: SandboxingFlagSet,
899 resource_header: Vec<u8>,
901 about_base_url: Option<ServoUrl>,
903}
904
905pub(crate) struct ParserContext {
908 parser: Option<Trusted<ServoParser>>,
910 is_synthesized_document: bool,
912 has_loaded_document: bool,
914 webview_id: WebViewId,
916 pipeline_id: PipelineId,
918 url: ServoUrl,
920 pushed_entry_index: Option<usize>,
922 navigation_params: NavigationParams,
924}
925
926impl ParserContext {
927 pub(crate) fn new(
928 webview_id: WebViewId,
929 pipeline_id: PipelineId,
930 url: ServoUrl,
931 creation_sandboxing_flag_set: SandboxingFlagSet,
932 ) -> ParserContext {
933 ParserContext {
934 parser: None,
935 is_synthesized_document: false,
936 has_loaded_document: false,
937 webview_id,
938 pipeline_id,
939 url,
940 pushed_entry_index: None,
941 navigation_params: NavigationParams {
942 policy_container: Default::default(),
943 content_type: None,
944 link_headers: vec![],
945 final_sandboxing_flag_set: creation_sandboxing_flag_set,
946 resource_header: vec![],
947 about_base_url: Default::default(),
948 },
949 }
950 }
951
952 pub(crate) fn set_policy_container(&mut self, policy_container: Option<&PolicyContainer>) {
953 let Some(policy_container) = policy_container else {
954 return;
955 };
956 self.navigation_params.policy_container = policy_container.clone();
957 }
958
959 pub(crate) fn set_about_base_url(&mut self, about_base_url: Option<ServoUrl>) {
960 self.navigation_params.about_base_url = about_base_url;
961 }
962
963 pub(crate) fn get_document(&self) -> Option<DomRoot<Document>> {
964 self.parser
965 .as_ref()
966 .map(|parser| parser.root().document.as_rooted())
967 }
968
969 fn create_policy_container_from_fetch_response(metadata: &Metadata) -> PolicyContainer {
971 PolicyContainer {
976 csp_list: parse_csp_list_from_metadata(&metadata.headers),
978 referrer_policy: ReferrerPolicy::parse_header_for_response(&metadata.headers),
980 }
981 }
982
983 fn initialize_document_object(&self, document: &Document) {
985 document.set_policy_container(self.navigation_params.policy_container.clone());
987 document.set_active_sandboxing_flag_set(self.navigation_params.final_sandboxing_flag_set);
988 document.set_about_base_url(self.navigation_params.about_base_url.clone());
989 process_link_headers(
991 &self.navigation_params.link_headers,
992 document,
993 LinkProcessingPhase::PreMedia,
994 );
995 }
996
997 fn process_link_headers_in_media_phase_with_task(&mut self, document: &Document) {
999 let link_headers = std::mem::take(&mut self.navigation_params.link_headers);
1003 if !link_headers.is_empty() {
1004 let window = document.window();
1005 let document = Trusted::new(document);
1006 window
1007 .upcast::<GlobalScope>()
1008 .task_manager()
1009 .networking_task_source()
1010 .queue(task!(process_link_headers_task: move || {
1011 process_link_headers(&link_headers, &document.root(), LinkProcessingPhase::Media);
1012 }));
1013 }
1014 }
1015
1016 fn load_document(&mut self, can_gc: CanGc) {
1018 assert!(!self.has_loaded_document);
1019 self.has_loaded_document = true;
1020 let Some(ref parser) = self.parser.as_ref().map(|p| p.root()) else {
1021 return;
1022 };
1023 let content_type = &self.navigation_params.content_type;
1025 let mime_type = MimeClassifier::default().classify(
1026 LoadContext::Browsing,
1027 NoSniffFlag::Off,
1028 ApacheBugFlag::from_content_type(content_type.as_ref()),
1029 content_type,
1030 &self.navigation_params.resource_header,
1031 );
1032 let Some(media_type) = MimeClassifier::get_media_type(&mime_type) else {
1036 let page = format!(
1037 "<html><body><p>Unknown content type ({}).</p></body></html>",
1038 &mime_type,
1039 );
1040 self.load_inline_unknown_content(parser, page);
1041 return;
1042 };
1043 match media_type {
1044 MediaType::Html => self.load_html_document(parser),
1046 MediaType::Xml => self.load_xml_document(parser),
1048 MediaType::JavaScript | MediaType::Json | MediaType::Text | MediaType::Css => {
1050 self.load_text_document(parser)
1051 },
1052 MediaType::Image | MediaType::AudioVideo => {
1054 self.load_media_document(parser, media_type, &mime_type);
1055 return;
1056 },
1057 MediaType::Font => {
1058 let page = format!(
1059 "<html><body><p>Unable to load font with content type ({}).</p></body></html>",
1060 &mime_type,
1061 );
1062 self.load_inline_unknown_content(parser, page);
1063 return;
1064 },
1065 };
1066
1067 parser.parse_bytes_chunk(
1068 std::mem::take(&mut self.navigation_params.resource_header),
1069 can_gc,
1070 );
1071 }
1072
1073 fn load_html_document(&mut self, parser: &ServoParser) {
1075 self.initialize_document_object(&parser.document);
1078 self.process_link_headers_in_media_phase_with_task(&parser.document);
1082 }
1083
1084 fn load_xml_document(&mut self, parser: &ServoParser) {
1086 self.initialize_document_object(&parser.document);
1092 self.process_link_headers_in_media_phase_with_task(&parser.document);
1096 }
1097
1098 fn load_text_document(&mut self, parser: &ServoParser) {
1100 self.initialize_document_object(&parser.document);
1103 let page = "<pre>\n".into();
1110 parser.push_string_input_chunk(page);
1111 parser.parse_sync(CanGc::note());
1112 parser.tokenizer.set_plaintext_state();
1113 self.process_link_headers_in_media_phase_with_task(&parser.document);
1117 }
1118
1119 fn load_media_document(
1121 &mut self,
1122 parser: &ServoParser,
1123 media_type: MediaType,
1124 mime_type: &Mime,
1125 ) {
1126 self.initialize_document_object(&parser.document);
1129 self.is_synthesized_document = true;
1131 let page = "<html><body></body></html>".into();
1133 parser.push_string_input_chunk(page);
1134 parser.parse_sync(CanGc::note());
1135
1136 let doc = &parser.document;
1137 let node = if media_type == MediaType::Image {
1140 let img = Element::create(
1141 QualName::new(None, ns!(html), local_name!("img")),
1142 None,
1143 doc,
1144 ElementCreator::ParserCreated(1),
1145 CustomElementCreationMode::Asynchronous,
1146 None,
1147 CanGc::note(),
1148 );
1149 let img = DomRoot::downcast::<HTMLImageElement>(img).unwrap();
1150 img.SetSrc(USVString(self.url.to_string()));
1151 DomRoot::upcast::<Node>(img)
1152 } else if mime_type.type_() == mime::AUDIO {
1153 let audio = Element::create(
1154 QualName::new(None, ns!(html), local_name!("audio")),
1155 None,
1156 doc,
1157 ElementCreator::ParserCreated(1),
1158 CustomElementCreationMode::Asynchronous,
1159 None,
1160 CanGc::note(),
1161 );
1162 let audio = DomRoot::downcast::<HTMLMediaElement>(audio).unwrap();
1163 audio.SetControls(true);
1164 audio.SetSrc(USVString(self.url.to_string()));
1165 DomRoot::upcast::<Node>(audio)
1166 } else {
1167 let video = Element::create(
1168 QualName::new(None, ns!(html), local_name!("video")),
1169 None,
1170 doc,
1171 ElementCreator::ParserCreated(1),
1172 CustomElementCreationMode::Asynchronous,
1173 None,
1174 CanGc::note(),
1175 );
1176 let video = DomRoot::downcast::<HTMLMediaElement>(video).unwrap();
1177 video.SetControls(true);
1178 video.SetSrc(USVString(self.url.to_string()));
1179 DomRoot::upcast::<Node>(video)
1180 };
1181 let doc_body = DomRoot::upcast::<Node>(doc.GetBody().unwrap());
1183 doc_body
1184 .AppendChild(&node, CanGc::note())
1185 .expect("Appending failed");
1186 let link_headers = std::mem::take(&mut self.navigation_params.link_headers);
1188 process_link_headers(&link_headers, doc, LinkProcessingPhase::Media);
1189 }
1190
1191 fn load_inline_unknown_content(&mut self, parser: &ServoParser, page: String) {
1193 self.is_synthesized_document = true;
1194 parser.push_string_input_chunk(page);
1195 parser.parse_sync(CanGc::note());
1196 }
1197
1198 fn submit_resource_timing(&mut self) {
1200 let Some(parser) = self.parser.as_ref() else {
1201 return;
1202 };
1203 let parser = parser.root();
1204 if parser.aborted.get() {
1205 return;
1206 }
1207
1208 let document = &parser.document;
1209
1210 let performance_entry = PerformanceNavigationTiming::new(
1212 &document.global(),
1213 CrossProcessInstant::now(),
1214 document,
1215 CanGc::note(),
1216 );
1217 self.pushed_entry_index = document
1218 .global()
1219 .performance()
1220 .queue_entry(performance_entry.upcast::<PerformanceEntry>());
1221 }
1222}
1223
1224impl FetchResponseListener for ParserContext {
1225 fn process_request_body(&mut self, _: RequestId) {}
1226
1227 fn process_request_eof(&mut self, _: RequestId) {}
1228
1229 fn process_response(&mut self, _: RequestId, meta_result: Result<FetchMetadata, NetworkError>) {
1230 let (metadata, error) = match meta_result {
1231 Ok(meta) => (
1232 Some(match meta {
1233 FetchMetadata::Unfiltered(m) => m,
1234 FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
1235 }),
1236 None,
1237 ),
1238 Err(error) => (
1239 match &error {
1241 NetworkError::LoadCancelled => {
1242 return;
1243 },
1244 _ => {
1245 let mut meta = Metadata::default(self.url.clone());
1246 let mime: Option<Mime> = "text/html".parse().ok();
1247 meta.set_content_type(mime.as_ref());
1248 Some(meta)
1249 },
1250 },
1251 Some(error),
1252 ),
1253 };
1254 let content_type: Option<Mime> = metadata
1255 .clone()
1256 .and_then(|meta| meta.content_type)
1257 .map(Serde::into_inner)
1258 .map(Into::into);
1259
1260 let (policy_container, endpoints_list, link_headers) = match metadata.as_ref() {
1261 None => (PolicyContainer::default(), None, vec![]),
1262 Some(metadata) => (
1263 Self::create_policy_container_from_fetch_response(metadata),
1264 ReportingEndpoint::parse_reporting_endpoints_header(
1265 &self.url.clone(),
1266 &metadata.headers,
1267 ),
1268 extract_links_from_headers(&metadata.headers),
1269 ),
1270 };
1271
1272 let parser = match ScriptThread::page_headers_available(
1273 self.webview_id,
1274 self.pipeline_id,
1275 metadata,
1276 CanGc::note(),
1277 ) {
1278 Some(parser) => parser,
1279 None => return,
1280 };
1281 if parser.aborted.get() {
1282 return;
1283 }
1284
1285 let _realm = enter_realm(&*parser.document);
1286 let window = parser.document.window();
1287
1288 let final_sandboxing_flag_set = policy_container
1295 .csp_list
1296 .as_ref()
1297 .and_then(|csp| csp.get_sandboxing_flag_set_for_document())
1298 .unwrap_or(SandboxingFlagSet::empty())
1299 .union(parser.document.creation_sandboxing_flag_set());
1300
1301 if let Some(endpoints) = endpoints_list {
1302 window.set_endpoints_list(endpoints);
1303 }
1304 self.parser = Some(Trusted::new(&*parser));
1305 self.navigation_params = NavigationParams {
1306 policy_container,
1307 content_type,
1308 final_sandboxing_flag_set,
1309 link_headers,
1310 about_base_url: parser.document.about_base_url(),
1311 resource_header: vec![],
1312 };
1313 self.submit_resource_timing();
1314
1315 if let Some(error) = error {
1323 let page = match error {
1324 NetworkError::SslValidation(reason, bytes) => {
1325 let page = resources::read_string(Resource::BadCertHTML);
1326 let page = page.replace("${reason}", &reason);
1327 let encoded_bytes = general_purpose::STANDARD_NO_PAD.encode(bytes);
1328 let page = page.replace("${bytes}", encoded_bytes.as_str());
1329 page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string())
1330 },
1331 NetworkError::BlobURLStoreError(reason) |
1332 NetworkError::WebsocketConnectionFailure(reason) |
1333 NetworkError::HttpError(reason) |
1334 NetworkError::ResourceLoadError(reason) |
1335 NetworkError::MimeType(reason) => {
1336 let page = resources::read_string(Resource::NetErrorHTML);
1337 page.replace("${reason}", &reason)
1338 },
1339 NetworkError::Crash(details) => {
1340 let page = resources::read_string(Resource::CrashHTML);
1341 page.replace("${details}", &details)
1342 },
1343 NetworkError::UnsupportedScheme |
1344 NetworkError::CorsGeneral |
1345 NetworkError::CrossOriginResponse |
1346 NetworkError::CorsCredentials |
1347 NetworkError::CorsAllowMethods |
1348 NetworkError::CorsAllowHeaders |
1349 NetworkError::CorsMethod |
1350 NetworkError::CorsAuthorization |
1351 NetworkError::CorsHeaders |
1352 NetworkError::ConnectionFailure |
1353 NetworkError::RedirectError |
1354 NetworkError::TooManyRedirects |
1355 NetworkError::TooManyInFlightKeepAliveRequests |
1356 NetworkError::InvalidMethod |
1357 NetworkError::ContentSecurityPolicy |
1358 NetworkError::Nosniff |
1359 NetworkError::SubresourceIntegrity |
1360 NetworkError::MixedContent |
1361 NetworkError::CacheError |
1362 NetworkError::InvalidPort |
1363 NetworkError::LocalDirectoryError |
1364 NetworkError::PartialResponseToNonRangeRequestError |
1365 NetworkError::ProtocolHandlerSubstitutionError |
1366 NetworkError::DecompressionError => {
1367 let page = resources::read_string(Resource::NetErrorHTML);
1368 page.replace("${reason}", &format!("{:?}", error))
1369 },
1370 NetworkError::LoadCancelled => {
1371 return;
1373 },
1374 };
1375 self.load_inline_unknown_content(&parser, page);
1376 }
1377 }
1378
1379 fn process_response_chunk(&mut self, _: RequestId, payload: Vec<u8>) {
1380 if self.is_synthesized_document {
1381 return;
1382 }
1383 let Some(parser) = self.parser.as_ref().map(|p| p.root()) else {
1384 return;
1385 };
1386 if parser.aborted.get() {
1387 return;
1388 }
1389 if !self.has_loaded_document {
1390 self.navigation_params
1392 .resource_header
1393 .extend_from_slice(&payload);
1394 if self.navigation_params.resource_header.len() >= 1445 {
1396 self.load_document(CanGc::note());
1397 }
1398 } else {
1399 parser.parse_bytes_chunk(payload, CanGc::note());
1400 }
1401 }
1402
1403 fn process_response_eof(
1407 mut self,
1408 cx: &mut js::context::JSContext,
1409 _: RequestId,
1410 status: Result<(), NetworkError>,
1411 timing: ResourceFetchTiming,
1412 ) {
1413 let parser = match self.parser.as_ref() {
1414 Some(parser) => parser.root(),
1415 None => return,
1416 };
1417 if parser.aborted.get() {
1418 return;
1419 }
1420
1421 if let Err(error) = &status {
1422 debug!("Failed to load page URL {}, error: {error:?}", self.url);
1424 }
1425
1426 if !self.has_loaded_document {
1430 self.load_document(CanGc::from_cx(cx));
1431 }
1432
1433 let _realm = enter_realm(&*parser);
1434
1435 if status.is_ok() {
1436 parser.document.set_redirect_count(timing.redirect_count);
1437 }
1438
1439 parser.last_chunk_received.set(true);
1440 if !parser.suspended.get() {
1441 parser.parse_sync(CanGc::from_cx(cx));
1442 }
1443
1444 if let Some(pushed_index) = self.pushed_entry_index {
1447 let document = &parser.document;
1448 let performance_entry = PerformanceNavigationTiming::new(
1449 &document.global(),
1450 CrossProcessInstant::now(),
1451 document,
1452 CanGc::from_cx(cx),
1453 );
1454 document
1455 .global()
1456 .performance()
1457 .update_entry(pushed_index, performance_entry.upcast::<PerformanceEntry>());
1458 }
1459 }
1460
1461 fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
1462 let parser = match self.parser.as_ref() {
1463 Some(parser) => parser.root(),
1464 None => return,
1465 };
1466 let document = &parser.document;
1467 let global = &document.global();
1468 global.report_csp_violations(violations, None, None);
1470 }
1471}
1472
1473pub(crate) struct FragmentContext<'a> {
1474 pub(crate) context_elem: &'a Node,
1475 pub(crate) form_elem: Option<&'a Node>,
1476 pub(crate) context_element_allows_scripting: bool,
1477}
1478
1479#[cfg_attr(crown, expect(crown::unrooted_must_root))]
1480fn insert(
1481 parent: &Node,
1482 reference_child: Option<&Node>,
1483 child: NodeOrText<Dom<Node>>,
1484 parsing_algorithm: ParsingAlgorithm,
1485 custom_element_reaction_stack: &CustomElementReactionStack,
1486 can_gc: CanGc,
1487) {
1488 match child {
1489 NodeOrText::AppendNode(n) => {
1490 let element_in_non_fragment =
1494 parsing_algorithm != ParsingAlgorithm::Fragment && n.is::<Element>();
1495 if element_in_non_fragment {
1496 custom_element_reaction_stack.push_new_element_queue();
1497 }
1498 parent.InsertBefore(&n, reference_child, can_gc).unwrap();
1499 if element_in_non_fragment {
1500 custom_element_reaction_stack.pop_current_element_queue(can_gc);
1501 }
1502 },
1503 NodeOrText::AppendText(t) => {
1504 let text = reference_child
1506 .and_then(Node::GetPreviousSibling)
1507 .or_else(|| parent.GetLastChild())
1508 .and_then(DomRoot::downcast::<Text>);
1509
1510 if let Some(text) = text {
1511 text.upcast::<CharacterData>().append_data(&t);
1512 } else {
1513 let text = Text::new(String::from(t).into(), &parent.owner_doc(), can_gc);
1514 parent
1515 .InsertBefore(text.upcast(), reference_child, can_gc)
1516 .unwrap();
1517 }
1518 },
1519 }
1520}
1521
1522#[derive(JSTraceable, MallocSizeOf)]
1523#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
1524pub(crate) struct Sink {
1525 #[no_trace]
1526 base_url: ServoUrl,
1527 document: Dom<Document>,
1528 current_line: Cell<u64>,
1529 script: MutNullableDom<HTMLScriptElement>,
1530 parsing_algorithm: ParsingAlgorithm,
1531 #[conditional_malloc_size_of]
1532 custom_element_reaction_stack: Rc<CustomElementReactionStack>,
1533}
1534
1535impl Sink {
1536 fn same_tree(&self, x: &Dom<Node>, y: &Dom<Node>) -> bool {
1537 let x = x.downcast::<Element>().expect("Element node expected");
1538 let y = y.downcast::<Element>().expect("Element node expected");
1539
1540 x.is_in_same_home_subtree(y)
1541 }
1542
1543 fn has_parent_node(&self, node: &Dom<Node>) -> bool {
1544 node.GetParentNode().is_some()
1545 }
1546}
1547
1548impl TreeSink for Sink {
1549 type Output = Self;
1550 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1551 fn finish(self) -> Self {
1552 self
1553 }
1554
1555 type Handle = Dom<Node>;
1556 type ElemName<'a>
1557 = ExpandedName<'a>
1558 where
1559 Self: 'a;
1560
1561 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1562 fn get_document(&self) -> Dom<Node> {
1563 Dom::from_ref(self.document.upcast())
1564 }
1565
1566 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1567 fn get_template_contents(&self, target: &Dom<Node>) -> Dom<Node> {
1568 let template = target
1569 .downcast::<HTMLTemplateElement>()
1570 .expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing");
1571 Dom::from_ref(template.Content(CanGc::note()).upcast())
1572 }
1573
1574 fn same_node(&self, x: &Dom<Node>, y: &Dom<Node>) -> bool {
1575 x == y
1576 }
1577
1578 fn elem_name<'a>(&self, target: &'a Dom<Node>) -> ExpandedName<'a> {
1579 let elem = target
1580 .downcast::<Element>()
1581 .expect("tried to get name of non-Element in HTML parsing");
1582 ExpandedName {
1583 ns: elem.namespace(),
1584 local: elem.local_name(),
1585 }
1586 }
1587
1588 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1589 fn create_element(
1590 &self,
1591 name: QualName,
1592 attrs: Vec<Attribute>,
1593 flags: ElementFlags,
1594 ) -> Dom<Node> {
1595 let attrs = attrs
1596 .into_iter()
1597 .map(|attr| ElementAttribute::new(attr.name, DOMString::from(String::from(attr.value))))
1598 .collect();
1599 let parsing_algorithm = if flags.template {
1600 ParsingAlgorithm::Fragment
1601 } else {
1602 self.parsing_algorithm
1603 };
1604 let element = create_element_for_token(
1605 name,
1606 attrs,
1607 &self.document,
1608 ElementCreator::ParserCreated(self.current_line.get()),
1609 parsing_algorithm,
1610 &self.custom_element_reaction_stack,
1611 CanGc::note(),
1612 );
1613 Dom::from_ref(element.upcast())
1614 }
1615
1616 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1617 fn create_comment(&self, text: StrTendril) -> Dom<Node> {
1618 let comment = Comment::new(
1619 DOMString::from(String::from(text)),
1620 &self.document,
1621 None,
1622 CanGc::note(),
1623 );
1624 Dom::from_ref(comment.upcast())
1625 }
1626
1627 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1628 fn create_pi(&self, target: StrTendril, data: StrTendril) -> Dom<Node> {
1629 let doc = &*self.document;
1630 let pi = ProcessingInstruction::new(
1631 DOMString::from(String::from(target)),
1632 DOMString::from(String::from(data)),
1633 doc,
1634 CanGc::note(),
1635 );
1636 Dom::from_ref(pi.upcast())
1637 }
1638
1639 fn associate_with_form(
1640 &self,
1641 target: &Dom<Node>,
1642 form: &Dom<Node>,
1643 nodes: (&Dom<Node>, Option<&Dom<Node>>),
1644 ) {
1645 let (element, prev_element) = nodes;
1646 let tree_node = prev_element.map_or(element, |prev| {
1647 if self.has_parent_node(element) {
1648 element
1649 } else {
1650 prev
1651 }
1652 });
1653 if !self.same_tree(tree_node, form) {
1654 return;
1655 }
1656
1657 let node = target;
1658 let form = DomRoot::downcast::<HTMLFormElement>(DomRoot::from_ref(&**form))
1659 .expect("Owner must be a form element");
1660
1661 let elem = node.downcast::<Element>();
1662 let control = elem.and_then(|e| e.as_maybe_form_control());
1663
1664 if let Some(control) = control {
1665 control.set_form_owner_from_parser(&form, CanGc::note());
1666 }
1667 }
1668
1669 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1670 fn append_before_sibling(&self, sibling: &Dom<Node>, new_node: NodeOrText<Dom<Node>>) {
1671 let parent = sibling
1672 .GetParentNode()
1673 .expect("append_before_sibling called on node without parent");
1674
1675 insert(
1676 &parent,
1677 Some(sibling),
1678 new_node,
1679 self.parsing_algorithm,
1680 &self.custom_element_reaction_stack,
1681 CanGc::note(),
1682 );
1683 }
1684
1685 fn parse_error(&self, msg: Cow<'static, str>) {
1686 debug!("Parse error: {}", msg);
1687 }
1688
1689 fn set_quirks_mode(&self, mode: QuirksMode) {
1690 let mode = match mode {
1691 QuirksMode::Quirks => ServoQuirksMode::Quirks,
1692 QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks,
1693 QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks,
1694 };
1695 self.document.set_quirks_mode(mode);
1696 }
1697
1698 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1699 fn append(&self, parent: &Dom<Node>, child: NodeOrText<Dom<Node>>) {
1700 insert(
1701 parent,
1702 None,
1703 child,
1704 self.parsing_algorithm,
1705 &self.custom_element_reaction_stack,
1706 CanGc::note(),
1707 );
1708 }
1709
1710 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1711 fn append_based_on_parent_node(
1712 &self,
1713 elem: &Dom<Node>,
1714 prev_elem: &Dom<Node>,
1715 child: NodeOrText<Dom<Node>>,
1716 ) {
1717 if self.has_parent_node(elem) {
1718 self.append_before_sibling(elem, child);
1719 } else {
1720 self.append(prev_elem, child);
1721 }
1722 }
1723
1724 fn append_doctype_to_document(
1725 &self,
1726 name: StrTendril,
1727 public_id: StrTendril,
1728 system_id: StrTendril,
1729 ) {
1730 let doc = &*self.document;
1731 let doctype = DocumentType::new(
1732 DOMString::from(String::from(name)),
1733 Some(DOMString::from(String::from(public_id))),
1734 Some(DOMString::from(String::from(system_id))),
1735 doc,
1736 CanGc::note(),
1737 );
1738 doc.upcast::<Node>()
1739 .AppendChild(doctype.upcast(), CanGc::note())
1740 .expect("Appending failed");
1741 }
1742
1743 fn add_attrs_if_missing(&self, target: &Dom<Node>, attrs: Vec<Attribute>) {
1744 let elem = target
1745 .downcast::<Element>()
1746 .expect("tried to set attrs on non-Element in HTML parsing");
1747 for attr in attrs {
1748 elem.set_attribute_from_parser(
1749 attr.name,
1750 DOMString::from(String::from(attr.value)),
1751 None,
1752 CanGc::note(),
1753 );
1754 }
1755 }
1756
1757 fn remove_from_parent(&self, target: &Dom<Node>) {
1758 if let Some(ref parent) = target.GetParentNode() {
1759 parent.RemoveChild(target, CanGc::note()).unwrap();
1760 }
1761 }
1762
1763 fn mark_script_already_started(&self, node: &Dom<Node>) {
1764 let script = node.downcast::<HTMLScriptElement>();
1765 if let Some(script) = script {
1766 script.set_already_started(true)
1767 }
1768 }
1769
1770 fn reparent_children(&self, node: &Dom<Node>, new_parent: &Dom<Node>) {
1771 while let Some(ref child) = node.GetFirstChild() {
1772 new_parent.AppendChild(child, CanGc::note()).unwrap();
1773 }
1774 }
1775
1776 fn is_mathml_annotation_xml_integration_point(&self, handle: &Dom<Node>) -> bool {
1779 let elem = handle.downcast::<Element>().unwrap();
1780 elem.get_attribute(&ns!(), &local_name!("encoding"))
1781 .is_some_and(|attr| {
1782 attr.value().eq_ignore_ascii_case("text/html") ||
1783 attr.value().eq_ignore_ascii_case("application/xhtml+xml")
1784 })
1785 }
1786
1787 fn set_current_line(&self, line_number: u64) {
1788 self.current_line.set(line_number);
1789 }
1790
1791 fn pop(&self, node: &Dom<Node>) {
1792 let node = DomRoot::from_ref(&**node);
1793 vtable_for(&node).pop();
1794 }
1795
1796 fn allow_declarative_shadow_roots(&self, intended_parent: &Dom<Node>) -> bool {
1797 intended_parent.owner_doc().allow_declarative_shadow_roots()
1798 }
1799
1800 fn attach_declarative_shadow(
1804 &self,
1805 host: &Dom<Node>,
1806 template: &Dom<Node>,
1807 attributes: &[Attribute],
1808 ) -> bool {
1809 attach_declarative_shadow_inner(host, template, attributes)
1810 }
1811
1812 fn maybe_clone_an_option_into_selectedcontent(&self, option: &Self::Handle) {
1813 let Some(option) = option.downcast::<HTMLOptionElement>() else {
1814 if cfg!(debug_assertions) {
1815 unreachable!();
1816 }
1817 log::error!(
1818 "Received non-option element in maybe_clone_an_option_into_selectedcontent"
1819 );
1820 return;
1821 };
1822
1823 option.maybe_clone_an_option_into_selectedcontent(CanGc::note())
1824 }
1825}
1826
1827fn create_element_for_token(
1829 name: QualName,
1830 attrs: Vec<ElementAttribute>,
1831 document: &Document,
1832 creator: ElementCreator,
1833 parsing_algorithm: ParsingAlgorithm,
1834 custom_element_reaction_stack: &CustomElementReactionStack,
1835 can_gc: CanGc,
1836) -> DomRoot<Element> {
1837 let is = attrs
1855 .iter()
1856 .find(|attr| attr.name.local.eq_str_ignore_ascii_case("is"))
1857 .map(|attr| LocalName::from(&attr.value));
1858
1859 let definition = document.lookup_custom_element_definition(&name.ns, &name.local, is.as_ref());
1865
1866 let will_execute_script =
1869 definition.is_some() && parsing_algorithm != ParsingAlgorithm::Fragment;
1870
1871 if will_execute_script {
1873 document.increment_throw_on_dynamic_markup_insertion_counter();
1875 if is_execution_stack_empty() {
1878 document.window().perform_a_microtask_checkpoint(can_gc);
1879 }
1880 custom_element_reaction_stack.push_new_element_queue()
1883 }
1884
1885 let creation_mode = if will_execute_script {
1888 CustomElementCreationMode::Synchronous
1889 } else {
1890 CustomElementCreationMode::Asynchronous
1891 };
1892 let element = Element::create(name, is, document, creator, creation_mode, None, can_gc);
1893
1894 for attr in attrs {
1896 element.set_attribute_from_parser(attr.name, attr.value, None, can_gc);
1897 }
1898
1899 if will_execute_script {
1901 custom_element_reaction_stack.pop_current_element_queue(can_gc);
1906 document.decrement_throw_on_dynamic_markup_insertion_counter();
1908 }
1909
1910 if let Some(html_element) = element.downcast::<HTMLElement>() {
1920 if element.is_resettable() && !html_element.is_form_associated_custom_element() {
1921 element.reset(can_gc);
1922 }
1923 }
1924
1925 element
1935}
1936
1937fn attach_declarative_shadow_inner(host: &Node, template: &Node, attributes: &[Attribute]) -> bool {
1938 let host_element = host.downcast::<Element>().unwrap();
1939
1940 if host_element.shadow_root().is_some() {
1941 return false;
1942 }
1943
1944 let template_element = template.downcast::<HTMLTemplateElement>().unwrap();
1945
1946 let mut shadow_root_mode = ShadowRootMode::Open;
1953 let mut clonable = false;
1954 let mut delegatesfocus = false;
1955 let mut serializable = false;
1956
1957 let attributes: Vec<ElementAttribute> = attributes
1958 .iter()
1959 .map(|attr| {
1960 ElementAttribute::new(
1961 attr.name.clone(),
1962 DOMString::from(String::from(attr.value.clone())),
1963 )
1964 })
1965 .collect();
1966
1967 attributes
1968 .iter()
1969 .for_each(|attr: &ElementAttribute| match attr.name.local {
1970 local_name!("shadowrootmode") => {
1971 if attr.value.str().eq_ignore_ascii_case("open") {
1972 shadow_root_mode = ShadowRootMode::Open;
1973 } else if attr.value.str().eq_ignore_ascii_case("closed") {
1974 shadow_root_mode = ShadowRootMode::Closed;
1975 } else {
1976 unreachable!("shadowrootmode value is not open nor closed");
1977 }
1978 },
1979 local_name!("shadowrootclonable") => {
1980 clonable = true;
1981 },
1982 local_name!("shadowrootdelegatesfocus") => {
1983 delegatesfocus = true;
1984 },
1985 local_name!("shadowrootserializable") => {
1986 serializable = true;
1987 },
1988 _ => {},
1989 });
1990
1991 match host_element.attach_shadow(
1994 IsUserAgentWidget::No,
1995 shadow_root_mode,
1996 clonable,
1997 serializable,
1998 delegatesfocus,
1999 SlotAssignmentMode::Named,
2000 CanGc::note(),
2001 ) {
2002 Ok(shadow_root) => {
2003 shadow_root.set_declarative(true);
2005
2006 let shadow = shadow_root.upcast::<DocumentFragment>();
2008 template_element.set_contents(Some(shadow));
2009
2010 shadow_root.set_available_to_element_internals(true);
2012
2013 true
2014 },
2015 Err(_) => false,
2016 }
2017}