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

Code before:
    #[no_trace]
    layout_factory: Arc<dyn LayoutFactory>,

    /// The [`TimerId`] of a ScriptThread-scheduled "update the rendering" call, if any.
    /// The ScriptThread schedules calls to "update the rendering," but the renderer can
    /// also do this when animating. Renderer-based calls always take precedence.
    #[no_trace]
    scheduled_update_the_rendering: RefCell<Option<TimerId>>,

    /// Whether an animation tick or ScriptThread-triggered rendering update is pending. This might
    /// either be because the Servo renderer is managing animations and the [`ScriptThread`] has
    /// received a [`ScriptThreadMessage::TickAllAnimations`] message, because the [`ScriptThread`]
    /// itself is managing animations the timer fired triggering a [`ScriptThread`]-based
    /// animation tick, or if there are no animations running and the [`ScriptThread`] has noticed a
    /// change that requires a rendering update.
    needs_rendering_update: Arc<AtomicBool>,

    debugger_global: Dom<DebuggerGlobalScope>,

    /// A list of URLs that can access privileged internal APIs.
    #[no_trace]
    privileged_urls: Vec<ServoUrl>,

    /// Weak Rc to itself or None if not yet initialized
    #[no_trace]
    script_thread_handle: Weak<ScriptThread>,
}

struct BHMExitSignal {
    closing: Arc<AtomicBool>,
    js_context: ThreadSafeJSContext,
}

impl BackgroundHangMonitorExitSignal for BHMExitSignal {
    fn signal_to_exit(&self) {
        self.closing.store(true, Ordering::SeqCst);
        self.js_context.request_interrupt_callback();
    }
}

#[expect(unsafe_code)]
unsafe extern "C" fn interrupt_callback(_cx: *mut UnsafeJSContext) -> bool {
    let res = ScriptThread::can_continue_running();
    if !res {
        ScriptThread::prepare_for_shutdown();
    }
    res
}

/// In the event of thread panic, all data on the stack runs its destructor. However, there
/// are no reachable, owning pointers to the DOM memory, so it never gets freed by default

Review comment (refactor):
Let's move this to the top of the struct and use `this` as the name as that matches what we do for other pointers of different type to `self`:

```
    /// A `Weak` reference to this [`ScriptThread`] used to give to child [`Window`]s so
    /// they can more easily call methods on the [`ScriptThread`] without constantly having
    /// to pass it everywhere.
    #[no_trace]
    this: Weak<ScriptThread>,
```


Code after:
    #[no_trace]
    #[cfg(feature = "webgpu")]
    gpu_id_hub: Arc<IdentityHub>,

    /// A factory for making new layouts. This allows layout to depend on script.
    #[no_trace]
    layout_factory: Arc<dyn LayoutFactory>,

    /// The [`TimerId`] of a ScriptThread-scheduled "update the rendering" call, if any.
    /// The ScriptThread schedules calls to "update the rendering," but the renderer can
    /// also do this when animating. Renderer-based calls always take precedence.
    #[no_trace]
    scheduled_update_the_rendering: RefCell<Option<TimerId>>,

    /// Whether an animation tick or ScriptThread-triggered rendering update is pending. This might
    /// either be because the Servo renderer is managing animations and the [`ScriptThread`] has
    /// received a [`ScriptThreadMessage::TickAllAnimations`] message, because the [`ScriptThread`]
    /// itself is managing animations the timer fired triggering a [`ScriptThread`]-based
    /// animation tick, or if there are no animations running and the [`ScriptThread`] has noticed a
    /// change that requires a rendering update.
    needs_rendering_update: Arc<AtomicBool>,

    debugger_global: Dom<DebuggerGlobalScope>,

    /// A list of URLs that can access privileged internal APIs.
    #[no_trace]
    privileged_urls: Vec<ServoUrl>,
}

struct BHMExitSignal {
    closing: Arc<AtomicBool>,
    js_context: ThreadSafeJSContext,
}

impl BackgroundHangMonitorExitSignal for BHMExitSignal {
    fn signal_to_exit(&self) {
        self.closing.store(true, Ordering::SeqCst);
        self.js_context.request_interrupt_callback();
    }
}

#[expect(unsafe_code)]
unsafe extern "C" fn interrupt_callback(_cx: *mut UnsafeJSContext) -> bool {
    let res = ScriptThread::can_continue_running();
    if !res {
        ScriptThread::prepare_for_shutdown();
    }
    res
}

/// In the event of thread panic, all data on the stack runs its destructor. However, there