mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	@@ -6,10 +6,13 @@ To make a change to the node-red runtime being used by K4 avalanche:
 | 
				
			|||||||
3. PR into this branch
 | 
					3. PR into this branch
 | 
				
			||||||
4. Merge on approval
 | 
					4. Merge on approval
 | 
				
			||||||
5. Manually bump the package version
 | 
					5. Manually bump the package version
 | 
				
			||||||
6. Run `npm run build`
 | 
					6. Run `npm run build` - note you need to run node 10 to do this, you also need to have xcode installed
 | 
				
			||||||
7. Manually publish to NPM with `npm publish` - Request creds from ops for this
 | 
					7. Manually publish to NPM with `npm publish` - Request creds from ops for this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dev Work
 | 
				
			||||||
 | 
					When doing dev work dont try to link into k4/k5 it just causes issue, instead just go into the node-modules of k4/k5 and make your changes in there
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# CHANGE-LOG
 | 
					# CHANGE-LOG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.18.7-patch-11
 | 
					## 0.18.7-patch-11
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,270 +14,365 @@
 | 
				
			|||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 **/
 | 
					 **/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const PayloadValidator = require('../../PayloadValidator')
 | 
					const clone = require("clone");
 | 
				
			||||||
 | 
					const PayloadValidator = require("../../PayloadValidator");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function(RED) {
 | 
					module.exports = function (RED) {
 | 
				
			||||||
    "use strict";
 | 
					  "use strict";
 | 
				
			||||||
    var util = require("util");
 | 
					  var util = require("util");
 | 
				
			||||||
    var vm2 = require("vm2");
 | 
					  var vm2 = require("vm2");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function sendResults(node,_msgid,msgs) {
 | 
					  function sendResults(node, _msgid, msgs) {
 | 
				
			||||||
        if (msgs == null) {
 | 
					    if (msgs == null) {
 | 
				
			||||||
            return;
 | 
					      return;
 | 
				
			||||||
        } else if (!util.isArray(msgs)) {
 | 
					    } else if (!util.isArray(msgs)) {
 | 
				
			||||||
            msgs = [msgs];
 | 
					      msgs = [msgs];
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        var msgCount = 0;
 | 
					 | 
				
			||||||
        for (var m=0; m<msgs.length; m++) {
 | 
					 | 
				
			||||||
            if (msgs[m]) {
 | 
					 | 
				
			||||||
                if (!util.isArray(msgs[m])) {
 | 
					 | 
				
			||||||
                    msgs[m] = [msgs[m]];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                for (var n=0; n < msgs[m].length; n++) {
 | 
					 | 
				
			||||||
                    var msg = msgs[m][n];
 | 
					 | 
				
			||||||
                    if (msg !== null && msg !== undefined) {
 | 
					 | 
				
			||||||
                        if (typeof msg === 'object' && !Buffer.isBuffer(msg) && !util.isArray(msg)) {
 | 
					 | 
				
			||||||
                            msg._msgid = _msgid;
 | 
					 | 
				
			||||||
                            msgCount++;
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                            var type = typeof msg;
 | 
					 | 
				
			||||||
                            if (type === 'object') {
 | 
					 | 
				
			||||||
                                type = Buffer.isBuffer(msg)?'Buffer':(util.isArray(msg)?'Array':'Date');
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            node.error(RED._("function.error.non-message-returned",{ type: type }))
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (msgCount>0) {
 | 
					 | 
				
			||||||
            node.send(msgs);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    var msgCount = 0;
 | 
				
			||||||
    function FunctionNode(n) {
 | 
					    for (var m = 0; m < msgs.length; m++) {
 | 
				
			||||||
        RED.nodes.createNode(this,n);
 | 
					      if (msgs[m]) {
 | 
				
			||||||
        var node = this;
 | 
					        if (!util.isArray(msgs[m])) {
 | 
				
			||||||
        this.name = n.name;
 | 
					          msgs[m] = [msgs[m]];
 | 
				
			||||||
        this.func = n.func;
 | 
					        }
 | 
				
			||||||
        var functionText = "var results = null;"+
 | 
					        for (var n = 0; n < msgs[m].length; n++) {
 | 
				
			||||||
                           "results = (function(msg){ "+
 | 
					          var msg = msgs[m][n];
 | 
				
			||||||
                              "var __msgid__ = msg._msgid;"+
 | 
					          if (msg !== null && msg !== undefined) {
 | 
				
			||||||
                              "var node = {"+
 | 
					            if (
 | 
				
			||||||
                                 "log:__node__.log,"+
 | 
					              typeof msg === "object" &&
 | 
				
			||||||
                                 "error:__node__.error,"+
 | 
					              !Buffer.isBuffer(msg) &&
 | 
				
			||||||
                                 "warn:__node__.warn,"+
 | 
					              !util.isArray(msg)
 | 
				
			||||||
                                 "debug:__node__.debug,"+
 | 
					            ) {
 | 
				
			||||||
                                 "trace:__node__.trace,"+
 | 
					              msg._msgid = _msgid;
 | 
				
			||||||
                                 "on:__node__.on,"+
 | 
					              msgCount++;
 | 
				
			||||||
                                 "status:__node__.status,"+
 | 
					            } else {
 | 
				
			||||||
                                 "send:function(msgs){ __node__.send(__msgid__,msgs);}"+
 | 
					              var type = typeof msg;
 | 
				
			||||||
                              "};\n"+ 
 | 
					              if (type === "object") {
 | 
				
			||||||
                              this.func+"\n"+
 | 
					                type = Buffer.isBuffer(msg)
 | 
				
			||||||
                           "})(msg);";
 | 
					                  ? "Buffer"
 | 
				
			||||||
        this.topic = n.topic;
 | 
					                  : util.isArray(msg)
 | 
				
			||||||
        this.outstandingTimers = [];
 | 
					                  ? "Array"
 | 
				
			||||||
        this.outstandingIntervals = [];
 | 
					                  : "Date";
 | 
				
			||||||
        var sandbox = {
 | 
					              }
 | 
				
			||||||
            console: console,
 | 
					              node.error(
 | 
				
			||||||
            util:util,
 | 
					                RED._("function.error.non-message-returned", { type: type })
 | 
				
			||||||
            //Buffer:Buffer,
 | 
					              );
 | 
				
			||||||
            //Date: Date,
 | 
					 | 
				
			||||||
            RED: {
 | 
					 | 
				
			||||||
                util: RED.util
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            __node__: {
 | 
					 | 
				
			||||||
                log: function() {
 | 
					 | 
				
			||||||
                    node.log.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                error: function() {
 | 
					 | 
				
			||||||
                    node.error.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                warn: function() {
 | 
					 | 
				
			||||||
                    node.warn.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                debug: function() {
 | 
					 | 
				
			||||||
                    node.debug.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                trace: function() {
 | 
					 | 
				
			||||||
                    node.trace.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                send: function(id, msgs) {
 | 
					 | 
				
			||||||
                    sendResults(node, id, msgs);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                on: function() {
 | 
					 | 
				
			||||||
                    if (arguments[0] === "input") {
 | 
					 | 
				
			||||||
                        throw new Error(RED._("function.error.inputListener"));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    node.on.apply(node, arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                status: function() {
 | 
					 | 
				
			||||||
                    node.status.apply(node, arguments);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            context: {
 | 
					 | 
				
			||||||
                set: function() {
 | 
					 | 
				
			||||||
                    node.context().set.apply(node,arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                get: function() {
 | 
					 | 
				
			||||||
                    return node.context().get.apply(node,arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                keys: function() {
 | 
					 | 
				
			||||||
                    return node.context().keys.apply(node,arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                get global() {
 | 
					 | 
				
			||||||
                    return node.context().global;
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                get flow() {
 | 
					 | 
				
			||||||
                    return node.context().flow;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            flow: {
 | 
					 | 
				
			||||||
                set: function() {
 | 
					 | 
				
			||||||
                    node.context().flow.set.apply(node,arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                get: function() {
 | 
					 | 
				
			||||||
                    return node.context().flow.get.apply(node,arguments);
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                keys: function() {
 | 
					 | 
				
			||||||
                    return node.context().flow.keys.apply(node,arguments);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            // global: {
 | 
					 | 
				
			||||||
            //     set: function() {
 | 
					 | 
				
			||||||
            //         node.context().global.set.apply(node,arguments);
 | 
					 | 
				
			||||||
            //     },
 | 
					 | 
				
			||||||
            //     get: function() {
 | 
					 | 
				
			||||||
            //         return node.context().global.get.apply(node,arguments);
 | 
					 | 
				
			||||||
            //     },
 | 
					 | 
				
			||||||
            //     keys: function() {
 | 
					 | 
				
			||||||
            //         return node.context().global.keys.apply(node,arguments);
 | 
					 | 
				
			||||||
            //     }
 | 
					 | 
				
			||||||
            // },
 | 
					 | 
				
			||||||
            setTimeout: function () {
 | 
					 | 
				
			||||||
                var func = arguments[0];
 | 
					 | 
				
			||||||
                var timerId;
 | 
					 | 
				
			||||||
                arguments[0] = function() {
 | 
					 | 
				
			||||||
                    sandbox.clearTimeout(timerId);
 | 
					 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        func.apply(this,arguments);
 | 
					 | 
				
			||||||
                    } catch(err) {
 | 
					 | 
				
			||||||
                        node.error(err,{});
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                timerId = setTimeout.apply(this,arguments);
 | 
					 | 
				
			||||||
                node.outstandingTimers.push(timerId);
 | 
					 | 
				
			||||||
                return timerId;
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            clearTimeout: function(id) {
 | 
					 | 
				
			||||||
                clearTimeout(id);
 | 
					 | 
				
			||||||
                var index = node.outstandingTimers.indexOf(id);
 | 
					 | 
				
			||||||
                if (index > -1) {
 | 
					 | 
				
			||||||
                    node.outstandingTimers.splice(index,1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            setInterval: function() {
 | 
					 | 
				
			||||||
                var func = arguments[0];
 | 
					 | 
				
			||||||
                var timerId;
 | 
					 | 
				
			||||||
                arguments[0] = function() {
 | 
					 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        func.apply(this,arguments);
 | 
					 | 
				
			||||||
                    } catch(err) {
 | 
					 | 
				
			||||||
                        node.error(err,{});
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                timerId = setInterval.apply(this,arguments);
 | 
					 | 
				
			||||||
                node.outstandingIntervals.push(timerId);
 | 
					 | 
				
			||||||
                return timerId;
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            clearInterval: function(id) {
 | 
					 | 
				
			||||||
                clearInterval(id);
 | 
					 | 
				
			||||||
                var index = node.outstandingIntervals.indexOf(id);
 | 
					 | 
				
			||||||
                if (index > -1) {
 | 
					 | 
				
			||||||
                    node.outstandingIntervals.splice(index,1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (msgCount > 0) {
 | 
				
			||||||
 | 
					      node.send(msgs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function FunctionNode(n) {
 | 
				
			||||||
 | 
					    RED.nodes.createNode(this, n);
 | 
				
			||||||
 | 
					    var node = this;
 | 
				
			||||||
 | 
					    this.name = n.name;
 | 
				
			||||||
 | 
					    this.func = n.func;
 | 
				
			||||||
 | 
					    var functionText =
 | 
				
			||||||
 | 
					      "var results = null;" +
 | 
				
			||||||
 | 
					      "results = (function(msg){ " +
 | 
				
			||||||
 | 
					      "var __msgid__ = msg._msgid;" +
 | 
				
			||||||
 | 
					      "var node = {" +
 | 
				
			||||||
 | 
					      "log:__node__.log," +
 | 
				
			||||||
 | 
					      "error:__node__.error," +
 | 
				
			||||||
 | 
					      "warn:__node__.warn," +
 | 
				
			||||||
 | 
					      "debug:__node__.debug," +
 | 
				
			||||||
 | 
					      "trace:__node__.trace," +
 | 
				
			||||||
 | 
					      "on:__node__.on," +
 | 
				
			||||||
 | 
					      "status:__node__.status," +
 | 
				
			||||||
 | 
					      "send:function(msgs){ __node__.send(__msgid__,msgs);}" +
 | 
				
			||||||
 | 
					      "};\n" +
 | 
				
			||||||
 | 
					      this.func +
 | 
				
			||||||
 | 
					      "\n" +
 | 
				
			||||||
 | 
					      "})(msg);";
 | 
				
			||||||
 | 
					    this.topic = n.topic;
 | 
				
			||||||
 | 
					    this.outstandingTimers = [];
 | 
				
			||||||
 | 
					    this.outstandingIntervals = [];
 | 
				
			||||||
 | 
					    var sandbox = {
 | 
				
			||||||
 | 
					      console: console,
 | 
				
			||||||
 | 
					      util: util,
 | 
				
			||||||
 | 
					      //Buffer:Buffer,
 | 
				
			||||||
 | 
					      //Date: Date,
 | 
				
			||||||
 | 
					      RED: {
 | 
				
			||||||
 | 
					        util: RED.util,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      __node__: {
 | 
				
			||||||
 | 
					        log: function () {
 | 
				
			||||||
 | 
					          node.log.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        error: function () {
 | 
				
			||||||
 | 
					          node.error.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        warn: function () {
 | 
				
			||||||
 | 
					          node.warn.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        debug: function () {
 | 
				
			||||||
 | 
					          node.debug.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        trace: function () {
 | 
				
			||||||
 | 
					          node.trace.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        send: function (id, msgs) {
 | 
				
			||||||
 | 
					          sendResults(node, id, msgs);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        on: function () {
 | 
				
			||||||
 | 
					          if (arguments[0] === "input") {
 | 
				
			||||||
 | 
					            throw new Error(RED._("function.error.inputListener"));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          node.on.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        status: function () {
 | 
				
			||||||
 | 
					          node.status.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {
 | 
				
			||||||
 | 
					        set: function () {
 | 
				
			||||||
 | 
					          node.context().set.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        get: function () {
 | 
				
			||||||
 | 
					          return node.context().get.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        keys: function () {
 | 
				
			||||||
 | 
					          return node.context().keys.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        get global() {
 | 
				
			||||||
 | 
					          return node.context().global;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        get flow() {
 | 
				
			||||||
 | 
					          return node.context().flow;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      flow: {
 | 
				
			||||||
 | 
					        set: function () {
 | 
				
			||||||
 | 
					          node.context().flow.set.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        get: function () {
 | 
				
			||||||
 | 
					          return node.context().flow.get.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        keys: function () {
 | 
				
			||||||
 | 
					          return node.context().flow.keys.apply(node, arguments);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      // global: {
 | 
				
			||||||
 | 
					      //     set: function() {
 | 
				
			||||||
 | 
					      //         node.context().global.set.apply(node,arguments);
 | 
				
			||||||
 | 
					      //     },
 | 
				
			||||||
 | 
					      //     get: function() {
 | 
				
			||||||
 | 
					      //         return node.context().global.get.apply(node,arguments);
 | 
				
			||||||
 | 
					      //     },
 | 
				
			||||||
 | 
					      //     keys: function() {
 | 
				
			||||||
 | 
					      //         return node.context().global.keys.apply(node,arguments);
 | 
				
			||||||
 | 
					      //     }
 | 
				
			||||||
 | 
					      // },
 | 
				
			||||||
 | 
					      setTimeout: function () {
 | 
				
			||||||
 | 
					        var func = arguments[0];
 | 
				
			||||||
 | 
					        var timerId;
 | 
				
			||||||
 | 
					        arguments[0] = function () {
 | 
				
			||||||
 | 
					          sandbox.clearTimeout(timerId);
 | 
				
			||||||
 | 
					          try {
 | 
				
			||||||
 | 
					            func.apply(this, arguments);
 | 
				
			||||||
 | 
					          } catch (err) {
 | 
				
			||||||
 | 
					            node.error(err, {});
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        timerId = setTimeout.apply(this, arguments);
 | 
				
			||||||
        if (util.hasOwnProperty('promisify')) {
 | 
					        node.outstandingTimers.push(timerId);
 | 
				
			||||||
            sandbox.setTimeout[util.promisify.custom] = function(after, value) {
 | 
					        return timerId;
 | 
				
			||||||
                return new Promise(function(resolve, reject) {
 | 
					      },
 | 
				
			||||||
                    sandbox.setTimeout(function(){ resolve(value) }, after);
 | 
					      clearTimeout: function (id) {
 | 
				
			||||||
                });
 | 
					        clearTimeout(id);
 | 
				
			||||||
            }
 | 
					        var index = node.outstandingTimers.indexOf(id);
 | 
				
			||||||
 | 
					        if (index > -1) {
 | 
				
			||||||
 | 
					          node.outstandingTimers.splice(index, 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        try {
 | 
					      },
 | 
				
			||||||
            this.on("input", function(msg) {
 | 
					      setInterval: function () {
 | 
				
			||||||
                try {
 | 
					        var func = arguments[0];
 | 
				
			||||||
                    const payloadValidator = new PayloadValidator(msg, this.id)
 | 
					        var timerId;
 | 
				
			||||||
                    var start = process.hrtime();
 | 
					        arguments[0] = function () {
 | 
				
			||||||
                    sandbox.msg = msg;
 | 
					          try {
 | 
				
			||||||
                    const vm2Instance = new vm2.VM({ sandbox, timeout: 5000 });
 | 
					            func.apply(this, arguments);
 | 
				
			||||||
                    const result = vm2Instance.run(functionText);
 | 
					          } catch (err) {
 | 
				
			||||||
                    payloadValidator.verify(result)
 | 
					            node.error(err, {});
 | 
				
			||||||
                    sendResults(this,msg._msgid, result);
 | 
					          }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
                    var duration = process.hrtime(start);
 | 
					        timerId = setInterval.apply(this, arguments);
 | 
				
			||||||
                    var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
 | 
					        node.outstandingIntervals.push(timerId);
 | 
				
			||||||
                    this.metric("duration", msg, converted);
 | 
					        return timerId;
 | 
				
			||||||
                    if (process.env.NODE_RED_FUNCTION_TIME) {
 | 
					      },
 | 
				
			||||||
                        this.status({fill:"yellow",shape:"dot",text:""+converted});
 | 
					      clearInterval: function (id) {
 | 
				
			||||||
                    }
 | 
					        clearInterval(id);
 | 
				
			||||||
                } catch(err) {
 | 
					        var index = node.outstandingIntervals.indexOf(id);
 | 
				
			||||||
                    //remove unwanted part
 | 
					        if (index > -1) {
 | 
				
			||||||
                    var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
 | 
					          node.outstandingIntervals.splice(index, 1);
 | 
				
			||||||
                    err.stack = err.stack.slice(0, index).split('\n').slice(0,-1).join('\n');
 | 
					 | 
				
			||||||
                    var stack = err.stack.split(/\r?\n/);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    //store the error in msg to be used in flows
 | 
					 | 
				
			||||||
                    msg.error = err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    var line = 0;
 | 
					 | 
				
			||||||
                    var errorMessage;
 | 
					 | 
				
			||||||
                    var stack = err.stack.split(/\r?\n/);
 | 
					 | 
				
			||||||
                    if (stack.length > 0) {
 | 
					 | 
				
			||||||
                        while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
 | 
					 | 
				
			||||||
                            line++;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if (line < stack.length) {
 | 
					 | 
				
			||||||
                            errorMessage = stack[line];
 | 
					 | 
				
			||||||
                            var m = /:(\d+):(\d+)$/.exec(stack[line+1]);
 | 
					 | 
				
			||||||
                            if (m) {
 | 
					 | 
				
			||||||
                                var lineno = Number(m[1])-1;
 | 
					 | 
				
			||||||
                                var cha = m[2];
 | 
					 | 
				
			||||||
                                errorMessage += " (line "+lineno+", col "+cha+")";
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    if (!errorMessage) {
 | 
					 | 
				
			||||||
                        errorMessage = err.toString();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // gives access to the msg object in custom logger
 | 
					 | 
				
			||||||
                    const temp = errorMessage;
 | 
					 | 
				
			||||||
                    errorMessage = msg;
 | 
					 | 
				
			||||||
                    errorMessage.toString = () => temp; // preserve original error message in logs
 | 
					 | 
				
			||||||
                    msg.errorMessage = temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    this.error(errorMessage, msg);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            this.on("close", function() {
 | 
					 | 
				
			||||||
                while (node.outstandingTimers.length > 0) {
 | 
					 | 
				
			||||||
                    clearTimeout(node.outstandingTimers.pop())
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                while (node.outstandingIntervals.length > 0) {
 | 
					 | 
				
			||||||
                    clearInterval(node.outstandingIntervals.pop())
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                this.status({});
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        } catch(err) {
 | 
					 | 
				
			||||||
            // eg SyntaxError - which v8 doesn't include line number information
 | 
					 | 
				
			||||||
            // so we can't do better than this
 | 
					 | 
				
			||||||
            this.error(err);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (util.hasOwnProperty("promisify")) {
 | 
				
			||||||
 | 
					      sandbox.setTimeout[util.promisify.custom] = function (after, value) {
 | 
				
			||||||
 | 
					        return new Promise(function (resolve, reject) {
 | 
				
			||||||
 | 
					          sandbox.setTimeout(function () {
 | 
				
			||||||
 | 
					            resolve(value);
 | 
				
			||||||
 | 
					          }, after);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    RED.nodes.registerType("function",FunctionNode);
 | 
					    try {
 | 
				
			||||||
    RED.library.register("functions");
 | 
					      this.on("input", async function (msg) {
 | 
				
			||||||
}
 | 
					        try {
 | 
				
			||||||
 | 
					          const originalMessage = clone(msg);
 | 
				
			||||||
 | 
					          const payloadValidator = new PayloadValidator(msg, this.id);
 | 
				
			||||||
 | 
					          var start = process.hrtime();
 | 
				
			||||||
 | 
					          sandbox.msg = msg;
 | 
				
			||||||
 | 
					          const vm2Instance = new vm2.VM({ sandbox, timeout: 5000 });
 | 
				
			||||||
 | 
					          const beforeVm2 = process.hrtime();
 | 
				
			||||||
 | 
					          const result = vm2Instance.run(functionText);
 | 
				
			||||||
 | 
					          const afterVm2 = process.hrtime(beforeVm2);
 | 
				
			||||||
 | 
					          payloadValidator.verify(result);
 | 
				
			||||||
 | 
					          sendResults(this, msg._msgid, result);
 | 
				
			||||||
 | 
					          const logger = clone(msg.logger);
 | 
				
			||||||
 | 
					          let lambdaRequestId;
 | 
				
			||||||
 | 
					          let {
 | 
				
			||||||
 | 
					            payload: {
 | 
				
			||||||
 | 
					              system: { organization },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            event: {
 | 
				
			||||||
 | 
					              workers: [{ id: workerId }],
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          } = originalMessage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const {
 | 
				
			||||||
 | 
					            settings: {
 | 
				
			||||||
 | 
					              api: { codefile = false },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          } = RED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (codefile) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					              const messageToSend = clone(msg);
 | 
				
			||||||
 | 
					              delete messageToSend.logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              const beforeCodefile = process.hrtime();
 | 
				
			||||||
 | 
					              const {
 | 
				
			||||||
 | 
					                result: {
 | 
				
			||||||
 | 
					                  Result: { msg: responseMessage },
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              } = await codefile.run({ srcCode: this.func, context: { msg } });
 | 
				
			||||||
 | 
					              const afterCodefile = process.hrtime(beforeCodefile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              responseMessage.logger = logger;
 | 
				
			||||||
 | 
					              payloadValidator.verify(responseMessage);
 | 
				
			||||||
 | 
					              // to make function node return result from code file uncomment this line, and comment out the sendResults above
 | 
				
			||||||
 | 
					              // sendResults(this,msg._msgid, responseMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              workerId = workerId.split(":::")[0];
 | 
				
			||||||
 | 
					              const nodeId = this.id.split(`${organization}-${workerId}-`)[1];
 | 
				
			||||||
 | 
					              lambdaRequestId = responseMessage.lambdaRequestId;
 | 
				
			||||||
 | 
					              const metrics = {
 | 
				
			||||||
 | 
					                lambdaRequestId: requestId,
 | 
				
			||||||
 | 
					                organization,
 | 
				
			||||||
 | 
					                workerId: workerId,
 | 
				
			||||||
 | 
					                nodeId: nodeId,
 | 
				
			||||||
 | 
					                rawCode: this.func,
 | 
				
			||||||
 | 
					                vm2Runtime: `${
 | 
				
			||||||
 | 
					                  Math.floor((afterVm2[0] * 1e9 + afterVm2[1]) / 10000) / 100
 | 
				
			||||||
 | 
					                }ms`,
 | 
				
			||||||
 | 
					                codefileRuntime: `${
 | 
				
			||||||
 | 
					                  Math.floor(
 | 
				
			||||||
 | 
					                    (afterCodefile[0] * 1e9 + afterCodefile[1]) / 10000
 | 
				
			||||||
 | 
					                  ) / 100
 | 
				
			||||||
 | 
					                }ms`,
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              logger.info(JSON.stringify(metrics, null, 2));
 | 
				
			||||||
 | 
					            } catch (e) {
 | 
				
			||||||
 | 
					              logger.error({
 | 
				
			||||||
 | 
					                message: "Error running codefile",
 | 
				
			||||||
 | 
					                error: e,
 | 
				
			||||||
 | 
					                lambdaRequestId,
 | 
				
			||||||
 | 
					                organization,
 | 
				
			||||||
 | 
					                workerId: workerId,
 | 
				
			||||||
 | 
					                nodeId: nodeId,
 | 
				
			||||||
 | 
					                rawCode: this.func,
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // sendResults(this,msg._msgid, responseMessage);
 | 
				
			||||||
 | 
					          var duration = process.hrtime(start);
 | 
				
			||||||
 | 
					          var converted =
 | 
				
			||||||
 | 
					            Math.floor((duration[0] * 1e9 + duration[1]) / 10000) / 100;
 | 
				
			||||||
 | 
					          this.metric("duration", msg, converted);
 | 
				
			||||||
 | 
					          if (process.env.NODE_RED_FUNCTION_TIME) {
 | 
				
			||||||
 | 
					            this.status({ fill: "yellow", shape: "dot", text: "" + converted });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } catch (err) {
 | 
				
			||||||
 | 
					          //remove unwanted part
 | 
				
			||||||
 | 
					          var index = err.stack.search(
 | 
				
			||||||
 | 
					            /\n\s*at ContextifyScript.Script.runInContext/
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					          err.stack = err.stack
 | 
				
			||||||
 | 
					            .slice(0, index)
 | 
				
			||||||
 | 
					            .split("\n")
 | 
				
			||||||
 | 
					            .slice(0, -1)
 | 
				
			||||||
 | 
					            .join("\n");
 | 
				
			||||||
 | 
					          var stack = err.stack.split(/\r?\n/);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          //store the error in msg to be used in flows
 | 
				
			||||||
 | 
					          msg.error = err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          var line = 0;
 | 
				
			||||||
 | 
					          var errorMessage;
 | 
				
			||||||
 | 
					          var stack = err.stack.split(/\r?\n/);
 | 
				
			||||||
 | 
					          if (stack.length > 0) {
 | 
				
			||||||
 | 
					            while (
 | 
				
			||||||
 | 
					              line < stack.length &&
 | 
				
			||||||
 | 
					              stack[line].indexOf("ReferenceError") !== 0
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					              line++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (line < stack.length) {
 | 
				
			||||||
 | 
					              errorMessage = stack[line];
 | 
				
			||||||
 | 
					              var m = /:(\d+):(\d+)$/.exec(stack[line + 1]);
 | 
				
			||||||
 | 
					              if (m) {
 | 
				
			||||||
 | 
					                var lineno = Number(m[1]) - 1;
 | 
				
			||||||
 | 
					                var cha = m[2];
 | 
				
			||||||
 | 
					                errorMessage += " (line " + lineno + ", col " + cha + ")";
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (!errorMessage) {
 | 
				
			||||||
 | 
					            errorMessage = err.toString();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // gives access to the msg object in custom logger
 | 
				
			||||||
 | 
					          const temp = errorMessage;
 | 
				
			||||||
 | 
					          errorMessage = msg;
 | 
				
			||||||
 | 
					          errorMessage.toString = () => temp; // preserve original error message in logs
 | 
				
			||||||
 | 
					          msg.errorMessage = temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          this.error(errorMessage, msg);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      this.on("close", function () {
 | 
				
			||||||
 | 
					        while (node.outstandingTimers.length > 0) {
 | 
				
			||||||
 | 
					          clearTimeout(node.outstandingTimers.pop());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        while (node.outstandingIntervals.length > 0) {
 | 
				
			||||||
 | 
					          clearInterval(node.outstandingIntervals.pop());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.status({});
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					      // eg SyntaxError - which v8 doesn't include line number information
 | 
				
			||||||
 | 
					      // so we can't do better than this
 | 
				
			||||||
 | 
					      this.error(err);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  RED.nodes.registerType("function", FunctionNode);
 | 
				
			||||||
 | 
					  RED.library.register("functions");
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1885
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1885
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -97,7 +97,7 @@
 | 
				
			|||||||
    "grunt-jsonlint": "~1.1.0",
 | 
					    "grunt-jsonlint": "~1.1.0",
 | 
				
			||||||
    "grunt-mocha-istanbul": "5.0.2",
 | 
					    "grunt-mocha-istanbul": "5.0.2",
 | 
				
			||||||
    "grunt-nodemon": "~0.4.2",
 | 
					    "grunt-nodemon": "~0.4.2",
 | 
				
			||||||
    "grunt-sass": "~2.0.0",
 | 
					    "grunt-sass": "^2.0.0",
 | 
				
			||||||
    "grunt-simple-mocha": "~0.4.1",
 | 
					    "grunt-simple-mocha": "~0.4.1",
 | 
				
			||||||
    "grunt-webdriver": "^2.0.3",
 | 
					    "grunt-webdriver": "^2.0.3",
 | 
				
			||||||
    "http-proxy": "^1.16.2",
 | 
					    "http-proxy": "^1.16.2",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user