Revision: 13838
Author: [email protected]
Date: Wed Mar 6 05:55:21 2013
Log: ES6 symbols: filter symbols form for-in loops and Object.keys
[email protected]
BUG=v8:2158
Review URL: https://codereview.chromium.org/12455002
http://code.google.com/p/v8/source/detail?r=13838
Modified:
/branches/bleeding_edge/src/handles.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/property-details.h
/branches/bleeding_edge/src/proxy.js
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/v8natives.js
/branches/bleeding_edge/test/mjsunit/harmony/symbols.js
=======================================
--- /branches/bleeding_edge/src/handles.cc Mon Mar 4 07:00:57 2013
+++ /branches/bleeding_edge/src/handles.cc Wed Mar 6 05:55:21 2013
@@ -551,6 +551,7 @@
// Compute the property keys from the interceptor.
+// TODO(rossberg): support symbols in API, and filter here if needed.
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver>
receiver,
Handle<JSObject> object) {
Isolate* isolate = receiver->GetIsolate();
@@ -625,7 +626,7 @@
int len = array->length();
for (int i = 0; i < len; i++) {
Object* e = array->get(i);
- if (!(e->IsName() || e->IsNumber())) return false;
+ if (!(e->IsString() || e->IsNumber())) return false;
}
return true;
}
@@ -754,10 +755,10 @@
// to kInvalidEnumCache, this means that the map itself has never
used the
// present enum cache. The first step to using the cache is to set
the
// enum length of the map by counting the number of own descriptors
that
- // are not DONT_ENUM.
+ // are not DONT_ENUM or SYMBOLIC.
if (own_property_count == Map::kInvalidEnumCache) {
own_property_count = object->map()->NumberOfDescribedProperties(
- OWN_DESCRIPTORS, DONT_ENUM);
+ OWN_DESCRIPTORS, DONT_SHOW);
if (cache_result) object->map()->SetEnumLength(own_property_count);
}
@@ -784,7 +785,7 @@
}
isolate->counters()->enum_cache_misses()->Increment();
- int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS,
DONT_ENUM);
+ int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS,
DONT_SHOW);
Handle<FixedArray> storage =
isolate->factory()->NewFixedArray(num_enum);
Handle<FixedArray> indices =
isolate->factory()->NewFixedArray(num_enum);
@@ -798,9 +799,10 @@
for (int i = 0; i < descs->number_of_descriptors(); i++) {
PropertyDetails details = descs->GetDetails(i);
- if (!details.IsDontEnum()) {
+ Object* key = descs->GetKey(i);
+ if (!(details.IsDontEnum() || key->IsSymbol())) {
if (i < real_size) ++enum_size;
- storage->set(index, descs->GetKey(i));
+ storage->set(index, key);
if (!indices.is_null()) {
if (details.type() != FIELD) {
indices = Handle<FixedArray>();
@@ -860,7 +862,7 @@
isolate->factory()->NewFixedArray(next_enumeration);
storage = Handle<FixedArray>(dictionary->CopyEnumKeysTo(*storage));
- ASSERT(storage->length() ==
object->NumberOfLocalProperties(DONT_ENUM));
+ ASSERT(storage->length() ==
object->NumberOfLocalProperties(DONT_SHOW));
return storage;
}
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Tue Mar 5 09:38:35 2013
+++ /branches/bleeding_edge/src/objects.cc Wed Mar 6 05:55:21 2013
@@ -3513,7 +3513,9 @@
ASSERT(memcmp(Map::cast(fresh)->address(),
Map::cast(result)->address(),
Map::kCodeCacheOffset) == 0);
- int offset = Map::kCodeCacheOffset + kPointerSize;
+ STATIC_ASSERT(Map::kDependentCodeOffset ==
+ Map::kCodeCacheOffset + kPointerSize);
+ int offset = Map::kDependentCodeOffset + kPointerSize;
ASSERT(memcmp(Map::cast(fresh)->address() + offset,
Map::cast(result)->address() + offset,
Map::kSize - offset) == 0);
@@ -4570,7 +4572,10 @@
? descs->number_of_descriptors()
: NumberOfOwnDescriptors();
for (int i = 0; i < limit; i++) {
- if ((descs->GetDetails(i).attributes() & filter) == 0) result++;
+ if ((descs->GetDetails(i).attributes() & filter) == 0 &&
+ ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
+ result++;
+ }
}
return result;
}
@@ -11290,7 +11295,7 @@
if (HasFastProperties()) {
Map* map = this->map();
if (filter == NONE) return map->NumberOfOwnDescriptors();
- if (filter == DONT_ENUM) {
+ if (filter & DONT_ENUM) {
int result = map->EnumLength();
if (result != Map::kInvalidEnumCache) return result;
}
@@ -13324,7 +13329,8 @@
int result = 0;
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
- if (HashTable<Shape, Key>::IsKey(k)) {
+ if (HashTable<Shape, Key>::IsKey(k) &&
+ ((filter & SYMBOLIC) == 0 || !k->IsSymbol())) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
PropertyAttributes attr = details.attributes();
@@ -13379,7 +13385,7 @@
// that are deleted or not enumerable.
for (int i = 0; i < capacity; i++) {
Object* k = KeyAt(i);
- if (IsKey(k)) {
+ if (IsKey(k) && !k->IsSymbol()) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted() || details.IsDontEnum()) continue;
properties++;
=======================================
--- /branches/bleeding_edge/src/property-details.h Thu Nov 22 02:25:22 2012
+++ /branches/bleeding_edge/src/property-details.h Wed Mar 6 05:55:21 2013
@@ -42,6 +42,8 @@
SEALED = DONT_ENUM | DONT_DELETE,
FROZEN = SEALED | READ_ONLY,
+ SYMBOLIC = 8, // Used to filter symbol names
+ DONT_SHOW = DONT_ENUM | SYMBOLIC,
ABSENT = 16 // Used in runtime to indicate a property is
absent.
// ABSENT can never be stored in or returned from a descriptor's
attributes
// bitfield. It is only used as a return value meaning the attributes of
=======================================
--- /branches/bleeding_edge/src/proxy.js Mon Mar 4 08:05:12 2013
+++ /branches/bleeding_edge/src/proxy.js Wed Mar 6 05:55:21 2013
@@ -162,6 +162,7 @@
var enumerableNames = []
for (var i = 0, count = 0; i < names.length; ++i) {
var name = names[i]
+ if (IS_SYMBOL(name)) continue
var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
if (!IS_UNDEFINED(desc) && desc.enumerable) {
enumerableNames[count++] = names[i]
@@ -175,6 +176,7 @@
var enumerableNames = []
for (var i = 0, count = 0; i < names.length; ++i) {
var name = names[i]
+ if (IS_SYMBOL(name)) continue
var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
if (!IS_UNDEFINED(desc) && desc.enumerable) {
enumerableNames[count++] = names[i]
@@ -188,6 +190,6 @@
if (IS_UNDEFINED(handler.enumerate)) {
return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
} else {
- return ToNameArray(handler.enumerate(), "enumerate")
+ return ToNameArray(handler.enumerate(), "enumerate", false)
}
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Mar 5 09:24:08 2013
+++ /branches/bleeding_edge/src/runtime.cc Wed Mar 6 05:55:21 2013
@@ -4890,7 +4890,7 @@
Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
for (int i = 0; i < length; i++) {
Object* entry = contents->get(i);
- if (entry->IsName()) {
+ if (entry->IsString()) {
copy->set(i, entry);
} else {
ASSERT(entry->IsNumber());
=======================================
--- /branches/bleeding_edge/src/v8natives.js Mon Mar 4 08:05:12 2013
+++ /branches/bleeding_edge/src/v8natives.js Wed Mar 6 05:55:21 2013
@@ -346,8 +346,7 @@
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "keys", DerivedKeysTrap);
- // TODO(rossberg): filter non-string keys.
- return ToNameArray(names, "keys");
+ return ToNameArray(names, "keys", false);
}
return %LocalKeys(obj);
}
@@ -983,7 +982,7 @@
// For Harmony proxies
-function ToNameArray(obj, trap) {
+function ToNameArray(obj, trap, includeSymbols) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("proxy_non_object_prop_names", [obj, trap]);
}
@@ -992,6 +991,7 @@
var names = { __proto__: null }; // TODO(rossberg): use sets once ready.
for (var index = 0; index < n; index++) {
var s = ToName(obj[index]);
+ if (IS_SYMBOL(s) && !includeSymbols) continue;
if (%HasLocalProperty(names, s)) {
throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
}
@@ -1011,7 +1011,7 @@
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
- return ToNameArray(names, "getOwnPropertyNames");
+ return ToNameArray(names, "getOwnPropertyNames", true);
}
// Find all the indexed properties.
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/symbols.js Tue Mar 5
09:24:08 2013
+++ /branches/bleeding_edge/test/mjsunit/harmony/symbols.js Wed Mar 6
05:55:21 2013
@@ -178,26 +178,14 @@
function TestKeyEnum(obj) {
- // TODO(rossberg): symbols should not show up at all in for-in.
- var found = [];
- names: for (var name in obj) {
- for (var i in symbols) {
- if (name === symbols[i]) {
- found[i] = true;
- continue names;
- }
- }
- }
- // All even symbols should have been enumerated.
- for (var i = 0; i < symbols.length; i += 2) {
- assertTrue(i in found)
+ for (var name in obj) {
+ assertFalse(%_IsSymbol(name))
}
}
function TestKeyKeys(obj) {
- // TODO(rossberg): symbols should not be returned by Object.keys.
- assertEquals(symbols.length / 2, Object.keys(obj).length)
+ assertEquals(0, Object.keys(obj).length)
assertTrue(symbols.length <= Object.getOwnPropertyNames(obj).length)
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.