[esnext] implement Object.getOwnPropertyDescriptors() proposal

BUG=v8:4725
LOG=N
R=adamk@chromium.org, cbruni@chromium.org, rossberg@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#33752}
This commit is contained in:
caitpotter88 2016-02-04 13:56:07 -08:00 committed by Commit bot
parent 271f68ba02
commit ee10b595f9
6 changed files with 396 additions and 134 deletions

View File

@ -2459,6 +2459,19 @@ void Genesis::InitializeGlobal_harmony_object_values_entries() {
Builtins::kObjectValues, 1, false);
}
void Genesis::InitializeGlobal_harmony_object_own_property_descriptors() {
if (!FLAG_harmony_object_own_property_descriptors) 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->getOwnPropertyDescriptors_string(),
Builtins::kObjectGetOwnPropertyDescriptors, 1, false);
}
void Genesis::InstallJSProxyMaps() {
// Allocate the different maps for all Proxy types.
@ -2948,6 +2961,8 @@ bool Genesis::InstallExperimentalNatives() {
static const char* promise_extra_natives[] = {"native promise-extra.js",
nullptr};
static const char* harmony_object_values_entries_natives[] = {nullptr};
static const char* harmony_object_own_property_descriptors_natives[] = {
nullptr};
for (int i = ExperimentalNatives::GetDebuggerCount();
i < ExperimentalNatives::GetBuiltinsCount(); i++) {

View File

@ -1800,6 +1800,43 @@ BUILTIN(ObjectEntries) {
return *isolate->factory()->NewJSArrayWithElements(keys);
}
BUILTIN(ObjectGetOwnPropertyDescriptors) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Handle<Object> undefined = isolate->factory()->undefined_value();
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, OWN_ONLY, ALL_PROPERTIES,
CONVERT_TO_STRING));
Handle<Object> descriptors =
isolate->factory()->NewJSObject(isolate->object_function());
for (int i = 0; i < keys->length(); ++i) {
Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
PropertyDescriptor descriptor;
Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
isolate, receiver, key, &descriptor);
MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
Handle<Object> from_descriptor = did_get_descriptor.FromJust()
? descriptor.ToObject(isolate)
: undefined;
LookupIterator it = LookupIterator::PropertyOrElement(
isolate, descriptors, key, LookupIterator::OWN);
Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
Object::DONT_THROW);
CHECK(success.FromJust());
}
return *descriptors;
}
// ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions) {

View File

@ -118,6 +118,7 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(ObjectKeys, kNone) \
V(ObjectValues, kNone) \
V(ObjectEntries, kNone) \
V(ObjectGetOwnPropertyDescriptors, kNone) \
V(ObjectPreventExtensions, kNone) \
V(ObjectSeal, kNone) \
V(ObjectProtoToString, kNone) \

View File

@ -203,16 +203,18 @@ DEFINE_IMPLICATION(es_staging, harmony_regexp_lookbehind)
DEFINE_IMPLICATION(es_staging, move_object_start)
// Features that are still work in progress (behind individual flags).
#define HARMONY_INPROGRESS(V) \
V(harmony_modules, "harmony modules") \
V(harmony_function_name, "harmony Function name inference") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_tailcalls, "harmony tail calls") \
V(harmony_species, "harmony Symbol.species") \
V(harmony_object_values_entries, "harmony Object.values / Object.entries")
#define HARMONY_INPROGRESS(V) \
V(harmony_modules, "harmony modules") \
V(harmony_function_name, "harmony Function name inference") \
V(harmony_function_sent, "harmony function.sent") \
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
V(harmony_simd, "harmony simd") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_tailcalls, "harmony tail calls") \
V(harmony_species, "harmony Symbol.species") \
V(harmony_object_values_entries, "harmony Object.values / Object.entries") \
V(harmony_object_own_property_descriptors, \
"harmony Object.getOwnPropertyDescriptors()")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \

View File

