<!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>[174388] trunk/Source</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/174388">174388</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2014-10-06 23:58:41 -0700 (Mon, 06 Oct 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Make StringView check the lifetime of the StringImpl it's created from
https://bugs.webkit.org/show_bug.cgi?id=137202
Reviewed by Anders Carlsson.
Source/WebCore:
* platform/graphics/TextRun.cpp: Update since TextRun's definition now
uses a StringView.
Source/WTF:
* WTF.vcxproj/WTF.vcxproj: Added StringView.cpp.
* WTF.vcxproj/WTF.vcxproj.filters: Added StringView.cpp.
* WTF.xcodeproj/project.pbxproj: Added StringView.cpp.
* wtf/CMakeLists.txt: Added StringView.cpp.
* wtf/text/StringImpl.cpp:
(WTF::StringImpl::~StringImpl): Call StringView::invalidate.
* wtf/text/StringView.cpp: Added.
(WTF::underlyingStrings): Returns map from StringImpl to the underlying
string object used by StringView to track validity.
(WTF::StringView::invalidate): Mark the underlying string object invalid,
and remove it from the map, so any future StringImpl will get a new one,
even if it has the same pointer.
(WTF::StringView::underlyingStringIsValid): Return true only if the
underlying string is still valid.
(WTF::StringView::setUnderlyingString): Create and manage reference counts
of underlying string objects as needed.
* wtf/text/StringView.h: Moved function bodies out of the class definition,
so we can now read a clean class definition to see the class design and what
functions it offers.
(WTF::StringView::StringView): Added a comment to the default constructor.
Also added copy and move constructors so they can call setUnderlyingString
and assert the underlying string is valid as needed, replacing the
compiler-generated ones.
(WTF::StringView::~StringView): Added a call to setUnderlyingString.
(WTF::StringView::operator=): Added these assignment operators with the same
job as the constructors above.
(WTF::StringView::initialize): Added a comment.
(WTF::StringView::characters8): Added an assertion that the underlying
string is valid.
(WTF::StringView::characters16): Ditto.
(WTF::StringView::substring): Added code to propagate the underlying string
from the original string to the substring.
(WTF::StringView::invalidate): Inline empty version of this function for
non-debug builds.
(WTF::StringView::underlyingStringIsValid): Ditto.
(WTF::StringView::setUnderlyingString): Ditto.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFvcxprojWTFvcxproj">trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj</a></li>
<li><a href="#trunkSourceWTFWTFvcxprojWTFvcxprojfilters">trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCMakeListstxt">trunk/Source/WTF/wtf/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplcpp">trunk/Source/WTF/wtf/text/StringImpl.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextStringViewh">trunk/Source/WTF/wtf/text/StringView.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsTextRuncpp">trunk/Source/WebCore/platform/graphics/TextRun.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWTFwtftextStringViewcpp">trunk/Source/WTF/wtf/text/StringView.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/ChangeLog        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2014-10-06 Darin Adler <darin@apple.com>
+
+ Make StringView check the lifetime of the StringImpl it's created from
+ https://bugs.webkit.org/show_bug.cgi?id=137202
+
+ Reviewed by Anders Carlsson.
+
+ * WTF.vcxproj/WTF.vcxproj: Added StringView.cpp.
+ * WTF.vcxproj/WTF.vcxproj.filters: Added StringView.cpp.
+ * WTF.xcodeproj/project.pbxproj: Added StringView.cpp.
+ * wtf/CMakeLists.txt: Added StringView.cpp.
+
+ * wtf/text/StringImpl.cpp:
+ (WTF::StringImpl::~StringImpl): Call StringView::invalidate.
+
+ * wtf/text/StringView.cpp: Added.
+ (WTF::underlyingStrings): Returns map from StringImpl to the underlying
+ string object used by StringView to track validity.
+ (WTF::StringView::invalidate): Mark the underlying string object invalid,
+ and remove it from the map, so any future StringImpl will get a new one,
+ even if it has the same pointer.
+ (WTF::StringView::underlyingStringIsValid): Return true only if the
+ underlying string is still valid.
+ (WTF::StringView::setUnderlyingString): Create and manage reference counts
+ of underlying string objects as needed.
+
+ * wtf/text/StringView.h: Moved function bodies out of the class definition,
+ so we can now read a clean class definition to see the class design and what
+ functions it offers.
+ (WTF::StringView::StringView): Added a comment to the default constructor.
+ Also added copy and move constructors so they can call setUnderlyingString
+ and assert the underlying string is valid as needed, replacing the
+ compiler-generated ones.
+ (WTF::StringView::~StringView): Added a call to setUnderlyingString.
+ (WTF::StringView::operator=): Added these assignment operators with the same
+ job as the constructors above.
+ (WTF::StringView::initialize): Added a comment.
+ (WTF::StringView::characters8): Added an assertion that the underlying
+ string is valid.
+ (WTF::StringView::characters16): Ditto.
+ (WTF::StringView::substring): Added code to propagate the underlying string
+ from the original string to the substring.
+ (WTF::StringView::invalidate): Inline empty version of this function for
+ non-debug builds.
+ (WTF::StringView::underlyingStringIsValid): Ditto.
+ (WTF::StringView::setUnderlyingString): Ditto.
+
</ins><span class="cx"> 2014-10-06 Brent Fulgham <bfulgham@apple.com>
</span><span class="cx">
</span><span class="cx"> [Win] DateMath's calculateUTFOffset does not account for DST.
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -134,6 +134,7 @@
</span><span class="cx"> <ClCompile Include="..\wtf\text\StringBuilder.cpp" />
</span><span class="cx"> <ClCompile Include="..\wtf\text\StringImpl.cpp" />
</span><span class="cx"> <ClCompile Include="..\wtf\text\StringStatics.cpp" />
</span><ins>+ <ClCompile Include="..\wtf\text\StringView.cpp" />
</ins><span class="cx"> <ClCompile Include="..\wtf\text\WTFString.cpp" />
</span><span class="cx"> <ClCompile Include="..\wtf\text\cf\AtomicStringCF.cpp" />
</span><span class="cx"> <ClCompile Include="..\wtf\text\cf\StringCF.cpp" />
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -60,6 +60,9 @@
</span><span class="cx"> <ClCompile Include="..\wtf\text\StringStatics.cpp">
</span><span class="cx"> <Filter>text</Filter>
</span><span class="cx"> </ClCompile>
</span><ins>+ <ClCompile Include="..\wtf\text\StringView.cpp">
+ <Filter>text</Filter>
+ </ClCompile>
</ins><span class="cx"> <ClCompile Include="..\wtf\text\AtomicString.cpp">
</span><span class="cx"> <Filter>text</Filter>
</span><span class="cx"> </ClCompile>
</span><span class="lines">@@ -716,4 +719,4 @@
</span><span class="cx"> <None Include="WTFPostBuild.cmd" />
</span><span class="cx"> <None Include="WTFPreBuild.cmd" />
</span><span class="cx"> </ItemGroup>
</span><del>-</Project>
</del><span class="cx">\ No newline at end of file
</span><ins>+</Project>
</ins></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -84,6 +84,7 @@
</span><span class="cx">                 93934BD518A1F16900D0D6A1 /* StringViewCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93934BD418A1F16900D0D6A1 /* StringViewCF.cpp */; };
</span><span class="cx">                 93AC91A818942FC400244939 /* LChar.h in Headers */ = {isa = PBXBuildFile; fileRef = 93AC91A718942FC400244939 /* LChar.h */; };
</span><span class="cx">                 93B1AA80180E5AF3004A2F05 /* PassRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B1AA7F180E5AF3004A2F05 /* PassRef.h */; };
</span><ins>+                93F1993E19D7958D00C2390B /* StringView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F1993D19D7958D00C2390B /* StringView.cpp */; };
</ins><span class="cx">                 974CFC8E16A4F327006D5404 /* WeakPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 974CFC8D16A4F327006D5404 /* WeakPtr.h */; };
</span><span class="cx">                 9BC70F05176C379D00101DEC /* AtomicStringTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BC70F04176C379D00101DEC /* AtomicStringTable.cpp */; };
</span><span class="cx">                 9BD8F40B176C2B470002D865 /* AtomicStringTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD8F40A176C2AD80002D865 /* AtomicStringTable.h */; };
</span><span class="lines">@@ -373,6 +374,7 @@
</span><span class="cx">                 93934BD418A1F16900D0D6A1 /* StringViewCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringViewCF.cpp; path = cf/StringViewCF.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 93AC91A718942FC400244939 /* LChar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LChar.h; sourceTree = "<group>"; };
</span><span class="cx">                 93B1AA7F180E5AF3004A2F05 /* PassRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassRef.h; sourceTree = "<group>"; };
</span><ins>+                93F1993D19D7958D00C2390B /* StringView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringView.cpp; sourceTree = "<group>"; };
</ins><span class="cx">                 974CFC8D16A4F327006D5404 /* WeakPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakPtr.h; sourceTree = "<group>"; };
</span><span class="cx">                 9BC70F04176C379D00101DEC /* AtomicStringTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicStringTable.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 9BD8F40A176C2AD80002D865 /* AtomicStringTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtomicStringTable.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -954,12 +956,13 @@
</span><span class="cx">                                 A8A47327151A825B004123FF /* StringHash.h */,
</span><span class="cx">                                 A8A47328151A825B004123FF /* StringImpl.cpp */,
</span><span class="cx">                                 A8A47329151A825B004123FF /* StringImpl.h */,
</span><ins>+                                1A6EB1DF187D0BD30030126F /* StringView.h */,
+                                93F1993D19D7958D00C2390B /* StringView.cpp */,
</ins><span class="cx">                                 A8A4732A151A825B004123FF /* StringOperators.h */,
</span><span class="cx">                                 A8A4732B151A825B004123FF /* StringStatics.cpp */,
</span><span class="cx">                                 A8A4732C151A825B004123FF /* TextPosition.h */,
</span><span class="cx">                                 A8A4732D151A825B004123FF /* WTFString.cpp */,
</span><span class="cx">                                 A8A4732E151A825B004123FF /* WTFString.h */,
</span><del>-                                1A6EB1DF187D0BD30030126F /* StringView.h */,
</del><span class="cx">                         );
</span><span class="cx">                         path = text;
</span><span class="cx">                         sourceTree = "<group>";
</span><span class="lines">@@ -1351,6 +1354,7 @@
</span><span class="cx">                                 A8A473EC151A825B004123FF /* MetaAllocator.cpp in Sources */,
</span><span class="cx">                                 A8A473F4151A825B004123FF /* NumberOfCores.cpp in Sources */,
</span><span class="cx">                                 A8A473F7151A825B004123FF /* OSAllocatorPosix.cpp in Sources */,
</span><ins>+                                93F1993E19D7958D00C2390B /* StringView.cpp in Sources */,
</ins><span class="cx">                                 A8A473F9151A825B004123FF /* OSRandomSource.cpp in Sources */,
</span><span class="cx">                                 A8A47400151A825B004123FF /* PageAllocationAligned.cpp in Sources */,
</span><span class="cx">                                 A8A47402151A825B004123FF /* PageBlock.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -201,6 +201,7 @@
</span><span class="cx"> text/StringBuilder.cpp
</span><span class="cx"> text/StringImpl.cpp
</span><span class="cx"> text/StringStatics.cpp
</span><ins>+ text/StringView.cpp
</ins><span class="cx"> text/WTFString.cpp
</span><span class="cx">
</span><span class="cx"> threads/BinarySemaphore.cpp
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.cpp        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -105,6 +105,8 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!isStatic());
</span><span class="cx">
</span><ins>+ StringView::invalidate(*this);
+
</ins><span class="cx"> STRING_STATS_REMOVE_STRING(*this);
</span><span class="cx">
</span><span class="cx"> if (isAtomic() && m_length)
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringViewcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/text/StringView.cpp (0 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringView.cpp         (rev 0)
+++ trunk/Source/WTF/wtf/text/StringView.cpp        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -0,0 +1,123 @@
</span><ins>+/*
+
+Copyright (C) 2014 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "config.h"
+#include "StringView.h"
+
+#include <mutex>
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+
+#if CHECK_STRINGVIEW_LIFETIME
+
+namespace WTF {
+
+// Manage reference count manually so UnderlyingString does not need to be defined in the header.
+
+struct StringView::UnderlyingString {
+ std::atomic_uint refCount { 1 };
+ bool isValid { true };
+ const StringImpl& string;
+ explicit UnderlyingString(const StringImpl&);
+};
+
+StringView::UnderlyingString::UnderlyingString(const StringImpl& string)
+ : string(string)
+{
+}
+
+static std::mutex& underlyingStringsMutex()
+{
+ static NeverDestroyed<std::mutex> mutex;
+ return mutex;
+}
+
+static HashMap<const StringImpl*, StringView::UnderlyingString*>& underlyingStrings()
+{
+ static NeverDestroyed<HashMap<const StringImpl*, StringView::UnderlyingString*>> map;
+ return map;
+}
+
+void StringView::invalidate(const StringImpl& stringToBeDestroyed)
+{
+ UnderlyingString* underlyingString;
+ {
+ std::lock_guard<std::mutex> lock(underlyingStringsMutex());
+ underlyingString = underlyingStrings().take(&stringToBeDestroyed);
+ if (!underlyingString)
+ return;
+ }
+ ASSERT(underlyingString->isValid);
+ underlyingString->isValid = false;
+}
+
+bool StringView::underlyingStringIsValid() const
+{
+ return !m_underlyingString || m_underlyingString->isValid;
+}
+
+void StringView::adoptUnderlyingString(UnderlyingString* underlyingString)
+{
+ if (m_underlyingString) {
+ if (!--m_underlyingString->refCount) {
+ if (m_underlyingString->isValid) {
+ std::lock_guard<std::mutex> lock(underlyingStringsMutex());
+ underlyingStrings().remove(&m_underlyingString->string);
+ }
+ delete m_underlyingString;
+ }
+ }
+ m_underlyingString = underlyingString;
+}
+
+void StringView::setUnderlyingString(const StringImpl* string)
+{
+ UnderlyingString* underlyingString;
+ if (!string)
+ underlyingString = nullptr;
+ else {
+ std::lock_guard<std::mutex> lock(underlyingStringsMutex());
+ auto result = underlyingStrings().add(string, nullptr);
+ if (result.isNewEntry)
+ result.iterator->value = new UnderlyingString(*string);
+ else
+ ++result.iterator->value->refCount;
+ underlyingString = result.iterator->value;
+ }
+ adoptUnderlyingString(underlyingString);
+}
+
+void StringView::setUnderlyingString(const StringView& string)
+{
+ UnderlyingString* underlyingString = string.m_underlyingString;
+ if (underlyingString)
+ ++underlyingString->refCount;
+ adoptUnderlyingString(underlyingString);
+}
+
+}
+
+#endif
</ins><span class="cx">Property changes on: trunk/Source/WTF/wtf/text/StringView.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceWTFwtftextStringViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringView.h (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringView.h        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WTF/wtf/text/StringView.h        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -32,160 +32,202 @@
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx"> #include <wtf/text/LChar.h>
</span><span class="cx">
</span><ins>+#ifdef NDEBUG
+#define CHECK_STRINGVIEW_LIFETIME 0
+#else
+#define CHECK_STRINGVIEW_LIFETIME 1
+#endif
+
</ins><span class="cx"> namespace WTF {
</span><span class="cx">
</span><span class="cx"> // StringView is a non-owning reference to a string, similar to the proposed std::string_view.
</span><span class="cx"> // Whether the string is 8-bit or 16-bit is encoded in the upper bit of the length member.
</span><del>-// This means that strings longer than 2 Gigabytes can not be represented. If that turns out to be
-// a problem we can investigate alternative solutions.
</del><ins>+// This means that strings longer than 2 gigacharacters cannot be represented.
</ins><span class="cx">
</span><span class="cx"> class StringView {
</span><span class="cx"> public:
</span><del>- StringView()
- : m_characters(nullptr)
- , m_length(0)
- {
- }
</del><ins>+ StringView();
+ ~StringView();
+ StringView(StringView&&);
+ StringView(const StringView&);
+ StringView& operator=(StringView&&);
+ StringView& operator=(const StringView&);
</ins><span class="cx">
</span><del>- StringView(const LChar* characters, unsigned length)
- {
- initialize(characters, length);
- }
</del><ins>+ StringView(const String&);
+ StringView(const StringImpl&);
+ StringView(const LChar*, unsigned length);
+ StringView(const UChar*, unsigned length);
</ins><span class="cx">
</span><del>- StringView(const UChar* characters, unsigned length)
- {
- initialize(characters, length);
- }
</del><ins>+ static StringView empty();
</ins><span class="cx">
</span><del>- StringView(const StringImpl&);
- StringView(const String&);
</del><ins>+ unsigned length() const;
+ bool isEmpty() const;
</ins><span class="cx">
</span><del>- static StringView empty()
- {
- return StringView(reinterpret_cast<const LChar*>(""), 0);
- }
</del><ins>+ explicit operator bool() const;
+ bool isNull() const;
</ins><span class="cx">
</span><del>- const LChar* characters8() const
- {
- ASSERT(is8Bit());
</del><ins>+ UChar operator[](unsigned index) const;
</ins><span class="cx">
</span><del>- return static_cast<const LChar*>(m_characters);
- }
</del><ins>+ class CodeUnits;
+ CodeUnits codeUnits() const;
</ins><span class="cx">
</span><del>- const UChar* characters16() const
- {
- ASSERT(!is8Bit());
</del><ins>+ class CodePoints;
+ CodePoints codePoints() const;
</ins><span class="cx">
</span><del>- return static_cast<const UChar*>(m_characters);
- }
</del><ins>+ bool is8Bit() const;
+ const LChar* characters8() const;
+ const UChar* characters16() const;
</ins><span class="cx">
</span><ins>+ String toString() const;
+ String toStringWithoutCopying() const;
+
+#if USE(CF)
+ // This function converts null strings to empty strings.
+ WTF_EXPORT_STRING_API RetainPtr<CFStringRef> createCFStringWithoutCopying() const;
+#endif
+
+#ifdef __OBJC__
+ // These functions convert null strings to empty strings.
+ WTF_EXPORT_STRING_API RetainPtr<NSString> createNSString() const;
+ WTF_EXPORT_STRING_API RetainPtr<NSString> createNSStringWithoutCopying() const;
+#endif
+
+ class UpconvertedCharacters;
+ UpconvertedCharacters upconvertedCharacters() const;
+
</ins><span class="cx"> void getCharactersWithUpconvert(LChar*) const;
</span><span class="cx"> void getCharactersWithUpconvert(UChar*) const;
</span><span class="cx">
</span><del>- class UpconvertedCharacters {
- public:
- explicit UpconvertedCharacters(const StringView&);
- operator const UChar*() const { return m_characters; }
- const UChar* get() const { return m_characters; }
- private:
- Vector<UChar, 32> m_upconvertedCharacters;
- const UChar* m_characters;
- };
- UpconvertedCharacters upconvertedCharacters() const { return UpconvertedCharacters(*this); }
</del><ins>+ StringView substring(unsigned start, unsigned length = std::numeric_limits<unsigned>::max()) const;
</ins><span class="cx">
</span><del>- bool isNull() const { return !m_characters; }
- bool isEmpty() const { return !length(); }
- unsigned length() const { return m_length & ~is16BitStringFlag; }
</del><ins>+ size_t find(UChar, unsigned start = 0) const;
+ bool contains(UChar) const;
</ins><span class="cx">
</span><del>- explicit operator bool() const { return !isNull(); }
</del><ins>+ int toInt(bool& isValid) const;
+ float toFloat(bool& isValid) const;
</ins><span class="cx">
</span><del>- bool is8Bit() const { return !(m_length & is16BitStringFlag); }
</del><ins>+ static void invalidate(const StringImpl&);
</ins><span class="cx">
</span><del>- StringView substring(unsigned start, unsigned length = std::numeric_limits<unsigned>::max()) const
- {
- if (start >= this->length())
- return empty();
- unsigned maxLength = this->length() - start;
</del><ins>+ struct UnderlyingString;
</ins><span class="cx">
</span><del>- if (length >= maxLength) {
- if (!start)
- return *this;
- length = maxLength;
- }
</del><ins>+private:
+ void initialize(const LChar*, unsigned length);
+ void initialize(const UChar*, unsigned length);
</ins><span class="cx">
</span><del>- if (is8Bit())
- return StringView(characters8() + start, length);
</del><ins>+ WTF_EXPORT_STRING_API bool underlyingStringIsValid() const;
+ WTF_EXPORT_STRING_API void setUnderlyingString(const StringImpl*);
+ WTF_EXPORT_STRING_API void setUnderlyingString(const StringView&);
</ins><span class="cx">
</span><del>- return StringView(characters16() + start, length);
- }
</del><ins>+ static const unsigned is16BitStringFlag = 1u << 31;
</ins><span class="cx">
</span><del>- String toString() const;
</del><ins>+ const void* m_characters { nullptr };
+ unsigned m_length { 0 };
</ins><span class="cx">
</span><del>- float toFloat(bool& isValid) const;
- int toInt(bool& isValid) const;
</del><ins>+#if CHECK_STRINGVIEW_LIFETIME
+ void adoptUnderlyingString(UnderlyingString*);
+ UnderlyingString* m_underlyingString { nullptr };
+#endif
+};
</ins><span class="cx">
</span><del>- String toStringWithoutCopying() const;
</del><ins>+template<typename CharacterType, size_t inlineCapacity> void append(Vector<CharacterType, inlineCapacity>&, StringView);
</ins><span class="cx">
</span><del>- UChar operator[](unsigned index) const
- {
- ASSERT(index < length());
- if (is8Bit())
- return characters8()[index];
- return characters16()[index];
- }
</del><ins>+}
</ins><span class="cx">
</span><del>- size_t find(UChar character, unsigned start = 0) const;
</del><ins>+#include <wtf/text/WTFString.h>
</ins><span class="cx">
</span><del>- bool contains(UChar c) const { return find(c) != notFound; }
</del><ins>+namespace WTF {
</ins><span class="cx">
</span><del>- class CodePoints;
- class CodeUnits;
</del><ins>+inline StringView::StringView()
+{
+ // FIXME: It's peculiar that null strings are 16-bit and empty strings return 8-bit (according to the is8Bit function).
+}
</ins><span class="cx">
</span><del>- CodePoints codePoints() const;
- CodeUnits codeUnits() const;
</del><ins>+inline StringView::~StringView()
+{
+ setUnderlyingString(nullptr);
+}
</ins><span class="cx">
</span><del>-#if USE(CF)
- // This function converts null strings to empty strings.
- WTF_EXPORT_STRING_API RetainPtr<CFStringRef> createCFStringWithoutCopying() const;
-#endif
</del><ins>+inline StringView::StringView(StringView&& other)
+ : m_characters(other.m_characters)
+ , m_length(other.m_length)
+{
+ ASSERT(other.underlyingStringIsValid());
</ins><span class="cx">
</span><del>-#ifdef __OBJC__
- // These functions convert null strings to empty strings.
- WTF_EXPORT_STRING_API RetainPtr<NSString> createNSString() const;
- WTF_EXPORT_STRING_API RetainPtr<NSString> createNSStringWithoutCopying() const;
-#endif
</del><ins>+ other.m_characters = nullptr;
+ other.m_length = 0;
</ins><span class="cx">
</span><del>-private:
- void initialize(const LChar* characters, unsigned length)
- {
- ASSERT(!(length & is16BitStringFlag));
-
- m_characters = characters;
- m_length = length;
- }
</del><ins>+ setUnderlyingString(other);
+ other.setUnderlyingString(nullptr);
+}
</ins><span class="cx">
</span><del>- void initialize(const UChar* characters, unsigned length)
- {
- ASSERT(!(length & is16BitStringFlag));
-
- m_characters = characters;
- m_length = is16BitStringFlag | length;
- }
</del><ins>+inline StringView::StringView(const StringView& other)
+ : m_characters(other.m_characters)
+ , m_length(other.m_length)
+{
+ ASSERT(other.underlyingStringIsValid());
</ins><span class="cx">
</span><del>- static const unsigned is16BitStringFlag = 1u << 31;
</del><ins>+ setUnderlyingString(other);
+}
</ins><span class="cx">
</span><del>- const void* m_characters;
- unsigned m_length;
-};
</del><ins>+inline StringView& StringView::operator=(StringView&& other)
+{
+ ASSERT(other.underlyingStringIsValid());
</ins><span class="cx">
</span><ins>+ m_characters = other.m_characters;
+ m_length = other.m_length;
+
+ other.m_characters = nullptr;
+ other.m_length = 0;
+
+ setUnderlyingString(other);
+ other.setUnderlyingString(nullptr);
+
+ return *this;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-#include <wtf/text/WTFString.h>
</del><ins>+inline StringView& StringView::operator=(const StringView& other)
+{
+ ASSERT(other.underlyingStringIsValid());
</ins><span class="cx">
</span><del>-namespace WTF {
</del><ins>+ m_characters = other.m_characters;
+ m_length = other.m_length;
</ins><span class="cx">
</span><ins>+ setUnderlyingString(other);
+
+ return *this;
+}
+
+inline void StringView::initialize(const LChar* characters, unsigned length)
+{
+ // FIXME: We need a better solution here, because there is no guarantee that
+ // the length here won't be too long. Maybe at least a RELEASE_ASSERT?
+ ASSERT(!(length & is16BitStringFlag));
+ m_characters = characters;
+ m_length = length;
+}
+
+inline void StringView::initialize(const UChar* characters, unsigned length)
+{
+ // FIXME: We need a better solution here, because there is no guarantee that
+ // the length here won't be too long. Maybe at least a RELEASE_ASSERT?
+ ASSERT(!(length & is16BitStringFlag));
+ m_characters = characters;
+ m_length = is16BitStringFlag | length;
+}
+
+inline StringView::StringView(const LChar* characters, unsigned length)
+{
+ initialize(characters, length);
+}
+
+inline StringView::StringView(const UChar* characters, unsigned length)
+{
+ initialize(characters, length);
+}
+
</ins><span class="cx"> inline StringView::StringView(const StringImpl& string)
</span><span class="cx"> {
</span><ins>+ setUnderlyingString(&string);
</ins><span class="cx"> if (string.is8Bit())
</span><span class="cx"> initialize(string.characters8(), string.length());
</span><span class="cx"> else
</span><span class="lines">@@ -194,6 +236,7 @@
</span><span class="cx">
</span><span class="cx"> inline StringView::StringView(const String& string)
</span><span class="cx"> {
</span><ins>+ setUnderlyingString(string.impl());
</ins><span class="cx"> if (!string.impl()) {
</span><span class="cx"> m_characters = nullptr;
</span><span class="cx"> m_length = 0;
</span><span class="lines">@@ -206,55 +249,100 @@
</span><span class="cx"> initialize(string.characters16(), string.length());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-class StringView::CodePoints {
-public:
- class Iterator {
- public:
- Iterator(const StringView&, unsigned index);
- Iterator& operator++();
- UChar32 operator*() const;
- bool operator==(const Iterator&) const;
- bool operator!=(const Iterator&) const;
</del><ins>+inline StringView StringView::empty()
+{
+ return StringView(reinterpret_cast<const LChar*>(""), 0);
+}
</ins><span class="cx">
</span><del>- private:
- const StringView& m_stringView;
- mutable unsigned m_index;
-#if !ASSERT_DISABLED
- mutable bool m_alreadyIncremented;
-#endif
- };
</del><ins>+inline const LChar* StringView::characters8() const
+{
+ ASSERT(is8Bit());
+ ASSERT(underlyingStringIsValid());
+ return static_cast<const LChar*>(m_characters);
+}
</ins><span class="cx">
</span><del>- explicit CodePoints(const StringView&);
- Iterator begin() const;
- Iterator end() const;
</del><ins>+inline const UChar* StringView::characters16() const
+{
+ ASSERT(!is8Bit());
+ ASSERT(underlyingStringIsValid());
+ return static_cast<const UChar*>(m_characters);
+}
</ins><span class="cx">
</span><ins>+class StringView::UpconvertedCharacters {
+public:
+ explicit UpconvertedCharacters(const StringView&);
+ operator const UChar*() const { return m_characters; }
+ const UChar* get() const { return m_characters; }
</ins><span class="cx"> private:
</span><del>- StringView m_stringView;
</del><ins>+ Vector<UChar, 32> m_upconvertedCharacters;
+ const UChar* m_characters;
</ins><span class="cx"> };
</span><span class="cx">
</span><del>-class StringView::CodeUnits {
-public:
- class Iterator {
- public:
- Iterator(const StringView&, unsigned index);
- Iterator& operator++();
- UChar operator*() const;
- bool operator==(const Iterator&) const;
- bool operator!=(const Iterator&) const;
</del><ins>+inline StringView::UpconvertedCharacters StringView::upconvertedCharacters() const
+{
+ return UpconvertedCharacters(*this);
+}
</ins><span class="cx">
</span><del>- private:
- const StringView& m_stringView;
- unsigned m_index;
- };
</del><ins>+inline bool StringView::isNull() const
+{
+ return !m_characters;
+}
</ins><span class="cx">
</span><del>- explicit CodeUnits(const StringView&);
- Iterator begin() const;
- Iterator end() const;
</del><ins>+inline bool StringView::isEmpty() const
+{
+ return !length();
+}
</ins><span class="cx">
</span><del>-private:
- StringView m_stringView;
-};
</del><ins>+inline unsigned StringView::length() const
+{
+ return m_length & ~is16BitStringFlag;
+}
</ins><span class="cx">
</span><ins>+inline StringView::operator bool() const
+{
+ return !isNull();
+}
+
+inline bool StringView::is8Bit() const
+{
+ return !(m_length & is16BitStringFlag);
+}
+
+inline StringView StringView::substring(unsigned start, unsigned length) const
+{
+ if (start >= this->length())
+ return empty();
+ unsigned maxLength = this->length() - start;
+
+ if (length >= maxLength) {
+ if (!start)
+ return *this;
+ length = maxLength;
+ }
+
+ if (is8Bit()) {
+ StringView result(characters8() + start, length);
+ result.setUnderlyingString(*this);
+ return result;
+ }
+ StringView result(characters16() + start, length);
+ result.setUnderlyingString(*this);
+ return result;
+}
+
+inline UChar StringView::operator[](unsigned index) const
+{
+ ASSERT(index < length());
+ if (is8Bit())
+ return characters8()[index];
+ return characters16()[index];
+}
+
+inline bool StringView::contains(UChar character) const
+{
+ return find(character) != notFound;
+}
+
</ins><span class="cx"> inline void StringView::getCharactersWithUpconvert(LChar* destination) const
</span><span class="cx"> {
</span><span class="cx"> ASSERT(is8Bit());
</span><span class="lines">@@ -291,7 +379,6 @@
</span><span class="cx"> {
</span><span class="cx"> if (is8Bit())
</span><span class="cx"> return String(characters8(), length());
</span><del>-
</del><span class="cx"> return String(characters16(), length());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -313,7 +400,6 @@
</span><span class="cx"> {
</span><span class="cx"> if (is8Bit())
</span><span class="cx"> return StringImpl::createWithoutCopying(characters8(), length());
</span><del>-
</del><span class="cx"> return StringImpl::createWithoutCopying(characters16(), length());
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -324,6 +410,27 @@
</span><span class="cx"> return WTF::find(characters16(), length(), character, start);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#if !CHECK_STRINGVIEW_LIFETIME
+
+inline void StringView::invalidate(const StringImpl&)
+{
+}
+
+inline bool StringView::underlyingStringIsValid() const
+{
+ return true;
+}
+
+inline void StringView::setUnderlyingString(const StringImpl*)
+{
+}
+
+inline void StringView::setUnderlyingString(const StringView&)
+{
+}
+
+#endif
+
</ins><span class="cx"> template<typename StringType> class StringTypeAdapter;
</span><span class="cx">
</span><span class="cx"> template<> class StringTypeAdapter<StringView> {
</span><span class="lines">@@ -349,6 +456,63 @@
</span><span class="cx"> string.getCharactersWithUpconvert(buffer.data() + oldSize);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+class StringView::CodePoints {
+public:
+ explicit CodePoints(const StringView&);
+
+ class Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+
+private:
+ StringView m_stringView;
+};
+
+class StringView::CodeUnits {
+public:
+ explicit CodeUnits(const StringView&);
+
+ class Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+
+private:
+ StringView m_stringView;
+};
+
+class StringView::CodePoints::Iterator {
+public:
+ Iterator(const StringView&, unsigned index);
+
+ UChar32 operator*() const;
+ Iterator& operator++();
+
+ bool operator==(const Iterator&) const;
+ bool operator!=(const Iterator&) const;
+
+private:
+ const StringView& m_stringView;
+ mutable unsigned m_index;
+#if !ASSERT_DISABLED
+ mutable bool m_alreadyIncremented { false };
+#endif
+};
+
+class StringView::CodeUnits::Iterator {
+public:
+ Iterator(const StringView&, unsigned index);
+
+ UChar operator*() const;
+ Iterator& operator++();
+
+ bool operator==(const Iterator&) const;
+ bool operator!=(const Iterator&) const;
+
+private:
+ const StringView& m_stringView;
+ unsigned m_index;
+};
+
</ins><span class="cx"> inline auto StringView::codePoints() const -> CodePoints
</span><span class="cx"> {
</span><span class="cx"> return CodePoints(*this);
</span><span class="lines">@@ -367,9 +531,6 @@
</span><span class="cx"> inline StringView::CodePoints::Iterator::Iterator(const StringView& stringView, unsigned index)
</span><span class="cx"> : m_stringView(stringView)
</span><span class="cx"> , m_index(index)
</span><del>-#if !ASSERT_DISABLED
- , m_alreadyIncremented(false)
-#endif
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WebCore/ChangeLog        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-10-06 Darin Adler <darin@apple.com>
+
+ Make StringView check the lifetime of the StringImpl it's created from
+ https://bugs.webkit.org/show_bug.cgi?id=137202
+
+ Reviewed by Anders Carlsson.
+
+ * platform/graphics/TextRun.cpp: Update since TextRun's definition now
+ uses a StringView.
+
</ins><span class="cx"> 2014-10-06 Andy Estes <aestes@apple.com>
</span><span class="cx">
</span><span class="cx"> [iOS] Fix remaining misuses of abs() and fabsf()
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsTextRuncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/TextRun.cpp (174387 => 174388)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/TextRun.cpp        2014-10-07 06:54:48 UTC (rev 174387)
+++ trunk/Source/WebCore/platform/graphics/TextRun.cpp        2014-10-07 06:58:41 UTC (rev 174388)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,14 +29,14 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> struct ExpectedTextRunSize {
</span><del>- const void* pointer;
- int integers[2];
</del><ins>+ void* renderingContext;
+ StringView text;
+ unsigned integer1;
+ unsigned integer2;
</ins><span class="cx"> float float1;
</span><span class="cx"> float float2;
</span><span class="cx"> float float3;
</span><del>- uint32_t bitfields : 10;
- unsigned anUnsigned;
- RefPtr<TextRun::RenderingContext> renderingContext;
</del><ins>+ unsigned bitfields : 9;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> COMPILE_ASSERT(sizeof(TextRun) == sizeof(ExpectedTextRunSize), TextRun_is_not_of_expected_size);
</span></span></pre>
</div>
</div>
</body>
</html>