1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 10:08:10 +00:00

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.
This commit is contained in:
Ali Mohammad Pur 2023-02-15 17:55:13 +03:30 committed by Linus Groh
parent a8bcb901c0
commit bcfbe0fbf7
2 changed files with 25 additions and 3 deletions

View file

@ -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

View file

@ -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");
});