@ -5,130 +5,131 @@
#ifndef V8_HEAP_SYMBOLS_H_
#define V8_HEAP_SYMBOLS_H_
#define INTERNALIZED_STRING_LIST(V) \
V(anonymous_string, "anonymous") \
V(apply_string, "apply") \
V(assign_string, "assign") \
V(arguments_string, "arguments") \
V(Arguments_string, "Arguments") \
V(Array_string, "Array") \
V(bind_string, "bind") \
V(bool16x8_string, "bool16x8") \
V(Bool16x8_string, "Bool16x8") \
V(bool32x4_string, "bool32x4") \
V(Bool32x4_string, "Bool32x4") \
V(bool8x16_string, "bool8x16") \
V(Bool8x16_string, "Bool8x16") \
V(boolean_string, "boolean") \
V(Boolean_string, "Boolean") \
V(bound__string, "bound ") \
V(byte_length_string, "byteLength") \
V(byte_offset_string, "byteOffset") \
V(call_string, "call") \
V(callee_string, "callee") \
V(caller_string, "caller") \
V(cell_value_string, "%cell_value") \
V(char_at_string, "CharAt") \
V(closure_string, "(closure)") \
V(compare_ic_string, "==") \
V(configurable_string, "configurable") \
V(constructor_string, "constructor") \
V(construct_string, "construct") \
V(create_string, "create") \
V(Date_string, "Date") \
V(default_string, "default") \
V(defineProperty_string, "defineProperty") \
V(deleteProperty_string, "deleteProperty") \
V(display_name_string, "displayName") \
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") \
V(eval_string, "eval") \
V(false_string, "false") \
V(float32x4_string, "float32x4") \
V(Float32x4_string, "Float32x4") \
V(for_api_string, "for_api") \
V(for_string, "for") \
V(function_string, "function") \
V(Function_string, "Function") \
V(Generator_string, "Generator") \
V(getOwnPropertyDescriptor_string, "getOwnPropertyDescriptor") \
V(getPrototypeOf_string, "getPrototypeOf") \
V(get_string, "get") \
V(global_string, "global") \
V(has_string, "has") \
V(illegal_access_string, "illegal access") \
V(illegal_argument_string, "illegal argument") \
V(index_string, "index") \
V(infinity_string, "Infinity") \
V(input_string, "input") \
V(int16x8_string, "int16x8") \
V(Int16x8_string, "Int16x8") \
V(int32x4_string, "int32x4") \
V(Int32x4_string, "Int32x4") \
V(int8x16_string, "int8x16") \
V(Int8x16_string, "Int8x16") \
V(isExtensible_string, "isExtensible") \
V(isView_string, "isView") \
V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
V(last_index_string, "lastIndex") \
V(length_string, "length") \
V(Map_string, "Map") \
V(minus_infinity_string, "-Infinity") \
V(minus_zero_string, "-0") \
V(name_string, "name") \
V(nan_string, "NaN") \
V(next_string, "next") \
V(null_string, "null") \
V(null_to_string, "[object Null]") \
V(number_string, "number") \
V(Number_string, "Number") \
V(object_string, "object") \
V(Object_string, "Object") \
V(ownKeys_string, "ownKeys") \
V(preventExtensions_string, "preventExtensions") \
V(private_api_string, "private_api") \
V(Promise_string, "Promise") \
V(proto_string, "__proto__") \
V(prototype_string, "prototype") \
V(Proxy_string, "Proxy") \
V(query_colon_string, "(?:)") \
V(RegExp_string, "RegExp") \
V(setPrototypeOf_string, "setPrototypeOf") \
V(set_string, "set") \
V(Set_string, "Set") \
V(source_mapping_url_string, "source_mapping_url") \
V(source_string, "source") \
V(source_url_string, "source_url") \
V(stack_string, "stack") \
V(strict_compare_ic_string, "===") \
V(string_string, "string") \
V(String_string, "String") \
V(symbol_string, "symbol") \
V(Symbol_string, "Symbol") \
V(this_string, "this") \
V(throw_string, "throw") \
V(toJSON_string, "toJSON") \
V(toString_string, "toString") \
V(true_string, "true") \
V(uint16x8_string, "uint16x8") \
V(Uint16x8_string, "Uint16x8") \
V(uint32x4_string, "uint32x4") \
V(Uint32x4_string, "Uint32x4") \
V(uint8x16_string, "uint8x16") \
V(Uint8x16_string, "Uint8x16") \
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") \
#define INTERNALIZED_STRING_LIST(V) \
V(anonymous_string, "anonymous") \
V(apply_string, "apply") \
V(assign_string, "assign") \
V(arguments_string, "arguments") \
V(Arguments_string, "Arguments") \
V(Array_string, "Array") \
V(bind_string, "bind") \
V(bool16x8_string, "bool16x8") \
V(Bool16x8_string, "Bool16x8") \
V(bool32x4_string, "bool32x4") \
V(Bool32x4_string, "Bool32x4") \
V(bool8x16_string, "bool8x16") \
V(Bool8x16_string, "Bool8x16") \
V(boolean_string, "boolean") \
V(Boolean_string, "Boolean") \
V(bound__string, "bound ") \
V(byte_length_string, "byteLength") \
V(byte_offset_string, "byteOffset") \
V(call_string, "call") \
V(callee_string, "callee") \
V(caller_string, "caller") \
V(cell_value_string, "%cell_value") \
V(char_at_string, "CharAt") \
V(closure_string, "(closure)") \
V(compare_ic_string, "==") \
V(configurable_string, "configurable") \
V(constructor_string, "constructor") \
V(construct_string, "construct") \
V(create_string, "create") \
V(Date_string, "Date") \
V(default_string, "default") \
V(defineProperty_string, "defineProperty") \
V(deleteProperty_string, "deleteProperty") \
V(display_name_string, "displayName") \
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") \
V(eval_string, "eval") \
V(false_string, "false") \
V(float32x4_string, "float32x4") \
V(Float32x4_string, "Float32x4") \
V(for_api_string, "for_api") \
V(for_string, "for") \
V(function_string, "function") \
V(Function_string, "Function") \
V(Generator_string, "Generator") \
V(getOwnPropertyDescriptor_string, "getOwnPropertyDescriptor") \
V(getOwnPropertyDescriptors_string, "getOwnPropertyDescriptors") \
V(getPrototypeOf_string, "getPrototypeOf") \
V(get_string, "get") \
V(global_string, "global") \
V(has_string, "has") \
V(illegal_access_string, "illegal access") \
V(illegal_argument_string, "illegal argument") \
V(index_string, "index") \
V(infinity_string, "Infinity") \
V(input_string, "input") \
V(int16x8_string, "int16x8") \
V(Int16x8_string, "Int16x8") \
V(int32x4_string, "int32x4") \
V(Int32x4_string, "Int32x4") \
V(int8x16_string, "int8x16") \
V(Int8x16_string, "Int8x16") \
V(isExtensible_string, "isExtensible") \
V(isView_string, "isView") \
V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
V(last_index_string, "lastIndex") \
V(length_string, "length") \
V(Map_string, "Map") \
V(minus_infinity_string, "-Infinity") \
V(minus_zero_string, "-0") \
V(name_string, "name") \
V(nan_string, "NaN") \
V(next_string, "next") \
V(null_string, "null") \
V(null_to_string, "[object Null]") \
V(number_string, "number") \
V(Number_string, "Number") \
V(object_string, "object") \
V(Object_string, "Object") \
V(ownKeys_string, "ownKeys") \
V(preventExtensions_string, "preventExtensions") \
V(private_api_string, "private_api") \
V(Promise_string, "Promise") \
V(proto_string, "__proto__") \
V(prototype_string, "prototype") \
V(Proxy_string, "Proxy") \
V(query_colon_string, "(?:)") \
V(RegExp_string, "RegExp") \
V(setPrototypeOf_string, "setPrototypeOf") \
V(set_string, "set") \
V(Set_string, "Set") \
V(source_mapping_url_string, "source_mapping_url") \
V(source_string, "source") \
V(source_url_string, "source_url") \
V(stack_string, "stack") \
V(strict_compare_ic_string, "===") \
V(string_string, "string") \
V(String_string, "String") \
V(symbol_string, "symbol") \
V(Symbol_string, "Symbol") \
V(this_string, "this") \
V(throw_string, "throw") \
V(toJSON_string, "toJSON") \
V(toString_string, "toString") \
V(true_string, "true") \
V(uint16x8_string, "uint16x8") \
V(Uint16x8_string, "Uint16x8") \
V(uint32x4_string, "uint32x4") \
V(Uint32x4_string, "Uint32x4") \
V(uint8x16_string, "uint8x16") \
V(Uint8x16_string, "Uint8x16") \
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") \
V(writable_string, "writable")
#define PRIVATE_SYMBOL_LIST(V) \

