|
| 1 | +#include <sstream> |
| 2 | + |
| 3 | +#include "support/string.h" |
| 4 | +#include "gtest/gtest.h" |
| 5 | + |
| 6 | +using namespace wasm; |
| 7 | + |
| 8 | +using StringTest = ::testing::Test; |
| 9 | + |
| 10 | +namespace { |
| 11 | + |
| 12 | +std::string escapeJS(std::string_view str) { |
| 13 | + std::stringstream ss; |
| 14 | + String::printEscapedJS(ss, str); |
| 15 | + return ss.str(); |
| 16 | +} |
| 17 | + |
| 18 | +} // anonymous namespace |
| 19 | + |
| 20 | +TEST_F(StringTest, PrintEscapedJSPlain) { |
| 21 | + EXPECT_EQ(escapeJS(""), ""); |
| 22 | + EXPECT_EQ(escapeJS("env"), "env"); |
| 23 | + EXPECT_EQ(escapeJS("wasi_snapshot_preview1"), "wasi_snapshot_preview1"); |
| 24 | +} |
| 25 | + |
| 26 | +TEST_F(StringTest, PrintEscapedJSQuotes) { |
| 27 | + // Both quote characters are escaped so the result is safe in either a |
| 28 | + // single- or double-quoted literal. |
| 29 | + EXPECT_EQ(escapeJS("it's"), "it\\'s"); |
| 30 | + EXPECT_EQ(escapeJS("say \"hi\""), "say \\\"hi\\\""); |
| 31 | + EXPECT_EQ(escapeJS("mixed'and\"quotes"), "mixed\\'and\\\"quotes"); |
| 32 | +} |
| 33 | + |
| 34 | +TEST_F(StringTest, PrintEscapedJSBackslash) { |
| 35 | + EXPECT_EQ(escapeJS("a\\b"), "a\\\\b"); |
| 36 | + // A backslash followed by a quote must not collapse into a lone escape. |
| 37 | + EXPECT_EQ(escapeJS("\\'"), "\\\\\\'"); |
| 38 | +} |
| 39 | + |
| 40 | +TEST_F(StringTest, PrintEscapedJSNewlines) { |
| 41 | + EXPECT_EQ(escapeJS("line1\nline2"), "line1\\nline2"); |
| 42 | + EXPECT_EQ(escapeJS("line1\r\nline2"), "line1\\r\\nline2"); |
| 43 | +} |
| 44 | + |
| 45 | +TEST_F(StringTest, PrintEscapedJSLineSeparators) { |
| 46 | + // U+2028 and U+2029 are valid unescaped in JSON strings but are line |
| 47 | + // terminators in JavaScript, so they must be escaped. |
| 48 | + EXPECT_EQ(escapeJS("a\xE2\x80\xA8" |
| 49 | + "b"), |
| 50 | + "a\\u2028b"); |
| 51 | + EXPECT_EQ(escapeJS("a\xE2\x80\xA9" |
| 52 | + "b"), |
| 53 | + "a\\u2029b"); |
| 54 | + // Other characters in the same UTF-8 range pass through unchanged. |
| 55 | + EXPECT_EQ(escapeJS("a\xE2\x80\xA6" |
| 56 | + "b"), |
| 57 | + "a\xE2\x80\xA6" |
| 58 | + "b"); |
| 59 | + // A truncated sequence at the end of the string is passed through |
| 60 | + // byte-by-byte rather than read out of bounds. |
| 61 | + EXPECT_EQ(escapeJS("\xE2\x80"), "\xE2\x80"); |
| 62 | +} |
| 63 | + |
| 64 | +TEST_F(StringTest, PrintEscapedJSNonASCII) { |
| 65 | + // Non-ASCII UTF-8 is passed through unmodified. |
| 66 | + EXPECT_EQ(escapeJS("m\xC3\xB3" |
| 67 | + "dulo"), |
| 68 | + "m\xC3\xB3" |
| 69 | + "dulo"); |
| 70 | +} |
0 commit comments