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
@@ -616,12 +616,10 @@ ecma_builtin_date_prototype_dispatch_routine (uint16_t builtin_routine_id, /**<
if (!ecma_is_value_object (this_arg)
|| !ecma_object_class_is (ecma_get_object_from_value (this_arg), LIT_MAGIC_STRING_DATE_UL))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Date object expected"));
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a Date object"));
}
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) ecma_get_object_from_value (this_arg);
ecma_number_t *prim_value_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t,
ext_object_p->u.class_prop.u.value);
@@ -60,23 +60,17 @@ static ecma_value_t
ecma_builtin_regexp_prototype_flags_helper (ecma_value_t this, /**< this value */
uint16_t *flags_p) /**< [out] flags */
{
ecma_extended_object_t *ext_obj_p = ecma_op_check_object_type_is_class (this);
if (ext_obj_p != NULL)
if (!ecma_object_is_regexp_object (this))
{
if (ext_obj_p->u.class_prop.class_id == LIT_MAGIC_STRING_REGEXP_UL
|| ext_obj_p->u.class_prop.class_id == LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO)
{
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
ext_obj_p->u.class_prop.u.value);
*flags_p = bc_p->header.status_flags;
return ECMA_VALUE_EMPTY;
}
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
}
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (this);
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
*flags_p = bc_p->header.status_flags;
return ECMA_VALUE_EMPTY;
} /* ecma_builtin_regexp_prototype_flags_helper */
/**
@@ -222,21 +216,16 @@ ecma_op_escape_regexp_pattern (ecma_string_t *pattern_str_p) /**< RegExp pattern
static ecma_value_t
ecma_builtin_regexp_prototype_get_source (ecma_value_t this_arg) /**< this argument */
{
ecma_extended_object_t *ext_obj_p = ecma_op_check_object_type_is_class (this_arg);
if (ext_obj_p != NULL)
if (!ecma_object_is_regexp_object (this_arg))
{
if (ext_obj_p->u.class_prop.class_id == LIT_MAGIC_STRING_REGEXP_UL
|| ext_obj_p->u.class_prop.class_id == LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO)
{
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
ext_obj_p->u.class_prop.u.value);
return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source));
}
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
}
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (this_arg);
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source));
} /* ecma_builtin_regexp_prototype_get_source */
/**
@@ -389,11 +378,13 @@ ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument
#endif /* !ENABLED (JERRY_ES2015) */
)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not a RegExp object"));
}
ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg);
ecma_ref_object (this_obj_p);
ecma_extended_object_t *regexp_obj_p = (ecma_extended_object_t *) this_obj_p;
re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
regexp_obj_p->u.class_prop.u.value);
ecma_value_t status = ecma_builtin_helper_def_prop (this_obj_p,
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
@@ -406,7 +397,6 @@ ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument
{
if (!ecma_is_value_undefined (flags_arg))
{
ecma_deref_object (this_obj_p);
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument"));
}
@@ -414,14 +404,19 @@ ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
pattern_obj_p->u.class_prop.u.value);
ecma_ref_object (this_obj_p);
/* ecma_op_create_regexp_from_bytecode will never throw an error while re-initalizing the regexp object, so we
* can deref the old bytecode without leaving a dangling pointer. */
ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
return ecma_op_create_regexp_from_bytecode (this_obj_p, bc_p);
}
ecma_value_t ret_value = ecma_op_create_regexp_from_pattern (this_obj_p, pattern_arg, flags_arg);
if (ECMA_IS_VALUE_ERROR (ret_value))
if (!ECMA_IS_VALUE_ERROR (ret_value))
{
ecma_deref_object (this_obj_p);
ecma_ref_object (this_obj_p);
ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
}
return ret_value;
@@ -567,22 +562,11 @@ ecma_builtin_regexp_prototype_to_string (ecma_value_t this_arg) /**< this argume
ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
ecma_extended_object_t *re_obj_p = (ecma_extended_object_t *) obj_p;
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
ecma_string_t *source_p;
uint16_t flags;
if (bc_p != NULL)
{
source_p = ecma_get_string_from_value (bc_p->source);
flags = bc_p->header.status_flags;
}
else
{
source_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP);
flags = RE_FLAG_EMPTY;
}
ecma_string_t *source_p = ecma_get_string_from_value (bc_p->source);
uint16_t flags = bc_p->header.status_flags;
ecma_stringbuilder_t result = ecma_stringbuilder_create ();
ecma_stringbuilder_append_byte (&result, LIT_CHAR_SLASH);
@@ -445,6 +445,7 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
}
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
#if !ENABLED (JERRY_ES2015)
#if ENABLED (JERRY_BUILTIN_STRING)
case ECMA_BUILTIN_ID_STRING_PROTOTYPE:
{
@@ -502,35 +503,21 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
#if ENABLED (JERRY_ES2015)
ext_object_p->u.class_prop.class_id = LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO;
#else /* !ENABLED (JERRY_ES2015) */
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
#endif /* ENABLED (JERRY_ES2015) */
/* In the ECMA v6 version, we create a dummy bytecode for the RegExp prototype object for backwards compatibility,
* so we can use the existing methods to get the source and flags from the [[OriginalSource]] and [[OriginalFlags]]
* internal properties.
*/
#if ENABLED (JERRY_ES2015)
re_compiled_code_t *bc_p = (re_compiled_code_t *) jmem_heap_alloc_block (ECMA_REGEXP_PROTO_COMPILED_CODE_SIZE);
bc_p->header.status_flags = RE_FLAG_EMPTY;
bc_p->source = ecma_make_magic_string_value (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP);
#else /* !ENABLED (JERRY_ES2015) */
const re_compiled_code_t *bc_p = NULL;
ecma_value_t ret_value = 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 (ret_value));
#endif /* ENABLED (JERRY_ES2015) */
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, bc_p);
break;
}
#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
#endif /* !ENABLED (JERRY_ES2015) */
default:
{
JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_CLASS);
@@ -46,14 +46,99 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_ARRAY,
array)
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
#if ENABLED (JERRY_BUILTIN_STRING)
#if ENABLED (JERRY_ES2015)
# if ENABLED (JERRY_BUILTIN_STRING)
/* The String.prototype object (21.1.3) */
BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
string_prototype)
# endif /* ENABLED (JERRY_BUILTIN_STRING) */
# if ENABLED (JERRY_BUILTIN_BOOLEAN)
/* The Boolean.prototype object (19.3.3) */
BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
boolean_prototype)
# endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */
# if ENABLED (JERRY_BUILTIN_NUMBER)
/* The Number.prototype object (20.1.3) */
BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
number_prototype)
# endif /* ENABLED (JERRY_BUILTIN_NUMBER) */
# if ENABLED (JERRY_BUILTIN_DATE)
/* The Date.prototype object (20.3.4) */
BUILTIN (ECMA_BUILTIN_ID_DATE_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
date_prototype)
# endif /* ENABLED (JERRY_BUILTIN_DATE) */
# if ENABLED (JERRY_BUILTIN_REGEXP)
/* The RegExp.prototype object (21.2.5) */
BUILTIN (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
regexp_prototype)
# endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
#else /* !ENABLED (JERRY_ES2015) */
# if ENABLED (JERRY_BUILTIN_STRING)
/* The String.prototype object (15.5.4) */
BUILTIN (ECMA_BUILTIN_ID_STRING_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
string_prototype)
# endif /* ENABLED (JERRY_BUILTIN_STRING) */
# if ENABLED (JERRY_BUILTIN_BOOLEAN)
/* The Boolean.prototype object (15.6.4) */
BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
boolean_prototype)
# endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */
# if ENABLED (JERRY_BUILTIN_NUMBER)
/* The Number.prototype object (15.7.4) */
BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
number_prototype)
# endif /* ENABLED (JERRY_BUILTIN_NUMBER) */
# if ENABLED (JERRY_BUILTIN_DATE)
/* The Date.prototype object (15.9.4) */
BUILTIN (ECMA_BUILTIN_ID_DATE_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
date_prototype)
# endif /* ENABLED (JERRY_BUILTIN_DATE) */
# if ENABLED (JERRY_BUILTIN_REGEXP)
/* The RegExp.prototype object (15.10.6) */
BUILTIN (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
regexp_prototype)
# endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
#endif /* !ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_BUILTIN_STRING)
/* The String object (15.5.1) */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_STRING,
ECMA_OBJECT_TYPE_FUNCTION,
@@ -63,13 +148,6 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_STRING,
#endif /* ENABLED (JERRY_BUILTIN_STRING) */
#if ENABLED (JERRY_BUILTIN_BOOLEAN)
/* The Boolean.prototype object (15.6.4) */
BUILTIN (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
boolean_prototype)
/* The Boolean object (15.6.1) */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BOOLEAN,
ECMA_OBJECT_TYPE_FUNCTION,
@@ -79,13 +157,6 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BOOLEAN,
#endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */
#if ENABLED (JERRY_BUILTIN_NUMBER)
/* The Number.prototype object (15.7.4) */
BUILTIN (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
number_prototype)
/* The Number object (15.7.1) */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_NUMBER,
ECMA_OBJECT_TYPE_FUNCTION,
@@ -137,13 +208,6 @@ BUILTIN (ECMA_BUILTIN_ID_JSON,
#endif /* ENABLED (JERRY_BUILTIN_JSON) */
#if ENABLED (JERRY_BUILTIN_DATE)
/* The Date.prototype object (15.9.4) */
BUILTIN (ECMA_BUILTIN_ID_DATE_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
date_prototype)
/* The Date object (15.9.3) */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATE,
ECMA_OBJECT_TYPE_FUNCTION,
@@ -153,13 +217,6 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATE,
#endif /* ENABLED (JERRY_BUILTIN_DATE) */
#if ENABLED (JERRY_BUILTIN_REGEXP)
/* The RegExp.prototype object (15.10.6) */
BUILTIN (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE,
ECMA_OBJECT_TYPE_CLASS,
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
true,
regexp_prototype)
/* The RegExp object (15.10) */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_REGEXP,
ECMA_OBJECT_TYPE_FUNCTION,