mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 23:06:52 +00:00
08f421be7c
- Bug 1231404 - SubscriptBaselineDropMin or SuperscriptBaselineDropMax are not read from the MATH table. r=jfkthame (4293e32fef) - Bug 953408 - switch to unprefixed hyphens property in tests. r=jfkthame (2ee7ee6bd4) - Bug 1207061 - Reftest for buggy bidi font that fails with graphite 1.3.2. r=jdaggett (3d1ae98e9e) - Bug 1161900 - Basic reftest to check that Balinese two-part vowel characters are shaped properly. r=jdaggett (5bd6653da0) - Bug 686225 - Reftest for Indic shaping with buggy OS X (AAT) fonts. r=jdaggett (76e81fba3e) - Bug 1156111 patch 1 - Give layout/reftests/ its own moz.build file. r=gps (8c1b128a6b) - Bug 1156111 patch 2 - Add BUG_COMPONENT metadata for tests in layout/reftests/. r=gps (c9089a56cf) - Bug 1153407 - browser_toolbox_options_enable_serviceworkers_testing.js breaks other tests, needs to be e10s. r=ochameau (556a1364a0) - Bug 1150054, part 1 - Pull down the upstreamed version of EventWatcher from the web-platform-tests js harness into imptests. r=Ms2ger (d77d33d62d) - fix test file (2dd7d20fa8) - Bug 1173288 - Update testharness code in imptests; rs=jgraham (cfabd5a670) - bug 1224165 - Remove some Makefiles in js/xpconnect/tests/. r=glandium (424ee2fc95) - Bug 1186940 - Prevent leaking Debugger objects on toolbox close. r=jryans (fb25133351) - Bug 994555 - Adds contextmenu items to edit add and delete attributes; r=pbro (8fc519a452) - Bug 835896 - Make inspector searchbox also provide results matching text or attributes in the page;r=pbrosset (e22e11b12b) - Bug 1108042 - No autoblackboxing of minified sources when they've been already checked. r=ejpbruel (42cdb62575) - bits of NO BUG - s/if(/if (/ in toolkit/devtools JS; r=jimb DONTBUILD (e0c8f7ad58) - add and shuffle around some tests (c91d7bf912) - bits of Bug 1202902 - Fix the world. (84e1fd88bd) - Bug 1201008 - only add a breakpoint in the debugger if a source is actually loaded. r=bgrins (c63ac35123) - Bug 1219572 - Give the heap view's tree items a little space between the function name and source; r=jsantell DONTBUILD (2fe9adaa49) - Bug 1219421 - Guide users to recording allocations when no allocation stacks are present; r=jsantell (304a35da7e) - Bug 1218670 - Add % to heap view tree items; r=jsantell (212a1403a2) - Bug 1219820 - Do not try and select the hidden root when navigating the heap view tree with keyboard shortcuts; r=jsantell (b2a0dd9e13) - Bug 1219071 - Cache the results of the dfs when rendering the tree widget; r=jsantell (ec4a705b37) - Bug 1218673 - Clean up toolbar stlying and be more responsive in the memory tool. r=fitzgen (57948229e4) - Bug 1221673 - Add support for filtering censuses to memory tool's frontend; r=jsantell,vporof (57a0d4dd3f)
339 lines
8.6 KiB
JavaScript
339 lines
8.6 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
const { Cu, Ci } = require("chrome");
|
|
const { getRootBindingParent } = require("devtools/shared/layout/utils");
|
|
var EventEmitter = require("devtools/shared/event-emitter");
|
|
|
|
/**
|
|
* API
|
|
*
|
|
* new Selection(walker=null, node=null, track={attributes,detached});
|
|
* destroy()
|
|
* node (readonly)
|
|
* setNode(node, origin="unknown")
|
|
*
|
|
* Helpers:
|
|
*
|
|
* window
|
|
* document
|
|
* isRoot()
|
|
* isNode()
|
|
* isHTMLNode()
|
|
*
|
|
* Check the nature of the node:
|
|
*
|
|
* isElementNode()
|
|
* isAttributeNode()
|
|
* isTextNode()
|
|
* isCDATANode()
|
|
* isEntityRefNode()
|
|
* isEntityNode()
|
|
* isProcessingInstructionNode()
|
|
* isCommentNode()
|
|
* isDocumentNode()
|
|
* isDocumentTypeNode()
|
|
* isDocumentFragmentNode()
|
|
* isNotationNode()
|
|
*
|
|
* Events:
|
|
* "new-node" when the inner node changed
|
|
* "before-new-node" when the inner node is set to change
|
|
* "attribute-changed" when an attribute is changed (only if tracked)
|
|
* "detached" when the node (or one of its parents) is removed from the document (only if tracked)
|
|
* "reparented" when the node (or one of its parents) is moved under a different node (only if tracked)
|
|
*/
|
|
|
|
/**
|
|
* A Selection object. Hold a reference to a node.
|
|
* Includes some helpers, fire some helpful events.
|
|
*
|
|
* @param node Inner node.
|
|
* Can be null. Can be (un)set in the future via the "node" property;
|
|
* @param trackAttribute Tell if events should be fired when the attributes of
|
|
* the node change.
|
|
*
|
|
*/
|
|
function Selection(walker, node=null, track={attributes:true,detached:true}) {
|
|
EventEmitter.decorate(this);
|
|
|
|
this._onMutations = this._onMutations.bind(this);
|
|
this.track = track;
|
|
this.setWalker(walker);
|
|
this.setNode(node);
|
|
}
|
|
|
|
exports.Selection = Selection;
|
|
|
|
Selection.prototype = {
|
|
_walker: null,
|
|
_node: null,
|
|
|
|
_onMutations: function(mutations) {
|
|
let attributeChange = false;
|
|
let pseudoChange = false;
|
|
let detached = false;
|
|
let parentNode = null;
|
|
|
|
for (let m of mutations) {
|
|
if (!attributeChange && m.type == "attributes") {
|
|
attributeChange = true;
|
|
}
|
|
if (m.type == "childList") {
|
|
if (!detached && !this.isConnected()) {
|
|
if (this.isNode()) {
|
|
parentNode = m.target;
|
|
}
|
|
detached = true;
|
|
}
|
|
}
|
|
if (m.type == "pseudoClassLock") {
|
|
pseudoChange = true;
|
|
}
|
|
}
|
|
|
|
// Fire our events depending on what changed in the mutations array
|
|
if (attributeChange) {
|
|
this.emit("attribute-changed");
|
|
}
|
|
if (pseudoChange) {
|
|
this.emit("pseudoclass");
|
|
}
|
|
if (detached) {
|
|
let rawNode = null;
|
|
if (parentNode && parentNode.isLocal_toBeDeprecated()) {
|
|
rawNode = parentNode.rawNode();
|
|
}
|
|
|
|
this.emit("detached", rawNode, null);
|
|
this.emit("detached-front", parentNode);
|
|
}
|
|
},
|
|
|
|
destroy: function() {
|
|
this.setNode(null);
|
|
this.setWalker(null);
|
|
},
|
|
|
|
setWalker: function(walker) {
|
|
if (this._walker) {
|
|
this._walker.off("mutations", this._onMutations);
|
|
}
|
|
this._walker = walker;
|
|
if (this._walker) {
|
|
this._walker.on("mutations", this._onMutations);
|
|
}
|
|
},
|
|
|
|
// Not remote-safe
|
|
setNode: function(value, reason="unknown") {
|
|
if (value) {
|
|
value = this._walker.frontForRawNode(value);
|
|
}
|
|
this.setNodeFront(value, reason);
|
|
},
|
|
|
|
// Not remote-safe
|
|
get node() {
|
|
return this._node;
|
|
},
|
|
|
|
// Not remote-safe
|
|
get window() {
|
|
if (this.isNode()) {
|
|
return this.node.ownerDocument.defaultView;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
// Not remote-safe
|
|
get document() {
|
|
if (this.isNode()) {
|
|
return this.node.ownerDocument;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
setNodeFront: function(value, reason="unknown") {
|
|
this.reason = reason;
|
|
|
|
// If a singleTextChild text node is being set, then set it's parent instead.
|
|
let parentNode = value && value.parentNode();
|
|
if (value && parentNode && parentNode.singleTextChild === value) {
|
|
value = parentNode;
|
|
}
|
|
|
|
// We used to return here if the node had not changed but we now need to
|
|
// set the node even if it is already set otherwise it is not possible to
|
|
// e.g. highlight the same node twice.
|
|
let rawValue = null;
|
|
if (value && value.isLocal_toBeDeprecated()) {
|
|
rawValue = value.rawNode();
|
|
}
|
|
this.emit("before-new-node", rawValue, reason);
|
|
this.emit("before-new-node-front", value, reason);
|
|
let previousNode = this._node;
|
|
let previousFront = this._nodeFront;
|
|
this._node = rawValue;
|
|
this._nodeFront = value;
|
|
this.emit("new-node", previousNode, this.reason);
|
|
this.emit("new-node-front", value, this.reason);
|
|
},
|
|
|
|
get documentFront() {
|
|
return this._walker.document(this._nodeFront);
|
|
},
|
|
|
|
get nodeFront() {
|
|
return this._nodeFront;
|
|
},
|
|
|
|
isRoot: function() {
|
|
return this.isNode() &&
|
|
this.isConnected() &&
|
|
this._nodeFront.isDocumentElement;
|
|
},
|
|
|
|
isNode: function() {
|
|
if (!this._nodeFront) {
|
|
return false;
|
|
}
|
|
|
|
// As long as tools are still accessing node.rawNode(),
|
|
// this needs to stay here.
|
|
if (this._node && Cu.isDeadWrapper(this._node)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
isLocal: function() {
|
|
return !!this._node;
|
|
},
|
|
|
|
isConnected: function() {
|
|
let node = this._nodeFront;
|
|
if (!node || !node.actorID) {
|
|
return false;
|
|
}
|
|
|
|
// As long as there are still tools going around
|
|
// accessing node.rawNode, this needs to stay.
|
|
let rawNode = null;
|
|
if (node.isLocal_toBeDeprecated()) {
|
|
rawNode = node.rawNode();
|
|
}
|
|
if (rawNode) {
|
|
try {
|
|
let doc = this.document;
|
|
if (doc && doc.defaultView) {
|
|
let docEl = doc.documentElement;
|
|
let bindingParent = getRootBindingParent(rawNode);
|
|
|
|
if (docEl.contains(bindingParent)) {
|
|
return true;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// "can't access dead object" error
|
|
}
|
|
return false;
|
|
}
|
|
|
|
while(node) {
|
|
if (node === this._walker.rootNode) {
|
|
return true;
|
|
}
|
|
node = node.parentNode();
|
|
};
|
|
return false;
|
|
},
|
|
|
|
isHTMLNode: function() {
|
|
let xhtml_ns = "http://www.w3.org/1999/xhtml";
|
|
return this.isNode() && this.nodeFront.namespaceURI == xhtml_ns;
|
|
},
|
|
|
|
// Node type
|
|
|
|
isElementNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ELEMENT_NODE;
|
|
},
|
|
|
|
isPseudoElementNode: function() {
|
|
return this.isNode() && this.nodeFront.isPseudoElement;
|
|
},
|
|
|
|
isAnonymousNode: function() {
|
|
return this.isNode() && this.nodeFront.isAnonymous;
|
|
},
|
|
|
|
isAttributeNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ATTRIBUTE_NODE;
|
|
},
|
|
|
|
isTextNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.TEXT_NODE;
|
|
},
|
|
|
|
isCDATANode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.CDATA_SECTION_NODE;
|
|
},
|
|
|
|
isEntityRefNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ENTITY_REFERENCE_NODE;
|
|
},
|
|
|
|
isEntityNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.ENTITY_NODE;
|
|
},
|
|
|
|
isProcessingInstructionNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.PROCESSING_INSTRUCTION_NODE;
|
|
},
|
|
|
|
isCommentNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.PROCESSING_INSTRUCTION_NODE;
|
|
},
|
|
|
|
isDocumentNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE;
|
|
},
|
|
|
|
/**
|
|
* @returns true if the selection is the <body> HTML element.
|
|
*/
|
|
isBodyNode: function() {
|
|
return this.isHTMLNode() &&
|
|
this.isConnected() &&
|
|
this.nodeFront.nodeName === "BODY";
|
|
},
|
|
|
|
/**
|
|
* @returns true if the selection is the <head> HTML element.
|
|
*/
|
|
isHeadNode: function() {
|
|
return this.isHTMLNode() &&
|
|
this.isConnected() &&
|
|
this.nodeFront.nodeName === "HEAD";
|
|
},
|
|
|
|
isDocumentTypeNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.DOCUMENT_TYPE_NODE;
|
|
},
|
|
|
|
isDocumentFragmentNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.DOCUMENT_FRAGMENT_NODE;
|
|
},
|
|
|
|
isNotationNode: function() {
|
|
return this.isNode() && this.nodeFront.nodeType == Ci.nsIDOMNode.NOTATION_NODE;
|
|
},
|
|
};
|