Skip to main content

script/dom/performance/
largestcontentfulpaint.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
5use dom_struct::dom_struct;
6use js::context::{JSContext, NoGC};
7use layout_api::LCPCandidate;
8use paint_api::display_list::PaintTimingInfo;
9use script_bindings::domstring::TracedDOMString;
10use script_bindings::reflector::reflect_dom_object;
11use servo_base::cross_process_instant::CrossProcessInstant;
12use time::Duration;
13
14use super::performanceentry::{EntryType, PerformanceEntry};
15use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
16use crate::dom::bindings::codegen::Bindings::LargestContentfulPaintBinding::LargestContentfulPaintMethods;
17use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
18use crate::dom::bindings::inheritance::Castable;
19use crate::dom::bindings::reflector::DomGlobal;
20use crate::dom::bindings::root::{Dom, DomRoot};
21use crate::dom::bindings::str::DOMString;
22use crate::dom::element::Element;
23use crate::dom::globalscope::GlobalScope;
24use crate::dom::node::Node;
25
26#[dom_struct]
27pub(crate) struct LargestContentfulPaint {
28    entry: PerformanceEntry,
29    #[no_trace]
30    load_time: Option<CrossProcessInstant>,
31    #[no_trace]
32    render_time: CrossProcessInstant,
33    size: usize,
34    url: TracedDOMString,
35    element: Option<Dom<Element>>,
36    /// <https://www.w3.org/TR/paint-timing/#paint-timing-info>
37    #[no_trace]
38    paint_timing_info: PaintTimingInfo,
39}
40
41impl LargestContentfulPaint {
42    pub(crate) fn new_inherited(
43        candidate: &LCPCandidate,
44        element: Option<&Element>,
45        load_time: Option<CrossProcessInstant>,
46        paint_timing_info: PaintTimingInfo,
47    ) -> LargestContentfulPaint {
48        // From: <https://www.w3.org/TR/largest-contentful-paint/#sec-largest-contentful-paint-interface>
49        //
50        // The renderTime attribute must return the default paint timestamp
51        // given this’s paint timing info.
52        let render_time = paint_timing_info.default_paint_timestamp();
53        LargestContentfulPaint {
54            entry: PerformanceEntry::new_inherited(
55                DOMString::new().into(),
56                EntryType::LargestContentfulPaint,
57                Some(render_time),
58                Duration::ZERO,
59            ),
60            load_time,
61            render_time,
62            size: candidate.area,
63            url: candidate
64                .url
65                .as_ref()
66                .map(|url| DOMString::from(url.as_str()))
67                .unwrap_or_default()
68                .traced(),
69            element: element.map(Dom::from_ref),
70            paint_timing_info,
71        }
72    }
73
74    pub(crate) fn new(
75        cx: &mut JSContext,
76        global: &GlobalScope,
77        candidate: &LCPCandidate,
78        element: Option<&Element>,
79        load_time: Option<CrossProcessInstant>,
80        paint_timing_info: PaintTimingInfo,
81    ) -> DomRoot<LargestContentfulPaint> {
82        reflect_dom_object(
83            cx,
84            Box::new(LargestContentfulPaint::new_inherited(
85                candidate,
86                element,
87                load_time,
88                paint_timing_info,
89            )),
90            global,
91        )
92    }
93}
94
95impl LargestContentfulPaintMethods<crate::DomTypeHolder> for LargestContentfulPaint {
96    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-loadtime>
97    fn LoadTime(&self, cx: &mut JSContext) -> DOMHighResTimeStamp {
98        self.global()
99            .performance(cx)
100            .maybe_to_dom_high_res_time_stamp(self.load_time)
101    }
102
103    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-rendertime>
104    fn RenderTime(&self, cx: &mut JSContext) -> DOMHighResTimeStamp {
105        self.global()
106            .performance(cx)
107            .to_dom_high_res_time_stamp(self.render_time)
108    }
109
110    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-size>
111    fn Size(&self) -> u32 {
112        self.size as u32
113    }
114
115    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-url>
116    fn Url(&self) -> DOMString {
117        self.url.clone().root()
118    }
119
120    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-id>
121    fn Id(&self, no_gc: &NoGC) -> DOMString {
122        self.GetElement(no_gc)
123            .map(|element| element.Id())
124            .unwrap_or_default()
125    }
126
127    /// <https://www.w3.org/TR/largest-contentful-paint/#dom-largestcontentfulpaint-element>
128    fn GetElement(&self, no_gc: &NoGC) -> Option<DomRoot<Element>> {
129        self.element
130            .as_ref()
131            .filter(|element| {
132                element
133                    .upcast::<Node>()
134                    .is_connected_with_browsing_context(no_gc)
135            })
136            .map(|element| element.as_rooted())
137    }
138
139    /// <https://www.w3.org/TR/paint-timing/#dom-painttimingmixin-painttime>
140    fn PaintTime(&self, cx: &mut JSContext) -> DOMHighResTimeStamp {
141        self.global()
142            .performance(cx)
143            .to_dom_high_res_time_stamp(self.paint_timing_info.paint_time())
144    }
145
146    /// <https://www.w3.org/TR/paint-timing/#dom-painttimingmixin-presentationtime>
147    fn GetPresentationTime(&self, cx: &mut JSContext) -> Option<DOMHighResTimeStamp> {
148        Some(
149            self.global()
150                .performance(cx)
151                .maybe_to_dom_high_res_time_stamp(self.paint_timing_info.presentation_time()),
152        )
153    }
154}