-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify String and Array maximum lengths #641
base: main
Are you sure you want to change the base?
Conversation
Firefox appears to have a max length of |
This should be an agenda item, as I'm sure implementers will want to discuss |
Particularly considering the change was requested by an implementer: https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-07/july-28.md#612-stringprototypesplit-its-limit-argument-and-tolength-vs-touint32 |
Just added it to the agenda. |
During development of ES6 a decision was made to extend the specified max length of Strings and Typed Arrays 253-1. The rationale was the 4 gig strings and arrays were likely to become too limiting in a world where address spaces could grow to be thousands of gigabytes. We would have also extended the max length of Array except for the strange legacy 232-1 wrapping behavior of Array property indexing. The fear was that extending the max size of Array (and removing the wrapping) might break some existing code. However, we did decide that most of the Array.prototype methods that are written to operate on generic integer indexed collections (not just Array instances) could safely be rewritten to not have dependencies upon the 232-1 limit or index wrapping. All of this and the trade-offs involved was extensively discussed at TC39 meetings and should be in meeting notes (most likely 2011-2014 timeframe). We really shouldn't want to revert the max size of strings or Typed Arrays/ArrayBuffer. Someday that is going to be a problem and the best way to fix it is to allow for it now, before implementations are running into it as an issue. The real challenge is how to make it possible to extend Array beyond that limit. From that perspective I think we came to the wrong conclusion at the July 2015 meeting WRT split. Remember the only reason that the max length of Array wasn't increased was because of web breakage concerns. But note that part of the rationale TC39 used to justify removing the 232-1 limits within most Array prototype functions was that as of that time, no implementation support Arrays (or strings) of that size, so there could be no legacy usage of those functions that depended upon that size limit. Generally, there is no need to legacy protect code that didn't exist prior to the spec. edition that first makes the change. In the case, of split, there could be no valid legacy code that is dependent upon splitting a string whose length is > 232-1. So how should split be specified to behave in a future where some implementations allow such a limit? The simple and immediate fix (rather than reverting to using ToUint32 on the length) would be to simply throw if split needs to create an array whose length is greater than 232-1. In future code, if it isn't possible to create an Array instance of the necessary size, throwing is the appropriate behavior rather than creating a too short Array that doesn't match the expected results of split. But I think, there is possibly a better solution. Remember, that the only reason we didn't extend the length limit for Array was the fear that removing the wrapping behavior of array indexing would break some legacy code. Maybe there is a way around that legacy trap. What if we allow for two variants of Array instances. Instances that have the 232-1 length limit and which warp indexing and instances that have a 253-1 length limit and don't warp indexing. (Note that both would be considered instances of the Array constructor, share the same prototype etc. The different semantics would be imposed at the MOP level rather than at the class level). Let's distinguish the two kinds of Array instances, let's call them "legacy arrays" and "huge arrays". To maintain legacy compatibility with new Array.huge(len) //len may be aValueGreaterThan2raisedTo32 It should also be possible to say things like: Array.huge.from(anotherPossibleHugeCollection) New ES code that wants to accommodate very large arrays (or use smaller arrays the don't wrap large indices) would use |
Is there actually any data on code intentionally relying on wrapping of On Jul 22, 2016 12:45 PM, "Allen Wirfs-Brock" notifications@github.com
|
This was discussed at past TC39 meetings, but I don't recall whether any actual evidence was presented. Need to search past TC39 meeting notes. |
I’ve found the following old bug about removing the uint32 length restriction on arrays. But it was WONTFIXed without other explanation than "we didn't do that": |
I've tested various ways of attempting to construct an array of out-of-bound length. The results are in the table below. The most interesting cases are in the last two columns, namely the behaviour of the .concat() method. In ECMA262, the RangeError is due to the final step in the respective algorithms, that attempts to set an illegal value to the length of the array. (That final step was accidentally removed in .concat() in ES5, see ecmascript:bug#129, but it was present in ES3 and again in ES6). Without that final step, the length of the array would be stuck to at most 232-1 if I read correctly the spec. Relevant nontrivial section in the spec: the [[DefineOwnProperty]] internal method of Array exotic objects (NB: 0xffffffff = 232-1 = 4294967295.)
So, I think it is feasible to extend array's max length to 253-1. |
Repeating the most interesting columns of the preceding table for easier reading:
|
The legacy concern wasn’t about the cases where such huge arrays might be created. The concern was about what happens when a value greater than 232-2 is used as an array index. In particular, consider: var a = new Array(0); a[Math.pow(2,32)-2]=“x”; a[Math.pow(2,32)]=“x”; This can be happening today. Would changing this behavior (such that array lengths auto updated beyond length 232-1 break anything/ Nobody knows. Allen |
So, what is the risk concretely? I imagine that some rare broken script could get even more broken... But sure, the only way to know is to try. It would be a shame that nobody would want to try. |
Array wrapping sounds useful for tricking a nodejs/iojs server into writing to fields that do not expect user-provided data. Not sure though whether a higher or lower wrap index is more useful, probably depends on how that server reads or calculates the target index number. |
@msaboff should I leave this open or has this proposal been withdrawn since last TC39? |
@bterlson I still think it is an open issue. |
@msaboff What are the next steps for this proposal? |
No example of real code has been provided over years. From the other hand - the longer this change awaits - the higher is the chance for such legacy code to be written, and something important actually depending on this old limitation. |
3d0c24c
to
7a79833
Compare
Currently Strings are defined to consist of up to 253 - 1 elements (See 6.1.4 The String Type). Arrays on the other hand can have up to 232 - 1 indexed elements (See 6.1.7 The Object Type and the definition of array index). Given that there are functions that convert readily between Arrays and Strings, it makes sense that their limits be the same. Another way of looking at this is that a String is an array of elements.