Skip to content

Instantly share code, notes, and snippets.

@rtsao
Created November 24, 2016 01:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rtsao/08e6db5409c034b842fe9523181e6410 to your computer and use it in GitHub Desktop.
Save rtsao/08e6db5409c034b842fe9523181e6410 to your computer and use it in GitHub Desktop.
SSR escaping
const _ = require('lodash');
const randomatic = require('randomatic');
const Benchmark = require('benchmark');
const {table} = require('table');
/**
* TEST CODE
*/
function control(_string) {
const string = _string + '';
const length = string.length;
let characters = '';
for (let i = 0; i < length; i++) {
switch (string.charCodeAt(i)) {
case 38:
characters += '&amp;';
break;
case 39:
characters += '&#039;';
break;
case 34:
characters += '&quot;';
break;
case 60:
characters += '&lt;';
break;
case 62:
characters += '&gt;';
break;
default:
characters += string[i];
}
}
return characters;
}
var UNSAFE_CHARS_PATTERN = /[<>&"']/g;
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to
// their Unicode counterparts which are safe to use in JavaScript strings.
var HTML_CHARS = {
'<' : '&lt;',
'>' : '&gt;',
'"' : '&quot;',
"'" : '&#39;',
'&' : '&amp;'
};
function getChar(unsafeChar) {
return HTML_CHARS[unsafeChar];
}
function treatment(_str) {
const str = _str + '';
return str.replace(UNSAFE_CHARS_PATTERN, getChar);
}
/**
* BENCHMARK CODE
*/
const escapedChars = Object.keys(HTML_CHARS);
function generateString(length, escapeProportion) {
const str = randomatic('Aa0', length);
const numEscaped = Math.ceil(length * escapeProportion);
const charArray = str.split('');
const indices = _.range(length);
const indicesToReplace = _.sampleSize(indices, numEscaped);
indicesToReplace.forEach(index => {
charArray[index] = _.sample(escapedChars);
});
return charArray.join('');
}
const PROPORTIONS = [0, 0.15, 0.30];
const LENGTHS = [8, 16, 32, 64, 128, 256, 512, 1024];
let suites = [];
let results = [[' ', ...LENGTHS]];
PROPORTIONS.forEach((proportion, i) => {
results[i + 1] = [proportion];
LENGTHS.forEach((length, j) => {
const str = generateString(length, proportion);
const suite = new Benchmark.Suite;
suite
.add(`control(${length}, ${proportion})`, function() {
control(str);
})
.add(`treatment(${length}, ${proportion})`, function() {
treatment(str);
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
const fastest = this.filter('fastest').map('name');
results[i + 1][j + 1] = fastest[0].split('(')[0];
console.log('Fastest is ' + fastest + "\n");
});
suites.push(suite);
});
});
for (let k = 0; k < suites.length; k++) {
suites[k].run({ 'async': false });
}
console.log(table(results));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment