mirror of
https://github.com/servo/servo.git
synced 2025-09-29 16:19:14 +01:00
Combine some access to the thread local variable for script thread. (#38752)
This combines some access to the thread local variable for script thread. - We introduce a new UserInteractingScriptGuard which on drop handles the resetting of was_interacting to the previous value. Sometimes throughout the code `ScriptThread::is_user_interacting` was reset to the previous value while sometimes just set to false. This should remove this footgun. - This also reduces the amount of thread local access for MutationObservers and task queue. Testing: WPT tests should cover this. Fixes: This addresses part of https://github.com/servo/servo/issues/37969 but there is probably still stuff to be done. --------- Signed-off-by: Narfinger <Narfinger@users.noreply.github.com> Signed-off-by: Josh Matthews <josh@joshmatthews.net> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
5de041e6ef
commit
19f70dccf6
11 changed files with 156 additions and 117 deletions
|
@ -28,7 +28,6 @@ use crate::dom::document::Document;
|
|||
use crate::dom::element::{AttributeMutation, Element};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::html::htmlelement::HTMLElement;
|
||||
use crate::dom::mutationobserver::MutationObserver;
|
||||
use crate::dom::node::{BindContext, Node, NodeDamage, NodeTraits, ShadowIncluding, UnbindContext};
|
||||
use crate::dom::virtualmethods::VirtualMethods;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
@ -357,7 +356,8 @@ impl HTMLSlotElement {
|
|||
ScriptThread::add_signal_slot(self);
|
||||
|
||||
// Step 2. Queue a mutation observer microtask.
|
||||
MutationObserver::queue_mutation_observer_microtask();
|
||||
let mutation_observers = ScriptThread::mutation_observers();
|
||||
mutation_observers.queue_mutation_observer_microtask(ScriptThread::microtask_queue());
|
||||
}
|
||||
|
||||
pub(crate) fn remove_from_signal_slots(&self) {
|
||||
|
|
|
@ -9,22 +9,18 @@ use dom_struct::dom_struct;
|
|||
use html5ever::{LocalName, Namespace, ns};
|
||||
use js::rust::HandleObject;
|
||||
|
||||
use crate::dom::bindings::callback::ExceptionHandling;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::MutationObserverBinding::MutationObserver_Binding::MutationObserverMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::MutationObserverBinding::{
|
||||
MutationCallback, MutationObserverInit,
|
||||
};
|
||||
use crate::dom::bindings::error::{Error, Fallible};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
use crate::dom::mutationrecord::MutationRecord;
|
||||
use crate::dom::node::{Node, ShadowIncluding};
|
||||
use crate::dom::window::Window;
|
||||
use crate::microtask::Microtask;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::script_thread::ScriptThread;
|
||||
|
||||
|
@ -91,59 +87,12 @@ impl MutationObserver {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#queue-a-mutation-observer-compound-microtask>
|
||||
pub(crate) fn queue_mutation_observer_microtask() {
|
||||
// Step 1. If the surrounding agent’s mutation observer microtask queued is true, then return.
|
||||
if ScriptThread::is_mutation_observer_microtask_queued() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2. Set the surrounding agent’s mutation observer microtask queued to true.
|
||||
ScriptThread::set_mutation_observer_microtask_queued(true);
|
||||
|
||||
// Step 3. Queue a microtask to notify mutation observers.
|
||||
ScriptThread::enqueue_microtask(Microtask::NotifyMutationObservers);
|
||||
pub(crate) fn record_queue(&self) -> &DomRefCell<Vec<DomRoot<MutationRecord>>> {
|
||||
&self.record_queue
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#notify-mutation-observers>
|
||||
pub(crate) fn notify_mutation_observers(can_gc: CanGc) {
|
||||
// Step 1. Set the surrounding agent’s mutation observer microtask queued to false.
|
||||
ScriptThread::set_mutation_observer_microtask_queued(false);
|
||||
|
||||
// Step 2. Let notifySet be a clone of the surrounding agent’s pending mutation observers.
|
||||
// TODO Step 3. Empty the surrounding agent’s pending mutation observers.
|
||||
let notify_list = ScriptThread::get_mutation_observers();
|
||||
|
||||
// Step 4. Let signalSet be a clone of the surrounding agent’s signal slots.
|
||||
// Step 5. Empty the surrounding agent’s signal slots.
|
||||
let signal_set = ScriptThread::take_signal_slots();
|
||||
|
||||
// Step 6. For each mo of notifySet:
|
||||
for mo in ¬ify_list {
|
||||
// Step 6.1 Let records be a clone of mo’s record queue.
|
||||
let queue: Vec<DomRoot<MutationRecord>> = mo.record_queue.borrow().clone();
|
||||
|
||||
// Step 6.2 Empty mo’s record queue.
|
||||
mo.record_queue.borrow_mut().clear();
|
||||
|
||||
// TODO Step 6.3 For each node of mo’s node list, remove all transient registered observers
|
||||
// whose observer is mo from node’s registered observer list.
|
||||
|
||||
// Step 6.4 If records is not empty, then invoke mo’s callback with « records,
|
||||
// mo » and "report", and with callback this value mo.
|
||||
if !queue.is_empty() {
|
||||
let _ = mo
|
||||
.callback
|
||||
.Call_(&**mo, queue, mo, ExceptionHandling::Report, can_gc);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6. For each slot of signalSet, fire an event named slotchange,
|
||||
// with its bubbles attribute set to true, at slot.
|
||||
for slot in signal_set {
|
||||
slot.upcast::<EventTarget>()
|
||||
.fire_event(atom!("slotchange"), can_gc);
|
||||
}
|
||||
pub(crate) fn callback(&self) -> &Rc<MutationCallback> {
|
||||
&self.callback
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#queueing-a-mutation-record>
|
||||
|
@ -286,7 +235,8 @@ impl MutationObserver {
|
|||
}
|
||||
|
||||
// Step 5
|
||||
MutationObserver::queue_mutation_observer_microtask();
|
||||
let mutation_observers = ScriptThread::mutation_observers();
|
||||
mutation_observers.queue_mutation_observer_microtask(ScriptThread::microtask_queue());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +250,7 @@ impl MutationObserverMethods<crate::DomTypeHolder> for MutationObserver {
|
|||
) -> Fallible<DomRoot<MutationObserver>> {
|
||||
global.set_exists_mut_observer();
|
||||
let observer = MutationObserver::new_with_proto(global, proto, callback, can_gc);
|
||||
ScriptThread::add_mutation_observer(&observer);
|
||||
ScriptThread::mutation_observers().add_mutation_observer(&observer);
|
||||
Ok(observer)
|
||||
}
|
||||
|
||||
|
|
|
@ -323,10 +323,8 @@ impl XRSystem {
|
|||
task!(fire_sessionavailable_event: move || {
|
||||
// The sessionavailable event indicates user intent to enter an XR session
|
||||
let xr = xr.root();
|
||||
let interacting = ScriptThread::is_user_interacting();
|
||||
ScriptThread::set_user_interacting(true);
|
||||
xr.upcast::<EventTarget>().fire_bubbling_event(atom!("sessionavailable"), CanGc::note());
|
||||
ScriptThread::set_user_interacting(interacting);
|
||||
let _guard = ScriptThread::user_interacting_guard();
|
||||
xr.upcast::<EventTarget>().fire_bubbling_event(atom!("sessionavailable"), CanGc::note());
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use js::jsval::JSVal;
|
|||
use profile_traits::ipc;
|
||||
use webxr_api::{self, Error as XRError, MockDeviceInit, MockDeviceMsg};
|
||||
|
||||
use crate::ScriptThread;
|
||||
use crate::dom::bindings::callback::ExceptionHandling;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
|
@ -27,7 +28,6 @@ use crate::dom::fakexrdevice::{FakeXRDevice, get_origin, get_views, get_world};
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::script_thread::ScriptThread;
|
||||
|
||||
#[dom_struct]
|
||||
pub(crate) struct XRTest {
|
||||
|
@ -181,7 +181,7 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
|
||||
/// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md>
|
||||
fn SimulateUserActivation(&self, f: Rc<Function>, can_gc: CanGc) {
|
||||
ScriptThread::set_user_interacting(true);
|
||||
let _guard = ScriptThread::user_interacting_guard();
|
||||
rooted!(in(*GlobalScope::get_cx()) let mut value: JSVal);
|
||||
let _ = f.Call__(
|
||||
vec![],
|
||||
|
@ -189,7 +189,6 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
|
|||
ExceptionHandling::Rethrow,
|
||||
can_gc,
|
||||
);
|
||||
ScriptThread::set_user_interacting(false);
|
||||
}
|
||||
|
||||
/// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue