use dom_struct::dom_struct;
use js::context::{JSContext, NoGC};
use js::gc::HandleObject;
use rustc_hash::FxHashMap;
use script_bindings::codegen::GenericBindings::QuotaExceededErrorBinding::{
QuotaExceededErrorMethods, QuotaExceededErrorOptions,
};
use script_bindings::num::Finite;
use script_bindings::reflector::{reflect_dom_object_with_cx, reflect_dom_object_with_proto};
use script_bindings::root::DomRoot;
use script_bindings::str::DOMString;
use servo_base::id::{QuotaExceededErrorId, QuotaExceededErrorIndex};
use servo_constellation_traits::SerializableQuotaExceededError;
use crate::dom::bindings::error::Error;
use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::types::{DOMException, GlobalScope};
#[dom_struct]
pub(crate) struct QuotaExceededError {
dom_exception: DOMException,
quota: Option<Finite<f64>>,
requested: Option<Finite<f64>>,
}
impl QuotaExceededError {
fn new_inherited(
message: DOMString,
quota: Option<Finite<f64>>,
requested: Option<Finite<f64>>,
) -> Self {
Self {
dom_exception: DOMException::new_inherited(message, "QuotaExceededError".into()),
quota,
requested,
}
}
pub(crate) fn new(
cx: &mut JSContext,
global: &GlobalScope,
message: DOMString,
quota: Option<Finite<f64>>,
requested: Option<Finite<f64>>,
) -> DomRoot<Self> {
reflect_dom_object_with_cx(
Box::new(Self::new_inherited(message, quota, requested)),
global,
cx,
)
}
}
impl QuotaExceededErrorMethods<crate::DomTypeHolder> for QuotaExceededError {
fn Constructor(
cx: &mut JSContext,
global: &GlobalScope,
proto: Option<HandleObject>,
message: DOMString,
options: &QuotaExceededErrorOptions,
) -> Result<DomRoot<Self>, Error> {
if let Some(quota) = options.quota {
if *quota < 0.0 {
return Err(Error::Range(
c"quota must be at least zero if present".to_owned(),
));
}
}
if let Some(requested) = options.requested {
if *requested < 0.0 {
return Err(Error::Range(
c"requested must be at least zero if present".to_owned(),
));
}
}
if let (Some(quota), Some(requested)) = (options.quota, options.requested) &&
*requested < *quota
{
return Err(Error::Range(c"requested is less than quota".to_owned()));
}
Ok(reflect_dom_object_with_proto(
cx,
Box::new(QuotaExceededError::new_inherited(
message,
options.quota,
options.requested,
)),
global,
proto,
))
}
fn GetQuota(&self) -> Option<Finite<f64>> {
self.quota
}
fn GetRequested(&self) -> Option<Finite<f64>> {
self.requested
}
}
impl Serializable for QuotaExceededError {
type Index = QuotaExceededErrorIndex;
type Data = SerializableQuotaExceededError;
fn serialize(&self, no_gc: &NoGC) -> Result<(QuotaExceededErrorId, Self::Data), ()> {
let (_, dom_exception) = self.dom_exception.serialize(no_gc)?;
let serialized = SerializableQuotaExceededError {
dom_exception,
quota: self.quota.as_deref().copied(),
requested: self.requested.as_deref().copied(),
};
Ok((QuotaExceededErrorId::new(), serialized))
}
fn deserialize(
cx: &mut JSContext,
owner: &GlobalScope,
serialized: Self::Data,
) -> Result<DomRoot<Self>, ()>
where
Self: Sized,
{
Ok(Self::new(
cx,
owner,
DOMString::from(serialized.dom_exception.message),
serialized
.quota
.map(|val| Finite::new(val).ok_or(()))
.transpose()?,
serialized
.requested
.map(|val| Finite::new(val).ok_or(()))
.transpose()?,
))
}
fn serialized_storage<'a>(
data: StructuredData<'a, '_>,
) -> &'a mut Option<FxHashMap<QuotaExceededErrorId, Self::Data>> {
match data {
StructuredData::Reader(reader) => &mut reader.quota_exceeded_errors,
StructuredData::Writer(writer) => &mut writer.quota_exceeded_errors,
}
}
}