Skip to content

Commit b3d743d

Browse files
committed
Merge branch 'main' into marc/ocbin
# Conflicts: # src/submodules/googletest
2 parents f9dbbf2 + 6a93078 commit b3d743d

File tree

97 files changed

+5151
-1143
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+5151
-1143
lines changed

eng/Version.Details.xml

+156-156
Large diffs are not rendered by default.

eng/Versions.props

+83-82
Large diffs are not rendered by default.

src/Components/Components/src/ComponentFactory.cs

+22-3
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,26 @@ void Initialize(IServiceProvider serviceProvider, IComponent component)
134134
}
135135

136136
// Tracks information about a specific component type that ComponentFactory uses
137-
private record class ComponentTypeInfoCacheEntry(
138-
IComponentRenderMode? ComponentTypeRenderMode,
139-
Action<IServiceProvider, IComponent> PerformPropertyInjection);
137+
private sealed class ComponentTypeInfoCacheEntry
138+
{
139+
public IComponentRenderMode? ComponentTypeRenderMode { get; }
140+
141+
public Action<IServiceProvider, IComponent> PerformPropertyInjection { get; }
142+
143+
public ComponentTypeInfoCacheEntry(
144+
IComponentRenderMode? componentTypeRenderMode,
145+
Action<IServiceProvider, IComponent> performPropertyInjection)
146+
{
147+
ComponentTypeRenderMode = componentTypeRenderMode;
148+
PerformPropertyInjection = performPropertyInjection;
149+
}
150+
151+
public void Deconstruct(
152+
out IComponentRenderMode? componentTypeRenderMode,
153+
out Action<IServiceProvider, IComponent> performPropertyInjection)
154+
{
155+
componentTypeRenderMode = ComponentTypeRenderMode;
156+
performPropertyInjection = PerformPropertyInjection;
157+
}
158+
}
140159
}

src/Components/Endpoints/src/DependencyInjection/ServerComponentSerializer.cs

