hax/proposal-index-from-end

Behavior of non-index/out-of-range cases

hax opened this issue · 0 comments

hax commented

Basically a[^i] should have very same behavior to a[i] (except it calculate index from the end), but we need to consider how to handle non-index case. For a[i], it just use i as property, or in some cases (eg. TypedArray), it fallback to property semantic for non-index cases. ^i always represent index, so if it failed to calculate index, should it and how it could be fallback to normal property?

Here are the non-index (and out-of-range) cases:

  • a is not an Array-like, ie. Number(a.length) is NaN.
  • i is not a numeric, ie. Number(i) is NaN.
  • i is not an integer
  • i is negative
  • i is greater than a.length
// not Array-like
let x = {0: 0, 1: 1, '-1': -1}
x[^1] // ?
x[^1] = '^1' // what will happen?

// other cases
let x = [1, 2, 3]
let v = "not-numeric" // or 0.5 (not integer), -1 (negative), 10 (> x.length)
x[^v] // ?
x[^v] = "?" // ?

Here are some possible options:

A. Always throw TypeError/RangeError for non-index/out-of-range cases
B. For Get operation, just return undefined, for Set operation, silent failure
C. For Get operation, just return undefined, for Set operation, throw TypeError/RangeError
D. For Get operation, just return undefined, for Set operation, throw TypeError/RangeError in strict mode, silent failure in non-strict mode
E. Same as A in strict mode, same as B in non-strict mode
F. Pure syntax sugar, aka. use the exact semantic of a[a.length - i] (though only access a and a.length once)
G. Use the similar semantic of Array methods (eg. at(), slice())
H. Some other behavior?

My preferences is E = D > A = B = C >> F >> G.

A seems too rigor, F seems too loose (easy to introduce unexpected result or effect, eg. might add NaN property on a in Set case), G is actually not the option, just for comparison.