Skip to content

Instantly share code, notes, and snippets.

@redexp
Created February 16, 2023 21:19
Show Gist options
  • Save redexp/7d4e7b7731c85e4ce8f29c26cb234fad to your computer and use it in GitHub Desktop.
Save redexp/7d4e7b7731c85e4ce8f29c26cb234fad to your computer and use it in GitHub Desktop.
Build cleared elk-worker from no needed code
const recast = require('recast');
const b = recast.types.builders;
const esprima = require('esprima-next');
const {readFileSync, writeFileSync} = require('fs');
const {resolve} = require('path');
const used = require('./used.json');
const INPUT = resolve(__dirname, 'node_modules/elkjs/lib/elk-worker.js');
const OUTPUT = resolve(__dirname, 'elk-worker-clear.js');
const ast = parse(readFileSync(INPUT, 'utf-8'));
const $noop = b.identifier('$noop');
recast.visit(ast, {
visitAssignmentExpression(path) {
const {node} = path;
if (
path.parent.value.type === 'ExpressionStatement' &&
node.left.type === 'MemberExpression' &&
node.left.object.type === 'Identifier' &&
node.left.property.type === 'Identifier' &&
node.right.type === 'FunctionExpression' &&
!used.includes(node.right.loc.start.line)
) {
path.parent.replace();
return false;
}
this.traverse(path);
},
visitFunctionExpression(path) {
const {line} = path.value.loc.start;
if (used.includes(line)) {
this.traverse(path);
return;
}
path.replace($noop);
return false;
},
visitFunctionDeclaration(path) {
const {line} = path.value.loc.start;
if (used.includes(line)) {
this.traverse(path);
return;
}
path.get('params').replace([]);
path.get('body').replace(b.blockStatement([]));
// path.replace();
return false;
},
});
ast.program.body.splice(1, 0, b.functionDeclaration(b.identifier('$noop'), [], b.blockStatement([])));
writeFileSync(OUTPUT, recast.print(ast).code, 'utf8');
function parse(code) {
return recast.parse(code, {
parser: esprima
});
}
const recast = require('recast');
const b = recast.types.builders;
const esprima = require('esprima-next');
const {readFileSync, writeFileSync} = require('fs');
const {resolve} = require('path');
const INPUT = resolve(__dirname, 'node_modules/elkjs/lib/elk-worker.js');
const OUTPUT = resolve(__dirname, 'elk-worker-dev.js');
console.log('parse');
const ast = parse(readFileSync(INPUT, 'utf-8'));
const $used = parse(`
const $used = {};
var $usedStr = '';
function $setUsed(i) {
$used[i] = true;
}
setInterval(() => {
const keys = Object.keys($used).map(i => Number(i)).sort((a, b) => a - b);
const str = JSON.stringify(keys);
if (str === $usedStr) return;
$usedStr = str;
console.log('write this array to used.json', keys);
}, 1000);
`);
const $setUsed = (i) => b.expressionStatement(
b.callExpression(
b.identifier('$setUsed'),
[b.literal(i)]
)
);
let prevLine = 0;
const addUsed = function (path) {
const {line} = path.value.loc.start;
if (line <= prevLine) {
throw new Error('invalid line');
}
prevLine = line;
path.value.body.body.unshift($setUsed(line));
this.traverse(path);
};
console.log('visit');
recast.visit(ast, {
visitFunctionExpression: addUsed,
visitFunctionDeclaration: addUsed,
});
ast.program.body.splice(1, 0, ...$used.program.body);
console.log('write');
writeFileSync(OUTPUT, recast.print(ast).code, 'utf8');
function parse(code) {
return recast.parse(code, {
parser: esprima
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment