Skip to main content

script/dom/
quotaexceedederror.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::gc::HandleObject;
8use rustc_hash::FxHashMap;
9use script_bindings::codegen::GenericBindings::QuotaExceededErrorBinding::{
10    QuotaExceededErrorMethods, QuotaExceededErrorOptions,
11};
12use script_bindings::num::Finite;
13use script_bindings::reflector::{reflect_dom_object, reflect_dom_object_with_proto};
14use script_bindings::root::DomRoot;
15use script_bindings::script_runtime::CanGc;
16use script_bindings::str::DOMString;
17use servo_base::id::{QuotaExceededErrorId, QuotaExceededErrorIndex};
18use servo_constellation_traits::SerializableQuotaExceededError;
19
20use crate::dom::bindings::error::Error;
21use crate::dom::bindings::serializable::Serializable;
22use crate::dom::bindings::structuredclone::StructuredData;
23use crate::dom::types::{DOMException, GlobalScope};
24
25/// <https://webidl.spec.whatwg.org/#quotaexceedederror>
26#[dom_struct]
27pub(crate) struct QuotaExceededError {
28    /// <https://webidl.spec.whatwg.org/#idl-DOMException>
29    dom_exception: DOMException,
30    /// <https://webidl.spec.whatwg.org/#dom-quotaexceedederror-quota>
31    quota: Option<Finite<f64>>,
32    /// <https://webidl.spec.whatwg.org/#dom-quotaexceedederror-requested>
33    requested: Option<Finite<f64>>,
34}
35
36impl QuotaExceededError {
37    fn new_inherited(
38        message: DOMString,
39        quota: Option<Finite<f64>>,
40        requested: Option<Finite<f64>>,
41    ) -> Self {
42        Self {
43            dom_exception: DOMException::new_inherited(message, "QuotaExceededError".into()),
44            quota,
45            requested,
46        }
47    }
48
49    pub(crate) fn new(
50        global: &GlobalScope,
51        message: DOMString,
52        quota: Option<Finite<f64>>,
53        requested: Option<Finite<f64>>,
54        can_gc: CanGc,
55    ) -> DomRoot<Self> {
56        reflect_dom_object(
57            Box::new(Self::new_inherited(message, quota, requested)),
58            global,
59            can_gc,
60        )
61    }
62}
63
64impl QuotaExceededErrorMethods<crate::DomTypeHolder> for QuotaExceededError {
65    /// <https://webidl.spec.whatwg.org/#dom-quotaexceedederror-quotaexceedederror>
66    fn Constructor(
67        global: &GlobalScope,
68        proto: Option<HandleObject>,
69        can_gc: CanGc,
70        message: DOMString,
71        options: &QuotaExceededErrorOptions,
72    ) -> Result<DomRoot<Self>, Error> {
73        // If options["quota"] is present:
74        if let Some(quota) = options.quota {
75            // If options["quota"] is less than 0, then throw a RangeError.
76            if *quota < 0.0 {
77                return Err(Error::Range(
78                    c"quota must be at least zero if present".to_owned(),
79                ));
80            }
81        }
82        // If options["requested"] is present:
83        if let Some(requested) = options.requested {
84            // If options["requested"] is less than 0, then throw a RangeError.
85            if *requested < 0.0 {
86                return Err(Error::Range(
87                    c"requested must be at least zero if present".to_owned(),
88                ));
89            }
90        }
91        // If this’s quota is not null, this’s requested is not null, and this’s requested
92        // is less than this’s quota, then throw a RangeError.
93        if let (Some(quota), Some(requested)) = (options.quota, options.requested) &&
94            *requested < *quota
95        {
96            return Err(Error::Range(c"requested is less than quota".to_owned()));
97        }
98        Ok(reflect_dom_object_with_proto(
99            Box::new(QuotaExceededError::new_inherited(
100                message,
101                options.quota,
102                options.requested,
103            )),
104            global,
105            proto,
106            can_gc,
107        ))
108    }
109
110    /// <https://webidl.spec.whatwg.org/#dom-quotaexceedederror-quota>
111    fn GetQuota(&self) -> Option<Finite<f64>> {
112        // The quota getter steps are to return this’s quota.
113        self.quota
114    }
115
116    /// <https://webidl.spec.whatwg.org/#dom-quotaexceedederror-requested>
117    fn GetRequested(&self) -> Option<Finite<f64>> {
118        // The requested getter steps are to return this’s requested.
119        self.requested
120    }
121}
122
123impl Serializable for QuotaExceededError {
124    type Index = QuotaExceededErrorIndex;
125    type Data = SerializableQuotaExceededError;
126
127    /// <https://webidl.spec.whatwg.org/#quotaexceedederror>
128    fn serialize(&self) -> Result<(QuotaExceededErrorId, Self::Data), ()> {
129        let (_, dom_exception) = self.dom_exception.serialize()?;
130        let serialized = SerializableQuotaExceededError {
131            dom_exception,
132            quota: self.quota.as_deref().copied(),
133            requested: self.requested.as_deref().copied(),
134        };
135        Ok((QuotaExceededErrorId::new(), serialized))
136    }
137
138    /// <https://webidl.spec.whatwg.org/#quotaexceedederror>
139    fn deserialize(
140        cx: &mut JSContext,
141        owner: &GlobalScope,
142        serialized: Self::Data,
143    ) -> Result<DomRoot<Self>, ()>
144    where
145        Self: Sized,
146    {
147        Ok(Self::new(
148            owner,
149            DOMString::from(serialized.dom_exception.message),
150            serialized
151                .quota
152                .map(|val| Finite::new(val).ok_or(()))
153                .transpose()?,
154            serialized
155                .requested
156                .map(|val| Finite::new(val).ok_or(()))
157                .transpose()?,
158            CanGc::from_cx(cx),
159        ))
160    }
161
162    /// <https://webidl.spec.whatwg.org/#quotaexceedederror>
163    fn serialized_storage<'a>(
164        data: StructuredData<'a, '_>,
165    ) -> &'a mut Option<FxHashMap<QuotaExceededErrorId, Self::Data>> {
166        match data {
167            StructuredData::Reader(reader) => &mut reader.quota_exceeded_errors,
168            StructuredData::Writer(writer) => &mut writer.quota_exceeded_errors,
169        }
170    }
171}