Title: [210318] trunk
Revision
210318
Author
[email protected]
Date
2017-01-04 21:09:04 -0800 (Wed, 04 Jan 2017)

Log Message

Move editing history scripts to WebCore PrivateHeaders
https://bugs.webkit.org/show_bug.cgi?id=166709
<rdar://problem/29876612>

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:

Modified Paths

Added Paths

Removed Paths

  • trunk/Source/WebCore/InternalScripts/

Diff

Modified: trunk/Source/WebCore/ChangeLog (210317 => 210318)


--- 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)
@@ -1,3 +1,20 @@
+2017-01-04  Wenson Hsieh  <[email protected]>
+
+        Move editing history scripts to WebCore PrivateHeaders
+        https://bugs.webkit.org/show_bug.cgi?id=166709
+        <rdar://problem/29876612>
+
+        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:
+
 2017-01-04  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: forced pseudo classes aren't cleared from inspected page when Inspector closes

Copied: trunk/Source/WebCore/Scripts/DumpEditingHistory.js (from rev 210317, trunk/Source/WebCore/InternalScripts/DumpEditingHistory.js) (0 => 210318)


--- trunk/Source/WebCore/Scripts/DumpEditingHistory.js	                        (rev 0)
+++ trunk/Source/WebCore/Scripts/DumpEditingHistory.js	2017-01-05 05:09:04 UTC (rev 210318)
@@ -0,0 +1,93 @@
+(() => {
+    let initialized = false;
+    let globalNodeMap = new EditingHistory.GlobalNodeMap();
+    let topLevelUpdates = [];
+    let currentChildUpdates = [];
+    let isProcessingTopLevelUpdate = false;
+    let lastKnownSelectionState = null;
+    let mutationObserver = new MutationObserver(records => 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("contenteditable", true);
+    document.body.addEventListener("focus", () => {
+        if (initialized)
+            return;
+
+        initialized = true;
+
+        EditingHistory.getEditingHistoryAsJSONString = (formatted) => {
+            let record = {};
+            record.updates = topLevelUpdates.map(update => update.toObject());
+            record.globalNodeMap = globalNodeMap.toObject();
+            return formatted ? JSON.stringify(record, null, 4) : JSON.stringify(record);
+        };
+
+        document.addEventListener("selectionchange", () => {
+            appendSelectionUpdateIfNecessary();
+        });
+        document.addEventListener("beforeinput", event => {
+            appendDOMUpdatesFromRecords(mutationObserver.takeRecords());
+            beginProcessingTopLevelUpdate();
+        });
+
+        document.addEventListener("input", event => {
+            appendDOMUpdatesFromRecords(mutationObserver.takeRecords());
+            let eventData = event.dataTransfer ? event.dataTransfer.getData("text/html") : event.data;
+            lastKnownSelectionState = null;
+            endProcessingTopLevelUpdate(new EditingHistory.InputEventUpdate(globalNodeMap, currentChildUpdates, event.inputType, eventData, event.timeStamp));
+        });
+
+        document.addEventListener("keydown", event => {
+            if (event.key !== "s" || !event.metaKey)
+                return;
+
+            let fakeLink = document.createElement("a");
+            fakeLink.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(EditingHistory.getEditingHistoryAsJSONString()));
+            fakeLink.setAttribute("download", "record.json");
+            fakeLink.click();
+            event.preventDefault();
+        });
+
+        mutationObserver.observe(document, {
+            childList: true,
+            attributes: true,
+            characterData: true,
+            subtree: true,
+            attributeOldValue: true,
+            characterDataOldValue: true,
+        });
+    });
+})();

Copied: trunk/Source/WebCore/Scripts/EditingHistoryUtil.js (from rev 210317, trunk/Source/WebCore/InternalScripts/EditingHistoryUtil.js) (0 => 210318)


