Skip to main content

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