Handlebars-Net / Handlebars.Net

A real .NET Handlebars engine
MIT License
1.28k stars 219 forks source link

Trying to compile a template in Xamarin.iOS results in a System.NotImplementedException #458

Open mrbelk opened 3 years ago

mrbelk commented 3 years ago

Describe the bug

When I try to compile a template in Xamarin.iOS, a System.NotImplementedException is thrown with a message of "byref delegate." I am using HandleBars.Net v2.0.8.

I should note that an earlier version of our app, using HandleBars.Net 1.11.5 works fine.

Expected behavior:

I would expect that the template would compile correctly as it used to before.

Test to reproduce

[Fact]
public void Descriptive_Test_Name_Here()
{
    var handlebars = Handlebars.Create();
    var render = handlebars.Compile("{{input}}");
    object data = new { input = 42 };

    var actual = render(data);
    Assert.Equal(42, actual);
}

Other related info

The only thing I can find with a google search is here: https://github.com/dotnet/runtime/issues/31075, but this issue was closed because it's in the mono runtime.

I suppose this could be related to the Xamarin.iOS version or the Mono runtime version that the previous version was compiled against.

After submitting the issue

Please consider contributing to the project by submitting a PR with a fix to the issue. This would help to solve your problem in a shorter time as well as help other users of the project.

In case you do not know where to start - feel free to ask for help in the issue thread.

Building an active community is essential for any project survival as time of maintainers is limited.

mrbelk commented 3 years ago

this is the stack trace of the exception that's thrown:

MOBILE: Error MSG: Error printing test page | Exception: HandlebarsDotNet.HandlebarsCompilerException: An unhandled exception occurred while trying to compile the template ---> System.NotImplementedException: byref delegate
  at System.Linq.Expressions.Interpreter.LightLambda.CreateCustomDelegate (System.Type delegateType) [0x001cf] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs:422 
  at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate (System.Type delegateType) [0x00012] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs:446 
  at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate (System.Runtime.CompilerServices.IStrongBox[] closure) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightDelegateCreator.cs:33 
  at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightDelegateCreator.cs:28 
  at System.Linq.Expressions.Expression`1[TDelegate].Compile (System.Boolean preferInterpretation) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs:211 
  at System.Linq.Expressions.Expression`1[TDelegate].Compile () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs:192 
  at HandlebarsDotNet.Features.DefaultCompilerFeature+DefaultExpressionCompiler.Compile[T] (System.Linq.Expressions.Expression`1[TDelegate] expression) [0x0002a] in <538675ac0d604f22b198e7448cff5118>:0 
  at HandlebarsDotNet.Compiler.FunctionBuilder.Compile (System.Collections.Generic.IEnumerable`1[T] expressions, HandlebarsDotNet.Compiler.CompilationContext compilationContext) [0x0003c] in <538675ac0d604f22b198e7448cff5118>:0 
   --- End of inner exception stack trace ---
  at HandlebarsDotNet.Compiler.FunctionBuilder.Compile (System.Collections.Generic.IEnumerable`1[T] expressions, HandlebarsDotNet.Compiler.CompilationContext compilationContext) [0x00053] in <538675ac0d604f22b198e7448cff5118>:0 
  at HandlebarsDotNet.Compiler.HandlebarsCompiler.Compile (HandlebarsDotNet.ExtendedStringReader source, HandlebarsDotNet.Compiler.CompilationContext compilationContext) [0x0003d] in <538675ac0d604f22b198e7448cff5118>:0 
  at HandlebarsDotNet.HandlebarsEnvironment.Compile (System.IO.TextReader template) [0x00090] in <538675ac0d604f22b198e7448cff5118>:0 
  at HandlebarsDotNet.HandlebarsEnvironment.Compile (System.String template) [0x00014] in <538675ac0d604f22b198e7448cff5118>:0 
  at goRoamPOD.Services.PrintingHelpers.PrintTestPage () [0x00183] in /Users/matthew/Projects/goRoamPOD/goRoamPOD/Services/PrintingHelpers.cs:545 
mrbelk commented 3 years ago

I'm trying to figure out what might have changed between last November, which is the last version of our iOS app this particular customer has in the field and now, with respect to any of the things that are in the stack trace. So far, I cannot find any difference and I am looking all the way to the mono runtime makefiles to figure out if something changed.

I started here: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightLambda.cs

and searched for all of the conditional compilation directives and the other runtime classes up the call stack. I cannot find anything different in the commit histories of the files that are referenced or in anything else except the version of the handlebars package.

mrbelk commented 3 years ago

I just downgraded from 2.0.8 to 1.11.5 and everything works as expected on iOS again

oformaniuk commented 3 years ago

Hello @mrbelk The problem with versions 2 and above in iOS setting might be related to the fact that some features are missing from the Expression Tree compiler/interpreter. Starting from version 2 constructed delegates may contain by ref parameters. The only option to overcome the problem in iOS is to traverse the tree and rewrite it to avoid ref parameters in delegates, however I'm not sure it's easily achievable.

zijianhuang commented 1 year ago

I had encountered almost identical problem. The Xamarin app works well on Android. However, on iOS, the debug build work, but the release build pop up the same exception. I am using the latest VS and Xamarin.

zijianhuang commented 1 year ago

I had downloaded the lib source code and made a debug build. Then use the debug build of the lib in the release build of my app, and the same error occurs. So only the debug build of my app could work on iOS. But surely I cannot submit a debug build to app store. :(

zijianhuang commented 11 months ago

Further research revealed that this is not a handlebars.net specific problem, as I had googled "xamarin iphone exception byref delegate linq expressions lightlambda". This https://github.com/MessagePack-CSharp/MessagePack-CSharp/issues/1344 had provided a solution: Properties/iOS Build/Enable the Mono Interpreter checked

Though the size of the deployable is around 3MB larger.