Commit ee10b595 authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[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}
parent 271f68ba
......@@ -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++) {
......
......@@ -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) {
......
......@@ -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) \
......
......@@ -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) \
......
This diff is collapsed.
// 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();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment