Skip to content

Commit f1f45c3

Browse files
committed
wip
1 parent b42947e commit f1f45c3

File tree

2 files changed

+201
-13
lines changed

2 files changed

+201
-13
lines changed

benchmark/index.js

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22
/**
33
* Globals for benchmark.js
44
*/
5-
global.escapeHtml = require('..')
5+
var lib = require('..')
6+
global.escapeHtml = lib.escapeHtml
7+
global.escapeHtmlFast = lib.escapeHtmlFast
8+
global.escapeHtmlNoRegex = lib.escapeHtmlNoRegex
69

710
/**
811
* Module dependencies.
912
*/
1013
var benchmark = require('benchmark')
1114
var benchmarks = require('beautify-benchmark')
15+
var fs = require('fs')
16+
var hugeHTML = fs.readFileSync("mathematica.html").toString()
17+
18+
const MIN_SAMPLES = 3
1219

1320
for (var dep in process.versions) {
1421
console.log(' %s@%s', dep, process.versions[dep])
@@ -17,28 +24,129 @@ for (var dep in process.versions) {
1724
console.log('')
1825

1926
var suite = new benchmark.Suite()
27+
const fn = function() { escapeHtmlFast(str) }
28+
29+
// suite.add({
30+
// 'name': 'no special characters',
31+
// 'minSamples': MIN_SAMPLES,
32+
// 'fn': function() { escapeHtml(str) },,
33+
// 'setup': function() { str = "Hello, World!" }
34+
// })
35+
36+
// suite.add({
37+
// 'name': 'no special characters (large)',
38+
// 'minSamples': MIN_SAMPLES,
39+
// 'fn': function() { escapeHtml(str) },,
40+
// 'setup': function() { str = "Hello, World!".repeat(1000) }
41+
// })
42+
2043

2144
suite.add({
22-
'name': 'no special characters',
23-
'minSamples': 100,
24-
'fn': 'escapeHtml(str)',
25-
'setup': 'str = "Hello, World!"'
45+
'name': 'Long HTML page',
46+
'minSamples': MIN_SAMPLES,
47+
'fn': function() { escapeHtml(hugeHTML) },
2648
})
2749

50+
suite.add({
51+
'name': 'Long HTML page REGEX',
52+
'minSamples': MIN_SAMPLES,
53+
'fn': function() { escapeHtmlFast(hugeHTML) },
54+
})
55+
56+
suite.add({
57+
'name': 'Short HTML page',
58+
'minSamples': MIN_SAMPLES,
59+
'fn': function() { escapeHtml(hugeHTML.substring(1,30000)) },
60+
})
61+
62+
suite.add({
63+
'name': 'Short HTML page REGEX',
64+
'minSamples': MIN_SAMPLES,
65+
'fn': function() { escapeHtmlFast(hugeHTML.substring(1,30000)) },
66+
})
67+
68+
2869
suite.add({
2970
'name': 'single special character',
30-
'minSamples': 100,
31-
'fn': 'escapeHtml(str)',
32-
'setup': 'str = "Hello, World&!"'
71+
'minSamples': MIN_SAMPLES,
72+
'fn': function() { escapeHtml(str) },
73+
'setup': function() { str = "Hello, World&!" }
74+
})
75+
76+
suite.add({
77+
'name': 'single special character REGEX',
78+
'minSamples': MIN_SAMPLES,
79+
'fn': function() { escapeHtmlFast(str) },
80+
'setup': function() { str = "Hello, World&!" }
3381
})
3482

83+
suite.add({
84+
'name': 'single special character (large)',
85+
'minSamples': MIN_SAMPLES,
86+
'fn': function() { escapeHtml(str) },
87+
'setup': function() {
88+
str = "Hello, World!".repeat(500)
89+
+ "&"
90+
+ "Hello, World!".repeat(500)
91+
}
92+
})
93+
94+
suite.add({
95+
'name': 'single special character (large) REGEX',
96+
'minSamples': MIN_SAMPLES,
97+
'fn': function() { escapeHtmlFast(str) },
98+
'setup': function() {
99+
str = "Hello, World!".repeat(500)
100+
+ "&"
101+
+ "Hello, World!".repeat(500)
102+
}
103+
})
104+
105+
35106
suite.add({
36107
'name': 'many special characters',
37-
'minSamples': 100,
38-
'fn': 'escapeHtml(str)',
39-
'setup': 'str = "\'>\'\\"\\"&>h<e>&<y>"'
108+
'minSamples': MIN_SAMPLES,
109+
'fn': function() { escapeHtml(str) },
110+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"' }
111+
})
112+
113+
suite.add({
114+
'name': 'many special characters REGEX',
115+
'minSamples': MIN_SAMPLES,
116+
'fn': function() { escapeHtmlFast(str) },
117+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"' }
118+
})
119+
120+
suite.add({
121+
'name': 'many special characters NO REGEX',
122+
'minSamples': MIN_SAMPLES,
123+
'fn': function() { escapeHtmlNoRegex(str) },
124+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"' }
125+
})
126+
127+
128+
suite.add({
129+
'name': 'many special characters (large)',
130+
'minSamples': MIN_SAMPLES,
131+
'fn': function() { escapeHtml(str) },
132+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"'.repeat(1000) }
133+
})
134+
135+
suite.add({
136+
'name': 'many special characters (large) REGEX',
137+
'minSamples': MIN_SAMPLES,
138+
'fn': function() { escapeHtmlFast(str) },
139+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"'.repeat(1000) }
40140
})
41141

142+
suite.add({
143+
'name': 'many special characters (large) NO REGEX',
144+
'minSamples': MIN_SAMPLES,
145+
'fn': function() { escapeHtmlNoRegex(str) },
146+
'setup': function() { str = '\'>\'\\"\\"&>h<e>&<y>"'.repeat(1000) }
147+
})
148+
149+
42150
suite.on('cycle', function onCycle (event) {
43151
benchmarks.add(event.target)
44152
})
@@ -47,4 +155,4 @@ suite.on('complete', function onComplete () {
47155
benchmarks.log()
48156
})
49157

50-
suite.run({ 'async': false })
158+
suite.run({ 'async': false, maxTime: 0.001 })

index.js

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var matchHtmlRegExp = /["'&<>]/
2020
* @public
2121
*/
2222

23-
module.exports = escapeHtml
23+
module.exports = { escapeHtml, escapeHtmlFast, escapeHtmlNoRegex }
2424

2525
/**
2626
* Escape special characters in the given string of text.
@@ -30,6 +30,86 @@ module.exports = escapeHtml
3030
* @public
3131
*/
3232

33+
var matchHtmlRegExpFast = /["'&<>]/g
34+
function escapeHtmlFast (str) {
35+
var lastIndex = 0
36+
var html = ''
37+
var escape = ''
38+
var match
39+
40+
while (match = matchHtmlRegExpFast.test(str)) {
41+
switch (str.charCodeAt(matchHtmlRegExpFast.lastIndex)) {
42+
case 34: // "
43+
escape = '&quot;'
44+
break
45+
case 38: // &
46+
escape = '&amp;'
47+
break
48+
case 39: // '
49+
escape = '&#39;'
50+
break
51+
case 60: // <
52+
escape = '&lt;'
53+
break
54+
case 62: // >
55+
escape = '&gt;'
56+
break
57+
}
58+
// console.log(lastIndex, matchHtmlRegExpFast.lastIndex, str.length)
59+
html += str.substring(lastIndex, matchHtmlRegExpFast.lastIndex)
60+
lastIndex = matchHtmlRegExpFast.lastIndex + 1
61+
html += escape
62+
}
63+
return html + str.substring(lastIndex)
64+
}
65+
66+
function escapeHtmlNoRegex (str) {
67+
// var str = '' + string
68+
// var match = matchHtmlRegExp.exec(str)
69+
70+
// if (!match) {
71+
// return str
72+
// }
73+
74+
var escape
75+
var html = ''
76+
var index = 0
77+
var lastIndex = 0
78+
79+
for (index = 0; index < str.length; index++) {
80+
switch (str.charCodeAt(index)) {
81+
case 34: // "
82+
escape = '&quot;'
83+
break
84+
case 38: // &
85+
escape = '&amp;'
86+
break
87+
case 39: // '
88+
escape = '&#39;'
89+
break
90+
case 60: // <
91+
escape = '&lt;'
92+
break
93+
case 62: // >
94+
escape = '&gt;'
95+
break
96+
default:
97+
continue
98+
}
99+
100+
if (lastIndex !== index) {
101+
html += str.substring(lastIndex, index)
102+
}
103+
104+
lastIndex = index + 1
105+
html += escape
106+
}
107+
108+
return lastIndex !== index
109+
? html + str.substring(lastIndex, index)
110+
: html
111+
}
112+
33113
function escapeHtml (string) {
34114
var str = '' + string
35115
var match = matchHtmlRegExp.exec(str)

0 commit comments

Comments
 (0)