Repository: servo/servo
File: components/script/dom/document.rs (Rust)

Code before:
                // parsing-blocking script or deferred script.
                self.process_pending_parsing_blocking_script(can_gc);

                // Step 3.
                self.process_deferred_scripts(can_gc);
            },
            LoadType::PageSource(_) => {
                // We finished loading the page, so if the `Window` is still waiting for
                // the first layout, allow it.
                if self.has_browsing_context && self.is_fully_active() {
                    self.window().allow_layout_if_necessary();
                }

                // Deferred scripts have to wait for page to finish loading,
                // this is the first opportunity to process them.

                // Step 3.
                self.process_deferred_scripts(can_gc);
            },
            _ => {},
        }

        // Note: if a LoadBlocker is dropped since the whole page is dropped, we shouldn't continue
        // processing this load. Otherwise, any subsequent interaction with the document will panic.
        // The underlying problem might actually be that layout exits while it should be kept alive.
        // See https://github.com/servo/servo/issues/22507
        if !runtime_is_alive() {
            return;
        }

        // Step 8. Spin the event loop until there is nothing that delays the load event in the Document.
        let document = Trusted::new(self);
        self.owner_global()
            .task_manager()
            .dom_manipulation_task_source()
            .queue(task!(fire_load_event: move || {
                document.root().wait_until_load_blockers_have_resolved();
            }));
    }

    /// <https://html.spec.whatwg.org/multipage/#checking-if-unloading-is-canceled>
    pub(crate) fn check_if_unloading_is_cancelled(
        &self,
        recursive_flag: bool,
        can_gc: CanGc,
    ) -> bool {
        // TODO: Step 1, increase the event loop's termination nesting level by 1.
        // Step 2
        self.incr_ignore_opens_during_unload_counter();
        // Step 3-5.
        let beforeunload_event = BeforeUnloadEvent::new(

Review comment (suggestion):
Hrm. I'm not sure if this is relevant any longer. Layout now runs in the same thread as script so it cannot "exit" in the way it could before.

Code after:
                // parsing-blocking script or deferred script.
                self.process_pending_parsing_blocking_script(can_gc);

                // Step 3.
                self.process_deferred_scripts(can_gc);
            },
            LoadType::PageSource(_) => {
                // We finished loading the page, so if the `Window` is still waiting for
                // the first layout, allow it.
                if self.has_browsing_context && self.is_fully_active() {
                    self.window().allow_layout_if_necessary();
                }

                // Deferred scripts have to wait for page to finish loading,
                // this is the first opportunity to process them.

                // Step 3.
                self.process_deferred_scripts(can_gc);
            },
            _ => {},
        }

        // Note: if a LoadBlocker is dropped since the whole page is dropped, we shouldn't continue
        // processing this load. Otherwise, any subsequent interaction with the document will panic.
        if !runtime_is_alive() {
            return;
        }

        // Step 8. Spin the event loop until there is nothing that delays the load event in the Document.
        let document = Trusted::new(self);
        self.owner_global()
            .task_manager()
            .dom_manipulation_task_source()
            .queue(task!(check_load_blockers: move || {
                document.root().wait_until_load_blockers_have_resolved();
            }));
    }

    /// <https://html.spec.whatwg.org/multipage/#checking-if-unloading-is-canceled>
    pub(crate) fn check_if_unloading_is_cancelled(
        &self,
        recursive_flag: bool,
        can_gc: CanGc,
    ) -> bool {
        // TODO: Step 1, increase the event loop's termination nesting level by 1.
        // Step 2
        self.incr_ignore_opens_during_unload_counter();
        // Step 3-5.
        let beforeunload_event = BeforeUnloadEvent::new(
            &self.window,
            atom!("beforeunload"),