<!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>[209058] 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/209058">209058</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2016-11-28 20:29:55 -0800 (Mon, 28 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Streamline and speed up tokenizer and segmented string classes
https://bugs.webkit.org/show_bug.cgi?id=165003

Reviewed by Sam Weinig.

Source/JavaScriptCore:

* runtime/JSONObject.cpp:
(JSC::Stringifier::appendStringifiedValue): Use viewWithUnderlyingString when calling
StringBuilder::appendQuotedJSONString, since it now takes a StringView and there is
no benefit in creating a String for that function if one doesn't already exist.

Source/WebCore:

Profiling Speedometer on my iMac showed the tokenizer as one of the
hottest functions. This patch streamlines the segmented string class,
removing various unused features, and also improves some other functions
seen on the Speedometer profile. On my iMac I measured a speedup of
about 3%. Changes include:

- Removed m_pushedChar1, m_pushedChar2, and m_empty data members from the
  SegmentedString class and all the code that used to handle them.

- Simplified the SegmentedString advance functions so they are small
  enough to get inlined in the HTML tokenizer.

- Updated callers to call the simpler SegmentedString advance functions
  that don't handle newlines in as many cases as possible.

- Cut down on allocations of SegmentedString and made code move the
  segmented string and the strings that are moved into it rather than
  copying them whenever possible.

- Simplified segmented string functions, removing some branches, mostly
  from the non-fast paths.

- Removed small unused functions and small functions used in only one
  or two places, made more functions private and renamed for clarity.

* bindings/js/JSHTMLDocumentCustom.cpp:
(WebCore::documentWrite): Moved a little more of the common code in here
from the two functions belwo. Removed obsolete comment saying this was not
following the DOM specification because it is. Removed unneeded special
cases for 1 argument and no arguments. Take a reference instead of a pointer.
(WebCore::JSHTMLDocument::write): Updated for above.
(WebCore::JSHTMLDocument::writeln): Ditto.

* css/parser/CSSTokenizer.cpp: Added now-needed include.
* css/parser/CSSTokenizer.h: Removed unneeded include.

* css/parser/CSSTokenizerInputStream.h: Added definition of kEndOfFileMarker
here; this is now separate from the use in the HTMLParser. In the long run,
unclear to me whether it is really needed in either.

* dom/Document.cpp:
(WebCore::Document::prepareToWrite): Added. Helper function used by the three
different variants of write. Using this may prevent us from having to construct
a SegmentedString just to append one string after future refactoring.
(WebCore::Document::write): Updated to take an rvalue reference and move the
value through.
(WebCore::Document::writeln): Use a single write call instead of two.

* dom/Document.h: Changed write to take an rvalue reference to SegmentedString
rather than a const reference.

* dom/DocumentParser.h: Changed insert to take an rvalue reference to
SegmentedString. In the future, should probably overload to take a single
string since that is the normal case.

* dom/RawDataDocumentParser.h: Updated for change to DocumentParser.

* html/FTPDirectoryDocument.cpp:
(WebCore::FTPDirectoryDocumentParser::append): Refactored a bit, just enough
so that we don't need an assignment operator for SegmentedString that can
copy a String.

* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::insert): Updated to take an rvalue reference,
and move the value through.
* html/parser/HTMLDocumentParser.h: Updated for the above.

* html/parser/HTMLEntityParser.cpp:
(WebCore::HTMLEntityParser::consumeNamedEntity): Updated for name changes.
Changed the twao calls to advance here to call advancePastNonNewline; no
change in behavior, but asserts what the code was assuming before, that the
character was not a newline.

* html/parser/HTMLInputStream.h:
(WebCore::HTMLInputStream::appendToEnd): Updated to take an rvalue reference,
and move the value through.
(WebCore::HTMLInputStream::insertAtCurrentInsertionPoint): Ditto.
(WebCore::HTMLInputStream::markEndOfFile): Removed the code to construct a
SegmentedString, overkill since we can just append an individual string.
(WebCore::HTMLInputStream::splitInto): Rewrote the move idiom here to actually
use move, which will reduce reference count churn and other unneeded work.

* html/parser/HTMLMetaCharsetParser.cpp:
(WebCore::HTMLMetaCharsetParser::checkForMetaCharset): Removed unneeded
construction of a SegmentedString, just to append a string.

* html/parser/HTMLSourceTracker.cpp:
(WebCore::HTMLSourceTracker::HTMLSourceTracker): Moved to the class definition.
(WebCore::HTMLSourceTracker::source): Updated for function name change.
* html/parser/HTMLSourceTracker.h: Updated for above.

* html/parser/HTMLTokenizer.cpp: Added now-needed include.
(WebCore::HTMLTokenizer::emitAndResumeInDataState): Use advancePastNonNewline,
since this function is never called in response to a newline character.
(WebCore::HTMLTokenizer::commitToPartialEndTag): Ditto.
(WebCore::HTMLTokenizer::commitToCompleteEndTag): Ditto.
(WebCore::HTMLTokenizer::processToken): Use ADVANCE_PAST_NON_NEWLINE_TO macro
instead of ADVANCE_TO in cases where the character we are advancing past is
known not to be a newline, so we can use the more efficient advance function
that doesn't check for the newline character.

* html/parser/InputStreamPreprocessor.h: Moved kEndOfFileMarker to
SegmentedString.h; not sure that's a good place for it either. In the long run,
unclear to me whether this is really needed.
(WebCore::InputStreamPreprocessor::peek): Added UNLIKELY for the empty check.
Added LIKELY for the not-special character check.
(WebCore::InputStreamPreprocessor::advance): Updated for the new name of the
advanceAndUpdateLineNumber function.
(WebCore::InputStreamPreprocessor::advancePastNonNewline): Added. More
efficient than advance for cases where the last characer is known not to be
a newline character.
(WebCore::InputStreamPreprocessor::skipNextNewLine): Deleted. Was unused.
(WebCore::InputStreamPreprocessor::reset): Deleted. Was unused except in the
constructor; added initial values for the data members to replace.
(WebCore::InputStreamPreprocessor::processNextInputCharacter): Removed long
FIXME comment that didn't really need to be here. Reorganized a bit.
(WebCore::InputStreamPreprocessor::isAtEndOfFile): Renamed and made static.

* html/track/BufferedLineReader.cpp:
(WebCore::BufferedLineReader::nextLine): Updated to not use the poorly named
scanCharacter function to advance past a newline. Also renamed from getLine
and changed to return Optional&lt;String&gt; instead of using a boolean to indicate
failure and an out argument.

* html/track/BufferedLineReader.h:
(WebCore::BufferedLineReader::BufferedLineReader): Use the default, putting
initial values on each data member below.
(WebCore::BufferedLineReader::append): Updated to take an rvalue reference,
and move the value through.
(WebCore::BufferedLineReader::scanCharacter): Deleted. Was poorly named,
and easy to replace with two lines of code at its two call sites.
(WebCore::BufferedLineReader::reset): Rewrote to correctly clear all the
data members of the class, not just the segmented string.

* html/track/InbandGenericTextTrack.cpp:
(WebCore::InbandGenericTextTrack::parseWebVTTFileHeader): Updated to take
an rvalue reference and move the value through.
* html/track/InbandGenericTextTrack.h: Updated for the above.

* html/track/InbandTextTrack.h: Updated since parseWebVTTFileHeader now
takes an rvalue reference.

* html/track/WebVTTParser.cpp:
(WebCore::WebVTTParser::parseFileHeader): Updated to take an rvalue reference
and move the value through.
(WebCore::WebVTTParser::parseBytes): Updated to pass ownership of the string
in to the line reader append function.
(WebCore::WebVTTParser::parseCueData): Use auto and WTFMove for WebVTTCueData.
(WebCore::WebVTTParser::flush): More of the same.
(WebCore::WebVTTParser::parse): Changed to use nextLine instead of getLine.
* html/track/WebVTTParser.h: Updated for the above.

* html/track/WebVTTTokenizer.cpp:
(WebCore::advanceAndEmitToken): Use advanceAndUpdateLineNumber by its new
name, just advance. No change in behavior.
(WebCore::WebVTTTokenizer::WebVTTTokenizer): Pass a String, not a
SegmentedString, to add the end of file marker.

* platform/graphics/InbandTextTrackPrivateClient.h: Updated since
parseWebVTTFileHeader takes an rvalue reference.

* platform/text/SegmentedString.cpp:
(WebCore::SegmentedString::Substring::appendTo): Moved here from the header.
The only caller is SegmentedString::toString, inside this file.
(WebCore::SegmentedString::SegmentedString): Deleted the copy constructor.
No longer needed.
(WebCore::SegmentedString::operator=): Defined a move assignment operator
rather than an ordinary assignment operator, since that's what the call
sites really need.
(WebCore::SegmentedString::length): Simplified since we no longer need to
support pushed characters.
(WebCore::SegmentedString::setExcludeLineNumbers): Simplified, since we
can just iterate m_otherSubstrings without an extra check. Also changed to
write directly to the data member of Substring instead of using a function.
(WebCore::SegmentedString::updateAdvanceFunctionPointersForEmptyString):
Added. Used when we run out of characters.
(WebCore::SegmentedString::clear): Removed code to clear now-deleted members.
Updated for changes to other member names.
(WebCore::SegmentedString::appendSubstring): Renamed from just append to
avoid ambiguity with the public append function. Changed to take an rvalue
reference, and move in, and added code to set m_currentCharacter properly,
so the caller doesn't have to deal with that.
(WebCore::SegmentedString::close): Updated to use m_isClosed by its new name.
Also removed unneeded comment about assertion that fires when trying to close
an already closed string.
(WebCore::SegmentedString::append): Added overloads for rvalue references of
both entire SegmentedString objects and of String. Streamlined to just call
appendSubstring and append to the deque.
(WebCore::SegmentedString::pushBack): Tightened up since we don't allow empty
strings and changed to take just a string, not an entire segmented string.
(WebCore::SegmentedString::advanceSubstring): Moved logic into the
advancePastSingleCharacterSubstringWithoutUpdatingLineNumber function.
(WebCore::SegmentedString::toString): Simplified now that we don't need to
support pushed characters.
(WebCore::SegmentedString::advancePastNonNewlines): Deleted.
(WebCore::SegmentedString::advance8): Deleted.
(WebCore::SegmentedString::advanceWithoutUpdatingLineNumber16): Renamed from
advance16. Simplified now that there are no pushed characters. Also changed to
access data members of m_currentSubstring directly instead of calling a function.
(WebCore::SegmentedString::advanceAndUpdateLineNumber8): Deleted.
(WebCore::SegmentedString::advanceAndUpdateLineNumber16): Ditto.
(WebCore::SegmentedString::advancePastSingleCharacterSubstringWithoutUpdatingLineNumber):
Renamed from advanceSlowCase. Removed uneeded logic to handle pushed characters.
Moved code in here from advanceSubstring.
(WebCore::SegmentedString::advancePastSingleCharacterSubstring): Renamed from
advanceAndUpdateLineNumberSlowCase. Simplified by calling the function above.
(WebCore::SegmentedString::advanceEmpty): Broke assertion up into two.
(WebCore::SegmentedString::updateSlowCaseFunctionPointers): Updated for name changes.
(WebCore::SegmentedString::advancePastSlowCase): Changed name and meaning of
boolean argument. Rewrote to use the String class less; it's now used only when
we fail to match after the first character rather than being used for the actual
comparison with the literal.

* platform/text/SegmentedString.h: Moved all non-trivial function bodies out of
the class definition to make things easier to read. Moved the SegmentedSubstring
class inside the SegmentedString class, making it a private struct named Substring.
Removed the m_ prefix from data members of the struct, removed many functions from
the struct and made its union be anonymous instead of naming it m_data. Removed
unneeded StringBuilder.h include.
(WebCore::SegmentedString::isEmpty): Changed to use the length of the substring
instead of a separate boolean. We never create an empty substring, nor leave one
in place as the current substring unless the entire segmented string is empty.
(WebCore::SegmentedString::advancePast): Updated to use the new member function
template instead of a non-template member function. The new member function is
entirely rewritten and does the matching directly rather than allocating a string
just to do prefix matching.
(WebCore::SegmentedString::advancePastLettersIgnoringASCIICase): Renamed to make
it clear that the literal must be all non-letters or lowercase letters as with
the other &quot;letters ignoring ASCII case&quot; functions. The three call sites all fit
the bill. Implement by calling the new function template.
(WebCore::SegmentedString::currentCharacter): Renamed from currentChar.
(WebCore::SegmentedString::Substring::Substring): Use an rvalue reference and
move the string in.
(WebCore::SegmentedString::Substring::currentCharacter): Simplified since this
is never used on an empty substring.
(WebCore::SegmentedString::Substring::incrementAndGetCurrentCharacter): Ditto.
(WebCore::SegmentedString::SegmentedString): Overload to take an rvalue reference.
Simplified since there are now fewer data members.
(WebCore::SegmentedString::advanceWithoutUpdatingLineNumber): Renamed from
advance, since this is only safe to use if there is some reason it is OK to skip
updating the line number.
(WebCore::SegmentedString::advance): Renamed from advanceAndUpdateLineNumber,
since doing that is the normal desired behavior and not worth mentioning in the
public function name.
(WebCore::SegmentedString::advancePastNewline): Renamed from
advancePastNewlineAndUpdateLineNumber.
(WebCore::SegmentedString::numberOfCharactersConsumed): Greatly simplified since
pushed characters are no longer supported.
(WebCore::SegmentedString::characterMismatch): Added. Used by advancePast.

* xml/parser/CharacterReferenceParserInlines.h:
(WebCore::unconsumeCharacters): Use toString rather than toStringPreserveCapacity
because the SegmentedString is going to take ownership of the string.
(WebCore::consumeCharacterReference): Updated to use the pushBack that takes just
a String, not a SegmentedString. Also use advancePastNonNewline.

* xml/parser/MarkupTokenizerInlines.h: Added ADVANCE_PAST_NON_NEWLINE_TO.

* xml/parser/XMLDocumentParser.cpp:
(WebCore::XMLDocumentParser::insert): Updated since this takes an rvalue reference.
(WebCore::XMLDocumentParser::append): Removed unnecessary code to create a
SegmentedString.
* xml/parser/XMLDocumentParser.h: Updated for above. Also fixed indentation
and initialized most data members.
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::XMLDocumentParser): Moved most data member
initialization into the class definition.
(WebCore::XMLDocumentParser::resumeParsing): Removed code that copied a
segmented string, but converted the whole thing into a string before using it.
Now we convert to a string right away.

Source/WTF:

* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::bufferCharacters&lt;LChar&gt;): Moved this here from
the header since it is only used inside the class. Also renamed from
getBufferCharacters.
(WTF::StringBuilder::bufferCharacters&lt;UChar&gt;): Ditto.
(WTF::StringBuilder::appendUninitializedUpconvert): Added. Helper
for the upconvert case in the 16-bit overload of StrinBuilder::append.
(WTF::StringBuilder::append): Changed to use appendUninitializedUpconvert.
(WTF::quotedJSONStringLength): Added. Used in new appendQuotedJSONString
implementation below that now correctly determines the size of what will
be appended by walking thorugh the string twice.
(WTF::appendQuotedJSONStringInternal): Moved the code that writes the
quote marks in here. Also made a few coding style tweaks.
(WTF::StringBuilder::appendQuotedJSONString): Rewrote to use a much
simpler algorithm that grows the string the same way the append function
does. The old code would use reserveCapacity in a way that was costly when
doing a lot of appends on the same string, and also allocated far too much
memory for normal use cases where characters did not need to be turned
into escape sequences.

