diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c index cb48bd579..6acf34b46 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c @@ -137,6 +137,75 @@ ecma_builtin_regexp_prototype_get_flags (ecma_value_t this_arg) /**< this argume return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); } /* ecma_builtin_regexp_prototype_get_flags */ +/** + * The EscapeRegExpPattern method. + * + * See also: + * ECMA-262 v6, 21.2.3.2.4 + * + * @return ecma_value_t + */ +static ecma_value_t +ecma_op_escape_regexp_pattern (ecma_string_t *pattern_str_p) /**< RegExp pattern */ +{ + ecma_stringbuilder_t builder = ecma_stringbuilder_create (); + + ECMA_STRING_TO_UTF8_STRING (pattern_str_p, pattern_start_p, pattern_start_size); + + const lit_utf8_byte_t *pattern_str_curr_p = pattern_start_p; + const lit_utf8_byte_t *pattern_str_end_p = pattern_start_p + pattern_start_size; + + while (pattern_str_curr_p < pattern_str_end_p) + { + ecma_char_t c = lit_cesu8_read_next (&pattern_str_curr_p); + + switch (c) + { + case LIT_CHAR_SLASH: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\/", 2); + break; + } + case LIT_CHAR_LF: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\n", 2); + break; + } + case LIT_CHAR_CR: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\r", 2); + break; + } + case LIT_CHAR_LS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2028", 6); + break; + } + case LIT_CHAR_PS: + { + ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\\u2029", 6); + break; + } + case LIT_CHAR_BACKSLASH: + { + JERRY_ASSERT (pattern_str_curr_p < pattern_str_end_p); + ecma_stringbuilder_append_char (&builder, LIT_CHAR_BACKSLASH); + ecma_stringbuilder_append_char (&builder, lit_cesu8_read_next (&pattern_str_curr_p)); + break; + } + default: + { + ecma_stringbuilder_append_char (&builder, c); + break; + } + } + } + + ECMA_FINALIZE_UTF8_STRING (pattern_start_p, pattern_start_size); + + return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); +} /* ecma_op_escape_regexp_pattern */ + /** * The RegExp.prototype object's 'source' accessor property * @@ -162,8 +231,7 @@ ecma_builtin_regexp_prototype_get_source (ecma_value_t this_arg) /**< this argum if (bc_p != NULL) { - ecma_ref_ecma_string (ecma_get_string_from_value (bc_p->source)); - return bc_p->source; + 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)); diff --git a/tests/jerry/es2015/regexp-prototype-source.js b/tests/jerry/es2015/regexp-prototype-source.js new file mode 100644 index 000000000..15f940f2a --- /dev/null +++ b/tests/jerry/es2015/regexp-prototype-source.js @@ -0,0 +1,40 @@ +// 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. + +var regexp = /fooBar/ig; +assert(regexp.source === 'fooBar'); + +assert(new RegExp().source === '(?:)'); + +assert(new RegExp('/foo/').source === '\\/foo\\/'); +assert(new RegExp('/foo/').source.length === 7); + +assert(new RegExp('bar', 'ug').source === 'bar'); + +assert(new RegExp('/\?/').source === '\\/?\\/'); +assert(new RegExp('/\?/').source.length === 5); + +assert(new RegExp('\n').source === '\\n'); + +assert(new RegExp('\r').source === '\\r'); + +assert(new RegExp('\u2028').source === '\\u2028'); + +assert(new RegExp('\u2029').source === '\\u2029'); + +assert(new RegExp('/\n/').source === '\\/\\n\\/'); +assert(new RegExp('/\n/').source.length === 6); + +assert(new RegExp(/\/\//).source === '\\/\\/'); +assert(new RegExp(/\?\//g).source === '\\?\\/');