From 290eb9fe1941c7d5f5d694f2a3aff6d925efc98e Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 16 Sep 2024 01:49:53 -0700 Subject: [PATCH] Update variable storage types and fix JavaScript handling Changed storage driver types for 'Products' and 'Product' variables to `WorkflowInstanceStorageDriver`. Refactored JavaScript handling to properly process variables and exclude input names from overwriting. Re-enabled a previously skipped array sorting test. --- .../Handlers/ConfigureEngineWithVariables.cs | 38 +++++++++++++++---- .../Activities/ParallelForEachT.cs | 6 +-- .../JavascriptAndLiquidWorkflow.cs | 6 +-- .../JavaScriptListsAndArrays/Tests.cs | 4 +- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs index 89e5c3688..621a3cb47 100644 --- a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs +++ b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs @@ -1,9 +1,11 @@ using System.Dynamic; +using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.JavaScript.Helpers; using Elsa.JavaScript.Models; using Elsa.JavaScript.Notifications; using Elsa.Mediator.Contracts; +using Elsa.Workflows.Activities; using JetBrains.Annotations; using Jint; using Jint.Native; @@ -20,7 +22,7 @@ public class ConfigureEngineWithVariables : INotificationHandler)engine.GetValue("variables").ToObject()!; - + var inputNames = GetInputNames(context).Distinct().ToList(); + foreach (var (variableName, variableValue) in variablesContainer) { - var processedValue = variableValue is JsObject jsObject ? jsObject.ToObject() : variableValue; + if (inputNames.Contains(variableName)) + continue; + + var processedValue = variableValue is JsObject jsValue ? jsValue.ToObject() : variableValue ?? context.GetVariableInScope(variableName); context.SetVariable(variableName, processedValue); } } + private IEnumerable GetInputNames(ExpressionExecutionContext context) + { + var activityExecutionContext = context.TryGetActivityExecutionContext(out var aec) ? aec : null; + + while (activityExecutionContext != null) + { + if (activityExecutionContext.Activity is Workflow workflow) + { + var inputDefinitions = workflow.Inputs; + + foreach (var inputDefinition in inputDefinitions) + yield return inputDefinition.Name; + } + + activityExecutionContext = activityExecutionContext.ParentActivityExecutionContext; + } + } + private void CopyVariablesIntoEngine(EvaluatingJavaScript notification) { var engine = notification.Engine; var context = notification.Context; var variableNames = context.GetVariableNamesInScope().ToList(); var variablesContainer = (IDictionary)new ExpandoObject(); - + foreach (var variableName in variableNames) { var variableValue = context.GetVariableInScope(variableName); variableValue = ProcessVariableValue(engine, variableValue); variablesContainer[variableName] = variableValue; } - + engine.SetValue("variables", variablesContainer); } @@ -61,8 +85,8 @@ public class ConfigureEngineWithVariables : INotificationHandler : Activity var tags = new List(); var currentIndex = 0; - SetTagList(context, ScheduledTagsProperty, tags); - SetTagList(context, CompletedTagsProperty, new List()); - await foreach (var item in items) { // For each item, declare a new variable for the work to be scheduled. @@ -65,6 +62,9 @@ public class ParallelForEach : Activity await context.ScheduleActivityAsync(Body, OnChildCompleted, tag, variables); } + SetTagList(context, ScheduledTagsProperty, tags); + SetTagList(context, CompletedTagsProperty, new List()); + // If there were no items, we're done. if (tags.Count == 0) await context.CompleteActivityAsync(); diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/HttpRequestWithLiquid/JavascriptAndLiquidWorkflow.cs b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/HttpRequestWithLiquid/JavascriptAndLiquidWorkflow.cs index 18ecc023a..a6f3b85e7 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/HttpRequestWithLiquid/JavascriptAndLiquidWorkflow.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/HttpRequestWithLiquid/JavascriptAndLiquidWorkflow.cs @@ -13,8 +13,8 @@ public class JavascriptAndLiquidWorkflow : WorkflowBase { protected override void Build(IWorkflowBuilder builder) { - var products = new Variable { Name = "Products", StorageDriverType = typeof(WorkflowStorageDriver) }; - var product = new Variable { Name = "Product", StorageDriverType = typeof(WorkflowStorageDriver) }; + var products = new Variable { Name = "Products", StorageDriverType = typeof(WorkflowInstanceStorageDriver) }; + var product = new Variable { Name = "Product", StorageDriverType = typeof(WorkflowInstanceStorageDriver) }; builder.Root = new Sequence { @@ -31,7 +31,7 @@ public class JavascriptAndLiquidWorkflow : WorkflowBase new WriteLine(new Expression("Liquid", "Second product id: {{ Variables.Products[1].id }}")), new RunJavaScript { - Script = new(@"setProduct({""id"":2, ""price"":10})") + Script = new(@"variables.Product = {""id"":2, ""price"":10}") }, new WriteLine(new Expression("Liquid", "Single product id: {{ Variables.Product.id }}")), new WriteLine(new Expression("Liquid", "Single product as json: {{ Variables.Product | json }}")), diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptListsAndArrays/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptListsAndArrays/Tests.cs index 537b86c0d..1bb11cac9 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptListsAndArrays/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptListsAndArrays/Tests.cs @@ -79,7 +79,7 @@ public class Tests Assert.Equal(43, magicNumber); } - [Theory(DisplayName = "Can sort array and list properties as mutable arrays", Skip = "Not supported yet. See https://github.com/elsa-workflows/elsa-core/issues/5912")] + [Theory(DisplayName = "Can sort array and list properties as mutable arrays")] [MemberData(nameof(ArraySortEnumerableData))] // See also: // - https://github.com/sebastienros/jint/issues/1942 @@ -89,7 +89,7 @@ public class Tests dynamic dynamicObject = new ExpandoObject(); dynamicObject.Items = collection; var script = """ - const model = getModel(); + const model = variables.Model; model.Items.sort((a, b) => a - b); return model; """;