Skip to content

Commit 3ec0f9b

Browse files
committed
Implement Object.keys.
JerryScript-DCO-1.0-Signed-off-by: Peter Gal [email protected]
1 parent 9f1c1fd commit 3ec0f9b

File tree

2 files changed

+150
-2
lines changed

2 files changed

+150
-2
lines changed

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

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,87 @@ ecma_builtin_object_object_is_extensible (ecma_value_t this_arg, /**< 'this' arg
317317
* Returned value must be freed with ecma_free_completion_value.
318318
*/
319319
static ecma_completion_value_t
320-
ecma_builtin_object_object_keys (ecma_value_t this_arg, /**< 'this' argument */
320+
ecma_builtin_object_object_keys (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */
321321
ecma_value_t arg) /**< routine's argument */
322322
{
323-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arg);
323+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
324+
325+
if (!ecma_is_value_object (arg))
326+
{
327+
/* 1. */
328+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
329+
}
330+
else
331+
{
332+
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
333+
334+
/* 2. */
335+
ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
336+
ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
337+
338+
/* 4. */
339+
uint32_t index = 0;
340+
341+
/* 5. */
342+
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
343+
property_p != NULL;
344+
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p), index++)
345+
{
346+
if (property_p->type == ECMA_PROPERTY_INTERNAL
347+
|| !ecma_is_property_enumerable (property_p))
348+
{
349+
continue;
350+
}
351+
352+
ecma_string_t *property_name_p;
353+
354+
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
355+
{
356+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
357+
property_p->u.named_data_property.name_p);
358+
}
359+
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
360+
{
361+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
362+
property_p->u.named_accessor_property.name_p);
363+
}
364+
365+
JERRY_ASSERT (property_name_p != NULL);
366+
367+
/* 5.a */
368+
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
369+
370+
ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor ();
371+
{
372+
item_prop_desc.is_value_defined = true;
373+
item_prop_desc.value = ecma_make_string_value (property_name_p);
374+
375+
item_prop_desc.is_writable_defined = true;
376+
item_prop_desc.is_writable = true;
377+
378+
item_prop_desc.is_enumerable_defined = true;
379+
item_prop_desc.is_enumerable = true;
380+
381+
item_prop_desc.is_configurable_defined = true;
382+
item_prop_desc.is_configurable = true;
383+
}
384+
385+
ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_p,
386+
index_string_p,
387+
&item_prop_desc,
388+
false);
389+
390+
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
391+
|| ecma_is_completion_value_normal_false (completion));
392+
393+
ecma_deref_ecma_string (index_string_p);
394+
}
395+
396+
/* 6. */
397+
ret_value = new_array;
398+
}
399+
400+
return ret_value;
324401
} /* ecma_builtin_object_object_keys */
325402

326403
/**

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)