--- trunk/Source/WebCore/Scripts/EditingHistoryUtil.js	                        (rev 0)
+++ trunk/Source/WebCore/Scripts/EditingHistoryUtil.js	2017-01-05 05:09:04 UTC (rev 210318)
@@ -0,0 +1,693 @@
+(() => {
+    class Obfuscator {
+        constructor() {
+            this._scrambledLowercaseLetters = this._scramble(Array(26).fill().map((_, i) => 97 + i));
+            this._scrambledUppercaseLetters = this._scramble(Array(26).fill().map((_, i) => 65 + i));
+            this._scrambledNumbers = this._scramble(Array(10).fill().map((_, i) => 48 + i));
+            this.enabled = false;
+        }
+
+        _scramble(array) {
+            for (var i = array.length - 1; i > 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 = "";
+            for (let index = 0; index < 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(".");
+            return components.map((component, index) => {
+                if (index == components.length - 1)
+                    return component;
+
+                return this.applyToText(component);
+            }).join(".");
+        }
+
+        _scrambedNumberIndexForCode(code) {
+            return 48 <= code && code <= 57 ? code - 48 : null;
+        }
+
+        _scrambedLowercaseIndexForCode(code) {
+            return 97 <= code && code <= 122 ? code - 97 : null;
+        }
+
+        _scrambedUppercaseIndexForCode(code) {
+            return 65 <= code && code <= 90 ? code - 65 : null;
+        }
+
+        static shared() {
+            if (!Obfuscator._sharedInstance)
+                Obfuscator._sharedInstance = new Obfuscator();
+            return Obfuscator._sharedInstance;
+        }
+    }
+
+    function elementFromMarkdown(html) {
+        let temporaryDiv = document.createElement("div");
+        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 => this.nodeForGUID(guid));
+        }
+
+        guidsForNodes(nodes) {
+            if (!nodes.map)
+                nodes = Array.from(nodes);
+            return nodes.map(node => 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 = ""
+                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 => !!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 && node.tagName.toLowerCase() === "attachment") {
+                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() == "attachment") {
+                node.file = new File([`File named '${data.name}'`], data.name, {
+                    type: data.type,
+                    lastModified: data.lastModified
+                });
+            }
+
+            return node;
+        }
+
+        // Returns an Object containing attribute name => attribute value
+        static nodeAttributesToObject(node, attributesToExclude=[]) {
+            const excludeAttributesSet = new Set(attributesToExclude);
+            if (!node.attributes)
+                return null;
+
+            let attributeMap = {};
+            for (let index = 0; index < 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 `<span eh-guid=${guid} class="eh-node">${this.nodeForGUID(guid).nodeName}</span>`;
+        }
+
+        descriptionHTMLForNode(node) {
+            if (!node)
+                return "(null)";
+            return `<span eh-guid=${this.guidForNode(node)} class="eh-node">${node.nodeName}</span>`;
+        }
+    }
+
+    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
+                && this.startGUID === otherSelectionState.startGUID && this.startOffset === otherSelectionState.startOffset
+                && this.endGUID === otherSelectionState.endGUID && this.endOffset === otherSelectionState.endOffset
+                && this.anchorGUID === otherSelectionState.anchorGUID && this.anchorOffset === otherSelectionState.anchorOffset
+                && this.focusGUID === otherSelectionState.focusGUID && 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 "Expected subclass implementation.";
+        }
+
+        unapply() {
+            throw "Expected subclass implementation.";
+        }
+
+        targetNode() {
+            return this.nodeMap.nodeForGUID(this.targetGUID);
+        }
+
+        detailsElement() {
+            throw "Expected subclass implementation.";
+        }
+
+        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 "characterData":
+                    var update = new CharacterDataUpdate(nodeMap, nodeMap.guidForNode(target), record.oldValue, target.data)
+                    updates.push(update);
+                    characterDataUpdates.push(update);
+                    break;
+                case "childList":
+                    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 "attributes":
+                    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) => {
+                if (index == characterDataUpdates.length - 1)
+                    return;
+
+                for (let nextUpdateIndex = index + 1; nextUpdateIndex < 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) => {
+                if (index == attributeUpdates.length - 1)
+                    return;
+
+                for (let nextUpdateIndex = index + 1; nextUpdateIndex < attributeUpdates.length; nextUpdateIndex++) {
+                    let nextUpdate = attributeUpdates[nextUpdateIndex];
+                    if (currentUpdate.targetGUID === nextUpdate.targetGUID && 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: "ChildListUpdate",
+                targetGUID: this.targetGUID,
+                addedGUIDs: this.added,
+                removedGUIDs: this.removed,
+                nextSiblingGUID: this.nextSiblingGUID
+            };
+        }
+
+        detailsElement() {
+            let nextSibling = this._nextSibling();
+            let html =
+            `<details>
+                <summary>child list changed</summary>
+                <ul>
+                    <li>parent: ${this.nodeMap.descriptionHTMLForGUID(this.targetGUID)}</li>
+                    <li>added: [ ${[this._addedNodes().map(node => this.nodeMap.descriptionHTMLForNode(node))]} ]</li>
+                    <li>removed: [ ${[this._removedNodes().map(node => this.nodeMap.descriptionHTMLForNode(node))]} ]</li>
+                    <li>before sibling: ${nextSibling ? this.nodeMap.descriptionHTMLForNode(nextSibling) : "(null)"}</li>
+                </ul>
+            </details>`;
+            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 = ""
+        }
+
+        unapply() {
+            this.targetNode().data = ""
+        }
+
+        detailsElement() {
+            let html =
+            `<details>
+                <summary>character data changed</summary>
+                <ul>
+                    <li>old: ${this.oldData != null ? "'" + this.oldData + "'" : "(null)"}</li>
+                    <li>new: ${this.newData != null ? "'" + this.newData + "'" : "(null)"}</li>
+                </ul>
+            </details>`;
+            return elementFromMarkdown(html);
+        }
+
+        toObject() {
+            return {
+                type: "CharacterDataUpdate",
+                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 =
+            `<details>
+                <summary>attribute changed</summary>
+                <ul>
+                    <li>target: ${this.nodeMap.descriptionHTMLForGUID(this.targetGUID)}</li>
+                    <li>attribute: ${this.attribute}</li>
+                    <li>old: ${this.oldValue != null ? "'" + this.oldValue + "'" : "(null)"}</li>
+                    <li>new: ${this.newValue != null ? "'" + this.newValue + "'" : "(null)"}</li>
+                </ul>
+            </details>`;
+            return elementFromMarkdown(html);
+        }
+
+        toObject() {
+            return {
+                type: "AttributeUpdate",
+                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: "SelectionUpdate",
+                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 =
+            `<details>
+                <summary>Selection changed</summary>
+                <ul>
+                    <li>range: ${this._rangeDescriptionHTML()}</li>
+                    <li>anchor: ${this._anchorDescriptionHTML()}</li>
+                    <li>focus: ${this._focusDescriptionHTML()}</li>
+                </ul>
+            </details>`;
+            return elementFromMarkdown(html);
+        }
+    }
+
+    class InputEventUpdate extends DOMUpdate {
+        constructor(nodeMap, updates, inputType, data, timeStamp) {
+            super(nodeMap);
+            this.updates = updates;
+            this.inputType = inputType;
+            this.data = ""
+            this.timeStamp = timeStamp;
+        }
+
+        _obfuscatedData() {
+            return this.inputType.indexOf("insert") == 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 >= 0; index--)
+                this.updates[index].unapply();
+        }
+
+        toObject() {
+            return {
+                type: "InputEventUpdate",
+                inputType: this.inputType,
+                data: this._obfuscatedData(),
+                timeStamp: this.timeStamp,
+                updates: this.updates.map(update => update.toObject())
+            };
+        }
+
+        static fromObject(json, nodeMap) {
+            let updates = json.updates.map(update => DOMUpdate.ofType(update.type).fromObject(update, nodeMap));
+            return new InputEventUpdate(nodeMap, updates, json.inputType, json.data, json.timeStamp);
+        }
+
+        detailsElement() {
+            let html =
+            `<details>
+                <summary>Input (${this.inputType})</summary>
+                <ul>
+                    <li>time: ${this.timeStamp}</li>
+                    <li>data: ${!this.data ? "(null)" : "'" + this.data + "'"}</li>
+                </ul>
+            </details>`;
+            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
+    };
+})();

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (210317 => 210318)


--- 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)
@@ -2213,8 +2213,6 @@
 		51C81B8A0C4422F70019ECE3 /* FTPDirectoryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */; };
 		51CBFC990D10E483002DBF51 /* CachedFramePlatformData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51CBFC980D10E483002DBF51 /* CachedFramePlatformData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51D0C5160DAA90B7003B3831 /* JSStorageCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */; };
