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

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: 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..dade9c45d56890a9b6f36ef523407355835df068 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -9540,6 +9540,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
}
+static Object* NewSingleInterval(Isolate* isolate, uint32_t length) {
Michael Starzinger 2013/03/22 10:12:20 It is dangerous to have a method returning an unha
adamk 2013/03/22 15:11:18 Fair point. Going back and forth between JS and C+
+ 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,13 +9560,22 @@ 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();
-
+ 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);
+ }
int keys_length = keys->length();
rossberg 2013/03/22 14:22:34 Isn't the filtering below redundant now? You only
adamk 2013/03/22 15:11:18 I thought so too, but a test caught me: still need
rossberg 2013/03/22 17:27:22 Oh dear. Well, since the spec of the function says
adamk 2013/03/22 17:51:34 Added a comment, and a TODO (as I plan to change t
for (int i = 0; i < keys_length; i++) {
Object* key = keys->get(i);
@@ -9571,17 +9589,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
} 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