@effectful/transducers
Version:
JS syntax transformation framework for @effectful/js
152 lines (151 loc) • 5.09 kB
JavaScript
"use strict";
exports.__esModule = true;
exports.default = void 0;
var _core = require("../core");
var Kit = require("../kit");
var _default = exports.default = Kit.pipe(Kit.wrap("instrumentation", function (s) {
let curId = 0;
const src = s.opts.file && s.opts.file.filenameRelative || "?";
function* walk(pn, fv) {
for (const i of s.sub()) {
switch (i.type) {
case _core.Tag.Identifier:
//TODO: needs checking if arguments variable not in scope
if (fv != null && i.pos !== _core.Tag.key && i.pos !== _core.Tag.property && i.value.node.name === "arguments") {
fv.hasArgs = true;
Kit.skip(s.copy(i));
yield s.tok(i.pos, _core.Tag.Identifier, {
node: {
name: "e$y$arguments"
}
});
continue;
}
break;
case _core.Tag.ThisExpression:
if (fv) {
fv.hasThis = true;
Kit.skip(s.copy(i));
yield s.tok(i.pos, _core.Tag.Identifier, {
node: {
name: "e$y$this"
}
});
}
continue;
case _core.Tag.Class:
case _core.Tag.ClassDeclaration:
if (i.enter) {
if (i.value.node.id != null) {
yield i;
yield* walk(pn.concat([i.value.node.id.name]));
continue;
}
}
break;
case _core.Tag.FunctionDeclaration:
case _core.Tag.FunctionExpression:
case _core.Tag.ObjectMethod:
case _core.Tag.ClassMethod:
case _core.Tag.ArrowFunctionExpression:
if (i.enter) {
const n = i.value.node;
if (Kit.hasAnnot(n, "@NOPROF")) break;
let nm,
sn,
ln = "?",
id = n.id || n.key;
if (id != null && id.name != null) {
sn = id.name;
} else {
sn = `F${curId++}`;
}
const nl = pn.concat(sn);
nm = nl.join(".");
nm += "@" + src;
if (n.loc != null) {
ln = `${n.loc.start.line}[${n.loc.start.column}]`;
}
const lab = s.label();
yield s.peel(i);
const j = yield* s.findPos(_core.Tag.body);
const expr = j.type !== _core.Tag.BlockStatement;
if (expr) {
i.value.node.expression = false;
yield s.enter(_core.Tag.body, _core.Tag.BlockStatement);
yield s.enter(_core.Tag.body, _core.Tag.Array);
} else {
yield s.peel(j);
yield* s.peelTo(_core.Tag.body);
}
yield s.enter(_core.Tag.push, _core.Tag.ReturnStatement);
yield s.enter(_core.Tag.argument, _core.Tag.CallExpression);
yield s.tok(_core.Tag.callee, _core.Tag.Identifier, {
node: {
name: n.generator ? "e$y$prof$g" : "e$y$prof"
}
});
yield s.enter(_core.Tag.arguments, _core.Tag.Array);
yield s.tok(_core.Tag.push, _core.Tag.StringLiteral, {
node: {
value: nm
}
});
yield s.tok(_core.Tag.push, _core.Tag.StringLiteral, {
node: {
value: ln
}
});
yield s.enter(_core.Tag.push, _core.Tag.FunctionExpression, {
node: {
params: [],
generator: n.generator
}
});
n.generator = false;
yield s.enter(_core.Tag.body, _core.Tag.BlockStatement);
yield s.enter(_core.Tag.body, _core.Tag.Array);
if (expr) {
yield s.enter(_core.Tag.push, _core.Tag.ReturnStatement);
yield s.peel(Kit.setPos(j, _core.Tag.argument));
}
yield* walk(nl, i.value);
yield* lab();
continue;
}
break;
}
yield i;
}
}
return walk([]);
}), Array.from,
//TODO: common pass
Kit.wrap("instrumentation-spec-vars", function (s) {
function* walk() {
for (const i of s.sub()) {
yield i;
if (i.enter) {
switch (i.type) {
case _core.Tag.FunctionDeclaration:
case _core.Tag.FunctionExpression:
case _core.Tag.ArrowFunctionExpression:
case _core.Tag.ClassMethod:
case _core.Tag.ObjectMethod:
if (i.value.hasThis || i.value.hasArgs) {
const lab = s.label();
yield* s.peelTo(_core.Tag.body);
yield* s.peelTo(_core.Tag.body);
//TODO: uniq names
if (i.value.hasThis) yield* s.toks(_core.Tag.push, "const e$y$this = this");
if (i.value.hasArgs) yield* s.toks(_core.Tag.push, "const e$y$arguments = arguments");
yield* walk(true);
yield* lab();
}
break;
}
}
}
}
return walk(false);
}));