Skip to content

Commit 4598550

Browse files
committed
Disguise accessor properties as data properties
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent c9b1655 commit 4598550

File tree

10 files changed

+453
-18
lines changed

10 files changed

+453
-18
lines changed

jerry-core/api/jerry.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,7 @@ jerry_init_property_descriptor_fields (jerry_property_descriptor_t *prop_desc_p)
30653065
prop_desc_p->is_enumerable = false;
30663066
prop_desc_p->is_configurable_defined = false;
30673067
prop_desc_p->is_configurable = false;
3068+
prop_desc_p->is_data_accessor = false;
30683069
prop_desc_p->is_get_defined = false;
30693070
prop_desc_p->getter = ECMA_VALUE_UNDEFINED;
30703071
prop_desc_p->is_set_defined = false;
@@ -3084,31 +3085,33 @@ jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc
30843085
jerry_property_descriptor_t prop_desc;
30853086
jerry_init_property_descriptor_fields (&prop_desc);
30863087

3087-
if (prop_desc_p->flags & (ECMA_PROP_IS_ENUMERABLE_DEFINED))
3088+
if (prop_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
30883089
{
30893090
prop_desc.is_enumerable_defined = true;
3090-
prop_desc.is_enumerable = prop_desc_p->flags & (ECMA_PROP_IS_ENUMERABLE);
3091+
prop_desc.is_enumerable = (prop_desc_p->flags & ECMA_PROP_IS_ENUMERABLE) != 0;
30913092
}
30923093

3093-
if (prop_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE_DEFINED))
3094+
if (prop_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE_DEFINED)
30943095
{
30953096
prop_desc.is_configurable_defined = true;
3096-
prop_desc.is_configurable = prop_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE);
3097+
prop_desc.is_configurable = (prop_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE) != 0;
30973098
}
30983099

3099-
prop_desc.is_value_defined = prop_desc_p->flags & (ECMA_PROP_IS_VALUE_DEFINED);
3100+
prop_desc.is_value_defined = (prop_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED) != 0;
31003101

31013102
if (prop_desc.is_value_defined)
31023103
{
31033104
prop_desc.value = prop_desc_p->value;
31043105
}
31053106

3106-
if (prop_desc_p->flags & (ECMA_PROP_IS_WRITABLE_DEFINED))
3107+
if (prop_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
31073108
{
31083109
prop_desc.is_writable_defined = true;
3109-
prop_desc.is_writable = prop_desc_p->flags & (ECMA_PROP_IS_WRITABLE);
3110+
prop_desc.is_writable = (prop_desc_p->flags & ECMA_PROP_IS_WRITABLE) != 0;
31103111
}
31113112

3113+
prop_desc.is_data_accessor = (prop_desc_p->flags & ECMA_PROP_IS_DATA_ACCESSOR) != 0;
3114+
31123115
if (prop_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED))
31133116
{
31143117
ecma_value_t getter = ecma_make_object_value (prop_desc_p->get_p);
@@ -3176,6 +3179,11 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_
31763179
: ECMA_PROP_NO_OPTS));
31773180
}
31783181