-		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 */; };
 		51D7236C1BB6174900478CA3 /* IDBResultData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D7236A1BB60BFE00478CA3 /* IDBResultData.cpp */; };
 		51D7236D1BB6174900478CA3 /* IDBResultData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D7236B1BB60BFE00478CA3 /* IDBResultData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51D7EFEA1BDE8F8C00E93E10 /* ThreadSafeDataBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 511FAEA91BDC989A00B4AFE4 /* ThreadSafeDataBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6489,6 +6487,8 @@
 		F478755519983AFF0024A287 /* ScrollSnapAnimatorState.mm in Sources */ = {isa = PBXBuildFile; fileRef = F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */; };
 		F47A5E3E195B8C8A00483100 /* StyleScrollSnapPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F47A5E3F195B8E4800483100 /* StyleScrollSnapPoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F47A5E3A195B8C8A00483100 /* StyleScrollSnapPoints.cpp */; };
+		F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
+		F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
 		F50664F7157F52DC00AC226F /* FormController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F50664F5157F52DC00AC226F /* FormController.cpp */; };
 		F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
 		F513A3EA15FF4841001526DB /* ValidationMessageClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F513A3E915FF4841001526DB /* ValidationMessageClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6948,6 +6948,8 @@
 			dstPath = PrivateHeaders/Scripts;
 			dstSubfolderSpec = 1;
 			files = (
+				F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */,
+				F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */,
 				3717D7E817ECC591003C276D /* extract-localizable-strings.pl in Copy Scripts */,
 				37D456FD1A9A50D8003330A1 /* LocalizableStrings.pm in Copy Scripts */,
 			);
