Enter realms more consistently during the script event loop.

This commit is contained in:
Josh Matthews 2023-02-18 14:07:36 -05:00
parent 9ea1399c30
commit 864e072d5c
6 changed files with 52 additions and 5 deletions

View file

@ -9,6 +9,7 @@ use crate::dom::dedicatedworkerglobalscope::{AutoWorkerReset, DedicatedWorkerScr
use crate::dom::globalscope::GlobalScope;
use crate::dom::worker::TrustedWorkerAddress;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::enter_realm;
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use crate::task_queue::{QueuedTaskConversion, TaskQueue};
use crossbeam_channel::{Receiver, Sender};
@ -140,6 +141,7 @@ pub fn run_worker_event_loop<T, WorkerMsg, Event>(
}
// Step 3
for event in sequential {
let _realm = enter_realm(&*worker_scope);
if !worker_scope.handle_event(event) {
// Shutdown
return;

View file

@ -46,6 +46,7 @@ use crate::fetch::create_a_potential_cors_request;
use crate::image_listener::{generate_cache_listener_for_element, ImageCacheListener};
use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::enter_realm;
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
use app_units::{Au, AU_PER_PX};
@ -56,6 +57,7 @@ use html5ever::{LocalName, Prefix, QualName};
use ipc_channel::ipc;
use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER;
use js::jsapi::JSAutoRealm;
use mime::{self, Mime};
use msg::constellation_msg::PipelineId;
use net_traits::image::base::{Image, ImageMetadata};
@ -1353,6 +1355,13 @@ impl MicrotaskRunnable for ImageElementMicrotask {
},
}
}
fn enter_realm(&self) -> JSAutoRealm {
match self {
&ImageElementMicrotask::StableStateUpdateImageDataTask { ref elem, .. } |
&ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } => enter_realm(&**elem),
}
}
}
pub trait LayoutHTMLImageElementHelpers {

View file

@ -62,7 +62,7 @@ use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::{create_a_potential_cors_request, FetchCanceller};
use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::InRealm;
use crate::realms::{enter_realm, InRealm};
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
@ -74,6 +74,7 @@ use html5ever::{LocalName, Prefix};
use http::header::{self, HeaderMap, HeaderValue};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::jsapi::JSAutoRealm;
use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward, WindowGLContext};
use net_traits::image::base::Image;
use net_traits::request::Destination;
@ -2506,6 +2507,14 @@ impl MicrotaskRunnable for MediaElementMicrotask {
},
}
}
fn enter_realm(&self) -> JSAutoRealm {
match self {
&MediaElementMicrotask::ResourceSelectionTask { ref elem, .. } |
&MediaElementMicrotask::PauseIfNotInDocumentTask { ref elem } |
&MediaElementMicrotask::SeekedTask { ref elem, .. } => enter_realm(&**elem),
}
}
}
enum Resource {

View file

@ -34,6 +34,7 @@ use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::text::Text;
use crate::dom::virtualmethods::vtable_for;
use crate::network_listener::PreInvoke;
use crate::realms::enter_realm;
use crate::script_thread::ScriptThread;
use content_security_policy::{self as csp, CspList};
use dom_struct::dom_struct;
@ -828,6 +829,8 @@ impl FetchResponseListener for ParserContext {
return;
}
let _realm = enter_realm(&*parser.document);
parser.document.set_csp_list(csp_list);
self.parser = Some(Trusted::new(&*parser));
self.submit_resource_timing();

View file

@ -15,9 +15,10 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlimageelement::ImageElementMicrotask;
use crate::dom::htmlmediaelement::MediaElementMicrotask;
use crate::dom::mutationobserver::MutationObserver;
use crate::realms::enter_realm;
use crate::script_runtime::{notify_about_rejected_promises, JSContext};
use crate::script_thread::ScriptThread;
use js::jsapi::{JobQueueIsEmpty, JobQueueMayNotBeEmpty};
use js::jsapi::{JSAutoRealm, JobQueueIsEmpty, JobQueueMayNotBeEmpty};
use msg::constellation_msg::PipelineId;
use std::cell::Cell;
use std::mem;
@ -44,6 +45,7 @@ pub enum Microtask {
pub trait MicrotaskRunnable {
fn handler(&self) {}
fn enter_realm(&self) -> JSAutoRealm;
}
/// A promise callback scheduled to run during the next microtask checkpoint (#4283).
@ -108,19 +110,23 @@ impl MicrotaskQueue {
if let Some(target) = target_provider(job.pipeline) {
let was_interacting = ScriptThread::is_user_interacting();
ScriptThread::set_user_interacting(job.is_user_interacting);
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
ScriptThread::set_user_interacting(was_interacting);
}
},
Microtask::User(ref job) => {
if let Some(target) = target_provider(job.pipeline) {
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
}
},
Microtask::MediaElement(ref task) => {
let _realm = task.enter_realm();
task.handler();
},
Microtask::ImageElement(ref task) => {
let _realm = task.enter_realm();
task.handler();
},
Microtask::CustomElementReaction => {

View file

@ -1592,6 +1592,11 @@ impl ScriptThread {
let category = self.categorize_msg(&msg);
let pipeline_id = self.message_to_pipeline(&msg);
let _realm = pipeline_id.and_then(|id| {
let global = self.documents.borrow().find_global(id);
global.map(|global| enter_realm(&*global))
});
if self.closing.load(Ordering::SeqCst) {
// If we've received the closed signal from the BHM, only handle exit messages.
match msg {
@ -1656,6 +1661,8 @@ impl ScriptThread {
}
let window = document.window();
let _realm = enter_realm(&*document);
window
.upcast::<GlobalScope>()
.perform_a_dom_garbage_collection_checkpoint();
@ -1684,6 +1691,7 @@ impl ScriptThread {
}
for (_, document) in self.documents.borrow().iter() {
let _realm = enter_realm(&*document);
document.animations().send_pending_events(document.window());
}
}
@ -1786,7 +1794,7 @@ impl ScriptThread {
DispatchStorageEvent(id, ..) => Some(id),
ReportCSSError(id, ..) => Some(id),
Reload(id, ..) => Some(id),
PaintMetric(..) => None,
PaintMetric(id, ..) => Some(id),
ExitFullScreen(id, ..) => Some(id),
MediaSessionAction(..) => None,
SetWebGPUPort(..) => None,
@ -2070,7 +2078,13 @@ impl ScriptThread {
fn handle_msg_from_script(&self, msg: MainThreadScriptMsg) {
match msg {
MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task, _, _)) => task.run_box(),
MainThreadScriptMsg::Common(CommonScriptMsg::Task(_, task, pipeline_id, _)) => {
let _realm = pipeline_id.and_then(|id| {
let global = self.documents.borrow().find_global(id);
global.map(|global| enter_realm(&*global))
});
task.run_box()
},
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(chan)) => {
self.collect_reports(chan)
},
@ -3277,6 +3291,8 @@ impl ScriptThread {
incomplete.inherited_secure_context,
);
let _realm = enter_realm(&*window);
// Initialize the browsing context for the window.
let window_proxy = self.local_window_proxy(
&window,
@ -3460,6 +3476,8 @@ impl ScriptThread {
);
}
let _realm = enter_realm(&*window);
// Assuming all CompositionEvent are generated by user interactions.
ScriptThread::set_user_interacting(true);
match event {
@ -3978,7 +3996,7 @@ impl ScriptThread {
.documents
.borrow()
.iter()
.map(|(_id, document)| document.global())
.map(|(_id, document)| DomRoot::from_ref(document.window().upcast()))
.collect();
self.microtask_queue.checkpoint(