3182+
if (prop_desc_p->is_data_accessor)
3183+
{
3184+
flags |= ECMA_PROP_IS_DATA_ACCESSOR;
3185+
}
3186+
31793187
/* Copy accessor property info. */
31803188
if (prop_desc_p->is_get_defined)
31813189
{
@@ -3311,6 +3319,8 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val
33113319
prop_desc_p->is_writable_defined = (prop_desc.flags & ECMA_PROP_IS_WRITABLE_DEFINED) != 0;
33123320
prop_desc_p->is_writable = prop_desc_p->is_writable_defined ? (prop_desc.flags & ECMA_PROP_IS_WRITABLE) != 0 : false;
33133321

3322+
prop_desc_p->is_data_accessor = (prop_desc.flags & ECMA_PROP_IS_DATA_ACCESSOR) != 0;
3323+
33143324
prop_desc_p->is_value_defined = (prop_desc.flags & ECMA_PROP_IS_VALUE_DEFINED) != 0;
33153325
prop_desc_p->is_get_defined = (prop_desc.flags & ECMA_PROP_IS_GET_DEFINED) != 0;
33163326
prop_desc_p->is_set_defined = (prop_desc.flags & ECMA_PROP_IS_SET_DEFINED) != 0;

jerry-core/ecma/base/ecma-globals.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ typedef enum
398398
ECMA_PROPERTY_FLAG_CONFIGURABLE = 1u << 2, /**< property is configurable */
399399
ECMA_PROPERTY_FLAG_ENUMERABLE = 1u << 3, /**< property is enumerable */
400400
ECMA_PROPERTY_FLAG_WRITABLE = 1u << 4, /**< property is writable */
401+
ECMA_PROPERTY_FLAG_DATA_ACCESSOR = 1u << 4, /**< property is data accessor */
401402
ECMA_PROPERTY_FLAG_DATA = 1u << 5, /**< property contains data */
402403
} ecma_property_flags_t;
403404

@@ -1155,6 +1156,7 @@ typedef enum
11551156
ECMA_PROP_IS_CONFIGURABLE_DEFINED = (1 << 7), /** Is [[Configurable]] defined? */
11561157
ECMA_PROP_IS_ENUMERABLE_DEFINED = (1 << 8), /** Is [[Enumerable]] defined? */
11571158
ECMA_PROP_IS_WRITABLE_DEFINED = (1 << 9), /** Is [[Writable]] defined? */
1159+
ECMA_PROP_IS_DATA_ACCESSOR = (1 << 10), /** Is data accessor */
11581160
} ecma_property_descriptor_status_flags_t;
11591161

11601162
/**
@@ -1169,7 +1171,6 @@ typedef enum
11691171
*/
11701172
typedef struct
11711173
{
1172-
11731174
/** any combination of ecma_property_descriptor_status_flags_t bits */
11741175
uint16_t flags;
11751176

jerry-core/ecma/base/ecma-helpers.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
548548
JERRY_ASSERT (ecma_is_lexical_environment (object_p)
549549
|| !ecma_op_object_is_fast_array (object_p));
550550
JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
551-
JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0);
551+
JERRY_ASSERT ((prop_attributes & ~(ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE | ECMA_PROPERTY_FLAG_DATA_ACCESSOR)) == 0);
552552

553553
uint8_t type_and_flags = prop_attributes;
554554

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

+25
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,17 @@ ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, /*
725725

726726
if (ecma_is_value_true (status))
727727
{
728+
if (JERRY_UNLIKELY (prop_desc.flags & ECMA_PROP_IS_DATA_ACCESSOR))
729+
{
730+
status = ecma_op_to_data_property (obj_p, &prop_desc);
731+
732+
if (ECMA_IS_VALUE_ERROR (status))
733+
{
734+
ecma_free_property_descriptor (&prop_desc);
735+
return status;
736+
}
737+
}
738+
728739
/* 4. */
729740
ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc);
730741

@@ -786,6 +797,20 @@ ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /
786797

787798
if (ecma_is_value_true (status))
788799
{
800+
if (JERRY_UNLIKELY (prop_desc.flags & ECMA_PROP_IS_DATA_ACCESSOR))
801+
{
802+
status = ecma_op_to_data_property (obj_p, &prop_desc);
803+
804+
if (ECMA_IS_VALUE_ERROR (status))
805+
{
806+
ecma_free_property_descriptor (&prop_desc);
807+
ecma_deref_object (descriptors_p);
808+
ecma_collection_free (prop_names_p);
809+
810+
return status;
811+
}
812+
}
813+
789814
/* 4.b */
790815
ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc);
791816
/* 4.c */

jerry-core/ecma/operations/ecma-conversion.c

+44
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,50 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */
908908
return ret_value;
909909
} /* ecma_op_to_property_descriptor */
910910

