Skip to content

Commit

Permalink
Convert IAvaloniaXamlIlParentStackProvider to eager one if needed (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
MrJul committed Jun 18, 2024
1 parent 87ea0d2 commit 4aec7ac
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXaml
ContextTypeBuilderCallback = definition =>
{
EmitNameScopeField(rv, typeSystem, definition);
EmitEagerParentStackProvider(rv, typeSystem, definition);
EmitEagerParentStackProvider(rv, typeSystem, definition, runtimeHelpers);
}
};
return (rv, emit);
Expand Down Expand Up @@ -104,7 +104,8 @@ public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXaml
private static void EmitEagerParentStackProvider(
XamlLanguageTypeMappings mappings,
IXamlTypeSystem typeSystem,
IXamlILContextDefinition<IXamlILEmitter> definition)
IXamlILContextDefinition<IXamlILEmitter> definition,
IXamlType runtimeHelpers)
{
var interfaceType = typeSystem.FindType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlEagerParentStackProvider");

Expand All @@ -122,14 +123,22 @@ public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXaml
typeSystem.FindType("System.Object"),
typeSystem.FindType("System.Type")));

var asEagerParentStackProviderMethod = runtimeHelpers.GetMethod(new FindMethodMethodSignature(
"AsEagerParentStackProvider",
interfaceType,
mappings.ParentStackProvider)
{
IsStatic = true
});

// IAvaloniaXamlIlEagerParentStackProvider? ParentProvider
// => (IAvaloniaXamlIlEagerParentStackProvider)_serviceProvider.GetService(typeof(IAvaloniaXamlIlParentStackProvider))
// => XamlIlRuntimeHelpers.AsEagerParentStackProvider(_serviceProvider.GetService(typeof(IAvaloniaXamlIlParentStackProvider)));
var parentProviderGetter = ImplementInterfacePropertyGetter("ParentProvider");
parentProviderGetter.Generator
.LdThisFld(definition.ParentServiceProviderField)
.Ldtype(mappings.ParentStackProvider)
.EmitCall(serviceProviderGetServiceMethod)
.Castclass(interfaceType)
.EmitCall(asEagerParentStackProviderMethod)
.Ret();

IXamlMethodBuilder<IXamlILEmitter> ImplementInterfacePropertyGetter(string propertyName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlControlTemplateProvider.cs" />
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlParentStackProvider.cs" />
<Compile Include="XamlIl\Runtime\IAvaloniaXamlIlXmlNamespaceInfoProviderV1.cs" />
<Compile Include="XamlIl\Runtime\XamlIlParentStackProviderWrapper.cs" />
<Compile Include="XamlIl\Runtime\XamlIlRuntimeHelpers.cs" />
<Compile Include="XamlLoadException.cs" />
<Compile Include="XamlTypes.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.Linq;

namespace Avalonia.Markup.Xaml.XamlIl.Runtime;

/// <summary>
/// Wraps a <see cref="IAvaloniaXamlIlParentStackProvider"/> into a <see cref="IAvaloniaXamlIlEagerParentStackProvider"/>,
/// for backwards compatibility.
/// </summary>
internal sealed class XamlIlParentStackProviderWrapper : IAvaloniaXamlIlEagerParentStackProvider
{
private readonly IAvaloniaXamlIlParentStackProvider _provider;

private IReadOnlyList<object>? _directParentsStack;

public XamlIlParentStackProviderWrapper(IAvaloniaXamlIlParentStackProvider provider)
=> _provider = provider;

public IEnumerable<object> Parents
=> _provider.Parents;

public IReadOnlyList<object> DirectParentsStack
=> _directParentsStack ??= _provider.Parents.Reverse().ToArray();

public IAvaloniaXamlIlEagerParentStackProvider? ParentProvider
=> null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ private static IResourceNode[] AsResourceNodesStack(IAvaloniaXamlIlParentStackPr
return resourceNodes;
}

/// <summary>
/// Converts a <see cref="IAvaloniaXamlIlParentStackProvider"/> into a
/// <see cref="IAvaloniaXamlIlEagerParentStackProvider"/>.
/// </summary>
public static IAvaloniaXamlIlEagerParentStackProvider AsEagerParentStackProvider(
this IAvaloniaXamlIlParentStackProvider provider)
=> provider as IAvaloniaXamlIlEagerParentStackProvider ?? new XamlIlParentStackProviderWrapper(provider);

// Parent resource nodes are often the same (e.g. most values in a ResourceDictionary), cache the last ones.
private sealed class LastParentStack
{
Expand Down

0 comments on commit 4aec7ac

Please sign in to comment.