-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic setters are now shared between types #70
Conversation
We could provide a callback, so it shouldn't be a problem.
Setter sharing is only required in Cecil mode, with SRE we are free to call I haven't read the code yet, but how do you handle "XAML references a private nested type" scenario? |
I thought about it, but it doesn't solve the lifetime problem as one might want the setters to be shared between all compiler calls, some calls only, not at all... The callback can of course provide the type, but then the compiler has no idea when it should build it. Nothing unsolvable (it was my first approach after all), I felt it was cleaner and easier for the caller to control the setters type. Happy to discuss and change if needed :) Note that I'm talking about XamlX as a general purpose compiler here since it's very generic (great work by the way, when I started looking at the code, I really didn't expect XamlX to be so nicely separated!), not for Avalonia specific cases, which are well defined and scoped.
I don't, sorry if I wasn't clear, the "nested private type" I was talking referred to a setter being generated first in a private class (closure), then being incorrectly reused from another type. This doesn't happen here since the caller is responsible for providing an accessible type that will hold the setters. In general since you mention referencing private types from XAML files, I don't think XamlX does any visibility check, whether that's using private types or private members?
compiles, but fails at runtime with |
Consider the following scenario: class MyControl : UserControl
{
private object Foo {...} // avalonia property
} <UserControl x:Class="MyControl" Foo="{DynamicResource Bar}" /> For the user control itself the |
|
Good one! Indeed that would break currently.
I know about <Grid>
<Border Background="{StaticResource Foo}" />
<Border Background="{StaticResource Foo}" />
</Grid> One compilation, twice the same setter. Anyways, point well understood :) Since I'm reworking this I'll add some options/callbacks so the emitter and caller can work together to determine whether a cache is needed and which type should be used. |
a30c502
to
5fdd456
Compare
Pass 3! A new interface The default implementation of this interface, In Avalonia, the Cecil compiler can define a shared setters type before compiling and pass it to the |
I'm terribly sorry for my inactivity, it was caused by covid and then recent events. Hopefully I would either merge this or provide feedback in a week or two. |
No worries, take your time :) Thank you for letting me know. |
84d80b3
to
6ab5930
Compare
I just rebased this PR onto master and resolved conflicts, if you happen to have some time to review :) |
6ab5930
to
68bbb42
Compare
68bbb42
to
a2768ae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM in general, would be nice to have a test or two for effectively private methods not being placed to the shared cache.
I've added the requested tests. This involved a bit of refactoring to the Note that the private property case is only enabled on Cecil, since we need to extend the root type to access the property, which can't be done with SRE. I've also added a new commit to handle protected properties in the same way as the private ones. |
@kekekeks can it be merged? |
Following up on #65, this PR makes dynamic setter methods shared between all types.
My first try at implementing this kept creating the setters type in
PropertyAssignmentEmitter
, but this posed several problems:CreateType
(effectively building the type for SRE) on the setters type, since it needs to be shared between several compilation calls.Instead, this implementation requires the caller to define the setters type itself and pass it to the compiler. The caller can define the type as it sees fit and controls its sharing between calls and its final creation. This is very similar to what Avalonia already does for its extra generated XAML types (
XamlIlHelpers
,XamlILTrampolines
, etc.).The only downside is that this type can be seen as an implementation detail: another non-IL backend emitter might not need it. I think the pros outweigh the cons, and that a potential other implementation might still want to use this type to define its setters.
After this PR,
Avalonia.Themes.Fluent
without fonts goes from 815 KB (337 setters) to 774 KB (19 setters).