use ahash::AHashMap;
use crate::{
ecmascript::{OrdinaryObject, Value, execution::WeakKey},
engine::bindable_handle,
heap::{CompactionLists, HeapMarkAndSweep, HeapSweepWeakReference, WorkQueues},
};
#[derive(Debug, Default)]
pub(crate) struct WeakMapRecord<'a> {
pub(crate) weak_map_data: AHashMap<WeakKey<'a>, Value<'a>>,
pub(super) object_index: Option<OrdinaryObject<'a>>,
}
bindable_handle!(WeakMapRecord);
impl<'a> WeakMapRecord<'a> {
pub(super) fn delete(&mut self, key: WeakKey<'a>) -> bool {
self.weak_map_data.remove(&key).is_some()
}
pub(super) fn get(&mut self, key: WeakKey<'a>) -> Option<Value<'a>> {
self.weak_map_data.get(&key).cloned()
}
pub(super) fn has(&mut self, key: WeakKey<'a>) -> bool {
self.weak_map_data.contains_key(&key)
}
pub(super) fn set(&mut self, key: WeakKey<'a>, value: Value<'a>) {
self.weak_map_data.insert(key, value);
}
}
impl HeapMarkAndSweep for WeakMapRecord<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
let Self {
weak_map_data: map,
object_index,
} = self;
for (key, value) in map.iter() {
if queues.bits.is_marked(key) {
value.mark_values(queues);
} else {
queues.pending_ephemerons.push((*key, *value));
}
}
object_index.mark_values(queues);
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
let Self {
weak_map_data: map,
object_index,
} = self;
let old_map = core::mem::replace(map, AHashMap::with_capacity(map.len()));
for (key, mut value) in old_map {
if let Some(key) = key.sweep_weak_reference(compactions) {
value.sweep_values(compactions);
map.insert(key, value);
}
}
object_index.sweep_values(compactions);
}
}