diff --git a/Cargo.lock b/Cargo.lock index 96160a3b2b4..562cea89dc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1358,7 +1358,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3727,9 +3727,9 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a694fe8302828cfad7eae3f771ca0040b1aea123606ce34bbb4e13e5316ff407" +checksum = "9d485f1d312f0938f1d8c175a115a1e9f357f8b63262a043b66ce11e1e48128b" dependencies = [ "log", "mac", @@ -4806,7 +4806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -9735,7 +9735,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 344eb8ac72d..83655a2c2c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ gstreamer-video = "0.23" harfbuzz-sys = "0.6.1" headers = "0.4" hitrace = "0.1.5" -html5ever = "0.32" +html5ever = "0.33" http = "1.3" http-body-util = "0.1" hyper = "1.6" diff --git a/components/script/dom/servoparser/async_html.rs b/components/script/dom/servoparser/async_html.rs index f917a68a8c1..21920041af0 100644 --- a/components/script/dom/servoparser/async_html.rs +++ b/components/script/dom/servoparser/async_html.rs @@ -257,20 +257,19 @@ impl Tokenizer { tokenizer.insert_node(0, Dom::from_ref(document.upcast())); let sink = Sink::new(to_tokenizer_sender.clone()); - let mut ctxt_parse_node = None; let mut form_parse_node = None; - let mut fragment_context_is_some = false; - if let Some(fc) = fragment_context { + let mut parser_fragment_context = None; + if let Some(fragment_context) = fragment_context { let node = sink.new_parse_node(); - tokenizer.insert_node(node.id, Dom::from_ref(fc.context_elem)); - ctxt_parse_node = Some(node); + tokenizer.insert_node(node.id, Dom::from_ref(fragment_context.context_elem)); + parser_fragment_context = + Some((node, fragment_context.context_element_allows_scripting)); - form_parse_node = fc.form_elem.map(|form_elem| { + form_parse_node = fragment_context.form_elem.map(|form_elem| { let node = sink.new_parse_node(); tokenizer.insert_node(node.id, Dom::from_ref(form_elem)); node }); - fragment_context_is_some = true; }; // Create new thread for HtmlTokenizer. This is where parser actions @@ -282,8 +281,7 @@ impl Tokenizer { .spawn(move || { run( sink, - fragment_context_is_some, - ctxt_parse_node, + parser_fragment_context, form_parse_node, to_tokenizer_sender, html_tokenizer_receiver, @@ -597,10 +595,15 @@ impl Tokenizer { } } +/// Run the parser. +/// +/// The `fragment_context` argument is `Some` in the fragment case and describes the context +/// node as well as whether scripting is enabled for the context node. Note that whether or not +/// scripting is enabled for the context node does not affect whether scripting is enabled for the +/// parser, that is determined by the `scripting_enabled` argument. fn run( sink: Sink, - fragment_context_is_some: bool, - ctxt_parse_node: Option, + fragment_context: Option<(ParseNode, bool)>, form_parse_node: Option, sender: Sender, receiver: Receiver, @@ -612,16 +615,18 @@ fn run( ..Default::default() }; - let html_tokenizer = if fragment_context_is_some { - let tb = - TreeBuilder::new_for_fragment(sink, ctxt_parse_node.unwrap(), form_parse_node, options); + let html_tokenizer = if let Some((context_node, context_scripting_enabled)) = fragment_context { + let tree_builder = + TreeBuilder::new_for_fragment(sink, context_node, form_parse_node, options); let tok_options = TokenizerOpts { - initial_state: Some(tb.tokenizer_state_for_context_elem()), + initial_state: Some( + tree_builder.tokenizer_state_for_context_elem(context_scripting_enabled), + ), ..Default::default() }; - HtmlTokenizer::new(tb, tok_options) + HtmlTokenizer::new(tree_builder, tok_options) } else { HtmlTokenizer::new(TreeBuilder::new(sink, options), Default::default()) }; diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index 9dfbeda4030..dd5be7d2b8f 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -74,20 +74,22 @@ impl Tokenizer { ..Default::default() }; - let inner = if let Some(fc) = fragment_context { - let tb = TreeBuilder::new_for_fragment( + let inner = if let Some(fragment_context) = fragment_context { + let tree_builder = TreeBuilder::new_for_fragment( sink, - Dom::from_ref(fc.context_elem), - fc.form_elem.map(Dom::from_ref), + Dom::from_ref(fragment_context.context_elem), + fragment_context.form_elem.map(Dom::from_ref), options, ); - let tok_options = TokenizerOpts { - initial_state: Some(tb.tokenizer_state_for_context_elem()), + let tokenizer_options = TokenizerOpts { + initial_state: Some(tree_builder.tokenizer_state_for_context_elem( + fragment_context.context_element_allows_scripting, + )), ..Default::default() }; - HtmlTokenizer::new(tb, tok_options) + HtmlTokenizer::new(tree_builder, tokenizer_options) } else { HtmlTokenizer::new(TreeBuilder::new(sink, options), Default::default()) }; diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index e6f71b19f47..f0394a62a04 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -199,7 +199,7 @@ impl ServoParser { } } - // https://html.spec.whatwg.org/multipage/#parsing-html-fragments + /// pub(crate) fn parse_html_fragment( context: &Element, input: DOMString, @@ -211,7 +211,7 @@ impl ServoParser { let window = context_document.window(); let url = context_document.url(); - // Step 1. + // Step 1. Let document be a Document node whose type is "html". let loader = DocumentLoader::new_with_threads( context_document.loader().resource_threads().clone(), Some(url.clone()), @@ -237,9 +237,16 @@ impl ServoParser { can_gc, ); - // Step 2. + // Step 2. If context's node document is in quirks mode, then set document's mode to "quirks". + // Step 3. Otherwise, if context's node document is in limited-quirks mode, then set document's + // mode to "limited-quirks". document.set_quirks_mode(context_document.quirks_mode()); + // NOTE: The following steps happened as part of Step 1. + // Step 4. If allowDeclarativeShadowRoots is true, then set document's + // allow declarative shadow roots to true. + // Step 5. Create a new HTML parser, and associate it with document. + // Step 11. let form = context_node .inclusive_ancestors(ShadowIncluding::No) @@ -248,6 +255,7 @@ impl ServoParser { let fragment_context = FragmentContext { context_elem: context_node, form_elem: form.as_deref(), + context_element_allows_scripting: context_document.scripting_enabled(), }; let parser = ServoParser::new( @@ -1121,6 +1129,7 @@ impl PreInvoke for ParserContext {} pub(crate) struct FragmentContext<'a> { pub(crate) context_elem: &'a Node, pub(crate) form_elem: Option<&'a Node>, + pub(crate) context_element_allows_scripting: bool, } #[cfg_attr(crown, allow(crown::unrooted_must_root))] diff --git a/tests/wpt/meta/html/syntax/parsing-html-fragments/tokenizer-modes-001.html.ini b/tests/wpt/meta/html/syntax/parsing-html-fragments/tokenizer-modes-001.html.ini deleted file mode 100644 index 384f5a63b3a..00000000000 --- a/tests/wpt/meta/html/syntax/parsing-html-fragments/tokenizer-modes-001.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[tokenizer-modes-001.html] - [ should not break out of noscript.] - expected: FAIL