@@ -258,7 +258,8 @@ const PROXY_HANDLERS = {
258258 // Return `true` for indexes which are in bounds.
259259 // e.g. `'0' in arr`.
260260 has ( arr , key ) {
261- if ( isIndex ( key ) ) return key * 1 < getLength ( arr ) ;
261+ const index = toIndex ( key ) ;
262+ if ( index !== null ) return index < getLength ( arr ) ;
262263 return Reflect . has ( arr , key ) ;
263264 } ,
264265
@@ -268,7 +269,8 @@ const PROXY_HANDLERS = {
268269 // They can "unwrap" the proxy by getting `this[ARRAY]`.
269270 if ( key === ARRAY ) return arr ;
270271 if ( key === 'length' ) return getLength ( arr ) ;
271- if ( isIndex ( key ) ) return getElement ( arr , key * 1 ) ;
272+ const index = toIndex ( key ) ;
273+ if ( index !== null ) return getElement ( arr , index ) ;
272274
273275 return Reflect . get ( arr , key ) ;
274276 } ,
@@ -280,8 +282,9 @@ const PROXY_HANDLERS = {
280282 return { value : getLength ( arr ) , writable : true , enumerable : false , configurable : false } ;
281283 }
282284
283- if ( isIndex ( key ) ) {
284- const value = getElement ( arr , key * 1 ) ;
285+ const index = toIndex ( key ) ;
286+ if ( index !== null ) {
287+ const value = getElement ( arr , index ) ;
285288 if ( value === void 0 ) return void 0 ;
286289 // Cannot return `configurable: false` unfortunately
287290 return { value, writable : false , enumerable : true , configurable : true } ;
@@ -298,14 +301,14 @@ const PROXY_HANDLERS = {
298301 // * `Object.defineProperty(arr, 'length', {value: 0})`.
299302 // * Other operations which mutate entries e.g. `arr.push(123)`.
300303 defineProperty ( arr , key , descriptor ) {
301- if ( key === 'length' || isIndex ( key ) ) return false ;
304+ if ( key === 'length' || toIndex ( key ) !== null ) return false ;
302305 return Reflect . defineProperty ( arr , key , descriptor ) ;
303306 } ,
304307
305308 // Prevent deleting entries.
306309 deleteProperty ( arr , key ) {
307310 // Note: `Reflect.deleteProperty(arr, 'length')` already returns `false`
308- if ( isIndex ( key ) ) return false ;
311+ if ( toIndex ( key ) !== null ) return false ;
309312 return Reflect . deleteProperty ( arr , key ) ;
310313 } ,
311314
@@ -322,16 +325,24 @@ const PROXY_HANDLERS = {
322325} ;
323326
324327/**
325- * Check if a key is a valid array index.
328+ * Convert key to array index, if it is a valid array index.
329+ *
326330 * Only strings comprising a plain integer are valid indexes.
327331 * e.g. `"-1"`, `"01"`, `"0xFF"`, `"1e1"`, `"1 "` are not valid indexes.
332+ * Integers >= 4294967295 are not valid indexes.
328333 *
329- * @param {* } - Key used for property lookup.
330- * @returns {boolean } - `true` if `key` is a valid array index.
334+ * @param {string|Symbol } - Key used for property lookup.
335+ * @returns {number|null } - `key` converted to integer, if it's a valid array index, otherwise `null` .
331336 */
332- function isIndex ( key ) {
333- // TODO: Any way to do this without a regex?
334- return typeof key === 'string' && ( key === '0' || INDEX_REGEX . test ( key ) ) ;
337+ function toIndex ( key ) {
338+ if ( typeof key === 'string' ) {
339+ if ( key === '0' ) return 0 ;
340+ if ( INDEX_REGEX . test ( key ) ) {
341+ const index = + key ;
342+ if ( index < 4294967295 ) return index ;
343+ }
344+ }
345+ return null ;
335346}
336347
337348const INDEX_REGEX = / ^ [ 1 - 9 ] \d * $ / ;
0 commit comments