diff --git a/package.json b/package.json index 2468fcbd2..856120695 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ } ], "dependencies": { + "acorn": "8.3.0", + "acorn-walk": "8.1.0", "ajv": "6.12.6", "async-mutex": "0.3.1", "basic-auth": "2.0.1", diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.js b/packages/node_modules/@node-red/nodes/core/function/10-function.js index 1b3dc3ba9..c1c20f266 100644 --- a/packages/node_modules/@node-red/nodes/core/function/10-function.js +++ b/packages/node_modules/@node-red/nodes/core/function/10-function.js @@ -19,6 +19,8 @@ module.exports = function(RED) { var util = require("util"); var vm = require("vm"); + var acorn = require("acorn"); + var acornWalk = require("acorn-walk"); function sendResults(node,send,_msgid,msgs,cloneFirstMessage) { if (msgs == null) { @@ -102,14 +104,7 @@ module.exports = function(RED) { throw new Error(RED._("function.error.externalModuleNotAllowed")); } - var handleNodeDoneCall = true; - // Check to see if the Function appears to call `node.done()`. If so, - // we will assume it is well written and does actually call node.done(). - // Otherwise, we will call node.done() after the function returns regardless. - if (/node\.done\s*\(\s*\)/.test(node.func)) { - handleNodeDoneCall = false; - } var functionText = "var results = null;"+ "results = (async function(msg,__send__,__done__){ "+ @@ -130,6 +125,26 @@ module.exports = function(RED) { "};\n"+ node.func+"\n"+ "})(msg,__send__,__done__);"; + + var handleNodeDoneCall = true; + + // Check to see if the Function appears to call `node.done()`. If so, + // we will assume it is well written and does actually call node.done(). + // Otherwise, we will call node.done() after the function returns regardless. + if (/node\.done\s*\(\s*\)/.test(functionText)) { + // We have spotted the code contains `node.done`. It could be in a comment + // so need to do the extra work to parse the AST and examine it properly. + acornWalk.simple(acorn.parse(functionText,{ecmaVersion: "latest"} ), { + CallExpression(astNode) { + if (astNode.callee && astNode.callee.object) { + if (astNode.callee.object.name === "node" && astNode.callee.property.name === "done") { + handleNodeDoneCall = false; + } + } + } + }) + } + var finScript = null; var finOpt = null; node.topic = n.topic; diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json index 747e584a9..223c07e96 100644 --- a/packages/node_modules/@node-red/nodes/package.json +++ b/packages/node_modules/@node-red/nodes/package.json @@ -15,6 +15,8 @@ } ], "dependencies": { + "acorn": "8.3.0", + "acorn-walk": "8.1.0", "ajv": "6.12.6", "body-parser": "1.19.0", "cheerio": "0.22.0",