911+
/**
912+
* Convert accessor to data property.
913+
*
914+
* @return ECMA_VALUE_EMPTY - if the opertation is successful
915+
* error - otherwise
916+
*/
917+
ecma_value_t
918+
ecma_op_to_data_property (ecma_object_t *object_p, /**< base object */
919+
ecma_property_descriptor_t *prop_desc_p) /**< [in/out] property descriptor */
920+
{
921+
JERRY_ASSERT (prop_desc_p->flags & ECMA_PROP_IS_DATA_ACCESSOR);
922+
923+
ecma_value_t result = ECMA_VALUE_UNDEFINED;
924+
uint16_t flags = prop_desc_p->flags;
925+
926+
if ((flags & ECMA_PROP_IS_GET_DEFINED) && prop_desc_p->get_p != NULL)
927+
{
928+
result = ecma_op_function_call (prop_desc_p->get_p, ecma_make_object_value (object_p), NULL, 0);
929+
930+
if (ECMA_IS_VALUE_ERROR (result))
931+
{
932+
return result;
933+
}
934+
935+
ecma_deref_object (prop_desc_p->get_p);
936+
prop_desc_p->get_p = NULL;
937+
}
938+
939+
if ((flags & ECMA_PROP_IS_SET_DEFINED) && prop_desc_p->set_p != NULL)
940+
{
941+
ecma_deref_object (prop_desc_p->set_p);
942+
prop_desc_p->set_p = NULL;
943+
944+
flags |= ECMA_PROP_IS_WRITABLE;
945+
}
946+
947+
flags |= ECMA_PROP_IS_WRITABLE_DEFINED | ECMA_PROP_IS_VALUE_DEFINED;
948+
flags &= (uint16_t) ~(ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED | ECMA_PROP_IS_DATA_ACCESSOR);
949+
950+
prop_desc_p->value = result;
951+
prop_desc_p->flags = flags;
952+
return ECMA_VALUE_EMPTY;
953+
} /* ecma_op_to_data_property */
954+
911955
/**
912956
* IsInteger operation.
913957
*

jerry-core/ecma/operations/ecma-conversion.h

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, bool p
7272

7373
ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p);
7474
ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, ecma_property_descriptor_t *out_prop_desc_p);
75+
ecma_value_t ecma_op_to_data_property (ecma_object_t *object_p, ecma_property_descriptor_t *prop_desc_p);
7576

7677
/**
7778
* @}

jerry-core/ecma/operations/ecma-objects-general.c

+90-7
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
411411
else
412412
{
413413
/* b. */
414+
if (property_desc_p->flags & ECMA_PROP_IS_DATA_ACCESSOR)
415+
{
416+
prop_attributes |= ECMA_PROPERTY_FLAG_DATA_ACCESSOR;
417+
}
418+
414419
ecma_create_named_accessor_property (object_p,
415420
property_name_p,
416421
property_desc_p->get_p,
@@ -503,15 +508,9 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
503508
}
504509
}
505510
}
506-
else
511+
else if (is_current_configurable)
507512
{
508513
/* 9. */
509-
if (!is_current_configurable)
510-
{
511-
/* a. */
512-
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
513-
}
514-
515514
ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p;
516515

517516
if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR)
@@ -548,6 +547,81 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
548547
prop_flags ^= ECMA_PROPERTY_FLAG_DATA;
549548
*(ext_property_ref.property_p) = prop_flags;
550549
}
550+
else
551+
{
552+
/* Property is non-configurable. */
553+
if ((current_prop & ECMA_PROPERTY_FLAG_DATA)
554+
|| !(current_prop & ECMA_PROPERTY_FLAG_DATA_ACCESSOR))
555+
{
556+
/* a. */
557+
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
558+
}
559+
560+
/* Non-standard extension. */
561+
ecma_getter_setter_pointers_t *getter_setter_pair_p;
562+
getter_setter_pair_p = ecma_get_named_accessor_property (ext_property_ref.property_ref.value_p);
563+
564+
if (getter_setter_pair_p->setter_cp == JMEM_CP_NULL)
565+
{
566+
const uint16_t mask = ECMA_PROP_IS_WRITABLE_DEFINED | ECMA_PROP_IS_WRITABLE;
567+
568+
if ((property_desc_p->flags & mask) == mask)
569+
{
570+
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
571+
}
572+
573+
if (!(property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED))
574+
{
575+
return ECMA_VALUE_TRUE;
576+
}
577+
578+
ecma_value_t result = ECMA_VALUE_UNDEFINED;
579+
580+
if (getter_setter_pair_p->getter_cp != JMEM_CP_NULL)
581+
{
582+
ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, getter_setter_pair_p->getter_cp);
583+
result = ecma_op_function_call (getter_p, ecma_make_object_value (object_p), NULL, 0);
584+
585+
if (ECMA_IS_VALUE_ERROR (result))
586+
{
587+
return result;
588+
}
589+
}
590+
591+
bool same_value = ecma_op_same_value (property_desc_p->value, result);
592+
ecma_free_value (result);
593+
594+
if (!same_value)
595+
{
596+
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
597+
}
598+
return ECMA_VALUE_TRUE;
599+
}
600+
601+
if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
602+
{
603+
ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, getter_setter_pair_p->setter_cp);
604+
605+
ecma_value_t result;
606+
result = ecma_op_function_call (setter_p, ecma_make_object_value (object_p), &property_desc_p->value, 1);
607+
608+
if (ECMA_IS_VALUE_ERROR (result))
609+
{
610+
return result;
611+
}
612+
613+
ecma_free_value (result);
614+
}
615+
616+
/* Because the property is non-configurable, it cannot be modified. */
617+
if ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
618+
&& !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE))
619+
{
620+
getter_setter_pair_p->setter_cp = JMEM_CP_NULL;
621+
}
622+
623+
return ECMA_VALUE_TRUE;
624+
}
551625

