Skip to main content

script/dom/testing/
servotestutils.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5// check-tidy: no specs after this line
6
7use backtrace::Backtrace;
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use layout_api::ReflowPhasesRun;
11use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
12use script_bindings::domstring::DOMString;
13use script_bindings::reflector::Reflector;
14use script_bindings::root::DomRoot;
15use script_bindings::script_runtime::CanGc;
16use time::Duration;
17
18use crate::dom::bindings::codegen::Bindings::ServoTestUtilsBinding::ServoTestUtilsMethods;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::layoutresult::LayoutResult;
21
22#[dom_struct]
23pub(crate) struct ServoTestUtils {
24    reflector_: Reflector,
25}
26
27impl ServoTestUtilsMethods<crate::DomTypeHolder> for ServoTestUtils {
28    fn AdvanceClock(global: &GlobalScope, ms: i32) {
29        global
30            .as_window()
31            .advance_animation_clock(Duration::milliseconds(ms as i64));
32    }
33
34    #[expect(unsafe_code)]
35    fn CrashHard(_: &GlobalScope) {
36        unsafe { std::ptr::null_mut::<i32>().write(42) }
37    }
38
39    fn ForceLayout(cx: &mut JSContext, global: &GlobalScope) -> DomRoot<LayoutResult> {
40        let (phases_run, statistics) = global.as_window().Document().update_the_rendering(cx);
41
42        let mut phases = Vec::new();
43        if phases_run.contains(ReflowPhasesRun::RanLayout) {
44            phases.push(DOMString::from("RanLayout"))
45        }
46        if phases_run.contains(ReflowPhasesRun::BuiltStackingContextTree) {
47            phases.push(DOMString::from("BuiltStackingContextTree"))
48        }
49        if phases_run.contains(ReflowPhasesRun::BuiltDisplayList) {
50            phases.push(DOMString::from("BuiltDisplayList"))
51        }
52        if phases_run.contains(ReflowPhasesRun::UpdatedScrollNodeOffset) {
53            phases.push(DOMString::from("UpdatedScrollNodeOffset"))
54        }
55        if phases_run.contains(ReflowPhasesRun::UpdatedImageData) {
56            phases.push(DOMString::from("UpdatedImageData"))
57        }
58
59        LayoutResult::new(
60            global,
61            phases,
62            statistics.rebuilt_fragment_count,
63            statistics.restyle_fragment_count,
64            statistics.only_descendants_changed_count,
65            CanGc::from_cx(cx),
66        )
67    }
68
69    fn Js_backtrace(_: &GlobalScope) {
70        println!("Current JS stack:");
71        let rust_stack = Backtrace::new();
72        println!("Current Rust stack:\n{:?}", rust_stack);
73    }
74
75    fn Panic(_: &GlobalScope) {
76        panic!("explicit panic from script")
77    }
78
79    fn ForceAccessibilityUpdate(cx: &mut JSContext, global: &GlobalScope) {
80        let window = global.as_window();
81        window.layout().set_needs_accessibility_update();
82        let _ = window.Document().update_the_rendering(cx);
83    }
84}