aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlscriptelement.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2024-12-26 01:06:09 -0500
committerGitHub <noreply@github.com>2024-12-26 06:06:09 +0000
commit981616f91868de481f55e793a7632e6e133a743e (patch)
tree59d1f960e7d5e5d407dd80613cc6dc471271c99f /components/script/dom/htmlscriptelement.rs
parent20d67bdc441eeb61c52c38dd034eaec6504b3b32 (diff)
downloadservo-981616f91868de481f55e793a7632e6e133a743e.tar.gz
servo-981616f91868de481f55e793a7632e6e133a743e.zip
Don't run scripts while DOM tree is undergoing mutations (#34505)
* script: Implement node insertion post-connection hook. Ensure script elements only run scripts when the DOM has stabilized. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Make iframe element use post-connection steps when handling initial document insertion. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Use a delayed task when running post-connection steps. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * script: Add explanatory comment. Signed-off-by: Josh Matthews <josh@joshmatthews.net> * Tidy. Signed-off-by: Josh Matthews <josh@joshmatthews.net> --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Diffstat (limited to 'components/script/dom/htmlscriptelement.rs')
-rw-r--r--components/script/dom/htmlscriptelement.rs27
1 files changed, 17 insertions, 10 deletions
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 4ab12c60df1..244a18568c4 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -55,7 +55,7 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::{
- document_from_node, window_from_node, BindContext, ChildrenMutation, CloneChildrenFlag, Node,
+ document_from_node, window_from_node, ChildrenMutation, CloneChildrenFlag, Node,
};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::virtualmethods::VirtualMethods;
@@ -1188,25 +1188,32 @@ impl VirtualMethods for HTMLScriptElement {
}
}
+ /// <https://html.spec.whatwg.org/multipage/#script-processing-model:the-script-element-26>
fn children_changed(&self, mutation: &ChildrenMutation) {
if let Some(s) = self.super_type() {
s.children_changed(mutation);
}
- if !self.parser_inserted.get() && self.upcast::<Node>().is_connected() {
- self.prepare(CanGc::note());
+
+ if self.upcast::<Node>().is_connected() && !self.parser_inserted.get() {
+ let script = Trusted::new(self);
+ // This method can be invoked while there are script/layout blockers present
+ // as DOM mutations have not yet settled. We use a delayed task to avoid
+ // running any scripts until the DOM tree is safe for interactions.
+ document_from_node(self).add_delayed_task(task!(ScriptPrepare: move || {
+ let this = script.root();
+ this.prepare(CanGc::note());
+ }));
}
}
- fn bind_to_tree(&self, context: &BindContext) {
+ /// <https://html.spec.whatwg.org/multipage/#script-processing-model:the-script-element-20>
+ fn post_connection_steps(&self) {
if let Some(s) = self.super_type() {
- s.bind_to_tree(context);
+ s.post_connection_steps();
}
- if context.tree_connected && !self.parser_inserted.get() {
- let script = Trusted::new(self);
- document_from_node(self).add_delayed_task(task!(ScriptDelayedInitialize: move || {
- script.root().prepare(CanGc::note());
- }));
+ if self.upcast::<Node>().is_connected() && !self.parser_inserted.get() {
+ self.prepare(CanGc::note());
}
}