1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8use script_bindings::cell::DomRefCell;
9use script_bindings::reflector::reflect_dom_object_with_proto_and_cx;
10use stylo_atoms::Atom;
11
12use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
13use crate::dom::bindings::codegen::Bindings::StorageEventBinding;
14use crate::dom::bindings::codegen::Bindings::StorageEventBinding::StorageEventMethods;
15use crate::dom::bindings::error::Fallible;
16use crate::dom::bindings::inheritance::Castable;
17use crate::dom::bindings::root::{DomRoot, MutNullableDom};
18use crate::dom::bindings::str::{DOMString, USVString};
19use crate::dom::event::{Event, EventBubbles, EventCancelable};
20use crate::dom::storage::Storage;
21use crate::dom::window::Window;
22
23#[dom_struct]
24pub(crate) struct StorageEvent {
25 event: Event,
26 key: DomRefCell<Option<DOMString>>,
27 old_value: DomRefCell<Option<DOMString>>,
28 new_value: DomRefCell<Option<DOMString>>,
29 url: DomRefCell<DOMString>,
30 storage_area: MutNullableDom<Storage>,
31}
32
33#[expect(non_snake_case)]
34impl StorageEvent {
35 pub(crate) fn new_inherited(
36 key: Option<DOMString>,
37 old_value: Option<DOMString>,
38 new_value: Option<DOMString>,
39 url: DOMString,
40 storage_area: Option<&Storage>,
41 ) -> StorageEvent {
42 StorageEvent {
43 event: Event::new_inherited(),
44 key: DomRefCell::new(key),
45 old_value: DomRefCell::new(old_value),
46 new_value: DomRefCell::new(new_value),
47 url: DomRefCell::new(url),
48 storage_area: MutNullableDom::new(storage_area),
49 }
50 }
51
52 pub(crate) fn new_uninitialized(
53 cx: &mut JSContext,
54 window: &Window,
55 url: DOMString,
56 ) -> DomRoot<StorageEvent> {
57 Self::new_uninitialized_with_proto(cx, window, None, url)
58 }
59
60 fn new_uninitialized_with_proto(
61 cx: &mut JSContext,
62 window: &Window,
63 proto: Option<HandleObject>,
64 url: DOMString,
65 ) -> DomRoot<StorageEvent> {
66 reflect_dom_object_with_proto_and_cx(
67 Box::new(StorageEvent::new_inherited(None, None, None, url, None)),
68 window,
69 proto,
70 cx,
71 )
72 }
73
74 #[allow(clippy::too_many_arguments)]
75 pub(crate) fn new(
76 cx: &mut JSContext,
77 global: &Window,
78 type_: Atom,
79 bubbles: EventBubbles,
80 cancelable: EventCancelable,
81 key: Option<DOMString>,
82 oldValue: Option<DOMString>,
83 newValue: Option<DOMString>,
84 url: DOMString,
85 storageArea: Option<&Storage>,
86 ) -> DomRoot<StorageEvent> {
87 Self::new_with_proto(
88 cx,
89 global,
90 None,
91 type_,
92 bubbles,
93 cancelable,
94 key,
95 oldValue,
96 newValue,
97 url,
98 storageArea,
99 )
100 }
101
102 #[allow(clippy::too_many_arguments)]
103 fn new_with_proto(
104 cx: &mut JSContext,
105 global: &Window,
106 proto: Option<HandleObject>,
107 type_: Atom,
108 bubbles: EventBubbles,
109 cancelable: EventCancelable,
110 key: Option<DOMString>,
111 oldValue: Option<DOMString>,
112 newValue: Option<DOMString>,
113 url: DOMString,
114 storageArea: Option<&Storage>,
115 ) -> DomRoot<StorageEvent> {
116 let ev = reflect_dom_object_with_proto_and_cx(
117 Box::new(StorageEvent::new_inherited(
118 key,
119 oldValue,
120 newValue,
121 url,
122 storageArea,
123 )),
124 global,
125 proto,
126 cx,
127 );
128 {
129 let event = ev.upcast::<Event>();
130 event.init_event(type_, bool::from(bubbles), bool::from(cancelable));
131 }
132 ev
133 }
134}
135
136#[expect(non_snake_case)]
137impl StorageEventMethods<crate::DomTypeHolder> for StorageEvent {
138 fn Constructor(
140 cx: &mut JSContext,
141 global: &Window,
142 proto: Option<HandleObject>,
143 type_: DOMString,
144 init: &StorageEventBinding::StorageEventInit,
145 ) -> Fallible<DomRoot<StorageEvent>> {
146 let key = init.key.clone();
147 let oldValue = init.oldValue.clone();
148 let newValue = init.newValue.clone();
149 let url = init.url.clone();
150 let storageArea = init.storageArea.as_deref();
151 let bubbles = EventBubbles::from(init.parent.bubbles);
152 let cancelable = EventCancelable::from(init.parent.cancelable);
153 let event = StorageEvent::new_with_proto(
154 cx,
155 global,
156 proto,
157 Atom::from(type_),
158 bubbles,
159 cancelable,
160 key,
161 oldValue,
162 newValue,
163 url,
164 storageArea,
165 );
166 Ok(event)
167 }
168
169 fn GetKey(&self) -> Option<DOMString> {
171 self.key.borrow().clone()
172 }
173
174 fn GetOldValue(&self) -> Option<DOMString> {
176 self.old_value.borrow().clone()
177 }
178
179 fn GetNewValue(&self) -> Option<DOMString> {
181 self.new_value.borrow().clone()
182 }
183
184 fn Url(&self) -> DOMString {
186 self.url.borrow().clone()
187 }
188
189 fn GetStorageArea(&self) -> Option<DomRoot<Storage>> {
191 self.storage_area.get()
192 }
193
194 fn IsTrusted(&self) -> bool {
196 self.event.IsTrusted()
197 }
198
199 fn InitStorageEvent(
201 &self,
202 type_: DOMString,
203 bubbles: bool,
204 cancelable: bool,
205 key: Option<DOMString>,
206 oldValue: Option<DOMString>,
207 newValue: Option<DOMString>,
208 url: USVString,
209 storageArea: Option<&Storage>,
210 ) {
211 self.event
212 .init_event(Atom::from(type_), bubbles, cancelable);
213 *self.key.borrow_mut() = key;
214 *self.old_value.borrow_mut() = oldValue;
215 *self.new_value.borrow_mut() = newValue;
216 *self.url.borrow_mut() = url.into();
217 self.storage_area.set(storageArea);
218 }
219}