@@ -6954,18 +6956,6 @@
 			name = "Copy Scripts";
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		51D394771DF2486700ABE875 /* Copy Internal Scripts */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = "$(APPLE_INTERNAL_LIBRARY_DIR)/WebKit/InternalScripts";
-			dstSubfolderSpec = 0;
-			files = (
-				51D394781DF2492200ABE875 /* DumpEditingHistory.js in Copy Internal Scripts */,
-				51D394791DF2492200ABE875 /* EditingHistoryUtil.js in Copy Internal Scripts */,
-			);
-			name = "Copy Internal Scripts";
-			runOnlyForDeploymentPostprocessing = 1;
-		};
 		CD0DBF001422765700280263 /* Copy Audio Resources */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 2147483647;
@@ -9424,8 +9414,6 @@
 		51C81B880C4422F70019ECE3 /* FTPDirectoryParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryParser.h; sourceTree = "<group>"; };
 		51CBFC980D10E483002DBF51 /* CachedFramePlatformData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedFramePlatformData.h; sourceTree = "<group>"; };
 		51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStorageCustom.cpp; sourceTree = "<group>"; };
-		51D394741DF2454000ABE875 /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = DumpEditingHistory.js; path = InternalScripts/DumpEditingHistory.js; sourceTree = "<group>"; };
-		51D394751DF2454000ABE875 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = EditingHistoryUtil.js; path = InternalScripts/EditingHistoryUtil.js; sourceTree = "<group>"; };
 		51D7196C181106DF0016DC51 /* DOMWindowIndexedDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowIndexedDatabase.cpp; sourceTree = "<group>"; };
 		51D7196D181106DF0016DC51 /* DOMWindowIndexedDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWindowIndexedDatabase.h; sourceTree = "<group>"; };
 		51D7196E181106DF0016DC51 /* DOMWindowIndexedDatabase.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMWindowIndexedDatabase.idl; sourceTree = "<group>"; };
@@ -14516,6 +14504,8 @@
 		F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollSnapAnimatorState.mm; sourceTree = "<group>"; };
 		F47A5E3A195B8C8A00483100 /* StyleScrollSnapPoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleScrollSnapPoints.cpp; sourceTree = "<group>"; };
 		F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleScrollSnapPoints.h; sourceTree = "<group>"; };
+		F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = DumpEditingHistory.js; path = Scripts/DumpEditingHistory.js; sourceTree = "<group>"; };
+		F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = EditingHistoryUtil.js; path = Scripts/EditingHistoryUtil.js; sourceTree = "<group>"; };
 		F50664F5157F52DC00AC226F /* FormController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormController.cpp; sourceTree = "<group>"; };
 		F50664F6157F52DC00AC226F /* FormController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormController.h; sourceTree = "<group>"; };
 		F513A3E915FF4841001526DB /* ValidationMessageClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationMessageClient.h; sourceTree = "<group>"; };
@@ -15421,7 +15411,6 @@
 				2E4346310F546A6800B0F1BA /* workers */,
 				E1F0424309839389006694EA /* xml */,
 				656580EC09D12B20000E61D7 /* Derived Sources */,
