Skip to content

Commit 1193de8

Browse files
committed
Use [[DefineOwnProperty]] in Array builtins where necessary.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai [email protected]
1 parent 8cd1ade commit 1193de8

File tree

7 files changed

+125
-38
lines changed

7 files changed

+125
-38
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -895,15 +895,18 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar
895895
ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value);
896896

897897
ecma_string_t *to_idx_str_p = ecma_new_ecma_string_from_uint32 (n);
898-
/*
899-
* 10.c.ii
900-
* Using [[Put]] is equivalent to using [[DefineOwnProperty]] as specified the standard,
901-
* so we use [[Put]] instead for simplicity. No need for a try-catch block since it is called
902-
* with is_throw = false.
903-
*/
904-
ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p, to_idx_str_p, get_value, false);
905-
JERRY_ASSERT (ecma_is_completion_value_normal (put_comp_value));
906-
ecma_free_completion_value (put_comp_value);
898+
899+
/* 10.c.ii */
900+
/* This will always be a simple value since 'is_throw' is false, so no need to free. */
901+
ecma_completion_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p,
902+
to_idx_str_p,
903+
get_value,
904+
true, /* Writable */
905+
true, /* Enumerable */
906+
true, /* Configurable */
907+
false);
908+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
909+
907910
ecma_deref_ecma_string (to_idx_str_p);
908911

909912
ECMA_FINALIZE (get_value);
@@ -1477,16 +1480,17 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg
14771480

14781481
ecma_string_t *idx_str_new_p = ecma_new_ecma_string_from_uint32 (k);
14791482

1480-
/* 9.c.ii
1481-
* Using [[Put]] is equivalent to using [[DefineOwnProperty]] as specified the standard,
1482-
* so we use [[Put]] instead for simplicity. No need for a try-catch block since it is called
1483-
* with is_throw = false.
1484-
*/
1485-
ECMA_TRY_CATCH (put_value,
1486-
ecma_op_object_put (new_array_p, idx_str_new_p, get_value, false),
1487-
ret_value);
1483+
/* 9.c.ii */
1484+
/* This will always be a simple value since 'is_throw' is false, so no need to free. */
1485+
ecma_completion_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p,
1486+
idx_str_new_p,
1487+
get_value,
1488+
true, /* Writable */
1489+
true, /* Enumerable */
1490+
true, /* Configurable */
1491+
false);
1492+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
14881493

1489-
ECMA_FINALIZE (put_value);
14901494
ecma_deref_ecma_string (idx_str_new_p);
14911495
ECMA_FINALIZE (get_value);
14921496
}
@@ -2365,15 +2369,16 @@ ecma_builtin_array_prototype_object_map (ecma_value_t this_arg, /**< this argume
23652369

23662370
ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value);
23672371

2368-
/* 8.c.iii
2369-
* By definition we should use [[DefineOwnProperty]] here, but since [[Put]] will create the
2370-
* same property that we need, we can use it for simplicity. No need for a try-catch block
2371-
* since it is called with is_throw = false.
2372-
* ecma_op_to_boolean always returns a simple value, so no need to free.
2373-
*/
2374-
ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p, index_str_p, mapped_value, false);
2375-
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp_value));
2376-
ecma_free_completion_value (put_comp_value);
2372+
/* 8.c.iii */
2373+
/* This will always be a simple value since 'is_throw' is false, so no need to free. */
2374+
ecma_completion_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p,
2375+
index_str_p,
2376+
mapped_value,
2377+
true, /* Writable */
2378+
true, /* Enumerable */
2379+
true, /* Configurable */
2380+
false);
2381+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
23772382

23782383
ECMA_FINALIZE (mapped_value);
23792384
ECMA_FINALIZE (current_value);
@@ -2486,17 +2491,16 @@ ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this arg
24862491
if (ecma_is_completion_value_normal_true (ecma_op_to_boolean (call_value)))
24872492
{
24882493
ecma_string_t *to_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index);
2489-
/*
2490-
* By definition we should use [[DefineOwnProperty]] here, but since [[Put]] will create the
2491-
* same property that we need, we can use it for simplicity. No need for a try-catch block
2492-
* since it is called with is_throw = false.
2493-
*/
2494-
ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p,
2495-
to_index_string_p,
2496-
get_value,
2497-
false);
2498-
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp_value));
2499-
ecma_free_completion_value (put_comp_value);
2494+
2495+
/* This will always be a simple value since 'is_throw' is false, so no need to free. */
2496+
ecma_completion_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p,
2497+
to_index_string_p,
2498+
get_value,
2499+
true, /* Writable */
2500+
true, /* Enumerable */
2501+
true, /* Configurable */
2502+
false);
2503+
JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp));
25002504

