Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1030)

Unified Diff: src/runtime.cc

Issue 12653010: Fix %GetArrayKeys to not skip non-enumerable indices (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Handle review comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/mjsunit/array-shift.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 38f77d07137eb06acec574d67d409cdfca073cd1..26293e5c6a06aa71c3200653d1fc9af6615cd6cb 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -9540,6 +9540,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
}
+static Handle<Object> NewSingleInterval(Isolate* isolate, uint32_t length) {
+ Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
+ // -1 means start of array.
+ single_interval->set(0, Smi::FromInt(-1));
+ single_interval->set(1, *isolate->factory()->NewNumberFromUint(length));
+ return isolate->factory()->NewJSArrayWithElements(single_interval);
+}
+
+
// Returns an array that tells you where in the [0, length) interval an array
// might have elements. Can either return keys (positive integers) or
// intervals (pair of a negative integer (-start-1) followed by a
@@ -9551,37 +9560,34 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
if (array->elements()->IsDictionary()) {
- // Create an array and get all the keys into it, then remove all the
- // keys that are not integers in the range 0 to length-1.
- bool threw = false;
- Handle<FixedArray> keys =
- GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
- if (threw) return Failure::Exception();
-
- int keys_length = keys->length();
- for (int i = 0; i < keys_length; i++) {
- Object* key = keys->get(i);
- uint32_t index = 0;
- if (!key->ToArrayIndex(&index) || index >= length) {
- // Zap invalid keys.
- keys->set_undefined(i);
+ Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
+ for (Handle<Object> p = array;
+ !p->IsNull();
+ p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
+ if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
+ // Bail out if we find a proxy or interceptor, likely not worth
+ // collecting keys in that case.
+ return *NewSingleInterval(isolate, length);
}
+ Handle<JSObject> current = Handle<JSObject>::cast(p);
+ Handle<FixedArray> current_keys =
+ isolate->factory()->NewFixedArray(
+ current->NumberOfLocalElements(NONE));
+ current->GetLocalElementKeys(*current_keys, NONE);
+ keys = UnionOfKeys(keys, current_keys);
+ }
+ // Erase any keys >= length.
+ // TODO(adamk): Remove this step when the contract of %GetArrayKeys
+ // is changed to let this happen on the JS side.
+ for (int i = 0; i < keys->length(); i++) {
+ if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
}
return *isolate->factory()->NewJSArrayWithElements(keys);
} else {
ASSERT(array->HasFastSmiOrObjectElements() ||
array->HasFastDoubleElements());
- Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
- // -1 means start of array.
- single_interval->set(0, Smi::FromInt(-1));
- FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
- uint32_t actual_length =
- static_cast<uint32_t>(elements->length());
- uint32_t min_length = actual_length < length ? actual_length : length;
- Handle<Object> length_object =
- isolate->factory()->NewNumber(static_cast<double>(min_length));
- single_interval->set(1, *length_object);
- return *isolate->factory()->NewJSArrayWithElements(single_interval);
+ uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+ return *NewSingleInterval(isolate, Min(actual_length, length));
}
}
« no previous file with comments | « no previous file | test/mjsunit/array-shift.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698