552626
/* 12. */
553627
if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA)
@@ -583,6 +657,15 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
583657
ext_property_ref.property_ref.value_p,
584658
property_desc_p->set_p);
585659
}
660+
661+
if (property_desc_p->flags & ECMA_PROP_IS_DATA_ACCESSOR)
662+
{
663+
*ext_property_ref.property_p |= ECMA_PROPERTY_FLAG_DATA_ACCESSOR;
664+
}
665+
else
666+
{
667+
*ext_property_ref.property_p &= (uint8_t) ~ECMA_PROPERTY_FLAG_DATA_ACCESSOR;
668+
}
586669
}
587670

588671
if (property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)

jerry-core/ecma/operations/ecma-objects.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@
6565
* See also:
6666
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
6767
*
68-
* @return pointer to a property - if it exists,
69-
* NULL (i.e. ecma-undefined) - otherwise.
68+
* @return property descriptor - if it exists,
69+
* ECMA_PROPERTY_TYPE_NOT_FOUND / ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP - otherwise.
7070
*/
7171
ecma_property_t
7272
ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
@@ -1913,6 +1913,11 @@ ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the ob
19131913
prop_desc_p->set_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp);
19141914
ecma_ref_object (prop_desc_p->set_p);
19151915
}
1916+
1917+
if (property & ECMA_PROPERTY_FLAG_DATA_ACCESSOR)
1918+
{
1919+
prop_desc_p->flags |= ECMA_PROP_IS_DATA_ACCESSOR;
1920+
}
19161921
}
19171922

19181923
return ECMA_VALUE_TRUE;

jerry-core/include/jerryscript-core.h

+3
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ typedef struct
194194
/** [[Configurable]] */
195195
bool is_configurable;
196196

197+
/** Is data accessor property */
198+
bool is_data_accessor;
199+
197200
/** [[Value]] */
198201
jerry_value_t value;
199202

0 commit comments

Comments
 (0)