script/dom/performance/
largestcontentfulpaint.rs1use 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 #[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 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 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 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 fn Size(&self) -> u32 {
112 self.size as u32
113 }
114
115 fn Url(&self) -> DOMString {
117 self.url.clone().root()
118 }
119
120 fn Id(&self, no_gc: &NoGC) -> DOMString {
122 self.GetElement(no_gc)
123 .map(|element| element.Id())
124 .unwrap_or_default()
125 }
126
127 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 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 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}