Skip to content

Commit

Permalink
add random local scripts from chatgpt-source-watch/scripts/ast-poc
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdevalias committed Mar 28, 2024
1 parent 496eca0 commit 71fe5ca
Show file tree
Hide file tree
Showing 13 changed files with 43,243 additions and 0 deletions.
553 changes: 553 additions & 0 deletions babel_v1_3_cli.js

Large diffs are not rendered by default.

266 changes: 266 additions & 0 deletions esprima_5_scope_differ_v2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
#!/usr/bin/env node

// -------------------------------------------------------------------------------------------------
// TODO: The variable scope parsing/rewriting is pretty horribly broken in this currently I think..
// it might be easier to try and write it in something other than esprima...
// -------------------------------------------------------------------------------------------------

// Ref: https://replit.com/@0xdevalias/Rewriting-JavaScript-Variables-via-AST-Examples#esprima_5_scope_extractor.js

// Ref:
// https://chat.openai.com/c/07a322fd-ff60-4250-8e9c-cca0a732afce
// https://chat.openai.com/c/482911c5-6dd4-4e67-8531-c17f786887d1
//
// Note: This is based off the implementation in esprima_5.js, but this version is designed to extract the variableMapping from an existing piece of code; which can then be used later to rename those mappings

// TODO: Save these scripts somewhere useful:
// GITREF='HEAD' FILEREF='167'; git show ${GITREF}:../unpacked/_next/static/chunks/${FILEREF}.js | ./esprima_5_scope_extractor.js > variableMapping.${FILEREF}-${GITREF}.json
// git diff --no-index --patch -- variableMapping.167-HEAD\^1.json variableMapping.167-HEAD.json

// TODO: Explore using estools/escope instead of the hacky implementations within this:
// https://github.com/estools/escope

const fs = require('fs');

const {
readAndParseVariableMappingFile,
// makeDebugLog,
} = require('./lib/esprimaHelpers');

function diffVariableMappings(mapping1, mapping2) {
const diff = {
scopeAdded: {},
scopeRemoved: {},
scopeModified: {}
};

// Iterate through each scope in mapping1
for (const scope in mapping1) {
const scopeMapping1 = mapping1[scope];
const scopeMapping2 = mapping2[scope];

if (scope in mapping2) {
// Create objects to hold the added, removed, and changed keys
const added = {};
const removed = {};
const changed = {};

// Check for keys in scopeMapping1 but not in scopeMapping2
for (const key in scopeMapping1) {
if (!(key in scopeMapping2)) {
removed[key] = scopeMapping1[key];
} else if (scopeMapping1[key] !== scopeMapping2[key]) {
// Check for changed keys
changed[key] = { from: scopeMapping1[key], to: scopeMapping2[key] };
}
}

// Check for keys in scopeMapping2 but not in scopeMapping1
for (const key in scopeMapping2) {
if (!(key in scopeMapping1)) {
added[key] = scopeMapping2[key];
}
}

// Create an object to store the differences for this scope
const scopeDiff = {};

// Conditionally add added, removed, and changed to scopeDiff if non-empty
if (Object.keys(added).length > 0) scopeDiff.added = added;
if (Object.keys(removed).length > 0) scopeDiff.removed = removed;
if (Object.keys(changed).length > 0) scopeDiff.changed = changed;

// If there are differences, add them to the scopeModified under the scope
if (Object.keys(scopeDiff).length > 0) {
diff.scopeModified[scope] = scopeDiff;
}
} else {
// If the scope is not in mapping2, it is entirely removed
diff.scopeRemoved[scope] = scopeMapping1;
}
}

// Check for scopes in mapping2 that are not in mapping1
for (const scope in mapping2) {
if (!(scope in mapping1)) {
// If the scope is not in mapping1, it is entirely added
diff.scopeAdded[scope] = mapping2[scope];
}
}

// Remove empty sections
if (Object.keys(diff.scopeAdded).length === 0) delete diff.scopeAdded;
if (Object.keys(diff.scopeRemoved).length === 0) delete diff.scopeRemoved;
if (Object.keys(diff.scopeModified).length === 0) delete diff.scopeModified;

return diff;
}

// function diffVariableMappings(mapping1, mapping2) {
// const diff = {};

// // Iterate through each scope in mapping1
// for (const scope in mapping1) {
// const scopeMapping1 = mapping1[scope];
// const scopeMapping2 = mapping2[scope];

