%PDF- %PDF-
Direktori : /usr/lib/node_modules/pm2/node_modules/degenerator/dist/src/ |
Current File : //usr/lib/node_modules/pm2/node_modules/degenerator/dist/src/index.js |
"use strict"; const util_1 = require("util"); const escodegen_1 = require("escodegen"); const esprima_1 = require("esprima"); const ast_types_1 = require("ast-types"); const vm2_1 = require("vm2"); /** * Compiles sync JavaScript code into JavaScript with async Functions. * * @param {String} code JavaScript string to convert * @param {Array} names Array of function names to add `await` operators to * @return {String} Converted JavaScript string with async/await injected * @api public */ function degenerator(code, _names) { if (!Array.isArray(_names)) { throw new TypeError('an array of async function "names" is required'); } // Duplicate the `names` array since it's rude to augment the user args const names = _names.slice(0); const ast = esprima_1.parseScript(code); // First pass is to find the `function` nodes and turn them into async or // generator functions only if their body includes `CallExpressions` to // function in `names`. We also add the names of the functions to the `names` // array. We'll iterate several time, as every iteration might add new items // to the `names` array, until no new names were added in the iteration. let lastNamesLength = 0; do { lastNamesLength = names.length; ast_types_1.visit(ast, { visitVariableDeclaration(path) { if (path.node.declarations) { for (let i = 0; i < path.node.declarations.length; i++) { const declaration = path.node.declarations[i]; if (ast_types_1.namedTypes.VariableDeclarator.check(declaration) && ast_types_1.namedTypes.Identifier.check(declaration.init) && ast_types_1.namedTypes.Identifier.check(declaration.id) && checkName(declaration.init.name, names) && !checkName(declaration.id.name, names)) { names.push(declaration.id.name); } } } return false; }, visitAssignmentExpression(path) { if (ast_types_1.namedTypes.Identifier.check(path.node.left) && ast_types_1.namedTypes.Identifier.check(path.node.right) && checkName(path.node.right.name, names) && !checkName(path.node.left.name, names)) { names.push(path.node.left.name); } return false; }, visitFunction(path) { if (path.node.id) { let shouldDegenerate = false; ast_types_1.visit(path.node, { visitCallExpression(path) { if (checkNames(path.node, names)) { shouldDegenerate = true; } return false; }, }); if (!shouldDegenerate) { return false; } // Got a "function" expression/statement, // convert it into an async function path.node.async = true; // Add function name to `names` array if (!checkName(path.node.id.name, names)) { names.push(path.node.id.name); } } this.traverse(path); }, }); } while (lastNamesLength !== names.length); // Second pass is for adding `await`/`yield` statements to any function // invocations that match the given `names` array. ast_types_1.visit(ast, { visitCallExpression(path) { if (checkNames(path.node, names)) { // A "function invocation" expression, // we need to inject a `AwaitExpression`/`YieldExpression` const delegate = false; const { name, parent: { node: pNode }, } = path; const expr = ast_types_1.builders.awaitExpression(path.node, delegate); if (ast_types_1.namedTypes.CallExpression.check(pNode)) { pNode.arguments[name] = expr; } else { pNode[name] = expr; } } this.traverse(path); }, }); return escodegen_1.generate(ast); } (function (degenerator) { function compile(code, returnName, names, options = {}) { const compiled = degenerator(code, names); const vm = new vm2_1.VM(options); const script = new vm2_1.VMScript(`${compiled};${returnName}`, { filename: options.filename, }); const fn = vm.run(script); if (typeof fn !== 'function') { throw new Error(`Expected a "function" to be returned for \`${returnName}\`, but got "${typeof fn}"`); } const r = function (...args) { try { const p = fn.apply(this, args); if (typeof (p === null || p === void 0 ? void 0 : p.then) === 'function') { return p; } return Promise.resolve(p); } catch (err) { return Promise.reject(err); } }; Object.defineProperty(r, 'toString', { value: fn.toString.bind(fn), enumerable: false, }); return r; } degenerator.compile = compile; })(degenerator || (degenerator = {})); /** * Returns `true` if `node` has a matching name to one of the entries in the * `names` array. * * @param {types.Node} node * @param {Array} names Array of function names to return true for * @return {Boolean} * @api private */ function checkNames({ callee }, names) { let name; if (ast_types_1.namedTypes.Identifier.check(callee)) { name = callee.name; } else if (ast_types_1.namedTypes.MemberExpression.check(callee)) { if (ast_types_1.namedTypes.Identifier.check(callee.object) && ast_types_1.namedTypes.Identifier.check(callee.property)) { name = `${callee.object.name}.${callee.property.name}`; } else { return false; } } else if (ast_types_1.namedTypes.FunctionExpression.check(callee)) { if (callee.id) { name = callee.id.name; } else { return false; } } else { throw new Error(`Don't know how to get name for: ${callee.type}`); } return checkName(name, names); } function checkName(name, names) { // now that we have the `name`, check if any entries match in the `names` array for (let i = 0; i < names.length; i++) { const n = names[i]; if (util_1.isRegExp(n)) { if (n.test(name)) { return true; } } else if (name === n) { return true; } } return false; } module.exports = degenerator; //# sourceMappingURL=index.js.map