зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1102240 - split inspector actor in smaller files;r=ochameau,pbro
MozReview-Commit-ID: LgZav4dMQRR --HG-- rename : devtools/server/actors/inspector/inspector.js => devtools/server/actors/inspector/document-walker.js rename : devtools/server/actors/inspector/inspector.js => devtools/server/actors/inspector/node-actor.js rename : devtools/server/actors/inspector/inspector.js => devtools/server/actors/inspector/utils.js rename : devtools/server/actors/inspector/inspector.js => devtools/server/actors/inspector/walker-actor.js extra : rebase_source : b57466d2e2dfb6f332dec3a38a03b12506eb4a30
This commit is contained in:
Родитель
8eb0574c63
Коммит
8cca58077e
|
@ -11,7 +11,7 @@ const EventEmitter = require("devtools/shared/event-emitter");
|
|||
const {ActorClassWithSpec, Actor, FrontClassWithSpec, Front, generateActorSpec} =
|
||||
require("devtools/shared/protocol");
|
||||
|
||||
const {NodeActor} = require("devtools/server/actors/inspector/inspector");
|
||||
const {NodeActor} = require("devtools/server/actors/inspector/node-actor");
|
||||
|
||||
var eventsSpec = generateActorSpec({
|
||||
typeName: "eventsFormActor",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// Test editing a node's text content
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_markup_edit.html";
|
||||
const {DEFAULT_VALUE_SUMMARY_LENGTH} = require("devtools/server/actors/inspector/inspector");
|
||||
const {DEFAULT_VALUE_SUMMARY_LENGTH} = require("devtools/server/actors/inspector/walker-actor");
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
|
|
@ -18,7 +18,7 @@ const {
|
|||
setIgnoreLayoutChanges,
|
||||
getCurrentZoom,
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const inspector = require("devtools/server/actors/inspector/inspector");
|
||||
const { getNodeDisplayName } = require("devtools/server/actors/inspector/utils");
|
||||
const nodeConstants = require("devtools/shared/dom-node-constants");
|
||||
|
||||
// Note that the order of items in this array is important because it is used
|
||||
|
@ -676,7 +676,7 @@ class BoxModelHighlighter extends AutoRefreshHighlighter {
|
|||
getBindingElementAndPseudo(this.currentNode);
|
||||
|
||||
// Update the tag, id, classes, pseudo-classes and dimensions
|
||||
let displayName = inspector.getNodeDisplayName(node);
|
||||
let displayName = getNodeDisplayName(node);
|
||||
|
||||
let id = node.id ? "#" + node.id : "";
|
||||
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/* 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 {Cc, Ci, Cu} = require("chrome");
|
||||
|
||||
loader.lazyRequireGetter(this, "nodeFilterConstants", "devtools/shared/dom-node-filter-constants");
|
||||
loader.lazyRequireGetter(this, "standardTreeWalkerFilter", "devtools/server/actors/inspector/utils", true);
|
||||
|
||||
// SKIP_TO_* arguments are used with the DocumentWalker, driving the strategy to use if
|
||||
// the starting node is incompatible with the filter function of the walker.
|
||||
const SKIP_TO_PARENT = "SKIP_TO_PARENT";
|
||||
const SKIP_TO_SIBLING = "SKIP_TO_SIBLING";
|
||||
|
||||
/**
|
||||
* Wrapper for inDeepTreeWalker. Adds filtering to the traversal methods.
|
||||
* See inDeepTreeWalker for more information about the methods.
|
||||
*
|
||||
* @param {DOMNode} node
|
||||
* @param {Window} rootWin
|
||||
* @param {Number} whatToShow
|
||||
* See nodeFilterConstants / inIDeepTreeWalker for options.
|
||||
* @param {Function} filter
|
||||
* A custom filter function Taking in a DOMNode and returning an Int. See
|
||||
* WalkerActor.nodeFilter for an example.
|
||||
* @param {String} skipTo
|
||||
* Either SKIP_TO_PARENT or SKIP_TO_SIBLING. If the provided node is not compatible
|
||||
* with the filter function for this walker, try to find a compatible one either
|
||||
* in the parents or in the siblings of the node.
|
||||
*/
|
||||
function DocumentWalker(node, rootWin,
|
||||
whatToShow = nodeFilterConstants.SHOW_ALL,
|
||||
filter = standardTreeWalkerFilter,
|
||||
skipTo = SKIP_TO_PARENT) {
|
||||
if (Cu.isDeadWrapper(rootWin) || !rootWin.location) {
|
||||
throw new Error("Got an invalid root window in DocumentWalker");
|
||||
}
|
||||
|
||||
this.walker = Cc["@mozilla.org/inspector/deep-tree-walker;1"]
|
||||
.createInstance(Ci.inIDeepTreeWalker);
|
||||
this.walker.showAnonymousContent = true;
|
||||
this.walker.showSubDocuments = true;
|
||||
this.walker.showDocumentsAsNodes = true;
|
||||
this.walker.init(rootWin.document, whatToShow);
|
||||
this.filter = filter;
|
||||
|
||||
// Make sure that the walker knows about the initial node (which could
|
||||
// be skipped due to a filter).
|
||||
this.walker.currentNode = this.getStartingNode(node, skipTo);
|
||||
}
|
||||
|
||||
DocumentWalker.prototype = {
|
||||
|
||||
get whatToShow() {
|
||||
return this.walker.whatToShow;
|
||||
},
|
||||
get currentNode() {
|
||||
return this.walker.currentNode;
|
||||
},
|
||||
set currentNode(val) {
|
||||
this.walker.currentNode = val;
|
||||
},
|
||||
|
||||
parentNode: function () {
|
||||
return this.walker.parentNode();
|
||||
},
|
||||
|
||||
nextNode: function () {
|
||||
let node = this.walker.currentNode;
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let nextNode = this.walker.nextNode();
|
||||
while (nextNode && this.isSkippedNode(nextNode)) {
|
||||
nextNode = this.walker.nextNode();
|
||||
}
|
||||
|
||||
return nextNode;
|
||||
},
|
||||
|
||||
firstChild: function () {
|
||||
let node = this.walker.currentNode;
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let firstChild = this.walker.firstChild();
|
||||
while (firstChild && this.isSkippedNode(firstChild)) {
|
||||
firstChild = this.walker.nextSibling();
|
||||
}
|
||||
|
||||
return firstChild;
|
||||
},
|
||||
|
||||
lastChild: function () {
|
||||
let node = this.walker.currentNode;
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let lastChild = this.walker.lastChild();
|
||||
while (lastChild && this.isSkippedNode(lastChild)) {
|
||||
lastChild = this.walker.previousSibling();
|
||||
}
|
||||
|
||||
return lastChild;
|
||||
},
|
||||
|
||||
previousSibling: function () {
|
||||
let node = this.walker.previousSibling();
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = this.walker.previousSibling();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
nextSibling: function () {
|
||||
let node = this.walker.nextSibling();
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = this.walker.nextSibling();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
getStartingNode: function (node, skipTo) {
|
||||
// Keep a reference on the starting node in case we can't find a node compatible with
|
||||
// the filter.
|
||||
let startingNode = node;
|
||||
|
||||
if (skipTo === SKIP_TO_PARENT) {
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
} else if (skipTo === SKIP_TO_SIBLING) {
|
||||
node = this.getClosestAcceptedSibling(node);
|
||||
}
|
||||
|
||||
return node || startingNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Loop on all of the provided node siblings until finding one that is compliant with
|
||||
* the filter function.
|
||||
*/
|
||||
getClosestAcceptedSibling: function (node) {
|
||||
if (this.filter(node) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// node is already valid, return immediately.
|
||||
return node;
|
||||
}
|
||||
|
||||
// Loop on starting node siblings.
|
||||
let previous = node;
|
||||
let next = node;
|
||||
while (previous || next) {
|
||||
previous = previous && previous.previousSibling;
|
||||
next = next && next.nextSibling;
|
||||
|
||||
if (previous && this.filter(previous) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// A valid node was found in the previous siblings of the node.
|
||||
return previous;
|
||||
}
|
||||
|
||||
if (next && this.filter(next) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// A valid node was found in the next siblings of the node.
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
isSkippedNode: function (node) {
|
||||
return this.filter(node) === nodeFilterConstants.FILTER_SKIP;
|
||||
},
|
||||
};
|
||||
|
||||
exports.DocumentWalker = DocumentWalker;
|
||||
exports.SKIP_TO_PARENT = SKIP_TO_PARENT;
|
||||
exports.SKIP_TO_SIBLING = SKIP_TO_SIBLING;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -5,7 +5,11 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'inspector.js',
|
||||
'document-walker.js',
|
||||
'inspector.js',
|
||||
'node-actor.js',
|
||||
'utils.js',
|
||||
'walker-actor.js',
|
||||
)
|
||||
|
||||
with Files('**'):
|
||||
|
|
|
@ -0,0 +1,697 @@
|
|||
/* 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 {Ci, Cu} = require("chrome");
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {nodeSpec, nodeListSpec} = require("devtools/shared/specs/node");
|
||||
|
||||
const InspectorUtils = require("InspectorUtils");
|
||||
|
||||
loader.lazyRequireGetter(this, "colorUtils", "devtools/shared/css/color", true);
|
||||
|
||||
loader.lazyRequireGetter(this, "getCssPath", "devtools/shared/inspector/css-logic", true);
|
||||
loader.lazyRequireGetter(this, "getXPath", "devtools/shared/inspector/css-logic", true);
|
||||
loader.lazyRequireGetter(this, "findCssSelector", "devtools/shared/inspector/css-logic", true);
|
||||
|
||||
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isXBLAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isShadowAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isAnonymous", "devtools/shared/layout/utils", true);
|
||||
|
||||
loader.lazyRequireGetter(this, "InspectorActorUtils", "devtools/server/actors/inspector/utils");
|
||||
loader.lazyRequireGetter(this, "LongStringActor", "devtools/server/actors/string", true);
|
||||
loader.lazyRequireGetter(this, "getFontPreviewData", "devtools/server/actors/styles", true);
|
||||
loader.lazyRequireGetter(this, "CssLogic", "devtools/server/css-logic", true);
|
||||
loader.lazyRequireGetter(this, "EventParsers", "devtools/server/event-parsers", true);
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
|
||||
const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
|
||||
|
||||
/**
|
||||
* Server side of the node actor.
|
||||
*/
|
||||
const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
||||
initialize: function (walker, node) {
|
||||
protocol.Actor.prototype.initialize.call(this, null);
|
||||
this.walker = walker;
|
||||
this.rawNode = node;
|
||||
this._eventParsers = new EventParsers().parsers;
|
||||
|
||||
// Storing the original display of the node, to track changes when reflows
|
||||
// occur
|
||||
this.wasDisplayed = this.isDisplayed;
|
||||
},
|
||||
|
||||
toString: function () {
|
||||
return "[NodeActor " + this.actorID + " for " +
|
||||
this.rawNode.toString() + "]";
|
||||
},
|
||||
|
||||
/**
|
||||
* Instead of storing a connection object, the NodeActor gets its connection
|
||||
* from its associated walker.
|
||||
*/
|
||||
get conn() {
|
||||
return this.walker.conn;
|
||||
},
|
||||
|
||||
isDocumentElement: function () {
|
||||
return this.rawNode.ownerDocument &&
|
||||
this.rawNode.ownerDocument.documentElement === this.rawNode;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
|
||||
if (this.mutationObserver) {
|
||||
if (!Cu.isDeadWrapper(this.mutationObserver)) {
|
||||
this.mutationObserver.disconnect();
|
||||
}
|
||||
this.mutationObserver = null;
|
||||
}
|
||||
this.rawNode = null;
|
||||
this.walker = null;
|
||||
},
|
||||
|
||||
// Returns the JSON representation of this object over the wire.
|
||||
form: function (detail) {
|
||||
if (detail === "actorid") {
|
||||
return this.actorID;
|
||||
}
|
||||
|
||||
let parentNode = this.walker.parentNode(this);
|
||||
let inlineTextChild = this.walker.inlineTextChild(this);
|
||||
|
||||
let form = {
|
||||
actor: this.actorID,
|
||||
baseURI: this.rawNode.baseURI,
|
||||
parent: parentNode ? parentNode.actorID : undefined,
|
||||
nodeType: this.rawNode.nodeType,
|
||||
namespaceURI: this.rawNode.namespaceURI,
|
||||
nodeName: this.rawNode.nodeName,
|
||||
nodeValue: this.rawNode.nodeValue,
|
||||
displayName: InspectorActorUtils.getNodeDisplayName(this.rawNode),
|
||||
numChildren: this.numChildren,
|
||||
inlineTextChild: inlineTextChild ? inlineTextChild.form() : undefined,
|
||||
|
||||
// doctype attributes
|
||||
name: this.rawNode.name,
|
||||
publicId: this.rawNode.publicId,
|
||||
systemId: this.rawNode.systemId,
|
||||
|
||||
attrs: this.writeAttrs(),
|
||||
isBeforePseudoElement: this.isBeforePseudoElement,
|
||||
isAfterPseudoElement: this.isAfterPseudoElement,
|
||||
isAnonymous: isAnonymous(this.rawNode),
|
||||
isNativeAnonymous: isNativeAnonymous(this.rawNode),
|
||||
isXBLAnonymous: isXBLAnonymous(this.rawNode),
|
||||
isShadowAnonymous: isShadowAnonymous(this.rawNode),
|
||||
pseudoClassLocks: this.writePseudoClassLocks(),
|
||||
|
||||
isDisplayed: this.isDisplayed,
|
||||
isInHTMLDocument: this.rawNode.ownerDocument &&
|
||||
this.rawNode.ownerDocument.contentType === "text/html",
|
||||
hasEventListeners: this._hasEventListeners,
|
||||
};
|
||||
|
||||
if (this.isDocumentElement()) {
|
||||
form.isDocumentElement = true;
|
||||
}
|
||||
|
||||
// Add an extra API for custom properties added by other
|
||||
// modules/extensions.
|
||||
form.setFormProperty = (name, value) => {
|
||||
if (!form.props) {
|
||||
form.props = {};
|
||||
}
|
||||
form.props[name] = value;
|
||||
};
|
||||
|
||||
// Fire an event so, other modules can create its own properties
|
||||
// that should be passed to the client (within the form.props field).
|
||||
EventEmitter.emit(NodeActor, "form", {
|
||||
target: this,
|
||||
data: form
|
||||
});
|
||||
|
||||
return form;
|
||||
},
|
||||
|
||||
/**
|
||||
* Watch the given document node for mutations using the DOM observer
|
||||
* API.
|
||||
*/
|
||||
watchDocument: function (callback) {
|
||||
let node = this.rawNode;
|
||||
// Create the observer on the node's actor. The node will make sure
|
||||
// the observer is cleaned up when the actor is released.
|
||||
let observer = new node.defaultView.MutationObserver(callback);
|
||||
observer.mergeAttributeRecords = true;
|
||||
observer.observe(node, {
|
||||
nativeAnonymousChildList: true,
|
||||
attributes: true,
|
||||
characterData: true,
|
||||
characterDataOldValue: true,
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
this.mutationObserver = observer;
|
||||
},
|
||||
|
||||
get isBeforePseudoElement() {
|
||||
return this.rawNode.nodeName === "_moz_generated_content_before";
|
||||
},
|
||||
|
||||
get isAfterPseudoElement() {
|
||||
return this.rawNode.nodeName === "_moz_generated_content_after";
|
||||
},
|
||||
|
||||
// Estimate the number of children that the walker will return without making
|
||||
// a call to children() if possible.
|
||||
get numChildren() {
|
||||
// For pseudo elements, childNodes.length returns 1, but the walker
|
||||
// will return 0.
|
||||
if (this.isBeforePseudoElement || this.isAfterPseudoElement) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let rawNode = this.rawNode;
|
||||
let numChildren = rawNode.childNodes.length;
|
||||
let hasAnonChildren = rawNode.nodeType === Ci.nsIDOMNode.ELEMENT_NODE &&
|
||||
rawNode.ownerDocument.getAnonymousNodes(rawNode);
|
||||
|
||||
let hasContentDocument = rawNode.contentDocument;
|
||||
let hasSVGDocument = rawNode.getSVGDocument && rawNode.getSVGDocument();
|
||||
if (numChildren === 0 && (hasContentDocument || hasSVGDocument)) {
|
||||
// This might be an iframe with virtual children.
|
||||
numChildren = 1;
|
||||
}
|
||||
|
||||
// Normal counting misses ::before/::after. Also, some anonymous children
|
||||
// may ultimately be skipped, so we have to consult with the walker.
|
||||
if (numChildren === 0 || hasAnonChildren) {
|
||||
numChildren = this.walker.children(this).nodes.length;
|
||||
}
|
||||
|
||||
return numChildren;
|
||||
},
|
||||
|
||||
get computedStyle() {
|
||||
return CssLogic.getComputedStyle(this.rawNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Is the node's display computed style value other than "none"
|
||||
*/
|
||||
get isDisplayed() {
|
||||
// Consider all non-element nodes as displayed.
|
||||
if (InspectorActorUtils.isNodeDead(this) ||
|
||||
this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE ||
|
||||
this.isAfterPseudoElement ||
|
||||
this.isBeforePseudoElement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let style = this.computedStyle;
|
||||
if (!style) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return style.display !== "none";
|
||||
},
|
||||
|
||||
/**
|
||||
* Are there event listeners that are listening on this node? This method
|
||||
* uses all parsers registered via event-parsers.js.registerEventParser() to
|
||||
* check if there are any event listeners.
|
||||
*/
|
||||
get _hasEventListeners() {
|
||||
let parsers = this._eventParsers;
|
||||
for (let [, {hasListeners}] of parsers) {
|
||||
try {
|
||||
if (hasListeners && hasListeners(this.rawNode)) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// An object attached to the node looked like a listener but wasn't...
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
writeAttrs: function () {
|
||||
if (!this.rawNode.attributes) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [...this.rawNode.attributes].map(attr => {
|
||||
return {namespace: attr.namespace, name: attr.name, value: attr.value };
|
||||
});
|
||||
},
|
||||
|
||||
writePseudoClassLocks: function () {
|
||||
if (this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||
return undefined;
|
||||
}
|
||||
let ret = undefined;
|
||||
for (let pseudo of PSEUDO_CLASSES) {
|
||||
if (InspectorUtils.hasPseudoClassLock(this.rawNode, pseudo)) {
|
||||
ret = ret || [];
|
||||
ret.push(pseudo);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets event listeners and adds their information to the events array.
|
||||
*
|
||||
* @param {Node} node
|
||||
* Node for which we are to get listeners.
|
||||
*/
|
||||
getEventListeners: function (node) {
|
||||
let parsers = this._eventParsers;
|
||||
let dbg = this.parent().tabActor.makeDebugger();
|
||||
let listenerArray = [];
|
||||
|
||||
for (let [, {getListeners, normalizeListener}] of parsers) {
|
||||
try {
|
||||
let listeners = getListeners(node);
|
||||
|
||||
if (!listeners) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (let listener of listeners) {
|
||||
if (normalizeListener) {
|
||||
listener.normalizeListener = normalizeListener;
|
||||
}
|
||||
|
||||
this.processHandlerForEvent(node, listenerArray, dbg, listener);
|
||||
}
|
||||
} catch (e) {
|
||||
// An object attached to the node looked like a listener but wasn't...
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
listenerArray.sort((a, b) => {
|
||||
return a.type.localeCompare(b.type);
|
||||
});
|
||||
|
||||
return listenerArray;
|
||||
},
|
||||
|
||||
/**
|
||||
* Process a handler
|
||||
*
|
||||
* @param {Node} node
|
||||
* The node for which we want information.
|
||||
* @param {Array} listenerArray
|
||||
* listenerArray contains all event objects that we have gathered
|
||||
* so far.
|
||||
* @param {Debugger} dbg
|
||||
* JSDebugger instance.
|
||||
* @param {Object} eventInfo
|
||||
* See event-parsers.js.registerEventParser() for a description of the
|
||||
* eventInfo object.
|
||||
*
|
||||
* @return {Array}
|
||||
* An array of objects where a typical object looks like this:
|
||||
* {
|
||||
* type: "click",
|
||||
* handler: function() { doSomething() },
|
||||
* origin: "http://www.mozilla.com",
|
||||
* searchString: 'onclick="doSomething()"',
|
||||
* tags: tags,
|
||||
* DOM0: true,
|
||||
* capturing: true,
|
||||
* hide: {
|
||||
* DOM0: true
|
||||
* },
|
||||
* native: false
|
||||
* }
|
||||
*/
|
||||
processHandlerForEvent: function (node, listenerArray, dbg, listener) {
|
||||
let { handler } = listener;
|
||||
let global = Cu.getGlobalForObject(handler);
|
||||
let globalDO = dbg.addDebuggee(global);
|
||||
let listenerDO = globalDO.makeDebuggeeValue(handler);
|
||||
|
||||
let { normalizeListener } = listener;
|
||||
|
||||
if (normalizeListener) {
|
||||
listenerDO = normalizeListener(listenerDO, listener);
|
||||
}
|
||||
|
||||
let { capturing } = listener;
|
||||
let dom0 = false;
|
||||
let functionSource = handler.toString();
|
||||
let hide = listener.hide || {};
|
||||
let line = 0;
|
||||
let native = false;
|
||||
let override = listener.override || {};
|
||||
let tags = listener.tags || "";
|
||||
let type = listener.type || "";
|
||||
let url = "";
|
||||
|
||||
// If the listener is an object with a 'handleEvent' method, use that.
|
||||
if (listenerDO.class === "Object" || listenerDO.class === "XULElement") {
|
||||
let desc;
|
||||
|
||||
while (!desc && listenerDO) {
|
||||
desc = listenerDO.getOwnPropertyDescriptor("handleEvent");
|
||||
listenerDO = listenerDO.proto;
|
||||
}
|
||||
|
||||
if (desc && desc.value) {
|
||||
listenerDO = desc.value;
|
||||
}
|
||||
}
|
||||
|
||||
// If the listener is bound to a different context then we need to switch
|
||||
// to the bound function.
|
||||
if (listenerDO.isBoundFunction) {
|
||||
listenerDO = listenerDO.boundTargetFunction;
|
||||
}
|
||||
|
||||
let { isArrowFunction, name, script, parameterNames } = listenerDO;
|
||||
|
||||
if (script) {
|
||||
let scriptSource = script.source.text;
|
||||
|
||||
// Scripts are provided via script tags. If it wasn't provided by a
|
||||
// script tag it must be a DOM0 event.
|
||||
if (script.source.element) {
|
||||
dom0 = script.source.element.class !== "HTMLScriptElement";
|
||||
} else {
|
||||
dom0 = false;
|
||||
}
|
||||
|
||||
line = script.startLine;
|
||||
url = script.url;
|
||||
|
||||
// Checking for the string "[native code]" is the only way at this point
|
||||
// to check for native code. Even if this provides a false positive then
|
||||
// grabbing the source code a second time is harmless.
|
||||
if (functionSource === "[object Object]" ||
|
||||
functionSource === "[object XULElement]" ||
|
||||
functionSource.includes("[native code]")) {
|
||||
functionSource =
|
||||
scriptSource.substr(script.sourceStart, script.sourceLength);
|
||||
|
||||
// At this point the script looks like this:
|
||||
// () { ... }
|
||||
// We prefix this with "function" if it is not a fat arrow function.
|
||||
if (!isArrowFunction) {
|
||||
functionSource = "function " + functionSource;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the listener is a native one (provided by C++ code) then we have no
|
||||
// access to the script. We use the native flag to prevent showing the
|
||||
// debugger button because the script is not available.
|
||||
native = true;
|
||||
}
|
||||
|
||||
// Fat arrow function text always contains the parameters. Function
|
||||
// parameters are often missing e.g. if Array.sort is used as a handler.
|
||||
// If they are missing we provide the parameters ourselves.
|
||||
if (parameterNames && parameterNames.length > 0) {
|
||||
let prefix = "function " + name + "()";
|
||||
let paramString = parameterNames.join(", ");
|
||||
|
||||
if (functionSource.startsWith(prefix)) {
|
||||
functionSource = functionSource.substr(prefix.length);
|
||||
|
||||
functionSource = `function ${name} (${paramString})${functionSource}`;
|
||||
}
|
||||
}
|
||||
|
||||
// If the listener is native code we display the filename "[native code]."
|
||||
// This is the official string and should *not* be translated.
|
||||
let origin;
|
||||
if (native) {
|
||||
origin = "[native code]";
|
||||
} else {
|
||||
origin = url + ((dom0 || line === 0) ? "" : ":" + line);
|
||||
}
|
||||
|
||||
let eventObj = {
|
||||
type: override.type || type,
|
||||
handler: override.handler || functionSource.trim(),
|
||||
origin: override.origin || origin,
|
||||
tags: override.tags || tags,
|
||||
DOM0: typeof override.dom0 !== "undefined" ? override.dom0 : dom0,
|
||||
capturing: typeof override.capturing !== "undefined" ?
|
||||
override.capturing : capturing,
|
||||
hide: typeof override.hide !== "undefined" ? override.hide : hide,
|
||||
native
|
||||
};
|
||||
|
||||
// Hide the debugger icon for DOM0 and native listeners. DOM0 listeners are
|
||||
// generated dynamically from e.g. an onclick="" attribute so the script
|
||||
// doesn't actually exist.
|
||||
if (native || dom0) {
|
||||
eventObj.hide.debugger = true;
|
||||
}
|
||||
|
||||
listenerArray.push(eventObj);
|
||||
|
||||
dbg.removeDebuggee(globalDO);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a LongStringActor with the node's value.
|
||||
*/
|
||||
getNodeValue: function () {
|
||||
return new LongStringActor(this.conn, this.rawNode.nodeValue || "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the node's value to a given string.
|
||||
*/
|
||||
setNodeValue: function (value) {
|
||||
this.rawNode.nodeValue = value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a unique selector string for this node.
|
||||
*/
|
||||
getUniqueSelector: function () {
|
||||
if (Cu.isDeadWrapper(this.rawNode)) {
|
||||
return "";
|
||||
}
|
||||
return findCssSelector(this.rawNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the full CSS path for this node.
|
||||
*
|
||||
* @return {String} A CSS selector with a part for the node and each of its ancestors.
|
||||
*/
|
||||
getCssPath: function () {
|
||||
if (Cu.isDeadWrapper(this.rawNode)) {
|
||||
return "";
|
||||
}
|
||||
return getCssPath(this.rawNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the XPath for this node.
|
||||
*
|
||||
* @return {String} The XPath for finding this node on the page.
|
||||
*/
|
||||
getXPath: function () {
|
||||
if (Cu.isDeadWrapper(this.rawNode)) {
|
||||
return "";
|
||||
}
|
||||
return getXPath(this.rawNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Scroll the selected node into view.
|
||||
*/
|
||||
scrollIntoView: function () {
|
||||
this.rawNode.scrollIntoView(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the node's image data if any (for canvas and img nodes).
|
||||
* Returns an imageData object with the actual data being a LongStringActor
|
||||
* and a size json object.
|
||||
* The image data is transmitted as a base64 encoded png data-uri.
|
||||
* The method rejects if the node isn't an image or if the image is missing
|
||||
*
|
||||
* Accepts a maxDim request parameter to resize images that are larger. This
|
||||
* is important as the resizing occurs server-side so that image-data being
|
||||
* transfered in the longstring back to the client will be that much smaller
|
||||
*/
|
||||
getImageData: function (maxDim) {
|
||||
return InspectorActorUtils.imageToImageData(this.rawNode, maxDim).then(imageData => {
|
||||
return {
|
||||
data: LongStringActor(this.conn, imageData.data),
|
||||
size: imageData.size
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all event listeners that are listening on this node.
|
||||
*/
|
||||
getEventListenerInfo: function () {
|
||||
let node = this.rawNode;
|
||||
|
||||
if (this.rawNode.nodeName.toLowerCase() === "html") {
|
||||
let winListeners = this.getEventListeners(node.ownerGlobal) || [];
|
||||
let docElementListeners = this.getEventListeners(node) || [];
|
||||
let docListeners = this.getEventListeners(node.parentNode) || [];
|
||||
|
||||
return [...winListeners, ...docElementListeners, ...docListeners];
|
||||
}
|
||||
return this.getEventListeners(node);
|
||||
},
|
||||
|
||||
/**
|
||||
* Modify a node's attributes. Passed an array of modifications
|
||||
* similar in format to "attributes" mutations.
|
||||
* {
|
||||
* attributeName: <string>
|
||||
* attributeNamespace: <optional string>
|
||||
* newValue: <optional string> - If null or undefined, the attribute
|
||||
* will be removed.
|
||||
* }
|
||||
*
|
||||
* Returns when the modifications have been made. Mutations will
|
||||
* be queued for any changes made.
|
||||
*/
|
||||
modifyAttributes: function (modifications) {
|
||||
let rawNode = this.rawNode;
|
||||
for (let change of modifications) {
|
||||
if (change.newValue == null) {
|
||||
if (change.attributeNamespace) {
|
||||
rawNode.removeAttributeNS(change.attributeNamespace,
|
||||
change.attributeName);
|
||||
} else {
|
||||
rawNode.removeAttribute(change.attributeName);
|
||||
}
|
||||
} else if (change.attributeNamespace) {
|
||||
rawNode.setAttributeNS(change.attributeNamespace, change.attributeName,
|
||||
change.newValue);
|
||||
} else {
|
||||
rawNode.setAttribute(change.attributeName, change.newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given the font and fill style, get the image data of a canvas with the
|
||||
* preview text and font.
|
||||
* Returns an imageData object with the actual data being a LongStringActor
|
||||
* and the width of the text as a string.
|
||||
* The image data is transmitted as a base64 encoded png data-uri.
|
||||
*/
|
||||
getFontFamilyDataURL: function (font, fillStyle = "black") {
|
||||
let doc = this.rawNode.ownerDocument;
|
||||
let options = {
|
||||
previewText: FONT_FAMILY_PREVIEW_TEXT,
|
||||
previewFontSize: FONT_FAMILY_PREVIEW_TEXT_SIZE,
|
||||
fillStyle: fillStyle
|
||||
};
|
||||
let { dataURL, size } = getFontPreviewData(font, doc, options);
|
||||
|
||||
return { data: LongStringActor(this.conn, dataURL), size: size };
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the computed background color of the closest parent with
|
||||
* a set background color.
|
||||
* Returns a string with the background color of the form
|
||||
* rgba(r, g, b, a). Defaults to rgba(255, 255, 255, 1) if no
|
||||
* background color is found.
|
||||
*/
|
||||
getClosestBackgroundColor: function () {
|
||||
let current = this.rawNode;
|
||||
while (current) {
|
||||
let computedStyle = CssLogic.getComputedStyle(current);
|
||||
let currentStyle = computedStyle.getPropertyValue("background-color");
|
||||
if (colorUtils.isValidCSSColor(currentStyle)) {
|
||||
let currentCssColor = new colorUtils.CssColor(currentStyle);
|
||||
if (!currentCssColor.isTransparent()) {
|
||||
return currentCssColor.rgba;
|
||||
}
|
||||
}
|
||||
current = current.parentNode;
|
||||
}
|
||||
return "rgba(255, 255, 255, 1)";
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Server side of a node list as returned by querySelectorAll()
|
||||
*/
|
||||
const NodeListActor = protocol.ActorClassWithSpec(nodeListSpec, {
|
||||
typeName: "domnodelist",
|
||||
|
||||
initialize: function (walker, nodeList) {
|
||||
protocol.Actor.prototype.initialize.call(this);
|
||||
this.walker = walker;
|
||||
this.nodeList = nodeList || [];
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Instead of storing a connection object, the NodeActor gets its connection
|
||||
* from its associated walker.
|
||||
*/
|
||||
get conn() {
|
||||
return this.walker.conn;
|
||||
},
|
||||
|
||||
/**
|
||||
* Items returned by this actor should belong to the parent walker.
|
||||
*/
|
||||
marshallPool: function () {
|
||||
return this.walker;
|
||||
},
|
||||
|
||||
// Returns the JSON representation of this object over the wire.
|
||||
form: function () {
|
||||
return {
|
||||
actor: this.actorID,
|
||||
length: this.nodeList ? this.nodeList.length : 0
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a single node from the node list.
|
||||
*/
|
||||
item: function (index) {
|
||||
return this.walker.attachElement(this.nodeList[index]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a range of the items from the node list.
|
||||
*/
|
||||
items: function (start = 0, end = this.nodeList.length) {
|
||||
let items = Array.prototype.slice.call(this.nodeList, start, end)
|
||||
.map(item => this.walker._ref(item));
|
||||
return this.walker.attachElements(items);
|
||||
},
|
||||
|
||||
release: function () {}
|
||||
});
|
||||
|
||||
exports.NodeActor = NodeActor;
|
||||
exports.NodeListActor = NodeListActor;
|
|
@ -0,0 +1,255 @@
|
|||
/* 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 {Ci, Cu} = require("chrome");
|
||||
|
||||
const promise = require("promise");
|
||||
const {Task} = require("devtools/shared/task");
|
||||
|
||||
loader.lazyRequireGetter(this, "AsyncUtils", "devtools/shared/async-utils");
|
||||
loader.lazyRequireGetter(this, "flags", "devtools/shared/flags");
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/shared/DevToolsUtils");
|
||||
loader.lazyRequireGetter(this, "nodeFilterConstants", "devtools/shared/dom-node-filter-constants");
|
||||
|
||||
loader.lazyRequireGetter(this, "isNativeAnonymous", "devtools/shared/layout/utils", true);
|
||||
loader.lazyRequireGetter(this, "isXBLAnonymous", "devtools/shared/layout/utils", true);
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const IMAGE_FETCHING_TIMEOUT = 500;
|
||||
|
||||
/**
|
||||
* Returns the properly cased version of the node's tag name, which can be
|
||||
* used when displaying said name in the UI.
|
||||
*
|
||||
* @param {Node} rawNode
|
||||
* Node for which we want the display name
|
||||
* @return {String}
|
||||
* Properly cased version of the node tag name
|
||||
*/
|
||||
const getNodeDisplayName = function (rawNode) {
|
||||
if (rawNode.nodeName && !rawNode.localName) {
|
||||
// The localName & prefix APIs have been moved from the Node interface to the Element
|
||||
// interface. Use Node.nodeName as a fallback.
|
||||
return rawNode.nodeName;
|
||||
}
|
||||
return (rawNode.prefix ? rawNode.prefix + ":" : "") + rawNode.localName;
|
||||
};
|
||||
|
||||
function nodeDocument(node) {
|
||||
if (Cu.isDeadWrapper(node)) {
|
||||
return null;
|
||||
}
|
||||
return node.ownerDocument ||
|
||||
(node.nodeType == Ci.nsIDOMNode.DOCUMENT_NODE ? node : null);
|
||||
}
|
||||
|
||||
function isNodeDead(node) {
|
||||
return !node || !node.rawNode || Cu.isDeadWrapper(node.rawNode);
|
||||
}
|
||||
|
||||
function isInXULDocument(el) {
|
||||
let doc = nodeDocument(el);
|
||||
return doc &&
|
||||
doc.documentElement &&
|
||||
doc.documentElement.namespaceURI === XUL_NS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This DeepTreeWalker filter skips whitespace text nodes and anonymous
|
||||
* content with the exception of ::before and ::after and anonymous content
|
||||
* in XUL document (needed to show all elements in the browser toolbox).
|
||||
*/
|
||||
function standardTreeWalkerFilter(node) {
|
||||
// ::before and ::after are native anonymous content, but we always
|
||||
// want to show them
|
||||
if (node.nodeName === "_moz_generated_content_before" ||
|
||||
node.nodeName === "_moz_generated_content_after") {
|
||||
return nodeFilterConstants.FILTER_ACCEPT;
|
||||
}
|
||||
|
||||
// Ignore empty whitespace text nodes that do not impact the layout.
|
||||
if (isWhitespaceTextNode(node)) {
|
||||
return nodeHasSize(node)
|
||||
? nodeFilterConstants.FILTER_ACCEPT
|
||||
: nodeFilterConstants.FILTER_SKIP;
|
||||
}
|
||||
|
||||
// Ignore all native and XBL anonymous content inside a non-XUL document.
|
||||
// We need to do this to skip things like form controls, scrollbars,
|
||||
// video controls, etc (see bug 1187482).
|
||||
if (!isInXULDocument(node) && (isXBLAnonymous(node) ||
|
||||
isNativeAnonymous(node))) {
|
||||
return nodeFilterConstants.FILTER_SKIP;
|
||||
}
|
||||
|
||||
return nodeFilterConstants.FILTER_ACCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* This DeepTreeWalker filter is like standardTreeWalkerFilter except that
|
||||
* it also includes all anonymous content (like internal form controls).
|
||||
*/
|
||||
function allAnonymousContentTreeWalkerFilter(node) {
|
||||
// Ignore empty whitespace text nodes that do not impact the layout.
|
||||
if (isWhitespaceTextNode(node)) {
|
||||
return nodeHasSize(node)
|
||||
? nodeFilterConstants.FILTER_ACCEPT
|
||||
: nodeFilterConstants.FILTER_SKIP;
|
||||
}
|
||||
return nodeFilterConstants.FILTER_ACCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given node a text node composed of whitespace only?
|
||||
* @param {DOMNode} node
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function isWhitespaceTextNode(node) {
|
||||
return node.nodeType == Ci.nsIDOMNode.TEXT_NODE && !/[^\s]/.exec(node.nodeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given node have non-0 width and height?
|
||||
* @param {DOMNode} node
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function nodeHasSize(node) {
|
||||
if (!node.getBoxQuads) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let quads = node.getBoxQuads();
|
||||
return quads.length && quads.some(quad => quad.bounds.width && quad.bounds.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that is settled once the given HTMLImageElement has
|
||||
* finished loading.
|
||||
*
|
||||
* @param {HTMLImageElement} image - The image element.
|
||||
* @param {Number} timeout - Maximum amount of time the image is allowed to load
|
||||
* before the waiting is aborted. Ignored if flags.testing is set.
|
||||
*
|
||||
* @return {Promise} that is fulfilled once the image has loaded. If the image
|
||||
* fails to load or the load takes too long, the promise is rejected.
|
||||
*/
|
||||
function ensureImageLoaded(image, timeout) {
|
||||
let { HTMLImageElement } = image.ownerGlobal;
|
||||
if (!(image instanceof HTMLImageElement)) {
|
||||
return promise.reject("image must be an HTMLImageELement");
|
||||
}
|
||||
|
||||
if (image.complete) {
|
||||
// The image has already finished loading.
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
// This image is still loading.
|
||||
let onLoad = AsyncUtils.listenOnce(image, "load");
|
||||
|
||||
// Reject if loading fails.
|
||||
let onError = AsyncUtils.listenOnce(image, "error").then(() => {
|
||||
return promise.reject("Image '" + image.src + "' failed to load.");
|
||||
});
|
||||
|
||||
// Don't timeout when testing. This is never settled.
|
||||
let onAbort = new Promise(() => {});
|
||||
|
||||
if (!flags.testing) {
|
||||
// Tests are not running. Reject the promise after given timeout.
|
||||
onAbort = DevToolsUtils.waitForTime(timeout).then(() => {
|
||||
return promise.reject("Image '" + image.src + "' took too long to load.");
|
||||
});
|
||||
}
|
||||
|
||||
// See which happens first.
|
||||
return promise.race([onLoad, onError, onAbort]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an <img> or <canvas> element, return the image data-uri. If @param node
|
||||
* is an <img> element, the method waits a while for the image to load before
|
||||
* the data is generated. If the image does not finish loading in a reasonable
|
||||
* time (IMAGE_FETCHING_TIMEOUT milliseconds) the process aborts.
|
||||
*
|
||||
* @param {HTMLImageElement|HTMLCanvasElement} node - The <img> or <canvas>
|
||||
* element, or Image() object. Other types cause the method to reject.
|
||||
* @param {Number} maxDim - Optionally pass a maximum size you want the longest
|
||||
* side of the image to be resized to before getting the image data.
|
||||
|
||||
* @return {Promise} A promise that is fulfilled with an object containing the
|
||||
* data-uri and size-related information:
|
||||
* { data: "...",
|
||||
* size: {
|
||||
* naturalWidth: 400,
|
||||
* naturalHeight: 300,
|
||||
* resized: true }
|
||||
* }.
|
||||
*
|
||||
* If something goes wrong, the promise is rejected.
|
||||
*/
|
||||
const imageToImageData = Task.async(function* (node, maxDim) {
|
||||
let { HTMLCanvasElement, HTMLImageElement } = node.ownerGlobal;
|
||||
|
||||
let isImg = node instanceof HTMLImageElement;
|
||||
let isCanvas = node instanceof HTMLCanvasElement;
|
||||
|
||||
if (!isImg && !isCanvas) {
|
||||
throw new Error("node is not a <canvas> or <img> element.");
|
||||
}
|
||||
|
||||
if (isImg) {
|
||||
// Ensure that the image is ready.
|
||||
yield ensureImageLoaded(node, IMAGE_FETCHING_TIMEOUT);
|
||||
}
|
||||
|
||||
// Get the image resize ratio if a maxDim was provided
|
||||
let resizeRatio = 1;
|
||||
let imgWidth = node.naturalWidth || node.width;
|
||||
let imgHeight = node.naturalHeight || node.height;
|
||||
let imgMax = Math.max(imgWidth, imgHeight);
|
||||
if (maxDim && imgMax > maxDim) {
|
||||
resizeRatio = maxDim / imgMax;
|
||||
}
|
||||
|
||||
// Extract the image data
|
||||
let imageData;
|
||||
// The image may already be a data-uri, in which case, save ourselves the
|
||||
// trouble of converting via the canvas.drawImage.toDataURL method, but only
|
||||
// if the image doesn't need resizing
|
||||
if (isImg && node.src.startsWith("data:") && resizeRatio === 1) {
|
||||
imageData = node.src;
|
||||
} else {
|
||||
// Create a canvas to copy the rawNode into and get the imageData from
|
||||
let canvas = node.ownerDocument.createElementNS(XHTML_NS, "canvas");
|
||||
canvas.width = imgWidth * resizeRatio;
|
||||
canvas.height = imgHeight * resizeRatio;
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
// Copy the rawNode image or canvas in the new canvas and extract data
|
||||
ctx.drawImage(node, 0, 0, canvas.width, canvas.height);
|
||||
imageData = canvas.toDataURL("image/png");
|
||||
}
|
||||
|
||||
return {
|
||||
data: imageData,
|
||||
size: {
|
||||
naturalWidth: imgWidth,
|
||||
naturalHeight: imgHeight,
|
||||
resized: resizeRatio !== 1
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
allAnonymousContentTreeWalkerFilter,
|
||||
getNodeDisplayName,
|
||||
imageToImageData,
|
||||
isNodeDead,
|
||||
nodeDocument,
|
||||
standardTreeWalkerFilter,
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,7 +38,6 @@ DevToolsModules(
|
|||
'heap-snapshot-file.js',
|
||||
'highlighters.css',
|
||||
'highlighters.js',
|
||||
'inspector.js',
|
||||
'layout.js',
|
||||
'memory.js',
|
||||
'monitor.js',
|
||||
|
|
|
@ -11,7 +11,7 @@ const {Ci, Cu, Cr} = require("chrome");
|
|||
const {DebuggerServer} = require("devtools/server/main");
|
||||
const Services = require("Services");
|
||||
|
||||
loader.lazyGetter(this, "NodeActor", () => require("devtools/server/actors/inspector/inspector").NodeActor, true);
|
||||
loader.lazyGetter(this, "NodeActor", () => require("devtools/server/actors/inspector/node-actor").NodeActor, true);
|
||||
|
||||
const {
|
||||
XPCOMUtils,
|
||||
|
|
|
@ -15,7 +15,7 @@ const Services = require("Services");
|
|||
// promise is still used in tests using this helper
|
||||
const promise = require("promise"); // eslint-disable-line no-unused-vars
|
||||
const defer = require("devtools/shared/defer");
|
||||
const {_documentWalker} = require("devtools/server/actors/inspector/inspector");
|
||||
const {DocumentWalker: _documentWalker} = require("devtools/server/actors/inspector/document-walker");
|
||||
|
||||
// Always log packets when running tests.
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
|
|
@ -16,8 +16,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777674
|
|||
window.onload = function () {
|
||||
const {InspectorFront} =
|
||||
require("devtools/shared/fronts/inspector");
|
||||
const {_documentWalker} =
|
||||
require("devtools/server/actors/inspector/inspector");
|
||||
const {DocumentWalker: _documentWalker} =
|
||||
require("devtools/server/actors/inspector/document-walker");
|
||||
|
||||
const nodeFilterConstants =
|
||||
require("devtools/shared/dom-node-filter-constants");
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
|
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
|||
<script type="application/javascript">
|
||||
"use strict";
|
||||
|
||||
const inspector = require("devtools/server/actors/inspector/inspector");
|
||||
const {DocumentWalker} = require("devtools/server/actors/inspector/document-walker");
|
||||
|
||||
window.onload = function () {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -54,7 +54,7 @@ addAsyncTest(function* testRearrange() {
|
|||
let nextNode = children.nodes[13];
|
||||
yield gWalker.insertBefore(nodeA, longlist, nextNode);
|
||||
let sibling =
|
||||
new inspector._documentWalker(gInspectee.querySelector("#a"), window).nextSibling();
|
||||
new DocumentWalker(gInspectee.querySelector("#a"), window).nextSibling();
|
||||
is(sibling, nextNode.rawNode(), "Node should match the expected next node.");
|
||||
children = yield gWalker.children(longlist);
|
||||
is(nodeA, children.nodes[13], "a should be where we expect it.");
|
||||
|
|
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=
|
|||
<script type="application/javascript">
|
||||
"use strict";
|
||||
|
||||
const inspector = require("devtools/server/actors/inspector/inspector");
|
||||
const WalkerActor = require("devtools/server/actors/inspector/walker-actor");
|
||||
|
||||
window.onload = function () {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -21,9 +21,9 @@ window.onload = function () {
|
|||
};
|
||||
|
||||
const testSummaryLength = 10;
|
||||
inspector.setValueSummaryLength(testSummaryLength);
|
||||
WalkerActor.setValueSummaryLength(testSummaryLength);
|
||||
SimpleTest.registerCleanupFunction(function () {
|
||||
inspector.setValueSummaryLength(inspector.DEFAULT_VALUE_SUMMARY_LENGTH);
|
||||
WalkerActor.setValueSummaryLength(WalkerActor.DEFAULT_VALUE_SUMMARY_LENGTH);
|
||||
});
|
||||
|
||||
let gInspectee = null;
|
||||
|
|
|
@ -284,11 +284,11 @@ addTest(function testFrameTraversal() {
|
|||
|
||||
addTest(function testLongValue() {
|
||||
const testSummaryLength = 10;
|
||||
const inspector = require("devtools/server/actors/inspector/inspector");
|
||||
const WalkerActor = require("devtools/server/actors/inspector/walker-actor");
|
||||
|
||||
inspector.setValueSummaryLength(testSummaryLength);
|
||||
WalkerActor.setValueSummaryLength(testSummaryLength);
|
||||
SimpleTest.registerCleanupFunction(function () {
|
||||
inspector.setValueSummaryLength(inspector.DEFAULT_VALUE_SUMMARY_LENGTH);
|
||||
WalkerActor.setValueSummaryLength(WalkerActor.DEFAULT_VALUE_SUMMARY_LENGTH);
|
||||
});
|
||||
|
||||
let longstringText = gInspectee.getElementById("longstring").firstChild.nodeValue;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Test that a NodeListActor initialized with null nodelist doesn't cause
|
||||
// exceptions when calling NodeListActor.form.
|
||||
|
||||
const { NodeListActor } = require("devtools/server/actors/inspector/inspector");
|
||||
const { NodeListActor } = require("devtools/server/actors/inspector/node-actor");
|
||||
|
||||
function run_test() {
|
||||
check_actor_for_list(null);
|
||||
|
|
Загрузка…
Ссылка в новой задаче