Bug 1695435 - Part 2: Add more words to the chrome script heuristic in use-isInstance r=preferences-reviewers,Gijs,webdriver-reviewers,whimboo,sgalich

Differential Revision: https://phabricator.services.mozilla.com/D110932
This commit is contained in:
Kagami Sascha Rosylight 2022-08-24 22:47:42 +00:00
parent ecf7215279
commit 102bd338be
27 changed files with 78 additions and 60 deletions

View file

@ -26,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
// gA11yEventDumpToConsole = true; // debugging // gA11yEventDumpToConsole = true; // debugging
function changeARIAActiveDescendant(aContainer, aItem, aPrevItemId) { function changeARIAActiveDescendant(aContainer, aItem, aPrevItemId) {
let itemID = aItem instanceof Node ? aItem.id : aItem; let itemID = Node.isInstance(aItem) ? aItem.id : aItem;
this.eventSeq = [new focusChecker(aItem)]; this.eventSeq = [new focusChecker(aItem)];
if (aPrevItemId) { if (aPrevItemId) {

View file

@ -501,7 +501,7 @@ var gGestureSupport = {
* The MozRotateGestureUpdate event triggering this call * The MozRotateGestureUpdate event triggering this call
*/ */
rotate(aEvent) { rotate(aEvent) {
if (!(window.content.document instanceof ImageDocument)) { if (!ImageDocument.isInstance(window.content.document)) {
return; return;
} }
@ -523,7 +523,7 @@ var gGestureSupport = {
* Perform a rotation end for ImageDocuments * Perform a rotation end for ImageDocuments
*/ */
rotateEnd() { rotateEnd() {
if (!(window.content.document instanceof ImageDocument)) { if (!ImageDocument.isInstance(window.content.document)) {
return; return;
} }
@ -607,7 +607,7 @@ var gGestureSupport = {
return; return;
} }
if (!(window.content.document instanceof ImageDocument)) { if (!ImageDocument.isInstance(window.content.document)) {
return; return;
} }
@ -637,7 +637,7 @@ var gGestureSupport = {
_clearCompleteRotation() { _clearCompleteRotation() {
let contentElement = let contentElement =
window.content.document && window.content.document &&
window.content.document instanceof ImageDocument && ImageDocument.isInstance(window.content.document) &&
window.content.document.body && window.content.document.body &&
window.content.document.body.firstElementChild; window.content.document.body.firstElementChild;
if (!contentElement) { if (!contentElement) {

View file

@ -203,8 +203,8 @@ gImageView.getCellProperties = function(row, col) {
var props = ""; var props = "";
if ( if (
!checkProtocol(data) || !checkProtocol(data) ||
item instanceof HTMLEmbedElement || HTMLEmbedElement.isInstance(item) ||
(item instanceof HTMLObjectElement && !item.type.startsWith("image/")) (HTMLObjectElement.isInstance(item) && !item.type.startsWith("image/"))
) { ) {
props += "broken"; props += "broken";
} }
@ -720,9 +720,9 @@ function saveMedia() {
if (url) { if (url) {
var titleKey = "SaveImageTitle"; var titleKey = "SaveImageTitle";
if (item instanceof HTMLVideoElement) { if (HTMLVideoElement.isInstance(item)) {
titleKey = "SaveVideoTitle"; titleKey = "SaveVideoTitle";
} else if (item instanceof HTMLAudioElement) { } else if (HTMLAudioElement.isInstance(item)) {
titleKey = "SaveAudioTitle"; titleKey = "SaveAudioTitle";
} }

View file

@ -1998,7 +1998,7 @@
if (isMovingTabs) { if (isMovingTabs) {
let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0); let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
if ( if (
sourceNode instanceof XULElement && XULElement.isInstance(sourceNode) &&
sourceNode.localName == "tab" && sourceNode.localName == "tab" &&
sourceNode.ownerGlobal.isChromeWindow && sourceNode.ownerGlobal.isChromeWindow &&
sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == sourceNode.ownerDocument.documentElement.getAttribute("windowtype") ==

View file

@ -140,7 +140,7 @@ function performAccessKey(browser, key) {
callback, callback,
{ capture: true }, { capture: true },
event => { event => {
if (!(event.target instanceof HTMLElement)) { if (!HTMLElement.isInstance(event.target)) {
return false; // ignore window and document focus events return false; // ignore window and document focus events
} }

View file

@ -972,7 +972,7 @@ async function test_rotateGesturesOnTab() {
true true
); );
if (!(content.document instanceof ImageDocument)) { if (!ImageDocument.isInstance(content.document)) {
ok(false, "Image document failed to open for rotation testing"); ok(false, "Image document failed to open for rotation testing");
gBrowser.removeTab(test_imageTab); gBrowser.removeTab(test_imageTab);
BrowserTestUtils.removeTab(test_normalTab); BrowserTestUtils.removeTab(test_normalTab);

View file

@ -576,7 +576,7 @@ var gSearchResultsPane = {
// add it to the list of subitems. The items that don't match the search term // add it to the list of subitems. The items that don't match the search term
// will be hidden. // will be hidden.
if ( if (
child instanceof Element && Element.isInstance(child) &&
(child.classList.contains("featureGate") || (child.classList.contains("featureGate") ||
child.classList.contains("mozilla-product-item")) child.classList.contains("mozilla-product-item"))
) { ) {

View file

@ -54,7 +54,7 @@ class MarkupContextMenu {
show(event) { show(event) {
if ( if (
!(event.originalTarget instanceof Element) || !Element.isInstance(event.originalTarget) ||
event.originalTarget.closest("input[type=text]") || event.originalTarget.closest("input[type=text]") ||
event.originalTarget.closest("input:not([type])") || event.originalTarget.closest("input:not([type])") ||
event.originalTarget.closest("textarea") event.originalTarget.closest("textarea")

View file

@ -1521,18 +1521,22 @@ Column.prototype = {
// Only sort the array if we are sorting based on this column // Only sort the array if we are sorting based on this column
if (this.sorted == 1) { if (this.sorted == 1) {
items.sort((a, b) => { items.sort((a, b) => {
const val1 = const val1 = Node.isInstance(a[this.id])
a[this.id] instanceof Node ? a[this.id].textContent : a[this.id]; ? a[this.id].textContent
const val2 = : a[this.id];
b[this.id] instanceof Node ? b[this.id].textContent : b[this.id]; const val2 = Node.isInstance(b[this.id])
? b[this.id].textContent
: b[this.id];
return naturalSortCaseInsensitive(val1, val2); return naturalSortCaseInsensitive(val1, val2);
}); });
} else if (this.sorted > 1) { } else if (this.sorted > 1) {
items.sort((a, b) => { items.sort((a, b) => {
const val1 = const val1 = Node.isInstance(a[this.id])
a[this.id] instanceof Node ? a[this.id].textContent : a[this.id]; ? a[this.id].textContent
const val2 = : a[this.id];
b[this.id] instanceof Node ? b[this.id].textContent : b[this.id]; const val2 = Node.isInstance(b[this.id])
? b[this.id].textContent
: b[this.id];
return naturalSortCaseInsensitive(val2, val1); return naturalSortCaseInsensitive(val2, val1);
}); });
} }
@ -1683,13 +1687,13 @@ Cell.prototype = {
return; return;
} }
if (this.wrapTextInElements && !(value instanceof Node)) { if (this.wrapTextInElements && !Node.isInstance(value)) {
const span = this.label.ownerDocument.createElementNS(HTML_NS, "span"); const span = this.label.ownerDocument.createElementNS(HTML_NS, "span");
span.textContent = value; span.textContent = value;
value = span; value = span;
} }
if (value instanceof Node) { if (Node.isInstance(value)) {
this.label.removeAttribute("value"); this.label.removeAttribute("value");
while (this.label.firstChild) { while (this.label.firstChild) {

View file

@ -130,7 +130,7 @@ class LazyMessageList extends Component {
let element = this.#topBufferRef.current.nextSibling; let element = this.#topBufferRef.current.nextSibling;
let elementRect = element?.getBoundingClientRect(); let elementRect = element?.getBoundingClientRect();
while ( while (
element instanceof Element && Element.isInstance(element) &&
index < this.#clampedEndIndex && index < this.#clampedEndIndex &&
element !== this.#bottomBufferRef.current element !== this.#bottomBufferRef.current
) { ) {

View file

@ -427,7 +427,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
// node with `name="attributes"` exists in the DOM we need to bail. // node with `name="attributes"` exists in the DOM we need to bail.
if ( if (
!this.rawNode.attributes || !this.rawNode.attributes ||
!(this.rawNode.attributes instanceof NamedNodeMap) !NamedNodeMap.isInstance(this.rawNode.attributes)
) { ) {
return undefined; return undefined;
} }

View file

@ -14,8 +14,14 @@ These files are covered:
- ``*.js`` with a heuristic - ``*.js`` with a heuristic
Since there is no straightforward way to detect chrome scripts, currently the Since there is no straightforward way to detect chrome scripts, currently the
linter assumes that any script including ``ChromeUtils`` is chrome privileged. linter assumes that any script including the following words are chrome
This of course may not be sufficient and is open for change. privileged. This of course may not be sufficient and is open for change:
- ``ChromeUtils``, but not ``SpecialPowers.ChromeUtils``
- ``BrowserTestUtils``, ``PlacesUtils``
- ``document.createXULElement``
- ``loader.lazyRequireGetter``
- ``Services.foo``, but not ``SpecialPowers.Services.foo``
Examples of incorrect code for this rule: Examples of incorrect code for this rule:
----------------------------------------- -----------------------------------------

View file

@ -13,7 +13,7 @@ async function observeAttached(callback) {
function observer(subject, topic, data) { function observer(subject, topic, data) {
is(topic, TOPIC, "observing correct topic"); is(topic, TOPIC, "observing correct topic");
ok(subject instanceof BrowsingContext, "subject to be a BrowsingContext"); ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext");
is(typeof data, "string", "data to be a String"); is(typeof data, "string", "data to be a String");
info(`*** bc id=${subject.id}, why=${data}`); info(`*** bc id=${subject.id}, why=${data}`);
attached.set(subject.id, { browsingContext: subject, why: data }); attached.set(subject.id, { browsingContext: subject, why: data });

View file

@ -6,7 +6,7 @@ async function observeDiscarded(browsingContexts, callback) {
let discarded = []; let discarded = [];
let promise = BrowserUtils.promiseObserved(TOPIC, subject => { let promise = BrowserUtils.promiseObserved(TOPIC, subject => {
ok(subject instanceof BrowsingContext, "subject to be a BrowsingContext"); ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext");
discarded.push(subject); discarded.push(subject);
return browsingContexts.every(item => discarded.includes(item)); return browsingContexts.every(item => discarded.includes(item));

View file

@ -79,7 +79,7 @@ add_task(async function test_structuredCloneHolder() {
res = await resultPromise; res = await resultPromise;
ok( ok(
res.data instanceof StructuredCloneHolder, StructuredCloneHolder.isInstance(res.data),
"Sending structured clone holders through message managers works as expected" "Sending structured clone holders through message managers works as expected"
); );

View file

@ -41,7 +41,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=328885
inputelement.addEventListener('click', inputelement.addEventListener('click',
function(event) { function(event) {
var evt = SpecialPowers.wrap(event); var evt = SpecialPowers.wrap(event);
ok(SpecialPowers.call_Instanceof(evt.originalTarget, HTMLDivElement), ok(SpecialPowers.wrap(HTMLDivElement).isInstance(evt.originalTarget),
"(1) Wrong originalTarget!"); "(1) Wrong originalTarget!");
is(SpecialPowers.unwrap(evt.originalTarget.parentNode), inputelement, is(SpecialPowers.unwrap(evt.originalTarget.parentNode), inputelement,
"(2) Wront parent node!"); "(2) Wront parent node!");

View file

@ -51,7 +51,7 @@ add_task(async function test() {
}); });
}); });
ok(blob instanceof File, "We have a file"); ok(File.isInstance(blob), "We have a file");
is(blob.size, file.fileSize, "The size matches"); is(blob.size, file.fileSize, "The size matches");
is(blob.name, file.leafName, "The name is correct"); is(blob.name, file.leafName, "The name is correct");

View file

@ -54,7 +54,7 @@ add_task(async function testSteps() {
ok(false, "Should have thrown"); ok(false, "Should have thrown");
} catch (ex) { } catch (ex) {
ok(true, "Did throw"); ok(true, "Did throw");
ok(ex instanceof DOMException, "Threw DOMException"); ok(DOMException.isInstance(ex), "Threw DOMException");
is(ex.name, "QuotaExceededError", "Threw right DOMException"); is(ex.name, "QuotaExceededError", "Threw right DOMException");
is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code"); is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code");
} }

View file

@ -63,7 +63,7 @@ add_task(async function testSteps() {
ok(false, "Should have thrown"); ok(false, "Should have thrown");
} catch (ex) { } catch (ex) {
ok(true, "Did throw"); ok(true, "Did throw");
ok(ex instanceof DOMException, "Threw DOMException"); ok(DOMException.isInstance(ex), "Threw DOMException");
is(ex.name, "QuotaExceededError", "Threw right DOMException"); is(ex.name, "QuotaExceededError", "Threw right DOMException");
is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code"); is(ex.code, NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, "Threw with right code");
} }

View file

@ -77,7 +77,7 @@ async function addFrame(browser, path, selector) {
) { ) {
let document = content.document; let document = content.document;
let target = document.querySelector(selector); let target = document.querySelector(selector);
if (target instanceof content.HTMLIFrameElement) { if (content.HTMLIFrameElement.isInstance(target)) {
document = target.contentDocument; document = target.contentDocument;
target = document.body; target = document.body;
} }

View file

@ -51,7 +51,7 @@ add_task(async function test() {
}); });
}); });
ok(blob instanceof File, "We have a file"); ok(File.isInstance(blob), "We have a file");
is(blob.size, file.fileSize, "The size matches"); is(blob.size, file.fileSize, "The size matches");
is(blob.name, file.leafName, "The name is correct"); is(blob.name, file.leafName, "The name is correct");

View file

@ -216,6 +216,7 @@ add_task(async function runtimeSendMessageReply() {
add_task(async function runtimeSendMessageBlob() { add_task(async function runtimeSendMessageBlob() {
function background() { function background() {
browser.runtime.onMessage.addListener(msg => { browser.runtime.onMessage.addListener(msg => {
// eslint-disable-next-line mozilla/use-isInstance -- this function runs in an extension
browser.test.assertTrue(msg.blob instanceof Blob, "Message is a blob"); browser.test.assertTrue(msg.blob instanceof Blob, "Message is a blob");
return Promise.resolve(msg); return Promise.resolve(msg);
}); });
@ -230,6 +231,7 @@ add_task(async function runtimeSendMessageBlob() {
.sendMessage({ blob: new Blob(["hello"]) }) .sendMessage({ blob: new Blob(["hello"]) })
.then(response => { .then(response => {
browser.test.assertTrue( browser.test.assertTrue(
// eslint-disable-next-line mozilla/use-isInstance -- this function runs in an extension
response.blob instanceof Blob, response.blob instanceof Blob,
"Response is a blob" "Response is a blob"
); );

View file

@ -134,7 +134,7 @@ async function test_xhr({ manifest_version }) {
let x = await runXHR("http://example.com/dummy", { let x = await runXHR("http://example.com/dummy", {
responseType: "document", responseType: "document",
}); });
browser.test.assertTrue(x.response instanceof HTMLDocument, "is doc"); browser.test.assertTrue(HTMLDocument.isInstance(x.response), "is doc");
browser.test.assertTrue( browser.test.assertTrue(
x.response.querySelector("#id_of_some_element"), x.response.querySelector("#id_of_some_element"),
"got parsed document" "got parsed document"

View file

@ -137,8 +137,7 @@ add_task(async function test_returns_false_when_pref_disabled() {
// Use registration form test case, where we know it should return true if enabled // Use registration form test case, where we know it should return true if enabled
const testcase = TESTCASES[1]; const testcase = TESTCASES[1];
info("Starting testcase: " + testcase.description); info("Starting testcase: " + testcase.description);
const document = const document = Document.isInstance(testcase.document)
testcase.document instanceof Document
? testcase.document ? testcase.document
: MockDocument.createTestDocument( : MockDocument.createTestDocument(
"http://localhost:8080/test/", "http://localhost:8080/test/",
@ -164,8 +163,7 @@ for (let testcase of TESTCASES) {
(function() { (function() {
add_task(async function() { add_task(async function() {
info("Starting testcase: " + testcase.description); info("Starting testcase: " + testcase.description);
let document = let document = Document.isInstance(testcase.document)
testcase.document instanceof Document
? testcase.document ? testcase.document
: MockDocument.createTestDocument( : MockDocument.createTestDocument(
"http://localhost:8080/test/", "http://localhost:8080/test/",

View file

@ -48,7 +48,7 @@ add_task(async function test_fetchMany() {
for (let key of keys) { for (let key of keys) {
let page = pages.find(p => p.guid == key || p.url == key); let page = pages.find(p => p.guid == key || p.url == key);
Assert.deepEqual(page, fetched.get(key)); Assert.deepEqual(page, fetched.get(key));
Assert.ok(fetched.get(key).url instanceof URL); Assert.ok(URL.isInstance(fetched.get(key).url));
} }
}); });

View file

@ -37,8 +37,8 @@ const sandboxScript = function(shadowRoot) {
let doc = element.ownerDocument; let doc = element.ownerDocument;
let win = doc.defaultView; let win = doc.defaultView;
ok(shadowRoot instanceof win.ShadowRoot, "shadowRoot is a ShadowRoot"); ok(win.ShadowRoot.isInstance(shadowRoot), "shadowRoot is a ShadowRoot");
ok(element instanceof win.HTMLDivElement, "Element is a <div>"); ok(win.HTMLDivElement.isInstance(element), "Element is a <div>");
is("createElement" in doc, false, "No document.createElement"); is("createElement" in doc, false, "No document.createElement");
is("createElementNS" in doc, false, "No document.createElementNS"); is("createElementNS" in doc, false, "No document.createElementNS");
@ -67,7 +67,7 @@ const sandboxScript = function(shadowRoot) {
`<div xmlns="http://www.w3.org/1999/xhtml">Hello from DOMParser!</div>`, "application/xml"); `<div xmlns="http://www.w3.org/1999/xhtml">Hello from DOMParser!</div>`, "application/xml");
shadowRoot.importNodeAndAppendChildAt(shadowRoot, parserDoc.documentElement, true); shadowRoot.importNodeAndAppendChildAt(shadowRoot, parserDoc.documentElement, true);
ok(shadowRoot.lastChild instanceof win.HTMLDivElement, "<div> inserted"); ok(win.HTMLDivElement.isInstance(shadowRoot.lastChild), "<div> inserted");
is(shadowRoot.lastChild.textContent, "Hello from DOMParser!", "Deep import node worked"); is(shadowRoot.lastChild.textContent, "Hello from DOMParser!", "Deep import node worked");
info("UA Widget reflectors tests"); info("UA Widget reflectors tests");
@ -78,8 +78,8 @@ const sandboxScript = function(shadowRoot) {
SpecialPowers.Cu.evalInSandbox("this.script = " + sandboxScript.toString(), sandbox); SpecialPowers.Cu.evalInSandbox("this.script = " + sandboxScript.toString(), sandbox);
sandbox.script(div.shadowRoot); sandbox.script(div.shadowRoot);
ok(SpecialPowers.call_Instanceof(window.spanElementFromUAWidget, HTMLSpanElement), "<span> exposed"); ok(SpecialPowers.wrap(HTMLSpanElement).isInstance(window.spanElementFromUAWidget), "<span> exposed");
ok(SpecialPowers.call_Instanceof(window.divElementFromUAWidget, HTMLDivElement), "<div> exposed"); ok(SpecialPowers.wrap(HTMLDivElement).isInstance(window.divElementFromUAWidget), "<div> exposed");
try { try {
window.spanElementFromUAWidget.textContent; window.spanElementFromUAWidget.textContent;

View file

@ -95,9 +95,17 @@ function isChromeContext(context) {
return fs.readFileSync(filename).includes("there.is.only.xul"); return fs.readFileSync(filename).includes("there.is.only.xul");
} }
// Treat scripts using ChromeUtils as chrome scripts, but not SpecialPowers.ChromeUtils // Treat scripts as chrome privileged when using:
// 1. ChromeUtils, but not SpecialPowers.ChromeUtils
// 2. BrowserTestUtils, PlacesUtils
// 3. document.createXULElement
// 4. loader.lazyRequireGetter
// 5. Services.foo, but not SpecialPowers.Services.foo
// 6. evalInSandbox
const source = context.getSourceCode().text; const source = context.getSourceCode().text;
return !!source.match(/(^|\s)ChromeUtils/); return !!source.match(
/(^|\s)ChromeUtils|BrowserTestUtils|PlacesUtils|createXULElement|lazyRequireGetter|(^|\s)Services\.|evalInSandbox/
);
} }
module.exports = { module.exports = {