From 7ed875e53c0ab7cf2c82c8d136594630453ab754 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Sun, 28 Mar 2021 16:43:01 +0100 Subject: [PATCH] Resolve #761 - Add special-case for ExpandoObject It appears that this can be fixed by intercepting occasions when Jint returns an ExpandoObject but the desired return type is simply object. In this scenario we must return a Dictionary instead of a simple object, or else Jint freaks out should we try to stringify it later. I also added a second test to prove that making this change hasn't broken the way we expect Jint to work for us. --- .../Services/JavaScriptService.cs | 5 ++++- .../Services/JavaScriptServiceTests.cs | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/scripting/Elsa.Scripting.JavaScript/Services/JavaScriptService.cs b/src/scripting/Elsa.Scripting.JavaScript/Services/JavaScriptService.cs index f2a74cbc2..1c5fd0d48 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Services/JavaScriptService.cs +++ b/src/scripting/Elsa.Scripting.JavaScript/Services/JavaScriptService.cs @@ -1,6 +1,8 @@ using System; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; +using System.Dynamic; using System.Threading; using System.Threading.Tasks; using Elsa.Scripting.JavaScript.Converters; @@ -48,7 +50,8 @@ namespace Elsa.Scripting.JavaScript.Services if (converter.CanConvertTo(returnType)) converter.ConvertTo(returnValue, returnType); - if (returnValue is IEnumerable && !(returnValue is System.Dynamic.ExpandoObject)) + returnType = (returnValue is ExpandoObject && returnType == typeof(object))? typeof(Dictionary) : returnType; + if (returnValue is IEnumerable) { var json = JsonConvert.SerializeObject(returnValue); return JsonConvert.DeserializeObject(json, returnType); diff --git a/test/unit/Elsa.UnitTests/Scripting/JavaScript/Services/JavaScriptServiceTests.cs b/test/unit/Elsa.UnitTests/Scripting/JavaScript/Services/JavaScriptServiceTests.cs index e45df4193..6224f48fb 100644 --- a/test/unit/Elsa.UnitTests/Scripting/JavaScript/Services/JavaScriptServiceTests.cs +++ b/test/unit/Elsa.UnitTests/Scripting/JavaScript/Services/JavaScriptServiceTests.cs @@ -33,5 +33,25 @@ namespace Elsa.Scripting.JavaScript.Services Assert.Equal(@"{""foo"":""bar""}", result); } + + [Theory(DisplayName = "The EvaluateAsync method should be able to access a property of an object which was created via JSON.parse"), AutoMoqData] + public async Task EvaluateAsyncShouldBeAbleToAccessAPropertyWhichWasParsed([Frozen] IMediator mediator, + [Frozen] IOptions options, + JavaScriptService sut, + [StubActivityExecutionContext] ActivityExecutionContext context1, + [StubActivityExecutionContext] ActivityExecutionContext context2) + { + object returnedValue = null; + Mock.Get(mediator) + .Setup(x => x.Publish(It.Is(e => e.ActivityExecutionContext == context2), It.IsAny())) + .Callback((EvaluatingJavaScriptExpression expression, CancellationToken t) => { + expression.Engine.SetValue("MyVariable", returnedValue); + }); + + returnedValue = await sut.EvaluateAsync(@"JSON.parse(""{\""foo\"":\""bar\""}"")", typeof(object), context1); + var result = await sut.EvaluateAsync("MyVariable.foo", typeof(object), context2); + + Assert.Equal("bar", result); + } } } \ No newline at end of file