From 034b3b63f58dd78c94a971c0fb4bb6283c4f709f Mon Sep 17 00:00:00 2001 From: Roland Takacs <1487864+rtakacs@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:13:18 +0200 Subject: [PATCH] Correct Object.keys to collect only enumerable property names (#3952) In case of Proxy objects, there were no property descriptor checks when collecting enumerable properties. Therefore, all the non-enumerable Proxy.target properties were listed as well. JerryScript-DCO-1.0-Signed-off-by: Roland Takacs rtakacs@inf.u-szeged.hu --- jerry-core/ecma/operations/ecma-objects.c | 31 ++++++++++++++++++++++- tests/jerry/es.next/proxy_own_keys.js | 20 ++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 4e8331788..60d51068a 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -2064,7 +2064,36 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ } else if (!prop_is_symbol && (opts & ECMA_LIST_SYMBOLS_ONLY) == 0) { - ecma_collection_push_back (return_keys, entry); + if ((opts & ECMA_LIST_ENUMERABLE) == 0) + { + ecma_collection_push_back (return_keys, entry); + } + else + { + ecma_property_descriptor_t prop_desc; + ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + + if (ECMA_IS_VALUE_ERROR (status)) + { + ecma_collection_destroy (proxy_keys); + + return NULL; + } + + if ((prop_desc.flags & ECMA_PROP_IS_ENUMERABLE) == 0) + { + ecma_deref_ecma_string (prop_name_p); + } + else + { + ecma_collection_push_back (return_keys, entry); + } + + if (ecma_is_value_true (status)) + { + ecma_free_property_descriptor (&prop_desc); + } + } } else { diff --git a/tests/jerry/es.next/proxy_own_keys.js b/tests/jerry/es.next/proxy_own_keys.js index 9c2f03804..00daae4cc 100644 --- a/tests/jerry/es.next/proxy_own_keys.js +++ b/tests/jerry/es.next/proxy_own_keys.js @@ -78,7 +78,7 @@ var proxy = new Proxy(target, handler); array_check(Reflect.ownKeys(proxy), ["foo", "bar", symA]); array_check(Object.getOwnPropertyNames(proxy), ["foo", "bar"]); -array_check(Object.keys(proxy), ["foo", "bar"]); +array_check(Object.keys(proxy), []); array_check(Object.getOwnPropertySymbols(proxy), [symA]); handler.ownKeys = function(target) {return Object.getOwnPropertyNames(target);}; @@ -223,3 +223,21 @@ try { } catch (e) { assert(e instanceof TypeError); } + +var object = {}; +Object.defineProperties(object, { + a: { value: 42, enumerable: false }, + b: { value: "foo", enumerable: true }, + c: { value: "bar", enumerable: false } +}); + +var handler = { + ownKeys(target) { + return Reflect.ownKeys(target); + } +}; + +var proxy = new Proxy(object, handler); + +assert(Object.keys(proxy).length === 1); +assert(Object.keys(proxy)[0] === "b");