< Summary

Line coverage
91%
Covered lines: 44
Uncovered lines: 4
Coverable lines: 48
Total lines: 145
Line coverage: 91.6%
Branch coverage
76%
Covered branches: 23
Total branches: 30
Branch coverage: 76.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Expressions.JavaScript/Handlers/ConfigureEngineWithVariables.cs

#LineLine coverage
 1using System.Dynamic;
 2using System.Text.RegularExpressions;
 3using Elsa.Expressions.Models;
 4using Elsa.Extensions;
 5using Elsa.Expressions.JavaScript.Extensions;
 6using Elsa.Expressions.JavaScript.Helpers;
 7using Elsa.Expressions.JavaScript.Notifications;
 8using Elsa.Expressions.JavaScript.Options;
 9using Elsa.Mediator.Contracts;
 10using Elsa.Workflows.Activities;
 11using JetBrains.Annotations;
 12using Jint.Native;
 13using Microsoft.Extensions.Options;
 14
 15namespace Elsa.Expressions.JavaScript.Handlers;
 16
 17/// <summary>
 18/// A handler that configures the Jint engine with workflow variables.
 19/// </summary>
 20[UsedImplicitly]
 90921public partial class ConfigureEngineWithVariables(IOptions<JintOptions> options) : INotificationHandler<EvaluatingJavaSc
 22{
 56423    private bool IsEnabled => options.Value is { DisableWrappers: false, DisableVariableCopying: false };
 24
 25    /// <inheritdoc />
 26    public Task HandleAsync(EvaluatingJavaScript notification, CancellationToken cancellationToken)
 27    {
 28528        if (!IsEnabled)
 029            return Task.CompletedTask;
 30
 28531        CopyVariablesIntoEngine(notification);
 28532        return Task.CompletedTask;
 33    }
 34
 35    public Task HandleAsync(EvaluatedJavaScript notification, CancellationToken cancellationToken)
 36    {
 27937        if (!IsEnabled)
 038            return Task.CompletedTask;
 39
 27940        CopyVariablesIntoWorkflowExecutionContext(notification);
 27941        return Task.CompletedTask;
 42    }
 43
 44    private void CopyVariablesIntoWorkflowExecutionContext(EvaluatedJavaScript notification)
 45    {
 27946        var context = notification.Context;
 27947        var engine = notification.Engine;
 27948        var variablesContainer = (IDictionary<string, object?>)engine.GetValue("variables").ToObject()!;
 49
 50        // Only the variables the expression actually referenced were copied in, so an expression that never
 51        // mentions "variables." has nothing to copy back and does not need the input names resolved at all.
 27952        if (variablesContainer.Count == 0)
 26353            return;
 54
 1655        var inputNames = GetInputNames(context).FilterInvalidVariableNames().ToHashSet(StringComparer.Ordinal);
 56
 6457        foreach (var (variableName, variableValue) in variablesContainer)
 58        {
 1659            if (inputNames.Contains(variableName))
 60                continue;
 61
 1662            var processedValue = variableValue is JsObject jsValue ? jsValue.ToObject() : variableValue ?? context.GetVa
 1663            context.SetVariable(variableName, processedValue);
 64        }
 1665    }
 66
 67    private void CopyVariablesIntoEngine(EvaluatingJavaScript notification)
 68    {
 28569        var engine = notification.Engine;
 28570        var context = notification.Context;
 28571        var expression = notification.Expression;
 28572        var variableNames = GetUsedVariableNames(context, expression).ToList();
 28573        var variablesContainer = (IDictionary<string, object?>)new ExpandoObject();
 74
 59075        foreach (var variableName in variableNames)
 76        {
 1077            var variableValue = context.GetVariableInScope(variableName);
 1078            variableValue = ObjectConverterHelper.ProcessVariableValue(engine, variableValue);
 1079            variablesContainer[variableName] = variableValue;
 80        }
 81
 28582        engine.SetValue("variables", variablesContainer);
 28583    }
 84
 85    private IEnumerable<string> GetUsedVariableNames(ExpressionExecutionContext context, string expression)
 86    {
 28587        var variableNames = context.GetVariableNamesInScope().FilterInvalidVariableNames();
 88
 28589        var variableNamesInScript = ExtractVariableNamesRegex().Matches(expression)
 1190            .Select(m => m.Groups[1].Value)
 28591            .ToList();
 92
 44393        return variableNames.Where(x => variableNamesInScript.Contains(x));
 94    }
 95
 96    private IEnumerable<string> GetInputNames(ExpressionExecutionContext context)
 97    {
 1698        var activityExecutionContext = context.TryGetActivityExecutionContext(out var aec) ? aec : null;
 99
 45100        while (activityExecutionContext != null)
 101        {
 29102            if (activityExecutionContext.Activity is Workflow workflow)
 103            {
 14104                var inputDefinitions = workflow.Inputs;
 105
 28106                foreach (var inputDefinition in inputDefinitions)
 0107                    yield return inputDefinition.Name;
 108            }
 109
 58110            foreach (var syntheticProperty in activityExecutionContext.Activity.SyntheticProperties)
 111            {
 0112                yield return syntheticProperty.Key;
 113            }
 114
 29115            activityExecutionContext = activityExecutionContext.ParentActivityExecutionContext;
 116        }
 16117    }
 118
 119    [GeneratedRegex(@"variables\.(\w+)(?:\.\w+)*")]
 120    private static partial Regex ExtractVariableNamesRegex();
 121}

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Expressions.JavaScript/obj/Release/net10.0/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs

File '/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Expressions.JavaScript/obj/Release/net10.0/System.Text.RegularExpressions.Generator/System.Text.RegularExpressions.Generator.RegexGenerator/RegexGenerator.g.cs' does not exist (any more).