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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 372 additions and 272 deletions

View File

@ -1106,23 +1106,12 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
ecma_dealloc_number (num_p);
break;
}
#if ENABLED (JERRY_ES2015)
case LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO:
{
jmem_heap_free_block (ECMA_GET_INTERNAL_VALUE_POINTER (void, ext_object_p->u.class_prop.u.value),
ECMA_REGEXP_PROTO_COMPILED_CODE_SIZE);
break;
}
#endif /* ENABLED (JERRY_ES2015) */
case LIT_MAGIC_STRING_REGEXP_UL:
{
ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (ecma_compiled_code_t,
ext_object_p->u.class_prop.u.value);
if (bytecode_p != NULL)
{
ecma_bytecode_deref (bytecode_p);
}
ecma_bytecode_deref (bytecode_p);
break;
}

View File

@ -940,13 +940,6 @@ typedef struct
* If regexp, the other flags must be RE_FLAG... */
} ecma_compiled_code_t;
/**
* The proper memory size for the RegExp.prototype. We have to align the header's size manually, because
* in the struct, it is aligned to 8 bytes during the compilation.
*/
#define ECMA_REGEXP_PROTO_COMPILED_CODE_SIZE \
(JERRY_ALIGNUP (sizeof (ecma_compiled_code_t), JMEM_ALIGNMENT) + sizeof (ecma_value_t))
/**
* Description of bound function objects.
*/

View File

@ -1494,28 +1494,6 @@ ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *b
} /* ecma_compiled_code_get_tagged_template_collection */
#endif /* ENABLED (JERRY_ES2015) */
/**
* Helper function to check if the given value is a class
*
* @return pointer to the extended object - if 'this' is a class
* NULL- otherwise
*/
ecma_extended_object_t *
ecma_op_check_object_type_is_class (ecma_value_t this) /**< this value */
{
if (ecma_is_value_object (this))
{
ecma_object_t *obj_p = ecma_get_object_from_value (this);
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS)
{
return (ecma_extended_object_t *) obj_p;
}
}
return NULL;
} /* ecma_op_check_object_type_is_class */
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015)
/**
* Get the number of formal parameters of the compiled code

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,

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:
{

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);

View File

@ -51,7 +51,6 @@ typedef enum
LIT_INTERNAL_MAGIC_API_INTERNAL, /**< Property key used to add non-visible JS properties from the public API */
LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, /**< %ArrayProto_values% intrinsic routine */
LIT_INTERNAL_MAGIC_THIS_BINDING_VALUE, /**< FunctionEnvironmentRecord [[ThisBindingValue]] internal slot */
LIT_INTERNAL_MAGIC_STRING_REGEXP_PROTO, /**< RegExp object prototype */
/* List of well known symbols */
LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */
LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */

View File

@ -13,7 +13,6 @@
// limitations under the License.
assert (Date.length == 7);
assert (Object.prototype.toString.call (Date.prototype) === '[object Date]');
var d;
@ -28,8 +27,6 @@ catch (e)
assert (e.message === "foo");
}
assert (isNaN(Date.prototype.valueOf.call(Date.prototype)));
d = new Date("abcd");
assert (isNaN(d.valueOf()));

View File

@ -224,19 +224,3 @@ assert (isNaN (d.setMonth()));
assert (isNaN (d.setUTCMonth()));
assert (isNaN (d.setFullYear()));
assert (isNaN (d.setUTCFullYear()));
assert (isNaN (Date.prototype.setTime()));
assert (isNaN (Date.prototype.setMilliseconds()));
assert (isNaN (Date.prototype.setUTCMilliseconds()));
assert (isNaN (Date.prototype.setSeconds()));
assert (isNaN (Date.prototype.setUTCSeconds()));
assert (isNaN (Date.prototype.setMinutes()));
assert (isNaN (Date.prototype.setUTCMinutes()));
assert (isNaN (Date.prototype.setHours()));
assert (isNaN (Date.prototype.setUTCHours()));
assert (isNaN (Date.prototype.setDate()));
assert (isNaN (Date.prototype.getUTCDate()));
assert (isNaN (Date.prototype.setMonth()));
assert (isNaN (Date.prototype.setUTCMonth()));
assert (isNaN (Date.prototype.setFullYear()));
assert (isNaN (Date.prototype.setUTCFullYear()));

View File