25012505
ecma_deref_ecma_string (to_index_string_p);
25022506
new_array_index++;

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,54 @@ ecma_builtin_helper_string_index_normalize (ecma_number_t index, /**< index */
505505
return norm_index;
506506
} /* ecma_builtin_helper_string_index_normalize */
507507

508+
/**
509+
* Helper function for using [[DefineOwnProperty]].
510+
*
511+
* See also:
512+
* ECMA-262 v5, 8.12.9
513+
* ECMA-262 v5, 15.4.5.1
514+
*
515+
* @return completion value
516+
* Returned value must be freed with ecma_free_completion_value.
517+
*/
518+
ecma_completion_value_t
519+
ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */
520+
ecma_string_t *index_p, /**< index string */
521+
ecma_value_t value, /**< value */
522+
bool writable, /**< writable */
523+
bool enumerable, /**< enumerable */
524+
bool configurable, /**< configurable */
525+
bool is_throw) /**< is_throw */
526+
{
527+
ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
528+
529+
prop_desc.is_value_defined = true;
530+
prop_desc.value = value;
531+
532+
if (writable)
533+
{
534+
prop_desc.is_writable_defined = true;
535+
prop_desc.is_writable = true;
536+
}
537+
538+
if (enumerable)
539+
{
540+
prop_desc.is_enumerable_defined = true;
541+
prop_desc.is_enumerable = true;
542+
}
543+
544+
if (configurable)
545+
{
546+
prop_desc.is_configurable_defined = true;
547+
prop_desc.is_configurable = true;
548+
}
549+
550+
return ecma_op_object_define_own_property (obj_p,
551+
index_p,
552+
&prop_desc,
553+
is_throw);
554+
} /* ecma_builtin_helper_def_prop */
555+
508556
/**
509557
* @}
510558
* @}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ extern ecma_completion_value_t ecma_builtin_helper_array_concat_value (ecma_obje
3535
ecma_value_t);
3636
extern uint32_t ecma_builtin_helper_array_index_normalize (ecma_number_t index, uint32_t length);
3737
extern uint32_t ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length);
38+
extern ecma_completion_value_t ecma_builtin_helper_def_prop (ecma_object_t *obj_p,
39+
ecma_string_t *index_p,
40+
ecma_value_t value,
41+
bool writable,
42+
bool enumerable,
43+
bool configurable,
44+
bool is_throw);
3845

3946
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN
4047

tests/jerry/array-prototype-filter.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ assert(filtered[1] === 3);
4444
assert(filtered[2] === 5);
4545
assert(filtered[3] === 7);
4646

47+
var arr = [1,2];
48+
Array.prototype[0] = 3;
49+
var newArr = arr.filter(function() { return true; });
50+
delete Array.prototype[0];
51+
assert(newArr.hasOwnProperty("0"));
52+
assert(newArr[0] === 1);
53+
4754
// Checking behavior when unable to get length
4855
var obj = {};
4956
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });

tests/jerry/array-prototype-map.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ assert (long_array.map(func).equals([0,2]));
6262
long_array[100] = 1;
6363
assert (long_array.map(func).equals([0,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,101]));
6464

65+
var arr = [1,2];
66+
Array.prototype[0] = 3;
67+
var newArr = arr.map(function(value) { return value; });
68+
delete Array.prototype[0];
69+
assert(newArr.hasOwnProperty("0"));
70+
assert(newArr[0] === 1);
71+
6572
// check behavior when unable to get length
6673
var obj = {};
6774
Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } });

tests/jerry/array-prototype-slice.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ array[4294967293] = "bar";
7979
var result = array.slice(-4294967297, -4294967296);
8080
assert(result.length === 0);
8181

82+
var arr = [1,2];
83+
Array.prototype[0] = 3;
84+
var newArr = arr.slice(0, 1);
85+
delete Array.prototype[0];
86+
assert(newArr.hasOwnProperty("0"));
87+
assert(newArr[0] === 1);
88+
8289
// Checking behavior when unable to get length
8390
var obj = { slice : Array.prototype.slice };
8491
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });

tests/jerry/array-prototype-splice.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ assert(result.length === 1)
144144
assert(result[0] === "bar")
145145
assert(array[0] === "y")
146146

147+
var arr = [1,2];
148+
Array.prototype[0] = 3;
149+
var newArr = arr.splice(0, 1);
150+
delete Array.prototype[0];
151+
assert(newArr.hasOwnProperty("0"));
152+
assert(newArr[0] === 1);
153+
147154
// Checking behavior when unable to get length
148155
var obj = {splice : Array.prototype.splice};
149156
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });

0 commit comments

Comments
 (0)