-				51D394731DF244BA00ABE875 /* InternalScripts */,
 				089C1665FE841158C02AAC07 /* Resources */,
 				3717D7E417ECC36C003C276D /* Scripts */,
 				0867D69AFE84028FC02AAC07 /* Frameworks */,
@@ -16507,6 +16496,7 @@
 		3717D7E417ECC36C003C276D /* Scripts */ = {
 			isa = PBXGroup;
 			children = (
+				F48389791E1DD23A0076B7EA /* EditingHistory */,
 				3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */,
 				37D456FB1A9A50B6003330A1 /* LocalizableStrings.pm */,
 			);
@@ -17351,15 +17341,6 @@
 			path = mac;
 			sourceTree = "<group>";
 		};
-		51D394731DF244BA00ABE875 /* InternalScripts */ = {
-			isa = PBXGroup;
-			children = (
-				51D394741DF2454000ABE875 /* DumpEditingHistory.js */,
-				51D394751DF2454000ABE875 /* EditingHistoryUtil.js */,
-			);
-			name = InternalScripts;
-			sourceTree = "<group>";
-		};
 		59B5977111086556007159E8 /* jsc */ = {
 			isa = PBXGroup;
 			children = (
@@ -23347,6 +23328,15 @@
 			path = mac;
 			sourceTree = "<group>";
 		};
+		F48389791E1DD23A0076B7EA /* EditingHistory */ = {
+			isa = PBXGroup;
+			children = (
+				F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */,
+				F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */,
+			);
+			name = EditingHistory;
+			sourceTree = "<group>";
+		};
 		F523D18402DE42E8018635CA /* css */ = {
 			isa = PBXGroup;
 			children = (
@@ -28460,7 +28450,6 @@
 				37A1EAA3142699BC0087F425 /* Check For Inappropriate Objective-C Class Names */,
 				5DF50887116F3077005202AB /* Check For Inappropriate Files In Framework */,
 				71D6AA381DA4E69400B23969 /* Copy modern media controls code and assets */,
-				51D394771DF2486700ABE875 /* Copy Internal Scripts */,
 			);
 			buildRules = (
 			);

Modified: trunk/Tools/ChangeLog (210317 => 210318)


--- trunk/Tools/ChangeLog	2017-01-05 04:43:13 UTC (rev 210317)
+++ trunk/Tools/ChangeLog	2017-01-05 05:09:04 UTC (rev 210318)
@@ -1,3 +1,15 @@
+2017-01-04  Wenson Hsieh  <[email protected]>
+
+        Move editing history scripts to WebCore PrivateHeaders
+        https://bugs.webkit.org/show_bug.cgi?id=166709
+        <rdar://problem/29876612>
+
+        Reviewed by Dan Bernstein.
+
+        Update references to editing script files in WebCore that were moved.
+
+        * EditingHistory/EditingHistory.xcodeproj/project.pbxproj:
+
 2017-01-04  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, build fix after r210313 part 2

Modified: trunk/Tools/EditingHistory/EditingHistory.xcodeproj/project.pbxproj (210317 => 210318)


--- 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)
@@ -12,11 +12,11 @@
 		516ADBE61DE156BB00E2B98D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB11DE155BD00E2B98D /* main.m */; };
 		516ADBF31DE157AD00E2B98D /* RewindAndPlaybackTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBF21DE157AD00E2B98D /* RewindAndPlaybackTests.m */; };
 		517FD93C1DE18DC900A73673 /* DOMTestingUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = 517FD93B1DE18DC900A73673 /* DOMTestingUtil.js */; };
