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 6205af8f1..e2383c114 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 @@ -399,8 +399,8 @@ module.exports = function(RED) { if(node.timeout>0){ finOpt.timeout = node.timeout; finOpt.breakOnSigint = true; - } else if(RED.settings.defaultFunctionTimeout > 0){ - finOpt.timeout = RED.settings.defaultFunctionTimeout * 1000 + } else if (RED.settings.globalFunctionTimeout > 0){ + finOpt.timeout = RED.settings.globalFunctionTimeout * 1000 } } var promise = Promise.resolve(); @@ -417,13 +417,12 @@ module.exports = function(RED) { var opts = {}; if (node.timeout>0){ opts = node.timeoutOptions; - } else if(RED.settings.defaultFunctionTimeout > 0){ - opts.timeout = RED.settings.defaultFunctionTimeout * 1000 + } else if (RED.settings. globalFunctionTimeout > 0){ + opts.timeout = RED.settings. globalFunctionTimeout * 1000 } try { node.script.runInContext(context,opts); } catch (err) { - node.error(err); return done(err); } context.results.then(function(results) { diff --git a/packages/node_modules/node-red/settings.js b/packages/node_modules/node-red/settings.js index 2c589a62e..d6b3d993c 100644 --- a/packages/node_modules/node-red/settings.js +++ b/packages/node_modules/node-red/settings.js @@ -473,7 +473,7 @@ module.exports = { * - fileWorkingDirectory * - functionGlobalContext * - functionExternalModules - * - defaultFunctionTimeout + * - globalFunctionTimeout * - functionTimeout * - nodeMessageBufferMaxLength * - ui (for use with Node-RED Dashboard) @@ -502,27 +502,17 @@ module.exports = { /** - * Default function timeout (in seconds) for the Function node. - * A value of 0 indicates no timeout is applied, meaning the function can run indefinitely. - * - * The default function timeout is designed to prevent blocking code in function nodes, - * which could otherwise lead to a stalled or unresponsive main thread. For example, - * the following code would block the event loop indefinitely: - * - * `while(1) {}` - * - * By specifying a `defaultFunctionTimeout`, such scenarios can be mitigated, - * ensuring that long-running or infinite loops are terminated automatically after - * the specified timeout duration. - * - * Note: If both `defaultFunctionTimeout` and `functionTimeout` are defined in the - * settings file, `functionTimeout` takes precedence, providing a more granular - * control for individual function nodes. + * The default timeout (in seconds) for all Function nodes. + * Individual nodes can set their own timeout value within their configuration. */ + globalFunctionTimeout: 0, - defaultFunctionTimeout: 0, - - /** Default timeout, in seconds, for the Function node. 0 means no timeout is applied */ + /** + * Default timeout, in seconds, for the Function node. 0 means no timeout is applied + * This value is applied when the node is first added to the workspace - any changes + * must then be made with the individual node configurations. + * To set a global timeout value, use `globalFunctionTimeout` + */ functionTimeout: 0, /** The following property can be used to set predefined values in Global Context. diff --git a/test/nodes/core/function/10-function_spec.js b/test/nodes/core/function/10-function_spec.js index 3f7eedafd..6a04547f4 100644 --- a/test/nodes/core/function/10-function_spec.js +++ b/test/nodes/core/function/10-function_spec.js @@ -1437,7 +1437,7 @@ describe('function node', function() { var logEvents = helper.log().args.filter(function(evt) { return evt[0].type == "function"; }); - logEvents.should.have.length(2); + logEvents.should.have.length(1); var msg = logEvents[0][0]; msg.should.have.property('level', helper.log().ERROR); msg.should.have.property('id', 'n1'); @@ -1463,7 +1463,7 @@ describe('function node', function() { var logEvents = helper.log().args.filter(function (evt) { return evt[0].type == "function"; }); - logEvents.should.have.length(2); + logEvents.should.have.length(1); var msg = logEvents[0][0]; msg.should.have.property('level', helper.log().ERROR); msg.should.have.property('id', 'n1'); @@ -1480,7 +1480,7 @@ describe('function node', function() { }); it('check if default function timeout settings are recognized', function (done) { - RED.settings.defaultFunctionTimeout = 0.01; + RED.settings.globalFunctionTimeout = 0.01; var flow = [{id: "n1",type: "function",wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}]; helper.load(functionNode, flow, function () { var n1 = helper.getNode("n1"); @@ -1491,14 +1491,14 @@ describe('function node', function() { var logEvents = helper.log().args.filter(function (evt) { return evt[0].type == "function"; }); - logEvents.should.have.length(2); + logEvents.should.have.length(1); var msg = logEvents[0][0]; msg.should.have.property('level', helper.log().ERROR); msg.should.have.property('id', 'n1'); msg.should.have.property('type', 'function'); - should.equal(RED.settings.defaultFunctionTimeout, 0.01); + should.equal(RED.settings.globalFunctionTimeout, 0.01); should.equal(msg.msg.message, 'Script execution timed out after 10ms'); - delete RED.settings.defaultFunctionTimeout; + delete RED.settings.globalFunctionTimeout; done(); } catch (err) { done(err); @@ -1508,7 +1508,7 @@ describe('function node', function() { }); it('check if functionTimeout has higher precedence over default function timeout setting', function (done) { - RED.settings.defaultFunctionTimeout = 0.02; + RED.settings.globalFunctionTimeout = 0.02; RED.settings.functionTimeout = 0.01; var flow = [{id: "n1",type: "function",timeout: RED.settings.functionTimeout,wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}]; helper.load(functionNode, flow, function () { @@ -1520,16 +1520,16 @@ describe('function node', function() { var logEvents = helper.log().args.filter(function (evt) { return evt[0].type == "function"; }); - logEvents.should.have.length(2); + logEvents.should.have.length(1); var msg = logEvents[0][0]; msg.should.have.property('level', helper.log().ERROR); msg.should.have.property('id', 'n1'); msg.should.have.property('type', 'function'); should.equal(RED.settings.functionTimeout, 0.01); - should.equal(RED.settings.defaultFunctionTimeout, 0.02); + should.equal(RED.settings.globalFunctionTimeout, 0.02); should.equal(msg.msg.message, 'Script execution timed out after 10ms'); delete RED.settings.functionTimeout; - delete RED.settings.defaultFunctionTimeout; + delete RED.settings.globalFunctionTimeout; done(); } catch (err) { done(err);