summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2023-02-15 17:55:13 +0330
committerLinus Groh <mail@linusgroh.de>2023-02-16 21:03:19 +0100
commitbcfbe0fbf7465ed6706d806b69c5eaa2dcfc6325 (patch)
treeddd3ae95f9d6b484014fc7f4953da76c9b5f9ab9 /Userland
parenta8bcb901c0bbe023364e852796e900fa58bcac45 (diff)
downloadserenity-bcfbe0fbf7465ed6706d806b69c5eaa2dcfc6325.zip
LibJS: Manually loop over escaped regex pattern instead of ::replace()
This makes it ever-so-slightly faster, but more importantly, it fixes the bug where a `/\//` regex's `source` property would return `\\/` ("\\\\/") instead of `\/` due to the existing '/' -> '\/' replace() call.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpObject.cpp25
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.source.js3
2 files changed, 25 insertions, 3 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpObject.cpp b/Userland/Libraries/LibJS/Runtime/RegExpObject.cpp
index 74b52e3000..40c7a6638f 100644
--- a/Userland/Libraries/LibJS/Runtime/RegExpObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/RegExpObject.cpp
@@ -248,8 +248,31 @@ DeprecatedString RegExpObject::escape_regexp_pattern() const
// 3. Return S.
if (m_pattern.is_empty())
return "(?:)";
+
// FIXME: Check the 'u' and 'v' flags and escape accordingly
- return m_pattern.replace("\n"sv, "\\n"sv, ReplaceMode::All).replace("\r"sv, "\\r"sv, ReplaceMode::All).replace(LINE_SEPARATOR_STRING, "\\u2028"sv, ReplaceMode::All).replace(PARAGRAPH_SEPARATOR_STRING, "\\u2029"sv, ReplaceMode::All).replace("/"sv, "\\/"sv, ReplaceMode::All);
+ StringBuilder builder;
+ auto pattern = Utf8View { m_pattern };
+ auto escaped = false;
+ for (auto code_point : pattern) {
+ if (escaped) {
+ escaped = false;
+ builder.append_code_point('\\');
+ builder.append_code_point(code_point);
+ continue;
+ }
+
+ if (code_point == '\\') {
+ escaped = true;
+ continue;
+ }
+
+ if (code_point == '\r' || code_point == LINE_SEPARATOR || code_point == PARAGRAPH_SEPARATOR || code_point == '/') {
+ builder.append_code_point('\\');
+ }
+ builder.append_code_point(code_point);
+ }
+
+ return builder.to_deprecated_string();
}
// 22.2.3.2.4 RegExpCreate ( P, F ), https://tc39.es/ecma262/#sec-regexpcreate
diff --git a/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.source.js b/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.source.js
index 4f0e14297f..3992c7c1db 100644
--- a/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.source.js
+++ b/Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.source.js
@@ -3,6 +3,5 @@ test("basic functionality", () => {
expect(RegExp().source).toBe("(?:)");
expect(/test/.source).toBe("test");
expect(/\n/.source).toBe("\\n");
- // FIXME: RegExp parse doesn't parse \/ :(
- // expect(/foo\/bar/.source).toBe("foo\\/bar");
+ expect(/foo\/bar/.source).toBe("foo\\/bar");
});