Skip to content

Commit 5c012a1

Browse files
committed
Implement Object.getOwnPropertyNames and Object.keys.
JerryScript-DCO-1.0-Signed-off-by: Peter Gal [email protected]
1 parent 89e5444 commit 5c012a1

File tree

5 files changed

+263
-4
lines changed

5 files changed

+263
-4
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-helpers.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "ecma-builtin-helpers.h"
1818

19+
#include "ecma-array-object.h"
1920
#include "ecma-builtins.h"
2021
#include "ecma-conversion.h"
2122
#include "ecma-function-object.h"
@@ -187,6 +188,88 @@ ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /** < t
187188
return ret_value;
188189
} /* ecma_builtin_helper_get_to_locale_string_at_index */
189190

191+
192+
/**
193+
* The Object.keys and Object.getOwnPropertyName routine's common part.
194+
*
195+
* See also:
196+
* ECMA-262 v5, 15.2.3.4 steps 2-5
197+
* ECMA-262 v5, 15.2.3.14 steps 3-6
198+
*
199+
* @return completion value - Array of property names.
200+
* Returned value must be freed with ecma_free_completion_value.
201+
*/
202+
ecma_completion_value_t
203+
ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */
204+
bool only_enumerable_properties) /** < list enumerable properties? */
205+
{
206+
JERRY_ASSERT (obj_p != NULL);
207+
208+
ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
209+
JERRY_ASSERT (ecma_is_completion_value_normal (new_array));
210+
ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
211+
212+
uint32_t index = 0;
213+
214+
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
215+
property_p != NULL;
216+
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p), index++)
217+
{
218+
ecma_string_t *property_name_p;
219+
220+
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
221+
{
222+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
223+
property_p->u.named_data_property.name_p);
224+
}
225+
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
226+
{
227+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
228+
property_p->u.named_accessor_property.name_p);
229+
}
230+
else
231+
{
232+
continue;
233+
}
234+
235+
if (only_enumerable_properties && !ecma_is_property_enumerable (property_p))
236+
{
237+
continue;
238+
}
239+
240+
JERRY_ASSERT (property_name_p != NULL);
241+
242+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
243+
244+
ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor ();
245+
{
246+
item_prop_desc.is_value_defined = true;
247+
item_prop_desc.value = ecma_make_string_value (property_name_p);
248+
249+
item_prop_desc.is_writable_defined = true;
250+
item_prop_desc.is_writable = true;
251+
252+
item_prop_desc.is_enumerable_defined = true;
253+
item_prop_desc.is_enumerable = true;
254+
255+
item_prop_desc.is_configurable_defined = true;
256+
item_prop_desc.is_configurable = true;
257+
}
258+
259+
ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_p,
260+
index_string_p,
261+
&item_prop_desc,
262+
false);
263+
264+
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion));
265+
266+
ecma_free_completion_value (completion);
267+
ecma_deref_ecma_string (index_string_p);
268+
}
269+
270+
return new_array;
271+
} /* ecma_builtin_helper_object_get_properties */
272+
190273
/**
191274
* @}
192275
* @}

jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
extern ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg);
3030
extern ecma_completion_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index);
31+
extern ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj,
32+
bool only_enumerable_properties);
3133

3234
/**
3335
* @}

jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616

1717
#include "ecma-alloc.h"
18+
#include "ecma-array-object.h"
19+
#include "ecma-builtin-helpers.h"
1820
#include "ecma-builtins.h"
1921
#include "ecma-conversion.h"
2022
#include "ecma-exceptions.h"
@@ -128,10 +130,24 @@ ecma_builtin_object_object_get_prototype_of (ecma_value_t this_arg, /**< 'this'
128130
* Returned value must be freed with ecma_free_completion_value.
129131
*/
130132
static ecma_completion_value_t
131-
ecma_builtin_object_object_get_own_property_names (ecma_value_t this_arg, /**< 'this' argument */
133+
ecma_builtin_object_object_get_own_property_names (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
132134
ecma_value_t arg) /**< routine's argument */
133135
{
134-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arg);
136+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
137+
138+
if (!ecma_is_value_object (arg))
139+
{
140+
/* 1. */
141+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
142+
}
143+
else
144+
{
145+
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
146+
/* 2-5. */
147+
ret_value = ecma_builtin_helper_object_get_properties (obj_p, false);
148+
}
149+
150+
return ret_value;
135151
} /* ecma_builtin_object_object_get_own_property_names */
136152

137153
/**
@@ -240,10 +256,24 @@ ecma_builtin_object_object_is_extensible (ecma_value_t this_arg, /**< 'this' arg
240256
* Returned value must be freed with ecma_free_completion_value.
241257
*/
242258
static ecma_completion_value_t
243-
ecma_builtin_object_object_keys (ecma_value_t this_arg, /**< 'this' argument */
259+
ecma_builtin_object_object_keys (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
244260
ecma_value_t arg) /**< routine's argument */
245261
{
246-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arg);
262+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
263+
264+
if (!ecma_is_value_object (arg))
265+
{
266+
/* 1. */
267+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
268+
}
269+
else
270+
{
271+
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
272+
/* 3-6. */
273+
ret_value = ecma_builtin_helper_object_get_properties (obj_p, true);
274+
}
275+
276+
return ret_value;
247277
} /* ecma_builtin_object_object_keys */
248278

