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:
+12
-2
@@ -31,6 +31,7 @@
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-init-finalize.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "lit-char-helpers.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
@@ -1773,11 +1774,20 @@ jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-
|
||||
return jerry_throw (ecma_raise_common_error (ECMA_ERR_MSG ("Input must be a valid utf8 string")));
|
||||
}
|
||||
|
||||
ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
|
||||
|
||||
if (JERRY_UNLIKELY (regexp_obj_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_string_t *ecma_pattern = ecma_new_ecma_string_from_utf8 (pattern_p, pattern_size);
|
||||
|
||||
jerry_value_t ret_val = ecma_op_create_regexp_object (ecma_pattern, flags);
|
||||
|
||||
jerry_value_t ret_val = ecma_op_create_regexp_with_flags (regexp_obj_p,
|
||||
ecma_make_string_value (ecma_pattern),
|
||||
flags);
|
||||
ecma_deref_ecma_string (ecma_pattern);
|
||||
|
||||
return ret_val;
|
||||
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REGEXP) */
|
||||
|
||||
@@ -1106,17 +1106,24 @@ 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;
|
||||
bytecode_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (ecma_compiled_code_t,
|
||||
ext_object_p->u.class_prop.u.value);
|
||||
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);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
|
||||
|
||||
@@ -940,6 +940,13 @@ 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))
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
|
||||
/**
|
||||
|
||||
@@ -1494,6 +1494,28 @@ 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
|
||||
|
||||
@@ -430,6 +430,7 @@ uint8_t ecma_get_object_builtin_id (ecma_object_t *object_p);
|
||||
ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p);
|
||||
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p);
|
||||
ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values);
|
||||
ecma_extended_object_t *ecma_op_check_object_type_is_class (ecma_value_t this);
|
||||
|
||||
ecma_property_value_t *
|
||||
ecma_create_named_data_property (ecma_object_t *object_p, ecma_string_t *name_p, uint8_t prop_attributes,
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -2506,6 +2506,14 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
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:
|
||||
@@ -2790,6 +2798,24 @@ ecma_op_species_constructor (ecma_object_t *this_value, /**< This Value */
|
||||
return species;
|
||||
} /* ecma_op_species_constructor */
|
||||
|
||||
/**
|
||||
* 7.3.18 Abstract operation Invoke when property name is a magic string
|
||||
*
|
||||
* @return ecma_value result of the invoked function or raised error
|
||||
* note: returned value must be freed with ecma_free_value
|
||||
*/
|
||||
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_invoke_by_symbol_id (ecma_value_t object, /**< Object value */
|
||||
lit_magic_string_id_t symbol_id, /**< Symbol ID */
|
||||
ecma_value_t *args_p, /**< Argument list */
|
||||
ecma_length_t args_len) /**< Argument list length */
|
||||
{
|
||||
ecma_string_t *symbol_p = ecma_op_get_global_symbol (symbol_id);
|
||||
ecma_value_t ret_value = ecma_op_invoke (object, symbol_p, args_p, args_len);
|
||||
ecma_deref_ecma_string (symbol_p);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_invoke_by_symbol_id */
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,6 +77,8 @@ bool ecma_object_is_regexp_object (ecma_value_t arg);
|
||||
ecma_value_t ecma_op_is_concat_spreadable (ecma_value_t arg);
|
||||
ecma_value_t ecma_op_is_regexp (ecma_value_t arg);
|
||||
ecma_value_t ecma_op_species_constructor (ecma_object_t *this_value, ecma_builtin_id_t default_constructor_id);
|
||||
ecma_value_t ecma_op_invoke_by_symbol_id (ecma_value_t object, lit_magic_string_id_t magic_string_id,
|
||||
ecma_value_t *args_p, ecma_length_t args_len);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
ecma_value_t ecma_op_invoke (ecma_value_t object, ecma_string_t *property_name_p, ecma_value_t *args_p,
|
||||
ecma_length_t args_len);
|
||||
|
||||
@@ -125,88 +125,81 @@ ecma_regexp_parse_flags (ecma_string_t *flags_str_p, /**< Input string with flag
|
||||
return ret_value;
|
||||
} /* ecma_regexp_parse_flags */
|
||||
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
/*
|
||||
* Create the properties of a RegExp instance.
|
||||
*/
|
||||
static void
|
||||
ecma_regexp_create_props (ecma_object_t *re_object_p) /**< RegExp object */
|
||||
ecma_regexp_create_props (ecma_object_t *re_object_p, /**< RegExp object */
|
||||
ecma_string_t *source_p, /**< source string */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
|
||||
ecma_ref_ecma_string (source_p);
|
||||
prop_value_p->value = ecma_make_string_value (source_p);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_GLOBAL);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE);
|
||||
|
||||
prop_value_p = ecma_create_named_data_property (re_object_p,
|
||||
ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE),
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_MULTILINE);
|
||||
} /* ecma_regexp_create_props */
|
||||
|
||||
/*
|
||||
* Helper function to assign a value to a property
|
||||
* Update the properties of a RegExp instance.
|
||||
*/
|
||||
static void
|
||||
ecma_regexp_helper_assign_prop (ecma_object_t *re_object_p, /**< RegExp object */
|
||||
lit_magic_string_id_t prop_id, /**< property name ide */
|
||||
ecma_value_t value) /**< value */
|
||||
ecma_regexp_update_props (ecma_object_t *re_object_p, /**< RegExp object */
|
||||
ecma_string_t *source_p, /**< source string */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
ecma_property_ref_t property_ref;
|
||||
ecma_op_object_get_own_property (re_object_p,
|
||||
ecma_get_magic_string (prop_id),
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_VALUE);
|
||||
ecma_named_data_property_assign_value (re_object_p,
|
||||
property_ref.value_p,
|
||||
value);
|
||||
} /* ecma_regexp_helper_assign_prop */
|
||||
ecma_property_t *prop_p;
|
||||
|
||||
/**
|
||||
* Initializes the properties of a RegExp instance.
|
||||
*/
|
||||
void
|
||||
ecma_regexp_initialize_props (ecma_object_t *re_object_p, /**< RegExp object */
|
||||
ecma_string_t *source_p, /**< source string */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
ecma_regexp_helper_assign_prop (re_object_p,
|
||||
LIT_MAGIC_STRING_SOURCE,
|
||||
ecma_make_string_value (source_p));
|
||||
prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE));
|
||||
JERRY_ASSERT (prop_p != NULL);
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
ecma_free_value (prop_value_p->value);
|
||||
ecma_ref_ecma_string (source_p);
|
||||
prop_value_p->value = ecma_make_string_value (source_p);
|
||||
|
||||
ecma_regexp_helper_assign_prop (re_object_p,
|
||||
LIT_MAGIC_STRING_GLOBAL,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_GLOBAL));
|
||||
prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL));
|
||||
JERRY_ASSERT (prop_p != NULL);
|
||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_GLOBAL);
|
||||
|
||||
ecma_regexp_helper_assign_prop (re_object_p,
|
||||
LIT_MAGIC_STRING_IGNORECASE_UL,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE));
|
||||
prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL));
|
||||
JERRY_ASSERT (prop_p != NULL);
|
||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE);
|
||||
|
||||
ecma_regexp_helper_assign_prop (re_object_p,
|
||||
LIT_MAGIC_STRING_MULTILINE,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_MULTILINE));
|
||||
#else /* ENABLED (JERRY_ES2015) */
|
||||
JERRY_UNUSED (source_p);
|
||||
JERRY_UNUSED (flags);
|
||||
prop_p = ecma_find_named_property (re_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE));
|
||||
JERRY_ASSERT (prop_p != NULL);
|
||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
|
||||
prop_value_p->value = ecma_make_boolean_value (flags & RE_FLAG_MULTILINE);
|
||||
} /* ecma_regexp_update_props */
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
ecma_regexp_helper_assign_prop (re_object_p,
|
||||
LIT_MAGIC_STRING_LASTINDEX_UL,
|
||||
ecma_make_uint32_value (0));
|
||||
} /* ecma_regexp_initialize_props */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
/**
|
||||
* Helper function to get current code point and advance the string pointer.
|
||||
@@ -238,86 +231,232 @@ ecma_regexp_unicode_advance (const lit_utf8_byte_t **str_p, /**< reference to st
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* RegExp object creation operation.
|
||||
* RegExpAlloc method
|
||||
*
|
||||
* See also: ECMA-262 v5, 15.10.4.1
|
||||
* ECMA-262 v6, 21.2.3.2.1
|
||||
*
|
||||
* @return constructed RegExp object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
* Note:
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*
|
||||
* @return ecma_object_t
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_regexp_object_from_bytecode (re_compiled_code_t *bytecode_p) /**< RegExp bytecode */
|
||||
ecma_object_t *
|
||||
ecma_op_regexp_alloc (ecma_object_t *ctr_obj_p) /**< constructor object pointer */
|
||||
{
|
||||
JERRY_ASSERT (bytecode_p != NULL);
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool default_alloc = false;
|
||||
|
||||
ecma_object_t *re_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
|
||||
if (ctr_obj_p == NULL)
|
||||
{
|
||||
ecma_object_t *re_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (re_prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
ecma_value_t ctr_value = ecma_op_object_get_by_magic_id (re_prototype_obj_p, LIT_MAGIC_STRING_CONSTRUCTOR);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
if (ECMA_IS_VALUE_ERROR (ctr_value))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the internal [[Class]] property */
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
|
||||
ctr_obj_p = ecma_get_object_from_value (ctr_value);
|
||||
|
||||
/* Set bytecode internal property. */
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, bytecode_p);
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_p);
|
||||
default_alloc = true;
|
||||
}
|
||||
|
||||
/* Create and initialize RegExp object properties */
|
||||
ecma_regexp_create_props (object_p);
|
||||
ecma_regexp_initialize_props (object_p,
|
||||
ecma_get_string_from_value (bytecode_p->source),
|
||||
bytecode_p->header.status_flags);
|
||||
ecma_object_t *proto_obj_p = ecma_op_get_prototype_from_constructor (ctr_obj_p,
|
||||
ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_regexp_object_from_bytecode */
|
||||
if (default_alloc)
|
||||
{
|
||||
ecma_deref_object (ctr_obj_p);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (proto_obj_p == NULL))
|
||||
{
|
||||
return proto_obj_p;
|
||||
}
|
||||
|
||||
#else /* !ENABLED (JERRY_ES2015) */
|
||||
JERRY_UNUSED (ctr_obj_p);
|
||||
ecma_object_t *proto_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
ecma_object_t *new_object_p = ecma_create_object (proto_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
ecma_deref_object (proto_obj_p);
|
||||
#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;
|
||||
|
||||
ecma_value_t status = ecma_builtin_helper_def_prop (new_object_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));
|
||||
|
||||
return new_object_p;
|
||||
} /* ecma_op_regexp_alloc */
|
||||
|
||||
/**
|
||||
* RegExp object creation operation.
|
||||
* Helper method for initializing an aready existing RegExp object.
|
||||
*/
|
||||
static void
|
||||
ecma_op_regexp_initialize (ecma_object_t *regexp_obj_p, /**< RegExp object */
|
||||
const re_compiled_code_t *bc_p, /**< bytecode */
|
||||
ecma_string_t *pattern_str_p, /**< pattern */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
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))
|
||||
{
|
||||
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) */
|
||||
}
|
||||
#if !ENABLED (JERRY_ES2015)
|
||||
else
|
||||
{
|
||||
ecma_regexp_create_props (regexp_obj_p, pattern_str_p, flags);
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
JERRY_UNUSED (pattern_str_p);
|
||||
JERRY_UNUSED (flags);
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_obj_p->u.class_prop.u.value, bc_p);
|
||||
} /* ecma_op_regexp_initialize */
|
||||
|
||||
/**
|
||||
* Method for creating a RegExp object from pattern.
|
||||
*
|
||||
* See also: ECMA-262 v5, 15.10.4.1
|
||||
* Note:
|
||||
* Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
|
||||
*
|
||||
* @return constructed RegExp object - if pattern and flags were parsed successfully
|
||||
* error ecma value - otherwise
|
||||
*
|
||||
* Returned value must be freed with ecma_free_value
|
||||
* @return ecma_value_t
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_regexp_object (ecma_string_t *pattern_p, /**< input pattern */
|
||||
uint16_t flags) /**< flags */
|
||||
ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p, /**< RegExp object */
|
||||
ecma_value_t pattern_value, /**< pattern */
|
||||
ecma_value_t flags_value) /**< flags */
|
||||
{
|
||||
JERRY_ASSERT (pattern_p != NULL);
|
||||
ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value);
|
||||
uint16_t flags = 0;
|
||||
|
||||
ecma_object_t *re_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE);
|
||||
if (JERRY_UNLIKELY (pattern_str_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (re_prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_UNDEFINED;
|
||||
if (!ecma_is_value_undefined (flags_value))
|
||||
{
|
||||
ecma_string_t *flags_str_p = ecma_op_to_string (flags_value);
|
||||
|
||||
ecma_regexp_create_props (object_p);
|
||||
ecma_regexp_initialize_props (object_p, pattern_p, flags);
|
||||
if (JERRY_UNLIKELY (flags_str_p == NULL))
|
||||
{
|
||||
ecma_deref_ecma_string (pattern_str_p);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_value_t parse_flags_value = ecma_regexp_parse_flags (flags_str_p, &flags);
|
||||
ecma_deref_ecma_string (flags_str_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (parse_flags_value))
|
||||
{
|
||||
ecma_deref_ecma_string (pattern_str_p);
|
||||
return parse_flags_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (parse_flags_value));
|
||||
}
|
||||
|
||||
/* Compile bytecode. */
|
||||
const re_compiled_code_t *bc_p = NULL;
|
||||
ecma_value_t ret_value = re_compile_bytecode (&bc_p, pattern_p, flags);
|
||||
ecma_value_t ret_value = re_compile_bytecode (&bc_p, pattern_str_p, flags);
|
||||
ecma_deref_ecma_string (pattern_str_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_deref_object (object_p);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (ret_value));
|
||||
|
||||
/* Set [[Class]] and bytecode internal properties. */
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, bc_p);
|
||||
ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_regexp_object */
|
||||
return ecma_make_object_value (regexp_obj_p);
|
||||
} /* ecma_op_create_regexp_from_pattern */
|
||||
|
||||
/**
|
||||
* Method for creating a RegExp object from bytecode.
|
||||
*
|
||||
* Note:
|
||||
* Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
|
||||
*
|
||||
* @return ecma_value_t
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, /**< RegExp object */
|
||||
re_compiled_code_t *bc_p) /**< bytecode */
|
||||
{
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bc_p);
|
||||
ecma_string_t *pattern_str_p = ecma_get_string_from_value (bc_p->source);
|
||||
uint16_t flags = bc_p->header.status_flags;
|
||||
|
||||
ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
|
||||
|
||||
return ecma_make_object_value (regexp_obj_p);
|
||||
} /* ecma_op_create_regexp_from_bytecode */
|
||||
|
||||
/**
|
||||
* Method for creating a RegExp object from pattern with already parsed flags.
|
||||
*
|
||||
* Note:
|
||||
* Allocation have to happen before invoking this function using ecma_op_regexp_alloc.
|
||||
*
|
||||
* @return ecma_value_t
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p, /**< RegExp object */
|
||||
ecma_value_t pattern_value, /**< pattern */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
ecma_string_t *pattern_str_p = ecma_regexp_read_pattern_str_helper (pattern_value);
|
||||
|
||||
if (JERRY_UNLIKELY (pattern_str_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
const re_compiled_code_t *bc_p = NULL;
|
||||
|
||||
ecma_value_t ret_value = re_compile_bytecode (&bc_p, pattern_str_p, flags);
|
||||
|
||||
ecma_deref_ecma_string (pattern_str_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (ret_value));
|
||||
|
||||
ecma_op_regexp_initialize (regexp_obj_p, bc_p, pattern_str_p, flags);
|
||||
|
||||
return ecma_make_object_value (regexp_obj_p);
|
||||
} /* ecma_op_create_regexp_with_flags */
|
||||
|
||||
/**
|
||||
* Canonicalize a character
|
||||
@@ -1249,7 +1388,7 @@ ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */
|
||||
{
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
JERRY_ASSERT (ecma_object_class_is (regexp_object_p, LIT_MAGIC_STRING_REGEXP_UL));
|
||||
JERRY_ASSERT (ecma_object_is_regexp_object (ecma_make_object_value (regexp_object_p)));
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) regexp_object_p;
|
||||
re_compiled_code_t *bc_p = ECMA_GET_INTERNAL_VALUE_ANY_POINTER (re_compiled_code_t,
|
||||
@@ -2439,7 +2578,6 @@ ecma_regexp_replace_helper (ecma_value_t this_arg, /**< this argument */
|
||||
{
|
||||
ecma_extended_object_t *function_p = (ecma_extended_object_t *) ecma_get_object_from_value (result);
|
||||
if (ecma_object_class_is (this_obj_p, LIT_MAGIC_STRING_REGEXP_UL)
|
||||
&& !ecma_builtin_is (this_obj_p, ECMA_BUILTIN_ID_REGEXP_PROTOTYPE)
|
||||
&& ecma_builtin_is_regexp_exec (function_p))
|
||||
{
|
||||
result = ecma_op_object_get_by_magic_id (this_obj_p, LIT_MAGIC_STRING_STICKY);
|
||||
|
||||
@@ -97,22 +97,30 @@ typedef struct
|
||||
uint16_t flags; /**< RegExp flags */
|
||||
} ecma_regexp_ctx_t;
|
||||
|
||||
ecma_value_t ecma_op_create_regexp_object_from_bytecode (re_compiled_code_t *bytecode_p);
|
||||
ecma_value_t ecma_op_create_regexp_object (ecma_string_t *pattern_p, uint16_t flags);
|
||||
ecma_object_t *ecma_op_regexp_alloc (ecma_object_t *new_target_obj_p);
|
||||
ecma_value_t ecma_regexp_exec_helper (ecma_object_t *regexp_object_p,
|
||||
ecma_string_t *input_string_p);
|
||||
ecma_string_t *ecma_regexp_read_pattern_str_helper (ecma_value_t pattern_arg);
|
||||
lit_code_point_t ecma_regexp_canonicalize (lit_code_point_t ch, bool is_ignorecase);
|
||||
lit_code_point_t ecma_regexp_canonicalize_char (lit_code_point_t ch);
|
||||
ecma_value_t ecma_regexp_parse_flags (ecma_string_t *flags_str_p, uint16_t *flags_p);
|
||||
void ecma_regexp_initialize_props (ecma_object_t *re_obj_p, ecma_string_t *source_p, uint16_t flags);
|
||||
|
||||
void ecma_regexp_create_and_initialize_props (ecma_object_t *re_object_p,
|
||||
ecma_string_t *source_p,
|
||||
uint16_t flags);
|
||||
ecma_value_t ecma_regexp_replace_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t replace_arg);
|
||||
ecma_value_t ecma_regexp_search_helper (ecma_value_t regexp_arg, ecma_value_t string_arg);
|
||||
ecma_value_t ecma_regexp_split_helper (ecma_value_t this_arg, ecma_value_t string_arg, ecma_value_t limit_arg);
|
||||
ecma_value_t ecma_regexp_match_helper (ecma_value_t this_arg, ecma_value_t string_arg);
|
||||
|
||||
ecma_value_t ecma_op_regexp_exec (ecma_value_t this_arg, ecma_string_t *str_p);
|
||||
|
||||
ecma_value_t ecma_op_create_regexp_from_bytecode (ecma_object_t *regexp_obj_p, re_compiled_code_t *bc_p);
|
||||
ecma_value_t ecma_op_create_regexp_from_pattern (ecma_object_t *regexp_obj_p,
|
||||
ecma_value_t pattern_value,
|
||||
ecma_value_t flags_value);
|
||||
ecma_value_t ecma_op_create_regexp_with_flags (ecma_object_t *regexp_obj_p,
|
||||
ecma_value_t pattern_value,
|
||||
uint16_t flags);
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -51,6 +51,7 @@ 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 */
|
||||
|
||||
+4
-6
@@ -440,16 +440,14 @@ vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
#if ENABLED (JERRY_BUILTIN_REGEXP)
|
||||
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
|
||||
{
|
||||
ecma_value_t ret_value;
|
||||
ret_value = ecma_op_create_regexp_object_from_bytecode ((re_compiled_code_t *) bytecode_p);
|
||||
ecma_object_t *regexp_obj_p = ecma_op_regexp_alloc (NULL);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
if (JERRY_UNLIKELY (regexp_obj_p == NULL))
|
||||
{
|
||||
/* TODO: throw exception instead of define an 'undefined' value. */
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
return ecma_op_create_regexp_from_bytecode (regexp_obj_p, (re_compiled_code_t *) bytecode_p);;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
|
||||
|
||||
|
||||
@@ -14,12 +14,18 @@
|
||||
|
||||
var r = RegExp ("a","gim");
|
||||
var r2 = RegExp (r,"gim");
|
||||
var r3 = RegExp (r);
|
||||
|
||||
assert(r2.source === 'a');
|
||||
assert(r2.global === true);
|
||||
assert(r2.ignoreCase === true);
|
||||
assert(r2.multiline === true);
|
||||
|
||||
assert(r3.source === 'a');
|
||||
assert(r3.global === true);
|
||||
assert(r3.ignoreCase === true);
|
||||
assert(r3.multiline === true);
|
||||
|
||||
var obj = { get source() { throw 5 }, [Symbol.match] : true }
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user