自執行函式實參還原與替換
阿新 • • 發佈:2022-01-02
const parser = require("@babel/parser"); const traverse = require("@babel/traverse").default; // 將js程式碼轉換成AST // const { parse } = require("@babel/parser"); // 用來遍歷AST中的節點 // const traverse = require("@babel/traverse").default; // AST轉換成js const generator = require("@babel/generator").default; // 用來判斷節點型別和生成新的節點 consttypes = require("@babel/types"); const jscode = ` (function(t,a,b,c,d) { console.log(a[0]+a[1]); console.log(b[0]-b[1]); console.log(c); console.log(d); t = 123; })(5,[1,2],[5,3],6,-5); `; let ast = parser.parse(jscode); //判斷節點元素是否為字面量 //eg. ++123,-456,"789"; function isBaseLiteral(path) {if (path.isLiteral()) { return true; } if (path.isUnaryExpression({operator:"-"}) || path.isUnaryExpression({operator:"+"})) { return isBaseLiteral(path.get('argument')); } return false; } const resolveParams = { CallExpression(path) { let callee= path.get('callee'); let arguments = path.get('arguments'); if (!callee.isFunctionExpression() || arguments.length == 0) { return; } let scope = callee.scope; let params = callee.get('params'); for (let i=0;i< arguments.length;i++) { let paramsPath = params[i]; let argumentPath = arguments[i]; const binding = scope.getBinding(paramsPath.node.name); if (!binding || !binding.constant) { continue; } let canRemoved = true; for (let referPath of binding.referencePaths) { if (argumentPath.isIdentifier() || isBaseLiteral(argumentPath)) { referPath.replaceWith(argumentPath.node); } else if (argumentPath.isArrayExpression()) { let parentPath = referPath.parentPath if (!parentPath.isMemberExpression()) { canRemoved = false; continue; } let {property} = parentPath.node; if (!types.isNumericLiteral(property)) { canRemoved = false; continue; } let index = property.value; if (index > argumentPath.length) { canRemoved = false; continue; } let arrEle = argumentPath.node.elements[index]; parentPath.replaceWith(arrEle); } else { canRemoved = false; break; } } if (canRemoved) { paramsPath.remove(); argumentPath.remove(); } } }, } traverse(ast, resolveParams); let { code } = generator(ast); console.log(code);