Skip to content

Commit

Permalink
Merge branch 'main' into darc-main-1709b9ed-50a0-4e28-b9b8-0e3759aee720
Browse files Browse the repository at this point in the history
  • Loading branch information
TanayParikh committed Jul 6, 2021
2 parents 6fbf14b + 051aa95 commit 8f99347
Show file tree
Hide file tree
Showing 144 changed files with 4,110 additions and 913 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ dotnet_diagnostic.CA1846.severity = suggestion
dotnet_diagnostic.CA2008.severity = suggestion
# CA2012: Use ValueTask correctly
dotnet_diagnostic.CA2012.severity = suggestion
# IDE0044: Make field readonly
dotnet_diagnostic.IDE0044.severity = suggestion


# CA2016: Forward the 'CancellationToken' parameter to methods that take one
dotnet_diagnostic.CA2016.severity = suggestion
4 changes: 2 additions & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@
<PlaywrightSharpVersion>0.192.0</PlaywrightSharpVersion>
<PollyExtensionsHttpVersion>3.0.0</PollyExtensionsHttpVersion>
<PollyVersion>7.2.2</PollyVersion>
<SeleniumSupportVersion>4.0.0-beta2</SeleniumSupportVersion>
<SeleniumSupportVersion>4.0.0-beta4</SeleniumSupportVersion>
<SeleniumWebDriverChromeDriverVersion>91.0.4472.1900</SeleniumWebDriverChromeDriverVersion>
<SeleniumWebDriverVersion>4.0.0-beta2</SeleniumWebDriverVersion>
<SeleniumWebDriverVersion>4.0.0-beta4</SeleniumWebDriverVersion>
<SerilogExtensionsLoggingVersion>1.4.0</SerilogExtensionsLoggingVersion>
<SerilogSinksFileVersion>4.0.0</SerilogSinksFileVersion>
<StackExchangeRedisVersion>2.2.4</StackExchangeRedisVersion>
Expand Down
7 changes: 6 additions & 1 deletion src/Components/Authorization/test/AuthorizeRouteViewTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Components.Authorization
{
public class AuthorizeRouteViewTest
{
private readonly static IReadOnlyDictionary<string, object> EmptyParametersDictionary = new Dictionary<string, object>();
private static readonly IReadOnlyDictionary<string, object> EmptyParametersDictionary = new Dictionary<string, object>();
private readonly TestAuthenticationStateProvider _authenticationStateProvider;
private readonly TestRenderer _renderer;
private readonly RouteView _authorizeRouteViewComponent;
Expand All @@ -35,6 +35,7 @@ public AuthorizeRouteViewTest()
serviceCollection.AddSingleton<AuthenticationStateProvider>(_authenticationStateProvider);
serviceCollection.AddSingleton<IAuthorizationPolicyProvider, TestAuthorizationPolicyProvider>();
serviceCollection.AddSingleton<IAuthorizationService>(_testAuthorizationService);
serviceCollection.AddSingleton<NavigationManager, TestNavigationManager>();

_renderer = new TestRenderer(serviceCollection.BuildServiceProvider());
_authorizeRouteViewComponent = new AuthorizeRouteView();
Expand Down Expand Up @@ -424,5 +425,9 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
builder.CloseComponent();
}
}

class TestNavigationManager : NavigationManager
{
}
}
}
5 changes: 5 additions & 0 deletions src/Components/Components.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
"src\\Http\\Routing.Abstractions\\src\\Microsoft.AspNetCore.Routing.Abstractions.csproj",
"src\\Http\\Routing\\src\\Microsoft.AspNetCore.Routing.csproj",
"src\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj",
"src\\Identity\\ApiAuthorization.IdentityServer\\src\\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj",
"src\\Identity\\EntityFrameworkCore\\src\\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj",
"src\\Identity\\UI\\src\\Microsoft.AspNetCore.Identity.UI.csproj",
"src\\JSInterop\\Microsoft.JSInterop\\src\\Microsoft.JSInterop.csproj",
"src\\Middleware\\CORS\\src\\Microsoft.AspNetCore.Cors.csproj",
"src\\Middleware\\Diagnostics.Abstractions\\src\\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj",
Expand Down Expand Up @@ -96,8 +99,10 @@
"src\\Mvc\\Mvc\\src\\Microsoft.AspNetCore.Mvc.csproj",
"src\\Razor\\Razor.Runtime\\src\\Microsoft.AspNetCore.Razor.Runtime.csproj",
"src\\Razor\\Razor\\src\\Microsoft.AspNetCore.Razor.csproj",
"src\\Security\\Authentication\\Cookies\\src\\Microsoft.AspNetCore.Authentication.Cookies.csproj",
"src\\Security\\Authorization\\Core\\src\\Microsoft.AspNetCore.Authorization.csproj",
"src\\Security\\Authorization\\Policy\\src\\Microsoft.AspNetCore.Authorization.Policy.csproj",
"src\\Security\\CookiePolicy\\src\\Microsoft.AspNetCore.CookiePolicy.csproj",
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
"src\\Servers\\IIS\\IISIntegration\\src\\Microsoft.AspNetCore.Server.IISIntegration.csproj",
"src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj",
Expand Down
99 changes: 94 additions & 5 deletions src/Components/Components/src/BindConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Text.Json;

