Bug 1409040 - Make element.isXULElement more resiliant. r=maja_zf

Fixes isXULElement to recognise XBL elements, such as <xbl:framebox>.

Also tightens up the input checks so that arbitrary objects can be
tested, as checking node.namespaceURI directly could cause a JS error
if node is not an object.  Before checking the namespace we also ensure
it's an element node so that text- and comment nodes are not picked up.

This patch also introduces tests, which were sorely missing.

MozReview-Commit-ID: 8LNF1z3X1gP

--HG--
extra : rebase_source : ffacc5b1336b35624aaf0534101ce5c3fbdeaa95
This commit is contained in:
Andreas Tolfsen 2017-09-16 14:37:21 +01:00
Родитель fe6ba66d6c
Коммит 6332833688
2 изменённых файлов: 56 добавлений и 7 удалений

Просмотреть файл

@ -19,6 +19,7 @@ const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
this.EXPORTED_SYMBOLS = ["element"];
const XBLNS = "http://www.mozilla.org/xbl";
const XMLNS = "http://www.w3.org/1999/xhtml";
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -1050,8 +1051,21 @@ element.scrollIntoView = function(el) {
}
};
element.isXULElement = function(el) {
return el.namespaceURI === XULNS;
/**
* Ascertains whether <var>el</var> is a XUL- or XBL element.
*
* @param {*} node
* Element thought to be a XUL- or XBL element.
*
* @return {boolean}
* True if <var>node</var> is a XULElement or XBLElement,
* false otherwise.
*/
element.isXULElement = function(node) {
return typeof node == "object" &&
node !== null &&
node.nodeType === node.ELEMENT_NODE &&
[XBLNS, XULNS].includes(node.namespaceURI);
};
const boolEls = {

Просмотреть файл

@ -6,7 +6,10 @@ const {utils: Cu} = Components;
Cu.import("chrome://marionette/content/element.js");
class DOMElement {
const XBLNS = "http://www.mozilla.org/xbl";
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
class Element {
constructor(tagName, attrs = {}) {
this.tagName = tagName;
this.localName = tagName;
@ -14,6 +17,15 @@ class DOMElement {
for (let attr in attrs) {
this[attr] = attrs[attr];
}
}
get nodeType() { return 1; }
get ELEMENT_NODE() { return 1; }
}
class DOMElement extends Element {
constructor(tagName, attrs = {}) {
super(tagName, attrs);
if (this.localName == "option") {
this.selected = false;
@ -24,9 +36,6 @@ class DOMElement {
}
}
get nodeType() { return 1; }
get ELEMENT_NODE() { return 1; }
getBoundingClientRect() {
return {
top: 0,
@ -35,9 +44,25 @@ class DOMElement {
height: 100,
};
}
};
}
class XULElement extends Element {
constructor(tagName, attrs = {}) {
super(tagName, attrs);
this.namespaceURI = XULNS;
}
}
class XBLElement extends XULElement {
constructor(tagName, attrs = {}) {
super(tagName, attrs);
this.namespaceURI = XBLNS;
}
}
const domEl = new DOMElement("p");
const xulEl = new XULElement("browser");
const xblEl = new XBLElement("framebox");
add_test(function test_isSelected() {
let checkbox = new DOMElement("input", {type: "checkbox"});
@ -68,6 +93,16 @@ add_test(function test_isSelected() {
run_next_test();
});
add_test(function test_isXULElement() {
ok(element.isXULElement(xulEl));
ok(element.isXULElement(xblEl));
for (let typ of [true, 42, {}, [], undefined, null]) {
ok(!element.isXULElement(typ));
}
run_next_test();
});
add_test(function test_coordinates() {
let p = element.coordinates(domEl);
ok(p.hasOwnProperty("x"));