+2-29
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,17 @@ namespace Microsoft.AspNetCore.Components.Endpoints;
99
// See the details of the component serialization protocol in ServerComponentDeserializer.cs on the Components solution.
1010
internal sealed class ServerComponentSerializer
1111
{
12-
public const int PreambleBufferSize = 3;
13-
1412
private readonly ITimeLimitedDataProtector _dataProtector;
1513

1614
public ServerComponentSerializer(IDataProtectionProvider dataProtectionProvider) =>
1715
_dataProtector = dataProtectionProvider
1816
.CreateProtector(ServerComponentSerializationSettings.DataProtectionProviderPurpose)
1917
.ToTimeLimitedDataProtector();
2018

21-
public ServerComponentMarker SerializeInvocation(ServerComponentInvocationSequence invocationId, Type type, ParameterView parameters, string key, bool prerendered)
19+
public void SerializeInvocation(ref ComponentMarker marker, ServerComponentInvocationSequence invocationId, Type type, ParameterView parameters)
2220
{
2321
var (sequence, serverComponent) = CreateSerializedServerComponent(invocationId, type, parameters);
24-
return prerendered ? ServerComponentMarker.Prerendered(sequence, serverComponent, key) : ServerComponentMarker.NonPrerendered(sequence, serverComponent, key);
22+
marker.WriteServerData(sequence, serverComponent);
2523
}
2624

2725
private (int sequence, string payload) CreateSerializedServerComponent(
@@ -45,29 +43,4 @@ public ServerComponentMarker SerializeInvocation(ServerComponentInvocationSequen
4543
var protectedBytes = _dataProtector.Protect(serializedServerComponentBytes, ServerComponentSerializationSettings.DataExpiration);
4644
return (serverComponent.Sequence, Convert.ToBase64String(protectedBytes));
4745
}
48-
49-
/// <remarks>
50-
/// Remember to update <see cref="PreambleBufferSize"/> if the number of entries being appended in this function changes.
51-
/// </remarks>
52-
internal static void AppendPreamble(TextWriter writer, ServerComponentMarker record)
53-
{
54-
var serializedStartRecord = JsonSerializer.Serialize(
55-
record,
56-
ServerComponentSerializationSettings.JsonSerializationOptions);
57-
58-
writer.Write("<!--Blazor:");
59-
writer.Write(serializedStartRecord);
60-
writer.Write("-->");
61-
}
62-
63-
internal static void AppendEpilogue(TextWriter writer, ServerComponentMarker record)
64-
{
65-
var endRecord = JsonSerializer.Serialize(
66-
record.GetEndRecord(),
67-
ServerComponentSerializationSettings.JsonSerializationOptions);
68-
69-
writer.Write("<!--Blazor:");
70-
writer.Write(endRecord);
71-
writer.Write("-->");
72-
}
7346
}

src/Components/Endpoints/src/DependencyInjection/WebAssemblyComponentSerializer.cs

+2-25
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Components.Endpoints;
88
// See the details of the component serialization protocol in WebAssemblyComponentDeserializer.cs on the Components solution.
99
internal sealed class WebAssemblyComponentSerializer
1010
{
11-
public static WebAssemblyComponentMarker SerializeInvocation(Type type, ParameterView parameters, string? key, bool prerendered)
11+
public static void SerializeInvocation(ref ComponentMarker marker, Type type, ParameterView parameters)
1212
{
1313
var assembly = type.Assembly.GetName().Name ?? throw new InvalidOperationException("Cannot prerender components from assemblies with a null name");
1414
var typeFullName = type.FullName ?? throw new InvalidOperationException("Cannot prerender component types with a null name");
@@ -19,29 +19,6 @@ public static WebAssemblyComponentMarker SerializeInvocation(Type type, Paramete
1919
var serializedDefinitions = Convert.ToBase64String(JsonSerializer.SerializeToUtf8Bytes(definitions, WebAssemblyComponentSerializationSettings.JsonSerializationOptions));
2020
var serializedValues = Convert.ToBase64String(JsonSerializer.SerializeToUtf8Bytes(values, WebAssemblyComponentSerializationSettings.JsonSerializationOptions));
2121

22-
return prerendered ? WebAssemblyComponentMarker.Prerendered(assembly, typeFullName, serializedDefinitions, serializedValues, key) :
23-
WebAssemblyComponentMarker.NonPrerendered(assembly, typeFullName, serializedDefinitions, serializedValues, key);
24-
}
25-
26-
internal static void AppendPreamble(TextWriter writer, WebAssemblyComponentMarker record)
27-
{
28-
var serializedStartRecord = JsonSerializer.Serialize(
29-
record,
30-
WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
31-
32-
writer.Write("<!--Blazor:");
33-
writer.Write(serializedStartRecord);
34-
writer.Write("-->");
35-
}
36-
37-
internal static void AppendEpilogue(TextWriter writer, WebAssemblyComponentMarker record)
38-
{
39-
var endRecord = JsonSerializer.Serialize(
40-
record.GetEndRecord(),
41-
WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
42-
43-
writer.Write("<!--Blazor:");
44-
writer.Write(endRecord);
45-
writer.Write("-->");
22+
marker.WriteWebAssemblyData(assembly, typeFullName, serializedDefinitions, serializedValues);
4623
}
4724
}

src/Components/Endpoints/src/FormMapping/Factories/ComplexType/ComplexTypeExpressionConverterFactoryOfT.cs

+40-6
Original file line numberDiff line numberDiff line change
@@ -576,10 +576,44 @@ private static FormDataConverterReadParameters CreateFormDataConverterParameters
576576
Expression.Parameter(typeof(bool).MakeByRefType(), "foundValue"));
577577
}
578578

579-
private record struct FormDataConverterReadParameters(
580-
ParameterExpression ReaderParam,
581-
ParameterExpression TypeParam,
582-
ParameterExpression OptionsParam,
583-
ParameterExpression ResultParam,
584-
ParameterExpression FoundValueParam);
579+
private readonly struct FormDataConverterReadParameters
580+
{
581+
public ParameterExpression ReaderParam { get; }
582+
583+
public ParameterExpression TypeParam { get; }
584+
585+
public ParameterExpression OptionsParam { get; }
586+
587+
public ParameterExpression ResultParam { get; }
588+
589+
public ParameterExpression FoundValueParam { get; }
590+
591+
public FormDataConverterReadParameters(
592+
ParameterExpression readerParam,
593+
ParameterExpression typeParam,
594+
ParameterExpression optionsParam,
595+
ParameterExpression resultParam,
596+
ParameterExpression foundValueParam)
597+
{
598+
ReaderParam = readerParam;
599+
TypeParam = typeParam;
600+
OptionsParam = optionsParam;
601+
ResultParam = resultParam;
602+
FoundValueParam = foundValueParam;
603+
}
604+
605+
public void Deconstruct(
606+
out ParameterExpression readerParam,
607+
out ParameterExpression typeParam,
608+
out ParameterExpression optionsParam,
609+
out ParameterExpression resultParam,
610+
out ParameterExpression foundValueParam)
611+
{
612+
readerParam = ReaderParam;
613+
typeParam = TypeParam;
614+
optionsParam = OptionsParam;
615+
resultParam = ResultParam;
616+
foundValueParam = FoundValueParam;
617+
}
618+
}
585619
}

src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
</ItemGroup>
2626

2727
<ItemGroup>
28+
<Compile Include="$(SharedSourceRoot)Components\ComponentMarker.cs" LinkBase="DependencyInjection" />
2829
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentSerializationSettings.cs" LinkBase="DependencyInjection" />
2930
<Compile Include="$(SharedSourceRoot)Components\ServerComponentSerializationSettings.cs" LinkBase="DependencyInjection" />
30-
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentMarker.cs" LinkBase="DependencyInjection" />
31-
<Compile Include="$(SharedSourceRoot)Components\ServerComponentMarker.cs" LinkBase="DependencyInjection" />
3231
<Compile Include="$(SharedSourceRoot)Components\ServerComponent.cs" LinkBase="DependencyInjection" />
3332
<Compile Include="$(RepoRoot)src\Shared\Components\ComponentParameter.cs" LinkBase="DependencyInjection" />
3433
<Compile Include="$(RepoRoot)src\Shared\Components\PrerenderComponentApplicationStore.cs" LinkBase="DependencyInjection" />

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.Streaming.cs

+39-24
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Runtime.InteropServices;
55
using System.Text.Encodings.Web;
6+
using System.Text.Json;
67
using Microsoft.AspNetCore.Components.RenderTree;
78
using Microsoft.AspNetCore.Hosting;
89
using Microsoft.AspNetCore.Http;
@@ -199,29 +200,22 @@ private void WriteComponentHtml(int componentId, TextWriter output, bool allowBo
199200
var componentState = (EndpointComponentState)GetComponentState(componentId);
200201
var renderBoundaryMarkers = allowBoundaryMarkers && componentState.StreamRendering;
201202

202-
// TODO: It's not clear that we actually want to emit the interactive component markers using this
203-
// HTML-comment syntax that we've used historically, plus we likely want some way to coalesce both
204-
// marker types into a single thing for auto mode (the code below emits both separately for auto).
205-
// It may be better to use a custom element like <blazor-component ...>[prerendered]<blazor-component>
206-
// so it's easier for the JS code to react automatically whenever this gets inserted or updated during
207-
// streaming SSR or progressively-enhanced navigation.
208-
var (serverMarker, webAssemblyMarker) = componentState.Component is SSRRenderModeBoundary boundary
209-
? boundary.ToMarkers(_httpContext, sequenceAndKey.Sequence, sequenceAndKey.Key)
210-
: default;
211-
212-
if (serverMarker.HasValue)
203+
ComponentEndMarker? endMarkerOrNull = default;
204+
205+
if (componentState.Component is SSRRenderModeBoundary boundary)
213206
{
214-
if (!_httpContext.Response.HasStarted)
207+
var marker = boundary.ToMarker(_httpContext, sequenceAndKey.Sequence, sequenceAndKey.Key);
208+
endMarkerOrNull = marker.ToEndMarker();
209+
210+
if (!_httpContext.Response.HasStarted && marker.Type is ComponentMarker.ServerMarkerType or ComponentMarker.AutoMarkerType)
215211
{
216212
_httpContext.Response.Headers.CacheControl = "no-cache, no-store, max-age=0";
217213
}
218214

219-
ServerComponentSerializer.AppendPreamble(output, serverMarker.Value);
220-
}
221-
222-
if (webAssemblyMarker.HasValue)
223-
{
224-
WebAssemblyComponentSerializer.AppendPreamble(output, webAssemblyMarker.Value);
215+
var serializedStartRecord = JsonSerializer.Serialize(marker, ServerComponentSerializationSettings.JsonSerializationOptions);
216+
output.Write("<!--Blazor:");
217+
output.Write(serializedStartRecord);
218+
output.Write("-->");
225219
}
226220

227221
if (renderBoundaryMarkers)
@@ -240,17 +234,38 @@ private void WriteComponentHtml(int componentId, TextWriter output, bool allowBo
240234
output.Write("-->");
241235
}
242236

243-
if (webAssemblyMarker.HasValue && webAssemblyMarker.Value.PrerenderId is not null)
237+
if (endMarkerOrNull is { } endMarker)
244238
{
245-
WebAssemblyComponentSerializer.AppendEpilogue(output, webAssemblyMarker.Value);
239+
var serializedEndRecord = JsonSerializer.Serialize(endMarker, ServerComponentSerializationSettings.JsonSerializationOptions);
240+
output.Write("<!--Blazor:");
241+
output.Write(serializedEndRecord);
242+
output.Write("-->");
246243
}
244+
}
247245

248-
if (serverMarker.HasValue && serverMarker.Value.PrerenderId is not null)
246+
private readonly struct ComponentIdAndDepth
247+
{
248+
public int ComponentId { get; }
249+
250+
public int Depth { get; }
251+
252+
public ComponentIdAndDepth(int componentId, int depth)
249253
{
250-
ServerComponentSerializer.AppendEpilogue(output, serverMarker.Value);
254+
ComponentId = componentId;
255+
Depth = depth;
251256
}
252257
}
253258

254-
private readonly record struct ComponentIdAndDepth(int ComponentId, int Depth);
255-
private readonly record struct SequenceAndKey(int Sequence, object? Key);
259+
private readonly struct SequenceAndKey
260+
{
261+
public int Sequence { get; }
262+
263+
public object? Key { get; }
264+
265+
public SequenceAndKey(int sequence, object? key)
266+
{
267+
Sequence = sequence;
268+
Key = key;
269+
}
270+
}
256271
}

