Skip to content

Instantly share code, notes, and snippets.

@kmaglione
Created November 20, 2019 22:36
Show Gist options
  • Save kmaglione/24c5867ae6a1a80a3585aa538d752f17 to your computer and use it in GitHub Desktop.
Save kmaglione/24c5867ae6a1a80a3585aa538d752f17 to your computer and use it in GitHub Desktop.
"use strict";
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const nsFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { ProcessorBase } = ChromeUtils.import("resource://rewrites/Processor.jsm");
const { Replacer } = ChromeUtils.import("resource://rewrites/Replacer.jsm");
const { Parser, NodeWalker } = ChromeUtils.import("resource://rewrites/Parser.jsm");
var EXPORTED_SYMBOLS = ["Processor"];
Cu.importGlobalProperties(["fetch"]);
const CONTENTTASK_JSM = "resource://testing-common/ContentTask.jsm";
let mmGlobals = [
"addMessageListener",
"addWeakMessageListener",
"chromeOuterWindowID",
"removeMessageListener",
"removeWeakMessageListener",
"sendAsyncMessage",
"sendSyncMessage",
"sendRpcMessage",
];
let bah = new RegExp(`\\b(${mmGlobals.join("|")})\\b`);
const {isEmptyObject, isIdentifier, isLiteral, isMemberExpression} = Replacer.Utils;
class Processor extends ProcessorBase {
constructor(filters) {
super([], filters.length ? filters : null);
}
shouldProcess(path, text) {
return /\bContentTask\b/.test(text());
}
process(path, replacer) {
let isJSM = path.endsWith(".jsm");
let root = Parser.parse(replacer.code, path);
let self = this;
let leaf = path.replace(/.*\//, "");
let isHead = leaf.startsWith("head");
function mungeListeners(text) {
return text.replace(/ ((?:add|remove)EventListener)\(/g, (m0, m1) => {
return ` docShell.chromeEventHandler.${m1}(`;
}).replace(/ ((?:set|clear)(?:Timeout|Interval))\(/g, (m0, m1) => {
return ` content.${m1}(`;
});
}).replace(/ (privateNoteIntentionalCrash)\(/g, (m0, m1) => {
return ` ChromeUtils.${m1}(`;
}
let handlers = {
ChromeUtilsImport(node) {
if (!isLiteral(node.arguments[0], CONTENTTASK_JSM)) {
return;
}
switch (node.parent.type) {
case "VariableDeclarator":
if (node.parent.parent.type === "VariableDeclaration" &&
node.parent.parent.declarations.length === 1) {
replacer.remove(node.parent.parent);
}
break;
case "AssignmentExpression":
if (node.parent.parent.type === "ExpressionStatement") {
replacer.remove(node.parent.parent);
}
break;
}
},
ContentTaskSpawn(node) {
let args = node.arguments;
let newArgs = [replacer.getNodeText(args[0])];
if (isLiteral(args[1], null) || isEmptyObject(args[1])) {
newArgs.push("[]");
} else {
newArgs.push(`[${replacer.getNodeText(args[1])}]`);
}
newArgs.push(mungeListeners(replacer.getNodeText(args[2])));
if (bah.test(newArgs[2])) {
return;
}
let prefix = "";
if (isJSM) {
prefix = `${newArgs[0]}.ownerGlobal.`;
}
replacer.replaceCallee(node, `${prefix}SpecialPowers.spawn`, newArgs.join(", "));
},
};
root.walk(new NodeWalker({
CallExpression(node) {
if (isMemberExpression(node.callee, "ChromeUtils", "import")) {
return handlers.ChromeUtilsImport(node);
}
if (isMemberExpression(node.callee, "ContentTask", "spawn")) {
return handlers.ContentTaskSpawn(node);
}
},
}).onNode);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment