Skip to content

Commit 8a88fc1

Browse files
camillobruniCommit bot
authored andcommitted
[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}
1 parent 1473226 commit 8a88fc1

2 files changed

Lines changed: 72 additions & 9 deletions

File tree

src/runtime/runtime-array.cc

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,14 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
183183
DCHECK(args.length() == 2);
184184
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
185185
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
186+
ElementsKind kind = array->GetElementsKind();
186187

187-
if (array->HasFastStringWrapperElements()) {
188+
if (IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind)) {
189+
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
190+
return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
191+
}
192+
193+
if (kind == FAST_STRING_WRAPPER_ELEMENTS) {
188194
int string_length =
189195
String::cast(Handle<JSValue>::cast(array)->value())->length();
190196
int backing_store_length = array->elements()->length();
@@ -193,16 +199,8 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
193199
static_cast<uint32_t>(Max(string_length, backing_store_length))));
194200
}
195201

196-
if (!array->elements()->IsDictionary()) {
197-
CHECK(array->HasFastSmiOrObjectElements() ||
198-
array->HasFastDoubleElements());
199-
uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
200-
return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
201-
}
202-
203202
KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
204203
ALL_PROPERTIES);
205-
// No need to separate prototype levels since we only get element keys.
206204
for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
207205
!iter.IsAtEnd(); iter.Advance()) {
208206
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||

test/mjsunit/array-sort.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,68 @@ function TestSortOnProxy() {
479479
}
480480
}
481481
TestSortOnProxy();
482+
483+
484+
// Test special prototypes
485+
(function testSortSpecialPrototypes() {
486+
function test(proto, length, expected) {
487+
var result = {
488+
length: length,
489+
__proto__: proto,
490+
};
491+
Array.prototype.sort.call(result);
492+
assertEquals(expected.length, result.length, "result.length");
493+
for (var i = 0; i<expected.length; i++) {
494+
assertEquals(expected[i], result[i], "result["+i+"]");
495+
}
496+
}
497+
498+
(function fast() {
499+
// Fast elements, non-empty
500+
test(arguments, 0, []);
501+
test(arguments, 1, [2]);
502+
test(arguments, 2, [1, 2]);
503+
test(arguments, 4, [1, 2, 3, 4]);
504+
delete arguments[0]
505+
// sort copies down the properties to the receiver, hence result[1]
506+
// is read on the arguments through the hole on the receiver.
507+
test(arguments, 2, [1, 1]);
508+
arguments[0] = undefined;
509+
test(arguments, 2, [1, undefined]);
510+
})(2, 1, 4, 3);
511+
512+
(function fastSloppy(a) {
513+
// Fast sloppy
514+
test(arguments, 0, []);
515+
test(arguments, 1, [2]);
516+
test(arguments, 2, [1, 2]);
517+
delete arguments[0]
518+
test(arguments, 2, [1, 1]);
519+
arguments[0] = undefined;
520+
test(arguments, 2, [1, undefined]);
521+
})(2, 1);
522+
523+
(function fastEmpty() {
524+
test(arguments, 0, []);
525+
test(arguments, 1, [undefined]);
526+
test(arguments, 2, [undefined, undefined]);
527+
})();
528+
529+
(function stringWrapper() {
530+
// cannot redefine string wrapper properties
531+
assertThrows(() => test(new String('cba'), 3, []), TypeError);
532+
})();
533+
534+
(function typedArrys() {
535+
test(new Int32Array(0), 0, []);
536+
test(new Int32Array(1), 1, [0]);
537+
var array = new Int32Array(3);
538+
array[0] = 2;
539+
array[1] = 1;
540+
array[2] = 3;
541+
test(array, 1, [2]);
542+
test(array, 2, [1, 2]);
543+
test(array, 3, [1, 2, 3]);
544+
})()
545+
546+
})();

0 commit comments

Comments
 (0)