// if (scope in mapping2) {
// // Create objects to hold the added, removed, and changed keys
// const added = {};
// const removed = {};
// const changed = {};

// // Check for keys in scopeMapping1 but not in scopeMapping2
// for (const key in scopeMapping1) {
// if (!(key in scopeMapping2)) {
// removed[key] = scopeMapping1[key];
// } else if (scopeMapping1[key] !== scopeMapping2[key]) {
// // Check for changed keys
// changed[key] = { from: scopeMapping1[key], to: scopeMapping2[key] };
// }
// }

// // Check for keys in scopeMapping2 but not in scopeMapping1
// for (const key in scopeMapping2) {
// if (!(key in scopeMapping1)) {
// added[key] = scopeMapping2[key];
// }
// }

// // Create an object to store the differences for this scope
// const scopeDiff = {};

// // Conditionally add added, removed, and changed to scopeDiff if non-empty
// if (Object.keys(added).length > 0) scopeDiff.added = added;
// if (Object.keys(removed).length > 0) scopeDiff.removed = removed;
// if (Object.keys(changed).length > 0) scopeDiff.changed = changed;

// // If there are differences, add them to the diff under the scope
// if (Object.keys(scopeDiff).length > 0) {
// diff[scope] = scopeDiff;
// }
// } else {
// // If the scope is not in mapping2, consider it as entirely removed
// diff[scope] = { removed: scopeMapping1 };
// }
// }

// // Check for scopes in mapping2 that are not in mapping1
// for (const scope in mapping2) {
// if (!(scope in mapping1)) {
// diff[scope] = { added: mapping2[scope] };
// }
// }

// return diff;
// }

// function diffVariableMappings(mapping1, mapping2) {
// const diff = {};

// // Iterate through each scope in mapping1
// for (const scope in mapping1) {
// // If the scope is also in mapping2, compare the mappings
// if (scope in mapping2) {
// const scopeDiff = {};
// const scopeMapping1 = mapping1[scope];
// const scopeMapping2 = mapping2[scope];

// // Check for keys in scopeMapping1 but not in scopeMapping2
// for (const key in scopeMapping1) {
// if (!(key in scopeMapping2)) {
// scopeDiff[key] = scopeMapping1[key];
// }
// }

// // Check for keys in scopeMapping2 but not in scopeMapping1
// for (const key in scopeMapping2) {
// if (!(key in scopeMapping1)) {
// scopeDiff[key] = scopeMapping2[key];
// }
// }

// // If there are differences, add them to the diff under the scope
// if (Object.keys(scopeDiff).length > 0) {
// diff[scope] = scopeDiff;
// }
// } else {
// // If the scope is not in mapping2, add it to the diff
// diff[scope] = mapping1[scope];
// }
// }

// // Check for scopes in mapping2 that are not in mapping1
// for (const scope in mapping2) {
// if (!(scope in mapping1)) {
// if (scope in diff) {
// console.warn("WARNING: Scope from mapping2 overriding scope already in diff")
// }
// diff[scope] = mapping2[scope];
// }
// }

// return diff;
// }

// function diffVariableMappings(mapping1, mapping2) {
// const diffResult = {};

// console.error("Mapping 1:", mapping1["global.(anonymous_330)"]);
// console.error("Mapping 2:", mapping2["global.(anonymous_330)"]);

// // Iterate through the scopes in mapping1
// for (const [scope, variables] of Object.entries(mapping1)) {
// // Check if the scope exists in mapping2
// if (mapping2.hasOwnProperty(scope)) {
// // Temporary store for variable differences in current scope
// const scopeDiff = {};

// // Compare variables within the scope
// for (const [variable, mapping] of Object.entries(variables)) {
// if (mapping2[scope][variable] !== mapping) {
// // Add the different mapping to the scopeDiff
// scopeDiff[variable] = mapping2[scope][variable];
// }
// }

// // If there are differences in the scope, add them to diffResult
// if (Object.keys(scopeDiff).length > 0) {
// diffResult[scope] = scopeDiff;
// }
// }
// }

// // Iterate through the scopes in mapping2 to find scopes not present in mapping1
// for (const [scope, variables] of Object.entries(mapping2)) {
// if (!mapping1.hasOwnProperty(scope)) {
// // If the scope does not exist in mapping1, we add it to the result.
// diffResult[scope] = variables;
// }
// }

