1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #4332 from node-red/4330-fix-multiple-input-handlers

Handle nodes with multiple input handlers properly
This commit is contained in:
Nick O'Leary 2023-09-19 09:19:22 +01:00 committed by GitHub
commit 2ccdeb968c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 5 deletions

View File

@ -42,6 +42,7 @@ function Node(n) {
this._closeCallbacks = []; this._closeCallbacks = [];
this._inputCallback = null; this._inputCallback = null;
this._inputCallbacks = null; this._inputCallbacks = null;
this._expectedDoneCount = 0;
if (n.name) { if (n.name) {
this.name = n.name; this.name = n.name;
@ -159,6 +160,9 @@ Node.prototype.on = function(event, callback) {
if (event == "close") { if (event == "close") {
this._closeCallbacks.push(callback); this._closeCallbacks.push(callback);
} else if (event === "input") { } else if (event === "input") {
if (callback.length === 3) {
this._expectedDoneCount++
}
if (this._inputCallback) { if (this._inputCallback) {
this._inputCallbacks = [this._inputCallback, callback]; this._inputCallbacks = [this._inputCallback, callback];
this._inputCallback = null; this._inputCallback = null;
@ -218,19 +222,17 @@ Node.prototype._emitInput = function(arg) {
} else if (node._inputCallbacks) { } else if (node._inputCallbacks) {
// Multiple callbacks registered. Call each one, tracking eventual completion // Multiple callbacks registered. Call each one, tracking eventual completion
var c = node._inputCallbacks.length; var c = node._inputCallbacks.length;
let doneCount = 0
for (var i=0;i<c;i++) { for (var i=0;i<c;i++) {
var cb = node._inputCallbacks[i]; var cb = node._inputCallbacks[i];
if (cb.length === 2) {
c++;
}
try { try {
cb.call( cb.call(
node, node,
arg, arg,
function() { node.send.apply(node,arguments) }, function() { node.send.apply(node,arguments) },
function(err) { function(err) {
c--; doneCount++;
if (c === 0) { if (doneCount === node._expectedDoneCount) {
node._complete(arg,err); node._complete(arg,err);
} }
} }
@ -257,6 +259,9 @@ Node.prototype._removeListener = Node.prototype.removeListener;
Node.prototype.removeListener = function(name, listener) { Node.prototype.removeListener = function(name, listener) {
var index; var index;
if (name === "input") { if (name === "input") {
if (listener.length === 3) {
this._expectedDoneCount--
}
if (this._inputCallback && this._inputCallback === listener) { if (this._inputCallback && this._inputCallback === listener) {
// Removing the only callback // Removing the only callback
this._inputCallback = null; this._inputCallback = null;

View File

@ -183,6 +183,35 @@ describe('Node', function() {
n.receive(message); n.receive(message);
}); });
it('calls parent flow handleComplete when multiple callbacks provided', function(done) {
var n = new RedNode({id:'123',type:'abc', _flow: {
handleComplete: function(node,msg) {
try {
doneCount.should.equal(2)
msg.should.deepEqual(message);
done();
} catch(err) {
done(err);
}
}
}});
var message = {payload:"hello world"};
let doneCount = 0
n.on('input',function(msg, nodeSend, nodeDone) {
doneCount++
nodeDone();
});
// Include a callback without explicit done signature
n.on('input',function(msg) { });
n.on('input',function(msg, nodeSend, nodeDone) {
doneCount++
nodeDone();
});
n.receive(message);
});
it('triggers onComplete hook when done callback provided', function(done) { it('triggers onComplete hook when done callback provided', function(done) {
var handleCompleteCalled = false; var handleCompleteCalled = false;
var hookCalled = false; var hookCalled = false;