Update String.prototype.match to ECMA-262 v6 (#3375)
The algorithm is based on ECMA-262 v6, 21.1.3.11 JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
committed by
Dániel Bátyai
parent
531f1e9687
commit
7c0b1ca88a
@@ -630,164 +630,7 @@ static ecma_value_t
|
|||||||
ecma_builtin_regexp_prototype_symbol_match (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_regexp_prototype_symbol_match (ecma_value_t this_arg, /**< this argument */
|
||||||
ecma_value_t string_arg) /**< source string */
|
ecma_value_t string_arg) /**< source string */
|
||||||
{
|
{
|
||||||
if (!ecma_is_value_object (this_arg))
|
return ecma_regexp_match_helper (this_arg, string_arg);
|
||||||
{
|
|
||||||
return ecma_raise_type_error (ECMA_ERR_MSG ("TypeError"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_string_t *str_p = ecma_op_to_string (string_arg);
|
|
||||||
|
|
||||||
if (JERRY_UNLIKELY (str_p == NULL))
|
|
||||||
{
|
|
||||||
return ECMA_VALUE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
|
|
||||||
|
|
||||||
ecma_value_t global_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_GLOBAL);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (global_value))
|
|
||||||
{
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
return global_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool global = ecma_op_to_boolean (global_value);
|
|
||||||
|
|
||||||
ecma_free_value (global_value);
|
|
||||||
|
|
||||||
if (!global)
|
|
||||||
{
|
|
||||||
ecma_value_t result = ecma_op_regexp_exec (this_arg, str_p);
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_value_t full_unicode_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_UNICODE);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (full_unicode_value))
|
|
||||||
{
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
return full_unicode_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool full_unicode = ecma_op_to_boolean (full_unicode_value);
|
|
||||||
|
|
||||||
ecma_free_value (full_unicode_value);
|
|
||||||
|
|
||||||
ecma_value_t set_status = ecma_op_object_put (obj_p,
|
|
||||||
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
|
||||||
ecma_make_uint32_value (0),
|
|
||||||
true);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (set_status))
|
|
||||||
{
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
return set_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_value_t ret_value = ECMA_VALUE_ERROR;
|
|
||||||
ecma_value_t result_array = ecma_op_create_array_object (0, 0, false);
|
|
||||||
ecma_object_t *result_array_p = ecma_get_object_from_value (result_array);
|
|
||||||
uint32_t n = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ecma_value_t result_value = ecma_op_regexp_exec (this_arg, str_p);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (result_value))
|
|
||||||
{
|
|
||||||
goto result_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ecma_is_value_null (result_value))
|
|
||||||
{
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
ret_value = ECMA_VALUE_NULL;
|
|
||||||
goto result_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
return result_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_object_t *result_value_p = ecma_get_object_from_value (result_value);
|
|
||||||
ecma_value_t match_str_value = ecma_op_object_get_by_uint32_index (result_value_p, 0);
|
|
||||||
|
|
||||||
ecma_deref_object (result_value_p);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (match_str_value))
|
|
||||||
{
|
|
||||||
goto result_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_string_t *match_str_p = ecma_op_to_string (match_str_value);
|
|
||||||
|
|
||||||
if (JERRY_UNLIKELY (match_str_p == NULL))
|
|
||||||
{
|
|
||||||
ecma_free_value (match_str_value);
|
|
||||||
goto result_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_value_t new_prop = ecma_builtin_helper_def_prop_by_index (result_array_p,
|
|
||||||
n,
|
|
||||||
match_str_value,
|
|
||||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
|
||||||
|
|
||||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_prop));
|
|
||||||
|
|
||||||
ecma_value_t match_result = ECMA_VALUE_ERROR;
|
|
||||||
if (ecma_string_is_empty (match_str_p))
|
|
||||||
{
|
|
||||||
ecma_value_t this_index = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (this_index))
|
|
||||||
{
|
|
||||||
goto match_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t index;
|
|
||||||
ecma_value_t length_value = ecma_op_to_length (this_index, &index);
|
|
||||||
|
|
||||||
ecma_free_value (this_index);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (length_value))
|
|
||||||
{
|
|
||||||
goto match_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t next_index = ecma_op_advance_string_index (str_p, index, full_unicode);
|
|
||||||
|
|
||||||
ecma_value_t next_set_status = ecma_op_object_put (obj_p,
|
|
||||||
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
|
||||||
ecma_make_uint32_value (next_index),
|
|
||||||
true);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (next_set_status))
|
|
||||||
{
|
|
||||||
goto match_cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match_result = ECMA_VALUE_EMPTY;
|
|
||||||
|
|
||||||
match_cleanup:
|
|
||||||
ecma_deref_ecma_string (match_str_p);
|
|
||||||
ecma_free_value (match_str_value);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (match_result))
|
|
||||||
{
|
|
||||||
goto result_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
result_cleanup:
|
|
||||||
ecma_deref_ecma_string (str_p);
|
|
||||||
ecma_deref_object (result_array_p);
|
|
||||||
return ret_value;
|
|
||||||
} /* ecma_builtin_regexp_prototype_symbol_match */
|
} /* ecma_builtin_regexp_prototype_symbol_match */
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "ecma-array-object.h"
|
#include "ecma-array-object.h"
|
||||||
#include "ecma-builtin-helpers.h"
|
#include "ecma-builtin-helpers.h"
|
||||||
#include "ecma-builtins.h"
|
#include "ecma-builtins.h"
|
||||||
|
#include "ecma-builtin-regexp.inc.h"
|
||||||
#include "ecma-conversion.h"
|
#include "ecma-conversion.h"
|
||||||
#include "ecma-exceptions.h"
|
#include "ecma-exceptions.h"
|
||||||
#include "ecma-function-object.h"
|
#include "ecma-function-object.h"
|
||||||
@@ -317,180 +318,90 @@ 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_to_string_value, /**< this argument */
|
||||||
ecma_value_t regexp_arg) /**< routine's argument */
|
ecma_value_t regexp_arg) /**< routine's argument */
|
||||||
{
|
{
|
||||||
ecma_value_t regexp_value = ECMA_VALUE_EMPTY;
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
if (!(ecma_is_value_undefined (regexp_arg) || ecma_is_value_null (regexp_arg)))
|
||||||
ecma_value_t ret_value = ecma_builtin_string_prepare_search (regexp_arg, ®exp_value);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
|
||||||
{
|
{
|
||||||
return ret_value;
|
ecma_value_t matcher = ecma_op_get_method_by_symbol_id (regexp_arg, LIT_MAGIC_STRING_MATCH);
|
||||||
}
|
|
||||||
|
|
||||||
JERRY_ASSERT (!ecma_is_value_empty (regexp_value));
|
if (ECMA_IS_VALUE_ERROR (matcher))
|
||||||
ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_value);
|
|
||||||
|
|
||||||
/* 5. */
|
|
||||||
ecma_value_t global_value = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_GLOBAL);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (global_value))
|
|
||||||
{
|
|
||||||
ecma_deref_object (regexp_obj_p);
|
|
||||||
return global_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_string_t *this_string_p = ecma_get_string_from_value (this_to_string_value);
|
|
||||||
ecma_ref_ecma_string (this_string_p);
|
|
||||||
|
|
||||||
JERRY_ASSERT (ecma_is_value_boolean (global_value));
|
|
||||||
|
|
||||||
if (ecma_is_value_false (global_value))
|
|
||||||
{
|
|
||||||
/* 7. */
|
|
||||||
ret_value = ecma_regexp_exec_helper (regexp_value, this_to_string_value, false);
|
|
||||||
ecma_deref_ecma_string (this_string_p);
|
|
||||||
ecma_deref_object (regexp_obj_p);
|
|
||||||
return ret_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8.a. */
|
|
||||||
ecma_string_t *index_zero_string_p = ecma_get_ecma_string_from_uint32 (0);
|
|
||||||
|
|
||||||
ecma_value_t put_value = ecma_op_object_put (regexp_obj_p,
|
|
||||||
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
|
||||||
ecma_make_integer_value (0),
|
|
||||||
true);
|
|
||||||
|
|
||||||
JERRY_ASSERT (ecma_is_value_boolean (put_value)
|
|
||||||
|| ecma_is_value_empty (put_value)
|
|
||||||
|| ECMA_IS_VALUE_ERROR (put_value));
|
|
||||||
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (put_value))
|
|
||||||
{
|
|
||||||
ecma_deref_ecma_string (this_string_p);
|
|
||||||
ecma_deref_object (regexp_obj_p);
|
|
||||||
return put_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8.b. */
|
|
||||||
ecma_value_t new_array_value = ecma_op_create_array_object (NULL, 0, false);
|
|
||||||
|
|
||||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array_value));
|
|
||||||
|
|
||||||
ecma_object_t *new_array_obj_p = ecma_get_object_from_value (new_array_value);
|
|
||||||
|
|
||||||
/* 8.c. */
|
|
||||||
ecma_number_t previous_last_index = 0;
|
|
||||||
/* 8.d. */
|
|
||||||
uint32_t n = 0;
|
|
||||||
/* 8.e. */
|
|
||||||
bool last_match = true;
|
|
||||||
|
|
||||||
ret_value = ECMA_VALUE_ERROR;
|
|
||||||
|
|
||||||
/* 8.f. */
|
|
||||||
while (last_match)
|
|
||||||
{
|
|
||||||
/* 8.f.i. */
|
|
||||||
ecma_value_t exec_value = ecma_regexp_exec_helper (regexp_value, this_to_string_value, false);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (exec_value))
|
|
||||||
{
|
{
|
||||||
break;
|
return matcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ecma_is_value_null (exec_value))
|
if (!ecma_is_value_undefined (matcher))
|
||||||
{
|
{
|
||||||
/* 8.f.ii. */
|
ecma_object_t *matcher_method = ecma_get_object_from_value (matcher);
|
||||||
break;
|
ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_to_string_value, 1);
|
||||||
|
ecma_deref_object (matcher_method);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8.f.iii. */
|
|
||||||
ecma_value_t this_index_value = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (this_index_value))
|
|
||||||
{
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_value_t this_index_number = ecma_op_to_number (this_index_value);
|
|
||||||
|
|
||||||
if (ECMA_IS_VALUE_ERROR (this_index_value))
|
|
||||||
{
|
|
||||||
ecma_free_value (this_index_value);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_number_t this_index = ecma_get_number_from_value (this_index_number);
|
|
||||||
|
|
||||||
/* 8.f.iii.2. */
|
|
||||||
if (this_index == previous_last_index)
|
|
||||||
{
|
|
||||||
/* 8.f.iii.2.a. */
|
|
||||||
ecma_value_t index_put_value = ecma_op_object_put (regexp_obj_p,
|
|
||||||
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
|
||||||
ecma_make_number_value (this_index + 1),
|
|
||||||
true);
|
|
||||||
if (ECMA_IS_VALUE_ERROR (index_put_value))
|
|
||||||
{
|
|
||||||
ecma_free_value (this_index_value);
|
|
||||||
ecma_free_number (this_index_number);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8.f.iii.2.b. */
|
|
||||||
previous_last_index = this_index + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 8.f.iii.3. */
|
|
||||||
previous_last_index = this_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8.f.iii.4. */
|
|
||||||
JERRY_ASSERT (ecma_is_value_object (exec_value));
|
|
||||||
ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value);
|
|
||||||
|
|
||||||
ecma_value_t match_string_value = ecma_op_object_get (exec_obj_p, index_zero_string_p);
|
|
||||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (match_string_value));
|
|
||||||
|
|
||||||
/* 8.f.iii.5. */
|
|
||||||
ecma_value_t completion;
|
|
||||||
completion = ecma_builtin_helper_def_prop_by_index (new_array_obj_p,
|
|
||||||
n,
|
|
||||||
match_string_value,
|
|
||||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
|
||||||
|
|
||||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
|
||||||
/* 8.f.iii.6. */
|
|
||||||
n++;
|
|
||||||
|
|
||||||
ecma_free_value (match_string_value);
|
|
||||||
ecma_free_value (this_index_value);
|
|
||||||
ecma_free_number (this_index_number);
|
|
||||||
|
|
||||||
ecma_deref_object (exec_obj_p);
|
|
||||||
}
|
}
|
||||||
|
#else /* !ENABLED (JERRY_ES2015) */
|
||||||
if (n == 0)
|
if (ecma_object_is_regexp_object (regexp_arg))
|
||||||
{
|
{
|
||||||
/* 8.g. */
|
return ecma_regexp_match_helper (regexp_arg, this_to_string_value);
|
||||||
ret_value = ECMA_VALUE_NULL;
|
|
||||||
}
|
}
|
||||||
else
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
ecma_string_t *pattern_p = ecma_regexp_read_pattern_str_helper (regexp_arg);
|
||||||
|
|
||||||
|
if (JERRY_UNLIKELY (pattern_p == NULL))
|
||||||
{
|
{
|
||||||
/* 8.h. */
|
return ECMA_VALUE_ERROR;
|
||||||
ecma_ref_object (new_array_obj_p);
|
|
||||||
ret_value = new_array_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
ecma_value_t new_regexp = ecma_op_create_regexp_object (pattern_p, 0);
|
||||||
ecma_deref_object (new_array_obj_p);
|
|
||||||
|
|
||||||
ecma_deref_object (regexp_obj_p);
|
ecma_deref_ecma_string (pattern_p);
|
||||||
ecma_deref_ecma_string (this_string_p);
|
|
||||||
|
|
||||||
return ret_value;
|
if (ECMA_IS_VALUE_ERROR (new_regexp))
|
||||||
|
{
|
||||||
|
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_MAGIC_STRING_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_free_value (new_regexp);
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
return result;
|
||||||
} /* ecma_builtin_string_prototype_object_match */
|
} /* ecma_builtin_string_prototype_object_match */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2248,6 +2248,192 @@ cleanup_string:
|
|||||||
return result;
|
return result;
|
||||||
} /* ecma_regexp_replace_helper */
|
} /* ecma_regexp_replace_helper */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for RegExp based matching
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* String.prototype.match
|
||||||
|
* RegExp.prototype[@@match]
|
||||||
|
*
|
||||||
|
* @return ecma_value_t
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */
|
||||||
|
ecma_value_t string_arg) /**< source string */
|
||||||
|
{
|
||||||
|
if (!ecma_is_value_object (this_arg))
|
||||||
|
{
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG ("'this' is not an object."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_string_t *str_p = ecma_op_to_string (string_arg);
|
||||||
|
|
||||||
|
if (JERRY_UNLIKELY (str_p == NULL))
|
||||||
|
{
|
||||||
|
return ECMA_VALUE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
|
||||||
|
|
||||||
|
ecma_value_t global_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_GLOBAL);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (global_value))
|
||||||
|
{
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
return global_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool global = ecma_op_to_boolean (global_value);
|
||||||
|
|
||||||
|
ecma_free_value (global_value);
|
||||||
|
|
||||||
|
if (!global)
|
||||||
|
{
|
||||||
|
ecma_value_t result = ecma_op_regexp_exec (this_arg, str_p);
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
ecma_value_t full_unicode_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_UNICODE);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (full_unicode_value))
|
||||||
|
{
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
return full_unicode_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool full_unicode = ecma_op_to_boolean (full_unicode_value);
|
||||||
|
|
||||||
|
ecma_free_value (full_unicode_value);
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
ecma_value_t set_status = ecma_op_object_put (obj_p,
|
||||||
|
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
||||||
|
ecma_make_uint32_value (0),
|
||||||
|
true);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (set_status))
|
||||||
|
{
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
return set_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_value_t ret_value = ECMA_VALUE_ERROR;
|
||||||
|
ecma_value_t result_array = ecma_op_create_array_object (0, 0, false);
|
||||||
|
ecma_object_t *result_array_p = ecma_get_object_from_value (result_array);
|
||||||
|
uint32_t n = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ecma_value_t result_value = ecma_op_regexp_exec (this_arg, str_p);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (result_value))
|
||||||
|
{
|
||||||
|
goto result_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecma_is_value_null (result_value))
|
||||||
|
{
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
ret_value = ECMA_VALUE_NULL;
|
||||||
|
goto result_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
return result_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *result_value_p = ecma_get_object_from_value (result_value);
|
||||||
|
ecma_value_t match_str_value = ecma_op_object_get_by_uint32_index (result_value_p, 0);
|
||||||
|
|
||||||
|
ecma_deref_object (result_value_p);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (match_str_value))
|
||||||
|
{
|
||||||
|
goto result_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_string_t *match_str_p = ecma_op_to_string (match_str_value);
|
||||||
|
|
||||||
|
if (JERRY_UNLIKELY (match_str_p == NULL))
|
||||||
|
{
|
||||||
|
ecma_free_value (match_str_value);
|
||||||
|
goto result_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_value_t new_prop = ecma_builtin_helper_def_prop_by_index (result_array_p,
|
||||||
|
n,
|
||||||
|
match_str_value,
|
||||||
|
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
||||||
|
|
||||||
|
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_prop));
|
||||||
|
|
||||||
|
ecma_value_t match_result = ECMA_VALUE_ERROR;
|
||||||
|
if (ecma_string_is_empty (match_str_p))
|
||||||
|
{
|
||||||
|
ecma_value_t this_index = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LASTINDEX_UL);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (this_index))
|
||||||
|
{
|
||||||
|
goto match_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ES2015)
|
||||||
|
uint32_t index;
|
||||||
|
ecma_value_t length_value = ecma_op_to_length (this_index, &index);
|
||||||
|
|
||||||
|
ecma_free_value (this_index);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (length_value))
|
||||||
|
{
|
||||||
|
goto match_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t next_index = ecma_op_advance_string_index (str_p, index, full_unicode);
|
||||||
|
|
||||||
|
ecma_value_t next_set_status = ecma_op_object_put (obj_p,
|
||||||
|
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
||||||
|
ecma_make_uint32_value (next_index),
|
||||||
|
true);
|
||||||
|
#else /* !ENABLED (JERRY_ES2015) */
|
||||||
|
ecma_number_t next_index = ecma_get_number_from_value (this_index);
|
||||||
|
|
||||||
|
ecma_value_t next_set_status = ecma_op_object_put (obj_p,
|
||||||
|
ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL),
|
||||||
|
ecma_make_number_value (next_index + 1),
|
||||||
|
true);
|
||||||
|
|
||||||
|
ecma_free_value (this_index);
|
||||||
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (next_set_status))
|
||||||
|
{
|
||||||
|
goto match_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match_result = ECMA_VALUE_EMPTY;
|
||||||
|
|
||||||
|
match_cleanup:
|
||||||
|
ecma_deref_ecma_string (match_str_p);
|
||||||
|
ecma_free_value (match_str_value);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (match_result))
|
||||||
|
{
|
||||||
|
goto result_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_cleanup:
|
||||||
|
ecma_deref_ecma_string (str_p);
|
||||||
|
ecma_deref_object (result_array_p);
|
||||||
|
return ret_value;
|
||||||
|
} /* ecma_regexp_match_helper */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RegExpExec operation
|
* RegExpExec operation
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ ecma_regexp_replace_helper (ecma_value_t this_arg,
|
|||||||
ecma_value_t string_arg,
|
ecma_value_t string_arg,
|
||||||
ecma_value_t replace_arg);
|
ecma_value_t replace_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_regexp_exec (ecma_value_t this_arg, ecma_string_t *str_p);
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
class NewRegExp extends RegExp {
|
||||||
|
[Symbol.match](str) {
|
||||||
|
var result = RegExp.prototype[Symbol.match].call(this, str);
|
||||||
|
var successful = 0;
|
||||||
|
if (result) {
|
||||||
|
successful = 1;
|
||||||
|
}
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var str = 'This is a random string.';
|
||||||
|
var regexp = new NewRegExp(/[A-Z]/g);
|
||||||
|
assert(str.match(regexp) === 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String.prototype.match.call(null, regexp);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
var regexp2 = /[A-Z]/g;
|
||||||
|
regexp2[Symbol.match] = "foo";
|
||||||
|
|
||||||
|
try {
|
||||||
|
str.match(regexp2);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty (regexp2, Symbol.match, { get () { throw 5 }});
|
||||||
|
|
||||||
|
try {
|
||||||
|
str.match(regexp2);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e === 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrong_sytnax = "str.match(/[A-5]/g";
|
||||||
|
|
||||||
|
try {
|
||||||
|
eval(wrong_sytnax);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof SyntaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(RegExp.prototype[Symbol.match]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
str.match(regexp);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
var regexp3 = "foo";
|
||||||
|
RegExp.prototype[Symbol.match] = 3;
|
||||||
|
|
||||||
|
try {
|
||||||
|
str.match(regexp3);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof TypeError);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user