fix: avoid byref delegate parameters incompatible with Mono/Xamarin (issue #458)#627
Merged
Conversation
…o/Xamarin (#458) Mono's AOT/JIT compiler does not support delegates with byref parameters (ref/in). TemplateDelegate and DecoratorDelegate used `in EncodedTextWriter` which caused System.NotImplementedException: byref delegate at runtime on Xamarin.iOS and other Mono-based platforms. - Change `TemplateDelegate` from `delegate void TemplateDelegate(in EncodedTextWriter, ...)` to pass the struct by value - Change `DecoratorDelegate` similarly - Update `CompilationContext.EncodedWriter` to use `typeof(EncodedTextWriter)` instead of `MakeByRefType()` so Expression.Lambda<TemplateDelegate> no longer generates a byref parameter - Update all lambda literals in HandlebarsCompiler, FunctionBuilder, DecoratorDefinition and tests to drop the `in` modifier EncodedTextWriter is a small readonly struct (3 reference-type fields) so the by-value copy is cheap and there is no observable behaviour change on standard .NET runtimes. Adds two regression tests: Issue458_BasicTemplateCompilationAndRender and Issue458_BlockHelperTemplateCompilationAndRender. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #458
Root Cause
Mono's AOT/JIT compiler (used by Xamarin.iOS and other Mono-based platforms) does not support delegates whose parameter list includes byref types (
ref/in/out). Theinkeyword on a value-type parameter compiles to a managed byref, so any delegate type that usesinis a "byref delegate."In v2, two internal delegate types gained
in EncodedTextWriterparameters:TemplateDelegate—delegate void TemplateDelegate(in EncodedTextWriter writer, BindingContext context)DecoratorDelegate—delegate TemplateDelegate DecoratorDelegate(in EncodedTextWriter writer, ...)CompilationContextalso created the writer parameter astypeof(EncodedTextWriter).MakeByRefType(), so everyExpression.Lambda<TemplateDelegate>call produced a byref delegate, throwingSystem.NotImplementedException: byref delegateat template-compile time on Mono.Fix
Remove the
inmodifier from the two delegate type definitions soEncodedTextWriteris passed by value instead of by readonly reference:TemplateDelegate→delegate void TemplateDelegate(EncodedTextWriter writer, BindingContext context)DecoratorDelegate→delegate TemplateDelegate DecoratorDelegate(EncodedTextWriter writer, ...)CompilationContext.EncodedWriter→Expression.Parameter(typeof(EncodedTextWriter), "writer")EncodedTextWriteris a smallreadonly structcontaining three managed-reference fields (~24 bytes on 64-bit). Passing it by value incurs a negligible copy and produces no observable behaviour difference on standard .NET runtimes.The same
in-removal is applied to all lambda literals that match these delegate types, and to the two affected test helpers.Tests
Two regression tests added to
IssueTests.cs:Issue458_BasicTemplateCompilationAndRender— compile and render{{input}}Issue458_BlockHelperTemplateCompilationAndRender— compile and render{{#if show}}visible{{/if}}All 1748 existing tests continue to pass.
🤖 Generated with Claude Code