зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1592517 - Migrate devtools DOMHelpers.jsm from JSM to plain JS module r=ochameau
Depends on D51054 Summary of the changes here: - move DOMHelpers.jsm to dom-helpers.js - remove all unused methods - converted to a static helper to avoid instanciating DOMHelpers objects for no reason - updated call sites accordingly Differential Revision: https://phabricator.services.mozilla.com/D51065 --HG-- rename : devtools/shared/DOMHelpers.jsm => devtools/shared/dom-helpers.js extra : moz-landing-system : lando
This commit is contained in:
Родитель
be1867fdfd
Коммит
3f0e2f4c4f
|
@ -7,7 +7,7 @@
|
|||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const promise = require("promise");
|
||||
const Services = require("Services");
|
||||
const { DOMHelpers } = require("resource://devtools/shared/DOMHelpers.jsm");
|
||||
const { DOMHelpers } = require("devtools/shared/dom-helpers");
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
|
@ -78,12 +78,11 @@ BottomHost.prototype = {
|
|||
this.frame.setAttribute("src", "about:blank");
|
||||
|
||||
const frame = await new Promise(resolve => {
|
||||
const domHelper = new DOMHelpers(this.frame.contentWindow);
|
||||
const frameLoad = () => {
|
||||
this.emit("ready", this.frame);
|
||||
resolve(this.frame);
|
||||
};
|
||||
domHelper.onceDOMReady(frameLoad);
|
||||
DOMHelpers.onceDOMReady(this.frame.contentWindow, frameLoad);
|
||||
focusTab(this.hostTab);
|
||||
});
|
||||
|
||||
|
@ -174,12 +173,11 @@ class SidebarHost {
|
|||
this.frame.setAttribute("src", "about:blank");
|
||||
|
||||
const frame = await new Promise(resolve => {
|
||||
const domHelper = new DOMHelpers(this.frame.contentWindow);
|
||||
const frameLoad = () => {
|
||||
this.emit("ready", this.frame);
|
||||
resolve(this.frame);
|
||||
};
|
||||
domHelper.onceDOMReady(frameLoad);
|
||||
DOMHelpers.onceDOMReady(this.frame.contentWindow, frameLoad);
|
||||
focusTab(this.hostTab);
|
||||
});
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ var EventEmitter = require("devtools/shared/event-emitter");
|
|||
const Selection = require("devtools/client/framework/selection");
|
||||
var Telemetry = require("devtools/client/shared/telemetry");
|
||||
const { getUnicodeUrl } = require("devtools/client/shared/unicode-url");
|
||||
var { DOMHelpers } = require("resource://devtools/shared/DOMHelpers.jsm");
|
||||
var { DOMHelpers } = require("devtools/shared/dom-helpers");
|
||||
const { KeyCodes } = require("devtools/client/shared/keycodes");
|
||||
var Startup = Cc["@mozilla.org/devtools/startup-clh;1"].getService(
|
||||
Ci.nsISupports
|
||||
|
@ -727,11 +727,14 @@ Toolbox.prototype = {
|
|||
this._debugTargetData = this._getDebugTargetData();
|
||||
}
|
||||
|
||||
const domHelper = new DOMHelpers(this.win);
|
||||
const domReady = new Promise(resolve => {
|
||||
domHelper.onceDOMReady(() => {
|
||||
resolve();
|
||||
}, this._URL);
|
||||
DOMHelpers.onceDOMReady(
|
||||
this.win,
|
||||
() => {
|
||||
resolve();
|
||||
},
|
||||
this._URL
|
||||
);
|
||||
});
|
||||
|
||||
// Optimization: fire up a few other things before waiting on
|
||||
|
@ -2479,8 +2482,7 @@ Toolbox.prototype = {
|
|||
// on the DOM node every time because this won't work
|
||||
// if the (xul chrome) iframe is loaded in a content docshell.
|
||||
if (iframe.contentWindow) {
|
||||
const domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
domHelper.onceDOMReady(onLoad);
|
||||
DOMHelpers.onceDOMReady(iframe.contentWindow, onLoad);
|
||||
} else {
|
||||
const callback = () => {
|
||||
iframe.removeEventListener("DOMContentLoaded", callback);
|
||||
|
|
|
@ -200,11 +200,10 @@ async function testClickInInnerIframe(doc) {
|
|||
|
||||
iframe.srcdoc = "<div id=test style='height:50px'></div>";
|
||||
await new Promise(r => {
|
||||
const domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
const frameLoad = () => {
|
||||
r();
|
||||
};
|
||||
domHelper.onceDOMReady(frameLoad);
|
||||
DOMHelpers.onceDOMReady(iframe.contentWindow, frameLoad);
|
||||
});
|
||||
|
||||
await waitUntil(() => iframe.contentWindow.document.getElementById("test"));
|
||||
|
|
|
@ -13,9 +13,7 @@ Services.scriptloader.loadSubScript(
|
|||
this
|
||||
);
|
||||
|
||||
const { DOMHelpers } = ChromeUtils.import(
|
||||
"resource://devtools/shared/DOMHelpers.jsm"
|
||||
);
|
||||
const { DOMHelpers } = require("devtools/shared/dom-helpers");
|
||||
const { Hosts } = require("devtools/client/framework/toolbox-hosts");
|
||||
|
||||
const TEST_URI_ROOT = "http://example.com/browser/devtools/client/shared/test/";
|
||||
|
@ -119,9 +117,8 @@ const createHost = async function(
|
|||
const iframe = await host.create();
|
||||
|
||||
await new Promise(resolve => {
|
||||
const domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
iframe.setAttribute("src", src);
|
||||
domHelper.onceDOMReady(resolve);
|
||||
DOMHelpers.onceDOMReady(iframe.contentWindow, resolve);
|
||||
});
|
||||
|
||||
return [host, iframe.contentWindow, iframe.contentDocument];
|
||||
|
|
|
@ -8,7 +8,7 @@ const {
|
|||
} = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { getCurrentZoom } = require("devtools/shared/layout/utils");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { DOMHelpers } = require("resource://devtools/shared/DOMHelpers.jsm");
|
||||
const { DOMHelpers } = require("devtools/shared/dom-helpers");
|
||||
|
||||
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
|
||||
|
||||
|
@ -1293,8 +1293,7 @@ AbstractCanvasGraph.createIframe = function(url, parent, callback) {
|
|||
|
||||
// Use DOMHelpers to wait for the frame load. DOMHelpers relies on chromeEventHandler
|
||||
// so this will still work if DevTools are loaded in a content frame.
|
||||
const domHelper = new DOMHelpers(iframe.contentWindow);
|
||||
domHelper.onceDOMReady(function() {
|
||||
DOMHelpers.onceDOMReady(iframe.contentWindow, function() {
|
||||
callback(iframe);
|
||||
});
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ loader.lazyRequireGetter(
|
|||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"DOMHelpers",
|
||||
"resource://devtools/shared/DOMHelpers.jsm",
|
||||
"devtools/shared/dom-helpers",
|
||||
true
|
||||
);
|
||||
|
||||
|
@ -742,8 +742,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
|||
const { contentDocument, contentWindow } = this.rawNode;
|
||||
if (contentDocument && contentDocument.readyState !== "complete") {
|
||||
await new Promise(resolve => {
|
||||
const domHelper = new DOMHelpers(contentWindow);
|
||||
domHelper.onceDOMReady(resolve);
|
||||
DOMHelpers.onceDOMReady(contentWindow, resolve);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/* 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 { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
|
||||
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DOMHelpers"];
|
||||
|
||||
/**
|
||||
* DOMHelpers
|
||||
* Makes DOM traversal easier. Goes through iframes.
|
||||
*
|
||||
* @constructor
|
||||
* @param nsIDOMWindow win
|
||||
* The content window, owning the document to traverse.
|
||||
*/
|
||||
this.DOMHelpers = function DOMHelpers(win) {
|
||||
if (!win) {
|
||||
throw new Error("window can't be null or undefined");
|
||||
}
|
||||
this.window = win;
|
||||
};
|
||||
|
||||
DOMHelpers.prototype = {
|
||||
getParentObject: function(node) {
|
||||
const parentNode = node ? node.parentNode : null;
|
||||
|
||||
if (!parentNode) {
|
||||
// Documents have no parentNode; Attr, Document, DocumentFragment, Entity,
|
||||
// and Notation. top level windows have no parentNode
|
||||
if (node && node == this.window.Node.DOCUMENT_NODE) {
|
||||
// document type
|
||||
if (node.defaultView) {
|
||||
const embeddingFrame = node.defaultView.frameElement;
|
||||
if (embeddingFrame) {
|
||||
return embeddingFrame.parentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
// a Document object without a parentNode or window
|
||||
return null; // top level has no parent
|
||||
}
|
||||
|
||||
if (parentNode.nodeType == this.window.Node.DOCUMENT_NODE) {
|
||||
if (parentNode.defaultView) {
|
||||
return parentNode.defaultView.frameElement;
|
||||
}
|
||||
// parent is document element, but no window at defaultView.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!parentNode.localName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parentNode;
|
||||
},
|
||||
|
||||
getChildObject: function(
|
||||
node,
|
||||
index,
|
||||
previousSibling,
|
||||
showTextNodesWithWhitespace
|
||||
) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.contentDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return node.contentDocument.documentElement; // the node's HTMLElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.getSVGDocument) {
|
||||
const svgDocument = node.getSVGDocument();
|
||||
if (svgDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return svgDocument.documentElement; // the node's SVGElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let child = null;
|
||||
if (previousSibling) {
|
||||
// then we are walking
|
||||
child = this.getNextSibling(previousSibling);
|
||||
} else {
|
||||
child = this.getFirstChild(node);
|
||||
}
|
||||
|
||||
if (showTextNodesWithWhitespace) {
|
||||
return child;
|
||||
}
|
||||
|
||||
for (; child; child = this.getNextSibling(child)) {
|
||||
if (!this.isWhitespaceText(child)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return null; // we have no children worth showing.
|
||||
},
|
||||
|
||||
getFirstChild: function(node) {
|
||||
const SHOW_ALL = nodeFilterConstants.SHOW_ALL;
|
||||
this.treeWalker = node.ownerDocument.createTreeWalker(node, SHOW_ALL, null);
|
||||
return this.treeWalker.firstChild();
|
||||
},
|
||||
|
||||
getNextSibling: function(node) {
|
||||
const next = this.treeWalker.nextSibling();
|
||||
|
||||
if (!next) {
|
||||
delete this.treeWalker;
|
||||
}
|
||||
|
||||
return next;
|
||||
},
|
||||
|
||||
isWhitespaceText: function(node) {
|
||||
return (
|
||||
node.nodeType == this.window.Node.TEXT_NODE &&
|
||||
!/[^\s]/.exec(node.nodeValue)
|
||||
);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
delete this.window;
|
||||
delete this.treeWalker;
|
||||
},
|
||||
|
||||
/**
|
||||
* A simple way to be notified (once) when a window becomes
|
||||
* interactive (DOMContentLoaded).
|
||||
*
|
||||
* It is based on the chromeEventHandler. This is useful when
|
||||
* chrome iframes are loaded in content docshells (in Firefox
|
||||
* tabs for example).
|
||||
*/
|
||||
onceDOMReady: function(callback, targetURL) {
|
||||
const window = this.window;
|
||||
const docShell = window.docShell;
|
||||
const onReady = function(event) {
|
||||
if (event.target == window.document) {
|
||||
docShell.chromeEventHandler.removeEventListener(
|
||||
"DOMContentLoaded",
|
||||
onReady
|
||||
);
|
||||
// If in `callback` the URL of the window is changed and a listener to DOMContentLoaded
|
||||
// is attached, the event we just received will be also be caught by the new listener.
|
||||
// We want to avoid that so we execute the callback in the next queue.
|
||||
Services.tm.dispatchToMainThread(callback);
|
||||
}
|
||||
};
|
||||
if (
|
||||
(window.document.readyState == "complete" ||
|
||||
window.document.readyState == "interactive") &&
|
||||
window.location.href == targetURL
|
||||
) {
|
||||
Services.tm.dispatchToMainThread(callback);
|
||||
} else {
|
||||
docShell.chromeEventHandler.addEventListener("DOMContentLoaded", onReady);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
/* 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 Services = require("Services");
|
||||
|
||||
exports.DOMHelpers = {
|
||||
/**
|
||||
* A simple way to be notified (once) when a window becomes
|
||||
* interactive (DOMContentLoaded).
|
||||
*
|
||||
* It is based on the chromeEventHandler. This is useful when
|
||||
* chrome iframes are loaded in content docshells (in Firefox
|
||||
* tabs for example).
|
||||
*
|
||||
* @param nsIDOMWindow win
|
||||
* The content window, owning the document to traverse.
|
||||
* @param Function callback
|
||||
* The method to call when the frame is loaded.
|
||||
* @param String targetURL
|
||||
* (optional) Check that the frame URL corresponds to the provided URL
|
||||
* before calling the callback.
|
||||
*/
|
||||
onceDOMReady: function(win, callback, targetURL) {
|
||||
if (!win) {
|
||||
throw new Error("window can't be null or undefined");
|
||||
}
|
||||
const docShell = win.docShell;
|
||||
const onReady = function(event) {
|
||||
if (event.target == win.document) {
|
||||
docShell.chromeEventHandler.removeEventListener(
|
||||
"DOMContentLoaded",
|
||||
onReady
|
||||
);
|
||||
// If in `callback` the URL of the window is changed and a listener to DOMContentLoaded
|
||||
// is attached, the event we just received will be also be caught by the new listener.
|
||||
// We want to avoid that so we execute the callback in the next queue.
|
||||
Services.tm.dispatchToMainThread(callback);
|
||||
}
|
||||
};
|
||||
if (
|
||||
(win.document.readyState == "complete" ||
|
||||
win.document.readyState == "interactive") &&
|
||||
win.location.href == targetURL
|
||||
) {
|
||||
Services.tm.dispatchToMainThread(callback);
|
||||
} else {
|
||||
docShell.chromeEventHandler.addEventListener("DOMContentLoaded", onReady);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -53,9 +53,9 @@ DevToolsModules(
|
|||
'debounce.js',
|
||||
'defer.js',
|
||||
'DevToolsUtils.js',
|
||||
'dom-helpers.js',
|
||||
'dom-node-constants.js',
|
||||
'dom-node-filter-constants.js',
|
||||
'DOMHelpers.jsm',
|
||||
'event-emitter.js',
|
||||
'execution-point-utils.js',
|
||||
'extend.js',
|
||||
|
|
Загрузка…
Ссылка в новой задаче