From dc9b6b53ad97bf1e1d6699892a433555389817ff Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 4 Jul 2014 12:49:50 +1000 Subject: [PATCH] PERF: editor could be crashed if you entered huge inline blocks --- .../javascripts/discourse/dialects/html.js | 11 ++++--- vendor/assets/javascripts/better_markdown.js | 30 ++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/discourse/dialects/html.js b/app/assets/javascripts/discourse/dialects/html.js index d17723610cf..bf5a5752396 100644 --- a/app/assets/javascripts/discourse/dialects/html.js +++ b/app/assets/javascripts/discourse/dialects/html.js @@ -25,12 +25,15 @@ var blockTags = ['address', 'article', 'aside', 'audio', 'blockquote', 'canvas', }; Discourse.Dialect.registerBlock('html', function(block, next) { - var split; + var split, pos; // Fix manual blockquote paragraphing even though it's not strictly correct - if (block.search(/[^\s]+
= 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); diff --git a/vendor/assets/javascripts/better_markdown.js b/vendor/assets/javascripts/better_markdown.js index 7697667b2bc..2ec9e282fa6 100644 --- a/vendor/assets/javascripts/better_markdown.js +++ b/vendor/assets/javascripts/better_markdown.js @@ -1155,28 +1155,38 @@ inline: { __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__; - 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 ); - if (!m) { - // Just boring text + pos = text.search(search_re); + + // Just boring text + if (pos === -1) { return [ text.length, text ]; } - else if ( m[1] ) { + + if (pos !== 0) { // 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 ) { - res = this.dialect.inline[ m[2] ].call( + match_re = new RegExp( "^(" + (patterns_or_re.source || patterns_or_re) + ")" ); + m = match_re.exec( text ); + + if ( m[1] in this.dialect.inline ) { + res = this.dialect.inline[ m[1] ].call( this, text.substr( m.index ), m, previous_nodes || [] ); } + // 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; },