Skip to content

Commit

Permalink
fix: Fix resolving of expressions of deeply nested sub-nodes (#8612)
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegIvaniv authored Feb 14, 2024
1 parent d18cba3 commit f527430
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 43 deletions.
5 changes: 1 addition & 4 deletions packages/editor-ui/src/components/VariableSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ export default defineComponent({
if (!activeNode) {
return null;
}
return this.workflowHelpers.getParentMainInputNode(
this.workflowHelpers.getCurrentWorkflow(),
activeNode,
);
return this.workflow.getParentMainInputNode(activeNode);
},
extendAll(): boolean {
if (this.variableFilter) {
Expand Down
38 changes: 1 addition & 37 deletions packages/editor-ui/src/composables/useWorkflowHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,41 +73,6 @@ import { useI18n } from '@/composables/useI18n';
import type { Router } from 'vue-router';
import { useTelemetry } from '@/composables/useTelemetry';

export function getParentMainInputNode(workflow: Workflow, node: INode): INode {
const nodeType = useNodeTypesStore().getNodeType(node.type);
if (nodeType) {
const outputs = NodeHelpers.getNodeOutputs(workflow, node, nodeType);

if (!!outputs.find((output) => output !== NodeConnectionType.Main)) {
// Get the first node which is connected to a non-main output
const nonMainNodesConnected = outputs?.reduce((acc, outputName) => {
const parentNodes = workflow.getChildNodes(node.name, outputName);
if (parentNodes.length > 0) {
acc.push(...parentNodes);
}
return acc;
}, [] as string[]);

if (nonMainNodesConnected.length) {
const returnNode = workflow.getNode(nonMainNodesConnected[0]);
if (returnNode === null) {
// This should theoretically never happen as the node is connected
// but who knows and it makes TS happy
throw new Error(
`The node "${nonMainNodesConnected[0]}" which is a connection of "${node.name}" could not be found!`,
);
}

// The chain of non-main nodes is potentially not finished yet so
// keep on going
return getParentMainInputNode(workflow, returnNode);
}
}
}

return node;
}

export function resolveParameter(
parameter: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
opts: {
Expand All @@ -127,7 +92,7 @@ export function resolveParameter(
const workflow = getCurrentWorkflow();

if (activeNode) {
contextNode = getParentMainInputNode(workflow, activeNode);
contextNode = workflow.getParentMainInputNode(activeNode);
}

const workflowRunData = useWorkflowsStore().getWorkflowRunData;
Expand Down Expand Up @@ -1187,7 +1152,6 @@ export function useWorkflowHelpers(router: Router) {
getCurrentWorkflow,
getConnectedNodes,
getNodes,
getParentMainInputNode,
getWorkflow,
getNodeTypes,
connectionInputData,
Expand Down
44 changes: 43 additions & 1 deletion packages/workflow/src/Workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ import type {
NodeParameterValueType,
ConnectionTypes,
CloseFunction,
INodeOutputConfiguration,
} from './Interfaces';
import { Node } from './Interfaces';
import { Node, NodeConnectionType } from './Interfaces';
import type { IDeferredPromise } from './DeferredPromise';

import * as NodeHelpers from './NodeHelpers';
Expand Down Expand Up @@ -845,6 +846,47 @@ export class Workflow {
return returnConns;
}

getParentMainInputNode(node: INode): INode {
if (node) {
const nodeType = this.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
const outputs = NodeHelpers.getNodeOutputs(this, node, nodeType.description);

if (
!!outputs.find(
(output) =>
((output as INodeOutputConfiguration)?.type ?? output) !== NodeConnectionType.Main,
)
) {
// Get the first node which is connected to a non-main output
const nonMainNodesConnected = outputs?.reduce((acc, outputName) => {
const parentNodes = this.getChildNodes(
node.name,
(outputName as INodeOutputConfiguration)?.type ?? outputName,
);
if (parentNodes.length > 0) {
acc.push(...parentNodes);
}
return acc;
}, [] as string[]);

if (nonMainNodesConnected.length) {
const returnNode = this.getNode(nonMainNodesConnected[0]);
if (returnNode === null) {
// This should theoretically never happen as the node is connected
// but who knows and it makes TS happy
throw new ApplicationError(`Node "${nonMainNodesConnected[0]}" not found`);
}

// The chain of non-main nodes is potentially not finished yet so
// keep on going
return this.getParentMainInputNode(returnNode);
}
}
}

return node;
}

/**
* Returns via which output of the parent-node and index the current node
* they are connected
Expand Down
8 changes: 7 additions & 1 deletion packages/workflow/src/WorkflowDataProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,13 @@ export class WorkflowDataProxy {

// Before resolving the pairedItem make sure that the requested node comes in the
// graph before the current one
const parentNodes = that.workflow.getParentNodes(that.contextNodeName);
const activeNode = that.workflow.getNode(that.activeNodeName);
let contextNode = that.contextNodeName;
if (activeNode) {
const parentMainInputNode = that.workflow.getParentMainInputNode(activeNode);
contextNode = parentMainInputNode.name ?? contextNode;
}
const parentNodes = that.workflow.getParentNodes(contextNode);
if (!parentNodes.includes(nodeName)) {
throw createExpressionError('Invalid expression', {
messageTemplate: 'Invalid expression under ‘%%PARAMETER%%’',
Expand Down

0 comments on commit f527430

Please sign in to comment.