55//!
66//! [spec]: https://tc39.es/ecma262/#sec-map-iterator-objects
77
8- use super :: ordered_map:: { MapLock , OrderedMap } ;
8+ use super :: ordered_map:: OrderedMap ;
99use crate :: {
1010 Context , JsData , JsResult ,
1111 builtins:: {
@@ -21,6 +21,22 @@ use crate::{
2121} ;
2222use boa_gc:: { Finalize , Trace } ;
2323
24+ #[ derive( Debug , Trace ) ]
25+ struct MapIteratorLock ( JsObject < OrderedMap < JsValue > > ) ;
26+
27+ impl MapIteratorLock {
28+ fn new ( js_object : JsObject < OrderedMap < JsValue > > ) -> Self {
29+ js_object. borrow_mut ( ) . data_mut ( ) . lock ( ) ;
30+ Self ( js_object)
31+ }
32+ }
33+
34+ impl Finalize for MapIteratorLock {
35+ fn finalize ( & self ) {
36+ self . 0 . borrow_mut ( ) . data_mut ( ) . unlock ( ) ;
37+ }
38+ }
39+
2440/// The Map Iterator object represents an iteration over a map. It implements the iterator protocol.
2541///
2642/// More information:
@@ -29,11 +45,10 @@ use boa_gc::{Finalize, Trace};
2945/// [spec]: https://tc39.es/ecma262/#sec-map-iterator-objects
3046#[ derive( Debug , Finalize , Trace , JsData ) ]
3147pub ( crate ) struct MapIterator {
32- iterated_map : Option < JsObject > ,
33- map_next_index : usize ,
48+ iterated_map : Option < MapIteratorLock > ,
49+ next_index : usize ,
3450 #[ unsafe_ignore_trace]
35- map_iteration_kind : PropertyNameKind ,
36- lock : MapLock ,
51+ iteration_kind : PropertyNameKind ,
3752}
3853
3954impl IntrinsicObject for MapIterator {
@@ -70,30 +85,21 @@ impl MapIterator {
7085 ///
7186 /// [spec]: https://tc39.es/ecma262/#sec-createmapiterator
7287 pub ( crate ) fn create_map_iterator (
73- map : & JsValue ,
88+ map : JsObject < OrderedMap < JsValue > > ,
7489 kind : PropertyNameKind ,
7590 context : & mut Context ,
76- ) -> JsResult < JsValue > {
77- if let Some ( map_obj) = map. as_object ( )
78- && let Some ( mut map) = map_obj. downcast_mut :: < OrderedMap < JsValue > > ( )
79- {
80- let lock = map. lock ( map_obj. clone ( ) ) ;
81- let iter = Self {
82- iterated_map : Some ( map_obj. clone ( ) ) ,
83- map_next_index : 0 ,
84- map_iteration_kind : kind,
85- lock,
86- } ;
87- let map_iterator = JsObject :: from_proto_and_data_with_shared_shape (
88- context. root_shape ( ) ,
89- context. intrinsics ( ) . objects ( ) . iterator_prototypes ( ) . map ( ) ,
90- iter,
91- ) ;
92- return Ok ( map_iterator. into ( ) ) ;
93- }
94- Err ( JsNativeError :: typ ( )
95- . with_message ( "`this` is not a Map" )
96- . into ( ) )
91+ ) -> JsValue {
92+ let iter = Self {
93+ iterated_map : Some ( MapIteratorLock :: new ( map) ) ,
94+ next_index : 0 ,
95+ iteration_kind : kind,
96+ } ;
97+ let map_iterator = JsObject :: from_proto_and_data_with_shared_shape (
98+ context. root_shape ( ) ,
99+ context. intrinsics ( ) . objects ( ) . iterator_prototypes ( ) . map ( ) ,
100+ iter,
101+ ) ;
102+ map_iterator. into ( )
97103 }
98104
99105 /// %MapIteratorPrototype%.next( )
@@ -111,20 +117,19 @@ impl MapIterator {
111117 . and_then ( JsObject :: downcast_mut :: < Self > )
112118 . ok_or_else ( || JsNativeError :: typ ( ) . with_message ( "`this` is not a MapIterator" ) ) ?;
113119
114- let item_kind = map_iterator. map_iteration_kind ;
120+ let item_kind = map_iterator. iteration_kind ;
115121
116122 if let Some ( obj) = map_iterator. iterated_map . take ( ) {
117123 let e = {
118- let entries = obj
119- . downcast_ref :: < OrderedMap < JsValue > > ( )
120- . expect ( "iterator should only iterate maps" ) ;
124+ let mut entries = obj. 0 . borrow_mut ( ) ;
125+ let entries = entries. data_mut ( ) ;
121126 let len = entries. full_len ( ) ;
122127 loop {
123128 let element = entries
124- . get_index ( map_iterator. map_next_index )
129+ . get_index ( map_iterator. next_index )
125130 . map ( |( v, k) | ( v. clone ( ) , k. clone ( ) ) ) ;
126- map_iterator. map_next_index += 1 ;
127- if element. is_some ( ) || map_iterator. map_next_index >= len {
131+ map_iterator. next_index += 1 ;
132+ if element. is_some ( ) || map_iterator. next_index >= len {
128133 break element;
129134 }
130135 }
0 commit comments