View File

@ -0,0 +1,206 @@
// 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-own-property-descriptors
// Flags: --harmony-proxies --harmony-reflect --allow-natives-syntax
function DataDescriptor(value) {
return { "enumerable": true, "configurable": true, "writable": true, value };
}
function TestMeta() {
assertEquals(1, Object.getOwnPropertyDescriptors.length);
assertEquals(Function.prototype,
Object.getPrototypeOf(Object.getOwnPropertyDescriptors));
assertEquals(
'getOwnPropertyDescriptors', Object.getOwnPropertyDescriptors.name);
var desc = Reflect.getOwnPropertyDescriptor(
Object, 'getOwnPropertyDescriptors');
assertFalse(desc.enumerable);
assertTrue(desc.writable);
assertTrue(desc.configurable);
}
TestMeta();
function TestToObject() {
assertThrows(function() {
Object.getOwnPropertyDescriptors(null);
}, TypeError);
assertThrows(function() {
Object.getOwnPropertyDescriptors(undefined);
}, TypeError);
assertThrows(function() {
Object.getOwnPropertyDescriptors();
}, TypeError);
}
TestToObject();
function TestPrototypeProperties() {
function F() {};
F.prototype.a = "A";
F.prototype.b = "B";
var F2 = new F();
Object.defineProperties(F2, {
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
});
assertEquals({
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
}, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();
function TestPrototypeProperties() {
function F() {};
F.prototype.a = "A";
F.prototype.b = "B";
var F2 = new F();
Object.defineProperties(F2, {
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
});
assertEquals({
"b": {
enumerable: false,
configurable: true,
writable: false,
value: "Shadowed 'B'"
},
"c": {
enumerable: false,
configurable: true,
writable: false,
value: "C"
}
}, Object.getOwnPropertyDescriptors(F2));
}
TestPrototypeProperties();
function TestTypeFilteringAndOrder() {
var log = [];
var sym = Symbol("foo");
var psym = %CreatePrivateSymbol("private");
var O = {
0: 0,
[sym]: 3,
"a": 2,
[psym]: 4,
1: 1,
};
var P = new Proxy(O, {
ownKeys(target) {
log.push("ownKeys()");
return Reflect.ownKeys(target);
},
getOwnPropertyDescriptor(target, name) {
log.push(`getOwnPropertyDescriptor(${String(name)})`);
return Reflect.getOwnPropertyDescriptor(target, name);
},
get(target, name) { assertUnreachable(); },
set(target, name, value) { assertUnreachable(); },
deleteProperty(target, name) { assertUnreachable(); },
defineProperty(target, name, desc) { assertUnreachable(); }
});
var result1 = Object.getOwnPropertyDescriptors(O);
assertEquals({
0: DataDescriptor(0),
1: DataDescriptor(1),
"a": DataDescriptor(2),
[sym]: DataDescriptor(3)
}, result1);
var result2 = Object.getOwnPropertyDescriptors(P);
assertEquals([
"ownKeys()",
"getOwnPropertyDescriptor(0)",
"getOwnPropertyDescriptor(1)",
"getOwnPropertyDescriptor(a)",
"getOwnPropertyDescriptor(Symbol(foo))"
], log);
assertEquals({
0: DataDescriptor(0),
1: DataDescriptor(1),
"a": DataDescriptor(2),
[sym]: DataDescriptor(3)
}, result2);
}
TestTypeFilteringAndOrder();
function TestDuplicateKeys() {
var i = 0;
var log = [];
var P = new Proxy({}, {
ownKeys() {
log.push(`ownKeys()`);
return ["A", "A"];
},
getOwnPropertyDescriptor(t, name) {
log.push(`getOwnPropertyDescriptor(${name})`);
if (i++) return;
return {
configurable: true,
writable: false,
value: "VALUE"
};
},
get(target, name) { assertUnreachable(); },
set(target, name, value) { assertUnreachable(); },
deleteProperty(target, name) { assertUnreachable(); },
defineProperty(target, name, desc) { assertUnreachable(); }
});
var result = Object.getOwnPropertyDescriptors(P);
assertEquals({ "A": undefined }, result);
assertTrue(result.hasOwnProperty("A"));
assertEquals([
"ownKeys()",
"getOwnPropertyDescriptor(A)",
"getOwnPropertyDescriptor(A)"
], log);
}
TestDuplicateKeys();