<!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>[210318] 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/210318">210318</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2017-01-04 21:09:04 -0800 (Wed, 04 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move editing history scripts to WebCore PrivateHeaders
https://bugs.webkit.org/show_bug.cgi?id=166709
&lt;rdar://problem/29876612&gt;

Reviewed by Dan Bernstein.

Source/WebCore:

Move editing history scripts out of InternalScripts and into Scripts, and update the WebCore Copy Script build
phase to copy the editing scripts into PrivateHeaders.

No new tests, because there should be no behavior change.

* Scripts/DumpEditingHistory.js: Renamed from Source/WebCore/InternalScripts/DumpEditingHistory.js.
* Scripts/EditingHistoryUtil.js: Renamed from Source/WebCore/InternalScripts/EditingHistoryUtil.js.
* WebCore.xcodeproj/project.pbxproj:

Tools:

Update references to editing script files in WebCore that were moved.

* EditingHistory/EditingHistory.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsEditingHistoryEditingHistoryxcodeprojprojectpbxproj">trunk/Tools/EditingHistory/EditingHistory.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreScriptsDumpEditingHistoryjs">trunk/Source/WebCore/Scripts/DumpEditingHistory.js</a></li>
<li><a href="#trunkSourceWebCoreScriptsEditingHistoryUtiljs">trunk/Source/WebCore/Scripts/EditingHistoryUtil.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li>trunk/Source/WebCore/InternalScripts/</li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (210317 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-05 04:43:13 UTC (rev 210317)
+++ trunk/Source/WebCore/ChangeLog        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2017-01-04  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Move editing history scripts to WebCore PrivateHeaders
+        https://bugs.webkit.org/show_bug.cgi?id=166709
+        &lt;rdar://problem/29876612&gt;
+
+        Reviewed by Dan Bernstein.
+
+        Move editing history scripts out of InternalScripts and into Scripts, and update the WebCore Copy Script build
+        phase to copy the editing scripts into PrivateHeaders.
+
+        No new tests, because there should be no behavior change.
+
+        * Scripts/DumpEditingHistory.js: Renamed from Source/WebCore/InternalScripts/DumpEditingHistory.js.
+        * Scripts/EditingHistoryUtil.js: Renamed from Source/WebCore/InternalScripts/EditingHistoryUtil.js.
+        * WebCore.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2017-01-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: forced pseudo classes aren't cleared from inspected page when Inspector closes
</span></span></pre></div>
<a id="trunkSourceWebCoreScriptsDumpEditingHistoryjsfromrev210317trunkSourceWebCoreInternalScriptsDumpEditingHistoryjs"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Scripts/DumpEditingHistory.js (from rev 210317, trunk/Source/WebCore/InternalScripts/DumpEditingHistory.js) (0 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Scripts/DumpEditingHistory.js                                (rev 0)
+++ trunk/Source/WebCore/Scripts/DumpEditingHistory.js        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+(() =&gt; {
+    let initialized = false;
+    let globalNodeMap = new EditingHistory.GlobalNodeMap();
+    let topLevelUpdates = [];
+    let currentChildUpdates = [];
+    let isProcessingTopLevelUpdate = false;
+    let lastKnownSelectionState = null;
+    let mutationObserver = new MutationObserver(records =&gt; appendDOMUpdatesFromRecords(records));
+
+    function beginProcessingTopLevelUpdate() {
+        isProcessingTopLevelUpdate = true;
+    }
+
+    function endProcessingTopLevelUpdate(topLevelUpdate) {
+        topLevelUpdates.push(topLevelUpdate);
+        currentChildUpdates = [];
+        isProcessingTopLevelUpdate = false;
+    }
+
+    function appendDOMUpdatesFromRecords(records) {
+        if (!records.length)
+            return;
+
+        let newUpdates = EditingHistory.DOMUpdate.fromRecords(records, globalNodeMap);
+        if (isProcessingTopLevelUpdate)
+            currentChildUpdates = currentChildUpdates.concat(newUpdates);
+        else
+            topLevelUpdates = topLevelUpdates.concat(newUpdates);
+    }
+
+    function appendSelectionUpdateIfNecessary() {
+        let newSelectionState = EditingHistory.SelectionState.fromSelection(getSelection(), globalNodeMap);
+        if (newSelectionState.isEqual(lastKnownSelectionState))
+            return;
+
+        let update = new EditingHistory.SelectionUpdate(globalNodeMap, newSelectionState);
+        if (isProcessingTopLevelUpdate)
+            currentChildUpdates.push(update);
+        else
+            topLevelUpdates.push(update);
+        lastKnownSelectionState = newSelectionState;
+    }
+
+    document.body.setAttribute(&quot;contenteditable&quot;, true);
+    document.body.addEventListener(&quot;focus&quot;, () =&gt; {
+        if (initialized)
+            return;
+
+        initialized = true;
+
+        EditingHistory.getEditingHistoryAsJSONString = (formatted) =&gt; {
+            let record = {};
+            record.updates = topLevelUpdates.map(update =&gt; update.toObject());
+            record.globalNodeMap = globalNodeMap.toObject();
+            return formatted ? JSON.stringify(record, null, 4) : JSON.stringify(record);
+        };
+
+        document.addEventListener(&quot;selectionchange&quot;, () =&gt; {
+            appendSelectionUpdateIfNecessary();
+        });
+        document.addEventListener(&quot;beforeinput&quot;, event =&gt; {
+            appendDOMUpdatesFromRecords(mutationObserver.takeRecords());
+            beginProcessingTopLevelUpdate();
+        });
+
+        document.addEventListener(&quot;input&quot;, event =&gt; {
+            appendDOMUpdatesFromRecords(mutationObserver.takeRecords());
+            let eventData = event.dataTransfer ? event.dataTransfer.getData(&quot;text/html&quot;) : event.data;
+            lastKnownSelectionState = null;
+            endProcessingTopLevelUpdate(new EditingHistory.InputEventUpdate(globalNodeMap, currentChildUpdates, event.inputType, eventData, event.timeStamp));
+        });
+
+        document.addEventListener(&quot;keydown&quot;, event =&gt; {
+            if (event.key !== &quot;s&quot; || !event.metaKey)
+                return;
+
+            let fakeLink = document.createElement(&quot;a&quot;);
+            fakeLink.setAttribute(&quot;href&quot;, &quot;data:text/plain;charset=utf-8,&quot; + encodeURIComponent(EditingHistory.getEditingHistoryAsJSONString()));
+            fakeLink.setAttribute(&quot;download&quot;, &quot;record.json&quot;);
+            fakeLink.click();
+            event.preventDefault();
+        });
+
+        mutationObserver.observe(document, {
+            childList: true,
+            attributes: true,
+            characterData: true,
+            subtree: true,
+            attributeOldValue: true,
+            characterDataOldValue: true,
+        });
+    });
+})();
</ins></span></pre></div>
<a id="trunkSourceWebCoreScriptsEditingHistoryUtiljsfromrev210317trunkSourceWebCoreInternalScriptsEditingHistoryUtiljs"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Scripts/EditingHistoryUtil.js (from rev 210317, trunk/Source/WebCore/InternalScripts/EditingHistoryUtil.js) (0 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Scripts/EditingHistoryUtil.js                                (rev 0)
+++ trunk/Source/WebCore/Scripts/EditingHistoryUtil.js        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -0,0 +1,693 @@
</span><ins>+(() =&gt; {
+    class Obfuscator {
+        constructor() {
+            this._scrambledLowercaseLetters = this._scramble(Array(26).fill().map((_, i) =&gt; 97 + i));
+            this._scrambledUppercaseLetters = this._scramble(Array(26).fill().map((_, i) =&gt; 65 + i));
+            this._scrambledNumbers = this._scramble(Array(10).fill().map((_, i) =&gt; 48 + i));
+            this.enabled = false;
+        }
+
+        _scramble(array) {
+            for (var i = array.length - 1; i &gt; 0; i--) {
+                let j = Math.floor(Math.random() * (i + 1));
+                let temp = array[i];
+                array[i] = array[j];
+                array[j] = temp;
+            }
+            return array;
+        }
+
+        applyToText(text) {
+            if (!this.enabled || !text)
+                return text;
+
+            let result = &quot;&quot;;
+            for (let index = 0; index &lt; text.length; index++) {
+                let code = text.charCodeAt(index);
+                let numberIndex = this._scrambedNumberIndexForCode(code);
+                let lowercaseIndex = this._scrambedLowercaseIndexForCode(code);
+                let uppercaseIndex = this._scrambedUppercaseIndexForCode(code);
+
+                if (numberIndex != null)
+                    result += String.fromCharCode(this._scrambledNumbers[numberIndex]);
+                else if (lowercaseIndex != null)
+                    result += String.fromCharCode(this._scrambledLowercaseLetters[lowercaseIndex]);
+                else if (uppercaseIndex != null)
+                    result += String.fromCharCode(this._scrambledUppercaseLetters[uppercaseIndex]);
+                else
+                    result += text.charAt(index);
+            }
+            return result;
+        }
+
+        applyToFilename(filename) {
+            if (!this.enabled || !filename)
+                return filename;
+
+            let components = filename.split(&quot;.&quot;);
+            return components.map((component, index) =&gt; {
+                if (index == components.length - 1)
+                    return component;
+
+                return this.applyToText(component);
+            }).join(&quot;.&quot;);
+        }
+
+        _scrambedNumberIndexForCode(code) {
+            return 48 &lt;= code &amp;&amp; code &lt;= 57 ? code - 48 : null;
+        }
+
+        _scrambedLowercaseIndexForCode(code) {
+            return 97 &lt;= code &amp;&amp; code &lt;= 122 ? code - 97 : null;
+        }
+
+        _scrambedUppercaseIndexForCode(code) {
+            return 65 &lt;= code &amp;&amp; code &lt;= 90 ? code - 65 : null;
+        }
+
+        static shared() {
+            if (!Obfuscator._sharedInstance)
+                Obfuscator._sharedInstance = new Obfuscator();
+            return Obfuscator._sharedInstance;
+        }
+    }
+
+    function elementFromMarkdown(html) {
+        let temporaryDiv = document.createElement(&quot;div&quot;);
+        temporaryDiv.innerHTML = html;
+        return temporaryDiv.children[0];
+    }
+
+    class GlobalNodeMap {
+        constructor(nodesByGUID) {
+            this._nodesByGUID = nodesByGUID ? nodesByGUID : new Map();
+            this._guidsByNode = new Map();
+            this._currentGUID = 0;
+            for (let [guid, node] of this._nodesByGUID) {
+                this._guidsByNode.set(node, guid);
+                this._currentGUID = Math.max(this._currentGUID, guid);
+            }
+            this._currentGUID++;
+        }
+
+        nodesForGUIDs(guids) {
+            if (!guids.map)
+                guids = Array.from(guids);
+            return guids.map(guid =&gt; this.nodeForGUID(guid));
+        }
+
+        guidsForNodes(nodes) {
+            if (!nodes.map)
+                nodes = Array.from(nodes);
+            return nodes.map(node =&gt; this.guidForNode(node));
+        }
+
+        nodeForGUID(guid) {
+            if (!guid)
+                return null;
+
+            return this._nodesByGUID.get(guid);
+        }
+
+        guidForNode(node) {
+            if (!node)
+                return 0;
+
+            if (this.hasGUIDForNode(node))
+                return this._guidsByNode.get(node);
+
+            const guid = this._currentGUID;
+            this._guidsByNode.set(node, guid);
+            this._nodesByGUID.set(guid, node);
+            this._currentGUID++;
+            return guid;
+        }
+
+        hasGUIDForNode(node) {
+            return !!this._guidsByNode.get(node);
+        }
+
+        nodes() {
+            return Array.from(this._nodesByGUID.values());
+        }
+
+        toObject() {
+            let nodesAndGUIDsToProcess = [], guidsToProcess = new Set();
+            let guidsByNodeIterator = this._guidsByNode.entries();
+            for (let entry = guidsByNodeIterator.next(); !entry.done; entry = guidsByNodeIterator.next()) {
+                nodesAndGUIDsToProcess.push(entry.value);
+                guidsToProcess.add(entry.value[1]);
+            }
+
+            let iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_ALL);
+            for (let node = iterator.nextNode(); node; node = iterator.nextNode()) {
+                if (this.hasGUIDForNode(node))
+                    continue;
+
+                let newGUID = this.guidForNode(node);
+                nodesAndGUIDsToProcess.push([node, newGUID]);
+                guidsToProcess.add(newGUID);
+            }
+
+            let nodeInfoArray = [];
+            while (nodesAndGUIDsToProcess.length) {
+                let [node, guid] = nodesAndGUIDsToProcess.pop();
+                let info = {};
+                info.guid = guid;
+                info.tagName = node.tagName;
+                info.attributes = GlobalNodeMap.nodeAttributesToObject(node);
+                info.type = node.nodeType;
+                info.data = GlobalNodeMap.dataForNode(node);
+                if (node.hasChildNodes()) {
+                    info.childGUIDs = this.guidsForNodes(node.childNodes);
+                    for (let childGUID of info.childGUIDs) {
+                        if (!guidsToProcess.has(childGUID))
+                            nodesAndGUIDsToProcess.push([this.nodeForGUID(childGUID), childGUID]);
+                    }
+                }
+                nodeInfoArray.push(info);
+            }
+
+            return nodeInfoArray;
+        }
+
+        static fromObject(nodeInfoArray) {
+            let nodesByGUID = new Map();
+            for (let info of nodeInfoArray) {
+                let node = null;
+                if (info.type == Node.ELEMENT_NODE)
+                    node = GlobalNodeMap.elementFromTagName(info.tagName, info.attributes, info.data);
+
+                if (info.type == Node.TEXT_NODE)
+                    node = document.createTextNode(info.data);
+
+                if (info.type == Node.DOCUMENT_NODE)
+                    node = document;
+
+                console.assert(node);
+                nodesByGUID.set(info.guid, node);
+            }
+
+            // Then, set child nodes for all nodes that do not appear in the DOM.
+            for (let info of nodeInfoArray.filter(info =&gt; !!info.childGUIDs)) {
+                let node = nodesByGUID.get(info.guid);
+                for (let childGUID of info.childGUIDs)
+                     node.appendChild(nodesByGUID.get(childGUID));
+            }
+
+            return new GlobalNodeMap(nodesByGUID);
+        }
+
+        static dataForNode(node) {
+            if (node.nodeType === Node.TEXT_NODE)
+                return Obfuscator.shared().applyToText(node.data);
+
+            if (node.tagName &amp;&amp; node.tagName.toLowerCase() === &quot;attachment&quot;) {
+                return {
+                    type: node.file.type,
+                    name: Obfuscator.shared().applyToFilename(node.file.name),
+                    lastModified: new Date().getTime()
+                };
+            }
+
+            return null;
+        }
+
+        static elementFromTagName(tagName, attributes, data) {
+            let node = document.createElement(tagName);
+            for (let attributeName in attributes)
+                node.setAttribute(attributeName, attributes[attributeName]);
+
+            if (tagName.toLowerCase() == &quot;attachment&quot;) {
+                node.file = new File([`File named '${data.name}'`], data.name, {
+                    type: data.type,
+                    lastModified: data.lastModified
+                });
+            }
+
+            return node;
+        }
+
+        // Returns an Object containing attribute name =&gt; attribute value
+        static nodeAttributesToObject(node, attributesToExclude=[]) {
+            const excludeAttributesSet = new Set(attributesToExclude);
+            if (!node.attributes)
+                return null;
+
+            let attributeMap = {};
+            for (let index = 0; index &lt; node.attributes.length; index++) {
+                const attribute = node.attributes.item(index);
+                const [localName, value] = [attribute.localName, attribute.value];
+                if (excludeAttributesSet.has(localName))
+                    continue;
+
+                attributeMap[localName] = value;
+            }
+
+            return attributeMap;
+        }
+
+        descriptionHTMLForGUID(guid) {
+            return `&lt;span eh-guid=${guid} class=&quot;eh-node&quot;&gt;${this.nodeForGUID(guid).nodeName}&lt;/span&gt;`;
+        }
+
+        descriptionHTMLForNode(node) {
+            if (!node)
+                return &quot;(null)&quot;;
+            return `&lt;span eh-guid=${this.guidForNode(node)} class=&quot;eh-node&quot;&gt;${node.nodeName}&lt;/span&gt;`;
+        }
+    }
+
+    class SelectionState {
+        constructor(nodeMap, startNode, startOffset, endNode, endOffset, anchorNode, anchorOffset, focusNode, focusOffset) {
+            console.assert(nodeMap);
+            this.nodeMap = nodeMap;
+            this.startGUID = nodeMap.guidForNode(startNode);
+            this.startOffset = startOffset;
+            this.endGUID = nodeMap.guidForNode(endNode);
+            this.endOffset = endOffset;
+            this.anchorGUID = nodeMap.guidForNode(anchorNode);
+            this.anchorOffset = anchorOffset;
+            this.focusGUID = nodeMap.guidForNode(focusNode);
+            this.focusOffset = focusOffset;
+        }
+
+        isEqual(otherSelectionState) {
+            return otherSelectionState
+                &amp;&amp; this.startGUID === otherSelectionState.startGUID &amp;&amp; this.startOffset === otherSelectionState.startOffset
+                &amp;&amp; this.endGUID === otherSelectionState.endGUID &amp;&amp; this.endOffset === otherSelectionState.endOffset
+                &amp;&amp; this.anchorGUID === otherSelectionState.anchorGUID &amp;&amp; this.anchorOffset === otherSelectionState.anchorOffset
+                &amp;&amp; this.focusGUID === otherSelectionState.focusGUID &amp;&amp; this.focusOffset === otherSelectionState.focusOffset;
+        }
+
+        applyToSelection(selection) {
+            selection.removeAllRanges();
+            let range = document.createRange();
+            range.setStart(this.nodeMap.nodeForGUID(this.startGUID), this.startOffset);
+            range.setEnd(this.nodeMap.nodeForGUID(this.endGUID), this.endOffset);
+            selection.addRange(range);
+            selection.setBaseAndExtent(this.nodeMap.nodeForGUID(this.anchorGUID), this.anchorOffset, this.nodeMap.nodeForGUID(this.focusGUID), this.focusOffset);
+        }
+
+        static fromSelection(selection, nodeMap) {
+            let [startNode, startOffset, endNode, endOffset] = [null, 0, null, 0];
+            if (selection.rangeCount) {
+                let selectedRange = selection.getRangeAt(0);
+                startNode = selectedRange.startContainer;
+                startOffset = selectedRange.startOffset;
+                endNode = selectedRange.endContainer;
+                endOffset = selectedRange.endOffset;
+            }
+            return new SelectionState(
+                nodeMap, startNode, startOffset, endNode, endOffset,
+                selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset
+            );
+        }
+
+        toObject() {
+            return {
+                startGUID: this.startGUID, startOffset: this.startOffset, endGUID: this.endGUID, endOffset: this.endOffset,
+                anchorGUID: this.anchorGUID, anchorOffset: this.anchorOffset, focusGUID: this.focusGUID, focusOffset: this.focusOffset
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            if (!json)
+                return null;
+
+            return new SelectionState(
+                nodeMap, nodeMap.nodeForGUID(json.startGUID), json.startOffset, nodeMap.nodeForGUID(json.endGUID), json.endOffset,
+                nodeMap.nodeForGUID(json.anchorGUID), json.anchorOffset, nodeMap.nodeForGUID(json.focusGUID), json.focusOffset
+            );
+        }
+    }
+
+    class DOMUpdate {
+        constructor(nodeMap) {
+            console.assert(nodeMap);
+            this.nodeMap = nodeMap;
+        }
+
+        apply() {
+            throw &quot;Expected subclass implementation.&quot;;
+        }
+
+        unapply() {
+            throw &quot;Expected subclass implementation.&quot;;
+        }
+
+        targetNode() {
+            return this.nodeMap.nodeForGUID(this.targetGUID);
+        }
+
+        detailsElement() {
+            throw &quot;Expected subclass implementation.&quot;;
+        }
+
+        static ofType(type) {
+            if (!DOMUpdate._allTypes)
+                DOMUpdate._allTypes = { ChildListUpdate, CharacterDataUpdate, AttributeUpdate, InputEventUpdate, SelectionUpdate };
+            return DOMUpdate._allTypes[type];
+        }
+
+        static fromRecords(records, nodeMap) {
+            let updates = []
+                , characterDataUpdates = []
+                , attributeUpdates = [];
+
+            for (let record of records) {
+                let target = record.target;
+                switch (record.type) {
+                case &quot;characterData&quot;:
+                    var update = new CharacterDataUpdate(nodeMap, nodeMap.guidForNode(target), record.oldValue, target.data)
+                    updates.push(update);
+                    characterDataUpdates.push(update);
+                    break;
+                case &quot;childList&quot;:
+                    var update = new ChildListUpdate(nodeMap, nodeMap.guidForNode(target), nodeMap.guidsForNodes(record.addedNodes), nodeMap.guidsForNodes(record.removedNodes), nodeMap.guidForNode(record.nextSibling))
+                    updates.push(update);
+                    break;
+                case &quot;attributes&quot;:
+                    var update = new AttributeUpdate(nodeMap, nodeMap.guidForNode(target), record.attributeName, record.oldValue, target.getAttribute(record.attributeName))
+                    updates.push(update);
+                    attributeUpdates.push(update);
+                    break;
+                }
+            }
+
+            // Adjust all character data updates for the same target.
+            characterDataUpdates.forEach((currentUpdate, index) =&gt; {
+                if (index == characterDataUpdates.length - 1)
+                    return;
+
+                for (let nextUpdateIndex = index + 1; nextUpdateIndex &lt; characterDataUpdates.length; nextUpdateIndex++) {
+                    let nextUpdate = characterDataUpdates[nextUpdateIndex];
+                    if (currentUpdate.targetGUID === nextUpdate.targetGUID) {
+                        currentUpdate.newData = nextUpdate.oldData;
+                        break;
+                    }
+                }
+            });
+
+            // Adjust all attribute updates for the same target and attribute name.
+            attributeUpdates.forEach((currentUpdate, index) =&gt; {
+                if (index == attributeUpdates.length - 1)
+                    return;
+
+                for (let nextUpdateIndex = index + 1; nextUpdateIndex &lt; attributeUpdates.length; nextUpdateIndex++) {
+                    let nextUpdate = attributeUpdates[nextUpdateIndex];
+                    if (currentUpdate.targetGUID === nextUpdate.targetGUID &amp;&amp; currentUpdate.attribute === nextUpdate.attribute) {
+                        currentUpdate.newData = nextUpdate.oldData;
+                        break;
+                    }
+                }
+            });
+
+            return updates;
+        }
+    }
+
+    class ChildListUpdate extends DOMUpdate {
+        constructor(nodeMap, targetGUID, addedGUIDs, removedGUIDs, nextSiblingGUID) {
+            super(nodeMap);
+            this.targetGUID = targetGUID;
+            this.added = addedGUIDs;
+            this.removed = removedGUIDs;
+            this.nextSiblingGUID = nextSiblingGUID == undefined ? null : nextSiblingGUID;
+            console.assert(nodeMap.nodeForGUID(targetGUID));
+        }
+
+        apply() {
+            for (let removedNode of this._removedNodes())
+                removedNode.remove();
+
+            let target = this.targetNode();
+            for (let addedNode of this._addedNodes())
+                target.insertBefore(addedNode, this._nextSibling());
+        }
+
+        unapply() {
+            for (let addedNode of this._addedNodes())
+                addedNode.remove();
+
+            let target = this.targetNode();
+            for (let removedNode of this._removedNodes())
+                target.insertBefore(removedNode, this._nextSibling());
+        }
+
+        _nextSibling() {
+            if (this.nextSiblingGUID == null)
+                return null;
+            return this.nodeMap.nodeForGUID(this.nextSiblingGUID);
+        }
+
+        _removedNodes() {
+            return this.nodeMap.nodesForGUIDs(this.removed);
+        }
+
+        _addedNodes() {
+            return this.nodeMap.nodesForGUIDs(this.added);
+        }
+
+        toObject() {
+            return {
+                type: &quot;ChildListUpdate&quot;,
+                targetGUID: this.targetGUID,
+                addedGUIDs: this.added,
+                removedGUIDs: this.removed,
+                nextSiblingGUID: this.nextSiblingGUID
+            };
+        }
+
+        detailsElement() {
+            let nextSibling = this._nextSibling();
+            let html =
+            `&lt;details&gt;
+                &lt;summary&gt;child list changed&lt;/summary&gt;
+                &lt;ul&gt;
+                    &lt;li&gt;parent: ${this.nodeMap.descriptionHTMLForGUID(this.targetGUID)}&lt;/li&gt;
+                    &lt;li&gt;added: [ ${[this._addedNodes().map(node =&gt; this.nodeMap.descriptionHTMLForNode(node))]} ]&lt;/li&gt;
+                    &lt;li&gt;removed: [ ${[this._removedNodes().map(node =&gt; this.nodeMap.descriptionHTMLForNode(node))]} ]&lt;/li&gt;
+                    &lt;li&gt;before sibling: ${nextSibling ? this.nodeMap.descriptionHTMLForNode(nextSibling) : &quot;(null)&quot;}&lt;/li&gt;
+                &lt;/ul&gt;
+            &lt;/details&gt;`;
+            return elementFromMarkdown(html);
+        }
+
+        static fromObject(json, nodeMap) {
+            return new ChildListUpdate(nodeMap, json.targetGUID, json.addedGUIDs, json.removedGUIDs, json.nextSiblingGUID);
+        }
+    }
+
+    class CharacterDataUpdate extends DOMUpdate {
+        constructor(nodeMap, targetGUID, oldData, newData) {
+            super(nodeMap);
+            this.targetGUID = targetGUID;
+            this.oldData = oldData;
+            this.newData = newData;
+            console.assert(nodeMap.nodeForGUID(targetGUID));
+        }
+
+        apply() {
+            this.targetNode().data = this.newData;
+        }
+
+        unapply() {
+            this.targetNode().data = this.oldData;
+        }
+
+        detailsElement() {
+            let html =
+            `&lt;details&gt;
+                &lt;summary&gt;character data changed&lt;/summary&gt;
+                &lt;ul&gt;
+                    &lt;li&gt;old: ${this.oldData != null ? &quot;'&quot; + this.oldData + &quot;'&quot; : &quot;(null)&quot;}&lt;/li&gt;
+                    &lt;li&gt;new: ${this.newData != null ? &quot;'&quot; + this.newData + &quot;'&quot; : &quot;(null)&quot;}&lt;/li&gt;
+                &lt;/ul&gt;
+            &lt;/details&gt;`;
+            return elementFromMarkdown(html);
+        }
+
+        toObject() {
+            return {
+                type: &quot;CharacterDataUpdate&quot;,
+                targetGUID: this.targetGUID,
+                oldData: Obfuscator.shared().applyToText(this.oldData),
+                newData: Obfuscator.shared().applyToText(this.newData)
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            return new CharacterDataUpdate(nodeMap, json.targetGUID, json.oldData, json.newData);
+        }
+    }
+
+    class AttributeUpdate extends DOMUpdate {
+        constructor(nodeMap, targetGUID, attribute, oldValue, newValue) {
+            super(nodeMap);
+            this.targetGUID = targetGUID;
+            this.attribute = attribute;
+            this.oldValue = oldValue;
+            this.newValue = newValue;
+            console.assert(nodeMap.nodeForGUID(targetGUID));
+        }
+
+        apply() {
+            if (this.newValue == null)
+                this.targetNode().removeAttribute(this.attribute);
+            else
+                this.targetNode().setAttribute(this.attribute, this.newValue);
+        }
+
+        unapply() {
+            if (this.oldValue == null)
+                this.targetNode().removeAttribute(this.attribute);
+            else
+                this.targetNode().setAttribute(this.attribute, this.oldValue);
+        }
+
+        detailsElement() {
+            let html =
+            `&lt;details&gt;
+                &lt;summary&gt;attribute changed&lt;/summary&gt;
+                &lt;ul&gt;
+                    &lt;li&gt;target: ${this.nodeMap.descriptionHTMLForGUID(this.targetGUID)}&lt;/li&gt;
+                    &lt;li&gt;attribute: ${this.attribute}&lt;/li&gt;
+                    &lt;li&gt;old: ${this.oldValue != null ? &quot;'&quot; + this.oldValue + &quot;'&quot; : &quot;(null)&quot;}&lt;/li&gt;
+                    &lt;li&gt;new: ${this.newValue != null ? &quot;'&quot; + this.newValue + &quot;'&quot; : &quot;(null)&quot;}&lt;/li&gt;
+                &lt;/ul&gt;
+            &lt;/details&gt;`;
+            return elementFromMarkdown(html);
+        }
+
+        toObject() {
+            return {
+                type: &quot;AttributeUpdate&quot;,
+                targetGUID: this.targetGUID,
+                attribute: this.attribute,
+                oldValue: this.oldValue,
+                newValue: this.newValue
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            return new AttributeUpdate(nodeMap, json.targetGUID, json.attribute, json.oldValue, json.newValue);
+        }
+    }
+
+    class SelectionUpdate extends DOMUpdate {
+        constructor(nodeMap, state) {
+            super(nodeMap);
+            this.state = state;
+        }
+
+        // SelectionUpdates are not applied/unapplied by the normal means. The selection is applied via
+        // DOMUpdateHistoryContext.applyCurrentSelectionState instead, which considers the updates before and after the
+        // current update index.
+        apply() { }
+        unapply() { }
+
+        toObject() {
+            return {
+                type: &quot;SelectionUpdate&quot;,
+                state: this.state ? this.state.toObject() : null
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            return new SelectionUpdate(nodeMap, SelectionState.fromObject(json.state, nodeMap));
+        }
+
+        _rangeDescriptionHTML() {
+            return `(${this.nodeMap.descriptionHTMLForGUID(this.state.startGUID)}:${this.state.startOffset},
+                ${this.nodeMap.descriptionHTMLForGUID(this.state.endGUID)}:${this.state.endOffset})`;
+        }
+
+        _anchorDescriptionHTML() {
+            return `${this.nodeMap.descriptionHTMLForGUID(this.state.anchorGUID)}:${this.state.anchorOffset}`;
+        }
+
+        _focusDescriptionHTML() {
+            return `${this.nodeMap.descriptionHTMLForGUID(this.state.focusGUID)}:${this.state.focusOffset}`;
+        }
+
+        detailsElement() {
+            let html =
+            `&lt;details&gt;
+                &lt;summary&gt;Selection changed&lt;/summary&gt;
+                &lt;ul&gt;
+                    &lt;li&gt;range: ${this._rangeDescriptionHTML()}&lt;/li&gt;
+                    &lt;li&gt;anchor: ${this._anchorDescriptionHTML()}&lt;/li&gt;
+                    &lt;li&gt;focus: ${this._focusDescriptionHTML()}&lt;/li&gt;
+                &lt;/ul&gt;
+            &lt;/details&gt;`;
+            return elementFromMarkdown(html);
+        }
+    }
+
+    class InputEventUpdate extends DOMUpdate {
+        constructor(nodeMap, updates, inputType, data, timeStamp) {
+            super(nodeMap);
+            this.updates = updates;
+            this.inputType = inputType;
+            this.data = data;
+            this.timeStamp = timeStamp;
+        }
+
+        _obfuscatedData() {
+            return this.inputType.indexOf(&quot;insert&quot;) == 0 ? Obfuscator.shared().applyToText(this.data) : this.data;
+        }
+
+        apply() {
+            for (let update of this.updates)
+                update.apply();
+        }
+
+        unapply() {
+            for (let index = this.updates.length - 1; index &gt;= 0; index--)
+                this.updates[index].unapply();
+        }
+
+        toObject() {
+            return {
+                type: &quot;InputEventUpdate&quot;,
+                inputType: this.inputType,
+                data: this._obfuscatedData(),
+                timeStamp: this.timeStamp,
+                updates: this.updates.map(update =&gt; update.toObject())
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            let updates = json.updates.map(update =&gt; DOMUpdate.ofType(update.type).fromObject(update, nodeMap));
+            return new InputEventUpdate(nodeMap, updates, json.inputType, json.data, json.timeStamp);
+        }
+
+        detailsElement() {
+            let html =
+            `&lt;details&gt;
+                &lt;summary&gt;Input (${this.inputType})&lt;/summary&gt;
+                &lt;ul&gt;
+                    &lt;li&gt;time: ${this.timeStamp}&lt;/li&gt;
+                    &lt;li&gt;data: ${!this.data ? &quot;(null)&quot; : &quot;'&quot; + this.data + &quot;'&quot;}&lt;/li&gt;
+                &lt;/ul&gt;
+            &lt;/details&gt;`;
+            let topLevelDetails = elementFromMarkdown(html);
+            for (let update of this.updates)
+                topLevelDetails.children[topLevelDetails.childElementCount - 1].appendChild(update.detailsElement());
+            return topLevelDetails;
+        }
+    }
+
+    window.EditingHistory = {
+        GlobalNodeMap,
+        SelectionState,
+        DOMUpdate,
+        ChildListUpdate,
+        CharacterDataUpdate,
+        AttributeUpdate,
+        SelectionUpdate,
+        InputEventUpdate,
+        Obfuscator
+    };
+})();
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (210317 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-01-05 04:43:13 UTC (rev 210317)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -2213,8 +2213,6 @@
</span><span class="cx">                 51C81B8A0C4422F70019ECE3 /* FTPDirectoryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */; };
</span><span class="cx">                 51CBFC990D10E483002DBF51 /* CachedFramePlatformData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51CBFC980D10E483002DBF51 /* CachedFramePlatformData.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51D0C5160DAA90B7003B3831 /* JSStorageCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */; };
</span><del>-                51D394781DF2492200ABE875 /* DumpEditingHistory.js in Copy Internal Scripts */ = {isa = PBXBuildFile; fileRef = 51D394741DF2454000ABE875 /* DumpEditingHistory.js */; };
-                51D394791DF2492200ABE875 /* EditingHistoryUtil.js in Copy Internal Scripts */ = {isa = PBXBuildFile; fileRef = 51D394751DF2454000ABE875 /* EditingHistoryUtil.js */; };
</del><span class="cx">                 51D7236C1BB6174900478CA3 /* IDBResultData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D7236A1BB60BFE00478CA3 /* IDBResultData.cpp */; };
</span><span class="cx">                 51D7236D1BB6174900478CA3 /* IDBResultData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D7236B1BB60BFE00478CA3 /* IDBResultData.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51D7EFEA1BDE8F8C00E93E10 /* ThreadSafeDataBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 511FAEA91BDC989A00B4AFE4 /* ThreadSafeDataBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -6489,6 +6487,8 @@
</span><span class="cx">                 F478755519983AFF0024A287 /* ScrollSnapAnimatorState.mm in Sources */ = {isa = PBXBuildFile; fileRef = F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */; };
</span><span class="cx">                 F47A5E3E195B8C8A00483100 /* StyleScrollSnapPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 F47A5E3F195B8E4800483100 /* StyleScrollSnapPoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F47A5E3A195B8C8A00483100 /* StyleScrollSnapPoints.cpp */; };
</span><ins>+                F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
+                F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
</ins><span class="cx">                 F50664F7157F52DC00AC226F /* FormController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50664F5157F52DC00AC226F /* FormController.cpp */; };
</span><span class="cx">                 F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
</span><span class="cx">                 F513A3EA15FF4841001526DB /* ValidationMessageClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F513A3E915FF4841001526DB /* ValidationMessageClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -6948,6 +6948,8 @@
</span><span class="cx">                         dstPath = PrivateHeaders/Scripts;
</span><span class="cx">                         dstSubfolderSpec = 1;
</span><span class="cx">                         files = (
</span><ins>+                                F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */,
+                                F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */,
</ins><span class="cx">                                 3717D7E817ECC591003C276D /* extract-localizable-strings.pl in Copy Scripts */,
</span><span class="cx">                                 37D456FD1A9A50D8003330A1 /* LocalizableStrings.pm in Copy Scripts */,
</span><span class="cx">                         );
</span><span class="lines">@@ -6954,18 +6956,6 @@
</span><span class="cx">                         name = &quot;Copy Scripts&quot;;
</span><span class="cx">                         runOnlyForDeploymentPostprocessing = 0;
</span><span class="cx">                 };
</span><del>-                51D394771DF2486700ABE875 /* Copy Internal Scripts */ = {
-                        isa = PBXCopyFilesBuildPhase;
-                        buildActionMask = 8;
-                        dstPath = &quot;$(APPLE_INTERNAL_LIBRARY_DIR)/WebKit/InternalScripts&quot;;
-                        dstSubfolderSpec = 0;
-                        files = (
-                                51D394781DF2492200ABE875 /* DumpEditingHistory.js in Copy Internal Scripts */,
-                                51D394791DF2492200ABE875 /* EditingHistoryUtil.js in Copy Internal Scripts */,
-                        );
-                        name = &quot;Copy Internal Scripts&quot;;
-                        runOnlyForDeploymentPostprocessing = 1;
-                };
</del><span class="cx">                 CD0DBF001422765700280263 /* Copy Audio Resources */ = {
</span><span class="cx">                         isa = PBXCopyFilesBuildPhase;
</span><span class="cx">                         buildActionMask = 2147483647;
</span><span class="lines">@@ -9424,8 +9414,6 @@
</span><span class="cx">                 51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51CBFC980D10E483002DBF51 /* CachedFramePlatformData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedFramePlatformData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStorageCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                51D394741DF2454000ABE875 /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = InternalScripts/DumpEditingHistory.js; sourceTree = &quot;&lt;group&gt;&quot;; };
-                51D394751DF2454000ABE875 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = InternalScripts/EditingHistoryUtil.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 51D7196C181106DF0016DC51 /* DOMWindowIndexedDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowIndexedDatabase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51D7196D181106DF0016DC51 /* DOMWindowIndexedDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWindowIndexedDatabase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51D7196E181106DF0016DC51 /* DOMWindowIndexedDatabase.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMWindowIndexedDatabase.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -14516,6 +14504,8 @@
</span><span class="cx">                 F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollSnapAnimatorState.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F47A5E3A195B8C8A00483100 /* StyleScrollSnapPoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleScrollSnapPoints.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleScrollSnapPoints.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = Scripts/DumpEditingHistory.js; sourceTree = &quot;&lt;group&gt;&quot;; };
+                F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = Scripts/EditingHistoryUtil.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 F513A3E915FF4841001526DB /* ValidationMessageClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationMessageClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15421,7 +15411,6 @@
</span><span class="cx">                                 2E4346310F546A6800B0F1BA /* workers */,
</span><span class="cx">                                 E1F0424309839389006694EA /* xml */,
</span><span class="cx">                                 656580EC09D12B20000E61D7 /* Derived Sources */,
</span><del>-                                51D394731DF244BA00ABE875 /* InternalScripts */,
</del><span class="cx">                                 089C1665FE841158C02AAC07 /* Resources */,
</span><span class="cx">                                 3717D7E417ECC36C003C276D /* Scripts */,
</span><span class="cx">                                 0867D69AFE84028FC02AAC07 /* Frameworks */,
</span><span class="lines">@@ -16507,6 +16496,7 @@
</span><span class="cx">                 3717D7E417ECC36C003C276D /* Scripts */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                F48389791E1DD23A0076B7EA /* EditingHistory */,
</ins><span class="cx">                                 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */,
</span><span class="cx">                                 37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */,
</span><span class="cx">                         );
</span><span class="lines">@@ -17351,15 +17341,6 @@
</span><span class="cx">                         path = mac;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="cx">                 };
</span><del>-                51D394731DF244BA00ABE875 /* InternalScripts */ = {
-                        isa = PBXGroup;
-                        children = (
-                                51D394741DF2454000ABE875 /* DumpEditingHistory.js */,
-                                51D394751DF2454000ABE875 /* EditingHistoryUtil.js */,
-                        );
-                        name = InternalScripts;
-                        sourceTree = &quot;&lt;group&gt;&quot;;
-                };
</del><span class="cx">                 59B5977111086556007159E8 /* jsc */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><span class="lines">@@ -23347,6 +23328,15 @@
</span><span class="cx">                         path = mac;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="cx">                 };
</span><ins>+                F48389791E1DD23A0076B7EA /* EditingHistory */ = {
+                        isa = PBXGroup;
+                        children = (
+                                F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */,
+                                F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */,
+                        );
+                        name = EditingHistory;
+                        sourceTree = &quot;&lt;group&gt;&quot;;
+                };
</ins><span class="cx">                 F523D18402DE42E8018635CA /* css */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><span class="lines">@@ -28460,7 +28450,6 @@
</span><span class="cx">                                 37A1EAA3142699BC0087F425 /* Check For Inappropriate Objective-C Class Names */,
</span><span class="cx">                                 5DF50887116F3077005202AB /* Check For Inappropriate Files In Framework */,
</span><span class="cx">                                 71D6AA381DA4E69400B23969 /* Copy modern media controls code and assets */,
</span><del>-                                51D394771DF2486700ABE875 /* Copy Internal Scripts */,
</del><span class="cx">                         );
</span><span class="cx">                         buildRules = (
</span><span class="cx">                         );
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (210317 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-01-05 04:43:13 UTC (rev 210317)
+++ trunk/Tools/ChangeLog        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-01-04  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Move editing history scripts to WebCore PrivateHeaders
+        https://bugs.webkit.org/show_bug.cgi?id=166709
+        &lt;rdar://problem/29876612&gt;
+
+        Reviewed by Dan Bernstein.
+
+        Update references to editing script files in WebCore that were moved.
+
+        * EditingHistory/EditingHistory.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2017-01-04  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, build fix after r210313 part 2
</span></span></pre></div>
<a id="trunkToolsEditingHistoryEditingHistoryxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/EditingHistory/EditingHistory.xcodeproj/project.pbxproj (210317 => 210318)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/EditingHistory/EditingHistory.xcodeproj/project.pbxproj        2017-01-05 04:43:13 UTC (rev 210317)
+++ trunk/Tools/EditingHistory/EditingHistory.xcodeproj/project.pbxproj        2017-01-05 05:09:04 UTC (rev 210318)
</span><span class="lines">@@ -12,11 +12,11 @@
</span><span class="cx">                 516ADBE61DE156BB00E2B98D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB11DE155BD00E2B98D /* main.m */; };
</span><span class="cx">                 516ADBF31DE157AD00E2B98D /* RewindAndPlaybackTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBF21DE157AD00E2B98D /* RewindAndPlaybackTests.m */; };
</span><span class="cx">                 517FD93C1DE18DC900A73673 /* DOMTestingUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = 517FD93B1DE18DC900A73673 /* DOMTestingUtil.js */; };
</span><del>-                51D394801DF2541D00ABE875 /* DumpEditingHistory.js in Resources */ = {isa = PBXBuildFile; fileRef = 51D3947E1DF2541D00ABE875 /* DumpEditingHistory.js */; };
-                51D394811DF2541D00ABE875 /* EditingHistoryUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = 51D3947F1DF2541D00ABE875 /* EditingHistoryUtil.js */; };
</del><span class="cx">                 51ECC3E71DEE33CE00CB267E /* TestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB51DE155BD00E2B98D /* TestUtil.m */; };
</span><span class="cx">                 51ECC3E91DEE33D200CB267E /* WKWebViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB71DE155BD00E2B98D /* WKWebViewAdditions.m */; };
</span><span class="cx">                 51ECC3EA1DEE33DD00CB267E /* TestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB31DE155BD00E2B98D /* TestRunner.m */; };
</span><ins>+                F4BFB9891E1DE82D00862C24 /* DumpEditingHistory.js in Resources */ = {isa = PBXBuildFile; fileRef = F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */; };
+                F4BFB98A1E1DE82D00862C24 /* EditingHistoryUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */; };
</ins><span class="cx"> /* End PBXBuildFile section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXContainerItemProxy section */
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx">                 517FD93B1DE18DC900A73673 /* DOMTestingUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DOMTestingUtil.js; path = EditingHistory/Resources/DOMTestingUtil.js; sourceTree = SOURCE_ROOT; };
</span><span class="cx">                 51D3947E1DF2541D00ABE875 /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = ../../Source/WebCore/InternalScripts/DumpEditingHistory.js; sourceTree = SOURCE_ROOT; };
</span><span class="cx">                 51D3947F1DF2541D00ABE875 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = ../../Source/WebCore/InternalScripts/EditingHistoryUtil.js; sourceTree = SOURCE_ROOT; };
</span><ins>+                F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = DumpEditingHistory.js; path = ../../Source/WebCore/Scripts/DumpEditingHistory.js; sourceTree = &quot;&lt;group&gt;&quot;; };
+                F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = EditingHistoryUtil.js; path = ../../Source/WebCore/Scripts/EditingHistoryUtil.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx"> /* End PBXFileReference section */
</span><span class="cx"> 
</span><span class="cx"> /* Begin PBXFrameworksBuildPhase section */
</span><span class="lines">@@ -70,6 +72,8 @@
</span><span class="cx">                 512D7A8A1DE0FBEF0028F0E6 = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */,
+                                F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */,
</ins><span class="cx">                                 512D7A951DE0FBEF0028F0E6 /* EditingHistory */,
</span><span class="cx">                                 516ADBF11DE157AD00E2B98D /* EditingHistoryTests */,
</span><span class="cx">                                 512D7A941DE0FBEF0028F0E6 /* Products */,
</span><span class="lines">@@ -204,11 +208,11 @@
</span><span class="cx">                         isa = PBXResourcesBuildPhase;
</span><span class="cx">                         buildActionMask = 2147483647;
</span><span class="cx">                         files = (
</span><del>-                                51D394801DF2541D00ABE875 /* DumpEditingHistory.js in Resources */,
</del><ins>+                                F4BFB9891E1DE82D00862C24 /* DumpEditingHistory.js in Resources */,
+                                F4BFB98A1E1DE82D00862C24 /* EditingHistoryUtil.js in Resources */,
</ins><span class="cx">                                 516ADBE21DE156A900E2B98D /* CaptureHarness.html in Resources */,
</span><span class="cx">                                 517FD93C1DE18DC900A73673 /* DOMTestingUtil.js in Resources */,
</span><span class="cx">                                 516ADBE51DE156A900E2B98D /* PlaybackHarness.html in Resources */,
</span><del>-                                51D394811DF2541D00ABE875 /* EditingHistoryUtil.js in Resources */,
</del><span class="cx">                         );
</span><span class="cx">                         runOnlyForDeploymentPostprocessing = 0;
</span><span class="cx">                 };
</span></span></pre>
</div>
</div>

</body>
</html>