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<string,object> 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.
This commit is contained in:
Craig Fowler 2021-03-28 16:43:01 +01:00 committed by Sipke Schoorstra
parent a7f8926698
commit 7ed875e53c
2 changed files with 24 additions and 1 deletions

View file

@ -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<string,object>) : returnType;
if (returnValue is IEnumerable)
{
var json = JsonConvert.SerializeObject(returnValue);
return JsonConvert.DeserializeObject(json, returnType);

View file

@ -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<ScriptOptions> options,
JavaScriptService sut,
[StubActivityExecutionContext] ActivityExecutionContext context1,
[StubActivityExecutionContext] ActivityExecutionContext context2)
{
object returnedValue = null;
Mock.Get(mediator)
.Setup(x => x.Publish(It.Is<EvaluatingJavaScriptExpression>(e => e.ActivityExecutionContext == context2), It.IsAny<CancellationToken>()))
.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);
}
}
}