<!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>[213322] trunk/Source/WebCore</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/213322">213322</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2017-03-02 16:18:44 -0800 (Thu, 02 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Modernize ContentExtensionParser
https://bugs.webkit.org/show_bug.cgi?id=169106

Reviewed by Andy Estes.

We were returning std::error_code and passing the return value as a parameter reference.
because we wrote this code before we had WTF::Expected.

No change in behavior, verified by many API tests.

* contentextensions/ContentExtensionCompiler.cpp:
(WebCore::ContentExtensions::compileRuleList):
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::getDomainList):
(WebCore::ContentExtensions::loadTrigger):
(WebCore::ContentExtensions::loadAction):
(WebCore::ContentExtensions::loadRule):
(WebCore::ContentExtensions::loadEncodedRules):
(WebCore::ContentExtensions::parseRuleList):
* contentextensions/ContentExtensionParser.h:
* contentextensions/ContentExtensionRule.cpp:
(WebCore::ContentExtensions::ContentExtensionRule::ContentExtensionRule):
* contentextensions/ContentExtensionRule.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionCompilercpp">trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionParsercpp">trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionParserh">trunk/Source/WebCore/contentextensions/ContentExtensionParser.h</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionRulecpp">trunk/Source/WebCore/contentextensions/ContentExtensionRule.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionRuleh">trunk/Source/WebCore/contentextensions/ContentExtensionRule.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/ChangeLog        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2017-03-02  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Modernize ContentExtensionParser
+        https://bugs.webkit.org/show_bug.cgi?id=169106
+
+        Reviewed by Andy Estes.
+
+        We were returning std::error_code and passing the return value as a parameter reference.
+        because we wrote this code before we had WTF::Expected.
+
+        No change in behavior, verified by many API tests.
+
+        * contentextensions/ContentExtensionCompiler.cpp:
+        (WebCore::ContentExtensions::compileRuleList):
+        * contentextensions/ContentExtensionParser.cpp:
+        (WebCore::ContentExtensions::getDomainList):
+        (WebCore::ContentExtensions::loadTrigger):
+        (WebCore::ContentExtensions::loadAction):
+        (WebCore::ContentExtensions::loadRule):
+        (WebCore::ContentExtensions::loadEncodedRules):
+        (WebCore::ContentExtensions::parseRuleList):
+        * contentextensions/ContentExtensionParser.h:
+        * contentextensions/ContentExtensionRule.cpp:
+        (WebCore::ContentExtensions::ContentExtensionRule::ContentExtensionRule):
+        * contentextensions/ContentExtensionRule.h:
+
</ins><span class="cx"> 2017-03-02  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r213301.
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -205,13 +205,12 @@
</span><span class="cx">     root.setActions(actionsStart, static_cast&lt;uint16_t&gt;(actionsLength));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::error_code compileRuleList(ContentExtensionCompilationClient&amp; client, String&amp;&amp; ruleList)
</del><ins>+std::error_code compileRuleList(ContentExtensionCompilationClient&amp; client, String&amp;&amp; ruleJSON)
</ins><span class="cx"> {
</span><del>-    Vector&lt;ContentExtensionRule&gt; parsedRuleList;
-    auto parserError = parseRuleList(ruleList, parsedRuleList);
-    ruleList = String();
-    if (parserError)
-        return parserError;
</del><ins>+    auto ruleList = parseRuleList(WTFMove(ruleJSON));
+    if (!ruleList.hasValue())
+        return ruleList.error();
+    Vector&lt;ContentExtensionRule&gt; parsedRuleList = WTFMove(ruleList.value());
</ins><span class="cx"> 
</span><span class="cx"> #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
</span><span class="cx">     double patternPartitioningStart = monotonicallyIncreasingTime();
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionParser.cpp        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &lt;JavaScriptCore/JSONObject.h&gt;
</span><span class="cx"> #include &lt;JavaScriptCore/VM.h&gt;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><ins>+#include &lt;wtf/Expected.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="lines">@@ -58,31 +59,31 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-static std::error_code getDomainList(ExecState&amp; exec, const JSObject* arrayObject, Vector&lt;String&gt;&amp; vector)
</del><ins>+static Expected&lt;Vector&lt;String&gt;, std::error_code&gt; getDomainList(ExecState&amp; exec, const JSObject* arrayObject)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec.vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    ASSERT(vector.isEmpty());
</del><span class="cx">     if (!arrayObject || !isJSArray(arrayObject))
</span><del>-        return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">     const JSArray* array = jsCast&lt;const JSArray*&gt;(arrayObject);
</span><span class="cx">     
</span><ins>+    Vector&lt;String&gt; domains;
</ins><span class="cx">     unsigned length = array-&gt;length();
</span><span class="cx">     for (unsigned i = 0; i &lt; length; ++i) {
</span><span class="cx">         const JSValue value = array-&gt;getIndex(&amp;exec, i);
</span><span class="cx">         if (scope.exception() || !value.isString())
</span><del>-            return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">         
</span><span class="cx">         // Domains should be punycode encoded lower case.
</span><span class="cx">         const String&amp; domain = asString(value)-&gt;value(&amp;exec);
</span><span class="cx">         if (domain.isEmpty())
</span><del>-            return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">         if (!containsOnlyASCIIWithNoUppercase(domain))
</span><del>-            return ContentExtensionError::JSONDomainNotLowerCaseASCII;
-        vector.append(domain);
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONDomainNotLowerCaseASCII);
+        domains.append(domain);
</ins><span class="cx">     }
</span><del>-    return { };
</del><ins>+    return WTFMove(domains);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static std::error_code getTypeFlags(ExecState&amp; exec, const JSValue&amp; typeValue, ResourceFlags&amp; flags, uint16_t (*stringToType)(const String&amp;))
</span><span class="lines">@@ -117,7 +118,7 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-static std::error_code loadTrigger(ExecState&amp; exec, const JSObject&amp; ruleObject, Trigger&amp; trigger)
</del><ins>+static Expected&lt;Trigger, std::error_code&gt; loadTrigger(ExecState&amp; exec, const JSObject&amp; ruleObject)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec.vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -124,16 +125,17 @@
</span><span class="cx"> 
</span><span class="cx">     const JSValue triggerObject = ruleObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;trigger&quot;));
</span><span class="cx">     if (!triggerObject || scope.exception() || !triggerObject.isObject())
</span><del>-        return ContentExtensionError::JSONInvalidTrigger;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidTrigger);
</ins><span class="cx">     
</span><span class="cx">     const JSValue urlFilterObject = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;url-filter&quot;));
</span><span class="cx">     if (!urlFilterObject || scope.exception() || !urlFilterObject.isString())
</span><del>-        return ContentExtensionError::JSONInvalidURLFilterInTrigger;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidURLFilterInTrigger);
</ins><span class="cx"> 
</span><span class="cx">     String urlFilter = asString(urlFilterObject)-&gt;value(&amp;exec);
</span><span class="cx">     if (urlFilter.isEmpty())
</span><del>-        return ContentExtensionError::JSONInvalidURLFilterInTrigger;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidURLFilterInTrigger);
</ins><span class="cx"> 
</span><ins>+    Trigger trigger;
</ins><span class="cx">     trigger.urlFilter = urlFilter;
</span><span class="cx"> 
</span><span class="cx">     const JSValue urlFilterCaseValue = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;url-filter-is-case-sensitive&quot;));
</span><span class="lines">@@ -144,44 +146,46 @@
</span><span class="cx">     if (!scope.exception() &amp;&amp; resourceTypeValue.isObject()) {
</span><span class="cx">         auto typeFlagsError = getTypeFlags(exec, resourceTypeValue, trigger.flags, readResourceType);
</span><span class="cx">         if (typeFlagsError)
</span><del>-            return typeFlagsError;
</del><ins>+            return makeUnexpected(typeFlagsError);
</ins><span class="cx">     } else if (!resourceTypeValue.isUndefined())
</span><del>-        return ContentExtensionError::JSONInvalidTriggerFlagsArray;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidTriggerFlagsArray);
</ins><span class="cx"> 
</span><span class="cx">     const JSValue loadTypeValue = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;load-type&quot;));
</span><span class="cx">     if (!scope.exception() &amp;&amp; loadTypeValue.isObject()) {
</span><span class="cx">         auto typeFlagsError = getTypeFlags(exec, loadTypeValue, trigger.flags, readLoadType);
</span><span class="cx">         if (typeFlagsError)
</span><del>-            return typeFlagsError;
</del><ins>+            return makeUnexpected(typeFlagsError);
</ins><span class="cx">     } else if (!loadTypeValue.isUndefined())
</span><del>-        return ContentExtensionError::JSONInvalidTriggerFlagsArray;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidTriggerFlagsArray);
</ins><span class="cx"> 
</span><del>-    const JSValue ifDomain = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;if-domain&quot;));
-    if (!scope.exception() &amp;&amp; ifDomain.isObject()) {
-        auto ifDomainError = getDomainList(exec, asObject(ifDomain), trigger.domains);
-        if (ifDomainError)
-            return ifDomainError;
</del><ins>+    const JSValue ifDomainValue = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;if-domain&quot;));
+    if (!scope.exception() &amp;&amp; ifDomainValue.isObject()) {
+        auto ifDomain = getDomainList(exec, asObject(ifDomainValue));
+        if (!ifDomain.hasValue())
+            return makeUnexpected(ifDomain.error());
+        trigger.domains = WTFMove(ifDomain.value());
</ins><span class="cx">         if (trigger.domains.isEmpty())
</span><del>-            return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">         ASSERT(trigger.domainCondition == Trigger::DomainCondition::None);
</span><span class="cx">         trigger.domainCondition = Trigger::DomainCondition::IfDomain;
</span><del>-    } else if (!ifDomain.isUndefined())
-        return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+    } else if (!ifDomainValue.isUndefined())
+        return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">     
</span><del>-    const JSValue unlessDomain = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;unless-domain&quot;));
-    if (!scope.exception() &amp;&amp; unlessDomain.isObject()) {
</del><ins>+    const JSValue unlessDomainValue = triggerObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;unless-domain&quot;));
+    if (!scope.exception() &amp;&amp; unlessDomainValue.isObject()) {
</ins><span class="cx">         if (trigger.domainCondition != Trigger::DomainCondition::None)
</span><del>-            return ContentExtensionError::JSONUnlessAndIfDomain;
-        auto unlessDomainError = getDomainList(exec, asObject(unlessDomain), trigger.domains);
-        if (unlessDomainError)
-            return unlessDomainError;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONUnlessAndIfDomain);
+        auto unlessDomain = getDomainList(exec, asObject(unlessDomainValue));
+        if (!unlessDomain.hasValue())
+            return makeUnexpected(unlessDomain.error());
+        trigger.domains = WTFMove(unlessDomain.value());
</ins><span class="cx">         if (trigger.domains.isEmpty())
</span><del>-            return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx">         trigger.domainCondition = Trigger::DomainCondition::UnlessDomain;
</span><del>-    } else if (!unlessDomain.isUndefined())
-        return ContentExtensionError::JSONInvalidDomainList;
</del><ins>+    } else if (!unlessDomainValue.isUndefined())
+        return makeUnexpected(ContentExtensionError::JSONInvalidDomainList);
</ins><span class="cx"> 
</span><del>-    return { };
</del><ins>+    return WTFMove(trigger);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool isValidSelector(const String&amp; selector)
</span><span class="lines">@@ -193,114 +197,109 @@
</span><span class="cx">     return selectorList.isValid();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::error_code loadAction(ExecState&amp; exec, const JSObject&amp; ruleObject, Action&amp; action, bool&amp; validSelector)
</del><ins>+static Expected&lt;std::optional&lt;Action&gt;, std::error_code&gt; loadAction(ExecState&amp; exec, const JSObject&amp; ruleObject)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec.vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    validSelector = true;
</del><span class="cx">     const JSValue actionObject = ruleObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;action&quot;));
</span><span class="cx">     if (!actionObject || scope.exception() || !actionObject.isObject())
</span><del>-        return ContentExtensionError::JSONInvalidAction;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidAction);
</ins><span class="cx"> 
</span><span class="cx">     const JSValue typeObject = actionObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;type&quot;));
</span><span class="cx">     if (!typeObject || scope.exception() || !typeObject.isString())
</span><del>-        return ContentExtensionError::JSONInvalidActionType;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalidActionType);
</ins><span class="cx"> 
</span><span class="cx">     String actionType = asString(typeObject)-&gt;value(&amp;exec);
</span><span class="cx"> 
</span><span class="cx">     if (actionType == &quot;block&quot;)
</span><del>-        action = ActionType::BlockLoad;
-    else if (actionType == &quot;ignore-previous-rules&quot;)
-        action = ActionType::IgnorePreviousRules;
-    else if (actionType == &quot;block-cookies&quot;)
-        action = ActionType::BlockCookies;
-    else if (actionType == &quot;css-display-none&quot;) {
</del><ins>+        return {{ActionType::BlockLoad}};
+    if (actionType == &quot;ignore-previous-rules&quot;)
+        return {{ActionType::IgnorePreviousRules}};
+    if (actionType == &quot;block-cookies&quot;)
+        return {{ActionType::BlockCookies}};
+    if (actionType == &quot;css-display-none&quot;) {
</ins><span class="cx">         JSValue selector = actionObject.get(&amp;exec, Identifier::fromString(&amp;exec, &quot;selector&quot;));
</span><span class="cx">         if (!selector || scope.exception() || !selector.isString())
</span><del>-            return ContentExtensionError::JSONInvalidCSSDisplayNoneActionType;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
</ins><span class="cx"> 
</span><span class="cx">         String selectorString = asString(selector)-&gt;value(&amp;exec);
</span><span class="cx">         if (!isValidSelector(selectorString)) {
</span><span class="cx">             // Skip rules with invalid selectors to be backwards-compatible.
</span><del>-            validSelector = false;
-            return { };
</del><ins>+            return {std::nullopt};
</ins><span class="cx">         }
</span><del>-        action = Action(ActionType::CSSDisplayNoneSelector, selectorString);
-    } else if (actionType == &quot;make-https&quot;) {
-        action = ActionType::MakeHTTPS;
-    } else
-        return ContentExtensionError::JSONInvalidActionType;
-
-    return { };
</del><ins>+        return {Action(ActionType::CSSDisplayNoneSelector, selectorString)};
+    }
+    if (actionType == &quot;make-https&quot;)
+        return {{ActionType::MakeHTTPS}};
+    return makeUnexpected(ContentExtensionError::JSONInvalidActionType);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::error_code loadRule(ExecState&amp; exec, const JSObject&amp; ruleObject, Vector&lt;ContentExtensionRule&gt;&amp; ruleList)
</del><ins>+static Expected&lt;std::optional&lt;ContentExtensionRule&gt;, std::error_code&gt; loadRule(ExecState&amp; exec, const JSObject&amp; ruleObject)
</ins><span class="cx"> {
</span><del>-    Trigger trigger;
-    auto triggerError = loadTrigger(exec, ruleObject, trigger);
-    if (triggerError)
-        return triggerError;
</del><ins>+    auto trigger = loadTrigger(exec, ruleObject);
+    if (!trigger.hasValue())
+        return makeUnexpected(trigger.error());
</ins><span class="cx"> 
</span><del>-    Action action;
-    bool validSelector;
-    auto actionError = loadAction(exec, ruleObject, action, validSelector);
-    if (actionError)
-        return actionError;
</del><ins>+    auto action = loadAction(exec, ruleObject);
+    if (!action.hasValue())
+        return makeUnexpected(action.error());
</ins><span class="cx"> 
</span><del>-    if (validSelector)
-        ruleList.append(ContentExtensionRule(trigger, action));
-    return { };
</del><ins>+    if (action.value())
+        return {{{WTFMove(trigger.value()), WTFMove(action.value().value())}}};
+
+    return {std::nullopt};
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static std::error_code loadEncodedRules(ExecState&amp; exec, const String&amp; rules, Vector&lt;ContentExtensionRule&gt;&amp; ruleList)
</del><ins>+static Expected&lt;Vector&lt;ContentExtensionRule&gt;, std::error_code&gt; loadEncodedRules(ExecState&amp; exec, String&amp;&amp; ruleJSON)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec.vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><span class="cx">     // FIXME: JSONParse should require callbacks instead of an ExecState.
</span><del>-    const JSValue decodedRules = JSONParse(&amp;exec, rules);
</del><ins>+    const JSValue decodedRules = JSONParse(&amp;exec, ruleJSON);
</ins><span class="cx"> 
</span><span class="cx">     if (scope.exception() || !decodedRules)
</span><del>-        return ContentExtensionError::JSONInvalid;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONInvalid);
</ins><span class="cx"> 
</span><span class="cx">     if (!decodedRules.isObject())
</span><del>-        return ContentExtensionError::JSONTopLevelStructureNotAnObject;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONTopLevelStructureNotAnObject);
</ins><span class="cx"> 
</span><span class="cx">     const JSObject* topLevelObject = decodedRules.toObject(&amp;exec);
</span><span class="cx">     if (!topLevelObject || scope.exception())
</span><del>-        return ContentExtensionError::JSONTopLevelStructureNotAnObject;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONTopLevelStructureNotAnObject);
</ins><span class="cx">     
</span><span class="cx">     if (!isJSArray(topLevelObject))
</span><del>-        return ContentExtensionError::JSONTopLevelStructureNotAnArray;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONTopLevelStructureNotAnArray);
</ins><span class="cx"> 
</span><span class="cx">     const JSArray* topLevelArray = jsCast&lt;const JSArray*&gt;(topLevelObject);
</span><span class="cx"> 
</span><del>-    Vector&lt;ContentExtensionRule&gt; localRuleList;
</del><ins>+    Vector&lt;ContentExtensionRule&gt; ruleList;
</ins><span class="cx"> 
</span><span class="cx">     unsigned length = topLevelArray-&gt;length();
</span><span class="cx">     const unsigned maxRuleCount = 50000;
</span><span class="cx">     if (length &gt; maxRuleCount)
</span><del>-        return ContentExtensionError::JSONTooManyRules;
</del><ins>+        return makeUnexpected(ContentExtensionError::JSONTooManyRules);
</ins><span class="cx">     for (unsigned i = 0; i &lt; length; ++i) {
</span><span class="cx">         const JSValue value = topLevelArray-&gt;getIndex(&amp;exec, i);
</span><span class="cx">         if (scope.exception() || !value)
</span><del>-            return ContentExtensionError::JSONInvalidObjectInTopLevelArray;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidObjectInTopLevelArray);
</ins><span class="cx"> 
</span><span class="cx">         const JSObject* ruleObject = value.toObject(&amp;exec);
</span><span class="cx">         if (!ruleObject || scope.exception())
</span><del>-            return ContentExtensionError::JSONInvalidRule;
</del><ins>+            return makeUnexpected(ContentExtensionError::JSONInvalidRule);
</ins><span class="cx"> 
</span><del>-        auto error = loadRule(exec, *ruleObject, localRuleList);
-        if (error)
-            return error;
</del><ins>+        auto rule = loadRule(exec, *ruleObject);
+        if (!rule.hasValue())
+            return makeUnexpected(rule.error());
+        if (rule.value())
+            ruleList.append(*rule.value());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ruleList = WTFMove(localRuleList);
-    return { };
</del><ins>+    return WTFMove(ruleList);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::error_code parseRuleList(const String&amp; rules, Vector&lt;ContentExtensionRule&gt;&amp; ruleList)
</del><ins>+Expected&lt;Vector&lt;ContentExtensionRule&gt;, std::error_code&gt; parseRuleList(String&amp;&amp; ruleJSON)
</ins><span class="cx"> {
</span><span class="cx"> #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
</span><span class="cx">     double loadExtensionStartTime = monotonicallyIncreasingTime();
</span><span class="lines">@@ -311,15 +310,15 @@
</span><span class="cx">     JSGlobalObject* globalObject = JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull()));
</span><span class="cx"> 
</span><span class="cx">     ExecState* exec = globalObject-&gt;globalExec();
</span><del>-    auto error = loadEncodedRules(*exec, rules, ruleList);
</del><ins>+    auto ruleList = loadEncodedRules(*exec, WTFMove(ruleJSON));
</ins><span class="cx"> 
</span><span class="cx">     vm = nullptr;
</span><span class="cx"> 
</span><del>-    if (error)
-        return error;
</del><ins>+    if (!ruleList.hasValue())
+        return makeUnexpected(ruleList.error());
</ins><span class="cx"> 
</span><del>-    if (ruleList.isEmpty())
-        return ContentExtensionError::JSONContainsNoRules;
</del><ins>+    if (ruleList-&gt;isEmpty())
+        return makeUnexpected(ContentExtensionError::JSONContainsNoRules);
</ins><span class="cx"> 
</span><span class="cx"> #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
</span><span class="cx">     double loadExtensionEndTime = monotonicallyIncreasingTime();
</span><span class="lines">@@ -326,7 +325,7 @@
</span><span class="cx">     dataLogF(&quot;Time spent loading extension %f\n&quot;, (loadExtensionEndTime - loadExtensionStartTime));
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return { };
</del><ins>+    return WTFMove(*ruleList);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace ContentExtensions
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionParser.h (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionParser.h        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionParser.h        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(CONTENT_EXTENSIONS)
</span><span class="cx"> 
</span><span class="cx"> #include &lt;system_error&gt;
</span><ins>+#include &lt;wtf/Expected.h&gt;
</ins><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -37,7 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> class ContentExtensionRule;
</span><span class="cx"> 
</span><del>-std::error_code parseRuleList(const String&amp; rules, Vector&lt;ContentExtensionRule&gt;&amp;);
</del><ins>+Expected&lt;Vector&lt;ContentExtensionRule&gt;, std::error_code&gt; parseRuleList(String&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace ContentExtensions
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionRulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionRule.cpp (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionRule.cpp        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionRule.cpp        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -32,9 +32,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace ContentExtensions {
</span><span class="cx"> 
</span><del>-ContentExtensionRule::ContentExtensionRule(const Trigger&amp; trigger, const Action&amp; action)
-    : m_trigger(trigger)
-    , m_action(action)
</del><ins>+ContentExtensionRule::ContentExtensionRule(Trigger&amp;&amp; trigger, Action&amp;&amp; action)
+    : m_trigger(WTFMove(trigger))
+    , m_action(WTFMove(action))
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_trigger.urlFilter.isEmpty());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionRuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionRule.h (213321 => 213322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionRule.h        2017-03-03 00:10:24 UTC (rev 213321)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionRule.h        2017-03-03 00:18:44 UTC (rev 213322)
</span><span class="lines">@@ -175,7 +175,7 @@
</span><span class="cx">     
</span><span class="cx"> class ContentExtensionRule {
</span><span class="cx"> public:
</span><del>-    ContentExtensionRule(const Trigger&amp;, const Action&amp;);
</del><ins>+    ContentExtensionRule(Trigger&amp;&amp;, Action&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     const Trigger&amp; trigger() const { return m_trigger; }
</span><span class="cx">     const Action&amp; action() const { return m_action; }
</span></span></pre>
</div>
</div>

</body>
</html>