namespace Microsoft.AspNetCore.Components
{
Expand Down Expand Up @@ -523,7 +525,7 @@ public static bool TryConvertToString(object? obj, CultureInfo? culture, out str
return ConvertToStringCore(obj, culture, out value);
}

internal readonly static BindParser<string?> ConvertToString = ConvertToStringCore;
internal static readonly BindParser<string?> ConvertToString = ConvertToStringCore;

private static bool ConvertToStringCore(object? obj, CultureInfo? culture, out string? value)
{
Expand Down Expand Up @@ -556,8 +558,8 @@ public static bool TryConvertToNullableBool(object? obj, CultureInfo? culture, o
return ConvertToNullableBoolCore(obj, culture, out value);
}

internal readonly static BindParser<bool> ConvertToBool = ConvertToBoolCore;
internal readonly static BindParser<bool?> ConvertToNullableBool = ConvertToNullableBoolCore;
internal static readonly BindParser<bool> ConvertToBool = ConvertToBoolCore;
internal static readonly BindParser<bool?> ConvertToNullableBool = ConvertToNullableBoolCore;

private static bool ConvertToBoolCore(object? obj, CultureInfo? culture, out bool value)
{
Expand Down Expand Up @@ -1278,8 +1280,18 @@ private static bool ConvertToNullableEnum<T>(object? obj, CultureInfo? culture,

private static class FormatterDelegateCache
{
private readonly static ConcurrentDictionary<Type, Delegate> _cache = new ConcurrentDictionary<Type, Delegate>();
private static readonly ConcurrentDictionary<Type, Delegate> _cache = new ConcurrentDictionary<Type, Delegate>();

private static MethodInfo? _makeArrayFormatter;

[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2060:MakeGenericMethod",
Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2075:MakeGenericMethod",
Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
public static BindFormatter<T> Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
if (!_cache.TryGetValue(typeof(T), out var formatter))
Expand Down Expand Up @@ -1366,6 +1378,12 @@ private static class FormatterDelegateCache
{
formatter = (BindFormatter<T>)FormatEnumValueCore<T>;
}
else if (typeof(T).IsArray)
{
var method = _makeArrayFormatter ??= typeof(FormatterDelegateCache).GetMethod(nameof(MakeArrayFormatter), BindingFlags.NonPublic | BindingFlags.Static)!;
var elementType = typeof(T).GetElementType()!;
formatter = (Delegate)method.MakeGenericMethod(elementType).Invoke(null, null)!;
}
else
{
formatter = MakeTypeConverterFormatter<T>();
Expand All @@ -1377,6 +1395,36 @@ private static class FormatterDelegateCache
return (BindFormatter<T>)formatter;
}

private static BindFormatter<T[]> MakeArrayFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var elementFormatter = Get<T>();

return FormatArrayValue;

string? FormatArrayValue(T[] value, CultureInfo? culture)
{
if (value.Length == 0)
{
return "[]";
}

var builder = new StringBuilder("[\"");
builder.Append(JsonEncodedText.Encode(elementFormatter(value[0], culture)?.ToString() ?? string.Empty));
builder.Append('\"');

for (var i = 1; i < value.Length; i++)
{
builder.Append(", \"");
builder.Append(JsonEncodedText.Encode(elementFormatter(value[i], culture)?.ToString() ?? string.Empty));
builder.Append('\"');
}

builder.Append(']');

return builder.ToString();
}
}

private static BindFormatter<T> MakeTypeConverterFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
Expand All @@ -1400,15 +1448,20 @@ string FormatWithTypeConverter(T value, CultureInfo? culture)

internal static class ParserDelegateCache
{
private readonly static ConcurrentDictionary<Type, Delegate> _cache = new ConcurrentDictionary<Type, Delegate>();
private static readonly ConcurrentDictionary<Type, Delegate> _cache = new ConcurrentDictionary<Type, Delegate>();

private static MethodInfo? _convertToEnum;
private static MethodInfo? _convertToNullableEnum;
private static MethodInfo? _makeArrayTypeConverter;

[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2060:MakeGenericMethod",
Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
[UnconditionalSuppressMessage(
"ReflectionAnalysis",
"IL2075:MakeGenericMethod",
Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727")]
public static BindParser<T> Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
if (!_cache.TryGetValue(typeof(T), out var parser))
Expand Down Expand Up @@ -1503,6 +1556,12 @@ internal static class ParserDelegateCache
var method = _convertToNullableEnum ??= typeof(BindConverter).GetMethod(nameof(ConvertToNullableEnum), BindingFlags.NonPublic | BindingFlags.Static)!;
parser = method.MakeGenericMethod(innerType).CreateDelegate(typeof(BindParser<T>), target: null);
}
else if (typeof(T).IsArray)
{
var method = _makeArrayTypeConverter ??= typeof(ParserDelegateCache).GetMethod(nameof(MakeArrayTypeConverter), BindingFlags.NonPublic | BindingFlags.Static)!;
var elementType = typeof(T).GetElementType()!;
parser = (Delegate)method.MakeGenericMethod(elementType).Invoke(null, null)!;
}
else
{
parser = MakeTypeConverterConverter<T>();
Expand All @@ -1514,6 +1573,36 @@ internal static class ParserDelegateCache
return (BindParser<T>)parser;
}

private static BindParser<T[]?> MakeArrayTypeConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var elementParser = Get<T>();

return ConvertToArray;

bool ConvertToArray(object? obj, CultureInfo? culture, out T[]? value)
{
if (obj is not Array initialArray)
{
value = default;
return false;
}

var convertedArray = new T[initialArray.Length];

for (var i = 0; i < initialArray.Length; i++)
{
if (!elementParser(initialArray.GetValue(i), culture, out convertedArray[i]!))
{
value = default;
return false;
}
}

value = convertedArray;
return true;
}
}

private static BindParser<T> MakeTypeConverterConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<Nullable>enable</Nullable>
<Trimmable>true</Trimmable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" />
<Compile Include="$(ComponentsSharedSourceRoot)src\JsonSerializerOptionsProvider.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)src\HotReloadFeature.cs" LinkBase="HotReload" />
<Compile Include="$(SharedSourceRoot)LinkerFlags.cs" LinkBase="Shared" />
<Compile Include="$(SharedSourceRoot)QueryStringEnumerable.cs" LinkBase="Shared" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/Components/Components/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ Microsoft.AspNetCore.Components.CascadingTypeParameterAttribute
Microsoft.AspNetCore.Components.CascadingTypeParameterAttribute.CascadingTypeParameterAttribute(string! name) -> void
Microsoft.AspNetCore.Components.CascadingTypeParameterAttribute.Name.get -> string!
Microsoft.AspNetCore.Components.RenderTree.Renderer.GetEventArgsType(ulong eventHandlerId) -> System.Type!
Microsoft.AspNetCore.Components.SupplyParameterFromQueryAttribute
Microsoft.AspNetCore.Components.SupplyParameterFromQueryAttribute.Name.get -> string?
Microsoft.AspNetCore.Components.SupplyParameterFromQueryAttribute.Name.set -> void
Microsoft.AspNetCore.Components.SupplyParameterFromQueryAttribute.SupplyParameterFromQueryAttribute() -> void
abstract Microsoft.AspNetCore.Components.ErrorBoundaryBase.OnErrorAsync(System.Exception! exception) -> System.Threading.Tasks.Task!
override Microsoft.AspNetCore.Components.LayoutComponentBase.SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) -> System.Threading.Tasks.Task!
static Microsoft.AspNetCore.Components.ParameterView.FromDictionary(System.Collections.Generic.IDictionary<string!, object?>! parameters) -> Microsoft.AspNetCore.Components.ParameterView
Expand Down
10 changes: 5 additions & 5 deletions src/Components/Components/src/Reflection/ComponentProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace Microsoft.AspNetCore.Components.Reflection
{
internal static class ComponentProperties
{
private const BindingFlags _bindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase;
internal const BindingFlags BindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase;

// Right now it's not possible for a component to define a Parameter and a Cascading Parameter with
// the same name. We don't give you a way to express this in code (would create duplicate properties),
// and we don't have the ability to represent it in our data structures.
private readonly static ConcurrentDictionary<Type, WritersForType> _cachedWritersByType
private static readonly ConcurrentDictionary<Type, WritersForType> _cachedWritersByType
= new ConcurrentDictionary<Type, WritersForType>();

public static void ClearCache() => _cachedWritersByType.Clear();
Expand Down Expand Up @@ -162,15 +162,15 @@ static void SetProperty(object target, PropertySetter writer, string parameterNa
}

internal static IEnumerable<PropertyInfo> GetCandidateBindableProperties([DynamicallyAccessedMembers(Component)] Type targetType)
=> MemberAssignment.GetPropertiesIncludingInherited(targetType, _bindablePropertyFlags);
=> MemberAssignment.GetPropertiesIncludingInherited(targetType, BindablePropertyFlags);

[DoesNotReturn]
private static void ThrowForUnknownIncomingParameterName([DynamicallyAccessedMembers(Component)] Type targetType,
string parameterName)
{
// We know we're going to throw by this stage, so it doesn't matter that the following
// reflection code will be slow. We're just trying to help developers see what they did wrong.
var propertyInfo = targetType.GetProperty(parameterName, _bindablePropertyFlags);
var propertyInfo = targetType.GetProperty(parameterName, BindablePropertyFlags);
if (propertyInfo != null)
{
if (!propertyInfo.IsDefined(typeof(ParameterAttribute)) && !propertyInfo.IsDefined(typeof(CascadingParameterAttribute)))
Expand Down Expand Up @@ -223,7 +223,7 @@ private static void ThrowForCaptureUnmatchedValuesConflict(Type targetType, stri
private static void ThrowForMultipleCaptureUnmatchedValuesParameters([DynamicallyAccessedMembers(Component)] Type targetType)
{
var propertyNames = new List<string>();
foreach (var property in targetType.GetProperties(_bindablePropertyFlags))
foreach (var property in targetType.GetProperties(BindablePropertyFlags))
{
if (property.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true)
{
Expand Down
1 change: 1 addition & 0 deletions src/Components/Components/src/RenderTree/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ private async void RenderRootComponentsOnHotReload()
// Before re-rendering the root component, also clear any well-known caches in the framework
_componentFactory.ClearCache();
ComponentProperties.ClearCache();
Routing.QueryParameterValueSupplier.ClearCache();

await Dispatcher.InvokeAsync(() =>
{
Expand Down
16 changes: 16 additions & 0 deletions src/Components/Components/src/RouteView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
#nullable disable warnings

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;

namespace Microsoft.AspNetCore.Components
{
Expand All @@ -20,6 +22,9 @@ public class RouteView : IComponent
private readonly RenderFragment _renderPageWithParametersDelegate;
private RenderHandle _renderHandle;

[Inject]
private NavigationManager NavigationManager { get; set; }

/// <summary>
/// Gets or sets the route data. This determines the page that will be
/// displayed and the parameter values that will be supplied to the page.
Expand Down Expand Up @@ -90,6 +95,17 @@ private void RenderPageWithParameters(RenderTreeBuilder builder)
builder.AddAttribute(1, kvp.Key, kvp.Value);
}

var queryParameterSupplier = QueryParameterValueSupplier.ForType(RouteData.PageType);
if (queryParameterSupplier is not null)
{
// Since this component does accept some parameters from query, we must supply values for all of them,
// even if the querystring in the URI is empty. So don't skip the following logic.
var url = NavigationManager.Uri;
var queryStartPos = url.IndexOf('?');
var query = queryStartPos < 0 ? default : url.AsMemory(queryStartPos);
queryParameterSupplier.RenderParametersFromQueryString(builder, query);
}

builder.CloseComponent();
}
}
Expand Down
Loading

0 comments on commit 8f99347

Please sign in to comment.