Fix the types of builtin prototype objects (#3663)

In ES2015 many builtin prototypes are no longer valid instances of their
respective classes. This change updates affected prototypes to be
regular objects as required.

JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
This commit is contained in:
Dániel Bátyai
2020-04-06 12:00:58 +02:00
committed by GitHub
parent 73a78bd223
commit 48fa2ec01b
41 changed files with 372 additions and 272 deletions
+15 -10
View File
@@ -2456,6 +2456,19 @@ ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_ERROR_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_STRING_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_NUMBER_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATE_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_MAP_PROTOTYPE)
@@ -2475,9 +2488,6 @@ ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */
#if ENABLED (JERRY_ES2015_BUILTIN_WEAKSET)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_WEAKSET_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_WEAKSET) */
#if ENABLED (JERRY_ES2015)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
@@ -2508,13 +2518,6 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
{
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
#if ENABLED (JERRY_ES2015)
if (ext_object_p->u.class_prop.class_id == LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO)
{
return LIT_MAGIC_STRING_REGEXP_UL;
}
#endif /* ENABLED (JERRY_ES2015) */
return (lit_magic_string_id_t) ext_object_p->u.class_prop.class_id;
}
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
@@ -2600,6 +2603,7 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
return LIT_MAGIC_STRING_JSON_U;
}
#endif /* ENABLED (JERRY_BUILTIN_JSON) */
#if !ENABLED (JERRY_ES2015)
#if ENABLED (JERRY_BUILTIN_ERRORS)
case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
@@ -2612,6 +2616,7 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
{
return LIT_MAGIC_STRING_ERROR_UL;
}
#endif /* !ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
case ECMA_BUILTIN_ID_PROXY:
{
+11 -81
View File
@@ -290,8 +290,9 @@ ecma_op_regexp_alloc (ecma_object_t *ctr_obj_p) /**< constructor object pointer
#endif /* ENABLED (JERRY_ES2015) */
ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) new_object_p;
regexp_obj_p->u.class_prop.u.value = JMEM_CP_NULL;
regexp_obj_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
/* Class id will be initialized after the bytecode is compiled. */
regexp_obj_p->u.class_prop.class_id = LIT_MAGIC_STRING_UNDEFINED;
ecma_value_t status = ecma_builtin_helper_def_prop (new_object_p,
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
@@ -314,21 +315,15 @@ ecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */
{
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) regexp_obj_p;
if (JERRY_UNLIKELY (ext_obj_p->u.class_prop.u.value != JMEM_CP_NULL))
#if !ENABLED (JERRY_ES2015)
if (ext_obj_p->u.class_prop.class_id == LIT_MAGIC_STRING_UNDEFINED)
{
re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
ext_obj_p->u.class_prop.u.value);
ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
#if !ENABLED (JERRY_ES2015)
ecma_regexp_update_props (regexp_obj_p, pattern_str_p, flags);
#endif /* !ENABLED (JERRY_ES2015) */
/* This instance has not been initialized before. */
ecma_regexp_create_props (regexp_obj_p, pattern_str_p, flags);
}
#if !ENABLED (JERRY_ES2015)
else
{
ecma_regexp_create_props (regexp_obj_p, pattern_str_p, flags);
ecma_regexp_update_props (regexp_obj_p, pattern_str_p, flags);
}
#endif /* !ENABLED (JERRY_ES2015) */
@@ -337,6 +332,7 @@ ecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */
JERRY_UNUSED (flags);
#endif /* ENABLED (JERRY_ES2015) */
ext_obj_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
ECMA_SET_INTERNAL_VALUE_POINTER (ext_obj_p->u.class_prop.u.value, bc_p);
} /* ecma_op_regexp_initialize */
@@ -1395,27 +1391,6 @@ ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */
ext_object_p->u.class_prop.u.value);
ecma_regexp_ctx_t re_ctx;
if (bc_p == NULL)
{
#if ENABLED (JERRY_ES2015)
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
#else /* !ENABLED (JERRY_ES2015) */
/* Missing bytecode means the RegExp object is the RegExp.prototype,
* which will always result in an empty string match. */
re_ctx.captures_count = 1;
re_ctx.captures_p = jmem_heap_alloc_block (sizeof (ecma_regexp_capture_t));
re_ctx.captures_p->begin_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING__EMPTY);
re_ctx.captures_p->end_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING__EMPTY);
ret_value = ecma_regexp_create_result_object (&re_ctx, input_string_p, 0);
jmem_heap_free_block (re_ctx.captures_p, sizeof (ecma_regexp_capture_t));
return ret_value;
#endif /* ENABLED (JERRY_ES2015) */
}
re_ctx.flags = bc_p->header.status_flags;
lit_utf8_size_t input_size;
lit_utf8_size_t input_length;
@@ -2100,35 +2075,6 @@ cleanup_string:
const lit_utf8_byte_t *previous_str_p = string_buffer_p;
const lit_utf8_byte_t *const string_end_p = string_buffer_p + string_size;
/* Handle RegExp.prototype separately. */
if (JERRY_UNLIKELY (bc_p == NULL))
{
while (current_str_p < string_end_p)
{
lit_utf8_incr (&current_str_p);
ecma_string_t *str_p = ecma_new_ecma_string_from_utf8 (previous_str_p,
(lit_utf8_size_t) (current_str_p - previous_str_p));
result = ecma_builtin_helper_def_prop_by_index (array_p,
array_length++,
ecma_make_string_value (str_p),
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
JERRY_ASSERT (ecma_is_value_true (result));
ecma_deref_ecma_string (str_p);
if (array_length == limit)
{
result = array;
goto cleanup_buffer;
}
previous_str_p = current_str_p;
}
result = array;
goto cleanup_buffer;
}
ecma_regexp_ctx_t re_ctx;
re_ctx.flags = bc_p->header.status_flags;
ecma_regexp_initialize_context (&re_ctx,
@@ -2241,7 +2187,6 @@ cleanup_array:
ecma_deref_object (array_p);
cleanup_context:
ecma_regexp_cleanup_context (&re_ctx);
cleanup_buffer:
if (string_flags & ECMA_STRING_FLAG_MUST_BE_FREED)
{
jmem_heap_free_block ((void *) string_buffer_p, string_size);
@@ -2541,29 +2486,14 @@ ecma_regexp_replace_helper (ecma_value_t this_arg, /**< this argument */
#if !ENABLED (JERRY_ES2015)
ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) this_obj_p;
const re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
/* In ES5.1 the RegExp prototype object is a valid regexp, but we don't store bytecode for it to save memory.
* Handling this would be very awkward, so we temporarily compile bytecode for it. */
if (ecma_builtin_is (this_obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE))
{
JERRY_ASSERT (bc_p == NULL);
ecma_value_t compile = re_compile_bytecode (&bc_p,
ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP),
RE_FLAG_EMPTY);
JERRY_ASSERT (ecma_is_value_empty (compile));
}
const re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
result = ecma_regexp_replace_helper_fast (&replace_ctx,
bc_p,
string_p,
replace_arg);
if (ecma_builtin_is (this_obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE))
{
ecma_bytecode_deref ((ecma_compiled_code_t *) bc_p);
}
goto cleanup_replace;
#else /* ENABLED (JERRY_ES2015) */
result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_EXEC);