Update the RegExp constructor to ECMA-262 v6 (#3538)

The following methods have been implemented:
- RegExpAlloc, based on ECMA-262 v6, 21.2.3.2.1
- RegExpInitialize, based on ECMA-262 v6, 22.2.3.2.2
- RegExpCreate, based on ECMA-262 v6, 21.2.3.2.3

Co-authored-by: Robert Fancsik frobert@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam
2020-03-27 10:37:06 +01:00
committed by GitHub
parent 56832d772e
commit d539d30bf9
18 changed files with 618 additions and 358 deletions
@@ -814,7 +814,7 @@ ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, /**< object */
*/
ecma_value_t
ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */
ecma_string_t *index_p, /**< index string */
ecma_string_t *name_p, /**< name string */
ecma_value_t value, /**< value */
uint32_t opts) /**< any combination of ecma_property_flag_t bits
* with the optional ECMA_IS_THROW flag */
@@ -826,7 +826,7 @@ ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */
prop_desc.value = value;
return ecma_op_object_define_own_property (obj_p,
index_p,
name_p,
&prop_desc);
} /* ecma_builtin_helper_def_prop */
@@ -60,7 +60,7 @@ bool
ecma_builtin_helper_string_find_index (ecma_string_t *original_str_p, ecma_string_t *search_str_p, bool first_index,
ecma_length_t start_pos, ecma_length_t *ret_index_p);
ecma_value_t
ecma_builtin_helper_def_prop (ecma_object_t *obj_p, ecma_string_t *index_p, ecma_value_t value, uint32_t opts);
ecma_builtin_helper_def_prop (ecma_object_t *obj_p, ecma_string_t *name_p, ecma_value_t value, uint32_t opts);
ecma_value_t
ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, uint32_t index, ecma_value_t value, uint32_t opts);
@@ -60,21 +60,23 @@ static ecma_value_t
ecma_builtin_regexp_prototype_flags_helper (ecma_value_t this, /**< this value */
uint16_t *flags_p) /**< [out] flags */
{
if (!ecma_object_is_regexp_object (this))
ecma_extended_object_t *ext_obj_p = ecma_op_check_object_type_is_class (this);
if (ext_obj_p != NULL)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
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;
}
}
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_ANY_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
if (bc_p != NULL)
{
*flags_p = bc_p->header.status_flags;
}
return ECMA_VALUE_EMPTY;
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
} /* ecma_builtin_regexp_prototype_flags_helper */
/**
@@ -220,21 +222,21 @@ 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 */
{
if (!ecma_object_is_regexp_object (this_arg))
ecma_extended_object_t *ext_obj_p = ecma_op_check_object_type_is_class (this_arg);
if (ext_obj_p != NULL)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
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));
}
}
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_ANY_POINTER (re_compiled_code_t,
re_obj_p->u.class_prop.u.value);
if (bc_p != NULL)
{
return ecma_op_escape_regexp_pattern (ecma_get_string_from_value (bc_p->source));
}
return ecma_make_string_value (ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP));
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
} /* ecma_builtin_regexp_prototype_get_source */
/**
@@ -382,95 +384,47 @@ ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument
ecma_value_t flags_arg) /**< flags */
{
if (!ecma_object_is_regexp_object (this_arg)
/* The builtin RegExp.prototype object does not have [[RegExpMatcher]] internal slot */
|| ecma_get_object_from_value (this_arg) == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE))
#if !ENABLED (JERRY_ES2015)
|| ecma_get_object_from_value (this_arg) == ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)
#endif /* !ENABLED (JERRY_ES2015) */
)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type"));
}
uint16_t flags = 0;
ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg);
ecma_ref_object (this_obj_p);
if (ecma_object_is_regexp_object (pattern_arg)
&& ecma_get_object_from_value (pattern_arg) != ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE))
ecma_value_t status = ecma_builtin_helper_def_prop (this_obj_p,
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
ecma_make_uint32_value (0),
ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROP_IS_THROW);
JERRY_ASSERT (ecma_is_value_true (status));
if (ecma_object_is_regexp_object (pattern_arg))
{
if (!ecma_is_value_undefined (flags_arg))
{
ecma_deref_object (this_obj_p);
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument"));
}
/* Compile from existing RegExp object. */
ecma_extended_object_t *target_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_arg);
re_compiled_code_t *target_bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
target_p->u.class_prop.u.value);
ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_arg);
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
pattern_obj_p->u.class_prop.u.value);
ecma_object_t *this_object_p = ecma_get_object_from_value (this_arg);
ecma_extended_object_t *current_p = (ecma_extended_object_t *) this_object_p;
re_compiled_code_t *current_bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
current_p->u.class_prop.u.value);
JERRY_ASSERT (current_bc_p != NULL);
ecma_bytecode_deref ((ecma_compiled_code_t *) current_bc_p);
JERRY_ASSERT (target_bc_p != NULL);
ecma_bytecode_ref ((ecma_compiled_code_t *) target_bc_p);
ECMA_SET_INTERNAL_VALUE_POINTER (current_p->u.class_prop.u.value, target_bc_p);
ecma_regexp_initialize_props (this_object_p,
ecma_get_string_from_value (target_bc_p->source),
target_bc_p->header.status_flags);
return ecma_copy_value (this_arg);
return ecma_op_create_regexp_from_bytecode (this_obj_p, bc_p);
}
ecma_string_t *pattern_string_p = ecma_regexp_read_pattern_str_helper (pattern_arg);
ecma_value_t ret_value = ecma_op_create_regexp_from_pattern (this_obj_p, pattern_arg, flags_arg);
/* Get source string. */
if (pattern_string_p == NULL)
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ECMA_VALUE_ERROR;
ecma_deref_object (this_obj_p);
}
/* Parse flags. */
if (!ecma_is_value_undefined (flags_arg))
{
ecma_string_t *flags_str_p = ecma_op_to_string (flags_arg);
if (JERRY_UNLIKELY (flags_str_p == NULL))
{
ecma_deref_ecma_string (pattern_string_p);
return ECMA_VALUE_ERROR;
}
ecma_value_t parsed_flags_val = ecma_regexp_parse_flags (flags_str_p, &flags);
ecma_deref_ecma_string (flags_str_p);
if (ECMA_IS_VALUE_ERROR (parsed_flags_val))
{
ecma_deref_ecma_string (pattern_string_p);
return parsed_flags_val;
}
}
/* Try to compile bytecode from new source. */
const re_compiled_code_t *new_bc_p = NULL;
ecma_value_t bc_val = re_compile_bytecode (&new_bc_p, pattern_string_p, flags);
if (ECMA_IS_VALUE_ERROR (bc_val))
{
ecma_deref_ecma_string (pattern_string_p);
return bc_val;
}
ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg);
ecma_value_t *bc_prop_p = &(((ecma_extended_object_t *) this_obj_p)->u.class_prop.u.value);
re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t, *bc_prop_p);
JERRY_ASSERT (old_bc_p != NULL);
ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p);
ECMA_SET_INTERNAL_VALUE_POINTER (*bc_prop_p, new_bc_p);
ecma_regexp_initialize_props (this_obj_p, pattern_string_p, flags);
ecma_deref_ecma_string (pattern_string_p);
return ecma_copy_value (this_arg);
return ret_value;
} /* ecma_builtin_regexp_prototype_compile */
#endif /* ENABLED (JERRY_BUILTIN_ANNEXB) */
@@ -17,7 +17,9 @@
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "jcontext.h"
#include "ecma-objects.h"
#include "ecma-regexp-object.h"
#include "ecma-try-catch-macro.h"
@@ -41,34 +43,15 @@
* @{
*/
/**
* Handle calling [[Call]] of built-in RegExp object
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_builtin_regexp_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
return ecma_builtin_regexp_dispatch_construct (arguments_list_p, arguments_list_len);
} /* ecma_builtin_regexp_dispatch_call */
/**
* Handle calling [[Construct]] of built-in RegExp object
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
static ecma_value_t
ecma_builtin_regexp_dispatch_helper (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len, /**< number of arguments */
ecma_object_t *new_target_p) /**< pointer to the new target object */
{
ecma_value_t pattern_value = ECMA_VALUE_UNDEFINED;
ecma_value_t flags_value = ECMA_VALUE_UNDEFINED;
#if ENABLED (JERRY_ES2015)
ecma_value_t new_pattern = ECMA_VALUE_EMPTY;
ecma_value_t new_flags = ECMA_VALUE_EMPTY;
bool create_regexp_from_bc = false;
#endif /* ENABLED (JERRY_ES2015) */
if (arguments_list_len > 0)
@@ -90,88 +73,140 @@ ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /*
return regexp_value;
}
bool is_regexp = regexp_value == ECMA_VALUE_TRUE;
#else /* !ENABLED (JERRY_ES2015) */
bool is_regexp = ecma_object_is_regexp_object (pattern_value);
#endif /* ENABLED (JERRY_ES2015) */
bool pattern_is_regexp = regexp_value == ECMA_VALUE_TRUE;
re_compiled_code_t *bc_p = NULL;
if (is_regexp)
if (new_target_p == NULL)
{
new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP);
if (pattern_is_regexp && ecma_is_value_undefined (flags_value))
{
ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value);
ecma_value_t pattern_constructor = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_CONSTRUCTOR);
if (ECMA_IS_VALUE_ERROR (pattern_constructor))
{
return pattern_constructor;
}
bool is_same = ecma_op_same_value (ecma_make_object_value (new_target_p), pattern_constructor);
ecma_free_value (pattern_constructor);
if (is_same)
{
return ecma_copy_value (pattern_value);
}
}
}
if (ecma_object_is_regexp_object (pattern_value))
{
ecma_extended_object_t *pattern_obj_p = (ecma_extended_object_t *) ecma_get_object_from_value (pattern_value);
bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t,
pattern_obj_p->u.class_prop.u.value);
create_regexp_from_bc = ecma_is_value_undefined (flags_value);
if (!create_regexp_from_bc)
{
pattern_value = bc_p->source;
}
}
else if (pattern_is_regexp)
{
#if ENABLED (JERRY_ES2015)
ecma_object_t *pattern_obj_p = ecma_get_object_from_value (pattern_value);
new_pattern = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_SOURCE);
pattern_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_SOURCE);
if (ECMA_IS_VALUE_ERROR (new_pattern))
if (ECMA_IS_VALUE_ERROR (pattern_value))
{
return new_pattern;
return pattern_value;
}
pattern_value = new_pattern;
if (ecma_is_value_undefined (flags_value))
{
new_flags = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_FLAGS);
flags_value = ecma_op_object_get_by_magic_id (pattern_obj_p, LIT_MAGIC_STRING_FLAGS);
if (ECMA_IS_VALUE_ERROR (new_flags))
if (ECMA_IS_VALUE_ERROR (flags_value))
{
ecma_free_value (new_pattern);
return new_flags;
return flags_value;
}
flags_value = new_flags;
}
}
#else /* !ENABLED (JERRY_ES2015) */
if (ecma_object_is_regexp_object (pattern_value))
{
if (ecma_is_value_undefined (flags_value))
{
return ecma_copy_value (pattern_value);
}
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp call."));
}
#endif /* ENABLED (JERRY_ES2015) */
}
ecma_string_t *pattern_string_p = ecma_regexp_read_pattern_str_helper (pattern_value);
ecma_value_t ret_value = ECMA_VALUE_ERROR;
ecma_object_t *new_target_obj_p = ecma_op_regexp_alloc (new_target_p);
if (pattern_string_p == NULL)
if (JERRY_UNLIKELY (new_target_obj_p == NULL))
{
goto cleanup;
return ECMA_VALUE_ERROR;
}
uint16_t flags = 0;
ecma_value_t ret_value;
if (!ecma_is_value_undefined (flags_value))
{
ecma_string_t *flags_string_p = ecma_op_to_string (flags_value);
if (JERRY_UNLIKELY (flags_string_p == NULL))
{
ecma_deref_ecma_string (pattern_string_p);
goto cleanup;
}
ret_value = ecma_regexp_parse_flags (flags_string_p, &flags);
ecma_deref_ecma_string (flags_string_p);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
ecma_deref_ecma_string (pattern_string_p);
goto cleanup;
}
JERRY_ASSERT (ecma_is_value_empty (ret_value));
}
ret_value = ecma_op_create_regexp_object (pattern_string_p, flags);
ecma_deref_ecma_string (pattern_string_p);
cleanup:
#if ENABLED (JERRY_ES2015)
ecma_free_value (new_pattern);
ecma_free_value (new_flags);
if (create_regexp_from_bc)
{
ret_value = ecma_op_create_regexp_from_bytecode (new_target_obj_p, bc_p);
}
else
{
#endif /* ENABLED (JERRY_ES2015) */
ret_value = ecma_op_create_regexp_from_pattern (new_target_obj_p, pattern_value, flags_value);
#if ENABLED (JERRY_ES2015)
}
#endif /* ENABLED (JERRY_ES2015) */
if (ECMA_IS_VALUE_ERROR (ret_value))
{
ecma_deref_object (new_target_obj_p);
}
return ret_value;
} /* ecma_builtin_regexp_dispatch_helper */
/**
* Handle calling [[Call]] of built-in RegExp object
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_builtin_regexp_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
return ecma_builtin_regexp_dispatch_helper (arguments_list_p,
arguments_list_len,
NULL);
} /* ecma_builtin_regexp_dispatch_call */
/**
* Handle calling [[Construct]] of built-in RegExp object
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
return ecma_builtin_regexp_dispatch_helper (arguments_list_p,
arguments_list_len,
ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP));
} /* ecma_builtin_regexp_dispatch_construct */
#if ENABLED (JERRY_ES2015)
@@ -283,93 +283,98 @@ ecma_builtin_string_prototype_object_locale_compare (ecma_string_t *this_string_
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_string_prototype_object_match (ecma_value_t this_to_string_value, /**< this argument */
ecma_builtin_string_prototype_object_match (ecma_value_t this_argument, /**< this argument */
ecma_value_t regexp_arg) /**< routine's argument */
{
#if ENABLED (JERRY_ES2015)
/* 3. */
if (!(ecma_is_value_undefined (regexp_arg) || ecma_is_value_null (regexp_arg)))
{
/* 3.a */
ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_GLOBAL_SYMBOL_MATCH);
/* 3.b */
if (ECMA_IS_VALUE_ERROR (matcher))
{
return matcher;
}
/* 3.c */
if (!ecma_is_value_undefined (matcher))
{
/* 3.c.i */
ecma_object_t *matcher_method = ecma_get_object_from_value (matcher);
ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_to_string_value, 1);
ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1);
ecma_deref_object (matcher_method);
return result;
}
}
/* 4. */
ecma_string_t *this_str_p = ecma_op_to_string (this_argument);
/* 5. */
if (JERRY_UNLIKELY (this_str_p == NULL))
{
return ECMA_VALUE_ERROR;
}
/* 6. */
ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
if (JERRY_UNLIKELY (regexp_obj_p == NULL))
{
ecma_deref_ecma_string (this_str_p);
return ECMA_VALUE_ERROR;
}
ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED);
/* 7. */
if (ECMA_IS_VALUE_ERROR (new_regexp))
{
ecma_deref_object (regexp_obj_p);
ecma_deref_ecma_string (this_str_p);
return new_regexp;
}
ecma_value_t this_str_value = ecma_make_string_value (this_str_p);
/* 8. */
ecma_value_t ret_value = ecma_op_invoke_by_symbol_id (new_regexp, LIT_GLOBAL_SYMBOL_MATCH, &this_str_value, 1);
ecma_deref_ecma_string (this_str_p);
ecma_free_value (new_regexp);
return ret_value;
#else /* !ENABLED (JERRY_ES2015) */
if (ecma_object_is_regexp_object (regexp_arg))
{
return ecma_regexp_match_helper (regexp_arg, this_to_string_value);
return ecma_regexp_match_helper (regexp_arg, this_argument);
}
#endif /* ENABLED (JERRY_ES2015) */
ecma_string_t *pattern_p = ecma_regexp_read_pattern_str_helper (regexp_arg);
ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
if (JERRY_UNLIKELY (pattern_p == NULL))
if (JERRY_UNLIKELY (regexp_obj_p == NULL))
{
return ECMA_VALUE_ERROR;
}
ecma_value_t new_regexp = ecma_op_create_regexp_object (pattern_p, 0);
ecma_deref_ecma_string (pattern_p);
ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (regexp_obj_p, regexp_arg, ECMA_VALUE_UNDEFINED);
if (ECMA_IS_VALUE_ERROR (new_regexp))
{
ecma_deref_object (regexp_obj_p);
return new_regexp;
}
#if ENABLED (JERRY_ES2015)
ecma_object_t *new_regexp_obj = ecma_get_object_from_value (new_regexp);
ecma_value_t func_value = ecma_op_object_get_by_symbol_id (new_regexp_obj, LIT_GLOBAL_SYMBOL_MATCH);
if (ECMA_IS_VALUE_ERROR (func_value) || !ecma_op_is_callable (func_value))
{
ecma_deref_object (new_regexp_obj);
if (!ECMA_IS_VALUE_ERROR (func_value))
{
ecma_free_value (func_value);
ecma_raise_type_error (ECMA_ERR_MSG ("@@match is not callable."));
}
return ECMA_VALUE_ERROR;
}
ecma_object_t *func_obj = ecma_get_object_from_value (func_value);
ecma_string_t *str_p = ecma_op_to_string (this_to_string_value);
if (JERRY_UNLIKELY (str_p == NULL))
{
ecma_deref_object (new_regexp_obj);
ecma_deref_object (func_obj);
return ECMA_VALUE_ERROR;
}
ecma_value_t str_value = ecma_make_string_value (str_p);
ecma_value_t result = ecma_op_function_call (func_obj, new_regexp, &str_value, 1);
ecma_deref_ecma_string (str_p);
ecma_deref_object (new_regexp_obj);
ecma_deref_object (func_obj);
#else /* !ENABLED (JERRY_ES2015) */
ecma_value_t result = ecma_regexp_match_helper (new_regexp, this_to_string_value);
ecma_value_t result = ecma_regexp_match_helper (new_regexp, this_argument);
ecma_free_value (new_regexp);
#endif /* ENABLED (JERRY_ES2015) */
return result;
#endif /* ENABLED (JERRY_ES2015) */
} /* ecma_builtin_string_prototype_object_match */
/**
@@ -624,10 +629,24 @@ ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this
goto cleanup_string;
}
ecma_value_t new_regexp = ecma_op_create_regexp_object (pattern_p, 0);
ecma_object_t *new_regexp_obj_p = ecma_op_regexp_alloc (NULL);
if (JERRY_UNLIKELY (new_regexp_obj_p == NULL))
{
ecma_deref_ecma_string (string_p);
ecma_deref_ecma_string (pattern_p);
return ECMA_VALUE_ERROR;
}
ecma_value_t new_regexp = ecma_op_create_regexp_from_pattern (new_regexp_obj_p,
ecma_make_string_value (pattern_p),
ECMA_VALUE_UNDEFINED);
ecma_deref_ecma_string (pattern_p);
if (ECMA_IS_VALUE_ERROR (new_regexp))
{
ecma_deref_object (new_regexp_obj_p);
goto cleanup_string;
}
@@ -1323,6 +1342,13 @@ ecma_builtin_string_prototype_dispatch_routine (uint16_t builtin_routine_id, /**
ecma_value_t arg1 = arguments_list_p[0];
ecma_value_t arg2 = arguments_list_p[1];
#if ENABLED (JERRY_BUILTIN_REGEXP)
if (builtin_routine_id == ECMA_STRING_PROTOTYPE_MATCH)
{
return ecma_builtin_string_prototype_object_match (this_arg, arg1);
}
#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
if (builtin_routine_id <= ECMA_STRING_PROTOTYPE_CHAR_CODE_AT)
{
return ecma_builtin_string_prototype_char_at_helper (this_arg,
@@ -1371,11 +1397,6 @@ ecma_builtin_string_prototype_dispatch_routine (uint16_t builtin_routine_id, /**
break;
}
#if ENABLED (JERRY_BUILTIN_REGEXP)
case ECMA_STRING_PROTOTYPE_MATCH:
{
ret_value = ecma_builtin_string_prototype_object_match (to_string_val, arg1);
break;
}
case ECMA_STRING_PROTOTYPE_REPLACE:
{
ret_value = ecma_builtin_string_prototype_object_replace (to_string_val, arg1, arg2);
@@ -501,8 +501,32 @@ 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;
ext_object_p->u.class_prop.u.value = ECMA_NULL_POINTER;
#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) */