<!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>[201971] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>Deleting a CSSOM style rule invalidates any previously-added FontFaces
https://bugs.webkit.org/show_bug.cgi?id=158450

Reviewed by Darin Adler.

Source/WebCore:

This patch has two pieces: updating the CSSOM when the FontFace changes, and
updating the FontFace when the CSSOM changes.

1: Updating the CSSOM when the FontFace changes: CSSFontFaces already have a RefPtr
to their StyleRuleFontFace which represents their CSS-connection. When changing a
property of the CSSFontFace, we simply reach into the StyleRule and update it to
match. Our existing infrastructure of invalidation due to the attribute changes
makes sure that all the necessary updates occur.

2. Updating the FontFace when the CSSOM changes: If the CSSOM changes in a trivial
way (for example, a new @font-face is appended to the end of the last &lt;style&gt;
element), we can handle it directly. However, when something more invasive occurs,
we end up clearing the entire CSSFontSelector, and then adding all the style rules
from scratch. This involves three steps:
    a) CSSFontSelector::buildStarted() is run, which means &quot;we're about to start
       building up all the @font-face rules from scratch.&quot; We take this opportunity
       to purge as many fonts as possible. This is valuable because, for example,
       this function gets run when the page gets put into the page cache, so we
       want to destroy as much as possible. Not everything can be purged, however -
       only CSS-connected fonts which have never been inspected by script are
       purgeable. We don't allow fonts inspected by script to be purged because
       purging might result in a font appearing from JavaScript to transition from
       a success -&gt; failure state, which we don't allow.
    b) Upon style recalc (possibly asynchronously) CSSFontSelector::addFontFaceRule()
       is called for each @font-face rule. We actually detect that we're in the
       middle of a style rebuild, and defer this step.
    c) When we're done adding all the font face rules, we call
       CSSFontSelector::buildCompleted(). This is where we compare the newly built-
       up list of font faces with what existed previously (as remembered in
       CSSFontSelector::buildStarted()) in order to detect font faces which were
       deleted from the document. Fonts which were newly added to the document
       are handled naturally.
       Fonts which have a property modified on them are created as if they were new.
       However, instead of simply adding the CSSFontFace, we search for the existing
       CSSFontFace (by CSS connection pointer) and tell the existing FontFace to
       adopt this new CSSFontFace. This means that the JavaScript object will just
       pick up any newly-written values in the CSSOM. It also means that the
       &quot;status&quot; attribute of the JavaScript object is reset, but this is expected
       and allowed by the spec. (For example, if you change the &quot;src&quot; attribute of
       an @font-face block via the CSSOM, all bets are off when you inspect the
       FontFace JS object representing that block.)

Test: fast/text/font-face-set-cssom.html

* css/CSSFontFace.cpp:
(WebCore::CSSFontFace::CSSFontFace):
(WebCore::CSSFontFace::setFamilies):
(WebCore::CSSFontFace::setStyle):
(WebCore::CSSFontFace::setWeight):
(WebCore::CSSFontFace::setUnicodeRange):
(WebCore::CSSFontFace::setVariantLigatures):
(WebCore::CSSFontFace::setVariantPosition):
(WebCore::CSSFontFace::setVariantCaps):
(WebCore::CSSFontFace::setVariantNumeric):
(WebCore::CSSFontFace::setVariantAlternates):
(WebCore::CSSFontFace::setVariantEastAsian):
(WebCore::CSSFontFace::setFeatureSettings):
(WebCore::CSSFontFace::initializeWrapper):
(WebCore::CSSFontFace::wrapper):
(WebCore::CSSFontFace::setWrapper):
(WebCore::CSSFontFace::purgeable):
(WebCore::CSSFontFace::updateStyleIfNeeded):
* css/CSSFontFace.h:
* css/CSSFontFaceSet.cpp:
(WebCore::CSSFontFaceSet::remove):
(WebCore::CSSFontFaceSet::containsCSSConnection):
(WebCore::CSSFontFaceSet::purge):
* css/CSSFontFaceSet.h:
* css/CSSFontSelector.cpp:
(WebCore::CSSFontSelector::buildStarted):
(WebCore::CSSFontSelector::buildCompleted):
(WebCore::CSSFontSelector::addFontFaceRule):
* css/CSSFontSelector.h:
* css/FontFace.cpp:
(WebCore::FontFace::family):
(WebCore::FontFace::style):
(WebCore::FontFace::weight):
(WebCore::FontFace::unicodeRange):
(WebCore::FontFace::variant):
(WebCore::FontFace::featureSettings):
(WebCore::FontFace::adopt):
* css/FontFace.h:

LayoutTests:

