Commit 8a88fc14 authored by cbruni's avatar cbruni Committed by Commit bot

[arrays] Fix %GetArrayKeys for special element kinds

Array.prototype.sort would not work properly on sloppy arguments of size > 2.

BUG=chromium:618613

Review-Url: https://codereview.chromium.org/2051413004
Cr-Commit-Position: refs/heads/master@{#36920}
parent 14732265
......@@ -183,8 +183,14 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
ElementsKind kind = array->GetElementsKind();
if (array->HasFastStringWrapperElements()) {
if (IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind)) {
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
}
if (kind == FAST_STRING_WRAPPER_ELEMENTS) {
int string_length =
String::cast(Handle<JSValue>::cast(array)->value())->length();
int backing_store_length = array->elements()->length();
......@@ -193,16 +199,8 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
static_cast<uint32_t>(Max(string_length, backing_store_length))));
}
if (!array->elements()->IsDictionary()) {
CHECK(array->HasFastSmiOrObjectElements() ||
array->HasFastDoubleElements());
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
}
KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
ALL_PROPERTIES);
// No need to separate prototype levels since we only get element keys.
for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
!iter.IsAtEnd(); iter.Advance()) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||
......
......@@ -479,3 +479,68 @@ function TestSortOnProxy() {
}
}
TestSortOnProxy();
// Test special prototypes
(function testSortSpecialPrototypes() {
function test(proto, length, expected) {
var result = {
length: length,
__proto__: proto,
};
Array.prototype.sort.call(result);
assertEquals(expected.length, result.length, "result.length");
for (var i = 0; i<expected.length; i++) {
assertEquals(expected[i], result[i], "result["+i+"]");
}
}
(function fast() {
// Fast elements, non-empty
test(arguments, 0, []);
test(arguments, 1, [2]);
test(arguments, 2, [1, 2]);
test(arguments, 4, [1, 2, 3, 4]);
delete arguments[0]
// sort copies down the properties to the receiver, hence result[1]
// is read on the arguments through the hole on the receiver.
test(arguments, 2, [1, 1]);
arguments[0] = undefined;
test(arguments, 2, [1, undefined]);
})(2, 1, 4, 3);
(function fastSloppy(a) {
// Fast sloppy
test(arguments, 0, []);
test(arguments, 1, [2]);
test(arguments, 2, [1, 2]);
delete arguments[0]
test(arguments, 2, [1, 1]);
arguments[0] = undefined;
test(arguments, 2, [1, undefined]);
})(2, 1);
(function fastEmpty() {
test(arguments, 0, []);
test(arguments, 1, [undefined]);
test(arguments, 2, [undefined, undefined]);
})();
(function stringWrapper() {
// cannot redefine string wrapper properties
assertThrows(() => test(new String('cba'), 3, []), TypeError);
})();
(function typedArrys() {
test(new Int32Array(0), 0, []);
test(new Int32Array(1), 1, [0]);
var array = new Int32Array(3);
array[0] = 2;
array[1] = 1;
array[2] = 3;
test(array, 1, [2]);
test(array, 2, [1, 2]);
test(array, 3, [1, 2, 3]);
})()
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment