diff options
author | davidot <david.tuin@gmail.com> | 2021-09-01 18:34:19 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-09-06 08:43:38 +0100 |
commit | 3fee7b0d0b1985bf91e6b0b771cfb0e1eb777a04 (patch) | |
tree | 647de20df649ad7cf0127e123ddd8436fbc5f2bf /Userland | |
parent | f2512071f2824574dc2e3044eee0cffbeb8629c8 (diff) | |
download | serenity-3fee7b0d0b1985bf91e6b0b771cfb0e1eb777a04.zip |
LibJS: Fix that windows style line endings were not ignored or converted
These are tested by test262 but the current test262-runner reads the
files in python which automatically converts \r\n to \n.
This meant that we passed the tests while we should not have.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/Parser.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/parser-line-terminators.js | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Token.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Token.h | 1 |
4 files changed, 51 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index 7a3437915f..72d8d8f94f 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -1271,7 +1271,7 @@ NonnullRefPtr<TemplateLiteral> Parser::parse_template_literal(bool is_tagged) auto token = consume(); expressions.append(parse_string_literal(token, true)); if (is_tagged) - raw_strings.append(create_ast_node<StringLiteral>({ m_state.current_token.filename(), rule_start.position(), position() }, token.value())); + raw_strings.append(create_ast_node<StringLiteral>({ m_state.current_token.filename(), rule_start.position(), position() }, token.raw_template_value())); } else if (match(TokenType::TemplateLiteralExprStart)) { consume(TokenType::TemplateLiteralExprStart); if (match(TokenType::TemplateLiteralExprEnd)) { diff --git a/Userland/Libraries/LibJS/Tests/parser-line-terminators.js b/Userland/Libraries/LibJS/Tests/parser-line-terminators.js index ab88b0eb44..9b75eb4af0 100644 --- a/Userland/Libraries/LibJS/Tests/parser-line-terminators.js +++ b/Userland/Libraries/LibJS/Tests/parser-line-terminators.js @@ -61,6 +61,34 @@ test("line terminators can be mixed (but please don't)", () => { test("all line terminators are valid for line continuations", () => { expect(Function('return "a\\\nb"')()).toBe("ab"); expect(Function('return "a\\\rb"')()).toBe("ab"); + expect(Function('return "a\\\r\nb"')()).toBe("ab"); expect(Function('return "a\\
b"')()).toBe("ab"); expect(Function('return "a\\
b"')()).toBe("ab"); }); + +test("template-literals raw and real value", () => { + let lastTemplate; + let lastRaw; + + function tag(cs) { + lastTemplate = cs[0]; + lastRaw = cs.raw[0]; + } + + function checkTemplate(string_value, expected_template, expected_raw) { + eval("tag`" + string_value + "`"); + expect(lastTemplate).toBe(expected_template); + expect(lastRaw).toBe(expected_raw); + } + + checkTemplate("", "", ""); + checkTemplate("\n", "\n", "\n"); + checkTemplate("\r", "\n", "\n"); + checkTemplate("\r\n", "\n", "\n"); + checkTemplate("\n\r\n", "\n\n", "\n\n"); + + checkTemplate("a\\\nb", "ab", "a\\\nb"); + checkTemplate("a\\\rb", "ab", "a\\\nb"); + checkTemplate("a\\
b", "ab", "a\\
b"); + checkTemplate("a\\
b", "ab", "a\\
b"); +}); diff --git a/Userland/Libraries/LibJS/Token.cpp b/Userland/Libraries/LibJS/Token.cpp index b9c9ebb082..80c957ffd0 100644 --- a/Userland/Libraries/LibJS/Token.cpp +++ b/Userland/Libraries/LibJS/Token.cpp @@ -106,6 +106,16 @@ String Token::string_value(StringValueStatus& status) const while (!lexer.is_eof()) { // No escape, consume one char and continue if (!lexer.next_is('\\')) { + + if (is_template && lexer.next_is('\r')) { + lexer.ignore(); + if (lexer.next_is('\n')) + lexer.ignore(); + + builder.append('\n'); + continue; + } + builder.append(lexer.consume()); continue; } @@ -132,6 +142,8 @@ String Token::string_value(StringValueStatus& status) const // Line continuation if (lexer.next_is('\n') || lexer.next_is('\r')) { + if (lexer.next_is("\r\n")) + lexer.ignore(); lexer.ignore(); continue; } @@ -192,6 +204,15 @@ String Token::string_value(StringValueStatus& status) const return builder.to_string(); } +// 12.8.6.2 Static Semantics: TRV, https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-static-semantics-trv +String Token::raw_template_value() const +{ + String base = value().to_string(); + base.replace("\r\n", "\n", true); + base.replace("\r", "\n", true); + return base; +} + bool Token::bool_value() const { VERIFY(type() == TokenType::BoolLiteral); diff --git a/Userland/Libraries/LibJS/Token.h b/Userland/Libraries/LibJS/Token.h index c4d073219f..e5a9e92f8f 100644 --- a/Userland/Libraries/LibJS/Token.h +++ b/Userland/Libraries/LibJS/Token.h @@ -237,6 +237,7 @@ public: LegacyOctalEscapeSequence, }; String string_value(StringValueStatus& status) const; + String raw_template_value() const; bool is_identifier_name() const; bool trivia_contains_line_terminator() const; |