aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/servoparser
diff options
context:
space:
mode:
authorAndriy Sultanov <53952748+last-genius@users.noreply.github.com>2024-09-09 23:38:01 +0100
committerGitHub <noreply@github.com>2024-09-09 22:38:01 +0000
commite5150dbda1f89ff07294dbd1ca4e8f4f08cf4874 (patch)
treee77fae25f33905e1c8c626cf532e7222f521335c /components/script/dom/servoparser
parent10e5bb72d9e16655b625b8971e346ff479b17fd2 (diff)
downloadservo-e5150dbda1f89ff07294dbd1ca4e8f4f08cf4874.tar.gz
servo-e5150dbda1f89ff07294dbd1ca4e8f4f08cf4874.zip
Propagate `CanGc` from `Document::new()` (#33386)
* Add canGc as a parameter to autogenerated trait methods Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com> * Propagate CanGc from Document::new() Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com> --------- Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com>
Diffstat (limited to 'components/script/dom/servoparser')
-rw-r--r--components/script/dom/servoparser/async_html.rs38
-rw-r--r--components/script/dom/servoparser/html.rs3
-rw-r--r--components/script/dom/servoparser/mod.rs126
3 files changed, 107 insertions, 60 deletions
diff --git a/components/script/dom/servoparser/async_html.rs b/components/script/dom/servoparser/async_html.rs
index 551692af1f8..be8adb01e09 100644
--- a/components/script/dom/servoparser/async_html.rs
+++ b/components/script/dom/servoparser/async_html.rs
@@ -41,6 +41,7 @@ use crate::dom::node::Node;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::servoparser::{create_element_for_token, ElementAttribute, ParsingAlgorithm};
use crate::dom::virtualmethods::vtable_for;
+use crate::script_runtime::CanGc;
type ParseNodeId = usize;
@@ -283,7 +284,11 @@ impl Tokenizer {
tokenizer
}
- pub fn feed(&self, input: &BufferQueue) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
+ pub fn feed(
+ &self,
+ input: &BufferQueue,
+ _can_gc: CanGc,
+ ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
let mut send_tendrils = VecDeque::new();
while let Some(str) = input.pop_front() {
send_tendrils.push_back(SendTendril::from(str));
@@ -303,7 +308,9 @@ impl Tokenizer {
.recv()
.expect("Unexpected channel panic in main thread.")
{
- ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
+ ToTokenizerMsg::ProcessOperation(parse_op) => {
+ self.process_operation(parse_op, CanGc::note())
+ },
ToTokenizerMsg::TokenizerResultDone { updated_input } => {
let buffer_queue = create_buffer_queue(updated_input);
input.replace_with(buffer_queue);
@@ -323,7 +330,7 @@ impl Tokenizer {
}
}
- pub fn end(&self) {
+ pub fn end(&self, _can_gc: CanGc) {
self.html_tokenizer_sender
.send(ToHtmlTokenizerMsg::End)
.unwrap();
@@ -333,7 +340,9 @@ impl Tokenizer {
.recv()
.expect("Unexpected channel panic in main thread.")
{
- ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
+ ToTokenizerMsg::ProcessOperation(parse_op) => {
+ self.process_operation(parse_op, CanGc::note())
+ },
ToTokenizerMsg::TokenizerResultDone { updated_input: _ } |
ToTokenizerMsg::TokenizerResultScript {
script: _,
@@ -364,7 +373,7 @@ impl Tokenizer {
})
}
- fn append_before_sibling(&self, sibling: ParseNodeId, node: NodeOrText) {
+ fn append_before_sibling(&self, sibling: ParseNodeId, node: NodeOrText, can_gc: CanGc) {
let node = match node {
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
@@ -376,10 +385,10 @@ impl Tokenizer {
.GetParentNode()
.expect("append_before_sibling called on node without parent");
- super::insert(parent, Some(sibling), node, self.parsing_algorithm);
+ super::insert(parent, Some(sibling), node, self.parsing_algorithm, can_gc);
}
- fn append(&self, parent: ParseNodeId, node: NodeOrText) {
+ fn append(&self, parent: ParseNodeId, node: NodeOrText, can_gc: CanGc) {
let node = match node {
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
@@ -388,7 +397,7 @@ impl Tokenizer {
};
let parent = &**self.get_node(&parent);
- super::insert(parent, None, node, self.parsing_algorithm);
+ super::insert(parent, None, node, self.parsing_algorithm, can_gc);
}
fn has_parent_node(&self, node: ParseNodeId) -> bool {
@@ -404,7 +413,7 @@ impl Tokenizer {
x.is_in_same_home_subtree(y)
}
- fn process_operation(&self, op: ParseOperation) {
+ fn process_operation(&self, op: ParseOperation, can_gc: CanGc) {
let document = DomRoot::from_ref(&**self.get_node(&0));
let document = document
.downcast::<Document>()
@@ -415,7 +424,7 @@ impl Tokenizer {
let template = target
.downcast::<HTMLTemplateElement>()
.expect("Tried to extract contents from non-template element while parsing");
- self.insert_node(contents, Dom::from_ref(template.Content().upcast()));
+ self.insert_node(contents, Dom::from_ref(template.Content(can_gc).upcast()));
},
ParseOperation::CreateElement {
node,
@@ -433,6 +442,7 @@ impl Tokenizer {
&self.document,
ElementCreator::ParserCreated(current_line),
ParsingAlgorithm::Normal,
+ can_gc,
);
self.insert_node(node, Dom::from_ref(element.upcast()));
},
@@ -441,10 +451,10 @@ impl Tokenizer {
self.insert_node(node, Dom::from_ref(comment.upcast()));
},
ParseOperation::AppendBeforeSibling { sibling, node } => {
- self.append_before_sibling(sibling, node);
+ self.append_before_sibling(sibling, node, can_gc);
},
ParseOperation::Append { parent, node } => {
- self.append(parent, node);
+ self.append(parent, node, can_gc);
},
ParseOperation::AppendBasedOnParentNode {
element,
@@ -452,9 +462,9 @@ impl Tokenizer {
node,
} => {
if self.has_parent_node(element) {
- self.append_before_sibling(element, node);
+ self.append_before_sibling(element, node, can_gc);
} else {
- self.append(prev_element, node);
+ self.append(prev_element, node, can_gc);
}
},
ParseOperation::AppendDoctypeToDocument {
diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs
index b3184923609..a2ef2a323fd 100644
--- a/components/script/dom/servoparser/html.rs
+++ b/components/script/dom/servoparser/html.rs
@@ -30,6 +30,7 @@ use crate::dom::htmltemplateelement::HTMLTemplateElement;
use crate::dom::node::Node;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::servoparser::{ParsingAlgorithm, Sink};
+use crate::script_runtime::CanGc;
#[derive(JSTraceable, MallocSizeOf)]
#[crown::unrooted_must_root_lint::must_root]
@@ -163,7 +164,7 @@ fn rev_children_iter(n: &Node) -> impl Iterator<Item = DomRoot<Node>> {
}
match n.downcast::<HTMLTemplateElement>() {
- Some(t) => t.Content().upcast::<Node>().rev_children(),
+ Some(t) => t.Content(CanGc::note()).upcast::<Node>().rev_children(),
None => n.rev_children(),
}
}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index f6c7af85838..958b2bbf3db 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -67,6 +67,7 @@ use crate::dom::text::Text;
use crate::dom::virtualmethods::vtable_for;
use crate::network_listener::PreInvoke;
use crate::realms::enter_realm;
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
mod async_html;
@@ -150,7 +151,12 @@ impl ServoParser {
self.can_write()
}
- pub fn parse_html_document(document: &Document, input: Option<DOMString>, url: ServoUrl) {
+ pub fn parse_html_document(
+ document: &Document,
+ input: Option<DOMString>,
+ url: ServoUrl,
+ can_gc: CanGc,
+ ) {
let parser = if pref!(dom.servoparser.async_html_tokenizer.enabled) {
ServoParser::new(
document,
@@ -172,7 +178,7 @@ impl ServoParser {
// Set as the document's current parser and initialize with `input`, if given.
if let Some(input) = input {
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), can_gc);
} else {
parser.document.set_current_parser(Some(&parser));
}
@@ -182,6 +188,7 @@ impl ServoParser {
pub fn parse_html_fragment(
context: &Element,
input: DOMString,
+ can_gc: CanGc,
) -> impl Iterator<Item = DomRoot<Node>> {
let context_node = context.upcast::<Node>();
let context_document = context_node.owner_doc();
@@ -208,6 +215,7 @@ impl ServoParser {
None,
None,
Default::default(),
+ can_gc,
);
// Step 2.
@@ -233,7 +241,7 @@ impl ServoParser {
)),
ParserKind::Normal,
);
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), CanGc::note());
// Step 14.
let root_element = document.GetDocumentElement().expect("no document element");
@@ -257,7 +265,12 @@ impl ServoParser {
document.set_current_parser(Some(&parser));
}
- pub fn parse_xml_document(document: &Document, input: Option<DOMString>, url: ServoUrl) {
+ pub fn parse_xml_document(
+ document: &Document,
+ input: Option<DOMString>,
+ url: ServoUrl,
+ can_gc: CanGc,
+ ) {
let parser = ServoParser::new(
document,
Tokenizer::Xml(self::xml::Tokenizer::new(document, url)),
@@ -266,7 +279,7 @@ impl ServoParser {
// Set as the document's current parser and initialize with `input`, if given.
if let Some(input) = input {
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), can_gc);
} else {
parser.document.set_current_parser(Some(&parser));
}
@@ -298,6 +311,7 @@ impl ServoParser {
&self,
script: &HTMLScriptElement,
result: ScriptResult,
+ can_gc: CanGc,
) {
assert!(self.suspended.get());
self.suspended.set(false);
@@ -315,7 +329,7 @@ impl ServoParser {
self.script_nesting_level.set(script_nesting_level);
if !self.suspended.get() && !self.aborted.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
@@ -324,7 +338,7 @@ impl ServoParser {
}
/// Steps 6-8 of <https://html.spec.whatwg.org/multipage/#document.write()>
- pub fn write(&self, text: Vec<DOMString>) {
+ pub fn write(&self, text: Vec<DOMString>, _can_gc: CanGc) {
assert!(self.can_write());
if self.document.has_pending_parsing_blocking_script() {
@@ -347,7 +361,7 @@ impl ServoParser {
input.push_back(String::from(chunk).into());
}
- self.tokenize(|tokenizer| tokenizer.feed(&input));
+ self.tokenize(|tokenizer| tokenizer.feed(&input, CanGc::note()));
if self.suspended.get() {
// Parser got suspended, insert remaining input at end of
@@ -363,7 +377,7 @@ impl ServoParser {
}
// Steps 4-6 of https://html.spec.whatwg.org/multipage/#dom-document-close
- pub fn close(&self) {
+ pub fn close(&self, can_gc: CanGc) {
assert!(self.script_created_parser);
// Step 4.
@@ -375,11 +389,11 @@ impl ServoParser {
}
// Step 6.
- self.parse_sync();
+ self.parse_sync(can_gc);
}
// https://html.spec.whatwg.org/multipage/#abort-a-parser
- pub fn abort(&self) {
+ pub fn abort(&self, can_gc: CanGc) {
assert!(!self.aborted.get());
self.aborted.set(true);
@@ -392,7 +406,7 @@ impl ServoParser {
.set_ready_state(DocumentReadyState::Interactive);
// Step 3.
- self.tokenizer.end();
+ self.tokenizer.end(can_gc);
self.document.set_current_parser(None);
// Step 4.
@@ -499,7 +513,7 @@ impl ServoParser {
self.push_tendril_input_chunk(chunk);
}
- fn parse_sync(&self) {
+ fn parse_sync(&self, can_gc: CanGc) {
let metadata = TimerMetadata {
url: self.document.url().as_str().into(),
iframe: TimerMetadataFrameType::RootWindow,
@@ -514,11 +528,11 @@ impl ServoParser {
.upcast::<GlobalScope>()
.time_profiler_chan()
.clone(),
- || self.do_parse_sync(),
+ || self.do_parse_sync(can_gc),
)
}
- fn do_parse_sync(&self) {
+ fn do_parse_sync(&self, _can_gc: CanGc) {
assert!(self.script_input.is_empty());
// This parser will continue to parse while there is either pending input or
@@ -532,7 +546,7 @@ impl ServoParser {
}
}
}
- self.tokenize(|tokenizer| tokenizer.feed(&self.network_input));
+ self.tokenize(|tokenizer| tokenizer.feed(&self.network_input, CanGc::note()));
if self.suspended.get() {
return;
@@ -541,24 +555,24 @@ impl ServoParser {
assert!(self.network_input.is_empty());
if self.last_chunk_received.get() {
- self.finish();
+ self.finish(CanGc::note());
}
}
- fn parse_complete_string_chunk(&self, input: String) {
+ fn parse_complete_string_chunk(&self, input: String, can_gc: CanGc) {
self.document.set_current_parser(Some(self));
self.push_string_input_chunk(input);
self.last_chunk_received.set(true);
if !self.suspended.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
- fn parse_bytes_chunk(&self, input: Vec<u8>) {
+ fn parse_bytes_chunk(&self, input: Vec<u8>, can_gc: CanGc) {
self.document.set_current_parser(Some(self));
self.push_bytes_input_chunk(input);
if !self.suspended.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
@@ -586,7 +600,7 @@ impl ServoParser {
self.document
.window()
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(CanGc::note());
}
let script_nesting_level = self.script_nesting_level.get();
@@ -606,7 +620,7 @@ impl ServoParser {
}
// https://html.spec.whatwg.org/multipage/#the-end
- fn finish(&self) {
+ fn finish(&self, can_gc: CanGc) {
assert!(!self.suspended.get());
assert!(self.last_chunk_received.get());
assert!(self.script_input.is_empty());
@@ -618,12 +632,13 @@ impl ServoParser {
.set_ready_state(DocumentReadyState::Interactive);
// Step 2.
- self.tokenizer.end();
+ self.tokenizer.end(can_gc);
self.document.set_current_parser(None);
// Steps 3-12 are in another castle, namely finish_load.
let url = self.tokenizer.url().clone();
- self.document.finish_load(LoadType::PageSource(url));
+ self.document
+ .finish_load(LoadType::PageSource(url), CanGc::note());
}
}
@@ -666,18 +681,22 @@ enum Tokenizer {
}
impl Tokenizer {
- fn feed(&self, input: &BufferQueue) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
+ fn feed(
+ &self,
+ input: &BufferQueue,
+ can_gc: CanGc,
+ ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
match *self {
Tokenizer::Html(ref tokenizer) => tokenizer.feed(input),
- Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.feed(input),
+ Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.feed(input, can_gc),
Tokenizer::Xml(ref tokenizer) => tokenizer.feed(input),
}
}
- fn end(&self) {
+ fn end(&self, can_gc: CanGc) {
match *self {
Tokenizer::Html(ref tokenizer) => tokenizer.end(),
- Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.end(),
+ Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.end(can_gc),
Tokenizer::Xml(ref tokenizer) => tokenizer.end(),
}
}
@@ -797,7 +816,7 @@ impl FetchResponseListener for ParserContext {
Some(csp_list)
});
- let parser = match ScriptThread::page_headers_available(&self.id, metadata) {
+ let parser = match ScriptThread::page_headers_available(&self.id, metadata, CanGc::note()) {
Some(parser) => parser,
None => return,
};
@@ -829,7 +848,7 @@ impl FetchResponseListener for ParserContext {
self.is_synthesized_document = true;
let page = "<html><body></body></html>".into();
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
let doc = &parser.document;
let doc_body = DomRoot::upcast::<Node>(doc.GetBody().unwrap());
@@ -843,7 +862,7 @@ impl FetchResponseListener for ParserContext {
// https://html.spec.whatwg.org/multipage/#read-text
let page = "<pre>\n".into();
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
parser.tokenizer.set_plaintext_state();
},
(mime::TEXT, mime::HTML, _) => match error {
@@ -856,21 +875,21 @@ impl FetchResponseListener for ParserContext {
let page =
page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string());
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(NetworkError::Internal(reason)) => {
self.is_synthesized_document = true;
let page = resources::read_string(Resource::NetErrorHTML);
let page = page.replace("${reason}", &reason);
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(NetworkError::Crash(details)) => {
self.is_synthesized_document = true;
let page = resources::read_string(Resource::CrashHTML);
let page = page.replace("${details}", &details);
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(_) => {},
None => {},
@@ -888,7 +907,7 @@ impl FetchResponseListener for ParserContext {
);
self.is_synthesized_document = true;
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
}
}
@@ -905,7 +924,7 @@ impl FetchResponseListener for ParserContext {
return;
}
let _realm = enter_realm(&*parser);
- parser.parse_bytes_chunk(payload);
+ parser.parse_bytes_chunk(payload, CanGc::note());
}
// This method is called via script_thread::handle_fetch_eof, so we must call
@@ -935,7 +954,7 @@ impl FetchResponseListener for ParserContext {
parser.last_chunk_received.set(true);
if !parser.suspended.get() {
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
}
// TODO: Only update if this is the current document resource.
@@ -1000,6 +1019,7 @@ fn insert(
reference_child: Option<&Node>,
child: NodeOrText<Dom<Node>>,
parsing_algorithm: ParsingAlgorithm,
+ can_gc: CanGc,
) {
match child {
NodeOrText::AppendNode(n) => {
@@ -1013,7 +1033,7 @@ fn insert(
}
parent.InsertBefore(&n, reference_child).unwrap();
if element_in_non_fragment {
- ScriptThread::pop_current_element_queue();
+ ScriptThread::pop_current_element_queue(can_gc);
}
},
NodeOrText::AppendText(t) => {
@@ -1076,7 +1096,7 @@ impl TreeSink for Sink {
let template = target
.downcast::<HTMLTemplateElement>()
.expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing");
- Dom::from_ref(template.Content().upcast())
+ Dom::from_ref(template.Content(CanGc::note()).upcast())
}
fn same_node(&self, x: &Dom<Node>, y: &Dom<Node>) -> bool {
@@ -1110,6 +1130,7 @@ impl TreeSink for Sink {
&self.document,
ElementCreator::ParserCreated(self.current_line.get()),
self.parsing_algorithm,
+ CanGc::note(),
);
Dom::from_ref(element.upcast())
}
@@ -1167,7 +1188,13 @@ impl TreeSink for Sink {
.GetParentNode()
.expect("append_before_sibling called on node without parent");
- insert(&parent, Some(sibling), new_node, self.parsing_algorithm);
+ insert(
+ &parent,
+ Some(sibling),
+ new_node,
+ self.parsing_algorithm,
+ CanGc::note(),
+ );
}
fn parse_error(&self, msg: Cow<'static, str>) {
@@ -1185,7 +1212,7 @@ impl TreeSink for Sink {
#[allow(crown::unrooted_must_root)]
fn append(&self, parent: &Dom<Node>, child: NodeOrText<Dom<Node>>) {
- insert(parent, None, child, self.parsing_algorithm);
+ insert(parent, None, child, self.parsing_algorithm, CanGc::note());
}
#[allow(crown::unrooted_must_root)]
@@ -1289,6 +1316,7 @@ fn create_element_for_token(
document: &Document,
creator: ElementCreator,
parsing_algorithm: ParsingAlgorithm,
+ can_gc: CanGc,
) -> DomRoot<Element> {
// Step 3.
let is = attrs
@@ -1312,7 +1340,7 @@ fn create_element_for_token(
document
.window()
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(can_gc);
}
// Step 6.3
ScriptThread::push_new_element_queue()
@@ -1325,7 +1353,15 @@ fn create_element_for_token(
CustomElementCreationMode::Asynchronous
};
- let element = Element::create(name, is, document, creator, creation_mode, None);
+ let element = Element::create(
+ name,
+ is,
+ document,
+ creator,
+ creation_mode,
+ None,
+ CanGc::note(),
+ );
// https://html.spec.whatwg.org/multipage#the-input-element:value-sanitization-algorithm-3
// says to invoke sanitization "when an input element is first created";
@@ -1353,7 +1389,7 @@ fn create_element_for_token(
// Step 9.
if will_execute_script {
// Steps 9.1 - 9.2.
- ScriptThread::pop_current_element_queue();
+ ScriptThread::pop_current_element_queue(CanGc::note());
// Step 9.3.
document.decrement_throw_on_dynamic_markup_insertion_counter();
}