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

Clarification requested for interaction between ArraySetLength and Array.protoype.{concat,push,unshift} #1299

Open
Imasius opened this Issue Aug 30, 2018 · 1 comment

Comments

Projects
None yet
3 participants
@Imasius

Imasius commented Aug 30, 2018

Given the following code example:

let xs = [];
xs[2 ** 32 - 2] = 10;

print("Length (before): " + xs.length);
print("xs.unshift(1)");

try {
  xs.unshift(1);
} catch (ex) {
  print(ex);
}

print("Length (after): " + xs.length);
print("xs[0]: " + xs[0]);
print("xs[2 ** 32 - 2]: " + xs[2 ** 32 - 2]);
print("xs[2 ** 32 - 1]: " + xs[2 ** 32 - 1]);

The output of eshost is:

#### Chakra
Length (before): 4294967295
xs.unshift(1)
RangeError: Array length must be assigned a finite positive integer
Length (after): 4294967295
xs[0]: 1
xs[2 ** 32 - 2]: undefined
xs[2 ** 32 - 1]: 10

#### JavaScriptCore
Length (before): 4294967295
xs.unshift(1)
Error: Out of memory
Length (after): 4294967295
xs[0]: undefined
xs[2 ** 32 - 2]: 10
xs[2 ** 32 - 1]: undefined

#### V8
Length (before): 4294967295
xs.unshift(1)
RangeError: Invalid array length
Length (after): 4294967295
xs[0]: 1
xs[2 ** 32 - 2]: undefined
xs[2 ** 32 - 1]: 10

#### V8 --harmony
Length (before): 4294967295
xs.unshift(1)
RangeError: Invalid array length
Length (after): 4294967295
xs[0]: 1
xs[2 ** 32 - 2]: undefined
xs[2 ** 32 - 1]: 10

#### XS
Length (before): 4294967295
xs.unshift(1)
RangeError: ?: invalid length
Length (after): 4294967295
xs[0]: 1
xs[2 ** 32 - 2]: undefined
xs[2 ** 32 - 1]: 10

If we follow the spec, it says that for Array exotic objects we should observe the behavior of "unshift" [1] and then expect a RangeError when the "length" property of the Array is updated [2]. Chakra and V8 behave this way and I suspect SpiderMonkey as well (I killed the process as it was taking too long).

Is this behavior intended? In all other cases the TyperError (for new lengths > 2 ** 53 - 1) is thrown before "unshift" is executed.

[1]: Array.p.unshift
[2]: ArraySetLength

@allenwb

This comment has been minimized.

Show comment
Hide comment
@allenwb

allenwb Aug 30, 2018

Member

Yes, the spec. means what it says. The only specified error for your test case is the RangeError when the length of the ExoticArray is set at the end of the algorithm.

You might take a look at the specification of the equivalent method in ES5.1 https://ecma-international.org/ecma-262/5.1/index.html#sec-15.4.4.13

The intent of the ES2015+ version is that for Array Exotic objects the observable behavior should be exactly as specified in 5.1 (and earlier). The significant change applies for objects that aren't Array exotics. They don't get their length ToUint32 converted. You should run your test using an "array -like" object rather than an Array exotic and see what happens.

Member

allenwb commented Aug 30, 2018

Yes, the spec. means what it says. The only specified error for your test case is the RangeError when the length of the ExoticArray is set at the end of the algorithm.

You might take a look at the specification of the equivalent method in ES5.1 https://ecma-international.org/ecma-262/5.1/index.html#sec-15.4.4.13

The intent of the ES2015+ version is that for Array Exotic objects the observable behavior should be exactly as specified in 5.1 (and earlier). The significant change applies for objects that aren't Array exotics. They don't get their length ToUint32 converted. You should run your test using an "array -like" object rather than an Array exotic and see what happens.

@jmdyck jmdyck added the question label Sep 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment