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

Code before:
            .fire_event(atom!("readystatechange"), can_gc);
    }

    /// Return whether scripting is enabled or not
    pub(crate) fn is_scripting_enabled(&self) -> bool {
        self.scripting_enabled
    }

    /// Return the element that currently has focus.
    // https://w3c.github.io/uievents/#events-focusevent-doc-focus
    pub(crate) fn get_focused_element(&self) -> Option<DomRoot<Element>> {
        self.focused.get()
    }

    /// Initiate a new round of checking for elements requesting focus. The last element to call
    /// `request_focus` before `commit_focus_transaction` is called will receive focus.
    fn begin_focus_transaction(&self) {
        *self.focus_transaction.borrow_mut() = FocusTransaction::InTransaction(Default::default());
    }

    /// <https://html.spec.whatwg.org/multipage/#focus-fixup-rule>
    pub(crate) fn perform_focus_fixup_rule(&self, not_focusable: &Element) {
        if Some(not_focusable) != self.focused.get().as_deref() {
            return;
        }
        if self.script_and_layout_blockers.get() > 0 {
            let document = Trusted::new(self);
            self.owner_document().add_delayed_task(task!(
                RequestFocus: move || {
                    let document = document.root();
                    if document.focused.get().is_none() {
                        return;
                    }
                    document.request_focus(
                        document.GetBody().as_ref().map(|e| e.upcast()),
                        FocusType::Element,
                        CanGc::note()
                    );
                }
            ));
        } else {
            self.request_focus(
                self.GetBody().as_ref().map(|e| e.upcast()),
                FocusType::Element,
                CanGc::note(),
            );
        }
    }

    /// Request that the given element receive focus once the current transaction is complete.
    /// If None is passed, then whatever element is currently focused will no longer be focused

Review comment (suggestion):
I don't think we should split the logic like this, and I don't think that moving it into a delayed task is the right choice. I suspect that https://github.com/servo/servo/issues/32972#issuecomment-2275468206 is the right fix.

Code after:
    }

    /// Return whether scripting is enabled or not
    /// <https://html.spec.whatwg.org/multipage/#concept-n-noscript>
    pub(crate) fn scripting_enabled(&self) -> bool {
        self.has_browsing_context()
    }

    /// Return the element that currently has focus.
    // https://w3c.github.io/uievents/#events-focusevent-doc-focus
    pub(crate) fn get_focused_element(&self) -> Option<DomRoot<Element>> {
        self.focused.get()
    }

    /// Initiate a new round of checking for elements requesting focus. The last element to call
    /// `request_focus` before `commit_focus_transaction` is called will receive focus.
    fn begin_focus_transaction(&self) {
        *self.focus_transaction.borrow_mut() = FocusTransaction::InTransaction(Default::default());
    }

    /// <https://html.spec.whatwg.org/multipage/#focus-fixup-rule>
    pub(crate) fn perform_focus_fixup_rule(&self, not_focusable: &Element, can_gc: CanGc) {
        if Some(not_focusable) != self.focused.get().as_deref() {
            return;
        }
        self.request_focus(
            self.GetBody().as_ref().map(|e| e.upcast()),
            FocusType::Element,
            can_gc,
        )
    }

    /// Request that the given element receive focus once the current transaction is complete.
    /// If None is passed, then whatever element is currently focused will no longer be focused
    /// once the transaction is complete.
    pub(crate) fn request_focus(
        &self,
        elem: Option<&Element>,
        focus_type: FocusType,
        can_gc: CanGc,
    ) {
        let implicit_transaction = matches!(
            *self.focus_transaction.borrow(),
            FocusTransaction::NotInTransaction
        );
        if implicit_transaction {
            self.begin_focus_transaction();
        }
        if elem.is_none_or(|e| e.is_focusable_area()) {
            *self.focus_transaction.borrow_mut() =
                FocusTransaction::InTransaction(elem.map(Dom::from_ref));