<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[285016] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/285016">285016</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2021-10-28 19:53:47 -0700 (Thu, 28 Oct 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Source/WebCore:
Negative length returned by TextUtil::midWordBreak with surrogate pair
https://bugs.webkit.org/show_bug.cgi?id=232053

Patch by Gabriel Nava Marino <gnavamarino@apple.com> on 2021-10-28
Reviewed by Alan Bujtas.

When the substring does not fit, the right side is supposed to be the start
of the surrogate pair if applicable. However, if the start of the surrogate
pair falls to the left of the startPosition, we will end up returning a
negative length. Instead, bail out at this point since we know that our
middle point (which becomes the right) falls before the start position.
We are not going to find a non-empty fitting content anymore in here.

* layout/formattingContexts/inline/text/TextUtil.cpp:
(WebCore::Layout::TextUtil::breakWord):

LayoutTests:
Add an additional edge case for surrogate pairs to existing tests.
https://bugs.webkit.org/show_bug.cgi?id=232053

Patch by Gabriel Nava Marino <gnavamarino@apple.com> on 2021-10-28
Reviewed by Alan Bujtas.

* fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt:
* fast/text/word-break-column-gap-display-flex-utf16-surrogates.html:
* fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt:
* fast/text/word-break-letter-spacing-utf16-surrogates.html:
* fast/text/word-break-max-width-utf16-surrogates-expected.txt:
* fast/text/word-break-max-width-utf16-surrogates.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakcolumngapdisplayflexutf16surrogatesexpectedtxt">trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakcolumngapdisplayflexutf16surrogateshtml">trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates.html</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakletterspacingutf16surrogatesexpectedtxt">trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakletterspacingutf16surrogateshtml">trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates.html</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakmaxwidthutf16surrogatesexpectedtxt">trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttextwordbreakmaxwidthutf16surrogateshtml">trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlinetextTextUtilcpp">trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/ChangeLog 2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2021-10-28  Gabriel Nava Marino  <gnavamarino@apple.com>
+
+        Add an additional edge case for surrogate pairs to existing tests.
+        https://bugs.webkit.org/show_bug.cgi?id=232053
+
+        Reviewed by Alan Bujtas.
+
+        * fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt:
+        * fast/text/word-break-column-gap-display-flex-utf16-surrogates.html:
+        * fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt:
+        * fast/text/word-break-letter-spacing-utf16-surrogates.html:
+        * fast/text/word-break-max-width-utf16-surrogates-expected.txt:
+        * fast/text/word-break-max-width-utf16-surrogates.html:
+
</ins><span class="cx"> 2021-10-28  Nikos Mouchtaris  <nmouchtaris@apple.com>
</span><span class="cx"> 
</span><span class="cx">         if border-radius includes a var(), the value is not readable from .style
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakcolumngapdisplayflexutf16surrogatesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt     2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates-expected.txt        2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -12,4 +12,6 @@
</span><span class="cx"> �r�
</span><span class="cx"> �𐀀
</span><span class="cx"> 𐀀�
</span><ins>+r��r
+r𐀀r
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakcolumngapdisplayflexutf16surrogateshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates.html (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates.html     2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-column-gap-display-flex-utf16-surrogates.html        2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -48,6 +48,12 @@
</span><span class="cx"> 
</span><span class="cx">     // surrogate lead + surrogate trail + surrogate lead
</span><span class="cx">     document.getElementById("div14").append("\ud800\udc00\ud800");
</span><ins>+
+    // single + surrogate trail + surrogate lead + single
+    document.getElementById("div15").append("r\udc00\ud800r");
+
+    // single + surrogate lead + surrogate trail + single
+    document.getElementById("div16").append("r\ud800\udc00r");
</ins><span class="cx">    
</span><span class="cx">     if (window.testRunner)
</span><span class="cx">         testRunner.dumpAsText();
</span><span class="lines">@@ -67,4 +73,6 @@
</span><span class="cx"> <div id="div12"></div>
</span><span class="cx"> <div id="div13"></div>
</span><span class="cx"> <div id="div14"></div>
</span><ins>+<div id="div15"></div>
+<div id="div16"></div>
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakletterspacingutf16surrogatesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt      2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates-expected.txt 2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -12,4 +12,6 @@
</span><span class="cx"> �r�
</span><span class="cx"> �𐀀
</span><span class="cx"> 𐀀�
</span><ins>+r��r
+r𐀀r
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakletterspacingutf16surrogateshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates.html (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates.html      2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-letter-spacing-utf16-surrogates.html 2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -48,6 +48,12 @@
</span><span class="cx">     // surrogate lead + surrogate trail + surrogate lead
</span><span class="cx">     document.getElementById("div14").append("\ud800\udc00\ud800");
</span><span class="cx"> 
</span><ins>+    // single + surrogate trail + surrogate lead + single
+    document.getElementById("div15").append("r\udc00\ud800r");
+
+    // single + surrogate lead + surrogate trail + single
+    document.getElementById("div16").append("r\ud800\udc00r");
+
</ins><span class="cx">     if (window.testRunner)
</span><span class="cx">         testRunner.dumpAsText();
</span><span class="cx">   };
</span><span class="lines">@@ -66,4 +72,6 @@
</span><span class="cx"> <div id="div12"></div>
</span><span class="cx"> <div id="div13"></div>
</span><span class="cx"> <div id="div14"></div>
</span><ins>+<div id="div15"></div>
+<div id="div16"></div>
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakmaxwidthutf16surrogatesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates-expected.txt (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates-expected.txt   2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates-expected.txt      2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -12,4 +12,6 @@
</span><span class="cx"> �r�
</span><span class="cx"> �𐀀
</span><span class="cx"> 𐀀�
</span><ins>+r��r
+r𐀀r
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextwordbreakmaxwidthutf16surrogateshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates.html (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates.html   2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/LayoutTests/fast/text/word-break-max-width-utf16-surrogates.html      2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -48,6 +48,12 @@
</span><span class="cx">     // surrogate lead + surrogate trail + surrogate lead
</span><span class="cx">     document.getElementById("div14").append("\ud800\udc00\ud800");
</span><span class="cx"> 
</span><ins>+    // single + surrogate trail + surrogate lead + single
+    document.getElementById("div15").append("r\udc00\ud800r");
+
+    // single + surrogate lead + surrogate trail + single
+    document.getElementById("div16").append("r\ud800\udc00r");
+
</ins><span class="cx">     if (window.testRunner)
</span><span class="cx">         testRunner.dumpAsText();
</span><span class="cx">   };
</span><span class="lines">@@ -66,4 +72,6 @@
</span><span class="cx"> <div id="div12"></div>
</span><span class="cx"> <div id="div13"></div>
</span><span class="cx"> <div id="div14"></div>
</span><ins>+<div id="div15"></div>
+<div id="div16"></div>
</ins><span class="cx"> PASS
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/Source/WebCore/ChangeLog      2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2021-10-28  Gabriel Nava Marino  <gnavamarino@apple.com>
+
+        Negative length returned by TextUtil::midWordBreak with surrogate pair
+        https://bugs.webkit.org/show_bug.cgi?id=232053
+
+        Reviewed by Alan Bujtas.
+
+        When the substring does not fit, the right side is supposed to be the start
+        of the surrogate pair if applicable. However, if the start of the surrogate
+        pair falls to the left of the startPosition, we will end up returning a
+        negative length. Instead, bail out at this point since we know that our
+        middle point (which becomes the right) falls before the start position.
+        We are not going to find a non-empty fitting content anymore in here.
+
+        * layout/formattingContexts/inline/text/TextUtil.cpp:
+        (WebCore::Layout::TextUtil::breakWord):
+
</ins><span class="cx"> 2021-10-28  Nikos Mouchtaris  <nmouchtaris@apple.com>
</span><span class="cx"> 
</span><span class="cx">         if border-radius includes a var(), the value is not readable from .style
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlinetextTextUtilcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp (285015 => 285016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp  2021-10-29 02:19:51 UTC (rev 285015)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp     2021-10-29 02:53:47 UTC (rev 285016)
</span><span class="lines">@@ -151,6 +151,8 @@
</span><span class="cx">         // We should never break in the middle of a surrogate pair. They are considered one joint entity.
</span><span class="cx">         auto offset = index + 1;
</span><span class="cx">         U16_SET_CP_LIMIT(text, 0, offset, text.length());
</span><ins>+
+        // Returns the index at trail.
</ins><span class="cx">         return offset - 1;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -169,9 +171,11 @@
</span><span class="cx">             left = middle + 1;
</span><span class="cx">             leftSideWidth = width;
</span><span class="cx">         } else if (width > availableWidth) {
</span><del>-            // When the substring does not fit, the right side is supposed to be the start of the surrogate pair if applicable.
</del><ins>+            // When the substring does not fit, the right side is supposed to be the start of the surrogate pair if applicable, unless startPosition falls between surrogate pair.
</ins><span class="cx">             right = middle;
</span><span class="cx">             U16_SET_CP_START(text, 0, right);
</span><ins>+            if (right < startPosition)
+                return { };
</ins><span class="cx">         } else {
</span><span class="cx">             right = middle + 1;
</span><span class="cx">             leftSideWidth = width;
</span></span></pre>
</div>
</div>

</body>
</html>