From 49aa784741deb71b3aab937b7a0420173063ee32 Mon Sep 17 00:00:00 2001 From: Rafal Walczyna Date: Wed, 13 May 2020 11:53:54 +0200 Subject: [PATCH] Add support of escaping backslash and backtick to String.raw Template literals already supports escaping backslash and backtick, this commit enables escaping this in String.raw. It also fixes invalid behaviour of String.raw when using new line character. JerryScript-DCO-1.0-Signed-off-by: Rafal Walczyna r.walczyna@samsung.com --- jerry-core/parser/js/js-lexer.c | 19 ++++++++++++++ .../js/js-parser-tagged-template-literal.c | 2 +- .../string-raw-crash-escaping-backslash.js | 26 +++++++++++++++++++ tests/jerry/es2015/string-raw.js | 7 +++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/jerry/es2015/string-raw-crash-escaping-backslash.js diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index f661003348..ea257c5ae4 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -974,6 +974,9 @@ lexer_parse_string (parser_context_t *context_p, /**< context */ else if (*source_p == LEXER_NEWLINE_LS_PS_BYTE_1 && LEXER_NEWLINE_LS_PS_BYTE_23 (source_p)) { source_p += 3; +#if ENABLED (JERRY_ES2015) + length += 3 * raw_length_inc; +#endif /* ENABLED (JERRY_ES2015) */ line++; column = 1; continue; @@ -982,6 +985,12 @@ lexer_parse_string (parser_context_t *context_p, /**< context */ #if ENABLED (JERRY_ES2015) if (opts & LEXER_STRING_RAW) { + if ((*source_p == LIT_CHAR_GRAVE_ACCENT) || (*source_p == LIT_CHAR_BACKSLASH)) + { + source_p++; + column++; + length++; + } continue; } #endif /* ENABLED (JERRY_ES2015) */ @@ -2206,6 +2215,16 @@ lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */ } continue; } + if ((*source_p == LIT_CHAR_BACKSLASH) && is_raw) + { + JERRY_ASSERT (source_p + 1 < context_p->source_end_p); + if ((*(source_p + 1) == LIT_CHAR_GRAVE_ACCENT) || (*(source_p + 1) == LIT_CHAR_BACKSLASH)) + { + *destination_p++ = *source_p++; + *destination_p++ = *source_p++; + continue; + } + } } #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/parser/js/js-parser-tagged-template-literal.c b/jerry-core/parser/js/js-parser-tagged-template-literal.c index cb4dca9725..b8251ef871 100644 --- a/jerry-core/parser/js/js-parser-tagged-template-literal.c +++ b/jerry-core/parser/js/js-parser-tagged-template-literal.c @@ -43,7 +43,7 @@ parser_tagged_template_literal_append_strings (parser_context_t *context_p, /**< { lexer_lit_location_t *lit_loc_p = &context_p->token.lit_location; - if (lit_loc_p->length == 0) + if (lit_loc_p->length == 0 && !lit_loc_p->has_escape) { ecma_builtin_helper_def_prop_by_index (template_obj_p, prop_idx, diff --git a/tests/jerry/es2015/string-raw-crash-escaping-backslash.js b/tests/jerry/es2015/string-raw-crash-escaping-backslash.js new file mode 100644 index 0000000000..f5b29bc0ac --- /dev/null +++ b/tests/jerry/es2015/string-raw-crash-escaping-backslash.js @@ -0,0 +1,26 @@ +/* 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. + */ + +/* This test must be left unchanged - testing JerryScript crash */ + +try +{ + var s = 'print(String.raw`\\`)\n// `'; + eval (s) + asserts(false) +} +catch (error) +{ +} diff --git a/tests/jerry/es2015/string-raw.js b/tests/jerry/es2015/string-raw.js index 5a44a8d09c..5710271a9c 100644 --- a/tests/jerry/es2015/string-raw.js +++ b/tests/jerry/es2015/string-raw.js @@ -62,3 +62,10 @@ var raw = new Proxy({length: 2, 0: '', 1: ''}, { get: function(o, k) { get.push( var p = new Proxy({raw: raw}, { get: function(o, k) { get.push(k); return o[k]; }}); String.raw(p); assert(get + '' === "raw,length,0,1"); + +assert(String.raw`\\` == "\\\\") +assert(String.raw`\`` == "\\`") +assert(String.raw`\ +\ +` == "\\\n\\\n") +assert(String.raw`\
` == "\\\u2029")