diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c
index 31b9fd859..8f3732a8b 100644
--- a/jerry-core/ecma/operations/ecma-regexp-object.c
+++ b/jerry-core/ecma/operations/ecma-regexp-object.c
@@ -1921,7 +1921,7 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */
ecma_value_t result = ECMA_VALUE_ERROR;
- /* 3-4. */
+ /* 3. */
ecma_string_t *const string_p = ecma_op_to_string (string_arg);
if (string_p == NULL)
{
@@ -1930,7 +1930,7 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */
ecma_object_t *const regexp_object_p = ecma_get_object_from_value (regexp_arg);
- /* 5-6. */
+ /* 4. */
ecma_string_t *const last_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
const ecma_value_t prev_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p);
if (ECMA_IS_VALUE_ERROR (prev_last_index))
@@ -1938,35 +1938,56 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */
goto cleanup_string;
}
- /* 7-8. */
- const ecma_value_t status = ecma_op_object_put (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), true);
- if (ECMA_IS_VALUE_ERROR (status))
+ /* 5. */
+ if (prev_last_index != ecma_make_uint32_value (0))
{
- ecma_free_value (prev_last_index);
- goto cleanup_string;
+ const ecma_value_t status = ecma_op_object_put (regexp_object_p,
+ last_index_str_p,
+ ecma_make_uint32_value (0),
+ true);
+
+ if (ECMA_IS_VALUE_ERROR (status))
+ {
+ goto cleanup_prev_last_index;
+ }
+
+ JERRY_ASSERT (ecma_is_value_boolean (status));
}
- JERRY_ASSERT (ecma_is_value_boolean (status));
-
- /* 9-10. */
+ /* 6. */
const ecma_value_t match = ecma_op_regexp_exec (regexp_arg, string_p);
if (ECMA_IS_VALUE_ERROR (match))
{
- ecma_free_value (prev_last_index);
- goto cleanup_string;
+ goto cleanup_prev_last_index;
}
- /* 11-12. */
- result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true);
- ecma_free_value (prev_last_index);
-
- if (ECMA_IS_VALUE_ERROR (result))
+ /* 7. */
+ const ecma_value_t current_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p);
+ if (ECMA_IS_VALUE_ERROR (current_last_index))
{
ecma_free_value (match);
- goto cleanup_string;
+ goto cleanup_prev_last_index;
}
- /* 13-14. */
+ const bool same_value = ecma_op_same_value (prev_last_index, current_last_index);
+
+ ecma_free_value (current_last_index);
+
+ /* 8. */
+ if (!same_value)
+ {
+ result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ ecma_free_value (match);
+ goto cleanup_prev_last_index;
+ }
+
+ JERRY_ASSERT (ecma_is_value_boolean (result));
+ }
+
+ /* 9-10. */
if (ecma_is_value_null (match))
{
result = ecma_make_int32_value (-1);
@@ -1978,6 +1999,9 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */
ecma_deref_object (match_p);
}
+cleanup_prev_last_index:
+ ecma_free_value (prev_last_index);
+
cleanup_string:
ecma_deref_ecma_string (string_p);
return result;
diff --git a/tests/jerry/es.next/symbol-search.js b/tests/jerry/es.next/symbol-search.js
index 5f664d5e8..dd8d9cc19 100644
--- a/tests/jerry/es.next/symbol-search.js
+++ b/tests/jerry/es.next/symbol-search.js
@@ -226,3 +226,70 @@ o = {
}
assert (RegExp.prototype[Symbol.search].call (o, "str") === 0);
+
+var r = /a/;
+r.lastIndex = 3.14;
+
+var get_calls = [];
+var set_calls = [];
+
+var handler = {
+ get: function(o, k) {
+ get_calls.push(k);
+
+ if (k === "exec") {
+ return (str) => r.exec(str);
+ }
+
+ return r[k];
+ },
+ set: function(o, k, v) {
+ set_calls.push(k);
+ r[k] = v;
+ }
+};
+
+var p = new Proxy(r, handler);
+assert (search.call(p, "bba") === 2);
+
+assert (get_calls.join(",") === "lastIndex,exec,lastIndex");
+assert (set_calls.join(",") === "lastIndex,lastIndex");
+assert (r.lastIndex === 3.14);
+
+var o = {
+ get lastIndex() {
+ Object.defineProperty(o, "lastIndex", {
+ get: function () { throw "abrupt get second lastIndex"; }
+ });
+ return 1;
+ },
+ set lastIndex(v) {},
+ exec: () => { return null; }
+}
+
+try {
+ search.call(o, "str");
+ assert (false);
+} catch (e) {
+ assert (e === "abrupt get second lastIndex");
+}
+
+var index = 1;
+var o = {
+ get lastIndex() {
+ return index++;
+ },
+ set lastIndex(v) {
+ Object.defineProperty(o, "lastIndex", {
+ set: function (v) { throw "abrupt set second lastIndex"; }
+ });
+ },
+ exec: () => { return null; }
+}
+
+try {
+ search.call(o, "str");
+ assert (false);
+} catch (e) {
+ assert (e === "abrupt set second lastIndex");
+}
diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml
index 95031e99c..30ad9c783 100644
--- a/tests/test262-es6-excludelist.xml
+++ b/tests/test262-es6-excludelist.xml
@@ -378,4 +378,6 @@
Unicode 13: 0x180E is no longer whitespace character
Unicode 13: 0x180E is no longer whitespace character
Unicode 13: 0x180E is no longer whitespace character
+ lastIndex handling in Symbol.search has changed since ES6
+ lastIndex handling in Symbol.search has changed since ES6