<!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>[211965] 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/211965">211965</a></dd>
<dt>Author</dt> <dd>bfulgham@apple.com</dd>
<dt>Date</dt> <dd>2017-02-09 09:59:45 -0800 (Thu, 09 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Adopting a child node of a script element can run script
https://bugs.webkit.org/show_bug.cgi?id=167318

Patch by Ryosuke Niwa &lt;rniwa@webkit.org&gt; on 2017-02-09
Reviewed by Darin Adler.

Source/WebCore:

The bug was caused by ScriptElement::childrenChanged indiscriminately running the script.
Do this only if some node has been inserted as spec'ed:

https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
&quot;The script element is connected and a node or document fragment is inserted into
the script element, after any script elements inserted at that time.&quot;

Split NonContentsChildChanged into NonContentsChildInserted and NonContentsChildRemoved to disambiguate
non-contents child such as text and element being removed or inserted. New behavior matches that of
Gecko and Chrome as well as the latest HTML5 specification.

Also deploy NoEventDispatchAssertion in more places. Unfortunately, this results in some DOM trees
internal to WebKit to be mutated while there is NoEventDispatchAssertion in the stack. Added a new RAII
object &quot;EventAllowedScope&quot; to temporarily disable this assertion within such a tree. CachedSVGFont's
ensureCustomFontData used to completely disable this assertion but we no longer have to do this either.

To clarify the new semantics, renamed isEventDispatchForbidden to isEventAllowedInMainThread with
the negated boolean value, and added a new variant isEventDispatchAllowedInSubtree, which checks
isEventDispatchForbidden() is true or if the node was one of an internal DOM node or its descendent
held by EventAllowedScope.

Inspired by https://chromium.googlesource.com/chromium/src/+/604e798ec6ee30f44d57a5c4a44ce3dab3a871ed

Tests: fast/html/script-must-not-run-when-child-is-adopted.html
       fast/html/script-must-not-run-when-child-is-removed.html

* dom/CharacterData.cpp:
(WebCore::CharacterData::notifyParentAfterChange): Added NoEventDispatchAssertion.
* dom/ContainerNode.cpp:
(WebCore::ContainerNode::insertBefore): Added NoEventDispatchAssertion around TreeScope's adoptIfNeeded
and insertBeforeCommon as done elsewhere.
(WebCore::ContainerNode::appendChildCommon): Added NoEventDispatchAssertion.
(WebCore::ContainerNode::changeForChildInsertion): Use NonContentsChildInserted here.
(WebCore::ContainerNode::notifyChildRemoved): Added NoEventDispatchAssertion.
(WebCore::ContainerNode::replaceChild): Moved adoptIfNeeded into NoEventDispatchAssertion.
(WebCore::ContainerNode::removeChild): Added NoEventDispatchAssertion.
(WebCore::ContainerNode::parserRemoveChild): Added NoEventDispatchAssertion.
(WebCore::ContainerNode::removeChildren): Call childrenChanged in NoEventDispatchAssertion.
(WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck): Moved adoptIfNeeded into
NoEventDispatchAssertion.
(WebCore::dispatchChildInsertionEvents): Check the forbidden-ness more precisely.
(WebCore::dispatchChildRemovalEvents): Ditto.
* dom/ContainerNode.h:
(WebCore::ContainerNode::ChildChange::isInsertion): Added.
* dom/ContainerNodeAlgorithms.cpp:
(WebCore::notifyChildNodeInserted): Check the forbidden-ness more precisely. Here, we check against
insertionPoint since EventAllowedScope checks against the root node.
* dom/Document.cpp:
(WebCore::Document::adoptNode): Assert the node to be adopted has not been inserted back, or else
remove() had resulted in an exception before calling TreeScope::adoptIfNeeded.
* dom/Element.cpp:
(WebCore::Element::childrenChanged):
* dom/NoEventDispatchAssertion.h:
(WebCore::NoEventDispatchAssertion::isEventDispatchForbidden): Added a new variant that takes a node.
If this node is a descendent of a node &quot;marked as safe&quot; by EventAllowedScope, then we don't consider
the event dispatch to be forbidden.
(WebCore::NoEventDispatchAssertion::dropTemporarily): Deleted.
(WebCore::NoEventDispatchAssertion::restoreDropped): Deleted.
(WebCore::NoEventDispatchAssertion::EventAllowedScope): Added. A RAII object which marks descendants of
a given node as &quot;safe&quot; for the purpose of checking isEventDispatchForbidden.
(WebCore::NoEventDispatchAssertion::EventAllowedScope::EventAllowedScope): Added. There can be a chain
of EventAllowedScope objects in the stack. s_currentScope points to the most recently instantiated
RAII object, and each instance remembers prior instance. 
(WebCore::NoEventDispatchAssertion::EventAllowedScope::~EventAllowedScope): Added.
(WebCore::NoEventDispatchAssertion::EventAllowedScope::isAllowedNode): Added. Returns true if the given
node is a descendent of any node held by instances of EventAllowedScope.
(WebCore::NoEventDispatchAssertion::EventAllowedScope::isAllowedNodeInternal): Added. A helper function
for isAllowedNode.
* dom/Node.cpp:
(WebCore::Node::dispatchSubtreeModifiedEvent): Check the forbidden-ness more precisely.
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::childrenChanged): Only prepare the script if we've inserted nodes.
(WebCore::ScriptElement::executeClassicScript): Assert isEventDispatchForbidden is false since running
arbitrary author scripts can, indeed, result dispatch any events.
* dom/ScriptElement.h:
* html/HTMLElement.cpp:
(WebCore::textToFragment): Made this a static local function and not return an exception since there
is no way appendChild called in this function can throw an exception.
(WebCore::HTMLElement::setInnerText): Create EventAllowedScope for the fragment. It's called called by
HTMLTextAreaElement's childrenChanged to update its UA shadow tree, and it's dispatching as event on
a new fragment can't execute arbitrary scripts since it has never been exposed to author scripts.
Because of the precise-ness of this check, this does not disable the assertion for &quot;this&quot; element.
HTMLTextFormControlElement::setInnerTextValue explicitly creates another EventAllowedScope to mark
the shadow tree into which the fragment is inserted safe.
(WebCore::HTMLElement::setOuterText):
* html/HTMLElement.h:
* html/HTMLScriptElement.cpp:
(WebCore::HTMLScriptElement::childrenChanged):
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::setInnerTextValue): See above (setInnerText).
* html/track/VTTCue.cpp:
(WebCore::VTTCue::createCueRenderingTree): Create EventAllowedScope for the cloned fragment here since
the VTT tree is never exposed to author scripts.
(WebCore::VTTCue::updateDisplayTree): Ditto.
* loader/cache/CachedSVGFont.cpp:
(WebCore::CachedSVGFont::ensureCustomFontData): Use EventAllowedScope to disable assertions only on
the new SVG document we just created instead of disabling for all DOM trees.
* svg/SVGScriptElement.cpp:
(WebCore::SVGScriptElement::childrenChanged):

