var unparse = require('escodegen').generate; module.exports = function (ast, vars) { if (!vars) vars = {}; var FAIL = {}; var result = (function walk (node, scopeVars) { if (node.type === 'Literal') { return node.value; } else if (node.type === 'UnaryExpression'){ var val = walk(node.argument) if (node.operator === '+') return +val if (node.operator === '-') return -val if (node.operator === '~') return ~val if (node.operator === '!') return !val return FAIL } else if (node.type === 'ArrayExpression') { var xs = []; for (var i = 0, l = node.elements.length; i < l; i++) { var x = walk(node.elements[i]); if (x === FAIL) return FAIL; xs.push(x); } return xs; } else if (node.type === 'ObjectExpression') { var obj = {}; for (var i = 0; i < node.properties.length; i++) { var prop = node.properties[i]; var value = prop.value === null ? prop.value : walk(prop.value) ; if (value === FAIL) return FAIL; obj[prop.key.value || prop.key.name] = value; } return obj; } else if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') { var l = walk(node.left); if (l === FAIL) return FAIL; var r = walk(node.right); if (r === FAIL) return FAIL; var op = node.operator; if (op === '==') return l == r; if (op === '===') return l === r; if (op === '!=') return l != r; if (op === '!==') return l !== r; if (op === '+') return l + r; if (op === '-') return l - r; if (op === '*') return l * r; if (op === '/') return l / r; if (op === '%') return l % r; if (op === '<') return l < r; if (op === '<=') return l <= r; if (op === '>') return l > r; if (op === '>=') return l >= r; if (op === '|') return l | r; if (op === '&') return l & r; if (op === '^') return l ^ r; if (op === '&&') return l && r; if (op === '||') return l || r; return FAIL; } else if (node.type === 'Identifier') { if ({}.hasOwnProperty.call(vars, node.name)) { return vars[node.name]; } else return FAIL; } else if (node.type === 'ThisExpression') { if ({}.hasOwnProperty.call(vars, 'this')) { return vars['this']; } else return FAIL; } else if (node.type === 'CallExpression') { var callee = walk(node.callee); if (callee === FAIL) return FAIL; if (typeof callee !== 'function') return FAIL; var ctx = node.callee.object ? walk(node.callee.object) : FAIL; if (ctx === FAIL) ctx = null; var args = []; for (var i = 0, l = node.arguments.length; i < l; i++) { var x = walk(node.arguments[i]); if (x === FAIL) return FAIL; args.push(x); } return callee.apply(ctx, args); } else if (node.type === 'MemberExpression') { var obj = walk(node.object); // do not allow access to methods on Function if((obj === FAIL) || (typeof obj == 'function')){ return FAIL; } if (node.property.type === 'Identifier') { return obj[node.property.name]; } var prop = walk(node.property); if (prop === FAIL) return FAIL; return obj[prop]; } else if (node.type === 'ConditionalExpression') { var val = walk(node.test) if (val === FAIL) return FAIL; return val ? walk(node.consequent) : walk(node.alternate) } else if (node.type === 'ExpressionStatement') { var val = walk(node.expression) if (val === FAIL) return FAIL; return val; } else if (node.type === 'ReturnStatement') { return walk(node.argument) } else if (node.type === 'FunctionExpression') { var bodies = node.body.body; // Create a "scope" for our arguments var oldVars = {}; Object.keys(vars).forEach(function(element){ oldVars[element] = vars[element]; }) for(var i=0; i