When expecting a positive integer...

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Apr 9 10:44:15 PDT 2013


On Apr 8, 2013, at 11:05 PM, Domenic Denicola wrote:

> I notice that operations accepting positive integers do various somewhat-inconsistent things as of the latest ES6 spec:
> 
> Various typed array things do `ToPositiveInteger`, a new operation as of ES6:
> 
>  - `ArrayBuffer(length)` and `TypedArray(length)` 
>  - Constructing a typed array, and `TypedArray.prototype.set`, coerce both the passed object's `length` property and the numeric byte-offset argument
>  - Most interestingly, `TypedArray.prototype.@@elementGet(index)` and `@@elementSet(index, value)` do a `ToPositiveInteger` on `index`. So `typedArray[-123] === typedArray[0]`, and `typedArray[-321] = 5` gives `typedArray[0] === 5`.
> 
> Whereas arrays use `ToUint32`, but sometimes throw `RangeError`s:
>  - Indices generally "work" if `ToString(ToUint32(index)) !== index`; otherwise they're treated as ordinary properties.
> - When getting a length from any array-like, you just do `ToUint32` on it.
> - But when setting a length, you validate so that if `ToUint32(length) !== length`, a `RangeError` is thrown.
> 
> Finally, one lone place throws `RangeError`s after conversion:
> 
> - `String.prototype.repeat(count)` throws if `ToInteger(count)` is negative or infinite.
> 
> ---
> 
> I was curious if there were any interesting rationales driving these decisions. (And I fully appreciate there might not be; it could just be compatibility constraints.) Or, to put it another way, I was curious what would be considered "idiomatic" JS, e.g. in the same way that the spec sets a precedent of `ToString`-ing all string inputs to its functions.

Remember this is just a working draft of the specification, and ToPositiveInteger is just a first cut at how to deal with array-like entities that are allowed to be larger than 2^32-2 in length.   I try to remember to include a margin note tagging things like this as open issues, but in this case I guess I didn't. Things like this are the starting points for design discussions like this one so thanks for starting it. 

Since we are entering somewhat uncharted territory WRT arrays, it isn't clear what precedents best apply and what would be most idiomatic. I decided to clamp negative indices to 0 based upon the precedent that Array does a Uint32 transformation of all numeric indices (ie, it transforms all values so they are a bounded, non-negative range) and never throws on "out of bound" accesses. ToPositiveInteger seemed like a reasonable first cut at for something analogous  when dealing with unbounded lengths.

Throwing is another possibility, but one for which there is very little precedent for throwing in such situations. WebIDL says (via its parameter conversion rules) that this is what should happen for negative Typed Array indices, but browsers don't seem to conform to that. 

A better precedent is probably the handling of string indexing which is specified to always returns undefined for negative string indices such as "abcd"[-2].  This also appear to be what at least some browser currently do for Typed Arrays.

Allen











> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 



More information about the es-discuss mailing list