refactor(renderer): bind document task capabilities atomically

This commit is contained in:
ldm0
2026-08-21 18:22:47 +08:00
committed by Donough Liu
parent 69037ba0ae
commit d5e41805f6
7 changed files with 48 additions and 41 deletions
@@ -44,7 +44,7 @@ impl DocumentRuntime {
self.main_document_script_preloads = store;
}
pub(crate) fn bind_main_document_runtime_producer(
pub(super) fn bind_main_document_runtime_producer(
&mut self,
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
) -> bool {
@@ -59,7 +59,7 @@ impl DocumentRuntime {
.has_main_document_runtime_route()
}
pub(crate) fn bind_stylesheet_task_producer(
pub(super) fn bind_stylesheet_task_producer(
&mut self,
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
) {
@@ -74,6 +74,24 @@ impl DocumentRuntime {
self.stylesheet_lifecycle.task_producer = Some(producer);
}
/// Installs every Page task capability for one exact main Document as one
/// synchronous owner transaction. Callers cannot publish work while only
/// a subset of the runtime, stylesheet, and parser routes has advanced.
pub(crate) fn replace_main_document_task_capabilities(
&mut self,
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
) -> bool {
assert_eq!(
self.main_frame_document_task_owner(),
Some(owner),
"main Document task capabilities must match the runtime incarnation"
);
let main_runtime_route_bound = self.bind_main_document_runtime_producer(owner);
self.bind_stylesheet_task_producer(owner);
self.bind_main_parser_continuation_producer(owner);
main_runtime_route_bound
}
pub(crate) fn enqueue_main_document_completion_recheck(
&mut self,
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
@@ -280,7 +298,7 @@ impl DocumentRuntime {
}
/// Completes the exact owner transaction started by [`Self::open_document`].
pub(crate) fn commit_main_document_open(&mut self, owner: FrameDocumentTaskOwner) {
pub(crate) fn commit_main_document_open(&mut self, owner: FrameDocumentTaskOwner) -> bool {
assert!(
matches!(
self.document_incarnation,
@@ -289,6 +307,7 @@ impl DocumentRuntime {
"main Document open must invalidate its retired incarnation before commit"
);
self.document_incarnation = DocumentRuntimeIncarnationIdentity::MainFrame(owner);
self.replace_main_document_task_capabilities(owner)
}
pub(crate) fn parser_module_scripts(&self) -> &ModuleScriptContinuationStore {
@@ -39,7 +39,7 @@ impl MainParserContinuationState {
}
impl DocumentRuntime {
pub(crate) fn bind_main_parser_continuation_producer(&mut self, owner: FrameDocumentTaskOwner) {
pub(super) fn bind_main_parser_continuation_producer(&mut self, owner: FrameDocumentTaskOwner) {
self.main_parser_continuation.producer =
Some(self.main_parser_continuation.sender.bind_producer(owner));
self.main_parser_continuation.admitted = false;
@@ -22,14 +22,16 @@ impl DocumentRuntime {
stylesheet_task_sender: crate::page_task_queue::RendererPageStylesheetTaskSender,
main_parser_continuation_sender: crate::page_task_queue::RendererPageMainParserContinuationSender,
) -> Self {
Self::from_dom_host_with_incarnation(
let mut runtime = Self::from_dom_host_with_incarnation(
dom_host,
DocumentRuntimeIncarnationIdentity::MainFrame(main_document_owner),
page_task_tx,
page_task_parser_boundary_injection_tx,
stylesheet_task_sender,
main_parser_continuation_sender,
)
);
runtime.replace_main_document_task_capabilities(main_document_owner);
runtime
}
pub(crate) fn main_frame_document_task_owner(
+8 -11
View File
@@ -54,7 +54,6 @@ pub(crate) struct HostScriptScheduler {
pending_failed_dynamic_scripts: VecDeque<FailedDynamicScript>,
page_task_tx: Option<PageTaskSender>,
main_document_runtime_producer: Option<RendererPageMainDocumentRuntimeProducer>,
main_document_runtime_target: Option<crate::frame_owner_model::FrameDocumentTaskOwner>,
main_document_completion_recheck_turn_queued: bool,
dynamic_module_job_turn_queued: bool,
native_module_owner_event_turn_queued: bool,
@@ -301,7 +300,6 @@ impl Default for HostScriptScheduler {
pending_failed_dynamic_scripts: VecDeque::new(),
page_task_tx: None,
main_document_runtime_producer: None,
main_document_runtime_target: None,
main_document_completion_recheck_turn_queued: false,
dynamic_module_job_turn_queued: false,
native_module_owner_event_turn_queued: false,
@@ -424,7 +422,6 @@ impl HostScriptScheduler {
self.pending_failed_dynamic_scripts.clear();
}
self.main_document_runtime_producer = None;
self.main_document_runtime_target = None;
self.main_document_completion_recheck_turn_queued = false;
self.dynamic_module_job_turn_queued = false;
self.native_module_owner_event_turn_queued = false;
@@ -1227,18 +1224,17 @@ impl HostScriptScheduler {
&mut self,
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
) -> bool {
let next_target = owner;
if self.main_document_runtime_target != Some(next_target) {
if self
.main_document_runtime_producer
.as_ref()
.is_none_or(|producer| producer.document_owner() != owner)
{
self.main_document_completion_recheck_turn_queued = false;
}
self.main_document_runtime_producer = self
.page_task_tx
.as_ref()
.map(|tx| tx.bind_main_document_runtime_producer(owner));
self.main_document_runtime_target = self
.main_document_runtime_producer
.as_ref()
.map(|_| next_target);
self.dynamic_module_job_turn_queued = false;
self.native_module_owner_event_turn_queued = false;
self.admit_ready_dynamic_module_job();
@@ -1312,8 +1308,9 @@ impl HostScriptScheduler {
owner: crate::frame_owner_model::FrameDocumentTaskOwner,
) -> bool {
if self
.main_document_runtime_target
.is_none_or(|target_owner| target_owner != owner)
.main_document_runtime_producer
.as_ref()
.is_none_or(|producer| producer.document_owner() != owner)
{
return false;
}
@@ -515,29 +515,18 @@ impl JsContextHost {
.expect("main document owner must exist before document.open() replacement");
{
let runtime: &mut DocumentRuntime = self;
runtime.commit_main_document_open(transition.current_owner());
let main_runtime_route_bound =
runtime.commit_main_document_open(transition.current_owner());
assert_eq!(
main_runtime_route_bound,
runtime.has_main_document_runtime_route(),
"document.open() must replace every main Document task capability"
);
runtime.start_root_document_parser_stream();
}
self.dom_agent_state
.reset_for_document_replacement(transition.current_owner().document_id);
self.replace_main_document_resource_loader(transition);
let main_runtime_route_expected = {
let runtime: &DocumentRuntime = self;
runtime.has_main_document_runtime_route()
};
let main_runtime_route_bound = {
let runtime: &mut DocumentRuntime = self;
runtime.bind_main_document_runtime_producer(transition.current_owner())
};
assert_eq!(
main_runtime_route_bound, main_runtime_route_expected,
"document.open() must replace the exact main runtime producer with the owner transaction"
);
{
let runtime: &mut DocumentRuntime = self;
runtime.bind_stylesheet_task_producer(transition.current_owner());
runtime.bind_main_parser_continuation_producer(transition.current_owner());
}
let rebound_meta_refresh = {
let runtime: &mut DocumentRuntime = self;
runtime.rebind_top_level_meta_refresh_after_document_open(transition.current_owner())
@@ -227,6 +227,10 @@ pub(crate) struct RendererPageMainDocumentRuntimeProducer {
}
impl RendererPageMainDocumentRuntimeProducer {
pub(crate) const fn document_owner(&self) -> FrameDocumentTaskOwner {
self.document_owner
}
fn send_action(
&self,
action: RendererPageMainDocumentRuntimeAction,
+2 -6
View File
@@ -1941,14 +1941,10 @@ impl ScriptVmPageRealmBootstrap {
.borrow_mut()
.register_main_document_resource_loader(&initial_document_loader);
document_runtime.set_cookie_store(initial_document_loader.request_client().cookie_store());
let main_runtime_route_bound =
document_runtime.bind_main_document_runtime_producer(main_document_owner);
document_runtime.bind_stylesheet_task_producer(main_document_owner);
document_runtime.bind_main_parser_continuation_producer(main_document_owner);
assert_eq!(
main_runtime_route_bound,
document_runtime.has_main_document_runtime_route(),
page_runtime_wake_tx.has_main_document_runtime_route(),
"main Document runtime producer binding must match the PageVm route capability"
"main Document runtime construction must match the PageVm route capability"
);
{
let context_host = context_host.borrow();