Fix ElementsKind handling of prototypes in Array.concat
Double elements, typed elements, and sloppy arguments elements were all erroneously marked UNREACHABLE. BUG=chromium:412203 LOG=n R=ulan@chromium.org Review URL: https://codereview.chromium.org/560463002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
bf7b4c12c3
commit
11f7584d0a
@ -10280,8 +10280,19 @@ static void CollectElementIndices(Handle<JSObject> object,
|
||||
}
|
||||
case FAST_HOLEY_DOUBLE_ELEMENTS:
|
||||
case FAST_DOUBLE_ELEMENTS: {
|
||||
// TODO(1810): Decide if it's worthwhile to implement this.
|
||||
UNREACHABLE();
|
||||
if (object->elements()->IsFixedArray()) {
|
||||
DCHECK(object->elements()->length() == 0);
|
||||
break;
|
||||
}
|
||||
Handle<FixedDoubleArray> elements(
|
||||
FixedDoubleArray::cast(object->elements()));
|
||||
uint32_t length = static_cast<uint32_t>(elements->length());
|
||||
if (range < length) length = range;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (!elements->is_the_hole(i)) {
|
||||
indices->Add(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
@ -10301,25 +10312,15 @@ static void CollectElementIndices(Handle<JSObject> object,
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
int dense_elements_length;
|
||||
switch (kind) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case EXTERNAL_##TYPE##_ELEMENTS: { \
|
||||
dense_elements_length = \
|
||||
External##Type##Array::cast(object->elements())->length(); \
|
||||
break; \
|
||||
}
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
||||
case TYPE##_ELEMENTS: \
|
||||
case EXTERNAL_##TYPE##_ELEMENTS:
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
#undef TYPED_ARRAY_CASE
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
dense_elements_length = 0;
|
||||
break;
|
||||
}
|
||||
uint32_t length = static_cast<uint32_t>(dense_elements_length);
|
||||
{
|
||||
uint32_t length = static_cast<uint32_t>(
|
||||
FixedArrayBase::cast(object->elements())->length());
|
||||
if (range <= length) {
|
||||
length = range;
|
||||
// We will add all indices, so we might as well clear it first
|
||||
@ -10332,6 +10333,17 @@ static void CollectElementIndices(Handle<JSObject> object,
|
||||
if (length == range) return; // All indices accounted for already.
|
||||
break;
|
||||
}
|
||||
case SLOPPY_ARGUMENTS_ELEMENTS: {
|
||||
uint32_t length = static_cast<uint32_t>(
|
||||
Handle<JSArray>::cast(object)->length()->Number());
|
||||
ElementsAccessor* accessor = object->GetElementsAccessor();
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
if (accessor->HasElement(object, object, i)) {
|
||||
indices->Add(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PrototypeIterator iter(isolate, object);
|
||||
|
31
test/mjsunit/regress/regress-crbug-412203.js
Normal file
31
test/mjsunit/regress/regress-crbug-412203.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var b = [];
|
||||
b[10000] = 1;
|
||||
// Required to reproduce the bug.
|
||||
assertTrue(%HasDictionaryElements(b));
|
||||
|
||||
var a1 = [1.5];
|
||||
b.__proto__ = a1;
|
||||
assertEquals(1.5, ([].concat(b))[0]);
|
||||
|
||||
var a2 = new Int32Array(2);
|
||||
a2[0] = 3;
|
||||
b.__proto__ = a2
|
||||
assertEquals(3, ([].concat(b))[0]);
|
||||
|
||||
function foo(x, y) {
|
||||
var a = [];
|
||||
a[10000] = 1;
|
||||
assertTrue(%HasDictionaryElements(a));
|
||||
|
||||
a.__proto__ = arguments;
|
||||
var c = [].concat(a);
|
||||
assertEquals(2, c[0]);
|
||||
assertEquals(undefined, c[1]);
|
||||
}
|
||||
foo(2);
|
Loading…
Reference in New Issue
Block a user