From f0839571d00df8bdf337278ce2cb9170bcb630f8 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 12 Sep 2019 22:08:52 +0100 Subject: [PATCH] Clone the first message passed to node.send in Function Also introduces an optional second arg to node.send in the Function node that can disable that cloning --- .../nodes/core/function/10-function.js | 14 ++++-- test/nodes/core/function/10-function_spec.js | 50 +++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) 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 f636b6b16..65a1b4a61 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,7 +19,7 @@ module.exports = function(RED) { var util = require("util"); var vm = require("vm"); - function sendResults(node,send,_msgid,msgs) { + function sendResults(node,send,_msgid,msgs,cloneFirstMessage) { if (msgs == null) { return; } else if (!util.isArray(msgs)) { @@ -35,6 +35,10 @@ module.exports = function(RED) { var msg = msgs[m][n]; if (msg !== null && msg !== undefined) { if (typeof msg === 'object' && !Buffer.isBuffer(msg) && !util.isArray(msg)) { + if (msgCount === 0 && cloneFirstMessage !== false) { + msgs[m][n] = RED.util.cloneMessage(msgs[m][n]); + msg = msgs[m][n]; + } msg._msgid = _msgid; msgCount++; } else { @@ -80,7 +84,7 @@ module.exports = function(RED) { "trace:__node__.trace,"+ "on:__node__.on,"+ "status:__node__.status,"+ - "send:function(msgs){ __node__.send(__send__,__msgid__,msgs);},"+ + "send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+ "done:__done__"+ "};\n"+ this.func+"\n"+ @@ -114,8 +118,8 @@ module.exports = function(RED) { trace: function() { node.trace.apply(node, arguments); }, - send: function(send, id, msgs) { - sendResults(node, send, id, msgs); + send: function(send, id, msgs, cloneMsg) { + sendResults(node, send, id, msgs, cloneMsg); }, on: function() { if (arguments[0] === "input") { @@ -241,7 +245,7 @@ module.exports = function(RED) { context.done = done; this.script.runInContext(context); - sendResults(this,send,msg._msgid,context.results); + sendResults(this,send,msg._msgid,context.results,false); if (handleNodeDoneCall) { done(); } diff --git a/test/nodes/core/function/10-function_spec.js b/test/nodes/core/function/10-function_spec.js index df44a66ee..c13dd1972 100644 --- a/test/nodes/core/function/10-function_spec.js +++ b/test/nodes/core/function/10-function_spec.js @@ -93,6 +93,56 @@ describe('function node', function() { }); }); + function testSendCloning(args,done) { + var flow = [{id:"n1",type:"function",wires:[["n2"],["n2"]],func:"node.send("+args+"); msg.payload = 'changed';"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + try { + msg.should.have.property('topic', 'bar'); + msg.should.have.property('payload', 'foo'); + done(); + } catch(err) { + done(err); + } + }); + var origMessage = {payload:"foo",topic: "bar"}; + n1.receive(origMessage); + }); + } + it('should clone single message sent using send()', function(done) { + testSendCloning("msg",done); + }); + it('should not clone single message sent using send(,false)', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.send(msg,false); msg.payload = 'changed';"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.should.have.property('payload', 'changed'); + done(); + }); + var origMessage = {payload:"foo",topic: "bar"}; + n1.receive(origMessage); + }); + }); + it('should clone first message sent using send() - array 1', function(done) { + testSendCloning("[msg]",done); + }); + it('should clone first message sent using send() - array 2', function(done) { + testSendCloning("[[msg],[null]]",done); + }); + it('should clone first message sent using send() - array 3', function(done) { + testSendCloning("[null,msg]",done); + }); + it('should clone first message sent using send() - array 3', function(done) { + testSendCloning("[null,[msg]]",done); + }); + it('should pass through _topic', function(done) { var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"}, {id:"n2", type:"helper"}];