[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:
parent
77df8659c2
commit
677be73e76
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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) \
|
||||
|
@ -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") \
|
||||
|
73
test/mjsunit/harmony/object-entries.js
Normal file
73
test/mjsunit/harmony/object-entries.js
Normal 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();
|
64
test/mjsunit/harmony/object-values.js
Normal file
64
test/mjsunit/harmony/object-values.js
Normal 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();
|
Loading…
Reference in New Issue
Block a user