summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authordavidot <david.tuin@gmail.com>2021-09-01 18:34:19 +0200
committerLinus Groh <mail@linusgroh.de>2021-09-06 08:43:38 +0100
commit3fee7b0d0b1985bf91e6b0b771cfb0e1eb777a04 (patch)
tree647de20df649ad7cf0127e123ddd8436fbc5f2bf /Userland
parentf2512071f2824574dc2e3044eee0cffbeb8629c8 (diff)
downloadserenity-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.cpp2
-rw-r--r--Userland/Libraries/LibJS/Tests/parser-line-terminators.js28
-rw-r--r--Userland/Libraries/LibJS/Token.cpp21
-rw-r--r--Userland/Libraries/LibJS/Token.h1
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;