@node-red/editor-client 4.0.7 → 4.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/editor-client",
3
- "version": "4.0.7",
3
+ "version": "4.0.8",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/public/red/about CHANGED
@@ -1,5 +1,11 @@
1
1
  #### 4.0.7: Maintenance Release
2
2
 
3
+ Editor
4
+
5
+ - Fix config node sort order when importing (#5000) @knolleary
6
+
7
+ #### 4.0.7: Maintenance Release
8
+
3
9
  Editor
4
10
 
5
11
  - Fix def can be undefined if the type is missing (#4997) @GogoVega
package/public/red/red.js CHANGED
@@ -6552,6 +6552,8 @@ RED.nodes = (function() {
6552
6552
  activeWorkspace = RED.workspaces.active();
6553
6553
  }
6554
6554
 
6555
+ const pendingConfigNodes = []
6556
+ const pendingConfigNodeIds = new Set()
6555
6557
  // Find all config nodes and add them
6556
6558
  for (i=0;i<newNodes.length;i++) {
6557
6559
  n = newNodes[i];
@@ -6611,7 +6613,8 @@ RED.nodes = (function() {
6611
6613
  type:n.type,
6612
6614
  info: n.info,
6613
6615
  users:[],
6614
- _config:{}
6616
+ _config:{},
6617
+ _configNodeReferences: new Set()
6615
6618
  };
6616
6619
  if (!n.z) {
6617
6620
  delete configNode.z;
@@ -6626,6 +6629,9 @@ RED.nodes = (function() {
6626
6629
  if (def.defaults.hasOwnProperty(d)) {
6627
6630
  configNode[d] = n[d];
6628
6631
  configNode._config[d] = JSON.stringify(n[d]);
6632
+ if (def.defaults[d].type) {
6633
+ configNode._configNodeReferences.add(n[d])
6634
+ }
6629
6635
  }
6630
6636
  }
6631
6637
  if (def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
@@ -6642,25 +6648,54 @@ RED.nodes = (function() {
6642
6648
  configNode.id = getID();
6643
6649
  }
6644
6650
  node_map[n.id] = configNode;
6645
- new_nodes.push(configNode);
6651
+ pendingConfigNodes.push(configNode);
6652
+ pendingConfigNodeIds.add(configNode.id)
6646
6653
  }
6647
6654
  }
6648
6655
  }
6649
6656
 
6650
- // Config node can use another config node, must ensure that this other
6651
- // config node is added before to exists when updating the user list
6652
- const configNodeFilter = function (node) {
6653
- let count = 0;
6654
- if (node._def?.defaults) {
6655
- for (const def of Object.values(node._def.defaults)) {
6656
- if (def.type) {
6657
- count++;
6658
- }
6657
+ // We need to sort new_nodes (which only contains config nodes at this point)
6658
+ // to ensure they get added in the right order. If NodeA depends on NodeB, then
6659
+ // NodeB must be added first.
6660
+
6661
+ // Limit us to 5 full iterations of the list - this should be more than
6662
+ // enough to process the list as config->config node relationships are
6663
+ // not very common
6664
+ let iterationLimit = pendingConfigNodes.length * 5
6665
+ const handledConfigNodes = new Set()
6666
+ while (pendingConfigNodes.length > 0 && iterationLimit > 0) {
6667
+ const node = pendingConfigNodes.shift()
6668
+ let hasPending = false
6669
+ // Loop through the nodes referenced by this node to see if anything
6670
+ // is pending
6671
+ node._configNodeReferences.forEach(id => {
6672
+ if (pendingConfigNodeIds.has(id) && !handledConfigNodes.has(id)) {
6673
+ // This reference is for a node we know is in this import, but
6674
+ // it isn't added yet - flag as pending
6675
+ hasPending = true
6659
6676
  }
6660
- }
6661
- return count;
6662
- };
6663
- new_nodes.sort((a, b) => configNodeFilter(a) - configNodeFilter(b));
6677
+ })
6678
+ if (!hasPending) {
6679
+ // This node has no pending config node references - safe to add
6680
+ delete node._configNodeReferences
6681
+ new_nodes.push(node)
6682
+ handledConfigNodes.add(node.id)
6683
+ } else {
6684
+ // This node has pending config node references
6685
+ // Put to the back of the queue
6686
+ pendingConfigNodes.push(node)
6687
+ }
6688
+ iterationLimit--
6689
+ }
6690
+ if (pendingConfigNodes.length > 0) {
6691
+ // We exceeded the iteration count. Could be due to reference loops
6692
+ // between the config nodes. At this point, just add the remaining
6693
+ // nodes as-is
6694
+ pendingConfigNodes.forEach(node => {
6695
+ delete node._configNodeReferences
6696
+ new_nodes.push(node)
6697
+ })
6698
+ }
6664
6699
 
6665
6700
  // Find regular flow nodes and subflow instances
6666
6701
  for (i=0;i<newNodes.length;i++) {