// return diffResult;
// }

async function main() {
if (process.argv.length !== 4) {
console.error('Usage: node diffVariableMappings.js <file1.json> <file2.json>');
process.exit(1);
}

const [file1Path, file2Path] = process.argv.slice(2);

try {
const mapping1 = await readAndParseVariableMappingFile(file1Path);
const mapping2 = await readAndParseVariableMappingFile(file2Path);

const diffResult = diffVariableMappings(mapping1, mapping2);

console.log(JSON.stringify(diffResult, null, 2));
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
}

main();
120 changes: 120 additions & 0 deletions esprima_5_scope_extractor_v3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env node

// Ref: https://replit.com/@0xdevalias/Rewriting-JavaScript-Variables-via-AST-Examples#esprima_5_scope_extractor.js

// Ref:
// https://chat.openai.com/c/07a322fd-ff60-4250-8e9c-cca0a732afce
// https://chat.openai.com/c/482911c5-6dd4-4e67-8531-c17f786887d1
//
// Note: This is based off the implementation in esprima_5.js, but this version is designed to extract the variableMapping from an existing piece of code; which can then be used later to rename those mappings

// TODO: Save these scripts somewhere useful:
// GITREF='HEAD' FILEREF='167'; git show ${GITREF}:../unpacked/_next/static/chunks/${FILEREF}.js | ./esprima_5_scope_extractor.js > variableMapping.${FILEREF}-${GITREF}.json
// git diff --no-index --patch -- variableMapping.167-HEAD\^1.json variableMapping.167-HEAD.json

// TODO: Explore using estools/escope instead of the hacky implementations within this:
// https://github.com/estools/escope

const readline = require('readline');

const esprima = require('esprima');
const estraverse = require('estraverse');

const {
readAndParseVariableMappingFile,
makeDebugLog,
getIndentation,
generateFunctionScopeName,
} = require('./lib/esprimaHelpers');

const DEBUG = process.env.DEBUG === 'true';

// Helper function for debug logging with indentation
const debugLog = makeDebugLog(DEBUG, { logFunc: console.log, linePrefix: '// ' });

// Check for stdin
if (process.stdin.isTTY) {
console.error('Error: Please provide JavaScript code via stdin.');
process.exit(1);
}

function extractVariableMapping(inputCode) {
// Parse the code into an Abstract Syntax Tree (AST)
const ast = esprima.parseScript(inputCode, { loc: true });

// Create a stack to keep track of the current scope
const scopeStack = ['global'];

// Keep track of the count of functions by type in each scope
const functionCountersByScope = {};

// Extract the variableMapping from the structure of the code
const variableMapping = {};

// Traverse the AST
estraverse.traverse(ast, {
enter: (node, parent) => {
// Track the current scope
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
const currentScope = generateFunctionScopeName(scopeStack, functionCountersByScope, node, parent);

debugLog(`Entering new scope: ${currentScope}`, scopeStack.length);

scopeStack.push(currentScope);
variableMapping[currentScope] = {};

// Add function parameters to the current scope
node.params.forEach(param => {
if (param.type === 'Identifier') {
variableMapping[currentScope][param.name] = param.name;
}
});

debugLog(`Variables in scope ${currentScope}: ${Object.keys(variableMapping[currentScope]).join(', ')}`, scopeStack.length);
}

const currentScope = scopeStack[scopeStack.length - 1];

// Extract variables to variableMapping
if (node.type === 'VariableDeclarator' && node.id.type === 'Identifier' && currentScope in variableMapping) {
variableMapping[currentScope][node.id.name] = node.id.name;
}
},
leave: (node, parent) => {
// Leave the current scope
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') {
debugLog(`Leaving scope: ${scopeStack[scopeStack.length - 1]}`, scopeStack.length - 1);
scopeStack.pop();
}
}
});

return variableMapping;
}

function main() {
let inputCode = '';

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});

rl.on('line', (line) => {
inputCode += line + '\n';
});

rl.on('close', () => {
if (!inputCode.trim()) {
console.error('Error: STDIN was empty');
process.exit(1);
}

const variableMapping = extractVariableMapping(inputCode);
// console.log(`const variableMapping = ${JSON.stringify(variableMapping, null, 2)}`);
console.log(JSON.stringify(variableMapping, null, 2));
});
}

main();
Loading

0 comments on commit 71fe5ca

Please sign in to comment.