249279
/**
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// Test array
17+
var arr = ['a', 'b', 'c'];
18+
var props = Object.getOwnPropertyNames(arr);
19+
// props should contain: 0,1,2,length and the order is not defined!
20+
assert (props.indexOf("0") !== -1);
21+
assert (props.indexOf("1") !== -1);
22+
assert (props.indexOf("2") !== -1);
23+
assert (props.indexOf("length") !== -1);
24+
assert (props.length === 4);
25+
26+
// Test object
27+
var obj = {key1: 'a', key3: 'b', key2: 'c', key4: 'c', key5: ''};
28+
props = Object.getOwnPropertyNames(obj);
29+
// props should contain: key1,key2,key3,key4,key5 and the order is not defined!
30+
assert (props.indexOf("key1") !== -1);
31+
assert (props.indexOf("key2") !== -1);
32+
assert (props.indexOf("key3") !== -1);
33+
assert (props.indexOf("key4") !== -1);
34+
assert (props.indexOf("key5") !== -1);
35+
assert (props.length === 5);
36+
37+
var obj2 = {};
38+
Object.defineProperties(obj2, {
39+
key_one: {enumerable: true, value: 'one'},
40+
key_two: {enumerable: false, value: 'two'},
41+
});
42+
43+
props = Object.getOwnPropertyNames(obj2);
44+
// props should contain: key_one,key_two and the order is not defined!
45+
assert (props.indexOf("key_one") !== -1);
46+
assert (props.indexOf("key_two") !== -1);
47+
assert (props.length === 2);
48+
49+
// Test prototype chain
50+
function Parent() {}
51+
Parent.prototype.inheritedMethod = function() {};
52+
53+
function Child() {
54+
this.prop = 5;
55+
this.method = function() {};
56+
}
57+
Child.prototype = new Parent;
58+
Child.prototype.prototypeMethod = function() {};
59+
60+
props = Object.getOwnPropertyNames (new Child());
61+
// props should contain: prop,method and the order is not defined!
62+
assert (props.indexOf("prop") !== -1);
63+
assert (props.indexOf("method") !== -1);
64+
65+
assert (props.length === 2);
66+
67+
// Test non-object argument
68+
try {
69+
Object.getOwnPrototypeNames("hello");
70+
assert (false);
71+
} catch (e) {
72+
assert (e instanceof TypeError);
73+
}

tests/jerry/object_keys.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// Test array
17+
var arr = ['a', 'b', 'c'];
18+
var props = Object.keys(arr);
19+
// props should contain: 0,1,2 and the order is not defined!
20+
assert (props.indexOf("0") !== -1);
21+
assert (props.indexOf("1") !== -1);
22+
assert (props.indexOf("2") !== -1);
23+
assert (props.length === 3);
24+
25+
// Test object
26+
var obj = {key1: 'a', key3: 'b', key2: 'c', key4: 'c', key5: ''};
27+
props = Object.keys(obj);
28+
// props should contain: key1,key2,key3,key4,key5 and the order is not defined!
29+
assert (props.indexOf("key1") !== -1);
30+
assert (props.indexOf("key2") !== -1);
31+
assert (props.indexOf("key3") !== -1);
32+
assert (props.indexOf("key4") !== -1);
33+
assert (props.indexOf("key5") !== -1);
34+
assert (props.length === 5);
35+
36+
var obj2 = {};
37+
Object.defineProperties(obj2, {
38+
key_one: {enumerable: true, value: 'one'},
39+
key_two: {enumerable: false, value: 'two'},
40+
});
41+
42+
props = Object.keys(obj2);
43+
// props should contain: key_one
44+
assert (props.indexOf("key_one") !== -1);
45+
assert (props.indexOf("key_two") === -1);
46+
assert (props.length === 1);
47+
48+
// Test prototype chain
49+
function Parent() {}
50+
Parent.prototype.inheritedMethod = function() {};
51+
52+
function Child() {
53+
this.prop = 5;
54+
this.method = function() {};
55+
}
56+
Child.prototype = new Parent;
57+
Child.prototype.prototypeMethod = function() {};
58+
59+
props = Object.keys (new Child());
60+
// props should contain: prop,method and the order is not defined!
61+
assert (props.indexOf("prop") !== -1);
62+
assert (props.indexOf("method") !== -1);
63+
assert (props.length === 2);
64+
65+
// Test non-object argument
66+
try {
67+
Object.keys("hello");
68+
assert (false);
69+
} catch (e) {
70+
assert (e instanceof TypeError);
71+
}

0 commit comments

Comments
 (0)