1use super::{
2 JsPrototype, ObjectStorage, PropertyDescriptor, PropertyKey,
3 shape::{
4 ChangeTransitionAction, RootShape, Shape, UniqueShape,
5 property_table::PropertyTableInner,
6 shared_shape::TransitionKey,
7 slot::{Slot, SlotAttributes},
8 },
9};
10use crate::value::JsVariant;
11use crate::{JsValue, property::PropertyDescriptorBuilder};
12use boa_gc::{Finalize, Trace};
13use rustc_hash::FxHashMap;
14use std::{collections::hash_map, iter::FusedIterator};
15use thin_vec::ThinVec;
16
17#[derive(Debug, Trace, Finalize)]
37pub enum IndexedProperties {
38 DenseI32(ThinVec<i32>),
40
41 DenseF64(ThinVec<f64>),
43
44 DenseElement(ThinVec<JsValue>),
46
47 SparseElement(Box<FxHashMap<u32, JsValue>>),
49
50 SparseProperty(Box<FxHashMap<u32, PropertyDescriptor>>),
52}
53
54impl Default for IndexedProperties {
55 #[inline]
56 fn default() -> Self {
57 Self::DenseI32(ThinVec::new())
58 }
59}
60
61impl IndexedProperties {
62 pub(crate) fn from_dense_js_value(elements: ThinVec<JsValue>) -> Self {
63 if elements.is_empty() {
64 return Self::default();
65 }
66 Self::DenseElement(elements)
67 }
68
69 #[inline]
70 fn property_simple_value(property: &PropertyDescriptor) -> Option<&JsValue> {
71 if property.writable().unwrap_or(false)
72 && property.enumerable().unwrap_or(false)
73 && property.configurable().unwrap_or(false)
74 {
75 property.value()
76 } else {
77 None
78 }
79 }
80
81 fn get(&self, key: u32) -> Option<PropertyDescriptor> {
83 let value = match self {
84 Self::DenseI32(vec) => vec.get(key as usize).copied()?.into(),
85 Self::DenseF64(vec) => vec.get(key as usize).copied()?.into(),
86 Self::DenseElement(vec) => vec.get(key as usize)?.clone(),
87 Self::SparseElement(map) => map.get(&key)?.clone(),
88 Self::SparseProperty(map) => return map.get(&key).cloned(),
89 };
90
91 Some(
92 PropertyDescriptorBuilder::new()
93 .writable(true)
94 .enumerable(true)
95 .configurable(true)
96 .value(value)
97 .build(),
98 )
99 }
100
101 fn convert_dense_to_sparse<T>(vec: &mut ThinVec<T>) -> FxHashMap<u32, PropertyDescriptor>
103 where
104 T: Into<JsValue>,
105 {
106 let data = std::mem::take(vec);
107
108 data.into_iter()
109 .enumerate()
110 .map(|(index, value)| {
111 (
112 index as u32,
113 PropertyDescriptorBuilder::new()
114 .writable(true)
115 .enumerable(true)
116 .configurable(true)
117 .value(value.into())
118 .build(),
119 )
120 })
121 .collect()
122 }
123
124 fn convert_dense_to_sparse_values<T>(vec: &mut ThinVec<T>) -> FxHashMap<u32, JsValue>
125 where
126 T: Into<JsValue>,
127 {
128 let data = std::mem::take(vec);
129
130 data.into_iter()
131 .enumerate()
132 .map(|(index, value)| (index as u32, value.into()))
133 .collect()
134 }
135
136 fn convert_to_sparse_and_insert(&mut self, key: u32, property: PropertyDescriptor) -> bool {
137 let mut descriptors = match self {
138 Self::DenseI32(vec) => Self::convert_dense_to_sparse(vec),
139 Self::DenseF64(vec) => Self::convert_dense_to_sparse(vec),
140 Self::DenseElement(vec) => Self::convert_dense_to_sparse(vec),
141 Self::SparseElement(map) => map
142 .iter()
143 .map(|(&index, value)| {
144 (
145 index,
146 PropertyDescriptorBuilder::new()
147 .writable(true)
148 .enumerable(true)
149 .configurable(true)
150 .value(value.clone())
151 .build(),
152 )
153 })
154 .collect(),
155 Self::SparseProperty(map) => {
156 return map.insert(key, property).is_some();
157 }
158 };
159
160 let replaced = descriptors.insert(key, property).is_some();
161 *self = Self::SparseProperty(Box::new(descriptors));
162 replaced
163 }
164
165 fn insert(&mut self, key: u32, property: PropertyDescriptor) -> bool {
167 let Some(value) = Self::property_simple_value(&property) else {
168 return self.convert_to_sparse_and_insert(key, property);
169 };
170
171 match self {
172 Self::DenseI32(vec) if key <= vec.len() as u32 => {
174 let len = vec.len() as u32;
175
176 if let Some(val) = value.as_i32() {
177 if key == len {
181 vec.push(val);
182 return false;
183 }
184
185 vec[key as usize] = val;
187 return true;
188 }
189
190 if let Some(num) = value.as_number() {
191 let mut vec = vec.iter().copied().map(f64::from).collect::<ThinVec<_>>();
192
193 if key == len {
197 vec.push(num);
198 *self = Self::DenseF64(vec);
199 return false;
200 }
201
202 vec[key as usize] = num;
204 *self = Self::DenseF64(vec);
205 return true;
206 }
207
208 let mut vec = vec
209 .iter()
210 .copied()
211 .map(JsValue::from)
212 .collect::<ThinVec<JsValue>>();
213
214 if key == len {
218 vec.push(value.clone());
219 *self = Self::DenseElement(vec);
220 return false;
221 }
222
223 vec[key as usize] = value.clone();
225 *self = Self::DenseElement(vec);
226 true
227 }
228 Self::DenseF64(vec) if key <= vec.len() as u32 => {
229 let len = vec.len() as u32;
230
231 if let Some(num) = value.as_number() {
232 if key == len {
236 vec.push(num);
237 return false;
238 }
239
240 vec[key as usize] = num;
242 return true;
243 }
244
245 let mut vec = vec
246 .iter()
247 .copied()
248 .map(JsValue::from)
249 .collect::<ThinVec<JsValue>>();
250
251 if key == len {
255 vec.push(value.clone());
256 *self = Self::DenseElement(vec);
257 return false;
258 }
259
260 vec[key as usize] = value.clone();
262 *self = Self::DenseElement(vec);
263 true
264 }
265 Self::DenseElement(vec) if key <= vec.len() as u32 => {
266 let len = vec.len() as u32;
267
268 if key == len {
272 vec.push(value.clone());
273 return false;
274 }
275
276 vec[key as usize] = value.clone();
278 true
279 }
280 Self::DenseI32(vec) => {
282 let mut values = Self::convert_dense_to_sparse_values(vec);
283 let replaced = values.insert(key, value.clone()).is_some();
284 *self = Self::SparseElement(Box::new(values));
285 replaced
286 }
287 Self::DenseF64(vec) => {
288 let mut values = Self::convert_dense_to_sparse_values(vec);
289 let replaced = values.insert(key, value.clone()).is_some();
290 *self = Self::SparseElement(Box::new(values));
291 replaced
292 }
293 Self::DenseElement(vec) => {
294 let mut values = Self::convert_dense_to_sparse_values(vec);
295 let replaced = values.insert(key, value.clone()).is_some();
296 *self = Self::SparseElement(Box::new(values));
297 replaced
298 }
299 Self::SparseElement(map) => map.insert(key, value.clone()).is_some(),
300 Self::SparseProperty(map) => {
301 let descriptor = PropertyDescriptorBuilder::new()
302 .value(value.clone())
303 .writable(true)
304 .enumerable(true)
305 .configurable(true)
306 .build();
307 map.insert(key, descriptor).is_some()
308 }
309 }
310 }
311
312 fn convert_to_sparse_and_remove(&mut self, key: u32) -> bool {
313 let mut descriptors = match self {
314 IndexedProperties::DenseI32(vec) => Self::convert_dense_to_sparse_values(vec),
315 IndexedProperties::DenseF64(vec) => Self::convert_dense_to_sparse_values(vec),
316 IndexedProperties::DenseElement(vec) => Self::convert_dense_to_sparse_values(vec),
317 IndexedProperties::SparseProperty(map) => return map.remove(&key).is_some(),
318 IndexedProperties::SparseElement(map) => {
319 return map.remove(&key).is_some();
320 }
321 };
322
323 let removed = descriptors.remove(&key).is_some();
324 *self = Self::SparseElement(Box::new(descriptors));
325 removed
326 }
327
328 fn remove(&mut self, key: u32) -> bool {
330 match self {
331 Self::DenseI32(vec) if (key + 1) == vec.len() as u32 => {
335 vec.pop();
336 true
337 }
338 Self::DenseI32(vec) if key >= vec.len() as u32 => false,
340 Self::DenseF64(vec) if (key + 1) == vec.len() as u32 => {
341 vec.pop();
342 true
343 }
344 Self::DenseF64(vec) if key >= vec.len() as u32 => false,
345 Self::DenseElement(vec) if (key + 1) == vec.len() as u32 => {
346 vec.pop();
347 true
348 }
349 Self::DenseElement(vec) if key >= vec.len() as u32 => false,
350 Self::SparseElement(map) => map.remove(&key).is_some(),
352 Self::SparseProperty(map) => map.remove(&key).is_some(),
353 _ => self.convert_to_sparse_and_remove(key),
354 }
355 }
356
357 fn contains_key(&self, key: u32) -> bool {
359 match self {
360 Self::DenseI32(vec) => (0..vec.len() as u32).contains(&key),
361 Self::DenseF64(vec) => (0..vec.len() as u32).contains(&key),
362 Self::DenseElement(vec) => (0..vec.len() as u32).contains(&key),
363 Self::SparseElement(map) => map.contains_key(&key),
364 Self::SparseProperty(map) => map.contains_key(&key),
365 }
366 }
367
368 pub(crate) fn push_dense(&mut self, value: &JsValue) -> bool {
375 match self {
376 Self::DenseI32(vec) => {
377 if let Some(i) = value.as_i32() {
378 vec.push(i);
379 } else if let Some(n) = value.as_number() {
380 let mut new_vec: ThinVec<f64> = vec.iter().copied().map(f64::from).collect();
381 new_vec.push(n);
382 *self = Self::DenseF64(new_vec);
383 } else {
384 let mut new_vec: ThinVec<JsValue> =
385 vec.iter().copied().map(JsValue::from).collect();
386 new_vec.push(value.clone());
387 *self = Self::DenseElement(new_vec);
388 }
389 true
390 }
391 Self::DenseF64(vec) => {
392 if let Some(n) = value.as_number() {
393 vec.push(n);
394 } else {
395 let mut new_vec: ThinVec<JsValue> =
396 vec.iter().copied().map(JsValue::from).collect();
397 new_vec.push(value.clone());
398 *self = Self::DenseElement(new_vec);
399 }
400 true
401 }
402 Self::DenseElement(vec) => {
403 vec.push(value.clone());
404 true
405 }
406 Self::SparseElement(_) | Self::SparseProperty(_) => false,
407 }
408 }
409
410 pub(crate) fn transform_to_sparse(&mut self) {
412 match &*self {
413 Self::DenseI32(v) => {
414 *self = Self::SparseElement(Box::new(
415 v.into_iter()
416 .copied()
417 .enumerate()
418 .map(|(i, v)| (i as u32, JsValue::from(v)))
419 .collect(),
420 ));
421 }
422 Self::DenseF64(v) => {
423 *self = Self::SparseElement(Box::new(
424 v.into_iter()
425 .copied()
426 .enumerate()
427 .map(|(i, v)| (i as u32, JsValue::from(v)))
428 .collect(),
429 ));
430 }
431 Self::DenseElement(v) => {
432 *self = Self::SparseElement(Box::new(
433 v.into_iter()
434 .enumerate()
435 .map(|(i, v)| (i as u32, v.clone()))
436 .collect(),
437 ));
438 }
439 _ => {}
440 }
441 }
442
443 fn iter(&self) -> IndexProperties<'_> {
444 match self {
445 Self::DenseI32(vec) => IndexProperties::DenseI32(vec.iter().enumerate()),
446 Self::DenseF64(vec) => IndexProperties::DenseF64(vec.iter().enumerate()),
447 Self::DenseElement(vec) => IndexProperties::DenseElement(vec.iter().enumerate()),
448 Self::SparseElement(map) => IndexProperties::SparseElement(map.iter()),
449 Self::SparseProperty(map) => IndexProperties::SparseProperty(map.iter()),
450 }
451 }
452
453 fn keys(&self) -> IndexPropertyKeys<'_> {
454 match self {
455 Self::DenseI32(vec) => IndexPropertyKeys::Dense(0..vec.len() as u32),
456 Self::DenseF64(vec) => IndexPropertyKeys::Dense(0..vec.len() as u32),
457 Self::DenseElement(vec) => IndexPropertyKeys::Dense(0..vec.len() as u32),
458 Self::SparseElement(map) => IndexPropertyKeys::SparseElement(map.keys()),
459 Self::SparseProperty(map) => IndexPropertyKeys::SparseProperty(map.keys()),
460 }
461 }
462
463 fn values(&self) -> IndexPropertyValues<'_> {
464 match self {
465 Self::DenseI32(vec) => IndexPropertyValues::DenseI32(vec.iter()),
466 Self::DenseF64(vec) => IndexPropertyValues::DenseF64(vec.iter()),
467 Self::DenseElement(vec) => IndexPropertyValues::DenseElement(vec.iter()),
468 Self::SparseElement(map) => IndexPropertyValues::SparseElement(map.values()),
469 Self::SparseProperty(map) => IndexPropertyValues::SparseProperty(map.values()),
470 }
471 }
472}
473
474impl<'a> IntoIterator for &'a IndexedProperties {
475 type IntoIter = IndexProperties<'a>;
476 type Item = (u32, PropertyDescriptor);
477 fn into_iter(self) -> Self::IntoIter {
478 self.iter()
479 }
480}
481
482#[derive(Default, Debug, Trace, Finalize)]
486pub struct PropertyMap {
487 pub(crate) indexed_properties: IndexedProperties,
489
490 pub(crate) shape: Shape,
491 pub(crate) storage: ObjectStorage,
492}
493
494impl PropertyMap {
495 #[must_use]
497 #[inline]
498 pub fn new(shape: Shape, indexed_properties: IndexedProperties) -> Self {
499 Self {
500 indexed_properties,
501 shape,
502 storage: Vec::default(),
503 }
504 }
505
506 #[must_use]
508 #[inline]
509 pub fn from_prototype_unique_shape(prototype: JsPrototype) -> Self {
510 Self {
511 indexed_properties: IndexedProperties::default(),
512 shape: UniqueShape::new(prototype, PropertyTableInner::default()).into(),
513 storage: Vec::default(),
514 }
515 }
516
517 #[must_use]
519 #[inline]
520 pub fn from_prototype_with_shared_shape(
521 root_shape: &RootShape,
522 prototype: JsPrototype,
523 ) -> Self {
524 let shape = root_shape.shape().change_prototype_transition(prototype);
525 Self {
526 indexed_properties: IndexedProperties::default(),
527 shape: shape.into(),
528 storage: Vec::default(),
529 }
530 }
531
532 #[must_use]
534 pub fn get(&self, key: &PropertyKey) -> Option<PropertyDescriptor> {
535 if let PropertyKey::Index(index) = key {
536 return self.indexed_properties.get(index.get());
537 }
538 if let Some(slot) = self.shape.lookup(key) {
539 return Some(self.get_storage(slot));
540 }
541
542 None
543 }
544
545 #[must_use]
547 pub(crate) fn get_with_slot(
548 &self,
549 key: &PropertyKey,
550 out_slot: &mut Slot,
551 ) -> Option<PropertyDescriptor> {
552 if let PropertyKey::Index(index) = key {
553 return self.indexed_properties.get(index.get());
554 }
555 if let Some(slot) = self.shape.lookup(key) {
556 out_slot.index = slot.index;
557
558 out_slot.attributes = (out_slot.attributes & SlotAttributes::INLINE_CACHE_BITS)
560 | slot.attributes
561 | SlotAttributes::FOUND;
562 return Some(self.get_storage(slot));
563 }
564
565 None
566 }
567
568 #[must_use]
570 pub(crate) fn get_storage(&self, Slot { index, attributes }: Slot) -> PropertyDescriptor {
571 let index = index as usize;
572 let mut builder = PropertyDescriptor::builder()
573 .configurable(attributes.contains(SlotAttributes::CONFIGURABLE))
574 .enumerable(attributes.contains(SlotAttributes::ENUMERABLE));
575 if attributes.is_accessor_descriptor() {
576 if attributes.has_get() {
577 builder = builder.get(self.storage[index].clone());
578 }
579 if attributes.has_set() {
580 builder = builder.set(self.storage[index + 1].clone());
581 }
582 } else {
583 builder = builder.writable(attributes.contains(SlotAttributes::WRITABLE));
584 builder = builder.value(self.storage[index].clone());
585 }
586 builder.build()
587 }
588
589 pub fn insert(&mut self, key: &PropertyKey, property: PropertyDescriptor) -> bool {
591 let mut dummy_slot = Slot::new();
592 self.insert_with_slot(key, property, &mut dummy_slot)
593 }
594
595 pub(crate) fn insert_with_slot(
597 &mut self,
598 key: &PropertyKey,
599 property: PropertyDescriptor,
600 out_slot: &mut Slot,
601 ) -> bool {
602 if let PropertyKey::Index(index) = key {
603 return self.indexed_properties.insert(index.get(), property);
604 }
605
606 let attributes = property.to_slot_attributes();
607
608 if let Some(slot) = self.shape.lookup(key) {
609 let index = slot.index as usize;
610
611 if slot.attributes != attributes {
612 let key = TransitionKey {
613 property_key: key.clone(),
614 attributes,
615 };
616 let transition = self.shape.change_attributes_transition(key);
617 self.shape = transition.shape;
618 match transition.action {
619 ChangeTransitionAction::Nothing => {}
620 ChangeTransitionAction::Remove => {
621 self.storage.remove(slot.index as usize + 1);
622 }
623 ChangeTransitionAction::Insert => {
624 self.storage.insert(index, JsValue::undefined());
626 }
627 }
628 }
629
630 if attributes.is_accessor_descriptor() {
631 if attributes.has_get() {
632 self.storage[index] = property
633 .get()
634 .cloned()
635 .map(JsValue::new)
636 .unwrap_or_default();
637 }
638 if attributes.has_set() {
639 self.storage[index + 1] = property
640 .set()
641 .cloned()
642 .map(JsValue::new)
643 .unwrap_or_default();
644 }
645 } else {
646 self.storage[index] = property.expect_value().clone();
647 }
648 out_slot.index = slot.index;
649 out_slot.attributes =
650 (out_slot.attributes & SlotAttributes::INLINE_CACHE_BITS) | attributes;
651 return true;
652 }
653
654 let transition_key = TransitionKey {
655 property_key: key.clone(),
656 attributes,
657 };
658 self.shape = self.shape.insert_property_transition(transition_key);
659
660 debug_assert_eq!(
662 self.shape.lookup(key),
663 Some(Slot {
664 index: self.storage.len() as u32,
665 attributes
666 })
667 );
668
669 out_slot.index = self.storage.len() as u32;
670 out_slot.attributes =
671 (out_slot.attributes & SlotAttributes::INLINE_CACHE_BITS) | attributes;
672
673 if attributes.is_accessor_descriptor() {
674 self.storage.push(
675 property
676 .get()
677 .cloned()
678 .map(JsValue::new)
679 .unwrap_or_default(),
680 );
681 self.storage.push(
682 property
683 .set()
684 .cloned()
685 .map(JsValue::new)
686 .unwrap_or_default(),
687 );
688 } else {
689 self.storage
690 .push(property.value().cloned().unwrap_or_default());
691 }
692
693 false
694 }
695
696 pub fn remove(&mut self, key: &PropertyKey) -> bool {
698 if let PropertyKey::Index(index) = key {
699 return self.indexed_properties.remove(index.get());
700 }
701 if let Some(slot) = self.shape.lookup(key) {
702 if slot.attributes.is_accessor_descriptor() {
704 self.storage.remove(slot.index as usize + 1);
705 }
706 self.storage.remove(slot.index as usize);
707
708 self.shape = self.shape.remove_property_transition(key);
709 return true;
710 }
711
712 false
713 }
714
715 pub(crate) fn override_indexed_properties(&mut self, properties: ThinVec<JsValue>) {
717 self.indexed_properties = IndexedProperties::DenseElement(properties);
718 }
719
720 pub(crate) fn get_dense_property(&self, index: u32) -> Option<JsValue> {
721 let index = index as usize;
722 match &self.indexed_properties {
723 IndexedProperties::DenseI32(properties) => {
724 properties.get(index).copied().map(JsValue::from)
725 }
726 IndexedProperties::DenseF64(properties) => {
727 properties.get(index).copied().map(JsValue::from)
728 }
729 IndexedProperties::DenseElement(properties) => properties.get(index).cloned(),
730 IndexedProperties::SparseProperty(_) | IndexedProperties::SparseElement(_) => None,
731 }
732 }
733
734 pub(crate) fn set_dense_property(&mut self, index: u32, value: &JsValue) -> bool {
735 let index = index as usize;
736
737 match &mut self.indexed_properties {
738 IndexedProperties::DenseI32(properties) => {
739 let Some(element) = properties.get_mut(index) else {
740 return false;
741 };
742
743 let is_rational_integer = |n: f64| n.to_bits() == f64::from(n as i32).to_bits();
746
747 let value = match value.variant() {
748 JsVariant::Integer32(n) => n,
749 JsVariant::Float64(n) if is_rational_integer(n) => n as i32,
750 JsVariant::Float64(value) => {
751 let mut properties = properties
752 .iter()
753 .copied()
754 .map(f64::from)
755 .collect::<ThinVec<_>>();
756 properties[index] = value;
757 self.indexed_properties = IndexedProperties::DenseF64(properties);
758
759 return true;
760 }
761 _ => {
762 let mut properties = properties
763 .iter()
764 .copied()
765 .map(JsValue::from)
766 .collect::<ThinVec<_>>();
767 properties[index] = value.clone();
768 self.indexed_properties = IndexedProperties::DenseElement(properties);
769
770 return true;
771 }
772 };
773
774 *element = value;
775 true
776 }
777 IndexedProperties::DenseF64(properties) => {
778 let Some(element) = properties.get_mut(index) else {
779 return false;
780 };
781
782 let Some(value) = value.as_number() else {
783 let mut properties = properties
784 .iter()
785 .copied()
786 .map(JsValue::from)
787 .collect::<ThinVec<_>>();
788 properties[index] = value.clone();
789 self.indexed_properties = IndexedProperties::DenseElement(properties);
790 return true;
791 };
792
793 *element = value;
794 true
795 }
796 IndexedProperties::DenseElement(properties) => {
797 let Some(element) = properties.get_mut(index) else {
798 return false;
799 };
800 *element = value.clone();
801 true
802 }
803 IndexedProperties::SparseProperty(_) | IndexedProperties::SparseElement(_) => false,
804 }
805 }
806
807 pub(crate) fn to_dense_indexed_properties(&self) -> Option<ThinVec<JsValue>> {
809 match &self.indexed_properties {
810 IndexedProperties::DenseI32(properties) => {
811 Some(properties.iter().copied().map(JsValue::from).collect())
812 }
813 IndexedProperties::DenseF64(properties) => {
814 Some(properties.iter().copied().map(JsValue::from).collect())
815 }
816 IndexedProperties::DenseElement(properties) => Some(properties.clone()),
817 IndexedProperties::SparseProperty(_) | IndexedProperties::SparseElement(_) => None,
818 }
819 }
820
821 pub(crate) fn dense_indexed_properties_mut(&mut self) -> Option<&mut ThinVec<JsValue>> {
823 if let IndexedProperties::DenseElement(properties) = &mut self.indexed_properties {
824 Some(properties)
825 } else {
826 None
827 }
828 }
829
830 #[inline]
834 #[must_use]
835 pub fn index_properties(&self) -> IndexProperties<'_> {
836 self.indexed_properties.iter()
837 }
838
839 #[inline]
843 #[must_use]
844 pub fn index_property_keys(&self) -> IndexPropertyKeys<'_> {
845 self.indexed_properties.keys()
846 }
847
848 #[inline]
852 #[must_use]
853 pub fn index_property_values(&self) -> IndexPropertyValues<'_> {
854 self.indexed_properties.values()
855 }
856
857 #[inline]
859 #[must_use]
860 pub fn contains_key(&self, key: &PropertyKey) -> bool {
861 if let PropertyKey::Index(index) = key {
862 return self.indexed_properties.contains_key(index.get());
863 }
864 if self.shape.lookup(key).is_some() {
865 return true;
866 }
867
868 false
869 }
870}
871
872#[derive(Debug, Clone)]
874pub enum IndexProperties<'a> {
875 DenseI32(std::iter::Enumerate<std::slice::Iter<'a, i32>>),
877
878 DenseF64(std::iter::Enumerate<std::slice::Iter<'a, f64>>),
880
881 DenseElement(std::iter::Enumerate<std::slice::Iter<'a, JsValue>>),
883
884 SparseElement(hash_map::Iter<'a, u32, JsValue>),
886
887 SparseProperty(hash_map::Iter<'a, u32, PropertyDescriptor>),
889}
890
891impl Iterator for IndexProperties<'_> {
892 type Item = (u32, PropertyDescriptor);
893
894 fn next(&mut self) -> Option<Self::Item> {
895 let (index, value) = match self {
896 Self::DenseI32(vec) => vec
897 .next()
898 .map(|(index, value)| (index, JsValue::from(*value)))?,
899 Self::DenseF64(vec) => vec
900 .next()
901 .map(|(index, value)| (index, JsValue::from(*value)))?,
902 Self::DenseElement(vec) => vec.next().map(|(index, value)| (index, value.clone()))?,
903 Self::SparseProperty(map) => {
904 return map.next().map(|(index, value)| (*index, value.clone()));
905 }
906 Self::SparseElement(map) => map
907 .next()
908 .map(|(index, value)| (*index as usize, value.clone()))?,
909 };
910
911 Some((
912 index as u32,
913 PropertyDescriptorBuilder::new()
914 .writable(true)
915 .configurable(true)
916 .enumerable(true)
917 .value(value.clone())
918 .build(),
919 ))
920 }
921
922 #[inline]
923 fn size_hint(&self) -> (usize, Option<usize>) {
924 match self {
925 Self::DenseI32(vec) => vec.size_hint(),
926 Self::DenseF64(vec) => vec.size_hint(),
927 Self::DenseElement(vec) => vec.size_hint(),
928 Self::SparseProperty(map) => map.size_hint(),
929 Self::SparseElement(map) => map.size_hint(),
930 }
931 }
932}
933
934impl ExactSizeIterator for IndexProperties<'_> {
935 #[inline]
936 fn len(&self) -> usize {
937 match self {
938 Self::DenseI32(vec) => vec.len(),
939 Self::DenseF64(vec) => vec.len(),
940 Self::DenseElement(vec) => vec.len(),
941 Self::SparseProperty(map) => map.len(),
942 Self::SparseElement(map) => map.len(),
943 }
944 }
945}
946
947impl FusedIterator for IndexProperties<'_> {}
948
949#[derive(Debug, Clone)]
951pub enum IndexPropertyKeys<'a> {
952 Dense(std::ops::Range<u32>),
954
955 SparseProperty(hash_map::Keys<'a, u32, PropertyDescriptor>),
957
958 SparseElement(hash_map::Keys<'a, u32, JsValue>),
960}
961
962impl Iterator for IndexPropertyKeys<'_> {
963 type Item = u32;
964
965 #[inline]
966 fn next(&mut self) -> Option<Self::Item> {
967 match self {
968 Self::Dense(vec) => vec.next(),
969 Self::SparseProperty(map) => map.next().copied(),
970 Self::SparseElement(map) => map.next().copied(),
971 }
972 }
973
974 #[inline]
975 fn size_hint(&self) -> (usize, Option<usize>) {
976 match self {
977 Self::Dense(vec) => vec.size_hint(),
978 Self::SparseProperty(map) => map.size_hint(),
979 Self::SparseElement(map) => map.size_hint(),
980 }
981 }
982}
983
984impl ExactSizeIterator for IndexPropertyKeys<'_> {
985 #[inline]
986 fn len(&self) -> usize {
987 match self {
988 Self::Dense(vec) => vec.len(),
989 Self::SparseProperty(map) => map.len(),
990 Self::SparseElement(map) => map.len(),
991 }
992 }
993}
994
995impl FusedIterator for IndexPropertyKeys<'_> {}
996
997#[derive(Debug, Clone)]
999#[allow(variant_size_differences)]
1000pub enum IndexPropertyValues<'a> {
1001 DenseI32(std::slice::Iter<'a, i32>),
1003
1004 DenseF64(std::slice::Iter<'a, f64>),
1006
1007 DenseElement(std::slice::Iter<'a, JsValue>),
1009
1010 SparseProperty(hash_map::Values<'a, u32, PropertyDescriptor>),
1012
1013 SparseElement(hash_map::Values<'a, u32, JsValue>),
1015}
1016
1017impl Iterator for IndexPropertyValues<'_> {
1018 type Item = PropertyDescriptor;
1019
1020 fn next(&mut self) -> Option<Self::Item> {
1021 let value = match self {
1022 Self::DenseI32(vec) => vec.next().copied()?.into(),
1023 Self::DenseF64(vec) => vec.next().copied()?.into(),
1024 Self::DenseElement(vec) => vec.next().cloned()?,
1025 Self::SparseProperty(map) => return map.next().cloned(),
1026 Self::SparseElement(map) => map.next().cloned()?,
1027 };
1028
1029 Some(
1030 PropertyDescriptorBuilder::new()
1031 .writable(true)
1032 .configurable(true)
1033 .enumerable(true)
1034 .value(value)
1035 .build(),
1036 )
1037 }
1038
1039 #[inline]
1040 fn size_hint(&self) -> (usize, Option<usize>) {
1041 match self {
1042 Self::DenseI32(vec) => vec.size_hint(),
1043 Self::DenseF64(vec) => vec.size_hint(),
1044 Self::DenseElement(vec) => vec.size_hint(),
1045 Self::SparseProperty(map) => map.size_hint(),
1046 Self::SparseElement(map) => map.size_hint(),
1047 }
1048 }
1049}
1050
1051impl ExactSizeIterator for IndexPropertyValues<'_> {
1052 #[inline]
1053 fn len(&self) -> usize {
1054 match self {
1055 Self::DenseI32(vec) => vec.len(),
1056 Self::DenseF64(vec) => vec.len(),
1057 Self::DenseElement(vec) => vec.len(),
1058 Self::SparseProperty(map) => map.len(),
1059 Self::SparseElement(map) => map.len(),
1060 }
1061 }
1062}