Skip to content

Commit d7f599d

Browse files
Merge pull request #228 from preactjs/perf-entity-encoding-scan
[perf] Improve string encoding performance by ~50%
2 parents 13b68cf + e4fe799 commit d7f599d

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

.changeset/orange-poems-learn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"preact-render-to-string": patch
3+
---
4+
5+
Improve string encoding performance by ~50%

src/util.js

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,34 @@ export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine
33

44
const ENCODED_ENTITIES = /[&<>"]/;
55

6-
export function encodeEntities(input) {
7-
const s = String(input);
8-
if (!ENCODED_ENTITIES.test(s)) {
9-
return s;
6+
export function encodeEntities(str) {
7+
// Ensure we're always parsing and returning a string:
8+
str += '';
9+
10+
// Skip all work for strings with no entities needing encoding:
11+
if (ENCODED_ENTITIES.test(str) === false) return str;
12+
13+
let last = 0,
14+
i = 0,
15+
out = '',
16+
ch = '';
17+
18+
// Seek forward in str until the next entity char:
19+
for (; i<str.length; i++) {
20+
switch (str.charCodeAt(i)) {
21+
case 60: ch = '&lt;'; break;
22+
case 62: ch = '&gt;'; break;
23+
case 34: ch = '&quot;'; break;
24+
case 38: ch = '&amp;'; break;
25+
default: continue;
26+
}
27+
// Append skipped/buffered characters and the encoded entity:
28+
if (i > last) out += str.slice(last, i);
29+
out += ch;
30+
// Start the next seek/buffer after the entity's offset:
31+
last = i + 1;
1032
}
11-
return s
12-
.replace(/&/g, '&amp;')
13-
.replace(/</g, '&lt;')
14-
.replace(/>/g, '&gt;')
15-
.replace(/"/g, '&quot;');
33+
return out + str.slice(last, i);
1634
}
1735

1836
export let indent = (s, char) =>

0 commit comments

Comments
 (0)