@ -0,0 +1,117 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var prototypes = [
String.prototype,
Boolean.prototype,
Number.prototype,
Date.prototype,
RegExp.prototype,
Error.prototype,
EvalError.prototype,
RangeError.prototype,
ReferenceError.prototype,
SyntaxError.prototype,
TypeError.prototype,
URIError.prototype
]
for (proto of prototypes) {
assert (Object.prototype.toString.call (proto) === '[object Object]');
}
try {
String.prototype.toString();
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
Boolean.prototype.valueOf();
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
Number.prototype.valueOf();
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
Date.prototype.valueOf();
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.exec("");
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.compile("a", "u");
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.source;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.global;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.ignoreCase;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.multiline;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.sticky;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
try {
RegExp.prototype.unicode;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}

View File

@ -60,3 +60,13 @@ assert (r.lastIndex === 0);
var r = /abc/yg;
m = r.exec ("strabcstr");
assert (m === null);
try {
RegExp.prototype.flags;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
var flagsProp = Object.getOwnPropertyDescriptor (RegExp.prototype, "flags");
assert(flagsProp.get.call({}) === '');

View File

@ -38,3 +38,18 @@ assert(new RegExp('/\n/').source.length === 6);
assert(new RegExp(/\/\//).source === '\\/\\/');
assert(new RegExp(/\?\//g).source === '\\?\\/');
try {
RegExp.prototype.source;
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}
var sourceProp = Object.getOwnPropertyDescriptor (RegExp.prototype, "source");
try {
sourceProp.get.call({});
assert (false);
} catch (e) {
assert (e instanceof TypeError);
}

View File

@ -12,4 +12,4 @@
// See the License for the specific language governing permissions and
// limitations under the License.
assert(String.prototype.repeat(1.1) === "");
assert("".repeat(1.1) === "");

View File

@ -13,4 +13,4 @@
// limitations under the License.
for (var [] of [[], []])
String.prototype.split(RegExp.prototype)
"".split(new RegExp())

View File

@ -0,0 +1,81 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
assert (Object.prototype.toString.call (String.prototype) === '[object String]');
assert (String.prototype.toString() === "");
assert (Object.prototype.toString.call (Boolean.prototype) === '[object Boolean]');
assert (Boolean.prototype.valueOf() === false);
assert (Object.prototype.toString.call (Number.prototype) === '[object Number]');
assert (Number.prototype.valueOf() === 0);
assert (Object.prototype.toString.call (Date.prototype) === '[object Date]');
assert (isNaN(Date.prototype.valueOf()));
assert (isNaN (Date.prototype.setTime()));
assert (isNaN (Date.prototype.setMilliseconds()));
assert (isNaN (Date.prototype.setUTCMilliseconds()));
assert (isNaN (Date.prototype.setSeconds()));
assert (isNaN (Date.prototype.setUTCSeconds()));
assert (isNaN (Date.prototype.setMinutes()));
assert (isNaN (Date.prototype.setUTCMinutes()));
assert (isNaN (Date.prototype.setHours()));
assert (isNaN (Date.prototype.setUTCHours()));
assert (isNaN (Date.prototype.setDate()));
assert (isNaN (Date.prototype.getUTCDate()));
assert (isNaN (Date.prototype.setMonth()));
assert (isNaN (Date.prototype.setUTCMonth()));
assert (isNaN (Date.prototype.setFullYear()));
assert (isNaN (Date.prototype.setUTCFullYear()));
assert (Object.prototype.toString.call (RegExp.prototype) === '[object RegExp]');
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);
RegExp.prototype.source = "a";
RegExp.prototype.global = true;
RegExp.prototype.ignoreCase = true;
RegExp.prototype.multiline = true;
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);
delete RegExp.prototype.source;
delete RegExp.prototype.global;
delete RegExp.prototype.ignoreCase;
delete RegExp.prototype.multiline;
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);
var prototypes = [
Error.prototype,
EvalError.prototype,
RangeError.prototype,
ReferenceError.prototype,
SyntaxError.prototype,
TypeError.prototype,
URIError.prototype
]
prototypes.forEach (function (proto) {
assert (Object.prototype.toString.call (proto) === '[object Error]');
})

View File

@ -76,8 +76,6 @@ assert (r.global == true);
assert (r.ignoreCase == true);
assert (r.multiline == true);
assert(Object.prototype.toString.call(RegExp.prototype) === '[object RegExp]');
/* The 'undefined' argument for the RegExp constructor should not be converted to string,
* and it should behave just like when there is no argument.
*/
@ -130,25 +128,3 @@ assert (r.multiline == false);
/* RegExp properties */
assert (RegExp.length === 2);
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);
RegExp.prototype.source = "a";
RegExp.prototype.global = true;
RegExp.prototype.ignoreCase = true;
RegExp.prototype.multiline = true;
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);
delete RegExp.prototype.source;
delete RegExp.prototype.global;
delete RegExp.prototype.ignoreCase;
delete RegExp.prototype.multiline;
assert (RegExp.prototype.source === "(?:)");
assert (RegExp.prototype.global === false);
assert (RegExp.prototype.ignoreCase === false);
assert (RegExp.prototype.multiline === false);