mod data;
mod plain_time_constructor;
mod plain_time_prototype;
pub(crate) use data::*;
pub(crate) use plain_time_constructor::*;
pub(crate) use plain_time_prototype::*;
use crate::{
ecmascript::{
Agent, ExceptionType, Function, InternalMethods, InternalSlots, JsResult, OrdinaryObject,
ProtoIntrinsics, Value, object_handle, ordinary_populate_from_constructor,
},
engine::{Bindable, GcScope, NoGcScope},
heap::{
ArenaAccess, ArenaAccessMut, BaseIndex, CompactionLists, CreateHeapData, Heap,
HeapMarkAndSweep, HeapSweepWeakReference, WorkQueues, arena_vec_access,
},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct TemporalPlainTime<'a>(BaseIndex<'a, PlainTimeRecord<'static>>);
object_handle!(TemporalPlainTime, PlainTime);
arena_vec_access!(
TemporalPlainTime,
'a,
PlainTimeRecord,
plain_times
);
impl TemporalPlainTime<'_> {
pub(crate) fn inner_plain_time(self, agent: &Agent) -> &temporal_rs::PlainTime {
&self.unbind().get(agent).plain_time
}
}
impl<'a> InternalSlots<'a> for TemporalPlainTime<'a> {
const DEFAULT_PROTOTYPE: ProtoIntrinsics = ProtoIntrinsics::TemporalPlainTime;
fn get_backing_object(self, agent: &Agent) -> Option<OrdinaryObject<'static>> {
self.get(agent).object_index.unbind()
}
fn set_backing_object(self, agent: &mut Agent, backing_object: OrdinaryObject<'static>) {
assert!(
self.get_mut(agent)
.object_index
.replace(backing_object)
.is_none()
);
}
}
impl<'a> InternalMethods<'a> for TemporalPlainTime<'a> {}
impl HeapMarkAndSweep for TemporalPlainTime<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
queues.plain_times.push(*self);
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
compactions.plain_times.shift_index(&mut self.0);
}
}
impl HeapSweepWeakReference for TemporalPlainTime<'static> {
fn sweep_weak_reference(self, compactions: &CompactionLists) -> Option<Self> {
compactions.plain_times.shift_weak_index(self.0).map(Self)
}
}
impl<'a> CreateHeapData<PlainTimeRecord<'a>, TemporalPlainTime<'a>> for Heap {
fn create(&mut self, data: PlainTimeRecord<'a>) -> TemporalPlainTime<'a> {
self.plain_times.push(data.unbind());
self.alloc_counter += core::mem::size_of::<PlainTimeRecord<'static>>();
TemporalPlainTime(BaseIndex::last(&self.plain_times))
}
}
#[inline(always)]
fn require_internal_slot_temporal_plain_time<'a>(
agent: &mut Agent,
value: Value,
gc: NoGcScope<'a, '_>,
) -> JsResult<'a, TemporalPlainTime<'a>> {
match value {
Value::PlainTime(plain_time) => Ok(plain_time.bind(gc)),
_ => Err(agent.throw_exception_with_static_message(
ExceptionType::TypeError,
"Object is not a Temporal PlainTime",
gc,
)),
}
}
pub(crate) fn create_temporal_plain_time<'gc>(
agent: &mut Agent,
plain_time: temporal_rs::PlainTime,
new_target: Option<Function>,
gc: GcScope<'gc, '_>,
) -> JsResult<'gc, TemporalPlainTime<'gc>> {
let new_target = new_target.unwrap_or_else(|| {
agent
.current_realm_record()
.intrinsics()
.temporal_plain_time()
.into()
});
let object = agent.heap.create(PlainTimeRecord {
object_index: None,
plain_time,
});
Ok(
TemporalPlainTime::try_from(ordinary_populate_from_constructor(
agent,
object.unbind().into(),
new_target,
ProtoIntrinsics::TemporalPlainTime,
gc,
)?)
.unwrap(),
)
}