<!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>[178313] 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/178313">178313</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-01-12 17:37:25 -0800 (Mon, 12 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add basic pattern matching support to the url filters
https://bugs.webkit.org/show_bug.cgi?id=140283

Reviewed by Andreas Kling.

Source/JavaScriptCore:

* JavaScriptCore.xcodeproj/project.pbxproj:
Make YarrParser.h private in order to use it from WebCore.

Source/WebCore:

This patch adds some basic generic pattern support for the url filters
of ContentExtensions.

Instead of writting a new parser, I re-used Gavin's parser for JavaScript
RegExp.

This patch only implements the very basic stuffs: transition on any character
and repetition.

* WebCore.xcodeproj/project.pbxproj:
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::setRuleList):
Use the new parser.

* contentextensions/DFA.cpp:
(WebCore::ContentExtensions::DFA::DFA):
(WebCore::ContentExtensions::printRange):
(WebCore::ContentExtensions::printTransition):
(WebCore::ContentExtensions::DFA::debugPrintDot):
* contentextensions/NFA.cpp:
(WebCore::ContentExtensions::printRange):
(WebCore::ContentExtensions::printTransition):
(WebCore::ContentExtensions::NFA::debugPrintDot):
The graphs generated with the extended patterns are vastly more complicated
than the old prefix matcher.
I changed the debug output to have a single link between any two nodes
instead of one per transition. This makes the graph a little more manageable.

* contentextensions/NFA.cpp:
(WebCore::ContentExtensions::NFA::addTransition):
(WebCore::ContentExtensions::NFA::addEpsilonTransition):
(WebCore::ContentExtensions::NFA::graphSize):
(WebCore::ContentExtensions::NFA::restoreToGraphSize):
* contentextensions/NFA.h:
* contentextensions/NFANode.h:
(WebCore::ContentExtensions::epsilonClosure):
The new parser can generate transitions back to the root node of index zero.
All the hash structures had to be updated to support this kind of key.

* contentextensions/NFAToDFA.cpp:
(WebCore::ContentExtensions::HashableNodeIdSetHash::hash):
Two tiny improvements:
-Don't hash zero to zero, it causes more conflicts that needed.
-The hash operation must use a commutative operation, otherwise the order
 of elements can affect the hash, which is undesired for a set.
I'll improve this further later.

(WebCore::ContentExtensions::NFAToDFA::convert):

