Skip to main content

script/dom/
domparser.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::rust::HandleObject;
7use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto_and_cx};
8use script_traits::DocumentActivity;
9
10use crate::document_loader::DocumentLoader;
11use crate::dom::bindings::codegen::Bindings::DOMParserBinding;
12use crate::dom::bindings::codegen::Bindings::DOMParserBinding::DOMParserMethods;
13use crate::dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{
14    Application_xhtml_xml, Application_xml, Image_svg_xml, Text_html, Text_xml,
15};
16use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentReadyState;
17use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
18use crate::dom::bindings::codegen::UnionTypes::TrustedHTMLOrString;
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
22use crate::dom::servoparser::ServoParser;
23use crate::dom::trustedtypes::trustedhtml::TrustedHTML;
24use crate::dom::window::Window;
25use crate::script_runtime::CanGc;
26
27#[dom_struct]
28pub(crate) struct DOMParser {
29    reflector_: Reflector,
30    window: Dom<Window>, // XXXjdm Document instead?
31}
32
33impl DOMParser {
34    fn new_inherited(window: &Window) -> DOMParser {
35        DOMParser {
36            reflector_: Reflector::new(),
37            window: Dom::from_ref(window),
38        }
39    }
40
41    fn new(
42        cx: &mut js::context::JSContext,
43        window: &Window,
44        proto: Option<HandleObject>,
45    ) -> DomRoot<DOMParser> {
46        reflect_dom_object_with_proto_and_cx(
47            Box::new(DOMParser::new_inherited(window)),
48            window,
49            proto,
50            cx,
51        )
52    }
53}
54
55impl DOMParserMethods<crate::DomTypeHolder> for DOMParser {
56    /// <https://html.spec.whatwg.org/multipage/#dom-domparser-constructor>
57    fn Constructor(
58        cx: &mut js::context::JSContext,
59        window: &Window,
60        proto: Option<HandleObject>,
61    ) -> Fallible<DomRoot<DOMParser>> {
62        Ok(DOMParser::new(cx, window, proto))
63    }
64
65    /// <https://html.spec.whatwg.org/multipage/#dom-domparser-parsefromstring>
66    fn ParseFromString(
67        &self,
68        cx: &mut js::context::JSContext,
69        s: TrustedHTMLOrString,
70        ty: DOMParserBinding::SupportedType,
71    ) -> Fallible<DomRoot<Document>> {
72        // Step 1. Let compliantString be the result of invoking the
73        // Get Trusted Type compliant string algorithm with TrustedHTML,
74        // this's relevant global object, string, "DOMParser parseFromString", and "script".
75        let compliant_string = TrustedHTML::get_trusted_type_compliant_string(
76            cx,
77            self.window.as_global_scope(),
78            s,
79            "DOMParser parseFromString",
80        )?;
81        let url = self.window.get_url();
82        let content_type = ty
83            .as_str()
84            .parse()
85            .expect("Supported type is not a MIME type");
86        let doc = self.window.Document();
87        let loader = DocumentLoader::new(&doc.loader());
88        // Step 3. Switch on type:
89        let document = match ty {
90            Text_html => {
91                // Step 2. Let document be a new Document, whose content type is type
92                // and URL is this's relevant global object's associated Document's URL.
93                let document = Document::new(
94                    &self.window,
95                    HasBrowsingContext::No,
96                    Some(url.clone()),
97                    None,
98                    doc.origin().clone(),
99                    IsHTMLDocument::HTMLDocument,
100                    Some(content_type),
101                    None,
102                    DocumentActivity::Inactive,
103                    DocumentSource::FromParser,
104                    loader,
105                    None,
106                    None,
107                    Default::default(),
108                    false,
109                    false,
110                    Some(doc.insecure_requests_policy()),
111                    doc.has_trustworthy_ancestor_or_current_origin(),
112                    doc.custom_element_reaction_stack(),
113                    doc.creation_sandboxing_flag_set(),
114                    CanGc::from_cx(cx),
115                );
116                // Step switch-1. Parse HTML from a string given document and compliantString.
117                ServoParser::parse_html_document(
118                    &document,
119                    Some(compliant_string),
120                    url,
121                    None,
122                    None,
123                    cx,
124                );
125                document
126            },
127            Text_xml | Application_xml | Application_xhtml_xml | Image_svg_xml => {
128                // Step 2. Let document be a new Document, whose content type is type
129                // and URL is this's relevant global object's associated Document's URL.
130                let document = Document::new(
131                    &self.window,
132                    HasBrowsingContext::No,
133                    Some(url.clone()),
134                    None,
135                    doc.origin().clone(),
136                    IsHTMLDocument::NonHTMLDocument,
137                    Some(content_type),
138                    None,
139                    DocumentActivity::Inactive,
140                    DocumentSource::FromParser,
141                    loader,
142                    None,
143                    None,
144                    Default::default(),
145                    false,
146                    false,
147                    Some(doc.insecure_requests_policy()),
148                    doc.has_trustworthy_ancestor_or_current_origin(),
149                    doc.custom_element_reaction_stack(),
150                    doc.creation_sandboxing_flag_set(),
151                    CanGc::from_cx(cx),
152                );
153                // Step switch-1. Create an XML parser parser, associated with document,
154                // and with XML scripting support disabled.
155                ServoParser::parse_xml_document(&document, Some(compliant_string), url, None, cx);
156                document
157            },
158        };
159        // Step 4. Return document.
160        document.set_ready_state(cx, DocumentReadyState::Complete);
161        Ok(document)
162    }
163}