[es7] implement Object.values() / Object.entries() proposal

BUG=v8:4663
LOG=N
TBR=hpayer@chromium.org
R=ljharb@gmail.com, rossberg@chromium.org, adamk@chromium.org

Review URL: https://codereview.chromium.org/1581033002

Cr-Commit-Position: refs/heads/master@{#33450}
This commit is contained in:
caitpotter88 2016-01-21 19:12:31 -08:00 committed by Commit bot
parent 77df8659c2
commit 677be73e76
7 changed files with 216 additions and 1 deletions

View File

@ -2451,6 +2451,22 @@ void Genesis::InitializeGlobal_harmony_simd() {
}
void Genesis::InitializeGlobal_harmony_object_values_entries() {
if (!FLAG_harmony_object_values_entries) return;
Handle<JSGlobalObject> global(
JSGlobalObject::cast(native_context()->global_object()));
Isolate* isolate = global->GetIsolate();
Factory* factory = isolate->factory();
Handle<JSFunction> object_function = isolate->object_function();
SimpleInstallFunction(object_function, factory->entries_string(),
Builtins::kObjectEntries, 1, false);
SimpleInstallFunction(object_function, factory->values_string(),
Builtins::kObjectValues, 1, false);
}
void Genesis::InstallJSProxyMaps() {
// Allocate the different maps for all Proxy types.
// Next to the default proxy, we need maps indicating callable and
@ -2940,6 +2956,7 @@ bool Genesis::InstallExperimentalNatives() {
static const char* harmony_function_name_natives[] = {nullptr};
static const char* promise_extra_natives[] = {"native promise-extra.js",
nullptr};
static const char* harmony_object_values_entries_natives[] = {nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {

View File

@ -1653,6 +1653,62 @@ BUILTIN(ObjectKeys) {
}
BUILTIN(ObjectValues) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Handle<JSReceiver> receiver;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Object::ToObject(isolate, object));
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
JSReceiver::GetKeys(receiver, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS,
CONVERT_TO_STRING));
for (int i = 0; i < keys->length(); ++i) {
auto key = Handle<Name>::cast(FixedArray::get(keys, i));
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, value, Object::GetPropertyOrElement(receiver, key, STRICT));
keys->set(i, *value);
}
return *isolate->factory()->NewJSArrayWithElements(keys);
}
BUILTIN(ObjectEntries) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Handle<JSReceiver> receiver;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Object::ToObject(isolate, object));
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
JSReceiver::GetKeys(receiver, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS,
CONVERT_TO_STRING));
for (int i = 0; i < keys->length(); ++i) {
auto key = Handle<Name>::cast(FixedArray::get(keys, i));
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, value, Object::GetPropertyOrElement(receiver, key, STRICT));
auto entry_storage = isolate->factory()->NewUninitializedFixedArray(2);
entry_storage->set(0, *key);
entry_storage->set(1, *value);
auto entry = isolate->factory()->NewJSArrayWithElements(entry_storage);
keys->set(i, *entry);
}
return *isolate->factory()->NewJSArrayWithElements(keys);
}
// ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions) {
HandleScope scope(isolate);

View File

@ -116,6 +116,8 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(ObjectIsFrozen, kNone) \
V(ObjectIsSealed, kNone) \
V(ObjectKeys, kNone) \
V(ObjectValues, kNone) \
V(ObjectEntries, kNone) \
V(ObjectPreventExtensions, kNone) \
V(ObjectSeal, kNone) \
V(ObjectProtoToString, kNone) \

View File

@ -206,7 +206,8 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_regexp_subclass, "harmony regexp subclassing") \
V(harmony_species, "harmony Symbol.species")
V(harmony_species, "harmony Symbol.species") \
V(harmony_object_values_entries, "harmony Object.values / Object.entries")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \

View File

@ -247,6 +247,7 @@ namespace internal {
V(done_string, "done") \
V(dot_result_string, ".result") \
V(dot_string, ".") \
V(entries_string, "entries") \
V(enumerable_string, "enumerable") \
V(enumerate_string, "enumerate") \
V(Error_string, "Error") \
@ -328,6 +329,7 @@ namespace internal {
V(undefined_string, "undefined") \
V(undefined_to_string, "[object Undefined]") \
V(valueOf_string, "valueOf") \
V(values_string, "values") \
V(value_string, "value") \
V(WeakMap_string, "WeakMap") \
V(WeakSet_string, "WeakSet") \

View File

@ -0,0 +1,73 @@
// Copyright 2016 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: --harmony-object-values-entries --harmony-proxies --harmony-reflect
function TestMeta() {
assertEquals(1, Object.entries.length);
assertEquals(Function.prototype, Object.getPrototypeOf(Object.entries));
}
TestMeta();
function TestBasic() {
var x = 16;
var O = {
d: 1,
c: 3,
[Symbol.iterator]: void 0,
0: 123,
1000: 456,
[x * x]: "ducks",
[`0x${(x * x).toString(16)}`]: "quack"
};
O.a = 2;
O.b = 4;
Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
assertEquals([
["0", 123],
["256", "ducks"],
["1000", 456],
["d", 1],
["c", 3],
["0x100", "quack"],
["a", 2],
["b", 4]
], Object.entries(O));
assertEquals(Object.entries(O), Object.keys(O).map(key => [key, O[key]]));
}
TestBasic();
function TestOrder() {
var O = {
a: 1,
[Symbol.iterator]: null
};
O[456] = 123;
Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
var log = [];
var P = new Proxy(O, {
ownKeys(target) {
log.push("[[OwnPropertyKeys]]");
return Reflect.ownKeys(target);
},
get(target, name) {
log.push(`[[Get]](${JSON.stringify(name)})`);
return Reflect.get(target, name);
},
set(target, name, value) {
assertUnreachable();
}
});
assertEquals([["456", 123], ["a", 1]], Object.entries(P));
assertEquals([
"[[OwnPropertyKeys]]",
"[[Get]](\"456\")",
"[[Get]](\"a\")"
], log);
}
TestOrder();

View File

@ -0,0 +1,64 @@
// Copyright 2016 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: --harmony-object-values-entries --harmony-proxies --harmony-reflect
function TestMeta() {
assertEquals(1, Object.values.length);
assertEquals(Function.prototype, Object.getPrototypeOf(Object.values));
}
TestMeta();
function TestBasic() {
var x = 16;
var O = {
d: 1,
c: 3,
[Symbol.iterator]: void 0,
0: 123,
1000: 456,
[x * x]: "ducks",
[`0x${(x * x).toString(16)}`]: "quack"
};
O.a = 2;
O.b = 4;
Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
assertEquals([123, "ducks", 456, 1, 3, "quack", 2, 4], Object.values(O));
assertEquals(Object.values(O), Object.keys(O).map(key => O[key]));
}
TestBasic();
function TestOrder() {
var O = {
a: 1,
[Symbol.iterator]: null
};
O[456] = 123;
Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
var log = [];
var P = new Proxy(O, {
ownKeys(target) {
log.push("[[OwnPropertyKeys]]");
return Reflect.ownKeys(target);
},
get(target, name) {
log.push(`[[Get]](${JSON.stringify(name)})`);
return Reflect.get(target, name);
},
set(target, name, value) {
assertUnreachable();
}
});
assertEquals([123, 1], Object.values(P));
assertEquals([
"[[OwnPropertyKeys]]",
"[[Get]](\"456\")",
"[[Get]](\"a\")"
], log);
}
TestOrder();