@@ -20,6 +20,7 @@ use crate::{
2020#[ derive( Debug ) ]
2121pub struct ArrayValue < ' a > {
2222 pub included : Cell < bool > ,
23+ pub trackable : Cell < bool > ,
2324 pub deps : RefCell < DepCollector < ' a > > ,
2425 pub cf_scope : CfScopeId ,
2526 pub elements : RefCell < allocator:: Vec < ' a , Entity < ' a > > > ,
@@ -34,6 +35,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
3435 fn include ( & ' a self , analyzer : & mut Analyzer < ' a > ) {
3536 use_included_flag ! ( self ) ;
3637
38+ self . trackable . set ( false ) ;
3739 self . deps . borrow ( ) . include_all ( analyzer) ;
3840 self . elements . borrow ( ) . include ( analyzer) ;
3941 self . rest . borrow ( ) . include ( analyzer) ;
@@ -55,6 +57,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
5557 return escaped:: unknown_mutate ( analyzer, dep) ;
5658 }
5759
60+ self . trackable . set ( false ) ;
5861 self . deps . borrow_mut ( ) . push ( analyzer. dep ( ( exec_deps, dep) ) ) ;
5962 }
6063
@@ -70,11 +73,11 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
7073
7174 analyzer. track_read ( self . cf_scope , ReadWriteTarget :: Array ( self . array_id ( ) ) , None ) ;
7275
73- if !self . deps . borrow ( ) . is_empty ( ) {
76+ if !self . trackable . get ( ) {
7477 return analyzer. factory . computed_unknown ( ( self , dep, key) ) ;
7578 }
7679
77- let dep = analyzer. dep ( ( dep, key) ) ;
80+ let dep = analyzer. dep ( ( dep, key, self . deps ( analyzer ) ) ) ;
7881 if let Some ( key_literals) = key. get_literals ( analyzer) {
7982 let mut result = analyzer. factory . vec ( ) ;
8083 let mut rest_added = false ;
@@ -132,9 +135,9 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
132135 return escaped:: set_property ( analyzer, dep, key, value) ;
133136 }
134137
135- let mut has_effect = false ;
138+ let deps = analyzer . dep ( ( exec_deps , key ) ) ;
136139 ' known: {
137- if !self . deps . borrow ( ) . is_empty ( ) {
140+ if !self . trackable . get ( ) {
138141 break ' known;
139142 }
140143
@@ -143,44 +146,47 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
143146 } ;
144147
145148 let definite = !non_det && key_literals. len ( ) == 1 ;
149+ let mut has_effect = false ;
146150 let mut rest_added = false ;
147151 for & key_literal in & key_literals {
148152 match key_literal {
149153 LiteralValue :: String ( key_str, _) => {
150154 if let Ok ( index) = key_str. parse :: < usize > ( ) {
151- has_effect = true ;
155+ let value = analyzer . factory . computed ( value , deps ) ;
152156 if let Some ( element) = self . elements . borrow_mut ( ) . get_mut ( index) {
153157 * element = if definite { value } else { analyzer. factory . union ( ( * element, value) ) } ;
154158 } else if !rest_added {
155159 rest_added = true ;
156160 self . rest . borrow_mut ( ) . push ( value) ;
157161 }
158162 } else if key_str == "length" {
159- if let Some ( length) = value. get_literal ( analyzer) . and_then ( |lit| lit. to_number ( ) ) {
160- if let Some ( length) = length. map ( |l| l. 0 . trunc ( ) ) {
161- let length = length as usize ;
162- if length > 1024 {
163- break ' known;
164- }
163+ if let Some ( literal) = value. get_literal ( analyzer)
164+ && let Some ( length) = literal. to_number ( )
165+ {
166+ if length. 0 . is_nan ( ) || length. 0 < 0.0 {
167+ break ' known;
168+ }
169+ let length = length. 0 . trunc ( ) as usize ;
170+ if length > 1024 {
171+ break ' known;
172+ }
165173
166- let mut elements = self . elements . borrow_mut ( ) ;
167- let mut rest = self . rest . borrow_mut ( ) ;
168- if elements. len ( ) > length {
169- has_effect = true ;
170- elements. truncate ( length) ;
171- rest. clear ( ) ;
172- } else if !rest. is_empty ( ) {
173- has_effect = true ;
174- rest. push ( analyzer. factory . undefined ) ;
175- } else if elements. len ( ) < length {
176- has_effect = true ;
177- for _ in elements. len ( ) ..length {
178- elements. push ( analyzer. factory . undefined ) ;
179- }
174+ self . deps . borrow_mut ( ) . push ( analyzer. dep ( value) ) ;
175+
176+ let mut elements = self . elements . borrow_mut ( ) ;
177+ let mut rest = self . rest . borrow_mut ( ) ;
178+ if elements. len ( ) > length {
179+ has_effect = true ;
180+ elements. truncate ( length) ;
181+ rest. clear ( ) ;
182+ } else if !rest. is_empty ( ) {
183+ has_effect = true ;
184+ rest. push ( analyzer. factory . undefined ) ;
185+ } else if elements. len ( ) < length {
186+ has_effect = true ;
187+ for _ in elements. len ( ) ..length {
188+ elements. push ( analyzer. factory . undefined ) ;
180189 }
181- } else {
182- analyzer. throw_builtin_error ( "Invalid array length" ) ;
183- has_effect = analyzer. config . preserve_exceptions ;
184190 }
185191 } else {
186192 has_effect = true ;
@@ -194,15 +200,14 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
194200 }
195201 }
196202 if has_effect {
197- let mut deps = self . deps . borrow_mut ( ) ;
198- deps. push ( analyzer. dep ( ( exec_deps, key) ) ) ;
203+ self . deps . borrow_mut ( ) . push ( deps) ;
199204 }
200205 return ;
201206 }
202207
203208 // Unknown
204- let mut deps = self . deps . borrow_mut ( ) ;
205- deps . push ( analyzer . dep ( ( exec_deps , key , value ) ) ) ;
209+ self . deps . borrow_mut ( ) . push ( analyzer . dep ( ( deps , value ) ) ) ;
210+ self . trackable . set ( false ) ;
206211 }
207212
208213 fn enumerate_properties (
@@ -216,7 +221,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
216221
217222 analyzer. track_read ( self . cf_scope , ReadWriteTarget :: Array ( self . array_id ( ) ) , None ) ;
218223
219- if !self . deps . borrow ( ) . is_empty ( ) {
224+ if !self . trackable . get ( ) {
220225 return EnumeratedProperties {
221226 known : Default :: default ( ) ,
222227 unknown : Some ( analyzer. factory . unknown ) ,
@@ -237,11 +242,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
237242 analyzer. factory . union ( allocator:: Vec :: from_iter_in ( rest. iter ( ) . copied ( ) , analyzer. allocator ) )
238243 } ) ;
239244
240- EnumeratedProperties {
241- known,
242- unknown,
243- dep : analyzer. dep ( ( self . deps . borrow_mut ( ) . collect ( analyzer. factory ) , dep) ) ,
244- }
245+ EnumeratedProperties { known, unknown, dep : analyzer. dep ( ( self . deps ( analyzer) , dep) ) }
245246 }
246247
247248 fn delete_property ( & ' a self , analyzer : & mut Analyzer < ' a > , dep : Dep < ' a > , key : Entity < ' a > ) {
@@ -258,6 +259,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
258259
259260 let mut deps = self . deps . borrow_mut ( ) ;
260261 deps. push ( analyzer. dep ( ( exec_deps, key) ) ) ;
262+ self . trackable . set ( false ) ;
261263 }
262264
263265 fn call (
@@ -297,7 +299,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
297299
298300 analyzer. track_read ( self . cf_scope , ReadWriteTarget :: Array ( self . array_id ( ) ) , None ) ;
299301
300- if !self . deps . borrow ( ) . is_empty ( ) {
302+ if !self . trackable . get ( ) {
301303 return ( vec ! [ ] , Some ( analyzer. factory . unknown ) , analyzer. dep ( ( self , dep) ) ) ;
302304 }
303305
@@ -307,7 +309,7 @@ impl<'a> ValueTrait<'a> for ArrayValue<'a> {
307309 self . rest . borrow ( ) . iter ( ) . copied ( ) ,
308310 analyzer. allocator ,
309311 ) ) ,
310- dep,
312+ analyzer . dep ( ( self . deps ( analyzer ) , dep ) ) ,
311313 )
312314 }
313315
@@ -398,13 +400,18 @@ impl<'a> ArrayValue<'a> {
398400
399401 ( is_exhaustive, non_det, exec_deps)
400402 }
403+
404+ fn deps ( & self , analyzer : & Analyzer < ' a > ) -> Option < Dep < ' a > > {
405+ self . deps . borrow_mut ( ) . collect ( analyzer. factory )
406+ }
401407}
402408
403409impl < ' a > Analyzer < ' a > {
404410 pub fn new_empty_array ( & mut self ) -> & ' a mut ArrayValue < ' a > {
405411 let cf_scope = self . scoping . cf . current_id ( ) ;
406412 self . factory . alloc ( ArrayValue {
407413 included : Cell :: new ( false ) ,
414+ trackable : Cell :: new ( true ) ,
408415 deps : RefCell :: new ( DepCollector :: new ( self . factory . vec ( ) ) ) ,
409416 cf_scope,
410417 elements : RefCell :: new ( self . factory . vec ( ) ) ,
0 commit comments