* contentextensions/URLFilterParser.cpp: Added.
(WebCore::ContentExtensions::GraphBuilder::GraphBuilder):
(WebCore::ContentExtensions::GraphBuilder::m_lastAtom):
(WebCore::ContentExtensions::GraphBuilder::finalize):
(WebCore::ContentExtensions::GraphBuilder::errorMessage):
(WebCore::ContentExtensions::GraphBuilder::atomPatternCharacter):
(WebCore::ContentExtensions::GraphBuilder::atomBuiltInCharacterClass):
(WebCore::ContentExtensions::GraphBuilder::quantifyAtom):
(WebCore::ContentExtensions::GraphBuilder::atomBackReference):
(WebCore::ContentExtensions::GraphBuilder::atomCharacterClassAtom):
(WebCore::ContentExtensions::GraphBuilder::assertionBOL):
(WebCore::ContentExtensions::GraphBuilder::assertionEOL):
(WebCore::ContentExtensions::GraphBuilder::assertionWordBoundary):
(WebCore::ContentExtensions::GraphBuilder::atomCharacterClassBegin):
(WebCore::ContentExtensions::GraphBuilder::atomCharacterClassRange):
(WebCore::ContentExtensions::GraphBuilder::atomCharacterClassBuiltIn):
(WebCore::ContentExtensions::GraphBuilder::atomCharacterClassEnd):
(WebCore::ContentExtensions::GraphBuilder::atomParenthesesSubpatternBegin):
(WebCore::ContentExtensions::GraphBuilder::atomParentheticalAssertionBegin):
(WebCore::ContentExtensions::GraphBuilder::atomParenthesesEnd):
(WebCore::ContentExtensions::GraphBuilder::disjunction):
(WebCore::ContentExtensions::GraphBuilder::hasError):
(WebCore::ContentExtensions::GraphBuilder::fail):
(WebCore::ContentExtensions::URLFilterParser::parse):
* contentextensions/URLFilterParser.h:
(WebCore::ContentExtensions::URLFilterParser::hasError):
(WebCore::ContentExtensions::URLFilterParser::errorMessage):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionsBackendcpp">trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsDFAcpp">trunk/Source/WebCore/contentextensions/DFA.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsNFAcpp">trunk/Source/WebCore/contentextensions/NFA.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsNFAh">trunk/Source/WebCore/contentextensions/NFA.h</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsNFANodeh">trunk/Source/WebCore/contentextensions/NFANode.h</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsNFAToDFAcpp">trunk/Source/WebCore/contentextensions/NFAToDFA.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorecontentextensionsURLFilterParsercpp">trunk/Source/WebCore/contentextensions/URLFilterParser.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsURLFilterParserh">trunk/Source/WebCore/contentextensions/URLFilterParser.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-01-12  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Add basic pattern matching support to the url filters
+        https://bugs.webkit.org/show_bug.cgi?id=140283
+
+        Reviewed by Andreas Kling.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        Make YarrParser.h private in order to use it from WebCore.
+
</ins><span class="cx"> 2015-01-12  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Out of bounds read in IdentifierArena::makeIdentifier
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -968,7 +968,7 @@
</span><span class="cx">                 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */; };
</span><span class="cx">                 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8112DBA33700A9FE7B /* YarrParser.h */; settings = {ATTRIBUTES = (); }; };
</del><ins>+                86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8112DBA33700A9FE7B /* YarrParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */; };
</span><span class="cx">                 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8312DBA33700A9FE7B /* YarrPattern.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; };
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/ChangeLog        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -1,3 +1,87 @@
</span><ins>+2015-01-12  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Add basic pattern matching support to the url filters
+        https://bugs.webkit.org/show_bug.cgi?id=140283
+
+        Reviewed by Andreas Kling.
+
+        This patch adds some basic generic pattern support for the url filters
+        of ContentExtensions.
+
+        Instead of writting a new parser, I re-used Gavin's parser for JavaScript
+        RegExp.
+
+        This patch only implements the very basic stuffs: transition on any character
+        and repetition.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::setRuleList):
+        Use the new parser.
+
+        * contentextensions/DFA.cpp:
+        (WebCore::ContentExtensions::DFA::DFA):
+        (WebCore::ContentExtensions::printRange):
+        (WebCore::ContentExtensions::printTransition):
+        (WebCore::ContentExtensions::DFA::debugPrintDot):
+        * contentextensions/NFA.cpp:
+        (WebCore::ContentExtensions::printRange):
+        (WebCore::ContentExtensions::printTransition):
+        (WebCore::ContentExtensions::NFA::debugPrintDot):
+        The graphs generated with the extended patterns are vastly more complicated
+        than the old prefix matcher.
+        I changed the debug output to have a single link between any two nodes
+        instead of one per transition. This makes the graph a little more manageable.
+
+        * contentextensions/NFA.cpp:
+        (WebCore::ContentExtensions::NFA::addTransition):
+        (WebCore::ContentExtensions::NFA::addEpsilonTransition):
+        (WebCore::ContentExtensions::NFA::graphSize):
+        (WebCore::ContentExtensions::NFA::restoreToGraphSize):
+        * contentextensions/NFA.h:
+        * contentextensions/NFANode.h:
+        (WebCore::ContentExtensions::epsilonClosure):
+        The new parser can generate transitions back to the root node of index zero.
+        All the hash structures had to be updated to support this kind of key.
+
+        * contentextensions/NFAToDFA.cpp:
+        (WebCore::ContentExtensions::HashableNodeIdSetHash::hash):
+        Two tiny improvements:
+        -Don't hash zero to zero, it causes more conflicts that needed.
+        -The hash operation must use a commutative operation, otherwise the order
+         of elements can affect the hash, which is undesired for a set.
+        I'll improve this further later.
+
+        (WebCore::ContentExtensions::NFAToDFA::convert):
+
+        * contentextensions/URLFilterParser.cpp: Added.
+        (WebCore::ContentExtensions::GraphBuilder::GraphBuilder):
+        (WebCore::ContentExtensions::GraphBuilder::m_lastAtom):
+        (WebCore::ContentExtensions::GraphBuilder::finalize):
+        (WebCore::ContentExtensions::GraphBuilder::errorMessage):
+        (WebCore::ContentExtensions::GraphBuilder::atomPatternCharacter):
+        (WebCore::ContentExtensions::GraphBuilder::atomBuiltInCharacterClass):
+        (WebCore::ContentExtensions::GraphBuilder::quantifyAtom):
+        (WebCore::ContentExtensions::GraphBuilder::atomBackReference):
+        (WebCore::ContentExtensions::GraphBuilder::atomCharacterClassAtom):
+        (WebCore::ContentExtensions::GraphBuilder::assertionBOL):
+        (WebCore::ContentExtensions::GraphBuilder::assertionEOL):
+        (WebCore::ContentExtensions::GraphBuilder::assertionWordBoundary):
+        (WebCore::ContentExtensions::GraphBuilder::atomCharacterClassBegin):
+        (WebCore::ContentExtensions::GraphBuilder::atomCharacterClassRange):
+        (WebCore::ContentExtensions::GraphBuilder::atomCharacterClassBuiltIn):
+        (WebCore::ContentExtensions::GraphBuilder::atomCharacterClassEnd):
+        (WebCore::ContentExtensions::GraphBuilder::atomParenthesesSubpatternBegin):
+        (WebCore::ContentExtensions::GraphBuilder::atomParentheticalAssertionBegin):
+        (WebCore::ContentExtensions::GraphBuilder::atomParenthesesEnd):
+        (WebCore::ContentExtensions::GraphBuilder::disjunction):
+        (WebCore::ContentExtensions::GraphBuilder::hasError):
+        (WebCore::ContentExtensions::GraphBuilder::fail):
+        (WebCore::ContentExtensions::URLFilterParser::parse):
+        * contentextensions/URLFilterParser.h:
+        (WebCore::ContentExtensions::URLFilterParser::hasError):
+        (WebCore::ContentExtensions::URLFilterParser::errorMessage):
+
</ins><span class="cx"> 2015-01-11  Sam Weinig  &lt;sam@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove support for SharedWorkers
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -1027,6 +1027,8 @@
</span><span class="cx">                 267725FF1A5B3AD9003C24DD /* DFANode.h in Headers */ = {isa = PBXBuildFile; fileRef = 267725F91A5B3AD9003C24DD /* DFANode.h */; };
</span><span class="cx">                 267726001A5B3AD9003C24DD /* NFAToDFA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267725FA1A5B3AD9003C24DD /* NFAToDFA.cpp */; };
</span><span class="cx">                 267726011A5B3AD9003C24DD /* NFAToDFA.h in Headers */ = {isa = PBXBuildFile; fileRef = 267725FB1A5B3AD9003C24DD /* NFAToDFA.h */; };
</span><ins>+                267726041A5DF6F2003C24DD /* URLFilterParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267726021A5DF6F2003C24DD /* URLFilterParser.cpp */; };
+                267726051A5DF6F2003C24DD /* URLFilterParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 267726031A5DF6F2003C24DD /* URLFilterParser.h */; };
</ins><span class="cx">                 269239961505E1AA009E57FC /* JSIDBVersionChangeEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 269239921505E1AA009E57FC /* JSIDBVersionChangeEvent.h */; };
</span><span class="cx">                 269397211A4A412F00E8349D /* NFANode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2693971F1A4A412F00E8349D /* NFANode.cpp */; };
</span><span class="cx">                 269397221A4A412F00E8349D /* NFANode.h in Headers */ = {isa = PBXBuildFile; fileRef = 269397201A4A412F00E8349D /* NFANode.h */; };
</span><span class="lines">@@ -8023,6 +8025,8 @@
</span><span class="cx">                 267725F91A5B3AD9003C24DD /* DFANode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFANode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 267725FA1A5B3AD9003C24DD /* NFAToDFA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFAToDFA.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 267725FB1A5B3AD9003C24DD /* NFAToDFA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NFAToDFA.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                267726021A5DF6F2003C24DD /* URLFilterParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLFilterParser.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                267726031A5DF6F2003C24DD /* URLFilterParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLFilterParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 269239911505E1AA009E57FC /* JSIDBVersionChangeEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBVersionChangeEvent.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 269239921505E1AA009E57FC /* JSIDBVersionChangeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIDBVersionChangeEvent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2693971F1A4A412F00E8349D /* NFANode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFANode.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15332,6 +15336,8 @@
</span><span class="cx">                                 269397201A4A412F00E8349D /* NFANode.h */,
</span><span class="cx">                                 267725FA1A5B3AD9003C24DD /* NFAToDFA.cpp */,
</span><span class="cx">                                 267725FB1A5B3AD9003C24DD /* NFAToDFA.h */,
</span><ins>+                                267726021A5DF6F2003C24DD /* URLFilterParser.cpp */,
+                                267726031A5DF6F2003C24DD /* URLFilterParser.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = contentextensions;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -23990,6 +23996,7 @@
</span><span class="cx">                                 85992EBE0AA5069500AC0785 /* DOMHTMLLinkElement.h in Headers */,
</span><span class="cx">                                 85E711B80AC5D5350053270F /* DOMHTMLLinkElementInternal.h in Headers */,
</span><span class="cx">                                 85ECBEF30AA7626900544F0B /* DOMHTMLMapElement.h in Headers */,
</span><ins>+                                267726051A5DF6F2003C24DD /* URLFilterParser.h in Headers */,
</ins><span class="cx">                                 85E711B90AC5D5350053270F /* DOMHTMLMapElementInternal.h in Headers */,
</span><span class="cx">                                 BC51579F0C03BBD3008BB0EE /* DOMHTMLMarqueeElement.h in Headers */,
</span><span class="cx">                                 BC5156EA0C03B741008BB0EE /* DOMHTMLMarqueeElementInternal.h in Headers */,
</span><span class="lines">@@ -28733,6 +28740,7 @@
</span><span class="cx">                                 07B5A2DB1464320A00A81ECE /* JSTextTrackList.cpp in Sources */,
</span><span class="cx">                                 07B5A30D14687D7100A81ECE /* JSTextTrackListCustom.cpp in Sources */,
</span><span class="cx">                                 E446141A0CD6826900FADA75 /* JSTimeRanges.cpp in Sources */,
</span><ins>+                                267726041A5DF6F2003C24DD /* URLFilterParser.cpp in Sources */,
</ins><span class="cx">                                 0FDA7C16188322EB00C954B5 /* JSTouch.cpp in Sources */,
</span><span class="cx">                                 0FDA7C18188322EB00C954B5 /* JSTouchEvent.cpp in Sources */,
</span><span class="cx">                                 0FDA7C1A188322EB00C954B5 /* JSTouchList.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionsBackendcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -31,7 +31,10 @@
</span><span class="cx"> #include &quot;NFA.h&quot;
</span><span class="cx"> #include &quot;NFAToDFA.h&quot;
</span><span class="cx"> #include &quot;URL.h&quot;
</span><ins>+#include &quot;URLFilterParser.h&quot;
+#include &lt;wtf/DataLog.h&gt;
</ins><span class="cx"> #include &lt;wtf/NeverDestroyed.h&gt;
</span><ins>+#include &lt;wtf/text/CString.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -55,21 +58,18 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     NFA nfa;
</span><del>-    unsigned rootNode = nfa.root();
</del><span class="cx">     for (unsigned ruleIndex = 0; ruleIndex &lt; ruleList.size(); ++ruleIndex) {
</span><span class="cx">         const ContentExtensionRule&amp; contentExtensionRule = ruleList[ruleIndex];
</span><span class="cx">         const ContentExtensionRule::Trigger&amp; trigger = contentExtensionRule.trigger();
</span><span class="cx">         ASSERT(trigger.urlFilter.length());
</span><span class="cx"> 
</span><del>-        unsigned lastNode = rootNode;
</del><ins>+        URLFilterParser urlFilterParser;
+        urlFilterParser.parse(trigger.urlFilter, ruleIndex, nfa);
</ins><span class="cx"> 
</span><del>-        for (unsigned i = 0; i &lt; trigger.urlFilter.length(); ++i) {
-            unsigned newNode = nfa.createNode(ruleIndex);
-            nfa.addTransition(lastNode, newNode, trigger.urlFilter[i]);
-            lastNode = newNode;
</del><ins>+        if (urlFilterParser.hasError()) {
+            dataLogF(&quot;Error while parsing %s: %s&quot;, trigger.urlFilter.utf8().data(), urlFilterParser.errorMessage().utf8().data());
+            continue;
</ins><span class="cx">         }
</span><del>-
-        nfa.setFinal(lastNode);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // FIXME: never add a DFA that only matches the empty set.
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsDFAcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/DFA.cpp (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/DFA.cpp        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/DFA.cpp        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     : m_nodes(WTF::move(nodes))
</span><span class="cx">     , m_root(rootIndex)
</span><span class="cx"> {
</span><del>-    ASSERT(rootIndex &lt; nodes.size());
</del><ins>+    ASSERT(rootIndex &lt; m_nodes.size());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DFA::DFA(const DFA&amp; dfa)
</span><span class="lines">@@ -80,6 +80,62 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><ins>+static void printRange(bool firstRange, char rangeStart, char rangeEnd)
+{
+    if (!firstRange)
+        dataLogF(&quot;, &quot;);
+    if (rangeStart == rangeEnd) {
+        if (rangeStart == '&quot;' || rangeStart == '\\')
+            dataLogF(&quot;\\%c&quot;, rangeStart);
+        else if (rangeStart &gt;= '!' &amp;&amp; rangeStart &lt;= '~')
+            dataLogF(&quot;%c&quot;, rangeStart);
+        else
+            dataLogF(&quot;\\\\%d&quot;, rangeStart);
+    } else
+        dataLogF(&quot;\\\\%d-\\\\%d&quot;, rangeStart, rangeEnd);
+}
+
+static void printTransition(unsigned sourceNode, const HashMap&lt;uint16_t, unsigned&gt;&amp; transitions)
+{
+    if (transitions.isEmpty())
+        return;
+
+    HashMap&lt;unsigned, Vector&lt;uint16_t&gt;, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt; transitionsPerTarget;
+
+    // First, we build the list of transitions coming to each target node.
+    for (const auto&amp; transition : transitions) {
+        unsigned target = transition.value;
+        transitionsPerTarget.add(target, Vector&lt;uint16_t&gt;());
+
+        transitionsPerTarget.find(target)-&gt;value.append(transition.key);
+    }
+
+    // Then we go over each one an display the ranges one by one.
+    for (const auto&amp; transitionPerTarget : transitionsPerTarget) {
+        dataLogF(&quot;        %d -&gt; %d [label=\&quot;&quot;, sourceNode, transitionPerTarget.key);
+
+        Vector&lt;uint16_t&gt; incommingCharacters = transitionPerTarget.value;
+        std::sort(incommingCharacters.begin(), incommingCharacters.end());
+
+        char rangeStart = incommingCharacters.first();
+        char rangeEnd = rangeStart;
+        bool first = true;
+        for (unsigned sortedTransitionIndex = 1; sortedTransitionIndex &lt; incommingCharacters.size(); ++sortedTransitionIndex) {
+            char nextChar = incommingCharacters[sortedTransitionIndex];
+            if (nextChar == rangeEnd+1) {
+                rangeEnd = nextChar;
+                continue;
+            }
+            printRange(first, rangeStart, rangeEnd);
+            rangeStart = rangeEnd = nextChar;
+            first = false;
+        }
+        printRange(first, rangeStart, rangeEnd);
+
+        dataLogF(&quot;\&quot;];\n&quot;);
+    }
+}
+
</ins><span class="cx"> void DFA::debugPrintDot() const
</span><span class="cx"> {
</span><span class="cx">     dataLogF(&quot;digraph DFA_Transitions {\n&quot;);
</span><span class="lines">@@ -117,10 +173,9 @@
</span><span class="cx">     dataLogF(&quot;    }\n&quot;);
</span><span class="cx"> 
</span><span class="cx">     dataLogF(&quot;    {\n&quot;);
</span><del>-    for (unsigned i = 0; i &lt; m_nodes.size(); ++i) {
-        for (const auto&amp; slot : m_nodes[i].transitions)
-            dataLogF(&quot;        %d -&gt; %d [label=\&quot;%c\&quot;];\n&quot;, i, slot.value, slot.key);
-    }
</del><ins>+    for (unsigned i = 0; i &lt; m_nodes.size(); ++i)
+        printTransition(i, m_nodes[i].transitions);
+
</ins><span class="cx">     dataLogF(&quot;    }\n&quot;);
</span><span class="cx">     dataLogF(&quot;}\n&quot;);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsNFAcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/NFA.cpp (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/NFA.cpp        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/NFA.cpp        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">     ASSERT(to &lt; m_nodes.size());
</span><span class="cx">     ASSERT(character);
</span><span class="cx"> 
</span><del>-    auto addResult = m_nodes[from].transitions.add(character, HashSet&lt;unsigned&gt;());
</del><ins>+    auto addResult = m_nodes[from].transitions.add(character, HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;());
</ins><span class="cx">     addResult.iterator-&gt;value.add(to);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">     ASSERT(from &lt; m_nodes.size());
</span><span class="cx">     ASSERT(to &lt; m_nodes.size());
</span><span class="cx"> 
</span><del>-    auto addResult = m_nodes[from].transitions.add(epsilonTransitionCharacter, HashSet&lt;unsigned&gt;());
</del><ins>+    auto addResult = m_nodes[from].transitions.add(epsilonTransitionCharacter, HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;());
</ins><span class="cx">     addResult.iterator-&gt;value.add(to);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -72,7 +72,79 @@
</span><span class="cx">     m_nodes[node].isFinal = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned NFA::graphSize() const
+{
+    return m_nodes.size();
+}
+
+void NFA::restoreToGraphSize(unsigned size)
+{
+    ASSERT(size &gt; 1);
+    ASSERT(size &lt;= graphSize());
+
+    m_nodes.shrink(size);
+}
+
</ins><span class="cx"> #ifndef NDEBUG
</span><ins>+
+static void printRange(bool firstRange, uint16_t rangeStart, uint16_t rangeEnd, uint16_t epsilonTransitionCharacter)
+{
+    if (!firstRange)
+        dataLogF(&quot;, &quot;);
+    if (rangeStart == rangeEnd) {
+        if (rangeStart == epsilonTransitionCharacter)
+            dataLogF(&quot;ɛ&quot;);
+        else if (rangeStart == '&quot;' || rangeStart == '\\')
+            dataLogF(&quot;\\%c&quot;, rangeStart);
+        else if (rangeStart &gt;= '!' &amp;&amp; rangeStart &lt;= '~')
+            dataLogF(&quot;%c&quot;, rangeStart);
+        else
+            dataLogF(&quot;\\\\%d&quot;, rangeStart);
+    } else {
+        if (rangeStart == 1 &amp;&amp; rangeEnd == 127)
+            dataLogF(&quot;[any input]&quot;);
+        else
+            dataLogF(&quot;\\\\%d-\\\\%d&quot;, rangeStart, rangeEnd);
+    }
+}
+
+static void printTransition(unsigned sourceNode, const HashMap&lt;uint16_t, HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&gt;&amp; transitions, uint16_t epsilonTransitionCharacter)
+{
+    HashMap&lt;unsigned, HashSet&lt;uint16_t&gt;, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt; transitionsPerTarget;
+
+    for (const auto&amp; transition : transitions) {
+        for (unsigned targetNode : transition.value) {
+            transitionsPerTarget.add(targetNode, HashSet&lt;uint16_t&gt;());
+            transitionsPerTarget.find(targetNode)-&gt;value.add(transition.key);
+        }
+    }
+
+    for (const auto&amp; transitionPerTarget : transitionsPerTarget) {
+        dataLogF(&quot;        %d -&gt; %d [label=\&quot;&quot;, sourceNode, transitionPerTarget.key);
+
+        Vector&lt;uint16_t&gt; incommingCharacters;
+        copyToVector(transitionPerTarget.value, incommingCharacters);
+        std::sort(incommingCharacters.begin(), incommingCharacters.end());
+
+        uint16_t rangeStart = incommingCharacters.first();
+        uint16_t rangeEnd = rangeStart;
+        bool first = true;
+        for (unsigned sortedTransitionIndex = 1; sortedTransitionIndex &lt; incommingCharacters.size(); ++sortedTransitionIndex) {
+            uint16_t nextChar = incommingCharacters[sortedTransitionIndex];
+            if (nextChar == rangeEnd+1) {
+                rangeEnd = nextChar;
+                continue;
+            }
+            printRange(first, rangeStart, rangeEnd, epsilonTransitionCharacter);
+            rangeStart = rangeEnd = nextChar;
+            first = false;
+        }
+        printRange(first, rangeStart, rangeEnd, epsilonTransitionCharacter);
+
+        dataLogF(&quot;\&quot;];\n&quot;);
+    }
+}
+
</ins><span class="cx"> void NFA::debugPrintDot() const
</span><span class="cx"> {
</span><span class="cx">     dataLogF(&quot;digraph NFA_Transitions {\n&quot;);
</span><span class="lines">@@ -93,16 +165,8 @@
</span><span class="cx">     dataLogF(&quot;    }\n&quot;);
</span><span class="cx"> 
</span><span class="cx">     dataLogF(&quot;    {\n&quot;);
</span><del>-    for (unsigned i = 0; i &lt; m_nodes.size(); ++i) {
-        for (const auto&amp; slot : m_nodes[i].transitions) {
-            for (unsigned nextState : slot.value) {
-                if (slot.key == epsilonTransitionCharacter)
-                    dataLogF(&quot;        %d -&gt; %d [label=\&quot;ɛ\&quot;];\n&quot;, i, nextState);
-                else
-                    dataLogF(&quot;        %d -&gt; %d [label=\&quot;%c\&quot;];\n&quot;, i, nextState, slot.key);
-            }
-        }
-    }
</del><ins>+    for (unsigned i = 0; i &lt; m_nodes.size(); ++i)
+        printTransition(i, m_nodes[i].transitions, epsilonTransitionCharacter);
</ins><span class="cx">     dataLogF(&quot;    }\n&quot;);
</span><span class="cx">     dataLogF(&quot;}\n&quot;);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsNFAh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/NFA.h (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/NFA.h        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/NFA.h        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -50,6 +50,9 @@
</span><span class="cx">     void addEpsilonTransition(unsigned from, unsigned to);
</span><span class="cx">     void setFinal(unsigned node);
</span><span class="cx"> 
</span><ins>+    unsigned graphSize() const;
+    void restoreToGraphSize(unsigned);
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx">     void debugPrintDot() const;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsNFANodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/NFANode.h (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/NFANode.h        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/NFANode.h        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> public:
</span><span class="cx">     NFANode(uint64_t ruleId);
</span><span class="cx"> 
</span><del>-    HashMap&lt;uint16_t, HashSet&lt;unsigned&gt;&gt; transitions;
</del><ins>+    HashMap&lt;uint16_t, HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&gt; transitions;
</ins><span class="cx">     bool isFinal;
</span><span class="cx">     const uint64_t ruleId;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsNFAToDFAcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/NFAToDFA.cpp (178312 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/NFAToDFA.cpp        2015-01-13 01:20:35 UTC (rev 178312)
+++ trunk/Source/WebCore/contentextensions/NFAToDFA.cpp        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">             const NFANode&amp; node = graph[nodeId];
</span><span class="cx">             auto epsilonTransitionSlot = node.transitions.find(epsilonTransitionCharacter);
</span><span class="cx">             if (epsilonTransitionSlot != node.transitions.end()) {
</span><del>-                const HashSet&lt;unsigned&gt;&amp; targets = epsilonTransitionSlot-&gt;value;
</del><ins>+                const HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&amp; targets = epsilonTransitionSlot-&gt;value;
</ins><span class="cx">                 for (unsigned targetNodeId : targets) {
</span><span class="cx">                     if (!outputNodeSet.contains(targetNodeId))
</span><span class="cx">                         nextGenerationDiscoveredNodes.add(targetNodeId);
</span><span class="lines">@@ -148,9 +148,9 @@
</span><span class="cx"> struct HashableNodeIdSetHash {
</span><span class="cx">     static unsigned hash(const HashableNodeIdSet&amp; p)
</span><span class="cx">     {
</span><del>-        unsigned hash = 0;
</del><ins>+        unsigned hash = 4207445155;
</ins><span class="cx">         for (unsigned nodeId : p.nodeIdSet())
</span><del>-            hash ^= DefaultHash&lt;unsigned&gt;::Hash::hash(nodeId);
</del><ins>+            hash += DefaultHash&lt;unsigned&gt;::Hash::hash(nodeId);
</ins><span class="cx">         return hash;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -212,7 +212,7 @@
</span><span class="cx">     do {
</span><span class="cx">         HashableNodeIdSet stateSet = unprocessedStateSets.takeAny();
</span><span class="cx"> 
</span><del>-        ASSERT(!processedStateSets.contains(stateSet));
</del><ins>+        ASSERT(!processedStateSets.contains(stateSet.nodeIdSet()));
</ins><span class="cx">         processedStateSets.add(stateSet.nodeIdSet());
</span><span class="cx"> 
</span><span class="cx">         unsigned dfaNodeId = nfaToDFANodeMap.get(stateSet);
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsURLFilterParsercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/contentextensions/URLFilterParser.cpp (0 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/URLFilterParser.cpp                                (rev 0)
+++ trunk/Source/WebCore/contentextensions/URLFilterParser.cpp        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -0,0 +1,245 @@
</span><ins>+/*
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;URLFilterParser.h&quot;
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include &quot;NFA.h&quot;
+#include &lt;JavaScriptCore/YarrParser.h&gt;
+
+namespace WebCore {
+
+namespace ContentExtensions {
+
+class GraphBuilder {
+private:
+    struct BoundedSubGraph {
+        unsigned start;
+        unsigned end;
+    };
+public:
+    GraphBuilder(NFA&amp; nfa, uint64_t patternId)
+        : m_nfa(nfa)
+        , m_patternId(patternId)
+        , m_activeGroup({ nfa.root(), nfa.root() })
+        , m_lastAtom(m_activeGroup)
+    {
+    }
+
+    void finalize()
+    {
+        if (hasError())
+            return;
+        if (m_activeGroup.start != m_activeGroup.end)
+            m_nfa.setFinal(m_activeGroup.end);
+        else
+            fail(ASCIILiteral(&quot;The pattern cannot match anything.&quot;));
+    }
+
+    const String&amp; errorMessage() const
+    {
+        return m_errorMessage;
+    }
+
+    void atomPatternCharacter(UChar character)
+    {
+        if (isASCII(character)) {
+            fail(ASCIILiteral(&quot;Only ASCII characters are supported in pattern.&quot;));
+            return;
+        }
+
+        if (hasError())
+            return;
+
+        m_hasValidAtom = true;
+        unsigned newEnd = m_nfa.createNode(m_patternId);
+        m_nfa.addTransition(m_lastAtom.end, newEnd, static_cast&lt;char&gt;(character));
+        m_lastAtom.start = m_lastAtom.end;
+        m_lastAtom.end = newEnd;
+        m_activeGroup.end = m_lastAtom.end;
+    }
+
+    void atomBuiltInCharacterClass(JSC::Yarr::BuiltInCharacterClassID builtInCharacterClassID, bool inverted)
+    {
+        if (hasError())
+            return;
+
+        if (builtInCharacterClassID == JSC::Yarr::NewlineClassID &amp;&amp; inverted) {
+            // FIXME: handle new line properly.
+            m_hasValidAtom = true;
+            unsigned newEnd = m_nfa.createNode(m_patternId);
+            for (unsigned i = 1; i &lt; 128; ++i)
+                m_nfa.addTransition(m_lastAtom.end, newEnd, i);
+            m_lastAtom.start = m_lastAtom.end;
+            m_lastAtom.end = newEnd;
+            m_activeGroup.end = m_lastAtom.end;
+        } else
+            fail(ASCIILiteral(&quot;Character class is not supported.&quot;));
+    }
+
+    void quantifyAtom(unsigned minimum, unsigned maximum, bool)
+    {
+        if (hasError())
+            return;
+
+        ASSERT(m_hasValidAtom);
+        if (!m_hasValidAtom) {
+            fail(ASCIILiteral(&quot;Quantifier without corresponding atom to quantify.&quot;));
+            return;
+        }
+
+        if (!minimum &amp;&amp; maximum == 1)
+            m_nfa.addEpsilonTransition(m_lastAtom.start, m_lastAtom.end);
+        else if (!minimum &amp;&amp; maximum == JSC::Yarr::quantifyInfinite) {
+            m_nfa.addEpsilonTransition(m_lastAtom.start, m_lastAtom.end);
+            m_nfa.addEpsilonTransition(m_lastAtom.end, m_lastAtom.start);
+        } else if (minimum == 1 &amp;&amp; maximum == JSC::Yarr::quantifyInfinite)
+            m_nfa.addEpsilonTransition(m_lastAtom.end, m_lastAtom.start);
+        else
+            fail(ASCIILiteral(&quot;Arbitrary atom repetitions are not supported.&quot;));
+    }
+
+    NO_RETURN_DUE_TO_ASSERT void atomBackReference(unsigned)
+    {
+        fail(ASCIILiteral(&quot;Patterns cannot contain backreferences.&quot;));
+        ASSERT_NOT_REACHED();
+    }
+
+    void atomCharacterClassAtom(UChar)
+    {
+        fail(ASCIILiteral(&quot;Character class atoms are not supported yet.&quot;));
+    }
+
+    void assertionBOL()
+    {
+        fail(ASCIILiteral(&quot;Line boundary assertions are not supported yet.&quot;));
+    }
+
+    void assertionEOL()
+    {
+        fail(ASCIILiteral(&quot;Line boundary assertions are not supported yet.&quot;));
+    }
+
+    void assertionWordBoundary(bool)
+    {
+        fail(ASCIILiteral(&quot;Word boundaries assertions are not supported yet.&quot;));
+    }
+
+    void atomCharacterClassBegin(bool = false)
+    {
+        fail(ASCIILiteral(&quot;Character class atoms are not supported yet.&quot;));
+    }
+
+    void atomCharacterClassRange(UChar, UChar)
+    {
+        fail(ASCIILiteral(&quot;Character class ranges are not supported yet.&quot;));
+    }
+
+    void atomCharacterClassBuiltIn(JSC::Yarr::BuiltInCharacterClassID, bool)
+    {
+        fail(ASCIILiteral(&quot;Buildins character class atoms are not supported yet.&quot;));
+    }
+
+    void atomCharacterClassEnd()
+    {
+        fail(ASCIILiteral(&quot;Character class are not supported yet.&quot;));
+    }
+
+    void atomParenthesesSubpatternBegin(bool = true)
+    {
+        fail(ASCIILiteral(&quot;Groups are not supported yet.&quot;));
+    }
+
+    void atomParentheticalAssertionBegin(bool = false)
+    {
+        fail(ASCIILiteral(&quot;Groups are not supported yet.&quot;));
+    }
+
+    void atomParenthesesEnd()
+    {
+        fail(ASCIILiteral(&quot;Groups are not supported yet.&quot;));
+    }
+
+    void disjunction()
+    {
+        fail(ASCIILiteral(&quot;Disjunctions are not supported yet.&quot;));
+    }
+
+
+private:
+    bool hasError() const
+    {
+        return !m_errorMessage.isNull();
+    }
+
+    void fail(const String&amp; errorMessage)
+    {
+        if (hasError())
+            return;
+        m_errorMessage = errorMessage;
+    }
+
+    NFA&amp; m_nfa;
+    const uint64_t m_patternId;
+
+    BoundedSubGraph m_activeGroup;
+
+    bool m_hasValidAtom = false;
+    BoundedSubGraph m_lastAtom;
+
+    String m_errorMessage;
+};
+
+void URLFilterParser::parse(const String&amp; pattern, uint64_t patternId, NFA&amp; nfa)
+{
+    if (!pattern.containsOnlyASCII())
+        m_errorMessage = ASCIILiteral(&quot;URLFilterParser only supports ASCII patterns.&quot;);
+    ASSERT(!pattern.isEmpty());
+
+    if (pattern.isEmpty())
+        return;
+
+    unsigned oldSize = nfa.graphSize();
+
+    GraphBuilder graphBuilder(nfa, patternId);
+    const char* error = JSC::Yarr::parse(graphBuilder, pattern, 0);
+    if (error)
+        m_errorMessage = String(error);
+    else
+        graphBuilder.finalize();
+
+    if (!error)
+        m_errorMessage = graphBuilder.errorMessage();
+
+    if (hasError())
+        nfa.restoreToGraphSize(oldSize);
+}
+
+} // namespace ContentExtensions
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
</ins></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsURLFilterParserh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/contentextensions/URLFilterParser.h (0 => 178313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/URLFilterParser.h                                (rev 0)
+++ trunk/Source/WebCore/contentextensions/URLFilterParser.h        2015-01-13 01:37:25 UTC (rev 178313)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+/*
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef URLFilterParser_h
+#define URLFilterParser_h
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+namespace ContentExtensions {
+
+class NFA;
+
+class URLFilterParser {
+public:
+    void parse(const String&amp; pattern, uint64_t patternId, NFA&amp;);
+
+    bool hasError() const { return !m_errorMessage.isNull(); }
+    String errorMessage() const { return m_errorMessage; }
+
+private:
+    struct BoundedSubGraph {
+        unsigned start;
+        unsigned end;
+    };
+
+    String m_errorMessage;
+};
+
+} // namespace ContentExtensions
+
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
+
+#endif // URLFilterParser_h
</ins></span></pre>
</div>
</div>

</body>
</html>