1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
import { group } from "mitata";
import { bench, run } from "mitata";
import { encode as htmlEntityEncode } from "html-entities";
import { escape as heEscape } from "he";
var bunEscapeHTML = globalThis.escapeHTML || Bun.escapeHTML;
const FIXTURE = require("fs")
.readFileSync(import.meta.dir + "/_fixture.txt", "utf8")
.split("")
.map((a) => {
if (a.charCodeAt(0) > 127) {
return "a";
}
return a;
})
.join("");
const FIXTURE_WITH_UNICODE = require("fs").readFileSync(
import.meta.dir + "/_fixture.txt",
"utf8"
);
// from react-dom:
const matchHtmlRegExp = /["'&<>]/;
function reactEscapeHtml(string) {
const str = "" + string;
const match = matchHtmlRegExp.exec(str);
if (!match) {
return str;
}
let escape;
let html = "";
let index;
let lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escape = """;
break;
case 38: // &
escape = "&";
break;
case 39: // '
escape = "'"; // modified from escape-html; used to be '''
break;
case 60: // <
escape = "<";
break;
case 62: // >
escape = ">";
break;
default:
continue;
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
}
// for (let input of [
// "<script>alert('xss')</script>",
// `long string, nothing to escape... `.repeat(9999),
// `long utf16 string, no esc 🤔🤔🤔🤔🤔` + "tex".repeat(4000),
// `smol`,
// // `medium string with <script>alert('xss')</script>`,
// FIXTURE,
// // "[unicode]" + FIXTURE_WITH_UNICODE,
// ]) {
// group(
// {
// summary: true,
// name:
// `"` +
// input.substring(0, Math.min(input.length, 32)) +
// `"` +
// ` (${input.length} chars)`,
// },
// () => {
// bench(`ReactDOM.escapeHTML`, () => reactEscapeHtml(input));
// bench(`html-entities.encode`, () => htmlEntityEncode(input));
// bench(`he.escape`, () => heEscape(input));
// bench(`Bun.escapeHTML`, () => bunEscapeHTML(input));
// }
// );
// }
for (let input of [
`long string, nothing to escape... `.repeat(9999999 * 3),
FIXTURE.repeat(8000),
// "[unicode]" + FIXTURE_WITH_UNICODE,
]) {
group(
{
summary: true,
name:
`"` +
input.substring(0, Math.min(input.length, 32)) +
`"` +
` (${new Intl.NumberFormat().format(input.length / 100_000_000_0)} GB)`,
},
() => {
// bench(`ReactDOM.escapeHTML`, () => reactEscapeHtml(input));
// bench(`html-entities.encode`, () => htmlEntityEncode(input));
// bench(`he.escape`, () => heEscape(input));
bench(`Bun.escapeHTML`, () => bunEscapeHTML(input));
}
);
}
await run();
|