Handle config nodes appearing out of order in flow

The editor ensures config nodes appear first in the flow file. The
code in the runtime and editor assumes this to be the case, so that
when a node is instantiated that requires a config node, it can assume
the config node already exists.

This change allows a config node to appear in the flow file after a
node that wants to use it. In both the editor and runtime, the code
now scans for config nodes and handles them first.
This commit is contained in:
Nick O'Leary 2015-02-24 23:02:45 +00:00
parent 049a5f1be6
commit d148a23ed6
2 changed files with 60 additions and 35 deletions

View File

@ -608,6 +608,21 @@ RED.nodes = (function() {
});
new_subflows.push(n);
addSubflow(n);
} else {
var def = registry.getNodeType(n.type);
if (def && def.category == "config") {
if (!RED.nodes.node(n.id)) {
var configNode = {id:n.id,type:n.type,users:[]};
for (var d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
}
}
configNode.label = def.label;
configNode._def = def;
RED.nodes.add(configNode);
}
}
}
}
if (defaultWorkspace == null) {
@ -627,19 +642,7 @@ RED.nodes = (function() {
// TODO: remove workspace in next release+1
if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") {
var def = registry.getNodeType(n.type);
if (def && def.category == "config") {
if (!RED.nodes.node(n.id)) {
var configNode = {id:n.id,type:n.type,users:[]};
for (var d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
}
}
configNode.label = def.label;
configNode._def = def;
RED.nodes.add(configNode);
}
} else {
if (!def || def.category != "config") {
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false};
if (createNewIds) {
if (subflow_map[node.z]) {

View File

@ -228,11 +228,14 @@ Flow.prototype.parseConfig = function(config) {
this.nodes = {};
this.subflows = {};
this.configNodes = {};
var unknownTypes = {};
for (i=0;i<this.config.length;i++) {
nodeConfig = this.config[i];
nodeType = nodeConfig.type;
this.allNodes[nodeConfig.id] = nodeConfig;
if (nodeType == "subflow") {
this.subflows[nodeConfig.id] = {
type: "subflow",
@ -243,11 +246,9 @@ Flow.prototype.parseConfig = function(config) {
}
//console.log("Known subflows:",Object.keys(this.subflows));
for (i=0;i<this.config.length;i++) {
nodeConfig = this.config[i];
this.allNodes[nodeConfig.id] = nodeConfig;
nodeType = nodeConfig.type;
@ -273,6 +274,15 @@ Flow.prototype.parseConfig = function(config) {
} else {
this.nodes[nodeConfig.id] = nodeInfo;
}
for (var prop in nodeConfig) {
if (nodeConfig.hasOwnProperty(prop) &&
prop != "id" &&
prop != "z" &&
prop != "wires" &&
this.allNodes[nodeConfig[prop]]) {
this.configNodes[nodeConfig[prop]] = this.allNodes[nodeConfig[prop]];
}
}
}
}
}
@ -302,10 +312,22 @@ Flow.prototype.start = function() {
throw new Error("missing types");
}
events.emit("nodes-starting");
for (var id in this.nodes) {
var id;
var node;
for (id in this.configNodes) {
if (this.configNodes.hasOwnProperty(id)) {
node = this.configNodes[id];
if (!this.activeNodes[id]) {
this.activeNodes[id] = createNode(node.type,node);
}
}
}
for (id in this.nodes) {
if (this.nodes.hasOwnProperty(id)) {
var node = this.nodes[id];
node = this.nodes[id];
if (!node.subflow) {
if (!this.activeNodes[id]) {
this.activeNodes[id] = createNode(node.type,node.config);
@ -460,7 +482,7 @@ Flow.prototype.applyConfig = function(config,type) {
Flow.prototype.diffFlow = function(config) {
var flow = this;
var configNodes = {};
var flowNodes = {};
var changedNodes = {};
var deletedNodes = {};
var linkChangedNodes = {};
@ -489,7 +511,7 @@ Flow.prototype.diffFlow = function(config) {
}
config.forEach(function(node) {
configNodes[node.id] = node;
flowNodes[node.id] = node;
});
config.forEach(function(node) {
@ -500,7 +522,7 @@ Flow.prototype.diffFlow = function(config) {
} else {
changed = diffNodeConfigs(flow.allNodes[node.id],node);
if (!changed) {
if (configNodes[node.z] && configNodes[node.z].type == "subflow") {
if (flowNodes[node.z] && flowNodes[node.z].type == "subflow") {
var originalNode = flow.allNodes[node.id];
if (originalNode && !redUtil.compareObjects(originalNode.wires,node.wires)) {
// This is a node in a subflow whose wiring has changed. Mark subflow as changed
@ -515,7 +537,7 @@ Flow.prototype.diffFlow = function(config) {
});
this.config.forEach(function(node) {
if (!configNodes[node.id] && node.type != "tab") {
if (!flowNodes[node.id] && node.type != "tab") {
deletedNodes[node.id] = node;
}
buildNodeLinks(activeLinks,node,flow.allNodes);
@ -550,7 +572,7 @@ Flow.prototype.diffFlow = function(config) {
}
};
Object.keys(changedNodes).forEach(function(n) { checkSubflowMembership(configNodes,n)});
Object.keys(changedNodes).forEach(function(n) { checkSubflowMembership(flowNodes,n)});
Object.keys(deletedNodes).forEach(function(n) { checkSubflowMembership(flow.allNodes,n)});
while (changedSubflowStack.length > 0) {
@ -560,7 +582,7 @@ Flow.prototype.diffFlow = function(config) {
if (node.type == "subflow:"+subflowId) {
if (!changedNodes[node.id]) {
changedNodes[node.id] = node;
checkSubflowMembership(configNodes,node.id);
checkSubflowMembership(flowNodes,node.id);
}
}
});
@ -568,7 +590,7 @@ Flow.prototype.diffFlow = function(config) {
}
config.forEach(function(node) {
buildNodeLinks(newLinks,node,configNodes);
buildNodeLinks(newLinks,node,flowNodes);
});
var markLinkedNodes = function(linkChanged,otherChangedNodes,linkMap,allNodes) {
@ -591,7 +613,7 @@ Flow.prototype.diffFlow = function(config) {
}
}
}
markLinkedNodes(linkChangedNodes,{},newLinks,configNodes);
markLinkedNodes(linkChangedNodes,{},newLinks,flowNodes);
markLinkedNodes(linkChangedNodes,{},activeLinks,flow.allNodes);
var modifiedLinkNodes = {};
@ -613,8 +635,8 @@ Flow.prototype.diffFlow = function(config) {
modifiedLinkNodes[node.id] = node;
linkChangedNodes[node.id] = node;
if (!changedNodes[link] && !deletedNodes[link]) {
modifiedLinkNodes[link] = configNodes[link];
linkChangedNodes[link] = configNodes[link];
modifiedLinkNodes[link] = flowNodes[link];
linkChangedNodes[link] = flowNodes[link];
}
}
});
@ -623,15 +645,15 @@ Flow.prototype.diffFlow = function(config) {
modifiedLinkNodes[node.id] = node;
linkChangedNodes[node.id] = node;
if (!changedNodes[link] && !deletedNodes[link]) {
modifiedLinkNodes[link] = configNodes[link];
linkChangedNodes[link] = configNodes[link];
modifiedLinkNodes[link] = flowNodes[link];
linkChangedNodes[link] = flowNodes[link];
}
}
});
}
});
markLinkedNodes(linkChangedNodes,modifiedLinkNodes,newLinks,configNodes);
markLinkedNodes(linkChangedNodes,modifiedLinkNodes,newLinks,flowNodes);
//config.forEach(function(n) {
// console.log((changedNodes[n.id]!=null)?"[C]":"[ ]",(linkChangedNodes[n.id]!=null)?"[L]":"[ ]","[ ]",n.id,n.type,n.name);
@ -643,14 +665,14 @@ Flow.prototype.diffFlow = function(config) {
//});
var diff = {
deleted: Object.keys(deletedNodes).filter(function(id) { return deletedNodes[id].type != "subflow" && (!deletedNodes[id].z || configNodes[deletedNodes[id].z].type != "subflow")}),
changed: Object.keys(changedNodes).filter(function(id) { return changedNodes[id].type != "subflow" && (!changedNodes[id].z || configNodes[changedNodes[id].z].type != "subflow")}),
linked: Object.keys(linkChangedNodes).filter(function(id) { return linkChangedNodes[id].type != "subflow" && (!linkChangedNodes[id].z || configNodes[linkChangedNodes[id].z].type != "subflow")}),
deleted: Object.keys(deletedNodes).filter(function(id) { return deletedNodes[id].type != "subflow" && (!deletedNodes[id].z || flowNodes[deletedNodes[id].z].type != "subflow")}),
changed: Object.keys(changedNodes).filter(function(id) { return changedNodes[id].type != "subflow" && (!changedNodes[id].z || flowNodes[changedNodes[id].z].type != "subflow")}),
linked: Object.keys(linkChangedNodes).filter(function(id) { return linkChangedNodes[id].type != "subflow" && (!linkChangedNodes[id].z || flowNodes[linkChangedNodes[id].z].type != "subflow")}),
wiringChanged: []
}
config.forEach(function(n) {
if (!configNodes[n.z] || configNodes[n.z].type != "subflow") {
if (!flowNodes[n.z] || flowNodes[n.z].type != "subflow") {
var originalNode = flow.allNodes[n.id];
if (originalNode && !redUtil.compareObjects(originalNode.wires,n.wires)) {
diff.wiringChanged.push(n.id);