LayoutTests:

Added regression tests for adopting or removing a child node of a script element.
The script must not run when nodes are adopted or removed.

* fast/html/script-must-not-run-when-child-is-adopted-expected.txt: Added.
* fast/html/script-must-not-run-when-child-is-adopted.html: Added.
* fast/html/script-must-not-run-when-child-is-removed-expected.txt: Added.
* fast/html/script-must-not-run-when-child-is-removed.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="#trunkSourceWebCoredomCharacterDatacpp">trunk/Source/WebCore/dom/CharacterData.cpp</a></li>
<li><a href="#trunkSourceWebCoredomContainerNodecpp">trunk/Source/WebCore/dom/ContainerNode.cpp</a></li>
<li><a href="#trunkSourceWebCoredomContainerNodeh">trunk/Source/WebCore/dom/ContainerNode.h</a></li>
<li><a href="#trunkSourceWebCoredomContainerNodeAlgorithmscpp">trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventDispatchercpp">trunk/Source/WebCore/dom/EventDispatcher.cpp</a></li>
<li><a href="#trunkSourceWebCoredomEventTargetcpp">trunk/Source/WebCore/dom/EventTarget.cpp</a></li>
<li><a href="#trunkSourceWebCoredomNoEventDispatchAssertionh">trunk/Source/WebCore/dom/NoEventDispatchAssertion.h</a></li>
<li><a href="#trunkSourceWebCoredomNodecpp">trunk/Source/WebCore/dom/Node.cpp</a></li>
<li><a href="#trunkSourceWebCoredomScriptElementcpp">trunk/Source/WebCore/dom/ScriptElement.cpp</a></li>
<li><a href="#trunkSourceWebCoredomScriptElementh">trunk/Source/WebCore/dom/ScriptElement.h</a></li>
<li><a href="#trunkSourceWebCoredomWebKitNamedFlowcpp">trunk/Source/WebCore/dom/WebKitNamedFlow.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLElementcpp">trunk/Source/WebCore/html/HTMLElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLElementh">trunk/Source/WebCore/html/HTMLElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLMediaElementcpp">trunk/Source/WebCore/html/HTMLMediaElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLScriptElementcpp">trunk/Source/WebCore/html/HTMLScriptElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLTextFormControlElementcpp">trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmltrackVTTCuecpp">trunk/Source/WebCore/html/track/VTTCue.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedSVGFontcpp">trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp</a></li>
<li><a href="#trunkSourceWebCoresvgSVGScriptElementcpp">trunk/Source/WebCore/svg/SVGScriptElement.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisadoptedexpectedtxt">trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisadoptedhtml">trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted.html</a></li>
<li><a href="#trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisremovedexpectedtxt">trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisremovedhtml">trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/LayoutTests/ChangeLog        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2017-02-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Adopting a child node of a script element can run script
+        https://bugs.webkit.org/show_bug.cgi?id=167318
+
+        Reviewed by Darin Adler.
+
+        Added regression tests for adopting or removing a child node of a script element.
+        The script must not run when nodes are adopted or removed.
+
+        * fast/html/script-must-not-run-when-child-is-adopted-expected.txt: Added.
+        * fast/html/script-must-not-run-when-child-is-adopted.html: Added.
+        * fast/html/script-must-not-run-when-child-is-removed-expected.txt: Added.
+        * fast/html/script-must-not-run-when-child-is-removed.html: Added.
+
</ins><span class="cx"> 2017-02-09  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MediaStream] Remove legacy Navigator.webkitGetUserMedia
</span></span></pre></div>
<a id="trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisadoptedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted-expected.txt (0 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted-expected.txt        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+Adopting a script element must not run the script.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Testing HTMLScriptElement
+PASS didRunScript is false
+PASS div.parentNode is not doc.body
+PASS div.parentNode is null
+PASS div.ownerDocument is document
+
+Testing SVGScriptElement
+PASS didRunScript is false
+PASS div.parentNode is not doc.body
+PASS div.parentNode is null
+PASS div.ownerDocument is document
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisadoptedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted.html (0 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted.html                                (rev 0)
+++ trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-adopted.html        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;div id=&quot;test-container&quot;&gt;&lt;/div&gt;
+&lt;script src=&quot;../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+description('Adopting a script element must not run the script.');
+
+let testContainer = document.getElementById('test-container');
+
+var doc;
+var didRunScript;
+var div;
+function runTest(createScriptElement)
+{
+    didRunScript = false;
+    div = document.createElement('div');
+
+    let iframe = document.createElement('iframe');
+    testContainer.appendChild(iframe);
+
+    doc = iframe.contentDocument;
+    let script = createScriptElement(doc);
+    script.type = 'invalid-type';
+    script.textContent = 'parent.didRunScript = true; document.body.appendChild(parent.div)';
+
+    script.appendChild(div);
+    doc.body.appendChild(script);
+
+    script.type = '';
+    document.adoptNode(div);
+    testContainer.innerHTML = '';
+
+    shouldBeFalse('didRunScript');
+    shouldNotBe('div.parentNode', 'doc.body');
+    shouldBe('div.parentNode', 'null');
+    shouldBe('div.ownerDocument', 'document');
+}
+
+debug('Testing HTMLScriptElement');
+runTest((doc) =&gt; doc.createElement('script'));
+
+debug('');
+debug('Testing SVGScriptElement');
+runTest((doc) =&gt; doc.createElementNS('http://www.w3.org/2000/svg', 'script'));
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisremovedexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed-expected.txt (0 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed-expected.txt        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -0,0 +1,15 @@
</span><ins>+Adopting a script element must not run the script.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS script = scriptElement(&quot;html&quot;); script.removeChild(textChild); didRunScript is false
+PASS script = scriptElement(&quot;svg&quot;); script.removeChild(textChild); didRunScript is false
+PASS script = scriptElement(&quot;html&quot;); script.removeChild(elementChild); didRunScript is false
+PASS script = scriptElement(&quot;svg&quot;); script.removeChild(elementChild); didRunScript is false
+PASS script = scriptElement(&quot;html&quot;); script.removeChild(commentChild); didRunScript is false
+PASS script = scriptElement(&quot;svg&quot;); script.removeChild(commentChild); didRunScript is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasthtmlscriptmustnotrunwhenchildisremovedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed.html (0 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed.html                                (rev 0)
+++ trunk/LayoutTests/fast/html/script-must-not-run-when-child-is-removed.html        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;div id=&quot;test-container&quot;&gt;&lt;/div&gt;
+&lt;script src=&quot;../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+
+description('Adopting a script element must not run the script.');
+
+let testContainer = document.getElementById('test-container');
+
+var didRunScript;
+var textChild;
+var elementChild;
+var commentChild;
+function scriptElement(type)
+{
+    didRunScript = false;
+
+    let namespaceURI = type == 'html' ? 'http://www.w3.org/1999/xhtml' : 'http://www.w3.org/2000/svg';
+    let script = document.createElementNS(namespaceURI, 'script');
+    script.type = 'invalid-type';
+    script.textContent = 'didRunScript = true';
+
+    document.body.appendChild(script);
+
+    textChild = document.createTextNode('');
+    script.appendChild(textChild);
+
+    elementChild = document.createElement('div');
+    script.appendChild(elementChild);
+
+    commentChild = document.createComment('');
+    script.appendChild(commentChild);
+
+    script.type = &quot;&quot;;
+    return script;
+}
+
+shouldBeFalse('script = scriptElement(&quot;html&quot;); script.removeChild(textChild); didRunScript');
+shouldBeFalse('script = scriptElement(&quot;svg&quot;); script.removeChild(textChild); didRunScript');
+
+shouldBeFalse('script = scriptElement(&quot;html&quot;); script.removeChild(elementChild); didRunScript');
+shouldBeFalse('script = scriptElement(&quot;svg&quot;); script.removeChild(elementChild); didRunScript');
+
+shouldBeFalse('script = scriptElement(&quot;html&quot;); script.removeChild(commentChild); didRunScript');
+shouldBeFalse('script = scriptElement(&quot;svg&quot;); script.removeChild(commentChild); didRunScript');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/ChangeLog        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -1,3 +1,110 @@
</span><ins>+2017-02-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Adopting a child node of a script element can run script
+        https://bugs.webkit.org/show_bug.cgi?id=167318
+
+        Reviewed by Darin Adler.
+
+        The bug was caused by ScriptElement::childrenChanged indiscriminately running the script.
+        Do this only if some node has been inserted as spec'ed:
+
+        https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
+        &quot;The script element is connected and a node or document fragment is inserted into
+        the script element, after any script elements inserted at that time.&quot;
+
+        Split NonContentsChildChanged into NonContentsChildInserted and NonContentsChildRemoved to disambiguate
+        non-contents child such as text and element being removed or inserted. New behavior matches that of
+        Gecko and Chrome as well as the latest HTML5 specification.
+
+        Also deploy NoEventDispatchAssertion in more places. Unfortunately, this results in some DOM trees
+        internal to WebKit to be mutated while there is NoEventDispatchAssertion in the stack. Added a new RAII
+        object &quot;EventAllowedScope&quot; to temporarily disable this assertion within such a tree. CachedSVGFont's
+        ensureCustomFontData used to completely disable this assertion but we no longer have to do this either.
+
+        To clarify the new semantics, renamed isEventDispatchForbidden to isEventAllowedInMainThread with
+        the negated boolean value, and added a new variant isEventDispatchAllowedInSubtree, which checks
+        isEventDispatchForbidden() is true or if the node was one of an internal DOM node or its descendent
+        held by EventAllowedScope.
+
+        Inspired by https://chromium.googlesource.com/chromium/src/+/604e798ec6ee30f44d57a5c4a44ce3dab3a871ed
+
+        Tests: fast/html/script-must-not-run-when-child-is-adopted.html
+               fast/html/script-must-not-run-when-child-is-removed.html
+
+        * dom/CharacterData.cpp:
+        (WebCore::CharacterData::notifyParentAfterChange): Added NoEventDispatchAssertion.
+        * dom/ContainerNode.cpp:
+        (WebCore::ContainerNode::insertBefore): Added NoEventDispatchAssertion around TreeScope's adoptIfNeeded
+        and insertBeforeCommon as done elsewhere.
+        (WebCore::ContainerNode::appendChildCommon): Added NoEventDispatchAssertion.
+        (WebCore::ContainerNode::changeForChildInsertion): Use NonContentsChildInserted here.
+        (WebCore::ContainerNode::notifyChildRemoved): Added NoEventDispatchAssertion.
+        (WebCore::ContainerNode::replaceChild): Moved adoptIfNeeded into NoEventDispatchAssertion.
+        (WebCore::ContainerNode::removeChild): Added NoEventDispatchAssertion.
+        (WebCore::ContainerNode::parserRemoveChild): Added NoEventDispatchAssertion.
+        (WebCore::ContainerNode::removeChildren): Call childrenChanged in NoEventDispatchAssertion.
+        (WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck): Moved adoptIfNeeded into
+        NoEventDispatchAssertion.
+        (WebCore::dispatchChildInsertionEvents): Check the forbidden-ness more precisely.
+        (WebCore::dispatchChildRemovalEvents): Ditto.
+        * dom/ContainerNode.h:
+        (WebCore::ContainerNode::ChildChange::isInsertion): Added.
+        * dom/ContainerNodeAlgorithms.cpp:
+        (WebCore::notifyChildNodeInserted): Check the forbidden-ness more precisely. Here, we check against
+        insertionPoint since EventAllowedScope checks against the root node.
+        * dom/Document.cpp:
+        (WebCore::Document::adoptNode): Assert the node to be adopted has not been inserted back, or else
+        remove() had resulted in an exception before calling TreeScope::adoptIfNeeded.
+        * dom/Element.cpp:
+        (WebCore::Element::childrenChanged):
+        * dom/NoEventDispatchAssertion.h:
+        (WebCore::NoEventDispatchAssertion::isEventDispatchForbidden): Added a new variant that takes a node.
+        If this node is a descendent of a node &quot;marked as safe&quot; by EventAllowedScope, then we don't consider
+        the event dispatch to be forbidden.
+        (WebCore::NoEventDispatchAssertion::dropTemporarily): Deleted.
+        (WebCore::NoEventDispatchAssertion::restoreDropped): Deleted.
+        (WebCore::NoEventDispatchAssertion::EventAllowedScope): Added. A RAII object which marks descendants of
+        a given node as &quot;safe&quot; for the purpose of checking isEventDispatchForbidden.
+        (WebCore::NoEventDispatchAssertion::EventAllowedScope::EventAllowedScope): Added. There can be a chain
+        of EventAllowedScope objects in the stack. s_currentScope points to the most recently instantiated
+        RAII object, and each instance remembers prior instance. 
+        (WebCore::NoEventDispatchAssertion::EventAllowedScope::~EventAllowedScope): Added.
+        (WebCore::NoEventDispatchAssertion::EventAllowedScope::isAllowedNode): Added. Returns true if the given
+        node is a descendent of any node held by instances of EventAllowedScope.
+        (WebCore::NoEventDispatchAssertion::EventAllowedScope::isAllowedNodeInternal): Added. A helper function
+        for isAllowedNode.
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchSubtreeModifiedEvent): Check the forbidden-ness more precisely.
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::childrenChanged): Only prepare the script if we've inserted nodes.
+        (WebCore::ScriptElement::executeClassicScript): Assert isEventDispatchForbidden is false since running
+        arbitrary author scripts can, indeed, result dispatch any events.
+        * dom/ScriptElement.h:
+        * html/HTMLElement.cpp:
+        (WebCore::textToFragment): Made this a static local function and not return an exception since there
+        is no way appendChild called in this function can throw an exception.
+        (WebCore::HTMLElement::setInnerText): Create EventAllowedScope for the fragment. It's called called by
+        HTMLTextAreaElement's childrenChanged to update its UA shadow tree, and it's dispatching as event on
+        a new fragment can't execute arbitrary scripts since it has never been exposed to author scripts.
+        Because of the precise-ness of this check, this does not disable the assertion for &quot;this&quot; element.
+        HTMLTextFormControlElement::setInnerTextValue explicitly creates another EventAllowedScope to mark
+        the shadow tree into which the fragment is inserted safe.
+        (WebCore::HTMLElement::setOuterText):
+        * html/HTMLElement.h:
+        * html/HTMLScriptElement.cpp:
+        (WebCore::HTMLScriptElement::childrenChanged):
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::setInnerTextValue): See above (setInnerText).
+        * html/track/VTTCue.cpp:
+        (WebCore::VTTCue::createCueRenderingTree): Create EventAllowedScope for the cloned fragment here since
+        the VTT tree is never exposed to author scripts.
+        (WebCore::VTTCue::updateDisplayTree): Ditto.
+        * loader/cache/CachedSVGFont.cpp:
+        (WebCore::CachedSVGFont::ensureCustomFontData): Use EventAllowedScope to disable assertions only on
+        the new SVG document we just created instead of disabling for all DOM trees.
+        * svg/SVGScriptElement.cpp:
+        (WebCore::SVGScriptElement::childrenChanged):
+
</ins><span class="cx"> 2017-02-09  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Document should always have a Settings.
</span></span></pre></div>
<a id="trunkSourceWebCoredomCharacterDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/CharacterData.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/CharacterData.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/CharacterData.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;MutationEvent.h&quot;
</span><span class="cx"> #include &quot;MutationObserverInterestGroup.h&quot;
</span><span class="cx"> #include &quot;MutationRecord.h&quot;
</span><ins>+#include &quot;NoEventDispatchAssertion.h&quot;
</ins><span class="cx"> #include &quot;ProcessingInstruction.h&quot;
</span><span class="cx"> #include &quot;RenderText.h&quot;
</span><span class="cx"> #include &quot;StyleInheritedData.h&quot;
</span><span class="lines">@@ -207,6 +208,8 @@
</span><span class="cx"> 
</span><span class="cx"> void CharacterData::notifyParentAfterChange(ContainerNode::ChildChangeSource source)
</span><span class="cx"> {
</span><ins>+    NoEventDispatchAssertion assertNoEventDispatch;
+
</ins><span class="cx">     document().incDOMTreeVersion();
</span><span class="cx"> 
</span><span class="cx">     if (!parentNode())
</span></span></pre></div>
<a id="trunkSourceWebCoredomContainerNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ContainerNode.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> unsigned NoEventDispatchAssertion::s_count = 0;
</span><ins>+NoEventDispatchAssertion::EventAllowedScope* NoEventDispatchAssertion::EventAllowedScope::s_currentScope = nullptr;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> static ExceptionOr&lt;void&gt; collectChildrenAndRemoveFromOldParent(Node&amp; node, NodeVector&amp; nodes)
</span><span class="lines">@@ -279,9 +280,12 @@
</span><span class="cx">         if (child-&gt;parentNode())
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        treeScope().adoptIfNeeded(child);
</del><ins>+        {
+            NoEventDispatchAssertion assertNoEventDispatch;
</ins><span class="cx"> 
</span><del>-        insertBeforeCommon(next, child);
</del><ins>+            treeScope().adoptIfNeeded(child);
+            insertBeforeCommon(next, child);
+        }
</ins><span class="cx"> 
</span><span class="cx">         updateTreeAfterInsertion(child);
</span><span class="cx">     }
</span><span class="lines">@@ -317,6 +321,8 @@
</span><span class="cx"> 
</span><span class="cx"> void ContainerNode::appendChildCommon(Node&amp; child)
</span><span class="cx"> {
</span><ins>+    NoEventDispatchAssertion assertNoEventDispatch;
+
</ins><span class="cx">     child.setParentNode(this);
</span><span class="cx"> 
</span><span class="cx">     if (m_lastChild) {
</span><span class="lines">@@ -334,7 +340,7 @@
</span><span class="cx">         return { AllChildrenReplaced, nullptr, nullptr, source };
</span><span class="cx"> 
</span><span class="cx">     return {
</span><del>-        child.isElementNode() ? ElementInserted : child.isTextNode() ? TextInserted : NonContentsChildChanged,
</del><ins>+        child.isElementNode() ? ElementInserted : child.isTextNode() ? TextInserted : NonContentsChildInserted,
</ins><span class="cx">         ElementTraversal::previousSibling(child),
</span><span class="cx">         ElementTraversal::nextSibling(child),
</span><span class="cx">         source
</span><span class="lines">@@ -356,10 +362,11 @@
</span><span class="cx"> 
</span><span class="cx"> void ContainerNode::notifyChildRemoved(Node&amp; child, Node* previousSibling, Node* nextSibling, ChildChangeSource source)
</span><span class="cx"> {
</span><ins>+    NoEventDispatchAssertion assertNoEventDispatch;
</ins><span class="cx">     notifyChildNodeRemoved(*this, child);
</span><span class="cx"> 
</span><span class="cx">     ChildChange change;
</span><del>-    change.type = is&lt;Element&gt;(child) ? ElementRemoved : is&lt;Text&gt;(child) ? TextRemoved : NonContentsChildChanged;
</del><ins>+    change.type = is&lt;Element&gt;(child) ? ElementRemoved : is&lt;Text&gt;(child) ? TextRemoved : NonContentsChildRemoved;
</ins><span class="cx">     change.previousSiblingElement = (!previousSibling || is&lt;Element&gt;(*previousSibling)) ? downcast&lt;Element&gt;(previousSibling) : ElementTraversal::previousSibling(*previousSibling);
</span><span class="cx">     change.nextSiblingElement = (!nextSibling || is&lt;Element&gt;(*nextSibling)) ? downcast&lt;Element&gt;(nextSibling) : ElementTraversal::nextSibling(*nextSibling);
</span><span class="cx">     change.source = source;
</span><span class="lines">@@ -450,10 +457,9 @@
</span><span class="cx">         if (child-&gt;parentNode())
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        treeScope().adoptIfNeeded(child);
-
</del><span class="cx">         {
</span><span class="cx">             NoEventDispatchAssertion assertNoEventDispatch;
</span><ins>+            treeScope().adoptIfNeeded(child);
</ins><span class="cx">             if (refChild)
</span><span class="cx">                 insertBeforeCommon(*refChild, child.get());
</span><span class="cx">             else
</span><span class="lines">@@ -534,6 +540,7 @@
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
</span><ins>+        NoEventDispatchAssertion assertNoEventDispatch;
</ins><span class="cx"> 
</span><span class="cx">         Node* prev = child-&gt;previousSibling();
</span><span class="cx">         Node* next = child-&gt;nextSibling();
</span><span class="lines">@@ -584,6 +591,8 @@
</span><span class="cx"> 
</span><span class="cx"> void ContainerNode::parserRemoveChild(Node&amp; oldChild)
</span><span class="cx"> {
</span><ins>+    NoEventDispatchAssertion assertNoEventDispatch;
+
</ins><span class="cx">     ASSERT(oldChild.parentNode() == this);
</span><span class="cx">     ASSERT(!oldChild.isDocumentFragment());
</span><span class="cx"> 
</span><span class="lines">@@ -675,12 +684,11 @@
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
</span><del>-        {
-            NoEventDispatchAssertion assertNoEventDispatch;
-            while (RefPtr&lt;Node&gt; child = m_firstChild) {
-                removeBetween(0, child-&gt;nextSibling(), *child);
-                notifyChildNodeRemoved(*this, *child);
-            }
</del><ins>+        NoEventDispatchAssertion assertNoEventDispatch;
+
+        while (RefPtr&lt;Node&gt; child = m_firstChild) {
+            removeBetween(0, child-&gt;nextSibling(), *child);
+            notifyChildNodeRemoved(*this, *child);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         ChildChange change = { AllChildrenRemoved, nullptr, nullptr, ChildChangeSourceAPI };
</span><span class="lines">@@ -733,11 +741,10 @@
</span><span class="cx">         if (child-&gt;parentNode())
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        treeScope().adoptIfNeeded(child);
-
</del><span class="cx">         // Append child to the end of the list
</span><span class="cx">         {
</span><span class="cx">             NoEventDispatchAssertion assertNoEventDispatch;
</span><ins>+            treeScope().adoptIfNeeded(child);
</ins><span class="cx">             appendChildCommon(child);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -807,7 +814,7 @@
</span><span class="cx">     if (child.isInShadowTree())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventDispatchAllowedInSubtree(child));
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Node&gt; c = &amp;child;
</span><span class="cx">     Ref&lt;Document&gt; document(child.document());
</span><span class="lines">@@ -829,7 +836,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventDispatchAllowedInSubtree(child));
</ins><span class="cx"> 
</span><span class="cx">     willCreatePossiblyOrphanedTreeByRemoval(&amp;child);
</span><span class="cx">     InspectorInstrumentation::willRemoveDOMNode(child.document(), child);
</span></span></pre></div>
<a id="trunkSourceWebCoredomContainerNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ContainerNode.h (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ContainerNode.h        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/ContainerNode.h        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx"> 
</span><span class="cx">     void cloneChildNodes(ContainerNode&amp; clone);
</span><span class="cx"> 
</span><del>-    enum ChildChangeType { ElementInserted, ElementRemoved, TextInserted, TextRemoved, TextChanged, AllChildrenRemoved, NonContentsChildChanged, AllChildrenReplaced };
</del><ins>+    enum ChildChangeType { ElementInserted, ElementRemoved, TextInserted, TextRemoved, TextChanged, AllChildrenRemoved, NonContentsChildRemoved, NonContentsChildInserted, AllChildrenReplaced };
</ins><span class="cx">     enum ChildChangeSource { ChildChangeSourceParser, ChildChangeSourceAPI };
</span><span class="cx">     struct ChildChange {
</span><span class="cx">         ChildChangeType type;
</span><span class="lines">@@ -76,6 +76,25 @@
</span><span class="cx">         Element* previousSiblingElement;
</span><span class="cx">         Element* nextSiblingElement;
</span><span class="cx">         ChildChangeSource source;
</span><ins>+
+        bool isInsertion() const
+        {
+            switch (type) {
+            case ElementInserted:
+            case TextInserted:
+            case NonContentsChildInserted:
+            case AllChildrenReplaced:
+                return true;
+            case ElementRemoved:
+            case TextRemoved:
+            case TextChanged:
+            case AllChildrenRemoved:
+            case NonContentsChildRemoved:
+                return false;
+            }
+            ASSERT_NOT_REACHED();
+            return false;
+        }
</ins><span class="cx">     };
</span><span class="cx">     virtual void childrenChanged(const ChildChange&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomContainerNodeAlgorithmscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;ContainerNodeAlgorithms.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;HTMLFrameOwnerElement.h&quot;
</span><ins>+#include &quot;HTMLTextAreaElement.h&quot;
</ins><span class="cx"> #include &quot;InspectorInstrumentation.h&quot;
</span><span class="cx"> #include &quot;NoEventDispatchAssertion.h&quot;
</span><span class="cx"> #include &quot;ShadowRoot.h&quot;
</span><span class="lines">@@ -90,7 +91,7 @@
</span><span class="cx"> 
</span><span class="cx"> void notifyChildNodeInserted(ContainerNode&amp; insertionPoint, Node&amp; node, NodeVector&amp; postInsertionNotificationTargets)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventDispatchAllowedInSubtree(insertionPoint));
</ins><span class="cx"> 
</span><span class="cx">     InspectorInstrumentation::didInsertDOMNode(node.document(), node);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/Document.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -1041,6 +1041,8 @@
</span><span class="cx">         auto result = source.remove();
</span><span class="cx">         if (result.hasException())
</span><span class="cx">             return result.releaseException();
</span><ins>+        ASSERT_WITH_SECURITY_IMPLICATION(!source.inDocument());
+        ASSERT_WITH_SECURITY_IMPLICATION(!source.parentNode());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     adoptIfNeeded(source);
</span><span class="lines">@@ -4066,7 +4068,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Document::dispatchWindowEvent(Event&amp; event, EventTarget* target)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     if (!m_domWindow)
</span><span class="cx">         return;
</span><span class="cx">     m_domWindow-&gt;dispatchEvent(event, target);
</span><span class="lines">@@ -4074,7 +4076,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Document::dispatchWindowLoadEvent()
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     if (!m_domWindow)
</span><span class="cx">         return;
</span><span class="cx">     m_domWindow-&gt;dispatchLoadEvent();
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/Element.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -2043,7 +2043,8 @@
</span><span class="cx">         case TextChanged:
</span><span class="cx">             shadowRoot-&gt;didChangeDefaultSlot();
</span><span class="cx">             break;
</span><del>-        case NonContentsChildChanged:
</del><ins>+        case NonContentsChildInserted:
+        case NonContentsChildRemoved:
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -2449,7 +2450,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Element::dispatchFocusInEvent(const AtomicString&amp; eventType, RefPtr&lt;Element&gt;&amp;&amp; oldFocusedElement)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().DOMFocusInEvent);
</span><span class="cx">     dispatchScopedEvent(FocusEvent::create(eventType, true, false, document().defaultView(), 0, WTFMove(oldFocusedElement)));
</span><span class="cx"> }
</span><span class="lines">@@ -2456,7 +2457,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Element::dispatchFocusOutEvent(const AtomicString&amp; eventType, RefPtr&lt;Element&gt;&amp;&amp; newFocusedElement)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     ASSERT(eventType == eventNames().focusoutEvent || eventType == eventNames().DOMFocusOutEvent);
</span><span class="cx">     dispatchScopedEvent(FocusEvent::create(eventType, true, false, document().defaultView(), 0, WTFMove(newFocusedElement)));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventDispatchercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventDispatcher.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool EventDispatcher::dispatchEvent(Node&amp; node, Event&amp; event)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     Ref&lt;Node&gt; protectedNode(node);
</span><span class="cx">     RefPtr&lt;FrameView&gt; view = node.document().view();
</span><span class="cx">     EventPath eventPath(node, event);
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx">     if (!event.target())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx"> 
</span><span class="cx">     InputElementClickState clickHandlingState;
</span><span class="cx">     if (is&lt;HTMLInputElement&gt;(node))
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventTarget.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/EventTarget.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -187,7 +187,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool EventTarget::fireEventListeners(Event&amp; event)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     ASSERT(event.isInitialized());
</span><span class="cx"> 
</span><span class="cx">     auto* data = eventTargetData();
</span></span></pre></div>
<a id="trunkSourceWebCoredomNoEventDispatchAssertionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/NoEventDispatchAssertion.h (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/NoEventDispatchAssertion.h        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/NoEventDispatchAssertion.h        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;ContainerNode.h&quot;
</ins><span class="cx"> #include &lt;wtf/MainThread.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -53,35 +54,58 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static bool isEventDispatchForbidden()
</del><ins>+    static bool isEventAllowedInMainThread()
</ins><span class="cx">     {
</span><span class="cx"> #if ASSERT_DISABLED
</span><del>-        return false;
</del><ins>+        return true;
</ins><span class="cx"> #else
</span><del>-        return isMainThread() &amp;&amp; s_count;
</del><ins>+        return !isMainThread() || !s_count;
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static unsigned dropTemporarily()
</del><ins>+    static bool isEventDispatchAllowedInSubtree(Node&amp; node)
</ins><span class="cx">     {
</span><del>-#if ASSERT_DISABLED
-        return 0;
-#else
-        unsigned count = s_count;
-        s_count = 0;
-        return count;
-#endif
</del><ins>+        return isEventAllowedInMainThread() || EventAllowedScope::isAllowedNode(node);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static void restoreDropped(unsigned count)
-    {
-#if ASSERT_DISABLED
-        UNUSED_PARAM(count);
</del><ins>+#if !ASSERT_DISABLED
+    class EventAllowedScope {
+    public:
+        explicit EventAllowedScope(ContainerNode&amp; userAgentContentRoot)
+            : m_eventAllowedTreeRoot(userAgentContentRoot)
+            , m_previousScope(s_currentScope)
+        {
+            s_currentScope = this;
+        }
+
+        ~EventAllowedScope()
+        {
+            s_currentScope = m_previousScope;
+        }
+
+        static bool isAllowedNode(Node&amp; node)
+        {
+            return s_currentScope &amp;&amp; s_currentScope-&gt;isAllowedNodeInternal(node);
+        }
+
+    private:
+        bool isAllowedNodeInternal(Node&amp; node)
+        {
+            return m_eventAllowedTreeRoot-&gt;contains(&amp;node) || (m_previousScope &amp;&amp; m_previousScope-&gt;isAllowedNodeInternal(node));
+        }
+
+        Ref&lt;ContainerNode&gt; m_eventAllowedTreeRoot;
+
+        EventAllowedScope* m_previousScope;
+        static EventAllowedScope* s_currentScope;
+    };
</ins><span class="cx"> #else
</span><del>-        ASSERT(!s_count);
-        s_count = count;
</del><ins>+    class EventAllowedScope {
+    public:
+        explicit EventAllowedScope(ContainerNode&amp;) { }
+        static bool isAllowedNode(Node&amp;) { return true; }
+    };
</ins><span class="cx"> #endif
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/Node.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -2192,7 +2192,7 @@
</span><span class="cx">     if (isInShadowTree())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventDispatchAllowedInSubtree(*this));
</ins><span class="cx"> 
</span><span class="cx">     if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
</span><span class="cx">         return;
</span><span class="lines">@@ -2205,7 +2205,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool Node::dispatchDOMActivateEvent(int detail, Event&amp; underlyingEvent)
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     Ref&lt;UIEvent&gt; event = UIEvent::create(eventNames().DOMActivateEvent, true, true, document().defaultView(), detail);
</span><span class="cx">     event-&gt;setUnderlyingEvent(&amp;underlyingEvent);
</span><span class="cx">     dispatchScopedEvent(event);
</span></span></pre></div>
<a id="trunkSourceWebCoredomScriptElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ScriptElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ScriptElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/ScriptElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;LoadableClassicScript.h&quot;
</span><span class="cx"> #include &quot;LoadableModuleScript.h&quot;
</span><span class="cx"> #include &quot;MIMETypeRegistry.h&quot;
</span><ins>+#include &quot;NoEventDispatchAssertion.h&quot;
</ins><span class="cx"> #include &quot;PendingScript.h&quot;
</span><span class="cx"> #include &quot;SVGScriptElement.h&quot;
</span><span class="cx"> #include &quot;ScriptController.h&quot;
</span><span class="lines">@@ -83,9 +84,9 @@
</span><span class="cx">     prepareScript(); // FIXME: Provide a real starting line number here.
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ScriptElement::childrenChanged()
</del><ins>+void ScriptElement::childrenChanged(const ContainerNode::ChildChange&amp; childChange)
</ins><span class="cx"> {
</span><del>-    if (!m_parserInserted &amp;&amp; m_element.isConnected())
</del><ins>+    if (!m_parserInserted &amp;&amp; childChange.isInsertion() &amp;&amp; m_element.isConnected())
</ins><span class="cx">         prepareScript(); // FIXME: Provide a real starting line number here.
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -365,6 +366,7 @@
</span><span class="cx"> 
</span><span class="cx"> void ScriptElement::executeClassicScript(const ScriptSourceCode&amp; sourceCode)
</span><span class="cx"> {
</span><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     ASSERT(m_alreadyStarted);
</span><span class="cx"> 
</span><span class="cx">     if (sourceCode.isEmpty())
</span></span></pre></div>
<a id="trunkSourceWebCoredomScriptElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ScriptElement.h (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ScriptElement.h        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/ScriptElement.h        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CachedResourceClient.h&quot;
</span><span class="cx"> #include &quot;CachedResourceHandle.h&quot;
</span><ins>+#include &quot;ContainerNode.h&quot;
</ins><span class="cx"> #include &quot;LoadableScript.h&quot;
</span><span class="cx"> #include &quot;LoadableScriptClient.h&quot;
</span><span class="cx"> #include &quot;Timer.h&quot;
</span><span class="lines">@@ -84,7 +85,7 @@
</span><span class="cx">     // Helper functions used by our parent classes.
</span><span class="cx">     bool shouldCallFinishedInsertingSubtree(ContainerNode&amp;);
</span><span class="cx">     void finishedInsertingSubtree();
</span><del>-    void childrenChanged();
</del><ins>+    void childrenChanged(const ContainerNode::ChildChange&amp;);
</ins><span class="cx">     void handleSourceAttribute(const String&amp; sourceURL);
</span><span class="cx">     void handleAsyncAttribute();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomWebKitNamedFlowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/WebKitNamedFlow.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/WebKitNamedFlow.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/dom/WebKitNamedFlow.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -212,7 +212,7 @@
</span><span class="cx"> 
</span><span class="cx"> void WebKitNamedFlow::dispatchRegionOversetChangeEvent()
</span><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx">     
</span><span class="cx">     // If the flow is in the &quot;NULL&quot; state the event should not be dispatched any more.
</span><span class="cx">     if (flowState() == FlowStateNull)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/HTMLElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -434,12 +434,14 @@
</span><span class="cx">         setAttributeEventListener(eventName, name, value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ExceptionOr&lt;Ref&lt;DocumentFragment&gt;&gt; HTMLElement::textToFragment(const String&amp; text)
</del><ins>+static Ref&lt;DocumentFragment&gt; textToFragment(Document&amp; document, const String&amp; text)
</ins><span class="cx"> {
</span><del>-    auto fragment = DocumentFragment::create(document());
</del><ins>+    auto fragment = DocumentFragment::create(document);
</ins><span class="cx"> 
</span><ins>+    // It's safe to dispatch events on the new fragment since author scripts have no access to it yet.
+    NoEventDispatchAssertion::EventAllowedScope allowedScope(fragment);
+
</ins><span class="cx">     for (unsigned start = 0, length = text.length(); start &lt; length; ) {
</span><del>-
</del><span class="cx">         // Find next line break.
</span><span class="cx">         UChar c = 0;
</span><span class="cx">         unsigned i;
</span><span class="lines">@@ -449,17 +451,11 @@
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        auto appendResult = fragment-&gt;appendChild(Text::create(document(), text.substring(start, i - start)));
-        if (appendResult.hasException())
-            return appendResult.releaseException();
-
</del><ins>+        fragment-&gt;appendChild(Text::create(document, text.substring(start, i - start)));
</ins><span class="cx">         if (i == length)
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        appendResult = fragment-&gt;appendChild(HTMLBRElement::create(document()));
-        if (appendResult.hasException())
-            return appendResult.releaseException();
-
</del><ins>+        fragment-&gt;appendChild(HTMLBRElement::create(document));
</ins><span class="cx">         // Make sure \r\n doesn't result in two line breaks.
</span><span class="cx">         if (c == '\r' &amp;&amp; i + 1 &lt; length &amp;&amp; text[i + 1] == '\n')
</span><span class="cx">             ++i;
</span><span class="lines">@@ -467,7 +463,7 @@
</span><span class="cx">         start = i + 1; // Character after line break.
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return WTFMove(fragment);
</del><ins>+    return fragment;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Returns the conforming 'dir' value associated with the state the attribute is in (in its canonical case), if any,
</span><span class="lines">@@ -527,11 +523,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Add text nodes and &lt;br&gt; elements.
</span><del>-    auto fragment = textToFragment(text);
-    if (fragment.hasException())
-        return fragment.releaseException();
</del><ins>+    auto fragment = textToFragment(document(), text);
</ins><span class="cx">     // FIXME: This should use replaceAllChildren() once it accepts DocumentFragments as input.
</span><del>-    return replaceChildrenWithFragment(*this, fragment.releaseReturnValue());
</del><ins>+    // It's safe to dispatch events on the new fragment since author scripts have no access to it yet.
+    NoEventDispatchAssertion::EventAllowedScope allowedScope(fragment.get());
+    return replaceChildrenWithFragment(*this, WTFMove(fragment));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ExceptionOr&lt;void&gt; HTMLElement::setOuterText(const String&amp; text)
</span><span class="lines">@@ -545,12 +541,9 @@
</span><span class="cx">     RefPtr&lt;Node&gt; newChild;
</span><span class="cx"> 
</span><span class="cx">     // Convert text to fragment with &lt;br&gt; tags instead of linebreaks if needed.
</span><del>-    if (text.contains('\r') || text.contains('\n')) {
-        auto result = textToFragment(text);
-        if (result.hasException())
-            return result.releaseException();
-        newChild = result.releaseReturnValue();
-    } else
</del><ins>+    if (text.contains('\r') || text.contains('\n'))
+        newChild = textToFragment(document(), text);
+    else
</ins><span class="cx">         newChild = Text::create(document(), text);
</span><span class="cx"> 
</span><span class="cx">     if (!parentNode())
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLElement.h (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLElement.h        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/HTMLElement.h        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -133,8 +133,6 @@
</span><span class="cx"> 
</span><span class="cx">     void mapLanguageAttributeToLocale(const AtomicString&amp;, MutableStyleProperties&amp;);
</span><span class="cx"> 
</span><del>-    ExceptionOr&lt;Ref&lt;DocumentFragment&gt;&gt; textToFragment(const String&amp;);
-
</del><span class="cx">     void dirAttributeChanged(const AtomicString&amp;);
</span><span class="cx">     void adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child);
</span><span class="cx">     void adjustDirectionalityIfNeededAfterChildrenChanged(Element* beforeChange, ChildChangeType);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLMediaElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLMediaElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -1284,7 +1284,7 @@
</span><span class="cx">     // Some of the code paths below this function dispatch the BeforeLoad event. This ASSERT helps
</span><span class="cx">     // us catch those bugs more quickly without needing all the branches to align to actually
</span><span class="cx">     // trigger the event.
</span><del>-    ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
</del><ins>+    ASSERT(NoEventDispatchAssertion::isEventAllowedInMainThread());
</ins><span class="cx"> 
</span><span class="cx">     // If we can't start a load right away, start it later.
</span><span class="cx">     if (!m_mediaSession-&gt;pageAllowsDataLoading(*this)) {
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLScriptElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLScriptElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLScriptElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/HTMLScriptElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx"> void HTMLScriptElement::childrenChanged(const ChildChange&amp; change)
</span><span class="cx"> {
</span><span class="cx">     HTMLElement::childrenChanged(change);
</span><del>-    ScriptElement::childrenChanged();
</del><ins>+    ScriptElement::childrenChanged(change);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLScriptElement::parseAttribute(const QualifiedName&amp; name, const AtomicString&amp; value)
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLTextFormControlElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;HTMLNames.h&quot;
</span><span class="cx"> #include &quot;HTMLParserIdioms.h&quot;
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><ins>+#include &quot;NoEventDispatchAssertion.h&quot;
</ins><span class="cx"> #include &quot;NodeTraversal.h&quot;
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> #include &quot;RenderTextControlSingleLine.h&quot;
</span><span class="lines">@@ -557,11 +558,17 @@
</span><span class="cx">                 cache-&gt;postNotification(this, AXObjectCache::AXValueChanged, TargetObservableParent);
</span><span class="cx">         }
</span><span class="cx"> #endif
</span><del>-        innerText-&gt;setInnerText(value);
</del><span class="cx"> 
</span><del>-        if (value.endsWith('\n') || value.endsWith('\r'))
-            innerText-&gt;appendChild(HTMLBRElement::create(document()));
</del><ins>+        {
+            // Events dispatched on the inner text element cannot execute arbitrary author scripts.
+            NoEventDispatchAssertion::EventAllowedScope allowedScope(*userAgentShadowRoot());
</ins><span class="cx"> 
</span><ins>+            innerText-&gt;setInnerText(value);
+
+            if (value.endsWith('\n') || value.endsWith('\r'))
+                innerText-&gt;appendChild(HTMLBRElement::create(document()));
+        }
+
</ins><span class="cx"> #if HAVE(ACCESSIBILITY) &amp;&amp; PLATFORM(COCOA)
</span><span class="cx">         if (textIsChanged &amp;&amp; renderer()) {
</span><span class="cx">             if (AXObjectCache* cache = document().existingAXObjectCache())
</span></span></pre></div>
<a id="trunkSourceWebCorehtmltrackVTTCuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/track/VTTCue.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/track/VTTCue.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/html/track/VTTCue.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include &quot;HTMLDivElement.h&quot;
</span><span class="cx"> #include &quot;HTMLSpanElement.h&quot;
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><ins>+#include &quot;NoEventDispatchAssertion.h&quot;
</ins><span class="cx"> #include &quot;NodeTraversal.h&quot;
</span><span class="cx"> #include &quot;RenderVTTCue.h&quot;
</span><span class="cx"> #include &quot;Text.h&quot;
</span><span class="lines">@@ -524,6 +525,10 @@
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     auto clonedFragment = DocumentFragment::create(ownerDocument());
</span><ins>+
+    // The cloned fragment is never exposed to author scripts so it's safe to dispatch events here.
+    NoEventDispatchAssertion::EventAllowedScope noEventDispatchAssertionDisabledForScope(clonedFragment);
+
</ins><span class="cx">     m_webVTTNodeTree-&gt;cloneChildNodes(clonedFragment);
</span><span class="cx">     return WTFMove(clonedFragment);
</span><span class="cx"> }
</span><span class="lines">@@ -779,6 +784,9 @@
</span><span class="cx">     if (!track()-&gt;isRendered())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    // Mutating the VTT contents is safe because it's never exposed to author scripts.
+    NoEventDispatchAssertion::EventAllowedScope allowedScopeForCueHighlightBox(*m_cueHighlightBox);
+
</ins><span class="cx">     // Clear the contents of the set.
</span><span class="cx">     m_cueHighlightBox-&gt;removeChildren();
</span><span class="cx"> 
</span><span class="lines">@@ -787,6 +795,8 @@
</span><span class="cx">     if (!referenceTree)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    NoEventDispatchAssertion::EventAllowedScope allowedScopeForReferenceTree(*referenceTree);
+
</ins><span class="cx">     markFutureAndPastNodes(referenceTree.get(), startMediaTime(), movieTime);
</span><span class="cx">     m_cueHighlightBox-&gt;appendChild(*referenceTree);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedSVGFontcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/loader/cache/CachedSVGFont.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -69,17 +69,20 @@
</span><span class="cx"> bool CachedSVGFont::ensureCustomFontData(const AtomicString&amp; remoteURI)
</span><span class="cx"> {
</span><span class="cx">     if (!m_externalSVGDocument &amp;&amp; !errorOccurred() &amp;&amp; !isLoading() &amp;&amp; m_data) {
</span><del>-        // We may get here during render tree updates when events are forbidden.
-        // Frameless document can't run scripts or call back to the client so this is safe.
-        auto count = NoEventDispatchAssertion::dropTemporarily();
</del><ins>+        bool sawError = false;
+        {
+            // We may get here during render tree updates when events are forbidden.
+            // Frameless document can't run scripts or call back to the client so this is safe.
+            m_externalSVGDocument = SVGDocument::create(nullptr, URL());
+            auto decoder = TextResourceDecoder::create(&quot;application/xml&quot;);
</ins><span class="cx"> 
</span><del>-        m_externalSVGDocument = SVGDocument::create(nullptr, URL());
-        RefPtr&lt;TextResourceDecoder&gt; decoder = TextResourceDecoder::create(&quot;application/xml&quot;);
-        m_externalSVGDocument-&gt;setContent(decoder-&gt;decodeAndFlush(m_data-&gt;data(), m_data-&gt;size()));
</del><ins>+            NoEventDispatchAssertion::EventAllowedScope allowedScope(*m_externalSVGDocument);
</ins><span class="cx"> 
</span><del>-        NoEventDispatchAssertion::restoreDropped(count);
</del><ins>+            m_externalSVGDocument-&gt;setContent(decoder-&gt;decodeAndFlush(m_data-&gt;data(), m_data-&gt;size()));
+            sawError = decoder-&gt;sawError();
+        }
</ins><span class="cx"> 
</span><del>-        if (decoder-&gt;sawError())
</del><ins>+        if (sawError)
</ins><span class="cx">             m_externalSVGDocument = nullptr;
</span><span class="cx">         if (m_externalSVGDocument)
</span><span class="cx">             maybeInitializeExternalSVGFontElement(remoteURI);
</span></span></pre></div>
<a id="trunkSourceWebCoresvgSVGScriptElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/SVGScriptElement.cpp (211964 => 211965)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/SVGScriptElement.cpp        2017-02-09 17:47:33 UTC (rev 211964)
+++ trunk/Source/WebCore/svg/SVGScriptElement.cpp        2017-02-09 17:59:45 UTC (rev 211965)
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx"> void SVGScriptElement::childrenChanged(const ChildChange&amp; change)
</span><span class="cx"> {
</span><span class="cx">     SVGElement::childrenChanged(change);
</span><del>-    ScriptElement::childrenChanged();
</del><ins>+    ScriptElement::childrenChanged(change);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SVGScriptElement::isURLAttribute(const Attribute&amp; attribute) const
</span></span></pre>
</div>
</div>

</body>
</html>