From 61b219953ada83783b1cf97151b6a16260494462 Mon Sep 17 00:00:00 2001
From: Turiiya <34311583+ttytm@users.noreply.github.com>
Date: Sun, 3 Sep 2023 18:01:19 +0200
Subject: [PATCH] encoding.html: optimize escape performance (#19264)
---
vlib/encoding/html/escape.v | 9 +++++++--
vlib/encoding/html/escape_test.v | 8 ++++----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/vlib/encoding/html/escape.v b/vlib/encoding/html/escape.v
index 5931adc4aee443..4c4ed9f7c6bcbd 100644
--- a/vlib/encoding/html/escape.v
+++ b/vlib/encoding/html/escape.v
@@ -5,15 +5,20 @@ pub struct EscapeConfig {
quote bool = true
}
+const (
+ html_replacement_table = ['&', '&', '<', '<', '>', '>']
+ html_quote_replacement_table = ['"', '"', "'", '''] // `'"'` is shorter than `'"'`
+)
+
// escape converts special characters in the input, specifically "<", ">", and "&"
// to HTML-safe sequences. If `quote` is set to true (which is default), quotes in
// HTML will also be translated. Both double and single quotes will be affected.
// **Note:** escape() supports funky accents by doing nothing about them. V's UTF-8
// support through `string` is robust enough to deal with these cases.
pub fn escape(input string, config EscapeConfig) string {
- tag_free_input := input.replace_each(['&', '&', '<', '<', '>', '>'])
+ tag_free_input := input.replace_each(html.html_replacement_table)
return if config.quote {
- tag_free_input.replace_each(['"', '"', "'", '''])
+ tag_free_input.replace_each(html.html_quote_replacement_table)
} else {
tag_free_input
}
diff --git a/vlib/encoding/html/escape_test.v b/vlib/encoding/html/escape_test.v
index 2b8ffbe13c144b..da0cb50af9ff76 100644
--- a/vlib/encoding/html/escape_test.v
+++ b/vlib/encoding/html/escape_test.v
@@ -5,15 +5,15 @@ fn test_escape_html() {
assert html.escape('No change') == 'No change'
assert html.escape('Bold text') == '<b>Bold text</b>'
assert html.escape('') == '<img />'
- assert html.escape("' onmouseover='alert(1)'") == '' onmouseover='alert(1)''
- assert html.escape("link") == '<a href='http://www.example.com'>link</a>'
- assert html.escape("") == '<script>alert('hello');</script>'
+ assert html.escape("' onmouseover='alert(1)'") == '' onmouseover='alert(1)''
+ assert html.escape("link") == '<a href='http://www.example.com'>link</a>'
+ assert html.escape("") == '<script>alert('hello');</script>'
// Cases obtained from:
// https://github.com/apache/commons-lang/blob/master/src/test/java/org/apache/commons/lang3/StringEscapeUtilsTest.java
assert html.escape('plain text') == 'plain text'
assert html.escape('') == ''
assert html.escape('bread & butter') == 'bread & butter'
- assert html.escape('"bread" & butter') == '"bread" & butter'
+ assert html.escape('"bread" & butter') == '"bread" & butter'
assert html.escape('greater than >') == 'greater than >'
assert html.escape('< less than') == '< less than'
// Leave accents as-is