PERF: editor could be crashed if you entered huge inline blocks

This commit is contained in:
Sam 2014-07-04 12:49:50 +10:00
parent 026a11e8dd
commit dc9b6b53ad
2 changed files with 27 additions and 14 deletions

View File

@ -25,12 +25,15 @@ var blockTags = ['address', 'article', 'aside', 'audio', 'blockquote', 'canvas',
}; };
Discourse.Dialect.registerBlock('html', function(block, next) { Discourse.Dialect.registerBlock('html', function(block, next) {
var split; var split, pos;
// Fix manual blockquote paragraphing even though it's not strictly correct // Fix manual blockquote paragraphing even though it's not strictly correct
if (block.search(/[^\s]+<blockquote/) === 0) { // PERF NOTE: /\S+<blockquote/ is a perf hog for search, try on huge string
split = splitAtLast('blockquote', block, next, true); if (pos = block.search(/<blockquote/) >= 0) {
if (split) { return this.processInline(split[0]); } if(block.substring(0, pos).search(/\s/) === -1) {
split = splitAtLast('blockquote', block, next, true);
if (split) { return this.processInline(split[0]); }
}
} }
var m = /^<([^>]+)\>/.exec(block); var m = /^<([^>]+)\>/.exec(block);

View File

@ -1155,28 +1155,38 @@
inline: { inline: {
__oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) { __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
var m, res; var m, res, pos, search_re, match_re;
// PERF NOTE: rewritten to avoid greedy match regex \([\s\S]*?)(...)\
// greedy match performs horribly with large inline blocks, it can be so
// slow it will crash chrome
patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__; patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" ); search_re = new RegExp(patterns_or_re.source || patterns_or_re);
m = re.exec( text ); pos = text.search(search_re);
if (!m) {
// Just boring text // Just boring text
if (pos === -1) {
return [ text.length, text ]; return [ text.length, text ];
} }
else if ( m[1] ) {
if (pos !== 0) {
// Some un-interesting text matched. Return that first // Some un-interesting text matched. Return that first
return [ m[1].length, m[1] ]; return [pos, text.substring(0,pos)];
} }
if ( m[2] in this.dialect.inline ) { match_re = new RegExp( "^(" + (patterns_or_re.source || patterns_or_re) + ")" );
res = this.dialect.inline[ m[2] ].call( m = match_re.exec( text );
if ( m[1] in this.dialect.inline ) {
res = this.dialect.inline[ m[1] ].call(
this, this,
text.substr( m.index ), m, previous_nodes || [] ); text.substr( m.index ), m, previous_nodes || [] );
} }
// Default for now to make dev easier. just slurp special and output it. // Default for now to make dev easier. just slurp special and output it.
res = res || [ m[2].length, m[2] ]; res = res || [ m[1].length, m[1] ];
return res; return res;
}, },