-		51D394801DF2541D00ABE875 /* DumpEditingHistory.js in Resources */ = {isa = PBXBuildFile; fileRef = 51D3947E1DF2541D00ABE875 /* DumpEditingHistory.js */; };
-		51D394811DF2541D00ABE875 /* EditingHistoryUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = 51D3947F1DF2541D00ABE875 /* EditingHistoryUtil.js */; };
 		51ECC3E71DEE33CE00CB267E /* TestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB51DE155BD00E2B98D /* TestUtil.m */; };
 		51ECC3E91DEE33D200CB267E /* WKWebViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB71DE155BD00E2B98D /* WKWebViewAdditions.m */; };
 		51ECC3EA1DEE33DD00CB267E /* TestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 516ADBB31DE155BD00E2B98D /* TestRunner.m */; };
+		F4BFB9891E1DE82D00862C24 /* DumpEditingHistory.js in Resources */ = {isa = PBXBuildFile; fileRef = F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */; };
+		F4BFB98A1E1DE82D00862C24 /* EditingHistoryUtil.js in Resources */ = {isa = PBXBuildFile; fileRef = F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -47,6 +47,8 @@
 		517FD93B1DE18DC900A73673 /* DOMTestingUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = DOMTestingUtil.js; path = EditingHistory/Resources/DOMTestingUtil.js; sourceTree = SOURCE_ROOT; };
 		51D3947E1DF2541D00ABE875 /* DumpEditingHistory.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = DumpEditingHistory.js; path = ../../Source/WebCore/InternalScripts/DumpEditingHistory.js; sourceTree = SOURCE_ROOT; };
 		51D3947F1DF2541D00ABE875 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; name = EditingHistoryUtil.js; path = ../../Source/WebCore/InternalScripts/EditingHistoryUtil.js; sourceTree = SOURCE_ROOT; };
+		F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; name = DumpEditingHistory.js; path = ../../Source/WebCore/Scripts/DumpEditingHistory.js; sourceTree = "<group>"; };
+		F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; name = EditingHistoryUtil.js; path = ../../Source/WebCore/Scripts/EditingHistoryUtil.js; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -70,6 +72,8 @@
 		512D7A8A1DE0FBEF0028F0E6 = {
 			isa = PBXGroup;
 			children = (
+				F4BFB9871E1DE82D00862C24 /* DumpEditingHistory.js */,
+				F4BFB9881E1DE82D00862C24 /* EditingHistoryUtil.js */,
 				512D7A951DE0FBEF0028F0E6 /* EditingHistory */,
 				516ADBF11DE157AD00E2B98D /* EditingHistoryTests */,
 				512D7A941DE0FBEF0028F0E6 /* Products */,
@@ -204,11 +208,11 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				51D394801DF2541D00ABE875 /* DumpEditingHistory.js in Resources */,
+				F4BFB9891E1DE82D00862C24 /* DumpEditingHistory.js in Resources */,
+				F4BFB98A1E1DE82D00862C24 /* EditingHistoryUtil.js in Resources */,
 				516ADBE21DE156A900E2B98D /* CaptureHarness.html in Resources */,
 				517FD93C1DE18DC900A73673 /* DOMTestingUtil.js in Resources */,
 				516ADBE51DE156A900E2B98D /* PlaybackHarness.html in Resources */,
-				51D394811DF2541D00ABE875 /* EditingHistoryUtil.js in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to