* fast/text/font-face-set-cssom-expected.txt: Added.
* fast/text/font-face-set-cssom.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFacecpp">trunk/Source/WebCore/css/CSSFontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceh">trunk/Source/WebCore/css/CSSFontFace.h</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceSetcpp">trunk/Source/WebCore/css/CSSFontFaceSet.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontFaceSeth">trunk/Source/WebCore/css/CSSFontFaceSet.h</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontSelectorcpp">trunk/Source/WebCore/css/CSSFontSelector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSFontSelectorh">trunk/Source/WebCore/css/CSSFontSelector.h</a></li>
<li><a href="#trunkSourceWebCorecssFontFacecpp">trunk/Source/WebCore/css/FontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssFontFaceh">trunk/Source/WebCore/css/FontFace.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasttextfontfacesetcssomexpectedtxt">trunk/LayoutTests/fast/text/font-face-set-cssom-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasttextfontfacesetcssomhtml">trunk/LayoutTests/fast/text/font-face-set-cssom.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/LayoutTests/ChangeLog        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-06-11  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Deleting a CSSOM style rule invalidates any previously-added FontFaces
+        https://bugs.webkit.org/show_bug.cgi?id=158450
+
+        Reviewed by Darin Adler.
+
+        * fast/text/font-face-set-cssom-expected.txt: Added.
+        * fast/text/font-face-set-cssom.html: Added.
+
</ins><span class="cx"> 2016-06-11  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WorkerNavigator is missing some attributes
</span></span></pre></div>
<a id="trunkLayoutTestsfasttextfontfacesetcssomexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/text/font-face-set-cssom-expected.txt (0 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/font-face-set-cssom-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/text/font-face-set-cssom-expected.txt        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+This test makes sure that the CSS Font Loading API plays nicely with modifying @font-face rules with the CSSOM.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is not 48
+PASS item3.getBoundingClientRect().width is not 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is not 48
+PASS item6.getBoundingClientRect().width is not 48
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is 48
+PASS item3.getBoundingClientRect().width is not 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is not 48
+PASS item6.getBoundingClientRect().width is not 48
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is 48
+PASS item3.getBoundingClientRect().width is 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is not 48
+PASS item6.getBoundingClientRect().width is not 48
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is 48
+PASS item3.getBoundingClientRect().width is not 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is not 48
+PASS item6.getBoundingClientRect().width is not 48
+PASS connectedFontFace.family is &quot;WebFont2&quot;
+PASS connectedFontFace.family is &quot;WebFont5&quot;
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is not 48
+PASS item3.getBoundingClientRect().width is not 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is 48
+PASS item6.getBoundingClientRect().width is not 48
+PASS styleSheet.cssRules[0].style.fontFamily is &quot;WebFont6&quot;
+PASS item1.getBoundingClientRect().width is 48
+PASS item2.getBoundingClientRect().width is not 48
+PASS item3.getBoundingClientRect().width is not 48
+PASS item4.getBoundingClientRect().width is not 48
+PASS item5.getBoundingClientRect().width is not 48
+PASS item6.getBoundingClientRect().width is 48
+PASS successfullyParsed is true
+
+TEST COMPLETE
+l l l l l l
</ins><span class="cx">Property changes on: trunk/LayoutTests/fast/text/font-face-set-cssom-expected.txt
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkLayoutTestsfasttextfontfacesetcssomhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/text/font-face-set-cssom.html (0 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/text/font-face-set-cssom.html                                (rev 0)
+++ trunk/LayoutTests/fast/text/font-face-set-cssom.html        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -0,0 +1,92 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style id=&quot;styleElement&quot;&gt;
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;span id=&quot;item1&quot; style=&quot;font: 48px WebFont;&quot;&gt;l&lt;/span&gt;
+&lt;span id=&quot;item2&quot; style=&quot;font: 48px WebFont2;&quot;&gt;l&lt;/span&gt;
+&lt;span id=&quot;item3&quot; style=&quot;font: 48px WebFont3;&quot;&gt;l&lt;/span&gt;
+&lt;span id=&quot;item4&quot; style=&quot;font: 48px WebFont4;&quot;&gt;l&lt;/span&gt;
+&lt;span id=&quot;item5&quot; style=&quot;font: 48px WebFont5;&quot;&gt;l&lt;/span&gt;
+&lt;span id=&quot;item6&quot; style=&quot;font: 48px WebFont6;&quot;&gt;l&lt;/span&gt;
+&lt;script&gt;
+description(&quot;This test makes sure that the CSS Font Loading API plays nicely with modifying @font-face rules with the CSSOM.&quot;);
+
+var item1 = document.getElementById(&quot;item1&quot;);
+var item2 = document.getElementById(&quot;item2&quot;);
+var item3 = document.getElementById(&quot;item3&quot;);
+var item4 = document.getElementById(&quot;item4&quot;);
+var item5 = document.getElementById(&quot;item5&quot;);
+var item6 = document.getElementById(&quot;item6&quot;);
+
+var fontFace = new FontFace(&quot;WebFont&quot;, &quot;local('Ahem')&quot;, {});
+document.fonts.add(fontFace);
+fontFace.load();
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+var styleSheet = document.getElementById(&quot;styleElement&quot;).sheet;
+styleSheet.insertRule(&quot;@font-face { font-family: 'WebFont2'; src: local('Ahem'); }&quot;, 0);
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+styleSheet.insertRule(&quot;@font-face { font-family: 'WebFont3'; src: local('Ahem'); }&quot;, 0);
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+styleSheet.deleteRule(0);
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+var connectedFontFace = document.fonts.keys().next().value;
+shouldBeEqualToString(&quot;connectedFontFace.family&quot;, &quot;WebFont2&quot;);
+
+styleSheet.cssRules[0].style.fontFamily = &quot;WebFont5&quot;;
+
+shouldBeEqualToString(&quot;connectedFontFace.family&quot;, &quot;WebFont5&quot;);
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+connectedFontFace.family = &quot;WebFont6&quot;;
+
+shouldBeEqualToString(&quot;styleSheet.cssRules[0].style.fontFamily&quot;, &quot;WebFont6&quot;);
+
+shouldBe(&quot;item1.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item2.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item3.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item4.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldNotBe(&quot;item5.getBoundingClientRect().width&quot;, &quot;48&quot;);
+shouldBe(&quot;item6.getBoundingClientRect().width&quot;, &quot;48&quot;);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/ChangeLog        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -1,3 +1,93 @@
</span><ins>+2016-06-11  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Deleting a CSSOM style rule invalidates any previously-added FontFaces
+        https://bugs.webkit.org/show_bug.cgi?id=158450
+
+        Reviewed by Darin Adler.
+
+        This patch has two pieces: updating the CSSOM when the FontFace changes, and
+        updating the FontFace when the CSSOM changes.
+
+        1: Updating the CSSOM when the FontFace changes: CSSFontFaces already have a RefPtr
+        to their StyleRuleFontFace which represents their CSS-connection. When changing a
+        property of the CSSFontFace, we simply reach into the StyleRule and update it to
+        match. Our existing infrastructure of invalidation due to the attribute changes
+        makes sure that all the necessary updates occur.
+
+        2. Updating the FontFace when the CSSOM changes: If the CSSOM changes in a trivial
+        way (for example, a new @font-face is appended to the end of the last &lt;style&gt;
+        element), we can handle it directly. However, when something more invasive occurs,
+        we end up clearing the entire CSSFontSelector, and then adding all the style rules
+        from scratch. This involves three steps:
+            a) CSSFontSelector::buildStarted() is run, which means &quot;we're about to start
+               building up all the @font-face rules from scratch.&quot; We take this opportunity
+               to purge as many fonts as possible. This is valuable because, for example,
+               this function gets run when the page gets put into the page cache, so we
+               want to destroy as much as possible. Not everything can be purged, however -
+               only CSS-connected fonts which have never been inspected by script are
+               purgeable. We don't allow fonts inspected by script to be purged because
+               purging might result in a font appearing from JavaScript to transition from
+               a success -&gt; failure state, which we don't allow.
+            b) Upon style recalc (possibly asynchronously) CSSFontSelector::addFontFaceRule()
+               is called for each @font-face rule. We actually detect that we're in the
+               middle of a style rebuild, and defer this step.
+            c) When we're done adding all the font face rules, we call
+               CSSFontSelector::buildCompleted(). This is where we compare the newly built-
+               up list of font faces with what existed previously (as remembered in
+               CSSFontSelector::buildStarted()) in order to detect font faces which were
+               deleted from the document. Fonts which were newly added to the document
+               are handled naturally.
+               Fonts which have a property modified on them are created as if they were new.
+               However, instead of simply adding the CSSFontFace, we search for the existing
+               CSSFontFace (by CSS connection pointer) and tell the existing FontFace to
+               adopt this new CSSFontFace. This means that the JavaScript object will just
+               pick up any newly-written values in the CSSOM. It also means that the
+               &quot;status&quot; attribute of the JavaScript object is reset, but this is expected
+               and allowed by the spec. (For example, if you change the &quot;src&quot; attribute of
+               an @font-face block via the CSSOM, all bets are off when you inspect the
+               FontFace JS object representing that block.)
+
+        Test: fast/text/font-face-set-cssom.html
+
+        * css/CSSFontFace.cpp:
+        (WebCore::CSSFontFace::CSSFontFace):
+        (WebCore::CSSFontFace::setFamilies):
+        (WebCore::CSSFontFace::setStyle):
+        (WebCore::CSSFontFace::setWeight):
+        (WebCore::CSSFontFace::setUnicodeRange):
+        (WebCore::CSSFontFace::setVariantLigatures):
+        (WebCore::CSSFontFace::setVariantPosition):
+        (WebCore::CSSFontFace::setVariantCaps):
+        (WebCore::CSSFontFace::setVariantNumeric):
+        (WebCore::CSSFontFace::setVariantAlternates):
+        (WebCore::CSSFontFace::setVariantEastAsian):
+        (WebCore::CSSFontFace::setFeatureSettings):
+        (WebCore::CSSFontFace::initializeWrapper):
+        (WebCore::CSSFontFace::wrapper):
+        (WebCore::CSSFontFace::setWrapper):
+        (WebCore::CSSFontFace::purgeable):
+        (WebCore::CSSFontFace::updateStyleIfNeeded):
+        * css/CSSFontFace.h:
+        * css/CSSFontFaceSet.cpp:
+        (WebCore::CSSFontFaceSet::remove):
+        (WebCore::CSSFontFaceSet::containsCSSConnection):
+        (WebCore::CSSFontFaceSet::purge):
+        * css/CSSFontFaceSet.h:
+        * css/CSSFontSelector.cpp:
+        (WebCore::CSSFontSelector::buildStarted):
+        (WebCore::CSSFontSelector::buildCompleted):
+        (WebCore::CSSFontSelector::addFontFaceRule):
+        * css/CSSFontSelector.h:
+        * css/FontFace.cpp:
+        (WebCore::FontFace::family):
+        (WebCore::FontFace::style):
+        (WebCore::FontFace::weight):
+        (WebCore::FontFace::unicodeRange):
+        (WebCore::FontFace::variant):
+        (WebCore::FontFace::featureSettings):
+        (WebCore::FontFace::adopt):
+        * css/FontFace.h:
+
</ins><span class="cx"> 2016-06-11  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WorkerNavigator is missing some attributes
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFace.cpp (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFace.cpp        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontFace.cpp        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx">     , m_cssConnection(cssConnection)
</span><span class="cx">     , m_wrapper(wrapper ? wrapper-&gt;createWeakPtr() : WeakPtr&lt;FontFace&gt;())
</span><span class="cx">     , m_isLocalFallback(isLocalFallback)
</span><ins>+    , m_mayBePurged(!wrapper)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -113,6 +114,9 @@
</span><span class="cx">     RefPtr&lt;CSSValueList&gt; oldFamilies = m_families;
</span><span class="cx">     m_families = &amp;familyList;
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontFamily, &amp;family);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this, oldFamilies.get());
</span><span class="cx">     });
</span><span class="lines">@@ -143,6 +147,9 @@
</span><span class="cx">     if (auto mask = calculateStyleMask(style)) {
</span><span class="cx">         m_traitsMask = static_cast&lt;FontTraitsMask&gt;((static_cast&lt;unsigned&gt;(m_traitsMask) &amp; (~FontStyleMask)) | mask.value());
</span><span class="cx"> 
</span><ins>+        if (m_cssConnection)
+            m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontStyle, &amp;style);
+
</ins><span class="cx">         iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">             client.fontPropertyChanged(*this);
</span><span class="cx">         });
</span><span class="lines">@@ -192,6 +199,9 @@
</span><span class="cx">     if (auto mask = calculateWeightMask(weight)) {
</span><span class="cx">         m_traitsMask = static_cast&lt;FontTraitsMask&gt;((static_cast&lt;unsigned&gt;(m_traitsMask) &amp; (~FontWeightMask)) | mask.value());
</span><span class="cx"> 
</span><ins>+        if (m_cssConnection)
+            m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontWeight, &amp;weight);
+
</ins><span class="cx">         iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">             client.fontPropertyChanged(*this);
</span><span class="cx">         });
</span><span class="lines">@@ -214,6 +224,9 @@
</span><span class="cx">         m_ranges.append({ range.from(), range.to() });
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyUnicodeRange, &amp;unicodeRange);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -230,6 +243,9 @@
</span><span class="cx">     m_variantSettings.historicalLigatures = ligatures.historicalLigatures;
</span><span class="cx">     m_variantSettings.contextualAlternates = ligatures.contextualAlternates;
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantLigatures, &amp;variantLigatures);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -244,6 +260,9 @@
</span><span class="cx"> 
</span><span class="cx">     m_variantSettings.position = downcast&lt;CSSPrimitiveValue&gt;(variantPosition);
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantPosition, &amp;variantPosition);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -258,6 +277,9 @@
</span><span class="cx"> 
</span><span class="cx">     m_variantSettings.caps = downcast&lt;CSSPrimitiveValue&gt;(variantCaps);
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantCaps, &amp;variantCaps);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -275,6 +297,9 @@
</span><span class="cx">     m_variantSettings.numericOrdinal = numeric.ordinal;
</span><span class="cx">     m_variantSettings.numericSlashedZero = numeric.slashedZero;
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantNumeric, &amp;variantNumeric);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -289,6 +314,9 @@
</span><span class="cx"> 
</span><span class="cx">     m_variantSettings.alternates = downcast&lt;CSSPrimitiveValue&gt;(variantAlternates);
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantAlternates, &amp;variantAlternates);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -304,6 +332,9 @@
</span><span class="cx">     m_variantSettings.eastAsianWidth = eastAsian.width;
</span><span class="cx">     m_variantSettings.eastAsianRuby = eastAsian.ruby;
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontVariantEastAsian, &amp;variantEastAsian);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -331,6 +362,9 @@
</span><span class="cx"> 
</span><span class="cx">     m_featureSettings = WTFMove(settings);
</span><span class="cx"> 
</span><ins>+    if (m_cssConnection)
+        m_cssConnection-&gt;mutableProperties().setProperty(CSSPropertyFontFeatureSettings, &amp;featureSettings);
+
</ins><span class="cx">     iterateClients(m_clients, [&amp;](Client&amp; client) {
</span><span class="cx">         client.fontPropertyChanged(*this);
</span><span class="cx">     });
</span><span class="lines">@@ -381,35 +415,47 @@
</span><span class="cx">     m_clients.remove(&amp;client);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref&lt;FontFace&gt; CSSFontFace::wrapper()
</del><ins>+void CSSFontFace::initializeWrapper()
</ins><span class="cx"> {
</span><del>-    if (m_wrapper)
-        return Ref&lt;FontFace&gt;(*m_wrapper.get());
-
-    Ref&lt;FontFace&gt; wrapper = FontFace::create(*this);
</del><span class="cx">     switch (m_status) {
</span><span class="cx">     case Status::Pending:
</span><span class="cx">         break;
</span><span class="cx">     case Status::Loading:
</span><del>-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
</del><ins>+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
</ins><span class="cx">         break;
</span><span class="cx">     case Status::TimedOut:
</span><del>-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
-        wrapper-&gt;fontStateChanged(*this, Status::Loading, Status::TimedOut);
</del><ins>+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
+        m_wrapper-&gt;fontStateChanged(*this, Status::Loading, Status::TimedOut);
</ins><span class="cx">         break;
</span><span class="cx">     case Status::Success:
</span><del>-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Success);
</del><ins>+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Success);
</ins><span class="cx">         break;
</span><span class="cx">     case Status::Failure:
</span><del>-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
-        wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Failure);
</del><ins>+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Loading);
+        m_wrapper-&gt;fontStateChanged(*this, Status::Pending, Status::Failure);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+}
+
+Ref&lt;FontFace&gt; CSSFontFace::wrapper()
+{
+    if (m_wrapper)
+        return *m_wrapper.get();
+
+    auto wrapper = FontFace::create(*this);
</ins><span class="cx">     m_wrapper = wrapper-&gt;createWeakPtr();
</span><ins>+    initializeWrapper();
+    m_mayBePurged = false;
</ins><span class="cx">     return wrapper;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CSSFontFace::setWrapper(FontFace&amp; newWrapper)
+{
+    m_wrapper = newWrapper.createWeakPtr();
+    initializeWrapper();
+}
+
</ins><span class="cx"> void CSSFontFace::adoptSource(std::unique_ptr&lt;CSSFontFaceSource&gt;&amp;&amp; source)
</span><span class="cx"> {
</span><span class="cx">     m_sources.append(WTFMove(source));
</span><span class="lines">@@ -552,6 +598,17 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool CSSFontFace::purgeable() const
+{
+    return cssConnection() &amp;&amp; m_mayBePurged;
+}
+
+void CSSFontFace::updateStyleIfNeeded()
+{
+    if (m_fontSelector &amp;&amp; m_fontSelector-&gt;document())
+        m_fontSelector-&gt;document()-&gt;updateStyleIfNeeded();
+}
+
</ins><span class="cx"> #if ENABLE(SVG_FONTS)
</span><span class="cx"> bool CSSFontFace::hasSVGFontFaceSource() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFace.h (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFace.h        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontFace.h        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -135,9 +135,15 @@
</span><span class="cx"> 
</span><span class="cx">     // We don't guarantee that the FontFace wrapper will be the same every time you ask for it.
</span><span class="cx">     Ref&lt;FontFace&gt; wrapper();
</span><ins>+    void setWrapper(FontFace&amp;);
+    FontFace* existingWrapper() { return m_wrapper.get(); }
</ins><span class="cx"> 
</span><span class="cx">     bool webFontsShouldAlwaysFallBack() const;
</span><span class="cx"> 
</span><ins>+    bool purgeable() const;
+
+    void updateStyleIfNeeded();
+
</ins><span class="cx"> #if ENABLE(SVG_FONTS)
</span><span class="cx">     bool hasSVGFontFaceSource() const;
</span><span class="cx"> #endif
</span><span class="lines">@@ -149,6 +155,8 @@
</span><span class="cx">     void setStatus(Status);
</span><span class="cx">     void notifyClientsOfFontPropertyChange();
</span><span class="cx"> 
</span><ins>+    void initializeWrapper();
+
</ins><span class="cx">     void fontLoadEventOccurred();
</span><span class="cx">     void timeoutFired();
</span><span class="cx"> 
</span><span class="lines">@@ -166,6 +174,7 @@
</span><span class="cx">     Status m_status { Status::Pending };
</span><span class="cx">     bool m_isLocalFallback { false };
</span><span class="cx">     bool m_sourcesPopulated { false };
</span><ins>+    bool m_mayBePurged { true };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFaceSet.cpp (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFaceSet.cpp        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontFaceSet.cpp        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -95,9 +95,10 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CSSFontFaceSet::registerLocalFontFacesForFamily(const String&amp; familyName)
</del><ins>+void CSSFontFaceSet::ensureLocalFontFacesForFamilyRegistered(const String&amp; familyName)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_locallyInstalledFacesLookupTable.contains(familyName));
</del><ins>+    if (m_locallyInstalledFacesLookupTable.contains(familyName))
+        return;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;FontTraitsMask&gt; traitsMasks = FontCache::singleton().getTraitsInFamily(familyName);
</span><span class="cx">     if (traitsMasks.isEmpty())
</span><span class="lines">@@ -160,7 +161,7 @@
</span><span class="cx">         if (addResult.isNewEntry) {
</span><span class="cx">             // m_locallyInstalledFontFaces grows without bound, eventually encorporating every font installed on the system.
</span><span class="cx">             // This is by design.
</span><del>-            registerLocalFontFacesForFamily(familyName);
</del><ins>+            ensureLocalFontFacesForFamilyRegistered(familyName);
</ins><span class="cx">             familyFontFaces = { };
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -187,6 +188,11 @@
</span><span class="cx"> 
</span><span class="cx">     if (face.status() == CSSFontFace::Status::Loading || face.status() == CSSFontFace::Status::TimedOut)
</span><span class="cx">         incrementActiveCount();
</span><ins>+
+    if (face.cssConnection()) {
+        auto addResult = m_constituentCSSConnections.add(face.cssConnection(), &amp;face);
+        ASSERT_UNUSED(addResult, addResult.isNewEntry);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CSSFontFaceSet::removeFromFacesLookupTable(const CSSFontFace&amp; face, const CSSValueList&amp; familiesToSearchFor)
</span><span class="lines">@@ -222,6 +228,11 @@
</span><span class="cx">     if (face.families())
</span><span class="cx">         removeFromFacesLookupTable(face, *face.families());
</span><span class="cx"> 
</span><ins>+    if (face.cssConnection()) {
+        bool removed = m_constituentCSSConnections.remove(face.cssConnection());
+        ASSERT_UNUSED(removed, removed);
+    }
+
</ins><span class="cx">     for (size_t i = 0; i &lt; m_faces.size(); ++i) {
</span><span class="cx">         if (m_faces[i].ptr() == &amp;face) {
</span><span class="cx">             if (i &lt; m_facesPartitionIndex)
</span><span class="lines">@@ -236,6 +247,23 @@
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CSSFontFace* CSSFontFaceSet::lookupByCSSConnection(StyleRuleFontFace&amp; target)
+{
+    return m_constituentCSSConnections.get(&amp;target);
+}
+
+void CSSFontFaceSet::purge()
+{
+    Vector&lt;Ref&lt;CSSFontFace&gt;&gt; toRemove;
+    for (auto&amp; face : m_faces) {
+        if (face-&gt;purgeable())
+            toRemove.append(face.copyRef());
+    }
+
+    for (auto&amp; item : toRemove)
+        remove(item.get());
+}
+
</ins><span class="cx"> void CSSFontFaceSet::clear()
</span><span class="cx"> {
</span><span class="cx">     for (auto&amp; face : m_faces)
</span><span class="lines">@@ -244,6 +272,7 @@
</span><span class="cx">     m_facesLookupTable.clear();
</span><span class="cx">     m_locallyInstalledFacesLookupTable.clear();
</span><span class="cx">     m_cache.clear();
</span><ins>+    m_constituentCSSConnections.clear();
</ins><span class="cx">     m_facesPartitionIndex = 0;
</span><span class="cx">     m_status = Status::Loaded;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontFaceSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontFaceSet.h (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontFaceSet.h        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontFaceSet.h        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -60,9 +60,12 @@
</span><span class="cx">     size_t faceCount() const { return m_faces.size(); }
</span><span class="cx">     void add(CSSFontFace&amp;);
</span><span class="cx">     void remove(const CSSFontFace&amp;);
</span><ins>+    void purge();
</ins><span class="cx">     void clear();
</span><span class="cx">     CSSFontFace&amp; operator[](size_t i);
</span><span class="cx"> 
</span><ins>+    CSSFontFace* lookupByCSSConnection(StyleRuleFontFace&amp;);
+
</ins><span class="cx">     bool check(const String&amp; font, const String&amp; text, ExceptionCode&amp;);
</span><span class="cx"> 
</span><span class="cx">     CSSSegmentedFontFace* getFontFace(FontTraitsMask, const AtomicString&amp; family);
</span><span class="lines">@@ -91,7 +94,7 @@
</span><span class="cx">     void fontStateChanged(CSSFontFace&amp;, CSSFontFace::Status oldState, CSSFontFace::Status newState) override;
</span><span class="cx">     void fontPropertyChanged(CSSFontFace&amp;, CSSValueList* oldFamilies = nullptr) override;
</span><span class="cx"> 
</span><del>-    void registerLocalFontFacesForFamily(const String&amp;);
</del><ins>+    void ensureLocalFontFacesForFamilyRegistered(const String&amp;);
</ins><span class="cx"> 
</span><span class="cx">     static String familyNameFromPrimitive(const CSSPrimitiveValue&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -100,6 +103,7 @@
</span><span class="cx">     HashMap&lt;String, Vector&lt;Ref&lt;CSSFontFace&gt;&gt;, ASCIICaseInsensitiveHash&gt; m_facesLookupTable;
</span><span class="cx">     HashMap&lt;String, Vector&lt;Ref&lt;CSSFontFace&gt;&gt;, ASCIICaseInsensitiveHash&gt; m_locallyInstalledFacesLookupTable;
</span><span class="cx">     HashMap&lt;String, HashMap&lt;unsigned, RefPtr&lt;CSSSegmentedFontFace&gt;&gt;, ASCIICaseInsensitiveHash&gt; m_cache;
</span><ins>+    HashMap&lt;StyleRuleFontFace*, CSSFontFace*&gt; m_constituentCSSConnections;
</ins><span class="cx">     size_t m_facesPartitionIndex { 0 }; // All entries in m_faces before this index are CSS-connected.
</span><span class="cx">     Status m_status { Status::Loaded };
</span><span class="cx">     HashSet&lt;CSSFontFaceSetClient*&gt; m_clients;
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontSelectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontSelector.cpp (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontSelector.cpp        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontSelector.cpp        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;Document.h&quot;
</span><span class="cx"> #include &quot;Font.h&quot;
</span><span class="cx"> #include &quot;FontCache.h&quot;
</span><ins>+#include &quot;FontFace.h&quot;
</ins><span class="cx"> #include &quot;FontFaceSet.h&quot;
</span><span class="cx"> #include &quot;FontSelectorClient.h&quot;
</span><span class="cx"> #include &quot;FontVariantBuilder.h&quot;
</span><span class="lines">@@ -101,7 +102,17 @@
</span><span class="cx"> void CSSFontSelector::buildStarted()
</span><span class="cx"> {
</span><span class="cx">     m_buildIsUnderway = true;
</span><ins>+    m_stagingArea.clear();
+    m_cssFontFaceSet-&gt;purge();
</ins><span class="cx">     ++m_version;
</span><ins>+
+    m_cssConnectionsPossiblyToRemove.clear();
+    m_cssConnectionsEncounteredDuringBuild.clear();
+    for (size_t i = 0; i &lt; m_cssFontFaceSet-&gt;faceCount(); ++i) {
+        CSSFontFace&amp; face = m_cssFontFaceSet.get()[i];
+        if (face.cssConnection())
+            m_cssConnectionsPossiblyToRemove.add(&amp;face);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CSSFontSelector::buildCompleted()
</span><span class="lines">@@ -111,7 +122,13 @@
</span><span class="cx"> 
</span><span class="cx">     m_buildIsUnderway = false;
</span><span class="cx"> 
</span><del>-    m_cssFontFaceSet-&gt;clear();
</del><ins>+    // Some font faces weren't re-added during the build process.
+    for (auto&amp; face : m_cssConnectionsPossiblyToRemove) {
+        auto* connection = face-&gt;cssConnection();
+        ASSERT(connection);
+        if (!m_cssConnectionsEncounteredDuringBuild.contains(connection))
+            m_cssFontFaceSet-&gt;remove(*face);
+    }
</ins><span class="cx"> 
</span><span class="cx">     for (auto&amp; item : m_stagingArea)
</span><span class="cx">         addFontFaceRule(item.styleRuleFontFace, item.isInitiatingElementInUserAgentShadowTree);
</span><span class="lines">@@ -121,6 +138,7 @@
</span><span class="cx"> void CSSFontSelector::addFontFaceRule(StyleRuleFontFace&amp; fontFaceRule, bool isInitiatingElementInUserAgentShadowTree)
</span><span class="cx"> {
</span><span class="cx">     if (m_buildIsUnderway) {
</span><ins>+        m_cssConnectionsEncounteredDuringBuild.add(&amp;fontFaceRule);
</ins><span class="cx">         m_stagingArea.append({fontFaceRule, isInitiatingElementInUserAgentShadowTree});
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -187,6 +205,12 @@
</span><span class="cx">     if (fontFace-&gt;allSourcesFailed())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (RefPtr&lt;CSSFontFace&gt; existingFace = m_cssFontFaceSet-&gt;lookupByCSSConnection(fontFaceRule)) {
+        m_cssFontFaceSet-&gt;remove(*existingFace);
+        if (auto* existingWrapper = existingFace-&gt;existingWrapper())
+            existingWrapper-&gt;adopt(fontFace.get());
+    }
+
</ins><span class="cx">     m_cssFontFaceSet-&gt;add(fontFace.get());
</span><span class="cx">     m_creatingFont = false;
</span><span class="cx">     ++m_version;
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSFontSelectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSFontSelector.h (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSFontSelector.h        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/CSSFontSelector.h        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -105,6 +105,8 @@
</span><span class="cx">     HashSet&lt;FontSelectorClient*&gt; m_clients;
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;CachedResourceHandle&lt;CachedFont&gt;&gt; m_fontsToBeginLoading;
</span><ins>+    HashSet&lt;RefPtr&lt;CSSFontFace&gt;&gt; m_cssConnectionsPossiblyToRemove;
+    HashSet&lt;RefPtr&lt;StyleRuleFontFace&gt;&gt; m_cssConnectionsEncounteredDuringBuild;
</ins><span class="cx">     Timer m_beginLoadingTimer;
</span><span class="cx"> 
</span><span class="cx">     unsigned m_uniqueId;
</span></span></pre></div>
<a id="trunkSourceWebCorecssFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/FontFace.cpp (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/FontFace.cpp        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/FontFace.cpp        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -270,11 +270,13 @@
</span><span class="cx"> 
</span><span class="cx"> String FontFace::family() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     return m_backing-&gt;families()-&gt;cssText();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String FontFace::style() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     switch (m_backing-&gt;traitsMask() &amp; FontStyleMask) {
</span><span class="cx">     case FontStyleNormalMask:
</span><span class="cx">         return String(&quot;normal&quot;, String::ConstructFromLiteral);
</span><span class="lines">@@ -287,6 +289,7 @@
</span><span class="cx"> 
</span><span class="cx"> String FontFace::weight() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     switch (m_backing-&gt;traitsMask() &amp; FontWeightMask) {
</span><span class="cx">     case FontWeight100Mask:
</span><span class="cx">         return String(&quot;100&quot;, String::ConstructFromLiteral);
</span><span class="lines">@@ -318,6 +321,7 @@
</span><span class="cx"> 
</span><span class="cx"> String FontFace::unicodeRange() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     if (!m_backing-&gt;ranges().size())
</span><span class="cx">         return &quot;U+0-10FFFF&quot;;
</span><span class="cx">     RefPtr&lt;CSSValueList&gt; values = CSSValueList::createCommaSeparated();
</span><span class="lines">@@ -328,11 +332,13 @@
</span><span class="cx"> 
</span><span class="cx"> String FontFace::variant() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     return computeFontVariant(m_backing-&gt;variantSettings())-&gt;cssText();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String FontFace::featureSettings() const
</span><span class="cx"> {
</span><ins>+    const_cast&lt;CSSFontFace&amp;&gt;(m_backing.get()).updateStyleIfNeeded();
</ins><span class="cx">     if (!m_backing-&gt;featureSettings().size())
</span><span class="cx">         return &quot;normal&quot;;
</span><span class="cx">     RefPtr&lt;CSSValueList&gt; list = CSSValueList::createCommaSeparated();
</span><span class="lines">@@ -359,6 +365,15 @@
</span><span class="cx">     return LoadStatus::Error;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void FontFace::adopt(CSSFontFace&amp; newFace)
+{
+    m_promise = Nullopt;
+    m_backing-&gt;removeClient(*this);
+    m_backing = newFace;
+    m_backing-&gt;addClient(*this);
+    newFace.setWrapper(*this);
+}
+
</ins><span class="cx"> void FontFace::fontStateChanged(CSSFontFace&amp; face, CSSFontFace::Status, CSSFontFace::Status newState)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(face, &amp;face == m_backing.ptr());
</span></span></pre></div>
<a id="trunkSourceWebCorecssFontFaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/FontFace.h (201970 => 201971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/FontFace.h        2016-06-11 17:44:20 UTC (rev 201970)
+++ trunk/Source/WebCore/css/FontFace.h        2016-06-11 17:52:35 UTC (rev 201971)
</span><span class="lines">@@ -69,6 +69,8 @@
</span><span class="cx">     Optional&lt;Promise&gt;&amp; promise() { return m_promise; }
</span><span class="cx">     void registerLoaded(Promise&amp;&amp;);
</span><span class="cx"> 
</span><ins>+    void adopt(CSSFontFace&amp;);
+
</ins><span class="cx">     void load();
</span><span class="cx"> 
</span><span class="cx">     CSSFontFace&amp; backing() { return m_backing; }
</span></span></pre>
</div>
</div>

</body>
</html>