src/Components/Endpoints/src/Rendering/SSRRenderModeBoundary.cs

+13-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Concurrent;
5+
using System.Diagnostics;
56
using System.Globalization;
67
using System.Security.Cryptography;
78
using System.Text;
@@ -99,7 +100,7 @@ private void Prerender(RenderTreeBuilder builder)
99100
builder.CloseComponent();
100101
}
101102

102-
public (ServerComponentMarker?, WebAssemblyComponentMarker?) ToMarkers(HttpContext httpContext, int sequence, object? key)
103+
public ComponentMarker ToMarker(HttpContext httpContext, int sequence, object? key)
103104
{
104105
// We expect that the '@key' and sequence number shouldn't change for a given component instance,
105106
// so we lazily compute the marker key once.
@@ -109,24 +110,30 @@ private void Prerender(RenderTreeBuilder builder)
109110
? ParameterView.Empty
110111
: ParameterView.FromDictionary((IDictionary<string, object?>)_latestParameters);
111112

112-
ServerComponentMarker? serverMarker = null;
113+
var marker = _renderMode switch
114+
{
115+
ServerRenderMode server => ComponentMarker.Create(ComponentMarker.ServerMarkerType, server.Prerender, _markerKey),
116+
WebAssemblyRenderMode webAssembly => ComponentMarker.Create(ComponentMarker.WebAssemblyMarkerType, webAssembly.Prerender, _markerKey),
117+
AutoRenderMode auto => ComponentMarker.Create(ComponentMarker.AutoMarkerType, auto.Prerender, _markerKey),
118+
_ => throw new UnreachableException($"Unknown render mode {_renderMode.GetType().FullName}"),
119+
};
120+
113121
if (_renderMode is ServerRenderMode or AutoRenderMode)
114122
{
115123
// Lazy because we don't actually want to require a whole chain of services including Data Protection
116124
// to be required unless you actually use Server render mode.
117125
var serverComponentSerializer = httpContext.RequestServices.GetRequiredService<ServerComponentSerializer>();
118126

119127
var invocationId = EndpointHtmlRenderer.GetOrCreateInvocationId(httpContext);
120-
serverMarker = serverComponentSerializer.SerializeInvocation(invocationId, _componentType, parameters, _markerKey, _prerender);
128+
serverComponentSerializer.SerializeInvocation(ref marker, invocationId, _componentType, parameters);
121129
}
122130

123-
WebAssemblyComponentMarker? webAssemblyMarker = null;
124131
if (_renderMode is WebAssemblyRenderMode or AutoRenderMode)
125132
{
126-
webAssemblyMarker = WebAssemblyComponentSerializer.SerializeInvocation(_componentType, parameters, _markerKey, _prerender);
133+
WebAssemblyComponentSerializer.SerializeInvocation(ref marker, _componentType, parameters);
127134
}
128135

129-
return (serverMarker, webAssemblyMarker);
136+
return marker;
130137
}
131138

132139
private string GenerateMarkerKey(int sequence, object? key)

0 commit comments

Comments
 (0)