Looks like mostly normal JS code. It keeps a stack of names for each time .__sub__ctx__
is called. The output of this program is "value: 10, stack: foo->bar->baz".
You could use this technique to e.g. pass a log function around that's specific to an HTTP request, or a database client, or implement a hierarchy of event emitters.
function makeCtx() {
'disable ctx';
const ctx = {
namePath: [],
__sub__ctx__(name) {
return { ...this, namePath: this.namePath.concat([name]) };
}
};
return ctx;
}
const delay = ms => new Promise((resolve) => setTimeout(resolve, ms));
async function foo() {
Promise.all([
delay(300).then(() => bar()),
delay(300).then(() => baz()),
]);
quux();
}
function foo(n) {
bar(n + 2);
}
function bar(m) {
baz(c(m + 3))
}
function baz(value) {
console.log(`value: ${value}, stack: ${ctx.namePath.join('->')}`);
}
const c = (x) => x + 4;
async function run() {
const ctx = makeCtx();
await foo();
}
run();
All the magic happens here:
export default function(babel) {
const { types: t, template } = babel;
const LOCAL = `ctx`;
const IMPL = `__ctx__`;
const FUNC = `__get${IMPL}`;
const SUB = `__sub${IMPL}`;
const ignoreIdent = new RegExp(String.raw`\b(${LOCAL}|${IMPL}|${FUNC}|${SUB})\b`, "g");
const getGlobal = `window`;
const access = template(`var ${LOCAL} = ${getGlobal}.${FUNC} && ${getGlobal}.${FUNC}.length && ${getGlobal}.${FUNC}.slice(-1)[0]();`);
const wrapCall = template(`(${getGlobal}.${FUNC}.push(
() => ${LOCAL} && ${LOCAL}.${SUB}(NAME)
),
UID = CALL,
${getGlobal}.${FUNC}.pop(),
UID
)`);
const initCtx = template(`${getGlobal}.${FUNC} = ${getGlobal}.${FUNC} || []`);
const SKIP = new WeakMap();
const OUR_NODES = new WeakMap();
const OUR_CTX_VAR = new WeakMap();
function maybeGetCallWrapper(path) {
const callee = path.get("callee");
let subName = "(unknown)";
if (path.node.hasOwnProperty("_fromTemplate")) return null;
const testIgnore = p => p.isIdentifier() && ignoreIdent.test(p.node.name);
if (path.parentPath.isSequenceExpression()) return null;
if (callee.isIdentifier()) {
const name = callee.node.name;
subName = name;
if (!path.scope.getBinding(name)) return null;
if (testIgnore(callee)) return null;
}
if (callee.isMemberExpression()) {
let nameParts = [];
let root = callee;
if (testIgnore(root.get("property"))) {
return null;
}
while (true) {
const next = root.get("object");
if (testIgnore(root.get("property"))) {
return null;
}
if (next && next.node) {
root = next;
} else {
break;
}
}
const prop = callee.get("property");
for (const value of [prop, root]) {
if (value.isIdentifier()) {
if (ignoreIdent.test(value.node.name)) return;
subName = prop.node.name;
}
}
if (root && root.isIdentifier()) {
if (!path.scope.getBinding(root.node.name)) {
return null;
}
}
}
const created = wrapCall({ NAME: t.stringLiteral(subName), CALL: path.node, UID: path.scope.generateDeclaredUidIdentifier(`ret`) });
console.log(created._fromTemplate);
const node = created.expression;
OUR_CTX_VAR.set(node, true);
return node;
}
function shouldDisableHere(_path) {
let path = _path;
do {
const dirs = path.get("directives");
if (!dirs || !dirs.length) continue;
const match = dirs.some(x => {
const v = x.get("value");
if (!v || !v.node) return false;
if (v.node.value === "disable ctx") return true;
});
if (match) return true;
} while ((path = path.parentPath));
return false;
}
return {
name: "ast-transform", // not required
visitor: {
Program(path) {
path.node.body.unshift(initCtx());
},
Function(path) {
if (shouldDisableHere(path)) return;
if (SKIP.has(path.node)) return;
if (path.node.params.some(x => t.isIdentifier(x) && x.name === "ctx")) {
return;
}
let skip = false;
path.traverse({
enter(path2) {
if (path2.isFunction()) return path2.skip();
if (path2.isVariableDeclarator()) {
const name = path2.get("id").node.name;
if (name === LOCAL) {
skip = true;
return path2.stop();
}
}
}
});
SKIP.set(path.node, true);
if (skip) return;
let body = path.get("body");
if (!body.isBlock()) {
body.replaceWith(t.blockStatement([t.returnStatement(body.node)]));
return;
}
const f = access();
path.node.body.body.unshift(f);
},
CallExpression(path) {
if (shouldDisableHere(path)) return;
if (SKIP.has(path.node)) return;
SKIP.set(path.node, true);
const localCtx = path.scope.getBinding(LOCAL);
if (localCtx && localCtx.path.node.type === "VariableDeclarator") {
const ourRoot = localCtx.path.findParent(p => OUR_CTX_VAR.has(p.node));
if (!ourRoot || !ourRoot.node) {
// console.log(`Skipping`, path.node);
// return;
}
}
if (!localCtx && !path.findParent(p => p.isFunction())) {
return;
}
const node = maybeGetCallWrapper(path);
if (!node) return;
SKIP.set(node, true);
path.replaceWith(node);
}
}
};
}
The combination of the above produces this:
window.__get__ctx__ = window.__get__ctx__ || [];
const delay = ms => {
return new Promise(resolve => {
return setTimeout(resolve, ms);
});
};
async function foo(ctx) {
var _ret, _ret2, _ret4, _ret5;
Promise.all([
(window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("then");
}), _ret = (window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("delay");
}), _ret2 = delay(300), window.__get__ctx__.pop(), _ret2).then(() => {
var _ret3;
return window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("bar");
}), _ret3 = bar(), window.__get__ctx__.pop(), _ret3;
}), window.__get__ctx__.pop(), _ret),
(window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("then");
}), _ret4 = (window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("delay");
}), _ret5 = delay(300), window.__get__ctx__.pop(), _ret5).then(() => {
var _ret6;
return window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("baz");
}), _ret6 = baz(), window.__get__ctx__.pop(), _ret6;
}), window.__get__ctx__.pop(), _ret4),
]);
quux();
}
function foo(n) {
var _ret7;
var ctx = window.__get__ctx__ && window.__get__ctx__.length && window.__get__ctx__.slice(-1)[0]();
window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("bar");
}), _ret7 = bar(n + 2), window.__get__ctx__.pop(), _ret7;
}
function bar(m) {
var _ret8, _ret9;
var ctx = window.__get__ctx__ && window.__get__ctx__.length && window.__get__ctx__.slice(-1)[0]();
window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("baz");
}), _ret8 = baz((window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("c");
}), _ret9 = c(m + 3), window.__get__ctx__.pop(), _ret9)), window.__get__ctx__.pop(), _ret8
}
function baz(value) {
var ctx = window.__get__ctx__ && window.__get__ctx__.length && window.__get__ctx__.slice(-1)[0]();
console.log(`value: ${value}, stack: ${ctx.namePath.join('->')}`);
}
const c = x => {
return x + 4;
};
async function run() {
var _ret10, _ret11;
const ctx = (window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("makeCtx");
}), _ret10 = makeCtx(), window.__get__ctx__.pop(), _ret10);
await (window.__get__ctx__.push(() => {
return ctx && ctx.__sub__ctx__("foo");
}), _ret11 = foo(1), window.__get__ctx__.pop(), _ret11);
}
function makeCtx() {
'disable ctx';
const ctx = {
namePath: [],
__sub__ctx__(name) {
return { ...this, namePath: this.namePath.concat([name]) };
}
};
return ctx;
}
run();