* wtf/text/StringBuilder.h:
(WTF::StringBuilder::append): Tweaked style a bit, fixed a bug where the
m_is8Bit field wasn't set correctly in one case, optimized the function that
adds substrings for the case where this is the first append and the substring
happens to cover the entire string. Also clarified the assertions and removed
an unneeded check from that substring overload.
(WTF::equal): Reimplemented, using equalCommon.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSONObjectcpp">trunk/Source/JavaScriptCore/runtime/JSONObject.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtftextStringBuildercpp">trunk/Source/WTF/wtf/text/StringBuilder.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextStringBuilderh">trunk/Source/WTF/wtf/text/StringBuilder.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSHTMLDocumentCustomcpp">trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSTokenizercpp">trunk/Source/WebCore/css/parser/CSSTokenizer.cpp</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSTokenizerh">trunk/Source/WebCore/css/parser/CSSTokenizer.h</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSTokenizerInputStreamh">trunk/Source/WebCore/css/parser/CSSTokenizerInputStream.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumenth">trunk/Source/WebCore/dom/Document.h</a></li>
<li><a href="#trunkSourceWebCoredomDocumentParserh">trunk/Source/WebCore/dom/DocumentParser.h</a></li>
<li><a href="#trunkSourceWebCoredomRawDataDocumentParserh">trunk/Source/WebCore/dom/RawDataDocumentParser.h</a></li>
<li><a href="#trunkSourceWebCorehtmlFTPDirectoryDocumentcpp">trunk/Source/WebCore/html/FTPDirectoryDocument.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParsercpp">trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParserh">trunk/Source/WebCore/html/parser/HTMLDocumentParser.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLEntityParsercpp">trunk/Source/WebCore/html/parser/HTMLEntityParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLInputStreamh">trunk/Source/WebCore/html/parser/HTMLInputStream.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLMetaCharsetParsercpp">trunk/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLSourceTrackercpp">trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLSourceTrackerh">trunk/Source/WebCore/html/parser/HTMLSourceTracker.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLTokenizercpp">trunk/Source/WebCore/html/parser/HTMLTokenizer.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserInputStreamPreprocessorh">trunk/Source/WebCore/html/parser/InputStreamPreprocessor.h</a></li>
<li><a href="#trunkSourceWebCorehtmltrackBufferedLineReadercpp">trunk/Source/WebCore/html/track/BufferedLineReader.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmltrackBufferedLineReaderh">trunk/Source/WebCore/html/track/BufferedLineReader.h</a></li>
<li><a href="#trunkSourceWebCorehtmltrackInbandGenericTextTrackcpp">trunk/Source/WebCore/html/track/InbandGenericTextTrack.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmltrackInbandGenericTextTrackh">trunk/Source/WebCore/html/track/InbandGenericTextTrack.h</a></li>
<li><a href="#trunkSourceWebCorehtmltrackInbandTextTrackh">trunk/Source/WebCore/html/track/InbandTextTrack.h</a></li>
<li><a href="#trunkSourceWebCorehtmltrackWebVTTParsercpp">trunk/Source/WebCore/html/track/WebVTTParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmltrackWebVTTParserh">trunk/Source/WebCore/html/track/WebVTTParser.h</a></li>
<li><a href="#trunkSourceWebCorehtmltrackWebVTTTokenizercpp">trunk/Source/WebCore/html/track/WebVTTTokenizer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsInbandTextTrackPrivateClienth">trunk/Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h</a></li>
<li><a href="#trunkSourceWebCoreplatformtextSegmentedStringcpp">trunk/Source/WebCore/platform/text/SegmentedString.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformtextSegmentedStringh">trunk/Source/WebCore/platform/text/SegmentedString.h</a></li>
<li><a href="#trunkSourceWebCorexmlparserCharacterReferenceParserInlinesh">trunk/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h</a></li>
<li><a href="#trunkSourceWebCorexmlparserMarkupTokenizerInlinesh">trunk/Source/WebCore/xml/parser/MarkupTokenizerInlines.h</a></li>
<li><a href="#trunkSourceWebCorexmlparserXMLDocumentParsercpp">trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp</a></li>
<li><a href="#trunkSourceWebCorexmlparserXMLDocumentParserh">trunk/Source/WebCore/xml/parser/XMLDocumentParser.h</a></li>
<li><a href="#trunkSourceWebCorexmlparserXMLDocumentParserLibxml2cpp">trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-11-28  Darin Adler  &lt;darin@apple.com&gt;
+
+        Streamline and speed up tokenizer and segmented string classes
+        https://bugs.webkit.org/show_bug.cgi?id=165003
+
+        Reviewed by Sam Weinig.
+
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::appendStringifiedValue): Use viewWithUnderlyingString when calling
+        StringBuilder::appendQuotedJSONString, since it now takes a StringView and there is
+        no benefit in creating a String for that function if one doesn't already exist.
+
</ins><span class="cx"> 2016-11-21  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix exception scope verification failures in runtime/Intl* files.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSONObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSONObject.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSONObject.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/JavaScriptCore/runtime/JSONObject.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2016 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">@@ -354,7 +354,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (value.isString()) {
</span><del>-        builder.appendQuotedJSONString(asString(value)-&gt;value(m_exec));
</del><ins>+        builder.appendQuotedJSONString(asString(value)-&gt;viewWithUnderlyingString(*m_exec).view);
</ins><span class="cx">         return StringifySucceeded;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WTF/ChangeLog        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2016-11-28  Darin Adler  &lt;darin@apple.com&gt;
+
+        Streamline and speed up tokenizer and segmented string classes
+        https://bugs.webkit.org/show_bug.cgi?id=165003
+
+        Reviewed by Sam Weinig.
+
+        * wtf/text/StringBuilder.cpp:
+        (WTF::StringBuilder::bufferCharacters&lt;LChar&gt;): Moved this here from
+        the header since it is only used inside the class. Also renamed from
+        getBufferCharacters.
+        (WTF::StringBuilder::bufferCharacters&lt;UChar&gt;): Ditto.
+        (WTF::StringBuilder::appendUninitializedUpconvert): Added. Helper
+        for the upconvert case in the 16-bit overload of StrinBuilder::append.
+        (WTF::StringBuilder::append): Changed to use appendUninitializedUpconvert.
+        (WTF::quotedJSONStringLength): Added. Used in new appendQuotedJSONString
+        implementation below that now correctly determines the size of what will
+        be appended by walking thorugh the string twice.
+        (WTF::appendQuotedJSONStringInternal): Moved the code that writes the
+        quote marks in here. Also made a few coding style tweaks.
+        (WTF::StringBuilder::appendQuotedJSONString): Rewrote to use a much
+        simpler algorithm that grows the string the same way the append function
+        does. The old code would use reserveCapacity in a way that was costly when
+        doing a lot of appends on the same string, and also allocated far too much
+        memory for normal use cases where characters did not need to be turned
+        into escape sequences.
+
+        * wtf/text/StringBuilder.h:
+        (WTF::StringBuilder::append): Tweaked style a bit, fixed a bug where the
+        m_is8Bit field wasn't set correctly in one case, optimized the function that
+        adds substrings for the case where this is the first append and the substring
+        happens to cover the entire string. Also clarified the assertions and removed
+        an unneeded check from that substring overload.
+        (WTF::equal): Reimplemented, using equalCommon.
+
</ins><span class="cx"> 2016-11-26  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WTF] Import std::optional reference implementation as WTF::Optional
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringBuilder.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringBuilder.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WTF/wtf/text/StringBuilder.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010, 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;IntegerToStringConversion.h&quot;
</span><span class="cx"> #include &quot;MathExtras.h&quot;
</span><del>-#include &quot;WTFString.h&quot;
</del><span class="cx"> #include &lt;wtf/dtoa.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -40,6 +39,18 @@
</span><span class="cx">     return std::max(requiredLength, std::max(minimumCapacity, capacity * 2));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;&gt; ALWAYS_INLINE LChar* StringBuilder::bufferCharacters&lt;LChar&gt;()
+{
+    ASSERT(m_is8Bit);
+    return m_bufferCharacters8;
+}
+
+template&lt;&gt; ALWAYS_INLINE UChar* StringBuilder::bufferCharacters&lt;UChar&gt;()
+{
+    ASSERT(!m_is8Bit);
+    return m_bufferCharacters16;
+}
+
</ins><span class="cx"> void StringBuilder::reifyString() const
</span><span class="cx"> {
</span><span class="cx">     // Check if the string already exists.
</span><span class="lines">@@ -97,6 +108,7 @@
</span><span class="cx"> void StringBuilder::allocateBuffer(const LChar* currentCharacters, unsigned requiredLength)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_is8Bit);
</span><ins>+
</ins><span class="cx">     // Copy the existing data into a new buffer, set result to point to the end of the existing data.
</span><span class="cx">     auto buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters8);
</span><span class="cx">     memcpy(m_bufferCharacters8, currentCharacters, static_cast&lt;size_t&gt;(m_length) * sizeof(LChar)); // This can't overflow.
</span><span class="lines">@@ -112,6 +124,7 @@
</span><span class="cx"> void StringBuilder::allocateBuffer(const UChar* currentCharacters, unsigned requiredLength)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_is8Bit);
</span><ins>+
</ins><span class="cx">     // Copy the existing data into a new buffer, set result to point to the end of the existing data.
</span><span class="cx">     auto buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters16);
</span><span class="cx">     memcpy(m_bufferCharacters16, currentCharacters, static_cast&lt;size_t&gt;(m_length) * sizeof(UChar)); // This can't overflow.
</span><span class="lines">@@ -124,10 +137,11 @@
</span><span class="cx"> 
</span><span class="cx"> // Allocate a new 16 bit buffer, copying in currentCharacters (which is 8 bit and may come
</span><span class="cx"> // from either m_string or m_buffer, neither will be reassigned until the copy has completed).
</span><del>-void StringBuilder::allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength)
</del><ins>+void StringBuilder::allocateBufferUpconvert(const LChar* currentCharacters, unsigned requiredLength)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_is8Bit);
</span><span class="cx">     ASSERT(requiredLength &gt;= m_length);
</span><ins>+
</ins><span class="cx">     // Copy the existing data into a new buffer, set result to point to the end of the existing data.
</span><span class="cx">     auto buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters16);
</span><span class="cx">     for (unsigned i = 0; i &lt; m_length; ++i)
</span><span class="lines">@@ -141,8 +155,7 @@
</span><span class="cx">     ASSERT(m_buffer-&gt;length() == requiredLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;&gt;
-void StringBuilder::reallocateBuffer&lt;LChar&gt;(unsigned requiredLength)
</del><ins>+template&lt;&gt; void StringBuilder::reallocateBuffer&lt;LChar&gt;(unsigned requiredLength)
</ins><span class="cx"> {
</span><span class="cx">     // If the buffer has only one ref (by this StringBuilder), reallocate it,
</span><span class="cx">     // otherwise fall back to &quot;allocate and copy&quot; method.
</span><span class="lines">@@ -158,8 +171,7 @@
</span><span class="cx">     ASSERT(m_buffer-&gt;length() == requiredLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;&gt;
-void StringBuilder::reallocateBuffer&lt;UChar&gt;(unsigned requiredLength)
</del><ins>+template&lt;&gt; void StringBuilder::reallocateBuffer&lt;UChar&gt;(unsigned requiredLength)
</ins><span class="cx"> {
</span><span class="cx">     // If the buffer has only one ref (by this StringBuilder), reallocate it,
</span><span class="cx">     // otherwise fall back to &quot;allocate and copy&quot; method.
</span><span class="lines">@@ -166,7 +178,7 @@
</span><span class="cx">     m_string = String();
</span><span class="cx">     
</span><span class="cx">     if (m_buffer-&gt;is8Bit())
</span><del>-        allocateBufferUpConvert(m_buffer-&gt;characters8(), requiredLength);
</del><ins>+        allocateBufferUpconvert(m_buffer-&gt;characters8(), requiredLength);
</ins><span class="cx">     else if (m_buffer-&gt;hasOneRef())
</span><span class="cx">         m_buffer = StringImpl::reallocate(m_buffer.releaseNonNull(), requiredLength, m_bufferCharacters16);
</span><span class="cx">     else
</span><span class="lines">@@ -188,7 +200,7 @@
</span><span class="cx">         // Grow the string, if necessary.
</span><span class="cx">         if (newCapacity &gt; m_length) {
</span><span class="cx">             if (!m_length) {
</span><del>-                LChar* nullPlaceholder = 0;
</del><ins>+                LChar* nullPlaceholder = nullptr;
</ins><span class="cx">                 allocateBuffer(nullPlaceholder, newCapacity);
</span><span class="cx">             } else if (m_string.is8Bit())
</span><span class="cx">                 allocateBuffer(m_string.characters8(), newCapacity);
</span><span class="lines">@@ -201,8 +213,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Make 'length' additional capacity be available in m_buffer, update m_string &amp; m_length,
</span><span class="cx"> // return a pointer to the newly allocated storage.
</span><del>-template &lt;typename CharType&gt;
-ALWAYS_INLINE CharType* StringBuilder::appendUninitialized(unsigned length)
</del><ins>+template&lt;typename CharacterType&gt; ALWAYS_INLINE CharacterType* StringBuilder::appendUninitialized(unsigned length)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(length);
</span><span class="cx"> 
</span><span class="lines">@@ -217,16 +228,15 @@
</span><span class="cx">         unsigned currentLength = m_length;
</span><span class="cx">         m_string = String();
</span><span class="cx">         m_length = requiredLength;
</span><del>-        return getBufferCharacters&lt;CharType&gt;() + currentLength;
</del><ins>+        return bufferCharacters&lt;CharacterType&gt;() + currentLength;
</ins><span class="cx">     }
</span><del>-    
-    return appendUninitializedSlow&lt;CharType&gt;(requiredLength);
</del><ins>+
+    return appendUninitializedSlow&lt;CharacterType&gt;(requiredLength);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Make 'length' additional capacity be available in m_buffer, update m_string &amp; m_length,
</span><span class="cx"> // return a pointer to the newly allocated storage.
</span><del>-template &lt;typename CharType&gt;
-CharType* StringBuilder::appendUninitializedSlow(unsigned requiredLength)
</del><ins>+template&lt;typename CharacterType&gt; CharacterType* StringBuilder::appendUninitializedSlow(unsigned requiredLength)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(requiredLength);
</span><span class="cx"> 
</span><span class="lines">@@ -233,19 +243,38 @@
</span><span class="cx">     if (m_buffer) {
</span><span class="cx">         // If the buffer is valid it must be at least as long as the current builder contents!
</span><span class="cx">         ASSERT(m_buffer-&gt;length() &gt;= m_length);
</span><del>-        
-        reallocateBuffer&lt;CharType&gt;(expandedCapacity(capacity(), requiredLength));
</del><ins>+        reallocateBuffer&lt;CharacterType&gt;(expandedCapacity(capacity(), requiredLength));
</ins><span class="cx">     } else {
</span><span class="cx">         ASSERT(m_string.length() == m_length);
</span><del>-        allocateBuffer(m_length ? m_string.characters&lt;CharType&gt;() : 0, expandedCapacity(capacity(), requiredLength));
</del><ins>+        allocateBuffer(m_length ? m_string.characters&lt;CharacterType&gt;() : nullptr, expandedCapacity(capacity(), requiredLength));
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    CharType* result = getBufferCharacters&lt;CharType&gt;() + m_length;
</del><ins>+    auto* result = bufferCharacters&lt;CharacterType&gt;() + m_length;
</ins><span class="cx">     m_length = requiredLength;
</span><span class="cx">     ASSERT(m_buffer-&gt;length() &gt;= m_length);
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline UChar* StringBuilder::appendUninitializedUpconvert(unsigned length)
+{
+    unsigned requiredLength = length + m_length;
+    if (requiredLength &lt; length)
+        CRASH();
+
+    if (m_buffer) {
+        // If the buffer is valid it must be at least as long as the current builder contents!
+        ASSERT(m_buffer-&gt;length() &gt;= m_length);
+        allocateBufferUpconvert(m_buffer-&gt;characters8(), expandedCapacity(capacity(), requiredLength));
+    } else {
+        ASSERT(m_string.length() == m_length);
+        allocateBufferUpconvert(m_string.isNull() ? nullptr : m_string.characters8(), expandedCapacity(capacity(), requiredLength));
+    }
+
+    auto* result = m_bufferCharacters16 + m_length;
+    m_length = requiredLength;
+    return result;
+}
+
</ins><span class="cx"> void StringBuilder::append(const UChar* characters, unsigned length)
</span><span class="cx"> {
</span><span class="cx">     if (!length)
</span><span class="lines">@@ -254,32 +283,16 @@
</span><span class="cx">     ASSERT(characters);
</span><span class="cx"> 
</span><span class="cx">     if (m_is8Bit) {
</span><del>-        if (length == 1 &amp;&amp; !(*characters &amp; ~0xff)) {
</del><ins>+        if (length == 1 &amp;&amp; !(*characters &amp; ~0xFF)) {
</ins><span class="cx">             // Append as 8 bit character
</span><span class="cx">             LChar lChar = static_cast&lt;LChar&gt;(*characters);
</span><span class="cx">             append(&amp;lChar, 1);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-
-        // Calculate the new size of the builder after appending.
-        unsigned requiredLength = length + m_length;
-        if (requiredLength &lt; length)
-            CRASH();
-        
-        if (m_buffer) {
-            // If the buffer is valid it must be at least as long as the current builder contents!
-            ASSERT(m_buffer-&gt;length() &gt;= m_length);
-            
-            allocateBufferUpConvert(m_buffer-&gt;characters8(), expandedCapacity(capacity(), requiredLength));
-        } else {
-            ASSERT(m_string.length() == m_length);
-            allocateBufferUpConvert(m_string.isNull() ? 0 : m_string.characters8(), expandedCapacity(capacity(), requiredLength));
-        }
-
-        memcpy(m_bufferCharacters16 + m_length, characters, static_cast&lt;size_t&gt;(length) * sizeof(UChar));
-        m_length = requiredLength;
</del><ins>+        memcpy(appendUninitializedUpconvert(length), characters, static_cast&lt;size_t&gt;(length) * sizeof(UChar));
</ins><span class="cx">     } else
</span><span class="cx">         memcpy(appendUninitialized&lt;UChar&gt;(length), characters, static_cast&lt;size_t&gt;(length) * sizeof(UChar));
</span><ins>+
</ins><span class="cx">     ASSERT(m_buffer-&gt;length() &gt;= m_length);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -290,19 +303,22 @@
</span><span class="cx">     ASSERT(characters);
</span><span class="cx"> 
</span><span class="cx">     if (m_is8Bit) {
</span><del>-        LChar* dest = appendUninitialized&lt;LChar&gt;(length);
</del><ins>+        auto* destination = appendUninitialized&lt;LChar&gt;(length);
+        // FIXME: How did we determine a threshold of 8 here was the right one?
+        // Also, this kind of optimization could be useful anywhere else we have a
+        // performance-sensitive code path that calls memcpy.
</ins><span class="cx">         if (length &gt; 8)
</span><del>-            memcpy(dest, characters, static_cast&lt;size_t&gt;(length) * sizeof(LChar));
</del><ins>+            memcpy(destination, characters, length);
</ins><span class="cx">         else {
</span><span class="cx">             const LChar* end = characters + length;
</span><span class="cx">             while (characters &lt; end)
</span><del>-                *(dest++) = *(characters++);
</del><ins>+                *destination++ = *characters++;
</ins><span class="cx">         }
</span><span class="cx">     } else {
</span><del>-        UChar* dest = appendUninitialized&lt;UChar&gt;(length);
</del><ins>+        auto* destination = appendUninitialized&lt;UChar&gt;(length);
</ins><span class="cx">         const LChar* end = characters + length;
</span><span class="cx">         while (characters &lt; end)
</span><del>-            *(dest++) = *(characters++);
</del><ins>+            *destination++ = *characters++;
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -385,17 +401,58 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;typename OutputCharacterType, typename InputCharacterType&gt;
-static void appendQuotedJSONStringInternal(OutputCharacterType*&amp; output, const InputCharacterType* input, unsigned length)
</del><ins>+template&lt;typename LengthType, typename CharacterType&gt; static LengthType quotedJSONStringLength(const CharacterType* input, unsigned length)
</ins><span class="cx"> {
</span><del>-    for (const InputCharacterType* end = input + length; input != end; ++input) {
-        if (LIKELY(*input &gt; 0x1F)) {
-            if (*input == '&quot;' || *input == '\\')
</del><ins>+    LengthType quotedLength = 2;
+    for (unsigned i = 0; i &lt; length; ++i) {
+        auto character = input[i];
+        if (LIKELY(character &gt; 0x1F)) {
+            switch (character) {
+            case '&quot;':
+            case '\\':
+                quotedLength += 2;
+                break;
+            default:
+                ++quotedLength;
+                break;
+            }
+        } else {
+            switch (character) {
+            case '\t':
+            case '\r':
+            case '\n':
+            case '\f':
+            case '\b':
+                quotedLength += 2;
+                break;
+            default:
+                quotedLength += 6;
+            }
+        }
+    }
+    return quotedLength;
+}
+
+template&lt;typename CharacterType&gt; static inline unsigned quotedJSONStringLength(const CharacterType* input, unsigned length)
+{
+    constexpr auto maxSafeLength = (std::numeric_limits&lt;unsigned&gt;::max() - 2) / 6;
+    if (length &lt;= maxSafeLength)
+        return quotedJSONStringLength&lt;unsigned&gt;(input, length);
+    return quotedJSONStringLength&lt;Checked&lt;unsigned&gt;&gt;(input, length).unsafeGet();
+}
+
+template&lt;typename OutputCharacterType, typename InputCharacterType&gt; static inline void appendQuotedJSONStringInternal(OutputCharacterType* output, const InputCharacterType* input, unsigned length)
+{
+    *output++ = '&quot;';
+    for (unsigned i = 0; i &lt; length; ++i) {
+        auto character = input[i];
+        if (LIKELY(character &gt; 0x1F)) {
+            if (UNLIKELY(character == '&quot;' || character == '\\'))
</ins><span class="cx">                 *output++ = '\\';
</span><del>-            *output++ = *input;
</del><ins>+            *output++ = character;
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><del>-        switch (*input) {
</del><ins>+        switch (character) {
</ins><span class="cx">         case '\t':
</span><span class="cx">             *output++ = '\\';
</span><span class="cx">             *output++ = 't';
</span><span class="lines">@@ -417,56 +474,35 @@
</span><span class="cx">             *output++ = 'b';
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><del>-            ASSERT((*input &amp; 0xFF00) == 0);
-            static const char hexDigits[] = &quot;0123456789abcdef&quot;;
</del><ins>+            ASSERT(!(character &amp; ~0xFF));
</ins><span class="cx">             *output++ = '\\';
</span><span class="cx">             *output++ = 'u';
</span><span class="cx">             *output++ = '0';
</span><span class="cx">             *output++ = '0';
</span><del>-            *output++ = static_cast&lt;LChar&gt;(hexDigits[(*input &gt;&gt; 4) &amp; 0xF]);
-            *output++ = static_cast&lt;LChar&gt;(hexDigits[*input &amp; 0xF]);
</del><ins>+            *output++ = upperNibbleToLowercaseASCIIHexDigit(character);
+            *output++ = lowerNibbleToLowercaseASCIIHexDigit(character);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    *output = '&quot;';
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void StringBuilder::appendQuotedJSONString(const String&amp; string)
</del><ins>+void StringBuilder::appendQuotedJSONString(StringView string)
</ins><span class="cx"> {
</span><del>-    // Make sure we have enough buffer space to append this string without having
-    // to worry about reallocating in the middle.
-    // The 2 is for the '&quot;' quotes on each end.
-    // The 6 is for characters that need to be \uNNNN encoded.
-    Checked&lt;unsigned&gt; stringLength = string.length();
-    Checked&lt;unsigned&gt; maximumCapacityRequired = length();
-    maximumCapacityRequired += 2 + stringLength * 6;
-    unsigned allocationSize = maximumCapacityRequired.unsafeGet();
-    // This max() is here to allow us to allocate sizes between the range [2^31, 2^32 - 2] because roundUpToPowerOfTwo(1&lt;&lt;31 + some int smaller than 1&lt;&lt;31) == 0.
-    allocationSize = std::max(allocationSize, roundUpToPowerOfTwo(allocationSize));
-
-    if (is8Bit() &amp;&amp; !string.is8Bit())
-        allocateBufferUpConvert(m_bufferCharacters8, allocationSize);
-    else
-        reserveCapacity(allocationSize);
-    ASSERT(m_buffer-&gt;length() &gt;= allocationSize);
-
-    if (is8Bit()) {
-        ASSERT(string.is8Bit());
-        LChar* output = m_bufferCharacters8 + m_length;
-        *output++ = '&quot;';
-        appendQuotedJSONStringInternal(output, string.characters8(), string.length());
-        *output++ = '&quot;';
-        m_length = output - m_bufferCharacters8;
</del><ins>+    unsigned length = string.length();
+    if (string.is8Bit()) {
+        auto* characters = string.characters8();
+        if (m_is8Bit)
+            appendQuotedJSONStringInternal(appendUninitialized&lt;LChar&gt;(quotedJSONStringLength(characters, length)), characters, length);
+        else
+            appendQuotedJSONStringInternal(appendUninitialized&lt;UChar&gt;(quotedJSONStringLength(characters, length)), characters, length);
</ins><span class="cx">     } else {
</span><del>-        UChar* output = m_bufferCharacters16 + m_length;
-        *output++ = '&quot;';
-        if (string.is8Bit())
-            appendQuotedJSONStringInternal(output, string.characters8(), string.length());
</del><ins>+        auto* characters = string.characters16();
+        if (m_is8Bit)
+            appendQuotedJSONStringInternal(appendUninitializedUpconvert(quotedJSONStringLength(characters, length)), characters, length);
</ins><span class="cx">         else
</span><del>-            appendQuotedJSONStringInternal(output, string.characters16(), string.length());
-        *output++ = '&quot;';
-        m_length = output - m_bufferCharacters16;
</del><ins>+            appendQuotedJSONStringInternal(appendUninitialized&lt;UChar&gt;(quotedJSONStringLength(characters, length)), characters, length);
</ins><span class="cx">     }
</span><del>-    ASSERT(m_buffer-&gt;length() &gt;= m_length);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringBuilder.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringBuilder.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WTF/wtf/text/StringBuilder.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009-2010, 2012-2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -24,26 +24,18 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef StringBuilder_h
-#define StringBuilder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><del>-#include &lt;wtf/text/AtomicString.h&gt;
</del><span class="cx"> #include &lt;wtf/text/StringView.h&gt;
</span><del>-#include &lt;wtf/text/WTFString.h&gt;
</del><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><span class="cx"> class StringBuilder {
</span><del>-    // Disallow copying since it's expensive and we don't want code to do it by accident.
</del><ins>+    // Disallow copying since it's expensive and we don't want anyone to do it by accident.
</ins><span class="cx">     WTF_MAKE_NONCOPYABLE(StringBuilder);
</span><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    StringBuilder()
-        : m_length(0)
-        , m_is8Bit(true)
-        , m_bufferCharacters8(0)
-    {
-    }
</del><ins>+    StringBuilder() = default;
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_PRIVATE void append(const UChar*, unsigned);
</span><span class="cx">     WTF_EXPORT_PRIVATE void append(const LChar*, unsigned);
</span><span class="lines">@@ -50,29 +42,27 @@
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast&lt;const LChar*&gt;(characters), length); }
</span><span class="cx"> 
</span><del>-    void append(const AtomicString&amp; atomicString)
-    {
-        append(atomicString.string());
-    }
</del><ins>+    void append(const AtomicString&amp; atomicString) { append(atomicString.string()); }
</ins><span class="cx"> 
</span><span class="cx">     void append(const String&amp; string)
</span><span class="cx">     {
</span><del>-        if (!string.length())
</del><ins>+        unsigned length = string.length();
+        if (!length)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
-        // then just retain the string.
</del><ins>+        // If we're appending to an empty string, and there is not a buffer
+        // (reserveCapacity has not been called) then just retain the string.
</ins><span class="cx">         if (!m_length &amp;&amp; !m_buffer) {
</span><span class="cx">             m_string = string;
</span><del>-            m_length = string.length();
-            m_is8Bit = m_string.is8Bit();
</del><ins>+            m_length = length;
+            m_is8Bit = string.is8Bit();
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (string.is8Bit())
</span><del>-            append(string.characters8(), string.length());
</del><ins>+            append(string.characters8(), length);
</ins><span class="cx">         else
</span><del>-            append(string.characters16(), string.length());
</del><ins>+            append(string.characters16(), length);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void append(const StringBuilder&amp; other)
</span><span class="lines">@@ -80,11 +70,12 @@
</span><span class="cx">         if (!other.m_length)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called)
-        // then just retain the string.
</del><ins>+        // If we're appending to an empty string, and there is not a buffer
+        // (reserveCapacity has not been called) then just retain the string.
</ins><span class="cx">         if (!m_length &amp;&amp; !m_buffer &amp;&amp; !other.m_string.isNull()) {
</span><span class="cx">             m_string = other.m_string;
</span><span class="cx">             m_length = other.m_length;
</span><ins>+            m_is8Bit = other.m_is8Bit;
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -105,6 +96,7 @@
</span><span class="cx"> #if USE(CF)
</span><span class="cx">     WTF_EXPORT_PRIVATE void append(CFStringRef);
</span><span class="cx"> #endif
</span><ins>+
</ins><span class="cx"> #if USE(CF) &amp;&amp; defined(__OBJC__)
</span><span class="cx">     void append(NSString *string) { append((__bridge CFStringRef)string); }
</span><span class="cx"> #endif
</span><span class="lines">@@ -111,11 +103,20 @@
</span><span class="cx">     
</span><span class="cx">     void append(const String&amp; string, unsigned offset, unsigned length)
</span><span class="cx">     {
</span><del>-        if (!string.length())
</del><ins>+        ASSERT(offset &lt;= string.length());
+        ASSERT(offset + length &lt;= string.length());
+
+        if (!length)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        if ((offset + length) &gt; string.length())
</del><ins>+        // If we're appending to an empty string, and there is not a buffer
+        // (reserveCapacity has not been called) then just retain the string.
+        if (!offset &amp;&amp; !m_length &amp;&amp; !m_buffer &amp;&amp; length == string.length()) {
+            m_string = string;
+            m_length = length;
+            m_is8Bit = string.is8Bit();
</ins><span class="cx">             return;
</span><ins>+        }
</ins><span class="cx"> 
</span><span class="cx">         if (string.is8Bit())
</span><span class="cx">             append(string.characters8() + offset, length);
</span><span class="lines">@@ -129,37 +130,33 @@
</span><span class="cx">             append(characters, strlen(characters));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void append(UChar c)
</del><ins>+    void append(UChar character)
</ins><span class="cx">     {
</span><span class="cx">         if (m_buffer &amp;&amp; m_length &lt; m_buffer-&gt;length() &amp;&amp; m_string.isNull()) {
</span><span class="cx">             if (!m_is8Bit) {
</span><del>-                m_bufferCharacters16[m_length++] = c;
</del><ins>+                m_bufferCharacters16[m_length++] = character;
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-
-            if (!(c &amp; ~0xff)) {
-                m_bufferCharacters8[m_length++] = static_cast&lt;LChar&gt;(c);
</del><ins>+            if (!(character &amp; ~0xFF)) {
+                m_bufferCharacters8[m_length++] = static_cast&lt;LChar&gt;(character);
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        append(&amp;c, 1);
</del><ins>+        append(&amp;character, 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void append(LChar c)
</del><ins>+    void append(LChar character)
</ins><span class="cx">     {
</span><span class="cx">         if (m_buffer &amp;&amp; m_length &lt; m_buffer-&gt;length() &amp;&amp; m_string.isNull()) {
</span><span class="cx">             if (m_is8Bit)
</span><del>-                m_bufferCharacters8[m_length++] = c;
</del><ins>+                m_bufferCharacters8[m_length++] = character;
</ins><span class="cx">             else
</span><del>-                m_bufferCharacters16[m_length++] = c;
</del><ins>+                m_bufferCharacters16[m_length++] = character;
</ins><span class="cx">         } else
</span><del>-            append(&amp;c, 1);
</del><ins>+            append(&amp;character, 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void append(char c)
-    {
-        append(static_cast&lt;LChar&gt;(c));
-    }
</del><ins>+    void append(char character) { append(static_cast&lt;LChar&gt;(character)); }
</ins><span class="cx"> 
</span><span class="cx">     void append(UChar32 c)
</span><span class="cx">     {
</span><span class="lines">@@ -171,10 +168,9 @@
</span><span class="cx">         append(U16_TRAIL(c));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    WTF_EXPORT_PRIVATE void appendQuotedJSONString(const String&amp;);
</del><ins>+    WTF_EXPORT_PRIVATE void appendQuotedJSONString(StringView);
</ins><span class="cx"> 
</span><del>-    template&lt;unsigned charactersCount&gt;
-    ALWAYS_INLINE void appendLiteral(const char (&amp;characters)[charactersCount]) { append(characters, charactersCount - 1); }
</del><ins>+    template&lt;unsigned charactersCount&gt; ALWAYS_INLINE void appendLiteral(const char (&amp;characters)[charactersCount]) { append(characters, charactersCount - 1); }
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_PRIVATE void appendNumber(int);
</span><span class="cx">     WTF_EXPORT_PRIVATE void appendNumber(unsigned int);
</span><span class="lines">@@ -220,24 +216,15 @@
</span><span class="cx">         return AtomicString(m_buffer.get(), 0, m_length);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned length() const
-    {
-        return m_length;
-    }
-
</del><ins>+    unsigned length() const { return m_length; }
</ins><span class="cx">     bool isEmpty() const { return !m_length; }
</span><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity);
</span><span class="cx"> 
</span><del>-    unsigned capacity() const
-    {
-        return m_buffer ? m_buffer-&gt;length() : m_length;
-    }
</del><ins>+    unsigned capacity() const { return m_buffer ? m_buffer-&gt;length() : m_length; }
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_PRIVATE void resize(unsigned newSize);
</span><del>-
</del><span class="cx">     WTF_EXPORT_PRIVATE bool canShrink() const;
</span><del>-
</del><span class="cx">     WTF_EXPORT_PRIVATE void shrinkToFit();
</span><span class="cx"> 
</span><span class="cx">     UChar operator[](unsigned i) const
</span><span class="lines">@@ -294,43 +281,35 @@
</span><span class="cx"> private:
</span><span class="cx">     void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength);
</span><span class="cx">     void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
</span><del>-    void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength);
-    template &lt;typename CharType&gt;
-    void reallocateBuffer(unsigned requiredLength);
-    template &lt;typename CharType&gt;
-    ALWAYS_INLINE CharType* appendUninitialized(unsigned length);
-    template &lt;typename CharType&gt;
-    CharType* appendUninitializedSlow(unsigned length);
-    template &lt;typename CharType&gt;
-    ALWAYS_INLINE CharType * getBufferCharacters();
</del><ins>+    void allocateBufferUpconvert(const LChar* currentCharacters, unsigned requiredLength);
+    template&lt;typename CharacterType&gt; void reallocateBuffer(unsigned requiredLength);
+    UChar* appendUninitializedUpconvert(unsigned length);
+    template&lt;typename CharacterType&gt; CharacterType* appendUninitialized(unsigned length);
+    template&lt;typename CharacterType&gt; CharacterType* appendUninitializedSlow(unsigned length);
+    template&lt;typename CharacterType&gt; CharacterType* bufferCharacters();
</ins><span class="cx">     WTF_EXPORT_PRIVATE void reifyString() const;
</span><span class="cx"> 
</span><del>-    unsigned m_length;
</del><ins>+    unsigned m_length { 0 };
</ins><span class="cx">     mutable String m_string;
</span><span class="cx">     RefPtr&lt;StringImpl&gt; m_buffer;
</span><del>-    bool m_is8Bit;
</del><ins>+    bool m_is8Bit { true };
</ins><span class="cx">     union {
</span><del>-        LChar* m_bufferCharacters8;
</del><ins>+        LChar* m_bufferCharacters8 { nullptr };
</ins><span class="cx">         UChar* m_bufferCharacters16;
</span><span class="cx">     };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-template &lt;&gt;
-ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters&lt;LChar&gt;()
-{
-    ASSERT(m_is8Bit);
-    return m_bufferCharacters8;
-}
</del><ins>+template&lt;typename StringType&gt; bool equal(const StringBuilder&amp;, const StringType&amp;);
+template&lt;typename CharacterType&gt; bool equal(const StringBuilder&amp;, const CharacterType*, unsigned length);
</ins><span class="cx"> 
</span><del>-template &lt;&gt;
-ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters&lt;UChar&gt;()
-{
-    ASSERT(!m_is8Bit);
-    return m_bufferCharacters16;
-}    
</del><ins>+bool operator==(const StringBuilder&amp;, const StringBuilder&amp;);
+bool operator!=(const StringBuilder&amp;, const StringBuilder&amp;);
+bool operator==(const StringBuilder&amp;, const String&amp;);
+bool operator!=(const StringBuilder&amp;, const String&amp;);
+bool operator==(const String&amp;, const StringBuilder&amp;);
+bool operator!=(const String&amp;, const StringBuilder&amp;);
</ins><span class="cx"> 
</span><del>-template &lt;typename CharType&gt;
-bool equal(const StringBuilder&amp; s, const CharType* buffer, unsigned length)
</del><ins>+template&lt;typename CharacterType&gt; inline bool equal(const StringBuilder&amp; s, const CharacterType* buffer, unsigned length)
</ins><span class="cx"> {
</span><span class="cx">     if (s.length() != length)
</span><span class="cx">         return false;
</span><span class="lines">@@ -341,24 +320,9 @@
</span><span class="cx">     return equal(s.characters16(), buffer, length);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template &lt;typename StringType&gt;
-bool equal(const StringBuilder&amp; a, const StringType&amp; b)
</del><ins>+template&lt;typename StringType&gt; inline bool equal(const StringBuilder&amp; a, const StringType&amp; b)
</ins><span class="cx"> {
</span><del>-    if (a.length() != b.length())
-        return false;
-
-    if (!a.length())
-        return true;
-
-    if (a.is8Bit()) {
-        if (b.is8Bit())
-            return equal(a.characters8(), b.characters8(), a.length());
-        return equal(a.characters8(), b.characters16(), a.length());
-    }
-
-    if (b.is8Bit())
-        return equal(a.characters16(), b.characters8(), a.length());
-    return equal(a.characters16(), b.characters16(), a.length());
</del><ins>+    return equalCommon(a, b);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool operator==(const StringBuilder&amp; a, const StringBuilder&amp; b) { return equal(a, b); }
</span><span class="lines">@@ -371,5 +335,3 @@
</span><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::StringBuilder;
</span><del>-
-#endif // StringBuilder_h
</del></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/ChangeLog        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,3 +1,281 @@
</span><ins>+2016-11-28  Darin Adler  &lt;darin@apple.com&gt;
+
+        Streamline and speed up tokenizer and segmented string classes
+        https://bugs.webkit.org/show_bug.cgi?id=165003
+
+        Reviewed by Sam Weinig.
+
+        Profiling Speedometer on my iMac showed the tokenizer as one of the
+        hottest functions. This patch streamlines the segmented string class,
+        removing various unused features, and also improves some other functions
+        seen on the Speedometer profile. On my iMac I measured a speedup of
+        about 3%. Changes include:
+
+        - Removed m_pushedChar1, m_pushedChar2, and m_empty data members from the
+          SegmentedString class and all the code that used to handle them.
+
+        - Simplified the SegmentedString advance functions so they are small
+          enough to get inlined in the HTML tokenizer.
+
+        - Updated callers to call the simpler SegmentedString advance functions
+          that don't handle newlines in as many cases as possible.
+
+        - Cut down on allocations of SegmentedString and made code move the
+          segmented string and the strings that are moved into it rather than
+          copying them whenever possible.
+
+        - Simplified segmented string functions, removing some branches, mostly
+          from the non-fast paths.
+
+        - Removed small unused functions and small functions used in only one
+          or two places, made more functions private and renamed for clarity.
+
+        * bindings/js/JSHTMLDocumentCustom.cpp:
+        (WebCore::documentWrite): Moved a little more of the common code in here
+        from the two functions belwo. Removed obsolete comment saying this was not
+        following the DOM specification because it is. Removed unneeded special
+        cases for 1 argument and no arguments. Take a reference instead of a pointer.
+        (WebCore::JSHTMLDocument::write): Updated for above.
+        (WebCore::JSHTMLDocument::writeln): Ditto.
+
+        * css/parser/CSSTokenizer.cpp: Added now-needed include.
+        * css/parser/CSSTokenizer.h: Removed unneeded include.
+
+        * css/parser/CSSTokenizerInputStream.h: Added definition of kEndOfFileMarker
+        here; this is now separate from the use in the HTMLParser. In the long run,
+        unclear to me whether it is really needed in either.
+
+        * dom/Document.cpp:
+        (WebCore::Document::prepareToWrite): Added. Helper function used by the three
+        different variants of write. Using this may prevent us from having to construct
+        a SegmentedString just to append one string after future refactoring.
+        (WebCore::Document::write): Updated to take an rvalue reference and move the
+        value through.
+        (WebCore::Document::writeln): Use a single write call instead of two.
+
+        * dom/Document.h: Changed write to take an rvalue reference to SegmentedString
+        rather than a const reference.
+
+        * dom/DocumentParser.h: Changed insert to take an rvalue reference to
+        SegmentedString. In the future, should probably overload to take a single
+        string since that is the normal case.
+
+        * dom/RawDataDocumentParser.h: Updated for change to DocumentParser.
+
+        * html/FTPDirectoryDocument.cpp:
+        (WebCore::FTPDirectoryDocumentParser::append): Refactored a bit, just enough
+        so that we don't need an assignment operator for SegmentedString that can
+        copy a String.
+
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::insert): Updated to take an rvalue reference,
+        and move the value through.
+        * html/parser/HTMLDocumentParser.h: Updated for the above.
+
+        * html/parser/HTMLEntityParser.cpp:
+        (WebCore::HTMLEntityParser::consumeNamedEntity): Updated for name changes.
+        Changed the twao calls to advance here to call advancePastNonNewline; no
+        change in behavior, but asserts what the code was assuming before, that the
+        character was not a newline.
+
+        * html/parser/HTMLInputStream.h:
+        (WebCore::HTMLInputStream::appendToEnd): Updated to take an rvalue reference,
+        and move the value through.
+        (WebCore::HTMLInputStream::insertAtCurrentInsertionPoint): Ditto.
+        (WebCore::HTMLInputStream::markEndOfFile): Removed the code to construct a
+        SegmentedString, overkill since we can just append an individual string.
+        (WebCore::HTMLInputStream::splitInto): Rewrote the move idiom here to actually
+        use move, which will reduce reference count churn and other unneeded work.
+
+        * html/parser/HTMLMetaCharsetParser.cpp:
+        (WebCore::HTMLMetaCharsetParser::checkForMetaCharset): Removed unneeded
+        construction of a SegmentedString, just to append a string.
+
+        * html/parser/HTMLSourceTracker.cpp:
+        (WebCore::HTMLSourceTracker::HTMLSourceTracker): Moved to the class definition.
+        (WebCore::HTMLSourceTracker::source): Updated for function name change.
+        * html/parser/HTMLSourceTracker.h: Updated for above.
+
+        * html/parser/HTMLTokenizer.cpp: Added now-needed include.
+        (WebCore::HTMLTokenizer::emitAndResumeInDataState): Use advancePastNonNewline,
+        since this function is never called in response to a newline character.
+        (WebCore::HTMLTokenizer::commitToPartialEndTag): Ditto.
+        (WebCore::HTMLTokenizer::commitToCompleteEndTag): Ditto.
+        (WebCore::HTMLTokenizer::processToken): Use ADVANCE_PAST_NON_NEWLINE_TO macro
+        instead of ADVANCE_TO in cases where the character we are advancing past is
+        known not to be a newline, so we can use the more efficient advance function
+        that doesn't check for the newline character.
+
+        * html/parser/InputStreamPreprocessor.h: Moved kEndOfFileMarker to
+        SegmentedString.h; not sure that's a good place for it either. In the long run,
+        unclear to me whether this is really needed.
+        (WebCore::InputStreamPreprocessor::peek): Added UNLIKELY for the empty check.
+        Added LIKELY for the not-special character check.
+        (WebCore::InputStreamPreprocessor::advance): Updated for the new name of the
+        advanceAndUpdateLineNumber function.
+        (WebCore::InputStreamPreprocessor::advancePastNonNewline): Added. More
+        efficient than advance for cases where the last characer is known not to be
+        a newline character.
+        (WebCore::InputStreamPreprocessor::skipNextNewLine): Deleted. Was unused.
+        (WebCore::InputStreamPreprocessor::reset): Deleted. Was unused except in the
+        constructor; added initial values for the data members to replace.
+        (WebCore::InputStreamPreprocessor::processNextInputCharacter): Removed long
+        FIXME comment that didn't really need to be here. Reorganized a bit.
+        (WebCore::InputStreamPreprocessor::isAtEndOfFile): Renamed and made static.
+
+        * html/track/BufferedLineReader.cpp:
+        (WebCore::BufferedLineReader::nextLine): Updated to not use the poorly named
+        scanCharacter function to advance past a newline. Also renamed from getLine
+        and changed to return Optional&lt;String&gt; instead of using a boolean to indicate
+        failure and an out argument.
+
+        * html/track/BufferedLineReader.h:
+        (WebCore::BufferedLineReader::BufferedLineReader): Use the default, putting
+        initial values on each data member below.
+        (WebCore::BufferedLineReader::append): Updated to take an rvalue reference,
+        and move the value through.
+        (WebCore::BufferedLineReader::scanCharacter): Deleted. Was poorly named,
+        and easy to replace with two lines of code at its two call sites.
+        (WebCore::BufferedLineReader::reset): Rewrote to correctly clear all the
+        data members of the class, not just the segmented string.
+
+        * html/track/InbandGenericTextTrack.cpp:
+        (WebCore::InbandGenericTextTrack::parseWebVTTFileHeader): Updated to take
+        an rvalue reference and move the value through.
+        * html/track/InbandGenericTextTrack.h: Updated for the above.
+
+        * html/track/InbandTextTrack.h: Updated since parseWebVTTFileHeader now
+        takes an rvalue reference.
+
+        * html/track/WebVTTParser.cpp:
+        (WebCore::WebVTTParser::parseFileHeader): Updated to take an rvalue reference
+        and move the value through.
+        (WebCore::WebVTTParser::parseBytes): Updated to pass ownership of the string
+        in to the line reader append function.
+        (WebCore::WebVTTParser::parseCueData): Use auto and WTFMove for WebVTTCueData.
+        (WebCore::WebVTTParser::flush): More of the same.
+        (WebCore::WebVTTParser::parse): Changed to use nextLine instead of getLine.
+        * html/track/WebVTTParser.h: Updated for the above.
+
+        * html/track/WebVTTTokenizer.cpp:
+        (WebCore::advanceAndEmitToken): Use advanceAndUpdateLineNumber by its new
+        name, just advance. No change in behavior.
+        (WebCore::WebVTTTokenizer::WebVTTTokenizer): Pass a String, not a
+        SegmentedString, to add the end of file marker.
+
+        * platform/graphics/InbandTextTrackPrivateClient.h: Updated since
+        parseWebVTTFileHeader takes an rvalue reference.
+
+        * platform/text/SegmentedString.cpp:
+        (WebCore::SegmentedString::Substring::appendTo): Moved here from the header.
+        The only caller is SegmentedString::toString, inside this file.
+        (WebCore::SegmentedString::SegmentedString): Deleted the copy constructor.
+        No longer needed.
+        (WebCore::SegmentedString::operator=): Defined a move assignment operator
+        rather than an ordinary assignment operator, since that's what the call
+        sites really need.
+        (WebCore::SegmentedString::length): Simplified since we no longer need to
+        support pushed characters.
+        (WebCore::SegmentedString::setExcludeLineNumbers): Simplified, since we
+        can just iterate m_otherSubstrings without an extra check. Also changed to
+        write directly to the data member of Substring instead of using a function.
+        (WebCore::SegmentedString::updateAdvanceFunctionPointersForEmptyString):
+        Added. Used when we run out of characters.
+        (WebCore::SegmentedString::clear): Removed code to clear now-deleted members.
+        Updated for changes to other member names.
+        (WebCore::SegmentedString::appendSubstring): Renamed from just append to
+        avoid ambiguity with the public append function. Changed to take an rvalue
+        reference, and move in, and added code to set m_currentCharacter properly,
+        so the caller doesn't have to deal with that.
+        (WebCore::SegmentedString::close): Updated to use m_isClosed by its new name.
+        Also removed unneeded comment about assertion that fires when trying to close
+        an already closed string.
+        (WebCore::SegmentedString::append): Added overloads for rvalue references of
+        both entire SegmentedString objects and of String. Streamlined to just call
+        appendSubstring and append to the deque.
+        (WebCore::SegmentedString::pushBack): Tightened up since we don't allow empty
+        strings and changed to take just a string, not an entire segmented string.
+        (WebCore::SegmentedString::advanceSubstring): Moved logic into the
+        advancePastSingleCharacterSubstringWithoutUpdatingLineNumber function.
+        (WebCore::SegmentedString::toString): Simplified now that we don't need to
+        support pushed characters.
+        (WebCore::SegmentedString::advancePastNonNewlines): Deleted.
+        (WebCore::SegmentedString::advance8): Deleted.
+        (WebCore::SegmentedString::advanceWithoutUpdatingLineNumber16): Renamed from
+        advance16. Simplified now that there are no pushed characters. Also changed to
+        access data members of m_currentSubstring directly instead of calling a function.
+        (WebCore::SegmentedString::advanceAndUpdateLineNumber8): Deleted.
+        (WebCore::SegmentedString::advanceAndUpdateLineNumber16): Ditto.
+        (WebCore::SegmentedString::advancePastSingleCharacterSubstringWithoutUpdatingLineNumber):
+        Renamed from advanceSlowCase. Removed uneeded logic to handle pushed characters.
+        Moved code in here from advanceSubstring.
+        (WebCore::SegmentedString::advancePastSingleCharacterSubstring): Renamed from
+        advanceAndUpdateLineNumberSlowCase. Simplified by calling the function above.
+        (WebCore::SegmentedString::advanceEmpty): Broke assertion up into two.
+        (WebCore::SegmentedString::updateSlowCaseFunctionPointers): Updated for name changes.
+        (WebCore::SegmentedString::advancePastSlowCase): Changed name and meaning of
+        boolean argument. Rewrote to use the String class less; it's now used only when
+        we fail to match after the first character rather than being used for the actual
+        comparison with the literal.
+
+        * platform/text/SegmentedString.h: Moved all non-trivial function bodies out of
+        the class definition to make things easier to read. Moved the SegmentedSubstring
+        class inside the SegmentedString class, making it a private struct named Substring.
+        Removed the m_ prefix from data members of the struct, removed many functions from
+        the struct and made its union be anonymous instead of naming it m_data. Removed
+        unneeded StringBuilder.h include.
+        (WebCore::SegmentedString::isEmpty): Changed to use the length of the substring
+        instead of a separate boolean. We never create an empty substring, nor leave one
+        in place as the current substring unless the entire segmented string is empty.
+        (WebCore::SegmentedString::advancePast): Updated to use the new member function
+        template instead of a non-template member function. The new member function is
+        entirely rewritten and does the matching directly rather than allocating a string
+        just to do prefix matching.
+        (WebCore::SegmentedString::advancePastLettersIgnoringASCIICase): Renamed to make
+        it clear that the literal must be all non-letters or lowercase letters as with
+        the other &quot;letters ignoring ASCII case&quot; functions. The three call sites all fit
+        the bill. Implement by calling the new function template.
+        (WebCore::SegmentedString::currentCharacter): Renamed from currentChar.
+        (WebCore::SegmentedString::Substring::Substring): Use an rvalue reference and
+        move the string in.
+        (WebCore::SegmentedString::Substring::currentCharacter): Simplified since this
+        is never used on an empty substring.
+        (WebCore::SegmentedString::Substring::incrementAndGetCurrentCharacter): Ditto.
+        (WebCore::SegmentedString::SegmentedString): Overload to take an rvalue reference.
+        Simplified since there are now fewer data members.
+        (WebCore::SegmentedString::advanceWithoutUpdatingLineNumber): Renamed from
+        advance, since this is only safe to use if there is some reason it is OK to skip
+        updating the line number.
+        (WebCore::SegmentedString::advance): Renamed from advanceAndUpdateLineNumber,
+        since doing that is the normal desired behavior and not worth mentioning in the
+        public function name.
+        (WebCore::SegmentedString::advancePastNewline): Renamed from
+        advancePastNewlineAndUpdateLineNumber.
+        (WebCore::SegmentedString::numberOfCharactersConsumed): Greatly simplified since
+        pushed characters are no longer supported.
+        (WebCore::SegmentedString::characterMismatch): Added. Used by advancePast.
+
+        * xml/parser/CharacterReferenceParserInlines.h:
+        (WebCore::unconsumeCharacters): Use toString rather than toStringPreserveCapacity
+        because the SegmentedString is going to take ownership of the string.
+        (WebCore::consumeCharacterReference): Updated to use the pushBack that takes just
+        a String, not a SegmentedString. Also use advancePastNonNewline.
+
+        * xml/parser/MarkupTokenizerInlines.h: Added ADVANCE_PAST_NON_NEWLINE_TO.
+
+        * xml/parser/XMLDocumentParser.cpp:
+        (WebCore::XMLDocumentParser::insert): Updated since this takes an rvalue reference.
+        (WebCore::XMLDocumentParser::append): Removed unnecessary code to create a
+        SegmentedString.
+        * xml/parser/XMLDocumentParser.h: Updated for above. Also fixed indentation
+        and initialized most data members.
+        * xml/parser/XMLDocumentParserLibxml2.cpp:
+        (WebCore::XMLDocumentParser::XMLDocumentParser): Moved most data member
+        initialization into the class definition.
+        (WebCore::XMLDocumentParser::resumeParsing): Removed code that copied a
+        segmented string, but converted the whole thing into a string before using it.
+        Now we convert to a string right away.
+
</ins><span class="cx"> 2016-11-28  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS] Use UIKit SPI to force popover presentation style on iPhone for html validation popovers
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSHTMLDocumentCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2007-2009, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2007-2016 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">@@ -26,24 +26,10 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JSHTMLDocument.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;Frame.h&quot;
-#include &quot;HTMLCollection.h&quot;
-#include &quot;HTMLDocument.h&quot;
-#include &quot;HTMLElement.h&quot;
</del><span class="cx"> #include &quot;HTMLIFrameElement.h&quot;
</span><del>-#include &quot;HTMLNames.h&quot;
-#include &quot;JSDOMWindow.h&quot;
</del><span class="cx"> #include &quot;JSDOMWindowCustom.h&quot;
</span><del>-#include &quot;JSDOMWindowShell.h&quot;
-#include &quot;JSDocumentCustom.h&quot;
</del><span class="cx"> #include &quot;JSHTMLCollection.h&quot;
</span><del>-#include &quot;JSMainThreadExecState.h&quot;
</del><span class="cx"> #include &quot;SegmentedString.h&quot;
</span><del>-#include &quot;DocumentParser.h&quot;
-#include &lt;interpreter/StackVisitor.h&gt;
-#include &lt;runtime/Error.h&gt;
-#include &lt;runtime/JSCell.h&gt;
-#include &lt;wtf/unicode/CharacterNames.h&gt;
</del><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="cx"> 
</span><span class="lines">@@ -54,10 +40,8 @@
</span><span class="cx"> JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref&lt;HTMLDocument&gt;&amp;&amp; passedDocument)
</span><span class="cx"> {
</span><span class="cx">     auto&amp; document = passedDocument.get();
</span><del>-    JSObject* wrapper = createWrapper&lt;HTMLDocument&gt;(globalObject, WTFMove(passedDocument));
-
</del><ins>+    auto* wrapper = createWrapper&lt;HTMLDocument&gt;(globalObject, WTFMove(passedDocument));
</ins><span class="cx">     reportMemoryForDocumentIfFrameless(*state, document);
</span><del>-
</del><span class="cx">     return wrapper;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -68,52 +52,51 @@
</span><span class="cx">     return toJSNewlyCreated(state, globalObject, Ref&lt;HTMLDocument&gt;(document));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JSHTMLDocument::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
</del><ins>+bool JSHTMLDocument::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot&amp; slot)
</ins><span class="cx"> {
</span><del>-    JSHTMLDocument* thisObject = jsCast&lt;JSHTMLDocument*&gt;(object);
-    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</del><ins>+    auto&amp; thisObject = *jsCast&lt;JSHTMLDocument*&gt;(object);
+    ASSERT_GC_OBJECT_INHERITS((&amp;thisObject), info());
</ins><span class="cx"> 
</span><span class="cx">     if (propertyName == &quot;open&quot;) {
</span><del>-        if (Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
</del><ins>+        if (Base::getOwnPropertySlot(&amp;thisObject, state, propertyName, slot))
</ins><span class="cx">             return true;
</span><del>-
-        slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter&lt;jsHTMLDocumentPrototypeFunctionOpen, 2&gt;);
</del><ins>+        slot.setCustom(&amp;thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter&lt;jsHTMLDocumentPrototypeFunctionOpen, 2&gt;);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSValue value;
</span><del>-    if (thisObject-&gt;nameGetter(exec, propertyName, value)) {
-        slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, value);
</del><ins>+    if (thisObject.nameGetter(state, propertyName, value)) {
+        slot.setValue(&amp;thisObject, ReadOnly | DontDelete | DontEnum, value);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
</del><ins>+    return Base::getOwnPropertySlot(&amp;thisObject, state, propertyName, slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JSHTMLDocument::nameGetter(ExecState* exec, PropertyName propertyName, JSValue&amp; value)
</del><ins>+bool JSHTMLDocument::nameGetter(ExecState* state, PropertyName propertyName, JSValue&amp; value)
</ins><span class="cx"> {
</span><span class="cx">     auto&amp; document = wrapped();
</span><span class="cx"> 
</span><del>-    AtomicStringImpl* atomicPropertyName = propertyName.publicName();
</del><ins>+    auto* atomicPropertyName = propertyName.publicName();
</ins><span class="cx">     if (!atomicPropertyName || !document.hasDocumentNamedItem(*atomicPropertyName))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     if (UNLIKELY(document.documentNamedItemContainsMultipleElements(*atomicPropertyName))) {
</span><del>-        Ref&lt;HTMLCollection&gt; collection = document.documentNamedItems(atomicPropertyName);
</del><ins>+        auto collection = document.documentNamedItems(atomicPropertyName);
</ins><span class="cx">         ASSERT(collection-&gt;length() &gt; 1);
</span><del>-        value = toJS(exec, globalObject(), collection);
</del><ins>+        value = toJS(state, globalObject(), collection);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Element&amp; element = *document.documentNamedItem(*atomicPropertyName);
</del><ins>+    auto&amp; element = *document.documentNamedItem(*atomicPropertyName);
</ins><span class="cx">     if (UNLIKELY(is&lt;HTMLIFrameElement&gt;(element))) {
</span><del>-        if (Frame* frame = downcast&lt;HTMLIFrameElement&gt;(element).contentFrame()) {
-            value = toJS(exec, frame);
</del><ins>+        if (auto* frame = downcast&lt;HTMLIFrameElement&gt;(element).contentFrame()) {
+            value = toJS(state, frame);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    value = toJS(exec, globalObject(), element);
</del><ins>+    value = toJS(state, globalObject(), element);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -122,9 +105,8 @@
</span><span class="cx"> JSValue JSHTMLDocument::all(ExecState&amp; state) const
</span><span class="cx"> {
</span><span class="cx">     // If &quot;all&quot; has been overwritten, return the overwritten value
</span><del>-    JSValue v = getDirect(state.vm(), Identifier::fromString(&amp;state, &quot;all&quot;));
-    if (v)
-        return v;
</del><ins>+    if (auto overwrittenValue = getDirect(state.vm(), Identifier::fromString(&amp;state, &quot;all&quot;)))
+        return overwrittenValue;
</ins><span class="cx"> 
</span><span class="cx">     return toJS(&amp;state, globalObject(), wrapped().all());
</span><span class="cx"> }
</span><span class="lines">@@ -135,15 +117,14 @@
</span><span class="cx">     putDirect(state.vm(), Identifier::fromString(&amp;state, &quot;all&quot;), value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static Document* findCallingDocument(ExecState&amp; state)
</del><ins>+static inline Document* findCallingDocument(ExecState&amp; state)
</ins><span class="cx"> {
</span><span class="cx">     CallerFunctor functor;
</span><span class="cx">     state.iterate(functor);
</span><del>-    CallFrame* callerFrame = functor.callerFrame();
</del><ins>+    auto* callerFrame = functor.callerFrame();
</ins><span class="cx">     if (!callerFrame)
</span><span class="cx">         return nullptr;
</span><del>-
-    return asJSDOMWindow(functor.callerFrame()-&gt;lexicalGlobalObject())-&gt;wrapped().document();
</del><ins>+    return asJSDOMWindow(callerFrame-&gt;lexicalGlobalObject())-&gt;wrapped().document();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Custom functions
</span><span class="lines">@@ -155,12 +136,11 @@
</span><span class="cx"> 
</span><span class="cx">     // For compatibility with other browsers, pass open calls with more than 2 parameters to the window.
</span><span class="cx">     if (state.argumentCount() &gt; 2) {
</span><del>-        if (Frame* frame = wrapped().frame()) {
-            JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame, currentWorld(&amp;state));
-            if (wrapper) {
-                JSValue function = wrapper-&gt;get(&amp;state, Identifier::fromString(&amp;state, &quot;open&quot;));
</del><ins>+        if (auto* frame = wrapped().frame()) {
+            if (auto* wrapper = toJSDOMWindowShell(frame, currentWorld(&amp;state))) {
+                auto function = wrapper-&gt;get(&amp;state, Identifier::fromString(&amp;state, &quot;open&quot;));
</ins><span class="cx">                 CallData callData;
</span><del>-                CallType callType = ::getCallData(function, callData);
</del><ins>+                auto callType = ::getCallData(function, callData);
</ins><span class="cx">                 if (callType == CallType::None)
</span><span class="cx">                     return throwTypeError(&amp;state, scope);
</span><span class="cx">                 return JSC::call(&amp;state, function, callType, callData, wrapper, ArgList(&amp;state));
</span><span class="lines">@@ -169,53 +149,41 @@
</span><span class="cx">         return jsUndefined();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // document.open clobbers the security context of the document and
-    // aliases it with the active security context.
-    Document* activeDocument = asJSDOMWindow(state.lexicalGlobalObject())-&gt;wrapped().document();
-
-    // In the case of two parameters or fewer, do a normal document open.
-    wrapped().open(activeDocument);
</del><ins>+    // Calling document.open clobbers the security context of the document and aliases it with the active security context.
+    // FIXME: Is it correct that this does not use findCallingDocument as the write function below does?
+    wrapped().open(asJSDOMWindow(state.lexicalGlobalObject())-&gt;wrapped().document());
+    // FIXME: Why do we return the document instead of returning undefined?
</ins><span class="cx">     return this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> enum NewlineRequirement { DoNotAddNewline, DoAddNewline };
</span><span class="cx"> 
</span><del>-static inline void documentWrite(ExecState&amp; state, JSHTMLDocument* thisDocument, NewlineRequirement addNewline)
</del><ins>+static inline JSValue documentWrite(ExecState&amp; state, JSHTMLDocument&amp; document, NewlineRequirement addNewline)
</ins><span class="cx"> {
</span><del>-    HTMLDocument* document = &amp;thisDocument-&gt;wrapped();
-    // DOM only specifies single string argument, but browsers allow multiple or no arguments.
</del><ins>+    VM&amp; vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
</ins><span class="cx"> 
</span><del>-    size_t size = state.argumentCount();
-
-    String firstString = state.argument(0).toString(&amp;state)-&gt;value(&amp;state);
-    SegmentedString segmentedString = firstString;
-    if (size != 1) {
-        if (!size)
-            segmentedString.clear();
-        else {
-            for (size_t i = 1; i &lt; size; ++i) {
-                String subsequentString = state.uncheckedArgument(i).toString(&amp;state)-&gt;value(&amp;state);
-                segmentedString.append(SegmentedString(subsequentString));
-            }
-        }
</del><ins>+    SegmentedString segmentedString;
+    size_t argumentCount = state.argumentCount();
+    for (size_t i = 0; i &lt; argumentCount; ++i) {
+        segmentedString.append(state.uncheckedArgument(i).toWTFString(&amp;state));
+        RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">     }
</span><span class="cx">     if (addNewline)
</span><del>-        segmentedString.append(SegmentedString(String(&amp;newlineCharacter, 1)));
</del><ins>+        segmentedString.append(String { &quot;\n&quot; });
</ins><span class="cx"> 
</span><del>-    Document* activeDocument = findCallingDocument(state);
-    document-&gt;write(segmentedString, activeDocument);
</del><ins>+    document.wrapped().write(WTFMove(segmentedString), findCallingDocument(state));
+    return jsUndefined();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSValue JSHTMLDocument::write(ExecState&amp; state)
</span><span class="cx"> {
</span><del>-    documentWrite(state, this, DoNotAddNewline);
-    return jsUndefined();
</del><ins>+    return documentWrite(state, *this, DoNotAddNewline);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSValue JSHTMLDocument::writeln(ExecState&amp; state)
</span><span class="cx"> {
</span><del>-    documentWrite(state, this, DoAddNewline);
-    return jsUndefined();
</del><ins>+    return documentWrite(state, *this, DoAddNewline);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSTokenizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSTokenizer.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSTokenizer.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/css/parser/CSSTokenizer.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #include &quot;CSSParserTokenRange.h&quot;
</span><span class="cx"> #include &quot;CSSTokenizerInputStream.h&quot;
</span><span class="cx"> #include &quot;HTMLParserIdioms.h&quot;
</span><ins>+#include &lt;wtf/text/StringBuilder.h&gt;
</ins><span class="cx"> #include &lt;wtf/unicode/CharacterNames.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSTokenizerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSTokenizer.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSTokenizer.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/css/parser/CSSTokenizer.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -30,7 +30,6 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CSSParserToken.h&quot;
</span><del>-#include &quot;InputStreamPreprocessor.h&quot;
</del><span class="cx"> #include &lt;climits&gt;
</span><span class="cx"> #include &lt;wtf/text/StringView.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSTokenizerInputStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSTokenizerInputStream.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSTokenizerInputStream.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/css/parser/CSSTokenizerInputStream.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -30,10 +30,11 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/text/StringView.h&gt;
</span><del>-#include &lt;wtf/text/WTFString.h&gt;
</del><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+constexpr LChar kEndOfFileMarker = 0;
+
</ins><span class="cx"> class CSSTokenizerInputStream {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(CSSTokenizerInputStream);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -2791,7 +2791,7 @@
</span><span class="cx">     return MonotonicTime::now() - m_documentCreationTime;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Document::write(const SegmentedString&amp; text, Document* ownerDocument)
</del><ins>+void Document::write(SegmentedString&amp;&amp; text, Document* ownerDocument)
</ins><span class="cx"> {
</span><span class="cx">     NestingLevelIncrementer nestingLevelIncrementer(m_writeRecursionDepth);
</span><span class="cx"> 
</span><span class="lines">@@ -2799,7 +2799,7 @@
</span><span class="cx">     m_writeRecursionIsTooDeep = (m_writeRecursionDepth &gt; cMaxWriteRecursionDepth) || m_writeRecursionIsTooDeep;
</span><span class="cx"> 
</span><span class="cx">     if (m_writeRecursionIsTooDeep)
</span><del>-       return;
</del><ins>+        return;
</ins><span class="cx"> 
</span><span class="cx">     bool hasInsertionPoint = m_parser &amp;&amp; m_parser-&gt;hasInsertionPoint();
</span><span class="cx">     if (!hasInsertionPoint &amp;&amp; (m_ignoreOpensDuringUnloadCount || m_ignoreDestructiveWriteCount))
</span><span class="lines">@@ -2809,18 +2809,19 @@
</span><span class="cx">         open(ownerDocument);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_parser);
</span><del>-    m_parser-&gt;insert(text);
</del><ins>+    m_parser-&gt;insert(WTFMove(text));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Document::write(const String&amp; text, Document* ownerDocument)
</span><span class="cx"> {
</span><del>-    write(SegmentedString(text), ownerDocument);
</del><ins>+    write(SegmentedString { text }, ownerDocument);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Document::writeln(const String&amp; text, Document* ownerDocument)
</span><span class="cx"> {
</span><del>-    write(text, ownerDocument);
-    write(&quot;\n&quot;, ownerDocument);
</del><ins>+    SegmentedString textWithNewline { text };
+    textWithNewline.append(String { &quot;\n&quot; });
+    write(WTFMove(textWithNewline), ownerDocument);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::chrono::milliseconds Document::minimumTimerInterval() const
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/dom/Document.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -602,7 +602,7 @@
</span><span class="cx"> 
</span><span class="cx">     void cancelParsing();
</span><span class="cx"> 
</span><del>-    void write(const SegmentedString&amp; text, Document* ownerDocument = nullptr);
</del><ins>+    void write(SegmentedString&amp;&amp; text, Document* ownerDocument = nullptr);
</ins><span class="cx">     WEBCORE_EXPORT void write(const String&amp; text, Document* ownerDocument = nullptr);
</span><span class="cx">     WEBCORE_EXPORT void writeln(const String&amp; text, Document* ownerDocument = nullptr);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/DocumentParser.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/DocumentParser.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/dom/DocumentParser.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     virtual bool hasInsertionPoint() { return true; }
</span><span class="cx"> 
</span><span class="cx">     // insert is used by document.write.
</span><del>-    virtual void insert(const SegmentedString&amp;) = 0;
</del><ins>+    virtual void insert(SegmentedString&amp;&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     // appendBytes and flush are used by DocumentWriter (the loader).
</span><span class="cx">     virtual void appendBytes(DocumentWriter&amp;, const char* bytes, size_t length) = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoredomRawDataDocumentParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/RawDataDocumentParser.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/RawDataDocumentParser.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/dom/RawDataDocumentParser.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">         appendBytes(writer, 0, 0);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void insert(const SegmentedString&amp;) override
</del><ins>+    void insert(SegmentedString&amp;&amp;) override
</ins><span class="cx">     {
</span><span class="cx">         // &lt;https://bugs.webkit.org/show_bug.cgi?id=25397&gt;: JS code can always call document.write, we need to handle it.
</span><span class="cx">         ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlFTPDirectoryDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/FTPDirectoryDocument.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/FTPDirectoryDocument.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/FTPDirectoryDocument.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -344,8 +344,6 @@
</span><span class="cx"> 
</span><span class="cx"> void FTPDirectoryDocumentParser::append(RefPtr&lt;StringImpl&gt;&amp;&amp; inputSource)
</span><span class="cx"> {
</span><del>-    String source(WTFMove(inputSource));
-
</del><span class="cx">     // Make sure we have the table element to append to by loading the template set in the pref, or
</span><span class="cx">     // creating a very basic document with the appropriate table
</span><span class="cx">     if (!m_tableElement) {
</span><span class="lines">@@ -357,9 +355,9 @@
</span><span class="cx">     bool foundNewLine = false;
</span><span class="cx"> 
</span><span class="cx">     m_dest = m_buffer;
</span><del>-    SegmentedString str = source;
-    while (!str.isEmpty()) {
-        UChar c = str.currentChar();
</del><ins>+    SegmentedString string { String { WTFMove(inputSource) } };
+    while (!string.isEmpty()) {
+        UChar c = string.currentCharacter();
</ins><span class="cx"> 
</span><span class="cx">         if (c == '\r') {
</span><span class="cx">             *m_dest++ = '\n';
</span><span class="lines">@@ -376,7 +374,7 @@
</span><span class="cx">             m_skipLF = false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        str.advance();
</del><ins>+        string.advance();
</ins><span class="cx"> 
</span><span class="cx">         // Maybe enlarge the buffer
</span><span class="cx">         checkBuffer();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -328,7 +328,7 @@
</span><span class="cx">     return m_input.hasInsertionPoint() || (wasCreatedByScript() &amp;&amp; !m_input.haveSeenEndOfFile());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void HTMLDocumentParser::insert(const SegmentedString&amp; source)
</del><ins>+void HTMLDocumentParser::insert(SegmentedString&amp;&amp; source)
</ins><span class="cx"> {
</span><span class="cx">     if (isStopped())
</span><span class="cx">         return;
</span><span class="lines">@@ -337,9 +337,8 @@
</span><span class="cx">     // but we need to ensure it isn't deleted yet.
</span><span class="cx">     Ref&lt;HTMLDocumentParser&gt; protectedThis(*this);
</span><span class="cx"> 
</span><del>-    SegmentedString excludedLineNumberSource(source);
-    excludedLineNumberSource.setExcludeLineNumbers();
-    m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
</del><ins>+    source.setExcludeLineNumbers();
+    m_input.insertAtCurrentInsertionPoint(WTFMove(source));
</ins><span class="cx">     pumpTokenizerIfPossible(ForceSynchronous);
</span><span class="cx"> 
</span><span class="cx">     if (isWaitingForScripts()) {
</span><span class="lines">@@ -363,7 +362,7 @@
</span><span class="cx">     // but we need to ensure it isn't deleted yet.
</span><span class="cx">     Ref&lt;HTMLDocumentParser&gt; protectedThis(*this);
</span><span class="cx"> 
</span><del>-    String source(WTFMove(inputSource));
</del><ins>+    String source { WTFMove(inputSource) };
</ins><span class="cx"> 
</span><span class="cx">     if (m_preloadScanner) {
</span><span class="cx">         if (m_input.current().isEmpty() &amp;&amp; !isWaitingForScripts()) {
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx"> protected:
</span><span class="cx">     explicit HTMLDocumentParser(HTMLDocument&amp;);
</span><span class="cx"> 
</span><del>-    void insert(const SegmentedString&amp;) final;
</del><ins>+    void insert(SegmentedString&amp;&amp;) final;
</ins><span class="cx">     void append(RefPtr&lt;StringImpl&gt;&amp;&amp;) override;
</span><span class="cx">     void finish() override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLEntityParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLEntityParser.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLEntityParser.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLEntityParser.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -61,12 +61,12 @@
</span><span class="cx">         StringBuilder consumedCharacters;
</span><span class="cx">         HTMLEntitySearch entitySearch;
</span><span class="cx">         while (!source.isEmpty()) {
</span><del>-            cc = source.currentChar();
</del><ins>+            cc = source.currentCharacter();
</ins><span class="cx">             entitySearch.advance(cc);
</span><span class="cx">             if (!entitySearch.isEntityPrefix())
</span><span class="cx">                 break;
</span><span class="cx">             consumedCharacters.append(cc);
</span><del>-            source.advance();
</del><ins>+            source.advancePastNonNewline();
</ins><span class="cx">         }
</span><span class="cx">         notEnoughCharacters = source.isEmpty();
</span><span class="cx">         if (notEnoughCharacters) {
</span><span class="lines">@@ -88,13 +88,13 @@
</span><span class="cx">             const int length = entitySearch.mostRecentMatch()-&gt;length;
</span><span class="cx">             const LChar* reference = entitySearch.mostRecentMatch()-&gt;entity;
</span><span class="cx">             for (int i = 0; i &lt; length; ++i) {
</span><del>-                cc = source.currentChar();
</del><ins>+                cc = source.currentCharacter();
</ins><span class="cx">                 ASSERT_UNUSED(reference, cc == *reference++);
</span><span class="cx">                 consumedCharacters.append(cc);
</span><del>-                source.advance();
</del><ins>+                source.advancePastNonNewline();
</ins><span class="cx">                 ASSERT(!source.isEmpty());
</span><span class="cx">             }
</span><del>-            cc = source.currentChar();
</del><ins>+            cc = source.currentCharacter();
</ins><span class="cx">         }
</span><span class="cx">         if (entitySearch.mostRecentMatch()-&gt;lastCharacter() == ';'
</span><span class="cx">             || !additionalAllowedCharacter
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLInputStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLInputStream.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLInputStream.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLInputStream.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -25,7 +25,6 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;InputStreamPreprocessor.h&quot;
</del><span class="cx"> #include &quot;SegmentedString.h&quot;
</span><span class="cx"> #include &lt;wtf/text/TextPosition.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -56,14 +55,14 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void appendToEnd(const SegmentedString&amp; string)
</del><ins>+    void appendToEnd(SegmentedString&amp;&amp; string)
</ins><span class="cx">     {
</span><del>-        m_last-&gt;append(string);
</del><ins>+        m_last-&gt;append(WTFMove(string));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void insertAtCurrentInsertionPoint(const SegmentedString&amp; string)
</del><ins>+    void insertAtCurrentInsertionPoint(SegmentedString&amp;&amp; string)
</ins><span class="cx">     {
</span><del>-        m_first.append(string);
</del><ins>+        m_first.append(WTFMove(string));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool hasInsertionPoint() const
</span><span class="lines">@@ -73,7 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">     void markEndOfFile()
</span><span class="cx">     {
</span><del>-        m_last-&gt;append(SegmentedString(String(&amp;kEndOfFileMarker, 1)));
</del><ins>+        m_last-&gt;append(String { &amp;kEndOfFileMarker, 1 });
</ins><span class="cx">         m_last-&gt;close();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -92,8 +91,7 @@
</span><span class="cx"> 
</span><span class="cx">     void splitInto(SegmentedString&amp; next)
</span><span class="cx">     {
</span><del>-        next = m_first;
-        m_first = SegmentedString();
</del><ins>+        next = WTFMove(m_first);
</ins><span class="cx">         if (m_last == &amp;m_first) {
</span><span class="cx">             // We used to only have one SegmentedString in the InputStream
</span><span class="cx">             // but now we have two.  That means m_first is no longer also
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLMetaCharsetParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2010 Google Inc. All Rights Reserved.
</span><del>- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2015-2016 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">@@ -151,9 +151,9 @@
</span><span class="cx">     // that are disallowed in &lt;head&gt;, we don't bail out until we've checked at
</span><span class="cx">     // least bytesToCheckUnconditionally bytes of input.
</span><span class="cx"> 
</span><del>-    static const int bytesToCheckUnconditionally = 1024;
</del><ins>+    constexpr int bytesToCheckUnconditionally = 1024;
</ins><span class="cx"> 
</span><del>-    m_input.append(SegmentedString(m_codec-&gt;decode(data, length)));
</del><ins>+    m_input.append(m_codec-&gt;decode(data, length));
</ins><span class="cx"> 
</span><span class="cx">     while (auto token = m_tokenizer.nextToken(m_input)) {
</span><span class="cx">         bool isEnd = token-&gt;type() == HTMLToken::EndTag;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLSourceTrackercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLSourceTracker.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -32,10 +32,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-HTMLSourceTracker::HTMLSourceTracker()
-{
-}
-
</del><span class="cx"> void HTMLSourceTracker::startToken(SegmentedString&amp; currentInput, HTMLTokenizer&amp; tokenizer)
</span><span class="cx"> {
</span><span class="cx">     if (!m_started) {
</span><span class="lines">@@ -78,12 +74,12 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned i = 0;
</span><span class="cx">     for ( ; i &lt; length &amp;&amp; !m_previousSource.isEmpty(); ++i) {
</span><del>-        source.append(m_previousSource.currentChar());
</del><ins>+        source.append(m_previousSource.currentCharacter());
</ins><span class="cx">         m_previousSource.advance();
</span><span class="cx">     }
</span><span class="cx">     for ( ; i &lt; length; ++i) {
</span><span class="cx">         ASSERT(!m_currentSource.isEmpty());
</span><del>-        source.append(m_currentSource.currentChar());
</del><ins>+        source.append(m_currentSource.currentCharacter());
</ins><span class="cx">         m_currentSource.advance();
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLSourceTrackerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLSourceTracker.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLSourceTracker.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLSourceTracker.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> class HTMLSourceTracker {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(HTMLSourceTracker);
</span><span class="cx"> public:
</span><del>-    HTMLSourceTracker();
</del><ins>+    HTMLSourceTracker() = default;
</ins><span class="cx"> 
</span><span class="cx">     void startToken(SegmentedString&amp;, HTMLTokenizer&amp;);
</span><span class="cx">     void endToken(SegmentedString&amp;, HTMLTokenizer&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLTokenizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLTokenizer.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLTokenizer.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/HTMLTokenizer.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008-2016 Apple Inc. All Rights Reserved.
</ins><span class="cx">  * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
</span><span class="cx">  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
</span><span class="cx">  *
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> #include &quot;HTMLEntityParser.h&quot;
</span><span class="cx"> #include &quot;HTMLNames.h&quot;
</span><span class="cx"> #include &quot;MarkupTokenizerInlines.h&quot;
</span><del>-#include &lt;wtf/ASCIICType.h&gt;
</del><ins>+#include &lt;wtf/text/StringBuilder.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WTF;
</span><span class="cx"> 
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx"> {
</span><span class="cx">     saveEndTagNameIfNeeded();
</span><span class="cx">     m_state = DataState;
</span><del>-    source.advanceAndUpdateLineNumber();
</del><ins>+    source.advancePastNonNewline();
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -157,9 +157,9 @@
</span><span class="cx"> 
</span><span class="cx"> bool HTMLTokenizer::commitToPartialEndTag(SegmentedString&amp; source, UChar character, State state)
</span><span class="cx"> {
</span><del>-    ASSERT(source.currentChar() == character);
</del><ins>+    ASSERT(source.currentCharacter() == character);
</ins><span class="cx">     appendToTemporaryBuffer(character);
</span><del>-    source.advanceAndUpdateLineNumber();
</del><ins>+    source.advancePastNonNewline();
</ins><span class="cx"> 
</span><span class="cx">     if (haveBufferedCharacterToken()) {
</span><span class="cx">         // Emit the buffered character token.
</span><span class="lines">@@ -174,9 +174,9 @@
</span><span class="cx"> 
</span><span class="cx"> bool HTMLTokenizer::commitToCompleteEndTag(SegmentedString&amp; source)
</span><span class="cx"> {
</span><del>-    ASSERT(source.currentChar() == '&gt;');
</del><ins>+    ASSERT(source.currentCharacter() == '&gt;');
</ins><span class="cx">     appendToTemporaryBuffer('&gt;');
</span><del>-    source.advance();
</del><ins>+    source.advancePastNonNewline();
</ins><span class="cx"> 
</span><span class="cx">     m_state = DataState;
</span><span class="cx"> 
</span><span class="lines">@@ -212,11 +212,11 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DataState)
</span><span class="cx">         if (character == '&amp;')
</span><del>-            ADVANCE_TO(CharacterReferenceInDataState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CharacterReferenceInDataState);
</ins><span class="cx">         if (character == '&lt;') {
</span><span class="cx">             if (haveBufferedCharacterToken())
</span><span class="cx">                 RETURN_IN_CURRENT_STATE(true);
</span><del>-            ADVANCE_TO(TagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(TagOpenState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker)
</span><span class="cx">             return emitEndOfFile(source);
</span><span class="lines">@@ -232,9 +232,9 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(RCDATAState)
</span><span class="cx">         if (character == '&amp;')
</span><del>-            ADVANCE_TO(CharacterReferenceInRCDATAState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CharacterReferenceInRCDATAState);
</ins><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(RCDATALessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RCDATALessThanSignState);
</ins><span class="cx">         if (character == kEndOfFileMarker)
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="cx">         bufferCharacter(character);
</span><span class="lines">@@ -249,7 +249,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(RAWTEXTState)
</span><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(RAWTEXTLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RAWTEXTLessThanSignState);
</ins><span class="cx">         if (character == kEndOfFileMarker)
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="cx">         bufferCharacter(character);
</span><span class="lines">@@ -258,7 +258,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(ScriptDataState)
</span><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(ScriptDataLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataLessThanSignState);
</ins><span class="cx">         if (character == kEndOfFileMarker)
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="cx">         bufferCharacter(character);
</span><span class="lines">@@ -274,12 +274,12 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(TagOpenState)
</span><span class="cx">         if (character == '!')
</span><del>-            ADVANCE_TO(MarkupDeclarationOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(MarkupDeclarationOpenState);
</ins><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(EndTagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(EndTagOpenState);
</ins><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             m_token.beginStartTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(TagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(TagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '?') {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -297,11 +297,11 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             m_token.beginEndTag(convertASCIIAlphaToLower(character));
</span><span class="cx">             m_appropriateEndTagName.clear();
</span><del>-            ADVANCE_TO(TagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(TagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><del>-            ADVANCE_TO(DataState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DataState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -317,7 +317,7 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(BeforeAttributeNameState);
</span><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(SelfClosingStartTagState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(SelfClosingStartTagState);
</ins><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (m_options.usePreHTML5ParserQuirks &amp;&amp; character == '&lt;')
</span><span class="lines">@@ -327,7 +327,7 @@
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="cx">         }
</span><span class="cx">         m_token.appendToName(toASCIILower(character));
</span><del>-        ADVANCE_TO(TagNameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(TagNameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(RCDATALessThanSignState)
</span><span class="lines">@@ -334,7 +334,7 @@
</span><span class="cx">         if (character == '/') {
</span><span class="cx">             m_temporaryBuffer.clear();
</span><span class="cx">             ASSERT(m_bufferedEndTagName.isEmpty());
</span><del>-            ADVANCE_TO(RCDATAEndTagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RCDATAEndTagOpenState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         RECONSUME_IN(RCDATAState);
</span><span class="lines">@@ -344,7 +344,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(RCDATAEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RCDATAEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         bufferASCIICharacter('/');
</span><span class="lines">@@ -355,7 +355,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(RCDATAEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RCDATAEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (isTokenizerWhitespace(character)) {
</span><span class="cx">             if (isAppropriateEndTag()) {
</span><span class="lines">@@ -385,7 +385,7 @@
</span><span class="cx">         if (character == '/') {
</span><span class="cx">             m_temporaryBuffer.clear();
</span><span class="cx">             ASSERT(m_bufferedEndTagName.isEmpty());
</span><del>-            ADVANCE_TO(RAWTEXTEndTagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RAWTEXTEndTagOpenState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         RECONSUME_IN(RAWTEXTState);
</span><span class="lines">@@ -395,7 +395,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(RAWTEXTEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RAWTEXTEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         bufferASCIICharacter('/');
</span><span class="lines">@@ -406,7 +406,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(RAWTEXTEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(RAWTEXTEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (isTokenizerWhitespace(character)) {
</span><span class="cx">             if (isAppropriateEndTag()) {
</span><span class="lines">@@ -436,12 +436,12 @@
</span><span class="cx">         if (character == '/') {
</span><span class="cx">             m_temporaryBuffer.clear();
</span><span class="cx">             ASSERT(m_bufferedEndTagName.isEmpty());
</span><del>-            ADVANCE_TO(ScriptDataEndTagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEndTagOpenState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '!') {
</span><span class="cx">             bufferASCIICharacter('&lt;');
</span><span class="cx">             bufferASCIICharacter('!');
</span><del>-            ADVANCE_TO(ScriptDataEscapeStartState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapeStartState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         RECONSUME_IN(ScriptDataState);
</span><span class="lines">@@ -451,7 +451,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         bufferASCIICharacter('/');
</span><span class="lines">@@ -462,7 +462,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (isTokenizerWhitespace(character)) {
</span><span class="cx">             if (isAppropriateEndTag()) {
</span><span class="lines">@@ -491,7 +491,7 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataEscapeStartState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataEscapeStartDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapeStartDashState);
</ins><span class="cx">         } else
</span><span class="cx">             RECONSUME_IN(ScriptDataState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -499,7 +499,7 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataEscapeStartDashState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataEscapedDashDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedDashDashState);
</ins><span class="cx">         } else
</span><span class="cx">             RECONSUME_IN(ScriptDataState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -507,10 +507,10 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataEscapedState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataEscapedDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(ScriptDataEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedLessThanSignState);
</ins><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="lines">@@ -522,10 +522,10 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataEscapedDashState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataEscapedDashDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedDashDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(ScriptDataEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedLessThanSignState);
</ins><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="lines">@@ -537,13 +537,13 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataEscapedDashDashState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataEscapedDashDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedDashDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;')
</span><del>-            ADVANCE_TO(ScriptDataEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedLessThanSignState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             bufferASCIICharacter('&gt;');
</span><del>-            ADVANCE_TO(ScriptDataState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -557,7 +557,7 @@
</span><span class="cx">         if (character == '/') {
</span><span class="cx">             m_temporaryBuffer.clear();
</span><span class="cx">             ASSERT(m_bufferedEndTagName.isEmpty());
</span><del>-            ADVANCE_TO(ScriptDataEscapedEndTagOpenState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedEndTagOpenState);
</ins><span class="cx">         }
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             bufferASCIICharacter('&lt;');
</span><span class="lines">@@ -564,7 +564,7 @@
</span><span class="cx">             bufferASCIICharacter(character);
</span><span class="cx">             m_temporaryBuffer.clear();
</span><span class="cx">             appendToTemporaryBuffer(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapeStartState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapeStartState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         RECONSUME_IN(ScriptDataEscapedState);
</span><span class="lines">@@ -574,7 +574,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataEscapedEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         bufferASCIICharacter('&lt;');
</span><span class="cx">         bufferASCIICharacter('/');
</span><span class="lines">@@ -585,7 +585,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             appendToTemporaryBuffer(character);
</span><span class="cx">             appendToPossibleEndTag(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataEscapedEndTagNameState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataEscapedEndTagNameState);
</ins><span class="cx">         }
</span><span class="cx">         if (isTokenizerWhitespace(character)) {
</span><span class="cx">             if (isAppropriateEndTag()) {
</span><span class="lines">@@ -622,7 +622,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             bufferASCIICharacter(character);
</span><span class="cx">             appendToTemporaryBuffer(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapeStartState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapeStartState);
</ins><span class="cx">         }
</span><span class="cx">         RECONSUME_IN(ScriptDataEscapedState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -630,11 +630,11 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataDoubleEscapedState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;') {
</span><span class="cx">             bufferASCIICharacter('&lt;');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedLessThanSignState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -647,11 +647,11 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataDoubleEscapedDashState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedDashDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;') {
</span><span class="cx">             bufferASCIICharacter('&lt;');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedLessThanSignState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -664,15 +664,15 @@
</span><span class="cx">     BEGIN_STATE(ScriptDataDoubleEscapedDashDashState)
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             bufferASCIICharacter('-');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedDashDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedDashDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&lt;') {
</span><span class="cx">             bufferASCIICharacter('&lt;');
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapedLessThanSignState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapedLessThanSignState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             bufferASCIICharacter('&gt;');
</span><del>-            ADVANCE_TO(ScriptDataState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -686,7 +686,7 @@
</span><span class="cx">         if (character == '/') {
</span><span class="cx">             bufferASCIICharacter('/');
</span><span class="cx">             m_temporaryBuffer.clear();
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapeEndState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapeEndState);
</ins><span class="cx">         }
</span><span class="cx">         RECONSUME_IN(ScriptDataDoubleEscapedState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -702,7 +702,7 @@
</span><span class="cx">         if (isASCIIAlpha(character)) {
</span><span class="cx">             bufferASCIICharacter(character);
</span><span class="cx">             appendToTemporaryBuffer(convertASCIIAlphaToLower(character));
</span><del>-            ADVANCE_TO(ScriptDataDoubleEscapeEndState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(ScriptDataDoubleEscapeEndState);
</ins><span class="cx">         }
</span><span class="cx">         RECONSUME_IN(ScriptDataDoubleEscapedState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -711,7 +711,7 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(BeforeAttributeNameState);
</span><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(SelfClosingStartTagState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(SelfClosingStartTagState);
</ins><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (m_options.usePreHTML5ParserQuirks &amp;&amp; character == '&lt;')
</span><span class="lines">@@ -724,7 +724,7 @@
</span><span class="cx">             parseError();
</span><span class="cx">         m_token.beginAttribute(source.numberOfCharactersConsumed());
</span><span class="cx">         m_token.appendToAttributeName(toASCIILower(character));
</span><del>-        ADVANCE_TO(AttributeNameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(AttributeNameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AttributeNameState)
</span><span class="lines">@@ -731,9 +731,9 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(AfterAttributeNameState);
</span><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(SelfClosingStartTagState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(SelfClosingStartTagState);
</ins><span class="cx">         if (character == '=')
</span><del>-            ADVANCE_TO(BeforeAttributeValueState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(BeforeAttributeValueState);
</ins><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (m_options.usePreHTML5ParserQuirks &amp;&amp; character == '&lt;')
</span><span class="lines">@@ -745,7 +745,7 @@
</span><span class="cx">         if (character == '&quot;' || character == '\'' || character == '&lt;' || character == '=')
</span><span class="cx">             parseError();
</span><span class="cx">         m_token.appendToAttributeName(toASCIILower(character));
</span><del>-        ADVANCE_TO(AttributeNameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(AttributeNameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AfterAttributeNameState)
</span><span class="lines">@@ -752,9 +752,9 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(AfterAttributeNameState);
</span><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(SelfClosingStartTagState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(SelfClosingStartTagState);
</ins><span class="cx">         if (character == '=')
</span><del>-            ADVANCE_TO(BeforeAttributeValueState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(BeforeAttributeValueState);
</ins><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (m_options.usePreHTML5ParserQuirks &amp;&amp; character == '&lt;')
</span><span class="lines">@@ -767,7 +767,7 @@
</span><span class="cx">             parseError();
</span><span class="cx">         m_token.beginAttribute(source.numberOfCharactersConsumed());
</span><span class="cx">         m_token.appendToAttributeName(toASCIILower(character));
</span><del>-        ADVANCE_TO(AttributeNameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(AttributeNameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(BeforeAttributeValueState)
</span><span class="lines">@@ -774,11 +774,11 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(BeforeAttributeValueState);
</span><span class="cx">         if (character == '&quot;')
</span><del>-            ADVANCE_TO(AttributeValueDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AttributeValueDoubleQuotedState);
</ins><span class="cx">         if (character == '&amp;')
</span><span class="cx">             RECONSUME_IN(AttributeValueUnquotedState);
</span><span class="cx">         if (character == '\'')
</span><del>-            ADVANCE_TO(AttributeValueSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AttributeValueSingleQuotedState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="lines">@@ -790,17 +790,17 @@
</span><span class="cx">         if (character == '&lt;' || character == '=' || character == '`')
</span><span class="cx">             parseError();
</span><span class="cx">         m_token.appendToAttributeValue(character);
</span><del>-        ADVANCE_TO(AttributeValueUnquotedState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(AttributeValueUnquotedState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AttributeValueDoubleQuotedState)
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             m_token.endAttribute(source.numberOfCharactersConsumed());
</span><del>-            ADVANCE_TO(AfterAttributeValueQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterAttributeValueQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&amp;') {
</span><span class="cx">             m_additionalAllowedCharacter = '&quot;';
</span><del>-            ADVANCE_TO(CharacterReferenceInAttributeValueState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CharacterReferenceInAttributeValueState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -814,11 +814,11 @@
</span><span class="cx">     BEGIN_STATE(AttributeValueSingleQuotedState)
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             m_token.endAttribute(source.numberOfCharactersConsumed());
</span><del>-            ADVANCE_TO(AfterAttributeValueQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterAttributeValueQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&amp;') {
</span><span class="cx">             m_additionalAllowedCharacter = '\'';
</span><del>-            ADVANCE_TO(CharacterReferenceInAttributeValueState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CharacterReferenceInAttributeValueState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -836,7 +836,7 @@
</span><span class="cx">         }
</span><span class="cx">         if (character == '&amp;') {
</span><span class="cx">             m_additionalAllowedCharacter = '&gt;';
</span><del>-            ADVANCE_TO(CharacterReferenceInAttributeValueState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CharacterReferenceInAttributeValueState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             m_token.endAttribute(source.numberOfCharactersConsumed());
</span><span class="lines">@@ -850,7 +850,7 @@
</span><span class="cx">         if (character == '&quot;' || character == '\'' || character == '&lt;' || character == '=' || character == '`')
</span><span class="cx">             parseError();
</span><span class="cx">         m_token.appendToAttributeValue(character);
</span><del>-        ADVANCE_TO(AttributeValueUnquotedState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(AttributeValueUnquotedState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CharacterReferenceInAttributeValueState)
</span><span class="lines">@@ -882,7 +882,7 @@
</span><span class="cx">         if (isTokenizerWhitespace(character))
</span><span class="cx">             ADVANCE_TO(BeforeAttributeNameState);
</span><span class="cx">         if (character == '/')
</span><del>-            ADVANCE_TO(SelfClosingStartTagState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(SelfClosingStartTagState);
</ins><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (m_options.usePreHTML5ParserQuirks &amp;&amp; character == '&lt;')
</span><span class="lines">@@ -932,7 +932,7 @@
</span><span class="cx">             if (result == SegmentedString::NotEnoughCharacters)
</span><span class="cx">                 RETURN_IN_CURRENT_STATE(haveBufferedCharacterToken());
</span><span class="cx">         } else if (isASCIIAlphaCaselessEqual(character, 'd')) {
</span><del>-            auto result = source.advancePastIgnoringCase(&quot;doctype&quot;);
</del><ins>+            auto result = source.advancePastLettersIgnoringASCIICase(&quot;doctype&quot;);
</ins><span class="cx">             if (result == SegmentedString::DidMatch)
</span><span class="cx">                 SWITCH_TO(DOCTYPEState);
</span><span class="cx">             if (result == SegmentedString::NotEnoughCharacters)
</span><span class="lines">@@ -950,7 +950,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CommentStartState)
</span><span class="cx">         if (character == '-')
</span><del>-            ADVANCE_TO(CommentStartDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentStartDashState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="lines">@@ -965,7 +965,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CommentStartDashState)
</span><span class="cx">         if (character == '-')
</span><del>-            ADVANCE_TO(CommentEndState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="lines">@@ -981,7 +981,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CommentState)
</span><span class="cx">         if (character == '-')
</span><del>-            ADVANCE_TO(CommentEndDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndDashState);
</ins><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="lines">@@ -992,7 +992,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CommentEndDashState)
</span><span class="cx">         if (character == '-')
</span><del>-            ADVANCE_TO(CommentEndState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndState);
</ins><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="lines">@@ -1007,12 +1007,12 @@
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (character == '!') {
</span><span class="cx">             parseError();
</span><del>-            ADVANCE_TO(CommentEndBangState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndBangState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '-') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.appendToComment('-');
</span><del>-            ADVANCE_TO(CommentEndState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1030,7 +1030,7 @@
</span><span class="cx">             m_token.appendToComment('-');
</span><span class="cx">             m_token.appendToComment('-');
</span><span class="cx">             m_token.appendToComment('!');
</span><del>-            ADVANCE_TO(CommentEndDashState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CommentEndDashState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;')
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="lines">@@ -1074,7 +1074,7 @@
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="cx">         }
</span><span class="cx">         m_token.beginDOCTYPE(toASCIILower(character));
</span><del>-        ADVANCE_TO(DOCTYPENameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPENameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DOCTYPENameState)
</span><span class="lines">@@ -1088,7 +1088,7 @@
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="cx">         }
</span><span class="cx">         m_token.appendToName(toASCIILower(character));
</span><del>-        ADVANCE_TO(DOCTYPENameState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPENameState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AfterDOCTYPENameState)
</span><span class="lines">@@ -1102,13 +1102,13 @@
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="cx">         }
</span><span class="cx">         if (isASCIIAlphaCaselessEqual(character, 'p')) {
</span><del>-            auto result = source.advancePastIgnoringCase(&quot;public&quot;);
</del><ins>+            auto result = source.advancePastLettersIgnoringASCIICase(&quot;public&quot;);
</ins><span class="cx">             if (result == SegmentedString::DidMatch)
</span><span class="cx">                 SWITCH_TO(AfterDOCTYPEPublicKeywordState);
</span><span class="cx">             if (result == SegmentedString::NotEnoughCharacters)
</span><span class="cx">                 RETURN_IN_CURRENT_STATE(haveBufferedCharacterToken());
</span><span class="cx">         } else if (isASCIIAlphaCaselessEqual(character, 's')) {
</span><del>-            auto result = source.advancePastIgnoringCase(&quot;system&quot;);
</del><ins>+            auto result = source.advancePastLettersIgnoringASCIICase(&quot;system&quot;);
</ins><span class="cx">             if (result == SegmentedString::DidMatch)
</span><span class="cx">                 SWITCH_TO(AfterDOCTYPESystemKeywordState);
</span><span class="cx">             if (result == SegmentedString::NotEnoughCharacters)
</span><span class="lines">@@ -1116,7 +1116,7 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AfterDOCTYPEPublicKeywordState)
</span><span class="lines">@@ -1125,12 +1125,12 @@
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setPublicIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setPublicIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1144,7 +1144,7 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(BeforeDOCTYPEPublicIdentifierState)
</span><span class="lines">@@ -1152,11 +1152,11 @@
</span><span class="cx">             ADVANCE_TO(BeforeDOCTYPEPublicIdentifierState);
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             m_token.setPublicIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPEPublicIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             m_token.setPublicIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPEPublicIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1170,12 +1170,12 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DOCTYPEPublicIdentifierDoubleQuotedState)
</span><span class="cx">         if (character == '&quot;')
</span><del>-            ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterDOCTYPEPublicIdentifierState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setForceQuirks();
</span><span class="lines">@@ -1192,7 +1192,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DOCTYPEPublicIdentifierSingleQuotedState)
</span><span class="cx">         if (character == '\'')
</span><del>-            ADVANCE_TO(AfterDOCTYPEPublicIdentifierState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterDOCTYPEPublicIdentifierState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setForceQuirks();
</span><span class="lines">@@ -1215,12 +1215,12 @@
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1229,7 +1229,7 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(BetweenDOCTYPEPublicAndSystemIdentifiersState)
</span><span class="lines">@@ -1239,11 +1239,11 @@
</span><span class="cx">             return emitAndResumeInDataState(source);
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == kEndOfFileMarker) {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1252,7 +1252,7 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(AfterDOCTYPESystemKeywordState)
</span><span class="lines">@@ -1261,12 +1261,12 @@
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1280,7 +1280,7 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(BeforeDOCTYPESystemIdentifierState)
</span><span class="lines">@@ -1288,11 +1288,11 @@
</span><span class="cx">             ADVANCE_TO(BeforeDOCTYPESystemIdentifierState);
</span><span class="cx">         if (character == '&quot;') {
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierDoubleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '\'') {
</span><span class="cx">             m_token.setSystemIdentifierToEmptyString();
</span><del>-            ADVANCE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DOCTYPESystemIdentifierSingleQuotedState);
</ins><span class="cx">         }
</span><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="lines">@@ -1306,12 +1306,12 @@
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><span class="cx">         m_token.setForceQuirks();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DOCTYPESystemIdentifierDoubleQuotedState)
</span><span class="cx">         if (character == '&quot;')
</span><del>-            ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterDOCTYPESystemIdentifierState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setForceQuirks();
</span><span class="lines">@@ -1328,7 +1328,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(DOCTYPESystemIdentifierSingleQuotedState)
</span><span class="cx">         if (character == '\'')
</span><del>-            ADVANCE_TO(AfterDOCTYPESystemIdentifierState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(AfterDOCTYPESystemIdentifierState);
</ins><span class="cx">         if (character == '&gt;') {
</span><span class="cx">             parseError();
</span><span class="cx">             m_token.setForceQuirks();
</span><span class="lines">@@ -1354,7 +1354,7 @@
</span><span class="cx">             return emitAndReconsumeInDataState();
</span><span class="cx">         }
</span><span class="cx">         parseError();
</span><del>-        ADVANCE_TO(BogusDOCTYPEState);
</del><ins>+        ADVANCE_PAST_NON_NEWLINE_TO(BogusDOCTYPEState);
</ins><span class="cx">     END_STATE()
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(BogusDOCTYPEState)
</span><span class="lines">@@ -1367,7 +1367,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CDATASectionState)
</span><span class="cx">         if (character == ']')
</span><del>-            ADVANCE_TO(CDATASectionRightSquareBracketState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CDATASectionRightSquareBracketState);
</ins><span class="cx">         if (character == kEndOfFileMarker)
</span><span class="cx">             RECONSUME_IN(DataState);
</span><span class="cx">         bufferCharacter(character);
</span><span class="lines">@@ -1376,7 +1376,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CDATASectionRightSquareBracketState)
</span><span class="cx">         if (character == ']')
</span><del>-            ADVANCE_TO(CDATASectionDoubleRightSquareBracketState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(CDATASectionDoubleRightSquareBracketState);
</ins><span class="cx">         bufferASCIICharacter(']');
</span><span class="cx">         RECONSUME_IN(CDATASectionState);
</span><span class="cx">     END_STATE()
</span><span class="lines">@@ -1383,7 +1383,7 @@
</span><span class="cx"> 
</span><span class="cx">     BEGIN_STATE(CDATASectionDoubleRightSquareBracketState)
</span><span class="cx">         if (character == '&gt;')
</span><del>-            ADVANCE_TO(DataState);
</del><ins>+            ADVANCE_PAST_NON_NEWLINE_TO(DataState);
</ins><span class="cx">         bufferASCIICharacter(']');
</span><span class="cx">         bufferASCIICharacter(']');
</span><span class="cx">         RECONSUME_IN(CDATASectionState);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserInputStreamPreprocessorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/InputStreamPreprocessor.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/InputStreamPreprocessor.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/parser/InputStreamPreprocessor.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -28,22 +28,17 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include &quot;SegmentedString.h&quot;
</span><del>-#include &lt;wtf/Noncopyable.h&gt;
</del><span class="cx"> #include &lt;wtf/unicode/CharacterNames.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-const LChar kEndOfFileMarker = 0;
-
</del><span class="cx"> // http://www.whatwg.org/specs/web-apps/current-work/#preprocessing-the-input-stream
</span><span class="cx"> template &lt;typename Tokenizer&gt;
</span><span class="cx"> class InputStreamPreprocessor {
</span><del>-    WTF_MAKE_NONCOPYABLE(InputStreamPreprocessor);
</del><span class="cx"> public:
</span><span class="cx">     explicit InputStreamPreprocessor(Tokenizer&amp; tokenizer)
</span><span class="cx">         : m_tokenizer(tokenizer)
</span><span class="cx">     {
</span><del>-        reset();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE UChar nextInputCharacter() const { return m_nextInputCharacter; }
</span><span class="lines">@@ -53,20 +48,21 @@
</span><span class="cx">     // characters in |source| (after collapsing \r\n, etc).
</span><span class="cx">     ALWAYS_INLINE bool peek(SegmentedString&amp; source, bool skipNullCharacters = false)
</span><span class="cx">     {
</span><del>-        if (source.isEmpty())
</del><ins>+        if (UNLIKELY(source.isEmpty()))
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        m_nextInputCharacter = source.currentChar();
</del><ins>+        m_nextInputCharacter = source.currentCharacter();
</ins><span class="cx"> 
</span><span class="cx">         // Every branch in this function is expensive, so we have a
</span><span class="cx">         // fast-reject branch for characters that don't require special
</span><span class="cx">         // handling. Please run the parser benchmark whenever you touch
</span><span class="cx">         // this function. It's very hot.
</span><del>-        static const UChar specialCharacterMask = '\n' | '\r' | '\0';
-        if (m_nextInputCharacter &amp; ~specialCharacterMask) {
</del><ins>+        constexpr UChar specialCharacterMask = '\n' | '\r' | '\0';
+        if (LIKELY(m_nextInputCharacter &amp; ~specialCharacterMask)) {
</ins><span class="cx">             m_skipNextNewLine = false;
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><ins>+
</ins><span class="cx">         return processNextInputCharacter(source, skipNullCharacters);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -73,16 +69,13 @@
</span><span class="cx">     // Returns whether there are more characters in |source| after advancing.
</span><span class="cx">     ALWAYS_INLINE bool advance(SegmentedString&amp; source, bool skipNullCharacters = false)
</span><span class="cx">     {
</span><del>-        source.advanceAndUpdateLineNumber();
</del><ins>+        source.advance();
</ins><span class="cx">         return peek(source, skipNullCharacters);
</span><span class="cx">     }
</span><del>-
-    bool skipNextNewLine() const { return m_skipNextNewLine; }
-
-    void reset(bool skipNextNewLine = false)
</del><ins>+    ALWAYS_INLINE bool advancePastNonNewline(SegmentedString&amp; source, bool skipNullCharacters = false)
</ins><span class="cx">     {
</span><del>-        m_nextInputCharacter = '\0';
-        m_skipNextNewLine = skipNextNewLine;
</del><ins>+        source.advancePastNonNewline();
+        return peek(source, skipNullCharacters);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -89,39 +82,34 @@
</span><span class="cx">     bool processNextInputCharacter(SegmentedString&amp; source, bool skipNullCharacters)
</span><span class="cx">     {
</span><span class="cx">     ProcessAgain:
</span><del>-        ASSERT(m_nextInputCharacter == source.currentChar());
-
</del><ins>+        ASSERT(m_nextInputCharacter == source.currentCharacter());
</ins><span class="cx">         if (m_nextInputCharacter == '\n' &amp;&amp; m_skipNextNewLine) {
</span><span class="cx">             m_skipNextNewLine = false;
</span><del>-            source.advancePastNewlineAndUpdateLineNumber();
</del><ins>+            source.advancePastNewline();
</ins><span class="cx">             if (source.isEmpty())
</span><span class="cx">                 return false;
</span><del>-            m_nextInputCharacter = source.currentChar();
</del><ins>+            m_nextInputCharacter = source.currentCharacter();
</ins><span class="cx">         }
</span><span class="cx">         if (m_nextInputCharacter == '\r') {
</span><span class="cx">             m_nextInputCharacter = '\n';
</span><span class="cx">             m_skipNextNewLine = true;
</span><del>-        } else {
-            m_skipNextNewLine = false;
-            // FIXME: The spec indicates that the surrogate pair range as well as
-            // a number of specific character values are parse errors and should be replaced
-            // by the replacement character. We suspect this is a problem with the spec as doing
-            // that filtering breaks surrogate pair handling and causes us not to match Minefield.
-            if (m_nextInputCharacter == '\0' &amp;&amp; !shouldTreatNullAsEndOfFileMarker(source)) {
-                if (skipNullCharacters &amp;&amp; !m_tokenizer.neverSkipNullCharacters()) {
-                    source.advancePastNonNewline();
-                    if (source.isEmpty())
-                        return false;
-                    m_nextInputCharacter = source.currentChar();
-                    goto ProcessAgain;
-                }
-                m_nextInputCharacter = replacementCharacter;
-            }
</del><ins>+            return true;
</ins><span class="cx">         }
</span><ins>+        m_skipNextNewLine = false;
+        if (m_nextInputCharacter || isAtEndOfFile(source))
+            return true;
+        if (skipNullCharacters &amp;&amp; !m_tokenizer.neverSkipNullCharacters()) {
+            source.advancePastNonNewline();
+            if (source.isEmpty())
+                return false;
+            m_nextInputCharacter = source.currentCharacter();
+            goto ProcessAgain;
+        }
+        m_nextInputCharacter = replacementCharacter;
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool shouldTreatNullAsEndOfFileMarker(SegmentedString&amp; source) const
</del><ins>+    static bool isAtEndOfFile(SegmentedString&amp; source)
</ins><span class="cx">     {
</span><span class="cx">         return source.isClosed() &amp;&amp; source.length() == 1;
</span><span class="cx">     }
</span><span class="lines">@@ -129,8 +117,8 @@
</span><span class="cx">     Tokenizer&amp; m_tokenizer;
</span><span class="cx"> 
</span><span class="cx">     // http://www.whatwg.org/specs/web-apps/current-work/#next-input-character
</span><del>-    UChar m_nextInputCharacter;
-    bool m_skipNextNewLine;
</del><ins>+    UChar m_nextInputCharacter { 0 };
+    bool m_skipNextNewLine { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackBufferedLineReadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/BufferedLineReader.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/BufferedLineReader.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/BufferedLineReader.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-bool BufferedLineReader::getLine(String&amp; line)
</del><ins>+std::optional&lt;String&gt; BufferedLineReader::nextLine()
</ins><span class="cx"> {
</span><span class="cx">     if (m_maybeSkipLF) {
</span><span class="cx">         // We ran out of data after a CR (U+000D), which means that we may be
</span><span class="lines">@@ -42,42 +42,42 @@
</span><span class="cx">         // in the middle of a CRLF pair. If the next character is a LF (U+000A)
</span><span class="cx">         // then skip it, and then (unconditionally) return the buffered line.
</span><span class="cx">         if (!m_buffer.isEmpty()) {
</span><del>-            scanCharacter(newlineCharacter);
</del><ins>+            if (m_buffer.currentCharacter() == newlineCharacter)
+                m_buffer.advancePastNewline();
</ins><span class="cx">             m_maybeSkipLF = false;
</span><span class="cx">         }
</span><span class="cx">         // If there was no (new) data available, then keep m_maybeSkipLF set,
</span><del>-        // and fall through all the way down to the EOS check at the end of
-        // the method.
</del><ins>+        // and fall through all the way down to the EOS check at the end of the function.
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool shouldReturnLine = false;
</span><span class="cx">     bool checkForLF = false;
</span><span class="cx">     while (!m_buffer.isEmpty()) {
</span><del>-        UChar c = m_buffer.currentChar();
</del><ins>+        UChar character = m_buffer.currentCharacter();
</ins><span class="cx">         m_buffer.advance();
</span><span class="cx"> 
</span><del>-        if (c == newlineCharacter || c == carriageReturn) {
</del><ins>+        if (character == newlineCharacter || character == carriageReturn) {
</ins><span class="cx">             // We found a line ending. Return the accumulated line.
</span><span class="cx">             shouldReturnLine = true;
</span><del>-            checkForLF = (c == carriageReturn);
</del><ins>+            checkForLF = (character == carriageReturn);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // NULs are transformed into U+FFFD (REPLACEMENT CHAR.) in step 1 of
</span><span class="cx">         // the WebVTT parser algorithm.
</span><del>-        if (c == '\0')
-            c = replacementCharacter;
</del><ins>+        if (character == '\0')
+            character = replacementCharacter;
</ins><span class="cx"> 
</span><del>-        m_lineBuffer.append(c);
</del><ins>+        m_lineBuffer.append(character);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (checkForLF) {
</span><span class="cx">         // May be in the middle of a CRLF pair.
</span><span class="cx">         if (!m_buffer.isEmpty()) {
</span><del>-            // Scan a potential newline character.
-            scanCharacter(newlineCharacter);
</del><ins>+            if (m_buffer.currentCharacter() == newlineCharacter)
+                m_buffer.advancePastNewline();
</ins><span class="cx">         } else {
</span><del>-            // Check for the LF on the next call (unless we reached EOS, in
</del><ins>+            // Check for the newline on the next call (unless we reached EOS, in
</ins><span class="cx">             // which case we'll return the contents of the line buffer, and
</span><span class="cx">             // reset state for the next line.)
</span><span class="cx">             m_maybeSkipLF = true;
</span><span class="lines">@@ -92,13 +92,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (shouldReturnLine) {
</span><del>-        line = m_lineBuffer.toString();
</del><ins>+        auto line = m_lineBuffer.toString();
</ins><span class="cx">         m_lineBuffer.clear();
</span><del>-        return true;
</del><ins>+        return WTFMove(line);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_buffer.isEmpty());
</span><del>-    return false;
</del><ins>+    return std::nullopt;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackBufferedLineReaderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/BufferedLineReader.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/BufferedLineReader.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/BufferedLineReader.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -38,50 +38,39 @@
</span><span class="cx"> // Line collection helper for the WebVTT Parser.
</span><span class="cx"> //
</span><span class="cx"> // Converts a stream of data (== a sequence of Strings) into a set of
</span><del>-// lines. CR, LR or CRLF are considered linebreaks. Normalizes NULs (U+0000)
-// to 'REPLACEMENT CHARACTER' (U+FFFD) and does not return the linebreaks as
</del><ins>+// lines. CR, LR or CRLF are considered line breaks. Normalizes NULs (U+0000)
+// to 'REPLACEMENT CHARACTER' (U+FFFD) and does not return the line breaks as
</ins><span class="cx"> // part of the result.
</span><span class="cx"> class BufferedLineReader {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(BufferedLineReader);
</span><span class="cx"> public:
</span><del>-    BufferedLineReader()
-        : m_endOfStream(false)
-        , m_maybeSkipLF(false) { }
</del><ins>+    BufferedLineReader() = default;
+    void reset();
</ins><span class="cx"> 
</span><del>-    // Append data to the internal buffer.
-    void append(const String&amp; data)
</del><ins>+    void append(String&amp;&amp; data)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(!m_endOfStream);
</span><del>-        m_buffer.append(SegmentedString(data));
</del><ins>+        m_buffer.append(WTFMove(data));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Indicate that no more data will be appended. This will cause any
-    // potentially &quot;unterminated&quot; line to be returned from getLine.
-    void setEndOfStream() { m_endOfStream = true; }
-
-    // Attempt to read a line from the internal buffer (fed via append).
-    // If successful, true is returned and |line| is set to the line that was
-    // read. If no line could be read false is returned.
-    bool getLine(String&amp; line);
-
-    // Returns true if EOS has been reached proper.
</del><ins>+    void appendEndOfStream() { m_endOfStream = true; }
</ins><span class="cx">     bool isAtEndOfStream() const { return m_endOfStream &amp;&amp; m_buffer.isEmpty(); }
</span><span class="cx"> 
</span><del>-    void reset() { m_buffer.clear(); }
</del><ins>+    std::optional&lt;String&gt; nextLine();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    // Consume the next character the buffer if it is the character |c|.
-    void scanCharacter(UChar c)
-    {
-        ASSERT(!m_buffer.isEmpty());
-        if (m_buffer.currentChar() == c)
-            m_buffer.advance();
-    }
-
</del><span class="cx">     SegmentedString m_buffer;
</span><span class="cx">     StringBuilder m_lineBuffer;
</span><del>-    bool m_endOfStream;
-    bool m_maybeSkipLF;
</del><ins>+    bool m_endOfStream { false };
+    bool m_maybeSkipLF { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline void BufferedLineReader::reset()
+{
+    m_buffer.clear();
+    m_lineBuffer.clear();
+    m_endOfStream = false;
+    m_maybeSkipLF = false;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackInbandGenericTextTrackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/InbandGenericTextTrack.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/InbandGenericTextTrack.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/InbandGenericTextTrack.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -185,10 +185,10 @@
</span><span class="cx">     parser().parseCueData(cueData);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InbandGenericTextTrack::parseWebVTTFileHeader(InbandTextTrackPrivate* trackPrivate, String header)
</del><ins>+void InbandGenericTextTrack::parseWebVTTFileHeader(InbandTextTrackPrivate* trackPrivate, String&amp;&amp; header)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(trackPrivate, trackPrivate == m_private);
</span><del>-    parser().parseFileHeader(header);
</del><ins>+    parser().parseFileHeader(WTFMove(header));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InbandGenericTextTrack::newCuesParsed()
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackInbandGenericTextTrackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/InbandGenericTextTrack.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/InbandGenericTextTrack.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/InbandGenericTextTrack.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">     WebVTTParser&amp; parser();
</span><span class="cx">     void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&amp;) final;
</span><del>-    void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) final;
</del><ins>+    void parseWebVTTFileHeader(InbandTextTrackPrivate*, String&amp;&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     void newCuesParsed() final;
</span><span class="cx">     void newRegionsParsed() final;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackInbandTextTrackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/InbandTextTrack.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/InbandTextTrack.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/InbandTextTrack.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx">     void updateGenericCue(InbandTextTrackPrivate*, GenericCueData*) override { ASSERT_NOT_REACHED(); }
</span><span class="cx">     void removeGenericCue(InbandTextTrackPrivate*, GenericCueData*) override { ASSERT_NOT_REACHED(); }
</span><span class="cx"> 
</span><del>-    void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) override { ASSERT_NOT_REACHED(); }
</del><ins>+    void parseWebVTTFileHeader(InbandTextTrackPrivate*, String&amp;&amp;) override { ASSERT_NOT_REACHED(); }
</ins><span class="cx">     void parseWebVTTCueData(InbandTextTrackPrivate*, const char*, unsigned) override { ASSERT_NOT_REACHED(); }
</span><span class="cx">     void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&amp;) override { ASSERT_NOT_REACHED(); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackWebVTTParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/WebVTTParser.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/WebVTTParser.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/WebVTTParser.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -104,24 +104,23 @@
</span><span class="cx">     m_regionList.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebVTTParser::parseFileHeader(const String&amp; data)
</del><ins>+void WebVTTParser::parseFileHeader(String&amp;&amp; data)
</ins><span class="cx"> {
</span><span class="cx">     m_state = Initial;
</span><span class="cx">     m_lineReader.reset();
</span><del>-    m_lineReader.append(data);
</del><ins>+    m_lineReader.append(WTFMove(data));
</ins><span class="cx">     parse();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVTTParser::parseBytes(const char* data, unsigned length)
</span><span class="cx"> {
</span><del>-    String textData = m_decoder-&gt;decode(data, length);
-    m_lineReader.append(textData);
</del><ins>+    m_lineReader.append(m_decoder-&gt;decode(data, length));
</ins><span class="cx">     parse();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebVTTParser::parseCueData(const ISOWebVTTCue&amp; data)
</span><span class="cx"> {
</span><del>-    RefPtr&lt;WebVTTCueData&gt; cue = WebVTTCueData::create();
</del><ins>+    auto cue = WebVTTCueData::create();
</ins><span class="cx"> 
</span><span class="cx">     MediaTime startTime = data.presentationTime();
</span><span class="cx">     cue-&gt;setStartTime(startTime);
</span><span class="lines">@@ -135,7 +134,7 @@
</span><span class="cx">     if (WebVTTParser::collectTimeStamp(data.originalStartTime(), originalStartTime))
</span><span class="cx">         cue-&gt;setOriginalStartTime(originalStartTime);
</span><span class="cx"> 
</span><del>-    m_cuelist.append(cue);
</del><ins>+    m_cuelist.append(WTFMove(cue));
</ins><span class="cx">     if (m_client)
</span><span class="cx">         m_client-&gt;newCuesParsed();
</span><span class="cx"> }
</span><span class="lines">@@ -142,9 +141,8 @@
</span><span class="cx"> 
</span><span class="cx"> void WebVTTParser::flush()
</span><span class="cx"> {
</span><del>-    String textData = m_decoder-&gt;flush();
-    m_lineReader.append(textData);
-    m_lineReader.setEndOfStream();
</del><ins>+    m_lineReader.append(m_decoder-&gt;flush());
+    m_lineReader.appendEndOfStream();
</ins><span class="cx">     parse();
</span><span class="cx">     flushPendingCue();
</span><span class="cx"> }
</span><span class="lines">@@ -153,15 +151,11 @@
</span><span class="cx"> {    
</span><span class="cx">     // WebVTT parser algorithm. (5.1 WebVTT file parsing.)
</span><span class="cx">     // Steps 1 - 3 - Initial setup.
</span><del>-    String line;
-    while (m_lineReader.getLine(line)) {
-        if (line.isNull())
-            return;
-
</del><ins>+    while (auto line = m_lineReader.nextLine()) {
</ins><span class="cx">         switch (m_state) {
</span><span class="cx">         case Initial:
</span><span class="cx">             // Steps 4 - 9 - Check for a valid WebVTT signature.
</span><del>-            if (!hasRequiredFileIdentifier(line)) {
</del><ins>+            if (!hasRequiredFileIdentifier(*line)) {
</ins><span class="cx">                 if (m_client)
</span><span class="cx">                     m_client-&gt;fileFailedToParse();
</span><span class="cx">                 return;
</span><span class="lines">@@ -171,9 +165,9 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case Header:
</span><del>-            collectMetadataHeader(line);
</del><ins>+            collectMetadataHeader(*line);
</ins><span class="cx"> 
</span><del>-            if (line.isEmpty()) {
</del><ins>+            if (line-&gt;isEmpty()) {
</ins><span class="cx">                 // Steps 10-14 - Allow a header (comment area) under the WEBVTT line.
</span><span class="cx">                 if (m_client &amp;&amp; m_regionList.size())
</span><span class="cx">                     m_client-&gt;newRegionsParsed();
</span><span class="lines">@@ -181,8 +175,8 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             // Step 15 - Break out of header loop if the line could be a timestamp line.
</span><del>-            if (line.contains(&quot;--&gt;&quot;))
-                m_state = recoverCue(line);
</del><ins>+            if (line-&gt;contains(&quot;--&gt;&quot;))
+                m_state = recoverCue(*line);
</ins><span class="cx"> 
</span><span class="cx">             // Step 16 - Line is not the empty string and does not contain &quot;--&gt;&quot;.
</span><span class="cx">             break;
</span><span class="lines">@@ -189,7 +183,7 @@
</span><span class="cx"> 
</span><span class="cx">         case Id:
</span><span class="cx">             // Steps 17 - 20 - Allow any number of line terminators, then initialize new cue values.
</span><del>-            if (line.isEmpty())
</del><ins>+            if (line-&gt;isEmpty())
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             // Step 21 - Cue creation (start a new cue).
</span><span class="lines">@@ -196,28 +190,28 @@
</span><span class="cx">             resetCueValues();
</span><span class="cx"> 
</span><span class="cx">             // Steps 22 - 25 - Check if this line contains an optional identifier or timing data.
</span><del>-            m_state = collectCueId(line);
</del><ins>+            m_state = collectCueId(*line);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case TimingsAndSettings:
</span><span class="cx">             // Steps 26 - 27 - Discard current cue if the line is empty.
</span><del>-            if (line.isEmpty()) {
</del><ins>+            if (line-&gt;isEmpty()) {
</ins><span class="cx">                 m_state = Id;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // Steps 28 - 29 - Collect cue timings and settings.
</span><del>-            m_state = collectTimingsAndSettings(line);
</del><ins>+            m_state = collectTimingsAndSettings(*line);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case CueText:
</span><span class="cx">             // Steps 31 - 41 - Collect the cue text, create a cue, and add it to the output.
</span><del>-            m_state = collectCueText(line);
</del><ins>+            m_state = collectCueText(*line);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case BadCue:
</span><span class="cx">             // Steps 42 - 48 - Discard lines until an empty line or a potential timing line is seen.
</span><del>-            m_state = ignoreBadCue(line);
</del><ins>+            m_state = ignoreBadCue(*line);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case Finished:
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackWebVTTParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/WebVTTParser.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/WebVTTParser.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/WebVTTParser.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -133,7 +133,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Input data to the parser to parse.
</span><span class="cx">     void parseBytes(const char*, unsigned);
</span><del>-    void parseFileHeader(const String&amp;);
</del><ins>+    void parseFileHeader(String&amp;&amp;);
</ins><span class="cx">     void parseCueData(const ISOWebVTTCue&amp;);
</span><span class="cx">     void flush();
</span><span class="cx">     void fileFinished();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackWebVTTTokenizercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/WebVTTTokenizer.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/WebVTTTokenizer.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/html/track/WebVTTTokenizer.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -30,11 +30,10 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><ins>+#include &quot;WebVTTTokenizer.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx"> 
</span><del>-#include &quot;WebVTTTokenizer.h&quot;
-
</del><span class="cx"> #include &quot;MarkupTokenizerInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> #include &lt;wtf/unicode/CharacterNames.h&gt;
</span><span class="lines">@@ -48,7 +47,7 @@
</span><span class="cx">         character = m_preprocessor.nextInputCharacter();    \
</span><span class="cx">         goto stateName;                                     \
</span><span class="cx">     } while (false)
</span><del>-    
</del><ins>+
</ins><span class="cx"> template&lt;unsigned charactersCount&gt; ALWAYS_INLINE bool equalLiteral(const StringBuilder&amp; s, const char (&amp;characters)[charactersCount])
</span><span class="cx"> {
</span><span class="cx">     return WTF::equal(s, reinterpret_cast&lt;const LChar*&gt;(characters), charactersCount - 1);
</span><span class="lines">@@ -69,7 +68,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline bool advanceAndEmitToken(SegmentedString&amp; source, WebVTTToken&amp; resultToken, const WebVTTToken&amp; token)
</span><span class="cx"> {
</span><del>-    source.advanceAndUpdateLineNumber();
</del><ins>+    source.advance();
</ins><span class="cx">     return emitToken(resultToken, token);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -79,7 +78,7 @@
</span><span class="cx"> {
</span><span class="cx">     // Append an EOF marker and close the input &quot;stream&quot;.
</span><span class="cx">     ASSERT(!m_input.isClosed());
</span><del>-    m_input.append(SegmentedString(String(&amp;kEndOfFileMarker, 1)));
</del><ins>+    m_input.append(String { &amp;kEndOfFileMarker, 1 });
</ins><span class="cx">     m_input.close();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsInbandTextTrackPrivateClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/platform/graphics/InbandTextTrackPrivateClient.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -180,7 +180,7 @@
</span><span class="cx">     virtual void updateGenericCue(InbandTextTrackPrivate*, GenericCueData*) = 0;
</span><span class="cx">     virtual void removeGenericCue(InbandTextTrackPrivate*, GenericCueData*) = 0;
</span><span class="cx"> 
</span><del>-    virtual void parseWebVTTFileHeader(InbandTextTrackPrivate*, String) { ASSERT_NOT_REACHED(); }
</del><ins>+    virtual void parseWebVTTFileHeader(InbandTextTrackPrivate*, String&amp;&amp;) { ASSERT_NOT_REACHED(); }
</ins><span class="cx">     virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const char* data, unsigned length) = 0;
</span><span class="cx">     virtual void parseWebVTTCueData(InbandTextTrackPrivate*, const ISOWebVTTCue&amp;) = 0;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformtextSegmentedStringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/SegmentedString.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/SegmentedString.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/platform/text/SegmentedString.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>-    Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
</del><ins>+    Copyright (C) 2004-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> 
</span><span class="cx">     This library is free software; you can redistribute it and/or
</span><span class="cx">     modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -20,332 +20,204 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;SegmentedString.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/text/StringBuilder.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/TextPosition.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-SegmentedString::SegmentedString(const SegmentedString&amp; other)
-    : m_pushedChar1(other.m_pushedChar1)
-    , m_pushedChar2(other.m_pushedChar2)
-    , m_currentString(other.m_currentString)
-    , m_numberOfCharactersConsumedPriorToCurrentString(other.m_numberOfCharactersConsumedPriorToCurrentString)
-    , m_numberOfCharactersConsumedPriorToCurrentLine(other.m_numberOfCharactersConsumedPriorToCurrentLine)
-    , m_currentLine(other.m_currentLine)
-    , m_substrings(other.m_substrings)
-    , m_closed(other.m_closed)
-    , m_empty(other.m_empty)
-    , m_fastPathFlags(other.m_fastPathFlags)
-    , m_advanceFunc(other.m_advanceFunc)
-    , m_advanceAndUpdateLineNumberFunc(other.m_advanceAndUpdateLineNumberFunc)
</del><ins>+inline void SegmentedString::Substring::appendTo(StringBuilder&amp; builder) const
</ins><span class="cx"> {
</span><del>-    if (m_pushedChar2)
-        m_currentChar = m_pushedChar2;
-    else if (m_pushedChar1)
-        m_currentChar = m_pushedChar1;
-    else
-        m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
</del><ins>+    builder.append(string, string.length() - length, length);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-SegmentedString&amp; SegmentedString::operator=(const SegmentedString&amp; other)
</del><ins>+SegmentedString&amp; SegmentedString::operator=(SegmentedString&amp;&amp; other)
</ins><span class="cx"> {
</span><del>-    m_pushedChar1 = other.m_pushedChar1;
-    m_pushedChar2 = other.m_pushedChar2;
-    m_currentString = other.m_currentString;
-    m_substrings = other.m_substrings;
-    if (m_pushedChar2)
-        m_currentChar = m_pushedChar2;
-    else if (m_pushedChar1)
-        m_currentChar = m_pushedChar1;
-    else
-        m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
</del><ins>+    m_currentSubstring = WTFMove(other.m_currentSubstring);
+    m_otherSubstrings = WTFMove(other.m_otherSubstrings);
</ins><span class="cx"> 
</span><del>-    m_closed = other.m_closed;
-    m_empty = other.m_empty;
-    m_fastPathFlags = other.m_fastPathFlags;
-    m_numberOfCharactersConsumedPriorToCurrentString = other.m_numberOfCharactersConsumedPriorToCurrentString;
</del><ins>+    m_isClosed = other.m_isClosed;
+
+    m_currentCharacter = other.m_currentCharacter;
+
+    m_numberOfCharactersConsumedPriorToCurrentSubstring = other.m_numberOfCharactersConsumedPriorToCurrentSubstring;
</ins><span class="cx">     m_numberOfCharactersConsumedPriorToCurrentLine = other.m_numberOfCharactersConsumedPriorToCurrentLine;
</span><span class="cx">     m_currentLine = other.m_currentLine;
</span><span class="cx"> 
</span><del>-    m_advanceFunc = other.m_advanceFunc;
-    m_advanceAndUpdateLineNumberFunc = other.m_advanceAndUpdateLineNumberFunc;
</del><ins>+    m_fastPathFlags = other.m_fastPathFlags;
+    m_advanceWithoutUpdatingLineNumberFunction = other.m_advanceWithoutUpdatingLineNumberFunction;
+    m_advanceAndUpdateLineNumberFunction = other.m_advanceAndUpdateLineNumberFunction;
</ins><span class="cx"> 
</span><ins>+    other.clear();
+
</ins><span class="cx">     return *this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned SegmentedString::length() const
</span><span class="cx"> {
</span><del>-    unsigned length = m_currentString.m_length;
-    if (m_pushedChar1) {
-        ++length;
-        if (m_pushedChar2)
-            ++length;
-    }
-    if (isComposite()) {
-        Deque&lt;SegmentedSubstring&gt;::const_iterator it = m_substrings.begin();
-        Deque&lt;SegmentedSubstring&gt;::const_iterator e = m_substrings.end();
-        for (; it != e; ++it)
-            length += it-&gt;m_length;
-    }
</del><ins>+    unsigned length = m_currentSubstring.length;
+    for (auto&amp; substring : m_otherSubstrings)
+        length += substring.length;
</ins><span class="cx">     return length;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SegmentedString::setExcludeLineNumbers()
</span><span class="cx"> {
</span><del>-    m_currentString.setExcludeLineNumbers();
-    if (isComposite()) {
-        Deque&lt;SegmentedSubstring&gt;::iterator it = m_substrings.begin();
-        Deque&lt;SegmentedSubstring&gt;::iterator e = m_substrings.end();
-        for (; it != e; ++it)
-            it-&gt;setExcludeLineNumbers();
-    }
</del><ins>+    if (!m_currentSubstring.doNotExcludeLineNumbers)
+        return;
+    m_currentSubstring.doNotExcludeLineNumbers = false;
+    for (auto&amp; substring : m_otherSubstrings)
+        substring.doNotExcludeLineNumbers = false;
+    updateAdvanceFunctionPointers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SegmentedString::clear()
</span><span class="cx"> {
</span><del>-    m_pushedChar1 = 0;
-    m_pushedChar2 = 0;
-    m_currentChar = 0;
-    m_currentString.clear();
-    m_numberOfCharactersConsumedPriorToCurrentString = 0;
</del><ins>+    m_currentSubstring.length = 0;
+    m_otherSubstrings.clear();
+
+    m_isClosed = false;
+
+    m_currentCharacter = 0;
+
+    m_numberOfCharactersConsumedPriorToCurrentSubstring = 0;
</ins><span class="cx">     m_numberOfCharactersConsumedPriorToCurrentLine = 0;
</span><span class="cx">     m_currentLine = 0;
</span><del>-    m_substrings.clear();
-    m_closed = false;
-    m_empty = true;
-    m_fastPathFlags = NoFastPath;
-    m_advanceFunc = &amp;SegmentedString::advanceEmpty;
-    m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceEmpty;
-}
</del><span class="cx"> 
</span><del>-void SegmentedString::append(const SegmentedSubstring&amp; s)
-{
-    ASSERT(!m_closed);
-    if (!s.m_length)
-        return;
-
-    if (!m_currentString.m_length) {
-        m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
-        m_currentString = s;
-        updateAdvanceFunctionPointers();
-    } else
-        m_substrings.append(s);
-    m_empty = false;
</del><ins>+    updateAdvanceFunctionPointersForEmptyString();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::pushBack(const SegmentedSubstring&amp; s)
</del><ins>+inline void SegmentedString::appendSubstring(Substring&amp;&amp; substring)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    ASSERT(!s.numberOfCharactersConsumed());
-    if (!s.m_length)
</del><ins>+    ASSERT(!m_isClosed);
+    if (!substring.length)
</ins><span class="cx">         return;
</span><del>-
-    // FIXME: We're assuming that the characters were originally consumed by
-    //        this SegmentedString.  We're also ASSERTing that s is a fresh
-    //        SegmentedSubstring.  These assumptions are sufficient for our
-    //        current use, but we might need to handle the more elaborate
-    //        cases in the future.
-    m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
-    m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length;
-    if (!m_currentString.m_length) {
-        m_currentString = s;
</del><ins>+    if (m_currentSubstring.length)
+        m_otherSubstrings.append(WTFMove(substring));
+    else {
+        m_numberOfCharactersConsumedPriorToCurrentSubstring += m_currentSubstring.numberOfCharactersConsumed();
+        m_currentSubstring = WTFMove(substring);
+        m_currentCharacter = m_currentSubstring.currentCharacter();
</ins><span class="cx">         updateAdvanceFunctionPointers();
</span><del>-    } else {
-        // Shift our m_currentString into our list.
-        m_substrings.prepend(m_currentString);
-        m_currentString = s;
-        updateAdvanceFunctionPointers();
</del><span class="cx">     }
</span><del>-    m_empty = false;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::close()
</del><ins>+void SegmentedString::pushBack(String&amp;&amp; string)
</ins><span class="cx"> {
</span><del>-    // Closing a stream twice is likely a coding mistake.
-    ASSERT(!m_closed);
-    m_closed = true;
-}
</del><ins>+    // We never create a substring for an empty string.
+    ASSERT(string.length());
</ins><span class="cx"> 
</span><del>-void SegmentedString::append(const SegmentedString&amp; s)
-{
-    ASSERT(!m_closed);
-    ASSERT(!s.m_pushedChar1);
-    append(s.m_currentString);
-    if (s.isComposite()) {
-        Deque&lt;SegmentedSubstring&gt;::const_iterator it = s.m_substrings.begin();
-        Deque&lt;SegmentedSubstring&gt;::const_iterator e = s.m_substrings.end();
-        for (; it != e; ++it)
-            append(*it);
-    }
-    m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
</del><ins>+    // The new substring we will create won't have the doNotExcludeLineNumbers set appropriately.
+    // That was lost when the characters were consumed before pushing them back. But this does
+    // not matter, because clients never use this for newlines. Catch that with this assertion.
+    ASSERT(!string.contains('\n'));
+
+    // The characters in the string must be previously consumed characters from this segmented string.
+    ASSERT(string.length() &lt;= numberOfCharactersConsumed());
+
+    m_numberOfCharactersConsumedPriorToCurrentSubstring += m_currentSubstring.numberOfCharactersConsumed();
+    if (m_currentSubstring.length)
+        m_otherSubstrings.prepend(WTFMove(m_currentSubstring));
+    m_currentSubstring = WTFMove(string);
+    m_numberOfCharactersConsumedPriorToCurrentSubstring -= m_currentSubstring.length;
+    m_currentCharacter = m_currentSubstring.currentCharacter();
+    updateAdvanceFunctionPointers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::pushBack(const SegmentedString&amp; s)
</del><ins>+void SegmentedString::close()
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    ASSERT(!s.m_pushedChar1);
-    if (s.isComposite()) {
-        Deque&lt;SegmentedSubstring&gt;::const_reverse_iterator it = s.m_substrings.rbegin();
-        Deque&lt;SegmentedSubstring&gt;::const_reverse_iterator e = s.m_substrings.rend();
-        for (; it != e; ++it)
-            pushBack(*it);
-    }
-    pushBack(s.m_currentString);
-    m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
</del><ins>+    ASSERT(!m_isClosed);
+    m_isClosed = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advanceSubstring()
</del><ins>+void SegmentedString::append(const SegmentedString&amp; string)
</ins><span class="cx"> {
</span><del>-    if (isComposite()) {
-        m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
-        m_currentString = m_substrings.takeFirst();
-        // If we've previously consumed some characters of the non-current
-        // string, we now account for those characters as part of the current
-        // string, not as part of &quot;prior to current string.&quot;
-        m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
-        updateAdvanceFunctionPointers();
-    } else {
-        m_currentString.clear();
-        m_empty = true;
-        m_fastPathFlags = NoFastPath;
-        m_advanceFunc = &amp;SegmentedString::advanceEmpty;
-        m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceEmpty;
-    }
</del><ins>+    appendSubstring(Substring { string.m_currentSubstring });
+    for (auto&amp; substring : string.m_otherSubstrings)
+        m_otherSubstrings.append(substring);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-String SegmentedString::toString() const
</del><ins>+void SegmentedString::append(SegmentedString&amp;&amp; string)
</ins><span class="cx"> {
</span><del>-    StringBuilder result;
-    if (m_pushedChar1) {
-        result.append(m_pushedChar1);
-        if (m_pushedChar2)
-            result.append(m_pushedChar2);
-    }
-    m_currentString.appendTo(result);
-    if (isComposite()) {
-        Deque&lt;SegmentedSubstring&gt;::const_iterator it = m_substrings.begin();
-        Deque&lt;SegmentedSubstring&gt;::const_iterator e = m_substrings.end();
-        for (; it != e; ++it)
-            it-&gt;appendTo(result);
-    }
-    return result.toString();
</del><ins>+    appendSubstring(WTFMove(string.m_currentSubstring));
+    for (auto&amp; substring : string.m_otherSubstrings)
+        m_otherSubstrings.append(WTFMove(substring));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advancePastNonNewlines(unsigned count, UChar* consumedCharacters)
</del><ins>+void SegmentedString::append(String&amp;&amp; string)
</ins><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(count &lt;= length());
-    for (unsigned i = 0; i &lt; count; ++i) {
-        consumedCharacters[i] = currentChar();
-        advancePastNonNewline();
-    }
</del><ins>+    appendSubstring(WTFMove(string));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advance8()
</del><ins>+void SegmentedString::append(const String&amp; string)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    decrementAndCheckLength();
-    m_currentChar = m_currentString.incrementAndGetCurrentChar8();
</del><ins>+    appendSubstring(String { string });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advance16()
</del><ins>+String SegmentedString::toString() const
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    decrementAndCheckLength();
-    m_currentChar = m_currentString.incrementAndGetCurrentChar16();
</del><ins>+    StringBuilder result;
+    m_currentSubstring.appendTo(result);
+    for (auto&amp; substring : m_otherSubstrings)
+        substring.appendTo(result);
+    return result.toString();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advanceAndUpdateLineNumber8()
</del><ins>+void SegmentedString::advanceWithoutUpdatingLineNumber16()
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    ASSERT(m_currentString.getCurrentChar() == m_currentChar);
-    if (m_currentChar == '\n') {
-        ++m_currentLine;
-        m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
-    }
</del><ins>+    m_currentCharacter = *++m_currentSubstring.currentCharacter16;
</ins><span class="cx">     decrementAndCheckLength();
</span><del>-    m_currentChar = m_currentString.incrementAndGetCurrentChar8();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SegmentedString::advanceAndUpdateLineNumber16()
</span><span class="cx"> {
</span><del>-    ASSERT(!m_pushedChar1);
-    ASSERT(m_currentString.getCurrentChar() == m_currentChar);
-    if (m_currentChar == '\n') {
-        ++m_currentLine;
-        m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
-    }
</del><ins>+    ASSERT(m_currentSubstring.doNotExcludeLineNumbers);
+    processPossibleNewline();
+    m_currentCharacter = *++m_currentSubstring.currentCharacter16;
</ins><span class="cx">     decrementAndCheckLength();
</span><del>-    m_currentChar = m_currentString.incrementAndGetCurrentChar16();
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advanceSlowCase()
</del><ins>+inline void SegmentedString::advancePastSingleCharacterSubstringWithoutUpdatingLineNumber()
</ins><span class="cx"> {
</span><del>-    if (m_pushedChar1) {
-        m_pushedChar1 = m_pushedChar2;
-        m_pushedChar2 = 0;
-
-        if (m_pushedChar1) {
-            m_currentChar = m_pushedChar1;
-            return;
-        }
-
-        updateAdvanceFunctionPointers();
-    } else if (m_currentString.m_length) {
-        if (--m_currentString.m_length == 0)
-            advanceSubstring();
-    } else if (!isComposite()) {
-        m_currentString.clear();
-        m_empty = true;
-        m_fastPathFlags = NoFastPath;
-        m_advanceFunc = &amp;SegmentedString::advanceEmpty;
-        m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceEmpty;
</del><ins>+    ASSERT(m_currentSubstring.length == 1);
+    if (m_otherSubstrings.isEmpty()) {
+        m_currentSubstring.length = 0;
+        m_currentCharacter = 0;
+        updateAdvanceFunctionPointersForEmptyString();
+        return;
</ins><span class="cx">     }
</span><del>-    m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
</del><ins>+    m_numberOfCharactersConsumedPriorToCurrentSubstring += m_currentSubstring.numberOfCharactersConsumed();
+    m_currentSubstring = m_otherSubstrings.takeFirst();
+    // If we've previously consumed some characters of the non-current string, we now account for those
+    // characters as part of the current string, not as part of &quot;prior to current string.&quot;
+    m_numberOfCharactersConsumedPriorToCurrentSubstring -= m_currentSubstring.numberOfCharactersConsumed();
+    m_currentCharacter = m_currentSubstring.currentCharacter();
+    updateAdvanceFunctionPointers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::advanceAndUpdateLineNumberSlowCase()
</del><ins>+void SegmentedString::advancePastSingleCharacterSubstring()
</ins><span class="cx"> {
</span><del>-    if (m_pushedChar1) {
-        m_pushedChar1 = m_pushedChar2;
-        m_pushedChar2 = 0;
-
-        if (m_pushedChar1) {
-            m_currentChar = m_pushedChar1;
-            return;
-        }
-
-        updateAdvanceFunctionPointers();
-    } else if (m_currentString.m_length) {
-        if (m_currentString.getCurrentChar() == '\n' &amp;&amp; m_currentString.doNotExcludeLineNumbers()) {
-            ++m_currentLine;
-            // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
-            m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
-        }
-        if (--m_currentString.m_length == 0)
-            advanceSubstring();
-        else
-            m_currentString.incrementAndGetCurrentChar(); // Only need the ++
-    } else if (!isComposite()) {
-        m_currentString.clear();
-        m_empty = true;
-        m_fastPathFlags = NoFastPath;
-        m_advanceFunc = &amp;SegmentedString::advanceEmpty;
-        m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceEmpty;
-    }
-
-    m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
</del><ins>+    ASSERT(m_currentSubstring.length == 1);
+    ASSERT(m_currentSubstring.doNotExcludeLineNumbers);
+    processPossibleNewline();
+    advancePastSingleCharacterSubstringWithoutUpdatingLineNumber();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SegmentedString::advanceEmpty()
</span><span class="cx"> {
</span><del>-    ASSERT(!m_currentString.m_length &amp;&amp; !isComposite());
-    m_currentChar = 0;
</del><ins>+    ASSERT(!m_currentSubstring.length);
+    ASSERT(m_otherSubstrings.isEmpty());
+    ASSERT(!m_currentCharacter);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SegmentedString::updateSlowCaseFunctionPointers()
</del><ins>+void SegmentedString::updateAdvanceFunctionPointersForSingleCharacterSubstring()
</ins><span class="cx"> {
</span><ins>+    ASSERT(m_currentSubstring.length == 1);
</ins><span class="cx">     m_fastPathFlags = NoFastPath;
</span><del>-    m_advanceFunc = &amp;SegmentedString::advanceSlowCase;
-    m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceAndUpdateLineNumberSlowCase;
</del><ins>+    m_advanceWithoutUpdatingLineNumberFunction = &amp;SegmentedString::advancePastSingleCharacterSubstringWithoutUpdatingLineNumber;
+    if (m_currentSubstring.doNotExcludeLineNumbers)
+        m_advanceAndUpdateLineNumberFunction = &amp;SegmentedString::advancePastSingleCharacterSubstring;
+    else
+        m_advanceAndUpdateLineNumberFunction = &amp;SegmentedString::advancePastSingleCharacterSubstringWithoutUpdatingLineNumber;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> OrdinalNumber SegmentedString::currentLine() const
</span><span class="lines">@@ -364,18 +236,36 @@
</span><span class="cx">     m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SegmentedString::AdvancePastResult SegmentedString::advancePastSlowCase(const char* literal, bool caseSensitive)
</del><ins>+SegmentedString::AdvancePastResult SegmentedString::advancePastSlowCase(const char* literal, bool lettersIgnoringASCIICase)
</ins><span class="cx"> {
</span><del>-    unsigned length = strlen(literal);
</del><ins>+    constexpr unsigned maxLength = 10;
+    ASSERT(!strchr(literal, '\n'));
+    auto length = strlen(literal);
+    ASSERT(length &lt;= maxLength);
</ins><span class="cx">     if (length &gt; this-&gt;length())
</span><span class="cx">         return NotEnoughCharacters;
</span><del>-    UChar* consumedCharacters;
-    String consumedString = String::createUninitialized(length, consumedCharacters);
-    advancePastNonNewlines(length, consumedCharacters);
-    if (consumedString.startsWith(literal, caseSensitive))
-        return DidMatch;
-    pushBack(SegmentedString(consumedString));
-    return DidNotMatch;
</del><ins>+    UChar consumedCharacters[maxLength];
+    for (unsigned i = 0; i &lt; length; ++i) {
+        auto character = m_currentCharacter;
+        if (characterMismatch(character, literal[i], lettersIgnoringASCIICase)) {
+            if (i)
+                pushBack(String { consumedCharacters, i });
+            return DidNotMatch;
+        }
+        advancePastNonNewline();
+        consumedCharacters[i] = character;
+    }
+    return DidMatch;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SegmentedString::updateAdvanceFunctionPointersForEmptyString()
+{
+    ASSERT(!m_currentSubstring.length);
+    ASSERT(m_otherSubstrings.isEmpty());
+    ASSERT(!m_currentCharacter);
+    m_fastPathFlags = NoFastPath;
+    m_advanceWithoutUpdatingLineNumberFunction = &amp;SegmentedString::advanceEmpty;
+    m_advanceAndUpdateLineNumberFunction = &amp;SegmentedString::advanceEmpty;
</ins><span class="cx"> }
</span><ins>+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformtextSegmentedStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/SegmentedString.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/SegmentedString.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/platform/text/SegmentedString.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>-    Copyright (C) 2004-2008, 2015 Apple Inc. All rights reserved.
</del><ins>+    Copyright (C) 2004-2016 Apple Inc. All rights reserved.
</ins><span class="cx"> 
</span><span class="cx">     This library is free software; you can redistribute it and/or
</span><span class="cx">     modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -17,381 +17,307 @@
</span><span class="cx">     Boston, MA 02110-1301, USA.
</span><span class="cx"> */
</span><span class="cx"> 
</span><del>-#ifndef SegmentedString_h
-#define SegmentedString_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/Deque.h&gt;
</span><del>-#include &lt;wtf/text/StringBuilder.h&gt;
</del><ins>+#include &lt;wtf/text/WTFString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-class SegmentedString;
</del><ins>+// FIXME: This should not start with &quot;k&quot;.
+// FIXME: This is a shared tokenizer concept, not a SegmentedString concept, but this is the only common header for now.
+constexpr LChar kEndOfFileMarker = 0;
</ins><span class="cx"> 
</span><del>-class SegmentedSubstring {
</del><ins>+class SegmentedString {
</ins><span class="cx"> public:
</span><del>-    SegmentedSubstring()
-        : m_length(0)
-        , m_doNotExcludeLineNumbers(true)
-        , m_is8Bit(false)
-    {
-        m_data.string16Ptr = 0;
-    }
</del><ins>+    SegmentedString() = default;
+    SegmentedString(String&amp;&amp;);
+    SegmentedString(const String&amp;);
</ins><span class="cx"> 
</span><del>-    SegmentedSubstring(const String&amp; str)
-        : m_length(str.length())
-        , m_doNotExcludeLineNumbers(true)
-        , m_string(str)
-    {
-        if (m_length) {
-            if (m_string.is8Bit()) {
-                m_is8Bit = true;
-                m_data.string8Ptr = m_string.characters8();
-            } else {
-                m_is8Bit = false;
-                m_data.string16Ptr = m_string.characters16();
-            }
-        } else
-            m_is8Bit = false;
-    }
</del><ins>+    SegmentedString(SegmentedString&amp;&amp;) = delete;
+    SegmentedString(const SegmentedString&amp;) = delete;
</ins><span class="cx"> 
</span><del>-    void clear() { m_length = 0; m_data.string16Ptr = 0; m_is8Bit = false;}
-    
-    bool is8Bit() { return m_is8Bit; }
-    
-    bool excludeLineNumbers() const { return !m_doNotExcludeLineNumbers; }
-    bool doNotExcludeLineNumbers() const { return m_doNotExcludeLineNumbers; }
</del><ins>+    SegmentedString&amp; operator=(SegmentedString&amp;&amp;);
+    SegmentedString&amp; operator=(const SegmentedString&amp;) = default;
</ins><span class="cx"> 
</span><del>-    void setExcludeLineNumbers() { m_doNotExcludeLineNumbers = false; }
</del><ins>+    void clear();
+    void close();
</ins><span class="cx"> 
</span><del>-    int numberOfCharactersConsumed() const { return m_string.length() - m_length; }
</del><ins>+    void append(SegmentedString&amp;&amp;);
+    void append(const SegmentedString&amp;);
</ins><span class="cx"> 
</span><del>-    void appendTo(StringBuilder&amp; builder) const
-    {
-        int offset = m_string.length() - m_length;
</del><ins>+    void append(String&amp;&amp;);
+    void append(const String&amp;);
</ins><span class="cx"> 
</span><del>-        if (!offset) {
-            if (m_length)
-                builder.append(m_string);
-        } else
-            builder.append(m_string.substring(offset, m_length));
-    }
</del><ins>+    void pushBack(String&amp;&amp;);
</ins><span class="cx"> 
</span><del>-    UChar getCurrentChar8()
-    {
-        return *m_data.string8Ptr;
-    }
</del><ins>+    void setExcludeLineNumbers();
</ins><span class="cx"> 
</span><del>-    UChar getCurrentChar16()
-    {
-        return m_data.string16Ptr ? *m_data.string16Ptr : 0;
-    }
</del><ins>+    bool isEmpty() const { return !m_currentSubstring.length; }
+    unsigned length() const;
</ins><span class="cx"> 
</span><del>-    UChar incrementAndGetCurrentChar8()
-    {
-        ASSERT(m_data.string8Ptr);
-        return *++m_data.string8Ptr;
-    }
</del><ins>+    bool isClosed() const { return m_isClosed; }
</ins><span class="cx"> 
</span><del>-    UChar incrementAndGetCurrentChar16()
-    {
-        ASSERT(m_data.string16Ptr);
-        return *++m_data.string16Ptr;
-    }
</del><ins>+    void advance();
+    void advancePastNonNewline(); // Faster than calling advance when we know the current character is not a newline.
+    void advancePastNewline(); // Faster than calling advance when we know the current character is a newline.
</ins><span class="cx"> 
</span><del>-    String currentSubString(unsigned length)
-    {
-        int offset = m_string.length() - m_length;
-        return m_string.substring(offset, length);
-    }
</del><ins>+    enum AdvancePastResult { DidNotMatch, DidMatch, NotEnoughCharacters };
+    template&lt;unsigned length&gt; AdvancePastResult advancePast(const char (&amp;literal)[length]) { return advancePast&lt;length, false&gt;(literal); }
+    template&lt;unsigned length&gt; AdvancePastResult advancePastLettersIgnoringASCIICase(const char (&amp;literal)[length]) { return advancePast&lt;length, true&gt;(literal); }
</ins><span class="cx"> 
</span><del>-    ALWAYS_INLINE UChar getCurrentChar()
-    {
-        ASSERT(m_length);
-        if (is8Bit())
-            return getCurrentChar8();
-        return getCurrentChar16();
-    }
-    
-    ALWAYS_INLINE UChar incrementAndGetCurrentChar()
-    {
-        ASSERT(m_length);
-        if (is8Bit())
-            return incrementAndGetCurrentChar8();
-        return incrementAndGetCurrentChar16();
-    }
</del><ins>+    unsigned numberOfCharactersConsumed() const;
</ins><span class="cx"> 
</span><del>-public:
-    union {
-        const LChar* string8Ptr;
-        const UChar* string16Ptr;
-    } m_data;
-    int m_length;
</del><ins>+    String toString() const;
</ins><span class="cx"> 
</span><del>-private:
-    bool m_doNotExcludeLineNumbers;
-    bool m_is8Bit;
-    String m_string;
-};
</del><ins>+    UChar currentCharacter() const { return m_currentCharacter; }
</ins><span class="cx"> 
</span><del>-class SegmentedString {
-public:
-    SegmentedString()
-        : m_pushedChar1(0)
-        , m_pushedChar2(0)
-        , m_currentChar(0)
-        , m_numberOfCharactersConsumedPriorToCurrentString(0)
-        , m_numberOfCharactersConsumedPriorToCurrentLine(0)
-        , m_currentLine(0)
-        , m_closed(false)
-        , m_empty(true)
-        , m_fastPathFlags(NoFastPath)
-        , m_advanceFunc(&amp;SegmentedString::advanceEmpty)
-        , m_advanceAndUpdateLineNumberFunc(&amp;SegmentedString::advanceEmpty)
-    {
-    }
</del><ins>+    OrdinalNumber currentColumn() const;
+    OrdinalNumber currentLine() const;
</ins><span class="cx"> 
</span><del>-    SegmentedString(const String&amp; str)
-        : m_pushedChar1(0)
-        , m_pushedChar2(0)
-        , m_currentString(str)
-        , m_currentChar(0)
-        , m_numberOfCharactersConsumedPriorToCurrentString(0)
-        , m_numberOfCharactersConsumedPriorToCurrentLine(0)
-        , m_currentLine(0)
-        , m_closed(false)
-        , m_empty(!str.length())
-        , m_fastPathFlags(NoFastPath)
-    {
-        if (m_currentString.m_length)
-            m_currentChar = m_currentString.getCurrentChar();
-        updateAdvanceFunctionPointers();
-    }
</del><ins>+    // Sets value of line/column variables. Column is specified indirectly by a parameter columnAfterProlog
+    // which is a value of column that we should get after a prolog (first prologLength characters) has been consumed.
+    void setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAfterProlog, int prologLength);
</ins><span class="cx"> 
</span><del>-    SegmentedString(const SegmentedString&amp;);
-    SegmentedString&amp; operator=(const SegmentedString&amp;);
</del><ins>+private:
+    struct Substring {
+        Substring() = default;
+        Substring(String&amp;&amp;);
</ins><span class="cx"> 
</span><del>-    void clear();
-    void close();
</del><ins>+        UChar currentCharacter() const;
+        UChar currentCharacterPreIncrement();
</ins><span class="cx"> 
</span><del>-    void append(const SegmentedString&amp;);
-    void pushBack(const SegmentedString&amp;);
</del><ins>+        unsigned numberOfCharactersConsumed() const;
+        void appendTo(StringBuilder&amp;) const;
</ins><span class="cx"> 
</span><del>-    void setExcludeLineNumbers();
</del><ins>+        String string;
+        unsigned length { 0 };
+        bool is8Bit;
+        union {
+            const LChar* currentCharacter8;
+            const UChar* currentCharacter16;
+        };
+        bool doNotExcludeLineNumbers { true };
+    };
</ins><span class="cx"> 
</span><del>-    void push(UChar c)
-    {
-        if (!m_pushedChar1) {
-            m_pushedChar1 = c;
-            m_currentChar = m_pushedChar1 ? m_pushedChar1 : m_currentString.getCurrentChar();
-            updateSlowCaseFunctionPointers();
-        } else {
-            ASSERT(!m_pushedChar2);
-            m_pushedChar2 = c;
-        }
-    }
</del><ins>+    enum FastPathFlags {
+        NoFastPath = 0,
+        Use8BitAdvanceAndUpdateLineNumbers = 1 &lt;&lt; 0,
+        Use8BitAdvance = 1 &lt;&lt; 1,
+    };
</ins><span class="cx"> 
</span><del>-    bool isEmpty() const { return m_empty; }
-    unsigned length() const;
</del><ins>+    void appendSubstring(Substring&amp;&amp;);
</ins><span class="cx"> 
</span><del>-    bool isClosed() const { return m_closed; }
</del><ins>+    void processPossibleNewline();
+    void startNewLine();
</ins><span class="cx"> 
</span><del>-    enum AdvancePastResult { DidNotMatch, DidMatch, NotEnoughCharacters };
-    template&lt;unsigned length&gt; AdvancePastResult advancePast(const char (&amp;literal)[length]) { return advancePast(literal, length - 1, true); }
-    template&lt;unsigned length&gt; AdvancePastResult advancePastIgnoringCase(const char (&amp;literal)[length]) { return advancePast(literal, length - 1, false); }
</del><ins>+    void advanceWithoutUpdatingLineNumber();
+    void advanceWithoutUpdatingLineNumber16();
+    void advanceAndUpdateLineNumber16();
+    void advancePastSingleCharacterSubstringWithoutUpdatingLineNumber();
+    void advancePastSingleCharacterSubstring();
+    void advanceEmpty();
</ins><span class="cx"> 
</span><del>-    void advance()
-    {
-        if (m_fastPathFlags &amp; Use8BitAdvance) {
-            ASSERT(!m_pushedChar1);
-            bool haveOneCharacterLeft = (--m_currentString.m_length == 1);
-            m_currentChar = m_currentString.incrementAndGetCurrentChar8();
</del><ins>+    void updateAdvanceFunctionPointers();
+    void updateAdvanceFunctionPointersForEmptyString();
+    void updateAdvanceFunctionPointersForSingleCharacterSubstring();
</ins><span class="cx"> 
</span><del>-            if (!haveOneCharacterLeft)
-                return;
</del><ins>+    void decrementAndCheckLength();
</ins><span class="cx"> 
</span><del>-            updateSlowCaseFunctionPointers();
</del><ins>+    template&lt;typename CharacterType&gt; static bool characterMismatch(CharacterType, char, bool lettersIgnoringASCIICase);
+    template&lt;unsigned length, bool lettersIgnoringASCIICase&gt; AdvancePastResult advancePast(const char (&amp;literal)[length]);
+    AdvancePastResult advancePastSlowCase(const char* literal, bool lettersIgnoringASCIICase);
</ins><span class="cx"> 
</span><del>-            return;
-        }
</del><ins>+    Substring m_currentSubstring;
+    Deque&lt;Substring&gt; m_otherSubstrings;
</ins><span class="cx"> 
</span><del>-        (this-&gt;*m_advanceFunc)();
-    }
</del><ins>+    bool m_isClosed { false };
</ins><span class="cx"> 
</span><del>-    void advanceAndUpdateLineNumber()
-    {
-        if (m_fastPathFlags &amp; Use8BitAdvance) {
-            ASSERT(!m_pushedChar1);
</del><ins>+    UChar m_currentCharacter { 0 };
</ins><span class="cx"> 
</span><del>-            bool haveNewLine = (m_currentChar == '\n') &amp; !!(m_fastPathFlags &amp; Use8BitAdvanceAndUpdateLineNumbers);
-            bool haveOneCharacterLeft = (--m_currentString.m_length == 1);
</del><ins>+    unsigned m_numberOfCharactersConsumedPriorToCurrentSubstring { 0 };
+    unsigned m_numberOfCharactersConsumedPriorToCurrentLine { 0 };
+    int m_currentLine { 0 };
</ins><span class="cx"> 
</span><del>-            m_currentChar = m_currentString.incrementAndGetCurrentChar8();
</del><ins>+    unsigned char m_fastPathFlags { NoFastPath };
+    void (SegmentedString::*m_advanceWithoutUpdatingLineNumberFunction)() { &amp;SegmentedString::advanceEmpty };
+    void (SegmentedString::*m_advanceAndUpdateLineNumberFunction)() { &amp;SegmentedString::advanceEmpty };
+};
</ins><span class="cx"> 
</span><del>-            if (!(haveNewLine | haveOneCharacterLeft))
-                return;
</del><ins>+inline SegmentedString::Substring::Substring(String&amp;&amp; passedString)
+    : string(WTFMove(passedString))
+    , length(string.length())
+{
+    if (length) {
+        is8Bit = string.impl()-&gt;is8Bit();
+        if (is8Bit)
+            currentCharacter8 = string.impl()-&gt;characters8();
+        else
+            currentCharacter16 = string.impl()-&gt;characters16();
+    }
+}
</ins><span class="cx"> 
</span><del>-            if (haveNewLine) {
-                ++m_currentLine;
-                m_numberOfCharactersConsumedPriorToCurrentLine =  m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
-            }
</del><ins>+inline unsigned SegmentedString::Substring::numberOfCharactersConsumed() const
+{
+    return string.length() - length;
+}
</ins><span class="cx"> 
</span><del>-            if (haveOneCharacterLeft)
-                updateSlowCaseFunctionPointers();
</del><ins>+ALWAYS_INLINE UChar SegmentedString::Substring::currentCharacter() const
+{
+    ASSERT(length);
+    return is8Bit ? *currentCharacter8 : *currentCharacter16;
+}
</ins><span class="cx"> 
</span><del>-            return;
-        }
</del><ins>+ALWAYS_INLINE UChar SegmentedString::Substring::currentCharacterPreIncrement()
+{
+    ASSERT(length);
+    return is8Bit ? *++currentCharacter8 : *++currentCharacter16;
+}
</ins><span class="cx"> 
</span><del>-        (this-&gt;*m_advanceAndUpdateLineNumberFunc)();
</del><ins>+inline SegmentedString::SegmentedString(String&amp;&amp; string)
+    : m_currentSubstring(WTFMove(string))
+{
+    if (m_currentSubstring.length) {
+        m_currentCharacter = m_currentSubstring.currentCharacter();
+        updateAdvanceFunctionPointers();
</ins><span class="cx">     }
</span><ins>+}
</ins><span class="cx"> 
</span><del>-    void advancePastNonNewline()
-    {
-        ASSERT(currentChar() != '\n');
-        advance();
-    }
</del><ins>+inline SegmentedString::SegmentedString(const String&amp; string)
+    : SegmentedString(String { string })
+{
+}
</ins><span class="cx"> 
</span><del>-    void advancePastNewlineAndUpdateLineNumber()
-    {
-        ASSERT(currentChar() == '\n');
-        if (!m_pushedChar1 &amp;&amp; m_currentString.m_length &gt; 1) {
-            int newLineFlag = m_currentString.doNotExcludeLineNumbers();
-            m_currentLine += newLineFlag;
-            if (newLineFlag)
-                m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
-            decrementAndCheckLength();
-            m_currentChar = m_currentString.incrementAndGetCurrentChar();
-            return;
-        }
-        advanceAndUpdateLineNumberSlowCase();
-    }
</del><ins>+ALWAYS_INLINE void SegmentedString::decrementAndCheckLength()
+{
+    ASSERT(m_currentSubstring.length &gt; 1);
+    if (UNLIKELY(--m_currentSubstring.length == 1))
+        updateAdvanceFunctionPointersForSingleCharacterSubstring();
+}
</ins><span class="cx"> 
</span><del>-    int numberOfCharactersConsumed() const
-    {
-        int numberOfPushedCharacters = 0;
-        if (m_pushedChar1) {
-            ++numberOfPushedCharacters;
-            if (m_pushedChar2)
-                ++numberOfPushedCharacters;
-        }
-        return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed() - numberOfPushedCharacters;
</del><ins>+ALWAYS_INLINE void SegmentedString::advanceWithoutUpdatingLineNumber()
+{
+    if (LIKELY(m_fastPathFlags &amp; Use8BitAdvance)) {
+        m_currentCharacter = *++m_currentSubstring.currentCharacter8;
+        decrementAndCheckLength();
+        return;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    String toString() const;
</del><ins>+    (this-&gt;*m_advanceWithoutUpdatingLineNumberFunction)();
+}
</ins><span class="cx"> 
</span><del>-    UChar currentChar() const { return m_currentChar; }    
</del><ins>+inline void SegmentedString::startNewLine()
+{
+    ++m_currentLine;
+    m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed();
+}
</ins><span class="cx"> 
</span><del>-    OrdinalNumber currentColumn() const;
-    OrdinalNumber currentLine() const;
</del><ins>+inline void SegmentedString::processPossibleNewline()
+{
+    if (m_currentCharacter == '\n')
+        startNewLine();
+}
</ins><span class="cx"> 
</span><del>-    // Sets value of line/column variables. Column is specified indirectly by a parameter columnAfterProlog
-    // which is a value of column that we should get after a prolog (first prologLength characters) has been consumed.
-    void setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAfterProlog, int prologLength);
-
-private:
-    enum FastPathFlags {
-        NoFastPath = 0,
-        Use8BitAdvanceAndUpdateLineNumbers = 1 &lt;&lt; 0,
-        Use8BitAdvance = 1 &lt;&lt; 1,
-    };
-
-    void append(const SegmentedSubstring&amp;);
-    void pushBack(const SegmentedSubstring&amp;);
-
-    void advance8();
-    void advance16();
-    void advanceAndUpdateLineNumber8();
-    void advanceAndUpdateLineNumber16();
-    void advanceSlowCase();
-    void advanceAndUpdateLineNumberSlowCase();
-    void advanceEmpty();
-    void advanceSubstring();
-    
-    void updateSlowCaseFunctionPointers();
-
-    void decrementAndCheckLength()
-    {
-        ASSERT(m_currentString.m_length &gt; 1);
-        if (--m_currentString.m_length == 1)
-            updateSlowCaseFunctionPointers();
</del><ins>+inline void SegmentedString::advance()
+{
+    if (LIKELY(m_fastPathFlags &amp; Use8BitAdvance)) {
+        ASSERT(m_currentSubstring.length &gt; 1);
+        bool lastCharacterWasNewline = m_currentCharacter == '\n';
+        m_currentCharacter = *++m_currentSubstring.currentCharacter8;
+        bool haveOneCharacterLeft = --m_currentSubstring.length == 1;
+        if (LIKELY(!(lastCharacterWasNewline | haveOneCharacterLeft)))
+            return;
+        if (lastCharacterWasNewline &amp; !!(m_fastPathFlags &amp; Use8BitAdvanceAndUpdateLineNumbers))
+            startNewLine();
+        if (haveOneCharacterLeft)
+            updateAdvanceFunctionPointersForSingleCharacterSubstring();
+        return;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void updateAdvanceFunctionPointers()
-    {
-        if ((m_currentString.m_length &gt; 1) &amp;&amp; !m_pushedChar1) {
-            if (m_currentString.is8Bit()) {
-                m_advanceFunc = &amp;SegmentedString::advance8;
-                m_fastPathFlags = Use8BitAdvance;
-                if (m_currentString.doNotExcludeLineNumbers()) {
-                    m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceAndUpdateLineNumber8;
-                    m_fastPathFlags |= Use8BitAdvanceAndUpdateLineNumbers;
-                } else
-                    m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advance8;
-                return;
-            }
</del><ins>+    (this-&gt;*m_advanceAndUpdateLineNumberFunction)();
+}
</ins><span class="cx"> 
</span><del>-            m_advanceFunc = &amp;SegmentedString::advance16;
-            m_fastPathFlags = NoFastPath;
-            if (m_currentString.doNotExcludeLineNumbers())
-                m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceAndUpdateLineNumber16;
-            else
-                m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advance16;
-            return;
-        }
</del><ins>+ALWAYS_INLINE void SegmentedString::advancePastNonNewline()
+{
+    ASSERT(m_currentCharacter != '\n');
+    advanceWithoutUpdatingLineNumber();
+}
</ins><span class="cx"> 
</span><del>-        if (!m_currentString.m_length &amp;&amp; !isComposite()) {
-            m_advanceFunc = &amp;SegmentedString::advanceEmpty;
-            m_fastPathFlags = NoFastPath;
-            m_advanceAndUpdateLineNumberFunc = &amp;SegmentedString::advanceEmpty;
-        }
-
-        updateSlowCaseFunctionPointers();
</del><ins>+inline void SegmentedString::advancePastNewline()
+{
+    ASSERT(m_currentCharacter == '\n');
+    if (m_currentSubstring.length &gt; 1) {
+        if (m_currentSubstring.doNotExcludeLineNumbers)
+            startNewLine();
+        m_currentCharacter = m_currentSubstring.currentCharacterPreIncrement();
+        decrementAndCheckLength();
+        return;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Writes consumed characters into consumedCharacters, which must have space for at least |count| characters.
-    void advancePastNonNewlines(unsigned count);
-    void advancePastNonNewlines(unsigned count, UChar* consumedCharacters);
</del><ins>+    (this-&gt;*m_advanceAndUpdateLineNumberFunction)();
+}
</ins><span class="cx"> 
</span><del>-    AdvancePastResult advancePast(const char* literal, unsigned length, bool caseSensitive);
-    AdvancePastResult advancePastSlowCase(const char* literal, bool caseSensitive);
</del><ins>+inline unsigned SegmentedString::numberOfCharactersConsumed() const
+{
+    return m_numberOfCharactersConsumedPriorToCurrentSubstring + m_currentSubstring.numberOfCharactersConsumed();
+}
</ins><span class="cx"> 
</span><del>-    bool isComposite() const { return !m_substrings.isEmpty(); }
-
-    UChar m_pushedChar1;
-    UChar m_pushedChar2;
-    SegmentedSubstring m_currentString;
-    UChar m_currentChar;
-    int m_numberOfCharactersConsumedPriorToCurrentString;
-    int m_numberOfCharactersConsumedPriorToCurrentLine;
-    int m_currentLine;
-    Deque&lt;SegmentedSubstring&gt; m_substrings;
-    bool m_closed;
-    bool m_empty;
-    unsigned char m_fastPathFlags;
-    void (SegmentedString::*m_advanceFunc)();
-    void (SegmentedString::*m_advanceAndUpdateLineNumberFunc)();
-};
-
-inline void SegmentedString::advancePastNonNewlines(unsigned count)
</del><ins>+template&lt;typename CharacterType&gt; ALWAYS_INLINE bool SegmentedString::characterMismatch(CharacterType a, char b, bool lettersIgnoringASCIICase)
</ins><span class="cx"> {
</span><del>-    for (unsigned i = 0; i &lt; count; ++i)
-        advancePastNonNewline();
</del><ins>+    return lettersIgnoringASCIICase ? !isASCIIAlphaCaselessEqual(a, b) : a != b;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline SegmentedString::AdvancePastResult SegmentedString::advancePast(const char* literal, unsigned length, bool caseSensitive)
</del><ins>+template&lt;unsigned lengthIncludingTerminator, bool lettersIgnoringASCIICase&gt; SegmentedString::AdvancePastResult SegmentedString::advancePast(const char (&amp;literal)[lengthIncludingTerminator])
</ins><span class="cx"> {
</span><del>-    ASSERT(strlen(literal) == length);
</del><ins>+    constexpr unsigned length = lengthIncludingTerminator - 1;
+    ASSERT(!literal[length]);
</ins><span class="cx">     ASSERT(!strchr(literal, '\n'));
</span><del>-    if (!m_pushedChar1) {
-        if (length &lt;= static_cast&lt;unsigned&gt;(m_currentString.m_length)) {
-            if (!m_currentString.currentSubString(length).startsWith(literal, caseSensitive))
-                return DidNotMatch;
-            advancePastNonNewlines(length);
-            return DidMatch;
</del><ins>+    if (length + 1 &lt; m_currentSubstring.length) {
+        if (m_currentSubstring.is8Bit) {
+            for (unsigned i = 0; i &lt; length; ++i) {
+                if (characterMismatch(m_currentSubstring.currentCharacter8[i], literal[i], lettersIgnoringASCIICase))
+                    return DidNotMatch;
+            }
+            m_currentSubstring.currentCharacter8 += length;
+            m_currentCharacter = *m_currentSubstring.currentCharacter8;
+        } else {
+            for (unsigned i = 0; i &lt; length; ++i) {
+                if (characterMismatch(m_currentSubstring.currentCharacter16[i], literal[i], lettersIgnoringASCIICase))
+                    return DidNotMatch;
+            }
+            m_currentSubstring.currentCharacter16 += length;
+            m_currentCharacter = *m_currentSubstring.currentCharacter16;
</ins><span class="cx">         }
</span><ins>+        m_currentSubstring.length -= length;
+        return DidMatch;
</ins><span class="cx">     }
</span><del>-    return advancePastSlowCase(literal, caseSensitive);
</del><ins>+    return advancePastSlowCase(literal, lettersIgnoringASCIICase);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void SegmentedString::updateAdvanceFunctionPointers()
+{
+    if (m_currentSubstring.length &gt; 1) {
+        if (m_currentSubstring.is8Bit) {
+            m_fastPathFlags = Use8BitAdvance;
+            if (m_currentSubstring.doNotExcludeLineNumbers)
+                m_fastPathFlags |= Use8BitAdvanceAndUpdateLineNumbers;
+            return;
+        }
+        m_fastPathFlags = NoFastPath;
+        m_advanceWithoutUpdatingLineNumberFunction = &amp;SegmentedString::advanceWithoutUpdatingLineNumber16;
+        if (m_currentSubstring.doNotExcludeLineNumbers)
+            m_advanceAndUpdateLineNumberFunction = &amp;SegmentedString::advanceAndUpdateLineNumber16;
+        else
+            m_advanceAndUpdateLineNumberFunction = &amp;SegmentedString::advanceWithoutUpdatingLineNumber16;
+        return;
+    }
+
+    if (!m_currentSubstring.length) {
+        updateAdvanceFunctionPointersForEmptyString();
+        return;
+    }
+
+    updateAdvanceFunctionPointersForSingleCharacterSubstring();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+}
</ins></span></pre></div>
<a id="trunkSourceWebCorexmlparserCharacterReferenceParserInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/xml/parser/CharacterReferenceParserInlines.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -30,9 +30,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-inline void unconsumeCharacters(SegmentedString&amp; source, const StringBuilder&amp; consumedCharacters)
</del><ins>+inline void unconsumeCharacters(SegmentedString&amp; source, StringBuilder&amp; consumedCharacters)
</ins><span class="cx"> {
</span><del>-    source.pushBack(SegmentedString(consumedCharacters.toStringPreserveCapacity()));
</del><ins>+    source.pushBack(consumedCharacters.toString());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename ParserFunctions&gt;
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx">     StringBuilder consumedCharacters;
</span><span class="cx">     
</span><span class="cx">     while (!source.isEmpty()) {
</span><del>-        UChar character = source.currentChar();
</del><ins>+        UChar character = source.currentCharacter();
</ins><span class="cx">         switch (state) {
</span><span class="cx">         case Initial:
</span><span class="cx">             if (character == '\x09' || character == '\x0A' || character == '\x0C' || character == ' ' || character == '&lt;' || character == '&amp;')
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">                 state = Decimal;
</span><span class="cx">                 goto Decimal;
</span><span class="cx">             }
</span><del>-            source.pushBack(SegmentedString(ASCIILiteral(&quot;#&quot;)));
</del><ins>+            source.pushBack(ASCIILiteral(&quot;#&quot;));
</ins><span class="cx">             return false;
</span><span class="cx">         case MaybeHexLowerCaseX:
</span><span class="cx">             if (isASCIIHexDigit(character)) {
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx">                 state = Hex;
</span><span class="cx">                 goto Hex;
</span><span class="cx">             }
</span><del>-            source.pushBack(SegmentedString(ASCIILiteral(&quot;#x&quot;)));
</del><ins>+            source.pushBack(ASCIILiteral(&quot;#x&quot;));
</ins><span class="cx">             return false;
</span><span class="cx">         case MaybeHexUpperCaseX:
</span><span class="cx">             if (isASCIIHexDigit(character)) {
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">                 state = Hex;
</span><span class="cx">                 goto Hex;
</span><span class="cx">             }
</span><del>-            source.pushBack(SegmentedString(ASCIILiteral(&quot;#X&quot;)));
</del><ins>+            source.pushBack(ASCIILiteral(&quot;#X&quot;));
</ins><span class="cx">             return false;
</span><span class="cx">         case Hex:
</span><span class="cx">         Hex:
</span><span class="lines">@@ -110,7 +110,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (character == ';') {
</span><del>-                source.advance();
</del><ins>+                source.advancePastNonNewline();
</ins><span class="cx">                 decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
</span><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="lines">@@ -129,7 +129,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (character == ';') {
</span><del>-                source.advance();
</del><ins>+                source.advancePastNonNewline();
</ins><span class="cx">                 decodedCharacter.append(ParserFunctions::legalEntityFor(overflow ? 0 : result));
</span><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx">             return ParserFunctions::consumeNamedEntity(source, decodedCharacter, notEnoughCharacters, additionalAllowedCharacter, character);
</span><span class="cx">         }
</span><span class="cx">         consumedCharacters.append(character);
</span><del>-        source.advance();
</del><ins>+        source.advancePastNonNewline();
</ins><span class="cx">     }
</span><span class="cx">     ASSERT(source.isEmpty());
</span><span class="cx">     notEnoughCharacters = true;
</span></span></pre></div>
<a id="trunkSourceWebCorexmlparserMarkupTokenizerInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/parser/MarkupTokenizerInlines.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/parser/MarkupTokenizerInlines.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/xml/parser/MarkupTokenizerInlines.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008-2016 Apple Inc. All Rights Reserved.
</ins><span class="cx">  * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
</span><span class="cx">  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
</span><span class="cx">  *
</span><span class="lines">@@ -27,8 +27,6 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;SegmentedString.h&quot;
-
</del><span class="cx"> #if COMPILER(MSVC)
</span><span class="cx"> // Disable the &quot;unreachable code&quot; warning so we can compile the ASSERT_NOT_REACHED in the END_STATE macro.
</span><span class="cx"> #pragma warning(disable: 4702)
</span><span class="lines">@@ -44,7 +42,7 @@
</span><span class="cx"> #define BEGIN_STATE(stateName)                                  \
</span><span class="cx">     case stateName:                                             \
</span><span class="cx">     stateName: {                                                \
</span><del>-        const auto currentState = stateName;                    \
</del><ins>+        constexpr auto currentState = stateName;                \
</ins><span class="cx">         UNUSED_PARAM(currentState);
</span><span class="cx"> 
</span><span class="cx"> #define END_STATE()                                             \
</span><span class="lines">@@ -74,6 +72,15 @@
</span><span class="cx">         character = m_preprocessor.nextInputCharacter();        \
</span><span class="cx">         goto newState;                                          \
</span><span class="cx">     } while (false)
</span><ins>+#define ADVANCE_PAST_NON_NEWLINE_TO(newState)                   \
+    do {                                                        \
+        if (!m_preprocessor.advancePastNonNewline(source, isNullCharacterSkippingState(newState))) { \
+            m_state = newState;                                 \
+            return haveBufferedCharacterToken();                \
+        }                                                       \
+        character = m_preprocessor.nextInputCharacter();        \
+        goto newState;                                          \
+    } while (false)
</ins><span class="cx"> 
</span><span class="cx"> // For more complex cases, caller consumes the characters first and then uses this macro.
</span><span class="cx"> #define SWITCH_TO(newState)                                     \
</span></span></pre></div>
<a id="trunkSourceWebCorexmlparserXMLDocumentParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -100,7 +100,7 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void XMLDocumentParser::insert(const SegmentedString&amp;)
</del><ins>+void XMLDocumentParser::insert(SegmentedString&amp;&amp;)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="lines">@@ -107,7 +107,8 @@
</span><span class="cx"> 
</span><span class="cx"> void XMLDocumentParser::append(RefPtr&lt;StringImpl&gt;&amp;&amp; inputSource)
</span><span class="cx"> {
</span><del>-    SegmentedString source(WTFMove(inputSource));
</del><ins>+    String source { WTFMove(inputSource) };
+
</ins><span class="cx">     if (m_sawXSLTransform || !m_sawFirstElement)
</span><span class="cx">         m_originalSourceForTransform.append(source);
</span><span class="cx"> 
</span><span class="lines">@@ -119,7 +120,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    doWrite(source.toString());
</del><ins>+    doWrite(source);
</ins><span class="cx"> 
</span><span class="cx">     // After parsing, dispatch image beforeload events.
</span><span class="cx">     ImageLoader::dispatchPendingBeforeLoadEvents();
</span><span class="lines">@@ -152,7 +153,6 @@
</span><span class="cx">     return String::fromUTF8(reinterpret_cast&lt;const char*&gt;(string), size); 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> bool XMLDocumentParser::updateLeafTextNode()
</span><span class="cx"> {
</span><span class="cx">     if (isStopped())
</span></span></pre></div>
<a id="trunkSourceWebCorexmlparserXMLDocumentParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParser.h (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/parser/XMLDocumentParser.h        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParser.h        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2000 Peter Kelly (pmk@post.com)
</span><del>- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
</span><span class="cx">  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
</span><span class="cx">  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
</span><span class="lines">@@ -29,164 +29,163 @@
</span><span class="cx"> #include &quot;ScriptableDocumentParser.h&quot;
</span><span class="cx"> #include &quot;SegmentedString.h&quot;
</span><span class="cx"> #include &quot;XMLErrors.h&quot;
</span><ins>+#include &lt;libxml/tree.h&gt;
+#include &lt;libxml/xmlstring.h&gt;
</ins><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/text/AtomicStringHash.h&gt;
</span><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> 
</span><del>-#include &lt;libxml/tree.h&gt;
-#include &lt;libxml/xmlstring.h&gt;
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class ContainerNode;
</span><span class="cx"> class CachedResourceLoader;
</span><span class="cx"> class DocumentFragment;
</span><del>-class Document;
</del><span class="cx"> class Element;
</span><span class="cx"> class FrameView;
</span><span class="cx"> class PendingCallbacks;
</span><del>-class PendingScript;
</del><span class="cx"> class Text;
</span><span class="cx"> 
</span><del>-    class XMLParserContext : public RefCounted&lt;XMLParserContext&gt; {
-    public:
-        static RefPtr&lt;XMLParserContext&gt; createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString&amp; chunk);
-        static Ref&lt;XMLParserContext&gt; createStringParser(xmlSAXHandlerPtr, void* userData);
-        ~XMLParserContext();
-        xmlParserCtxtPtr context() const { return m_context; }
</del><ins>+class XMLParserContext : public RefCounted&lt;XMLParserContext&gt; {
+public:
+    static RefPtr&lt;XMLParserContext&gt; createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString&amp; chunk);
+    static Ref&lt;XMLParserContext&gt; createStringParser(xmlSAXHandlerPtr, void* userData);
+    ~XMLParserContext();
+    xmlParserCtxtPtr context() const { return m_context; }
</ins><span class="cx"> 
</span><del>-    private:
-        XMLParserContext(xmlParserCtxtPtr context)
-            : m_context(context)
-        {
-        }
-        xmlParserCtxtPtr m_context;
-    };
</del><ins>+private:
+    XMLParserContext(xmlParserCtxtPtr context)
+        : m_context(context)
+    {
+    }
+    xmlParserCtxtPtr m_context;
+};
</ins><span class="cx"> 
</span><del>-    class XMLDocumentParser final : public ScriptableDocumentParser, public PendingScriptClient {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        static Ref&lt;XMLDocumentParser&gt; create(Document&amp; document, FrameView* view)
-        {
-            return adoptRef(*new XMLDocumentParser(document, view));
-        }
-        static Ref&lt;XMLDocumentParser&gt; create(DocumentFragment&amp; fragment, Element* element, ParserContentPolicy parserContentPolicy)
-        {
-            return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy));
-        }
</del><ins>+class XMLDocumentParser final : public ScriptableDocumentParser, public PendingScriptClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static Ref&lt;XMLDocumentParser&gt; create(Document&amp; document, FrameView* view)
+    {
+        return adoptRef(*new XMLDocumentParser(document, view));
+    }
+    static Ref&lt;XMLDocumentParser&gt; create(DocumentFragment&amp; fragment, Element* element, ParserContentPolicy parserContentPolicy)
+    {
+        return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy));
+    }
</ins><span class="cx"> 
</span><del>-        ~XMLDocumentParser();
</del><ins>+    ~XMLDocumentParser();
</ins><span class="cx"> 
</span><del>-        // Exposed for callbacks:
-        void handleError(XMLErrors::ErrorType, const char* message, TextPosition);
</del><ins>+    // Exposed for callbacks:
+    void handleError(XMLErrors::ErrorType, const char* message, TextPosition);
</ins><span class="cx"> 
</span><del>-        void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; }
-        bool isXHTMLDocument() const { return m_isXHTMLDocument; }
</del><ins>+    void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; }
+    bool isXHTMLDocument() const { return m_isXHTMLDocument; }
</ins><span class="cx"> 
</span><del>-        static bool parseDocumentFragment(const String&amp;, DocumentFragment&amp;, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent);
</del><ins>+    static bool parseDocumentFragment(const String&amp;, DocumentFragment&amp;, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent);
</ins><span class="cx"> 
</span><del>-        // Used by the XMLHttpRequest to check if the responseXML was well formed.
-        bool wellFormed() const override { return !m_sawError; }
</del><ins>+    // Used by XMLHttpRequest to check if the responseXML was well formed.
+    bool wellFormed() const final { return !m_sawError; }
</ins><span class="cx"> 
</span><del>-        static bool supportsXMLVersion(const String&amp;);
</del><ins>+    static bool supportsXMLVersion(const String&amp;);
</ins><span class="cx"> 
</span><del>-    private:
-        XMLDocumentParser(Document&amp;, FrameView* = nullptr);
-        XMLDocumentParser(DocumentFragment&amp;, Element*, ParserContentPolicy);
</del><ins>+private:
+    explicit XMLDocumentParser(Document&amp;, FrameView* = nullptr);
+    XMLDocumentParser(DocumentFragment&amp;, Element*, ParserContentPolicy);
</ins><span class="cx"> 
</span><del>-        // From DocumentParser
-        void insert(const SegmentedString&amp;) override;
-        void append(RefPtr&lt;StringImpl&gt;&amp;&amp;) override;
-        void finish() override;
-        bool isWaitingForScripts() const override;
-        void stopParsing() override;
-        void detach() override;
</del><ins>+    void insert(SegmentedString&amp;&amp;) final;
+    void append(RefPtr&lt;StringImpl&gt;&amp;&amp;) final;
+    void finish() final;
+    bool isWaitingForScripts() const final;
+    void stopParsing() final;
+    void detach() final;
</ins><span class="cx"> 
</span><del>-        TextPosition textPosition() const override;
-        bool shouldAssociateConsoleMessagesWithTextPosition() const override;
</del><ins>+    TextPosition textPosition() const final;
+    bool shouldAssociateConsoleMessagesWithTextPosition() const final;
</ins><span class="cx"> 
</span><del>-        void notifyFinished(PendingScript&amp;) final;
</del><ins>+    void notifyFinished(PendingScript&amp;) final;
</ins><span class="cx"> 
</span><del>-        void end();
</del><ins>+    void end();
</ins><span class="cx"> 
</span><del>-        void pauseParsing();
-        void resumeParsing();
</del><ins>+    void pauseParsing();
+    void resumeParsing();
</ins><span class="cx"> 
</span><del>-        bool appendFragmentSource(const String&amp;);
</del><ins>+    bool appendFragmentSource(const String&amp;);
</ins><span class="cx"> 
</span><del>-    public:
-        // callbacks from parser SAX
-        void error(XMLErrors::ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0);
-        void startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
-                            const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes);
-        void endElementNs();
-        void characters(const xmlChar* s, int len);
-        void processingInstruction(const xmlChar* target, const xmlChar* data);
-        void cdataBlock(const xmlChar* s, int len);
-        void comment(const xmlChar* s);
-        void startDocument(const xmlChar* version, const xmlChar* encoding, int standalone);
-        void internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID);
-        void endDocument();
</del><ins>+public:
+    // Callbacks from parser SAX, and other functions needed inside
+    // the parser implementation, but outside this class.
</ins><span class="cx"> 
</span><del>-        bool isParsingEntityDeclaration() const { return m_isParsingEntityDeclaration; }
-        void setIsParsingEntityDeclaration(bool value) { m_isParsingEntityDeclaration = value; }
</del><ins>+    void error(XMLErrors::ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0);
+    void startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI,
+        int numNamespaces, const xmlChar** namespaces,
+        int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes);
+    void endElementNs();
+    void characters(const xmlChar*, int length);
+    void processingInstruction(const xmlChar* target, const xmlChar* data);
+    void cdataBlock(const xmlChar*, int length);
+    void comment(const xmlChar*);
+    void startDocument(const xmlChar* version, const xmlChar* encoding, int standalone);
+    void internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID);
+    void endDocument();
</ins><span class="cx"> 
</span><del>-        int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; }
-        void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; }
</del><ins>+    bool isParsingEntityDeclaration() const { return m_isParsingEntityDeclaration; }
+    void setIsParsingEntityDeclaration(bool value) { m_isParsingEntityDeclaration = value; }
</ins><span class="cx"> 
</span><del>-    private:
-        void initializeParserContext(const CString&amp; chunk = CString());
</del><ins>+    int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; }
+    void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; }
</ins><span class="cx"> 
</span><del>-        void pushCurrentNode(ContainerNode*);
-        void popCurrentNode();
-        void clearCurrentNodeStack();
</del><ins>+private:
+    void initializeParserContext(const CString&amp; chunk = CString());
</ins><span class="cx"> 
</span><del>-        void insertErrorMessageBlock();
</del><ins>+    void pushCurrentNode(ContainerNode*);
+    void popCurrentNode();
+    void clearCurrentNodeStack();
</ins><span class="cx"> 
</span><del>-        void createLeafTextNode();
-        bool updateLeafTextNode();
</del><ins>+    void insertErrorMessageBlock();
</ins><span class="cx"> 
</span><del>-        void doWrite(const String&amp;);
-        void doEnd();
</del><ins>+    void createLeafTextNode();
+    bool updateLeafTextNode();
</ins><span class="cx"> 
</span><del>-        FrameView* m_view;
</del><ins>+    void doWrite(const String&amp;);
+    void doEnd();
</ins><span class="cx"> 
</span><del>-        SegmentedString m_originalSourceForTransform;
</del><ins>+    xmlParserCtxtPtr context() const { return m_context ? m_context-&gt;context() : nullptr; };
</ins><span class="cx"> 
</span><del>-        xmlParserCtxtPtr context() const { return m_context ? m_context-&gt;context() : nullptr; };
-        RefPtr&lt;XMLParserContext&gt; m_context;
-        std::unique_ptr&lt;PendingCallbacks&gt; m_pendingCallbacks;
-        Vector&lt;xmlChar&gt; m_bufferedText;
-        int m_depthTriggeringEntityExpansion;
-        bool m_isParsingEntityDeclaration;
</del><ins>+    FrameView* m_view { nullptr };
</ins><span class="cx"> 
</span><del>-        ContainerNode* m_currentNode;
-        Vector&lt;ContainerNode*&gt; m_currentNodeStack;
</del><ins>+    SegmentedString m_originalSourceForTransform;
</ins><span class="cx"> 
</span><del>-        RefPtr&lt;Text&gt; m_leafTextNode;
</del><ins>+    RefPtr&lt;XMLParserContext&gt; m_context;
+    std::unique_ptr&lt;PendingCallbacks&gt; m_pendingCallbacks;
+    Vector&lt;xmlChar&gt; m_bufferedText;
+    int m_depthTriggeringEntityExpansion { -1 };
+    bool m_isParsingEntityDeclaration { false };
</ins><span class="cx"> 
</span><del>-        bool m_sawError;
-        bool m_sawCSS;
-        bool m_sawXSLTransform;
-        bool m_sawFirstElement;
-        bool m_isXHTMLDocument;
-        bool m_parserPaused;
-        bool m_requestingScript;
-        bool m_finishCalled;
</del><ins>+    ContainerNode* m_currentNode { nullptr };
+    Vector&lt;ContainerNode*&gt; m_currentNodeStack;
</ins><span class="cx"> 
</span><del>-        std::unique_ptr&lt;XMLErrors&gt; m_xmlErrors;
</del><ins>+    RefPtr&lt;Text&gt; m_leafTextNode;
</ins><span class="cx"> 
</span><del>-        RefPtr&lt;PendingScript&gt; m_pendingScript;
-        TextPosition m_scriptStartPosition;
</del><ins>+    bool m_sawError { false };
+    bool m_sawCSS { false };
+    bool m_sawXSLTransform { false };
+    bool m_sawFirstElement { false };
+    bool m_isXHTMLDocument { false };
+    bool m_parserPaused { false };
+    bool m_requestingScript { false };
+    bool m_finishCalled { false };
</ins><span class="cx"> 
</span><del>-        bool m_parsingFragment;
-        AtomicString m_defaultNamespaceURI;
</del><ins>+    std::unique_ptr&lt;XMLErrors&gt; m_xmlErrors;
</ins><span class="cx"> 
</span><del>-        typedef HashMap&lt;AtomicString, AtomicString&gt; PrefixForNamespaceMap;
-        PrefixForNamespaceMap m_prefixToNamespaceMap;
-        SegmentedString m_pendingSrc;
-    };
</del><ins>+    RefPtr&lt;PendingScript&gt; m_pendingScript;
+    TextPosition m_scriptStartPosition;
</ins><span class="cx"> 
</span><ins>+    bool m_parsingFragment { false };
+    AtomicString m_defaultNamespaceURI;
+
+    HashMap&lt;AtomicString, AtomicString&gt; m_prefixToNamespaceMap;
+    SegmentedString m_pendingSrc;
+};
+
</ins><span class="cx"> #if ENABLE(XSLT)
</span><span class="cx"> void* xmlDocPtrForString(CachedResourceLoader&amp;, const String&amp; source, const String&amp; url);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorexmlparserXMLDocumentParserLibxml2cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp (209057 => 209058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp        2016-11-29 02:29:41 UTC (rev 209057)
+++ trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp        2016-11-29 04:29:55 UTC (rev 209058)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2000 Peter Kelly &lt;pmk@post.com&gt;
</span><del>- * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2006 Alexey Proskuryakov &lt;ap@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2007 Samuel Weinig &lt;sam@webkit.org&gt;
</span><span class="cx">  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
</span><span class="lines">@@ -35,35 +35,23 @@
</span><span class="cx"> #include &quot;DocumentFragment.h&quot;
</span><span class="cx"> #include &quot;DocumentType.h&quot;
</span><span class="cx"> #include &quot;Frame.h&quot;
</span><del>-#include &quot;FrameLoader.h&quot;
-#include &quot;FrameView.h&quot;
</del><span class="cx"> #include &quot;HTMLEntityParser.h&quot;
</span><span class="cx"> #include &quot;HTMLHtmlElement.h&quot;
</span><del>-#include &quot;HTMLLinkElement.h&quot;
-#include &quot;HTMLNames.h&quot;
-#include &quot;HTMLStyleElement.h&quot;
</del><span class="cx"> #include &quot;HTMLTemplateElement.h&quot;
</span><del>-#include &quot;LoadableClassicScript.h&quot;
</del><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;PendingScript.h&quot;
</span><span class="cx"> #include &quot;ProcessingInstruction.h&quot;
</span><span class="cx"> #include &quot;ResourceError.h&quot;
</span><del>-#include &quot;ResourceRequest.h&quot;
</del><span class="cx"> #include &quot;ResourceResponse.h&quot;
</span><span class="cx"> #include &quot;ScriptElement.h&quot;
</span><span class="cx"> #include &quot;ScriptSourceCode.h&quot;
</span><del>-#include &quot;SecurityOrigin.h&quot;
</del><span class="cx"> #include &quot;Settings.h&quot;
</span><span class="cx"> #include &quot;StyleScope.h&quot;
</span><del>-#include &quot;TextResourceDecoder.h&quot;
</del><span class="cx"> #include &quot;TransformSource.h&quot;
</span><span class="cx"> #include &quot;XMLNSNames.h&quot;
</span><span class="cx"> #include &quot;XMLDocumentParserScope.h&quot;
</span><span class="cx"> #include &lt;libxml/parserInternals.h&gt;
</span><del>-#include &lt;wtf/Ref.h&gt;
</del><span class="cx"> #include &lt;wtf/StringExtras.h&gt;
</span><del>-#include &lt;wtf/Threading.h&gt;
-#include &lt;wtf/Vector.h&gt;
</del><span class="cx"> #include &lt;wtf/unicode/UTF8.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XSLT)
</span><span class="lines">@@ -74,32 +62,33 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XSLT)
</span><del>-static inline bool hasNoStyleInformation(Document* document)
</del><ins>+
+static inline bool shouldRenderInXMLTreeViewerMode(Document&amp; document)
</ins><span class="cx"> {
</span><del>-    if (document-&gt;sawElementsInKnownNamespaces())
</del><ins>+    if (document.sawElementsInKnownNamespaces())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (document-&gt;transformSourceDocument())
</del><ins>+    if (document.transformSourceDocument())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (!document-&gt;frame() || !document-&gt;frame()-&gt;page())
</del><ins>+    auto* frame = document.frame();
+    if (!frame)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (!document-&gt;frame()-&gt;page()-&gt;settings().developerExtrasEnabled())
</del><ins>+    if (!frame-&gt;settings().developerExtrasEnabled())
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (document-&gt;frame()-&gt;tree().parent())
</del><ins>+    if (frame-&gt;tree().parent())
</ins><span class="cx">         return false; // This document is not in a top frame
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> class PendingCallbacks {
</span><del>-    WTF_MAKE_NONCOPYABLE(PendingCallbacks); WTF_MAKE_FAST_ALLOCATED;
</del><ins>+    WTF_MAKE_FAST_ALLOCATED;
</ins><span class="cx"> public:
</span><del>-    PendingCallbacks() = default;
-
</del><span class="cx">     void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int numNamespaces, const xmlChar** namespaces, int numAttributes, int numDefaulted, const xmlChar** attributes)
</span><span class="cx">     {
</span><span class="cx">         auto callback = std::make_unique&lt;PendingStartElementNSCallback&gt;();
</span><span class="lines">@@ -575,40 +564,16 @@
</span><span class="cx"> XMLDocumentParser::XMLDocumentParser(Document&amp; document, FrameView* frameView)
</span><span class="cx">     : ScriptableDocumentParser(document)
</span><span class="cx">     , m_view(frameView)
</span><del>-    , m_context(nullptr)
</del><span class="cx">     , m_pendingCallbacks(std::make_unique&lt;PendingCallbacks&gt;())
</span><del>-    , m_depthTriggeringEntityExpansion(-1)
-    , m_isParsingEntityDeclaration(false)
</del><span class="cx">     , m_currentNode(&amp;document)
</span><del>-    , m_sawError(false)
-    , m_sawCSS(false)
-    , m_sawXSLTransform(false)
-    , m_sawFirstElement(false)
-    , m_isXHTMLDocument(false)
-    , m_parserPaused(false)
-    , m_requestingScript(false)
-    , m_finishCalled(false)
</del><span class="cx">     , m_scriptStartPosition(TextPosition::belowRangePosition())
</span><del>-    , m_parsingFragment(false)
</del><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> XMLDocumentParser::XMLDocumentParser(DocumentFragment&amp; fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
</span><span class="cx">     : ScriptableDocumentParser(fragment.document(), parserContentPolicy)
</span><del>-    , m_view(nullptr)
-    , m_context(nullptr)
</del><span class="cx">     , m_pendingCallbacks(std::make_unique&lt;PendingCallbacks&gt;())
</span><del>-    , m_depthTriggeringEntityExpansion(-1)
-    , m_isParsingEntityDeclaration(false)
</del><span class="cx">     , m_currentNode(&amp;fragment)
</span><del>-    , m_sawError(false)
-    , m_sawCSS(false)
-    , m_sawXSLTransform(false)
-    , m_sawFirstElement(false)
-    , m_isXHTMLDocument(false)
-    , m_parserPaused(false)
-    , m_requestingScript(false)
-    , m_finishCalled(false)
</del><span class="cx">     , m_scriptStartPosition(TextPosition::belowRangePosition())
</span><span class="cx">     , m_parsingFragment(true)
</span><span class="cx"> {
</span><span class="lines">@@ -1194,8 +1159,7 @@
</span><span class="cx"> static size_t convertUTF16EntityToUTF8(const UChar* utf16Entity, size_t numberOfCodeUnits, char* target, size_t targetSize)
</span><span class="cx"> {
</span><span class="cx">     const char* originalTarget = target;
</span><del>-    WTF::Unicode::ConversionResult conversionResult = WTF::Unicode::convertUTF16ToUTF8(&amp;utf16Entity,
-        utf16Entity + numberOfCodeUnits, &amp;target, target + targetSize);
</del><ins>+    auto conversionResult = WTF::Unicode::convertUTF16ToUTF8(&amp;utf16Entity, utf16Entity + numberOfCodeUnits, &amp;target, target + targetSize);
</ins><span class="cx">     if (conversionResult != WTF::Unicode::conversionOK)
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><span class="lines">@@ -1364,7 +1328,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(XSLT)
</span><del>-    bool xmlViewerMode = !m_sawError &amp;&amp; !m_sawCSS &amp;&amp; !m_sawXSLTransform &amp;&amp; hasNoStyleInformation(document());
</del><ins>+    bool xmlViewerMode = !m_sawError &amp;&amp; !m_sawCSS &amp;&amp; !m_sawXSLTransform &amp;&amp; shouldRenderInXMLTreeViewerMode(*document());
</ins><span class="cx">     if (xmlViewerMode) {
</span><span class="cx">         XMLTreeViewer xmlTreeViewer(*document());
</span><span class="cx">         xmlTreeViewer.transformDocumentToTreeView();
</span><span class="lines">@@ -1450,13 +1414,12 @@
</span><span class="cx">             return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Then, write any pending data
-    SegmentedString rest = m_pendingSrc;
-    m_pendingSrc.clear();
</del><span class="cx">     // There is normally only one string left, so toString() shouldn't copy.
</span><span class="cx">     // In any case, the XML parser runs on the main thread and it's OK if
</span><span class="cx">     // the passed string has more than one reference.
</span><del>-    append(rest.toString().impl());
</del><ins>+    auto rest = m_pendingSrc.toString();
+    m_pendingSrc.clear();
+    append(rest.impl());
</ins><span class="cx"> 
</span><span class="cx">     // Finally, if finish() has been called and write() didn't result
</span><span class="cx">     // in any further callbacks being queued, call end()
</span></span></pre>
</div>
</div>

</body>
</html>