From 2a1eb398336351cb6c228f800b54285a5cc3c355 Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Wed, 28 Mar 2018 16:12:42 -0500 Subject: [PATCH 1/2] Fix long-running loop This can be caused by having text with a huge number of spaces. --- lib/line_wrapper.coffee | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/line_wrapper.coffee b/lib/line_wrapper.coffee index 25db6581a..1c457fa17 100644 --- a/lib/line_wrapper.coffee +++ b/lib/line_wrapper.coffee @@ -63,19 +63,32 @@ class LineWrapper extends EventEmitter while bk = breaker.nextBreak() word = text.slice(last?.position or 0, bk.position) w = wordWidths[word] ?= @wordWidth word - + # if the word is longer than the whole line, chop it up # TODO: break by grapheme clusters, not JS string characters if w > @lineWidth + @continuedX # make some fake break objects lbk = last fbk = {} - + while word.length # fit as much of the word as possible into the space we have - l = word.length - while w > @spaceLeft and l > 0 - w = @wordWidth word.slice(0, --l) + if w > @spaceLeft + # start checking our text at the end of our remaining space - this works around long loops when processing massive text + l = Math.ceil(@spaceLeft / (w / word.length)) + w = @wordWidth word.slice(0, l) + mightGrow = w <= @spaceLeft and l < word.length + else + l = word.length + mustShrink = w > @spaceLeft and l > 0 + while mustShrink or mightGrow + if mustShrink + w = @wordWidth word.slice(0, --l) + mustShrink = w > @spaceLeft and l > 0 + else + w = @wordWidth word.slice(0, ++l) + mustShrink = w > @spaceLeft and l > 0 + mightGrow = w <= @spaceLeft and l < word.length # send a required break unless this is the last piece fbk.required = l < word.length From 947dea9692c8790570df77353f20a0e7ec8a9922 Mon Sep 17 00:00:00 2001 From: Michael Keller Date: Wed, 28 Mar 2018 16:39:25 -0500 Subject: [PATCH 2/2] Cleanup comments for last fix --- lib/line_wrapper.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/line_wrapper.coffee b/lib/line_wrapper.coffee index 1c457fa17..8b64fe350 100644 --- a/lib/line_wrapper.coffee +++ b/lib/line_wrapper.coffee @@ -74,13 +74,15 @@ class LineWrapper extends EventEmitter while word.length # fit as much of the word as possible into the space we have if w > @spaceLeft - # start checking our text at the end of our remaining space - this works around long loops when processing massive text + # start our check at the end of our available space - this method is faster than a loop of each character and it resolves + # an issue with long loops when processing massive words, such as a huge number of spaces l = Math.ceil(@spaceLeft / (w / word.length)) w = @wordWidth word.slice(0, l) mightGrow = w <= @spaceLeft and l < word.length else l = word.length mustShrink = w > @spaceLeft and l > 0 + # shrink or grow word as necessary after our near-guess above while mustShrink or mightGrow if mustShrink w = @wordWidth word.slice(0, --l)