Skip to content

Commit 2e00ef9

Browse files
committed
add fast return to escapeHTML
1 parent 6752251 commit 2e00ef9

File tree

3 files changed

+56
-24
lines changed

3 files changed

+56
-24
lines changed

lib/micro-template.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ const template = function (id, data) {
3434
template.cache = new Map();
3535
template.get = function (id) { return document.getElementById(id).innerHTML };
3636
template.escapeHTML = (function () {
37+
const regexp = /[<>"'&]/;
3738
return function (str) {
3839
if (typeof str !== 'string') str = String(str);
39-
let result = '';
40-
for (let i = 0, len = str.length; i < len; i++) {
40+
let match = regexp.exec(str);
41+
if (match === null) return str;
42+
let result = str.slice(0, match.index);
43+
for (let i = match.index, len = str.length; i < len; i++) {
4144
switch (str.charCodeAt(i)) {
4245
case 60: result += '&lt;'; break; // <
4346
case 62: result += '&gt;'; break; // >

misc/benchmark-escapeHTML.js

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@ const escapeHTML_self_all = (function () {
2121
};
2222
})();
2323

24+
const escapeHTML_self_all_with_fast_return = (function () {
25+
const regexp = /[<>"'&]/;
26+
return function (str) {
27+
if (typeof str !== 'string') str = String(str);
28+
let match = regexp.exec(str);
29+
if (match === null) return str;
30+
let result = str.slice(0, match.index);
31+
for (let i = match.index, len = str.length; i < len; i++) {
32+
switch (str.charCodeAt(i)) {
33+
case 60: result += '&lt;'; break; // <
34+
case 62: result += '&gt;'; break; // >
35+
case 34: result += '&#x22;'; break; // "
36+
case 39: result += '&#x27;'; break; // '
37+
case 38: result += '&amp;'; break; // &
38+
default: result += str[i]; break;
39+
}
40+
}
41+
return result;
42+
};
43+
})();
44+
2445
const escapeHTML_self_case = (function () {
2546
const regexp = /[<>"'&]/g;
2647
return function (str) {
@@ -111,29 +132,36 @@ const escapeHTML_replace_obj = (function () {
111132
})();
112133

113134

114-
const target = 'Hello <world> & "everyone"\'s welcome!'.repeat(1000);
115135
barplot(() => {
116-
summary(() => {
117-
bench('escapeHTML_self_case', () => {
118-
escapeHTML_self_case(target);
119-
});
120-
bench('escapeHTML_self_map', () => {
121-
escapeHTML_self_map(target);
122-
});
123-
bench('escapeHTML_self_map_k', () => {
124-
escapeHTML_self_map_k(target);
125-
});
126-
bench('escapeHTML_self_obj', () => {
127-
escapeHTML_self_obj(target);
128-
});
129-
bench('escapeHTML_replace_map', () => {
130-
escapeHTML_replace_map(target);
131-
});
132-
bench('escapeHTML_replace_obj', () => {
133-
escapeHTML_replace_obj(target);
134-
});
135-
bench('escapeHTML_self_all', () => {
136-
escapeHTML_self_all(target);
136+
[
137+
'Hello <world> & "everyone"\'s welcome!',
138+
'plain text',
139+
].forEach(target => {
140+
summary(() => {
141+
bench('escapeHTML_self_case', () => {
142+
escapeHTML_self_case(target);
143+
});
144+
bench('escapeHTML_self_map', () => {
145+
escapeHTML_self_map(target);
146+
});
147+
bench('escapeHTML_self_map_k', () => {
148+
escapeHTML_self_map_k(target);
149+
});
150+
bench('escapeHTML_self_obj', () => {
151+
escapeHTML_self_obj(target);
152+
});
153+
bench('escapeHTML_replace_map', () => {
154+
escapeHTML_replace_map(target);
155+
});
156+
bench('escapeHTML_replace_obj', () => {
157+
escapeHTML_replace_obj(target);
158+
});
159+
bench('escapeHTML_self_all', () => {
160+
escapeHTML_self_all(target);
161+
});
162+
bench('escapeHTML_self_all_with_fast_return', () => {
163+
escapeHTML_self_all_with_fast_return(target);
164+
});
137165
});
138166
});
139167
});

test/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ test('template escapes html', (t) => {
5656
assert.strictEqual(template(d, { html: '<foobar>' }), '&lt;foobar&gt;');
5757
assert.strictEqual(template(d, { html: '<">'}), '&lt;&#x22;&gt;');
5858
assert.strictEqual(template(d, { html: "<'>" }), '&lt;&#x27;&gt;');
59+
assert.strictEqual(template(d, { html: "foo & bar" }), 'foo &amp; bar');
5960
});
6061

6162
test('template raw output', (t) => {

0 commit comments

Comments
 (0)