1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8use rustc_hash::FxHashMap;
9use script_bindings::reflector::{
10 reflect_dom_object_with_cx, reflect_dom_object_with_proto_and_cx,
11};
12use servo_base::id::{DomRectId, DomRectIndex};
13use servo_constellation_traits::DomRect;
14
15use crate::dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
16use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{
17 DOMRectInit, DOMRectReadOnlyMethods,
18};
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::bindings::serializable::Serializable;
22use crate::dom::bindings::structuredclone::StructuredData;
23use crate::dom::domrectreadonly::{DOMRectReadOnly, create_a_domrectreadonly_from_the_dictionary};
24use crate::dom::globalscope::GlobalScope;
25
26#[dom_struct]
27pub(crate) struct DOMRect {
28 rect: DOMRectReadOnly,
29}
30
31impl DOMRect {
32 fn new_inherited(x: f64, y: f64, width: f64, height: f64) -> DOMRect {
33 DOMRect {
34 rect: DOMRectReadOnly::new_inherited(x, y, width, height),
35 }
36 }
37
38 pub(crate) fn new(
39 cx: &mut JSContext,
40 global: &GlobalScope,
41 x: f64,
42 y: f64,
43 width: f64,
44 height: f64,
45 ) -> DomRoot<DOMRect> {
46 Self::new_with_proto(cx, global, None, x, y, width, height)
47 }
48
49 fn new_with_proto(
50 cx: &mut JSContext,
51 global: &GlobalScope,
52 proto: Option<HandleObject>,
53 x: f64,
54 y: f64,
55 width: f64,
56 height: f64,
57 ) -> DomRoot<DOMRect> {
58 reflect_dom_object_with_proto_and_cx(
59 Box::new(DOMRect::new_inherited(x, y, width, height)),
60 global,
61 proto,
62 cx,
63 )
64 }
65}
66
67impl DOMRectMethods<crate::DomTypeHolder> for DOMRect {
68 fn Constructor(
70 cx: &mut JSContext,
71 global: &GlobalScope,
72 proto: Option<HandleObject>,
73 x: f64,
74 y: f64,
75 width: f64,
76 height: f64,
77 ) -> Fallible<DomRoot<DOMRect>> {
78 Ok(DOMRect::new_with_proto(
79 cx, global, proto, x, y, width, height,
80 ))
81 }
82
83 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
85 fn FromRect(cx: &mut JSContext, global: &GlobalScope, other: &DOMRectInit) -> DomRoot<DOMRect> {
86 let rect = create_a_domrectreadonly_from_the_dictionary(other);
87
88 reflect_dom_object_with_cx(Box::new(Self { rect }), global, cx)
89 }
90
91 fn X(&self) -> f64 {
93 self.rect.X()
94 }
95
96 fn SetX(&self, value: f64) {
98 self.rect.set_x(value);
99 }
100
101 fn Y(&self) -> f64 {
103 self.rect.Y()
104 }
105
106 fn SetY(&self, value: f64) {
108 self.rect.set_y(value);
109 }
110
111 fn Width(&self) -> f64 {
113 self.rect.Width()
114 }
115
116 fn SetWidth(&self, value: f64) {
118 self.rect.set_width(value);
119 }
120
121 fn Height(&self) -> f64 {
123 self.rect.Height()
124 }
125
126 fn SetHeight(&self, value: f64) {
128 self.rect.set_height(value);
129 }
130}
131
132impl Serializable for DOMRect {
133 type Index = DomRectIndex;
134 type Data = DomRect;
135
136 fn serialize(&self) -> Result<(DomRectId, Self::Data), ()> {
137 let serialized = DomRect {
138 x: self.X(),
139 y: self.Y(),
140 width: self.Width(),
141 height: self.Height(),
142 };
143 Ok((DomRectId::new(), serialized))
144 }
145
146 fn deserialize(
147 cx: &mut JSContext,
148 owner: &GlobalScope,
149 serialized: Self::Data,
150 ) -> Result<DomRoot<Self>, ()>
151 where
152 Self: Sized,
153 {
154 Ok(Self::new(
155 cx,
156 owner,
157 serialized.x,
158 serialized.y,
159 serialized.width,
160 serialized.height,
161 ))
162 }
163
164 fn serialized_storage<'a>(
165 data: StructuredData<'a, '_>,
166 ) -> &'a mut Option<FxHashMap<DomRectId, Self::Data>> {
167 match data {
168 StructuredData::Reader(reader) => &mut reader.rects,
169 StructuredData::Writer(writer) => &mut writer.rects,
170 }
171 }
172}