diff --git a/jerry-core/ecma/base/ecma-helpers.cpp b/jerry-core/ecma/base/ecma-helpers.cpp index e30385d19..3ff849e13 100644 --- a/jerry-core/ecma/base/ecma-helpers.cpp +++ b/jerry-core/ecma/base/ecma-helpers.cpp @@ -829,8 +829,12 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ } case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: { - void *bytecode_p = ECMA_GET_NON_NULL_POINTER (void, property_value); - mem_heap_free_block (bytecode_p); + void *bytecode_p = ECMA_GET_POINTER (void, property_value); + + if (bytecode_p) + { + mem_heap_free_block (bytecode_p); + } } } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp index ee4b205ef..2afe5a8df 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.cpp @@ -15,6 +15,7 @@ */ #include "ecma-alloc.h" +#include "ecma-array-object.h" #include "ecma-builtins.h" #include "ecma-conversion.h" #include "ecma-exceptions.h" @@ -72,7 +73,44 @@ ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ ecma_op_to_string (arg), ret_value); - ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); + ecma_property_t *bytecode_prop_p; + ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); + bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); + + void *bytecode_p = ECMA_GET_POINTER (void, bytecode_prop_p->u.internal_property.value); + + if (bytecode_p == NULL) + { + /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ + ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); + ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); + ecma_string_t *input_str_p = ecma_get_string_from_value (input_str_value); + re_set_result_array_properties (result_array_obj_p, + input_str_p, + 1, + 0); + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (0); + ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + + ECMA_TRY_CATCH (put_res_value, + ecma_op_object_put (result_array_obj_p, + index_str_p, + ecma_make_string_value (capture_str_p), + true), + ret_value); + + ret_value = result_array; + + ECMA_FINALIZE (put_res_value) + + ecma_deref_ecma_string (capture_str_p); + ecma_deref_ecma_string (index_str_p); + } + else + { + ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); + } ECMA_FINALIZE (input_str_value); ECMA_FINALIZE (obj_this); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.cpp b/jerry-core/ecma/builtin-objects/ecma-builtins.cpp index 62be3f2fb..711e177bf 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.cpp @@ -167,8 +167,18 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_prop_num_value_p); break; } -#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */ +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */ +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN + case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE: + { + ecma_property_t *bytecode_prop_p; + bytecode_prop_p = ecma_create_internal_property (object_obj_p, + ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); + bytecode_prop_p->u.internal_property.value = ECMA_NULL_POINTER; + break; + } +#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */ default: { break; diff --git a/jerry-core/ecma/operations/ecma-regexp-object.cpp b/jerry-core/ecma/operations/ecma-regexp-object.cpp index b22dce876..78dd9ff2d 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.cpp +++ b/jerry-core/ecma/operations/ecma-regexp-object.cpp @@ -207,10 +207,11 @@ ecma_op_create_regexp_object (ecma_string_t *pattern_p, /**< input pattern */ ecma_dealloc_number (lastindex_num_p); /* Set bytecode internal property. */ - ecma_property_t *bytecode = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); + ecma_property_t *bytecode_prop_p; + bytecode_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Compile bytecode. */ - ECMA_TRY_CATCH (empty, re_compile_bytecode (bytecode, pattern_p, flags), ret_value); + ECMA_TRY_CATCH (empty, re_compile_bytecode (bytecode_prop_p, pattern_p, flags), ret_value); ret_value = ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); ECMA_FINALIZE (empty); @@ -1071,9 +1072,10 @@ re_match_regexp (re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */ /** * Define the necessary properties for the result array (index, input, length). */ -static void +void re_set_result_array_properties (ecma_object_t *array_obj_p, /**< result array */ - re_matcher_ctx_t *re_ctx_p, /**< RegExp matcher context */ + ecma_string_t *input_str_p, /**< input string */ + uint32_t num_of_elements, /**< Number of array elements */ int32_t index) /** index of matching */ { /* Set index property of the result array */ @@ -1111,9 +1113,6 @@ re_set_result_array_properties (ecma_object_t *array_obj_p, /**< result array */ ecma_property_descriptor_t array_item_prop_desc = ecma_make_empty_property_descriptor (); array_item_prop_desc.is_value_defined = true; - ecma_string_t *input_str_p = ecma_new_ecma_string_from_utf8 (re_ctx_p->input_start_p, - (lit_utf8_size_t) (re_ctx_p->input_end_p - - re_ctx_p->input_start_p)); array_item_prop_desc.value = ecma_make_string_value (input_str_p); array_item_prop_desc.is_writable_defined = true; @@ -1129,8 +1128,6 @@ re_set_result_array_properties (ecma_object_t *array_obj_p, /**< result array */ result_prop_str_p, &array_item_prop_desc, true); - - ecma_deref_ecma_string (input_str_p); } ecma_deref_ecma_string (result_prop_str_p); @@ -1142,7 +1139,7 @@ re_set_result_array_properties (ecma_object_t *array_obj_p, /**< result array */ array_item_prop_desc.is_value_defined = true; ecma_number_t *num_p = ecma_alloc_number (); - *num_p = (ecma_number_t) (re_ctx_p->num_of_captures / 2); + *num_p = (ecma_number_t) (num_of_elements); array_item_prop_desc.value = ecma_make_number_value (num_p); array_item_prop_desc.is_writable_defined = false; @@ -1315,7 +1312,9 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */ ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); - re_set_result_array_properties (result_array_obj_p, &re_ctx, index); + ecma_string_t *input_str_p = ecma_new_ecma_string_from_utf8 (iterator.buf_p, iterator.buf_size); + re_set_result_array_properties (result_array_obj_p, input_str_p, re_ctx.num_of_captures / 2, index); + ecma_deref_ecma_string (input_str_p); for (uint32_t i = 0; i < re_ctx.num_of_captures; i += 2) { diff --git a/jerry-core/ecma/operations/ecma-regexp-object.h b/jerry-core/ecma/operations/ecma-regexp-object.h index 6d86daad4..c06ca8351 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.h +++ b/jerry-core/ecma/operations/ecma-regexp-object.h @@ -59,6 +59,11 @@ ecma_regexp_exec_helper (ecma_value_t, ecma_value_t, bool); extern ecma_char_t re_canonicalize (ecma_char_t ch, bool is_ignorecase); +extern void +re_set_result_array_properties (ecma_object_t *array_obj_p, + ecma_string_t *input_str_p, + uint32_t num_of_elements, + int32_t index); /** * @} diff --git a/tests/jerry/regression-test-issue-312.js b/tests/jerry/regression-test-issue-312.js new file mode 100644 index 000000000..a3f063f4d --- /dev/null +++ b/tests/jerry/regression-test-issue-312.js @@ -0,0 +1,21 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var res = RegExp.prototype.exec(10); + +assert (res[0] === ""); +assert (res.input === "10"); +assert (res.index === 0); +assert (res.length === 1);