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