Skip to content

Prerender select elements with value; move HtmlRenderer into Mvc.ViewFeatures #12996

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

Merged
merged 7 commits into from
Aug 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -497,30 +497,12 @@ public ValidationStateChangedEventArgs() { }
}
namespace Microsoft.AspNetCore.Components.Rendering
{
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct ComponentRenderedText
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public System.Collections.Generic.IEnumerable<string> Tokens { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
public partial class EventFieldInfo
{
public EventFieldInfo() { }
public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public object FieldValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public partial class HtmlRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer
{
public HtmlRenderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.Func<string, string> htmlEncoder) : base (default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILoggerFactory)) { }
public override Microsoft.AspNetCore.Components.Dispatcher Dispatcher { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
protected override void HandleException(System.Exception exception) { }
[System.Diagnostics.DebuggerStepThroughAttribute]
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; }
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync<TComponent>(Microsoft.AspNetCore.Components.ParameterView initialParameters) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; }
protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch renderBatch) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct RenderBatch
{
Expand All @@ -539,6 +521,7 @@ public event System.UnhandledExceptionEventHandler UnhandledSynchronizationExcep
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
protected Microsoft.AspNetCore.Components.RenderTree.ArrayRange<Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame> GetCurrentRenderTreeFrames(int componentId) { throw null; }
protected abstract void HandleException(System.Exception exception);
protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; }
protected virtual void ProcessPendingRender() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,30 +497,12 @@ public ValidationStateChangedEventArgs() { }
}
namespace Microsoft.AspNetCore.Components.Rendering
{
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct ComponentRenderedText
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public System.Collections.Generic.IEnumerable<string> Tokens { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
public partial class EventFieldInfo
{
public EventFieldInfo() { }
public int ComponentId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public object FieldValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public partial class HtmlRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer
{
public HtmlRenderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.Func<string, string> htmlEncoder) : base (default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILoggerFactory)) { }
public override Microsoft.AspNetCore.Components.Dispatcher Dispatcher { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
protected override void HandleException(System.Exception exception) { }
[System.Diagnostics.DebuggerStepThroughAttribute]
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; }
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync<TComponent>(Microsoft.AspNetCore.Components.ParameterView initialParameters) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; }
protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch renderBatch) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct RenderBatch
{
Expand All @@ -539,6 +521,7 @@ public event System.UnhandledExceptionEventHandler UnhandledSynchronizationExcep
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
protected Microsoft.AspNetCore.Components.RenderTree.ArrayRange<Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame> GetCurrentRenderTreeFrames(int componentId) { throw null; }
protected abstract void HandleException(System.Exception exception);
protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; }
protected virtual void ProcessPendingRender() { }
Expand Down
29 changes: 0 additions & 29 deletions src/Components/Components/src/Rendering/ComponentRenderedText.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Components/Components/src/Rendering/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ protected internal int AssignRootComponentId(IComponent component)
/// </summary>
/// <param name="componentId">The id for the component.</param>
/// <returns>The <see cref="RenderTreeBuilder"/> representing the current render tree.</returns>
private protected ArrayRange<RenderTreeFrame> GetCurrentRenderTreeFrames(int componentId) => GetRequiredComponentState(componentId).CurrentRenderTree.GetFrames();
protected ArrayRange<RenderTreeFrame> GetCurrentRenderTreeFrames(int componentId) => GetRequiredComponentState(componentId).CurrentRenderTree.GetFrames();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the expectation that if you get the current frames you can or can't hold on to them? Does this make a copy?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't make a copy. The expectation is that you only access them synchronously.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could rename to “ViewCurrentRenderTreeFrames” to clarify this. Longer term we could use the same technique we plan for ParameterView to throw if you access after the underlying store is mutated further.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ViewCurrentRenderTreeFrames

I'm not actually going to rename it to that, because it's a strange name. The existing name GetCurrentRenderTreeFrames is more conventional. We can add the "don't read after mutation" check in the future if we want.


/// <summary>
/// Performs the first render for a root component, waiting for this component and all
Expand Down
16 changes: 0 additions & 16 deletions src/Components/Components/test/Rendering/HtmlRendererTests.cs

This file was deleted.

2 changes: 0 additions & 2 deletions src/Components/Server/src/Circuits/DefaultCircuitFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ public override CircuitHost CreateCircuitHost(
var components = ResolveComponentMetadata(httpContext);

var scope = _scopeFactory.CreateScope();
var encoder = scope.ServiceProvider.GetRequiredService<HtmlEncoder>();
var jsRuntime = (RemoteJSRuntime)scope.ServiceProvider.GetRequiredService<IJSRuntime>();
var componentContext = (RemoteComponentContext)scope.ServiceProvider.GetRequiredService<IComponentContext>();
jsRuntime.Initialize(client);
Expand All @@ -76,7 +75,6 @@ public override CircuitHost CreateCircuitHost(
_options,
jsRuntime,
client,
encoder,
_loggerFactory.CreateLogger<RemoteRenderer>());

var circuitHandlers = scope.ServiceProvider.GetServices<CircuitHandler>()
Expand Down
6 changes: 2 additions & 4 deletions src/Components/Server/src/Circuits/RemoteRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
Expand All @@ -17,7 +16,7 @@

namespace Microsoft.AspNetCore.Components.Web.Rendering
{
internal class RemoteRenderer : HtmlRenderer
internal class RemoteRenderer : Renderer
{
private static readonly Task CanceledTask = Task.FromCanceled(new CancellationToken(canceled: true));

Expand All @@ -43,9 +42,8 @@ public RemoteRenderer(
CircuitOptions options,
IJSRuntime jsRuntime,
CircuitClientProxy client,
HtmlEncoder encoder,
ILogger logger)
: base(serviceProvider, loggerFactory, encoder.Encode)
: base(serviceProvider, loggerFactory)
{
_jsRuntime = jsRuntime;
_client = client;
Expand Down
4 changes: 1 addition & 3 deletions src/Components/Server/test/Circuits/CircuitHostTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Rendering;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -238,7 +236,7 @@ private static TestRemoteRenderer GetRemoteRenderer()
private class TestRemoteRenderer : RemoteRenderer
{
public TestRemoteRenderer(IServiceProvider serviceProvider, IJSRuntime jsRuntime, IClientProxy client)
: base(serviceProvider, NullLoggerFactory.Instance, new CircuitOptions(), jsRuntime, new CircuitClientProxy(client, "connection"), HtmlEncoder.Default, NullLogger.Instance)
: base(serviceProvider, NullLoggerFactory.Instance, new CircuitOptions(), jsRuntime, new CircuitClientProxy(client, "connection"), NullLogger.Instance)
{
}

Expand Down
67 changes: 27 additions & 40 deletions src/Components/Server/test/Circuits/RemoteRendererTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Encodings.Web;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.AspNetCore.SignalR;
Expand All @@ -20,23 +18,18 @@

namespace Microsoft.AspNetCore.Components.Web.Rendering
{
public class RemoteRendererTest : HtmlRendererTestBase
public class RemoteRendererTest
{
// Nothing should exceed the timeout in a successful run of the the tests, this is just here to catch
// failures.
private static readonly TimeSpan Timeout = Debugger.IsAttached ? System.Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(10);

protected override HtmlRenderer GetHtmlRenderer(IServiceProvider serviceProvider)
{
return GetRemoteRenderer(serviceProvider, new CircuitClientProxy());
}

[Fact]
public void WritesAreBufferedWhenTheClientIsOffline()
{
// Arrange
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var renderer = (RemoteRenderer)GetHtmlRenderer(serviceProvider);
var renderer = GetRemoteRenderer(serviceProvider);
var component = new TestComponent(builder =>
{
builder.OpenElement(0, "my element");
Expand All @@ -57,7 +50,7 @@ public void WritesAreBufferedWhenTheClientIsOffline()
public void NotAcknowledgingRenders_ProducesBatches_UpToTheLimit()
{
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var renderer = (RemoteRenderer)GetHtmlRenderer(serviceProvider);
var renderer = GetRemoteRenderer(serviceProvider);
var component = new TestComponent(builder =>
{
builder.OpenElement(0, "my element");
Expand All @@ -81,7 +74,7 @@ public void NotAcknowledgingRenders_ProducesBatches_UpToTheLimit()
public async Task NoNewBatchesAreCreated_WhenThereAreNoPendingRenderRequestsFromComponents()
{
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var renderer = (RemoteRenderer)GetHtmlRenderer(serviceProvider);
var renderer = GetRemoteRenderer(serviceProvider);
var component = new TestComponent(builder =>
{
builder.OpenElement(0, "my element");
Expand All @@ -107,7 +100,7 @@ public async Task NoNewBatchesAreCreated_WhenThereAreNoPendingRenderRequestsFrom
public async Task ProducesNewBatch_WhenABatchGetsAcknowledged()
{
var serviceProvider = new ServiceCollection().BuildServiceProvider();
var renderer = (RemoteRenderer)GetHtmlRenderer(serviceProvider);
var renderer = GetRemoteRenderer(serviceProvider);
var i = 0;
var component = new TestComponent(builder =>
{
Expand Down Expand Up @@ -215,7 +208,7 @@ public async Task OnRenderCompletedAsync_DoesNotThrowWhenReceivedDuplicateAcks()
.Returns<string, object[], CancellationToken>((n, v, t) => (long)v[1] == 2 ? firstBatchTCS.Task : secondBatchTCS.Task);

// This produces the initial batch (id = 2)
var result = await renderer.RenderComponentAsync<AutoParameterTestComponent>(
await renderer.RenderComponentAsync<AutoParameterTestComponent>(
ParameterView.FromDictionary(new Dictionary<string, object>
{
[nameof(AutoParameterTestComponent.Content)] = initialContent,
Expand Down Expand Up @@ -278,7 +271,7 @@ public async Task OnRenderCompletedAsync_DoesNotThrowWhenThereAreNoPendingBatche
.Returns<string, object[], CancellationToken>((n, v, t) => (long)v[1] == 2 ? firstBatchTCS.Task : secondBatchTCS.Task);

// This produces the initial batch (id = 2)
var result = await renderer.RenderComponentAsync<AutoParameterTestComponent>(
await renderer.RenderComponentAsync<AutoParameterTestComponent>(
ParameterView.FromDictionary(new Dictionary<string, object>
{
[nameof(AutoParameterTestComponent.Content)] = initialContent,
Expand Down Expand Up @@ -341,7 +334,7 @@ public async Task ConsumesAllPendingBatchesWhenReceivingAHigherSequenceBatchId()
var trigger = new Trigger();

// This produces the initial batch (id = 2)
var result = await renderer.RenderComponentAsync<AutoParameterTestComponent>(
await renderer.RenderComponentAsync<AutoParameterTestComponent>(
ParameterView.FromDictionary(new Dictionary<string, object>
{
[nameof(AutoParameterTestComponent.Content)] = initialContent,
Expand Down Expand Up @@ -398,7 +391,7 @@ public async Task ThrowsIfWeReceivedAnAcknowledgeForANeverProducedBatch()
var trigger = new Trigger();

// This produces the initial batch (id = 2)
var result = await renderer.RenderComponentAsync<AutoParameterTestComponent>(
await renderer.RenderComponentAsync<AutoParameterTestComponent>(
ParameterView.FromDictionary(new Dictionary<string, object>
{
[nameof(AutoParameterTestComponent.Content)] = initialContent,
Expand Down Expand Up @@ -432,27 +425,7 @@ public async Task ThrowsIfWeReceivedAnAcknowledgeForANeverProducedBatch()
exception.Message);
}

[Fact]
public async Task PrerendersMultipleComponentsSuccessfully()
{
// Arrange
var serviceProvider = new ServiceCollection().BuildServiceProvider();

var renderer = GetRemoteRenderer(
serviceProvider,
new CircuitClientProxy());

// Act
var first = await renderer.RenderComponentAsync<TestComponent>(ParameterView.Empty);
var second = await renderer.RenderComponentAsync<TestComponent>(ParameterView.Empty);

// Assert
Assert.Equal(0, first.ComponentId);
Assert.Equal(1, second.ComponentId);
Assert.Equal(2, renderer._unacknowledgedRenderBatches.Count);
}

private RemoteRenderer GetRemoteRenderer(IServiceProvider serviceProvider, CircuitClientProxy circuitClientProxy)
private TestRemoteRenderer GetRemoteRenderer(IServiceProvider serviceProvider, CircuitClientProxy circuitClient = null)
{
var jsRuntime = new Mock<IJSRuntime>();
jsRuntime.Setup(r => r.InvokeAsync<object>(
Expand All @@ -462,16 +435,30 @@ private RemoteRenderer GetRemoteRenderer(IServiceProvider serviceProvider, Circu
It.IsAny<int>()))
.ReturnsAsync(Task.FromResult<object>(null));

return new RemoteRenderer(
return new TestRemoteRenderer(
serviceProvider,
NullLoggerFactory.Instance,
new CircuitOptions(),
jsRuntime.Object,
circuitClientProxy,
HtmlEncoder.Default,
circuitClient ?? new CircuitClientProxy(),
NullLogger.Instance);
}

private class TestRemoteRenderer : RemoteRenderer
{
public TestRemoteRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, CircuitOptions options, IJSRuntime jsRuntime, CircuitClientProxy client, ILogger logger)
: base(serviceProvider, loggerFactory, options, jsRuntime, client, logger)
{
}

public async Task RenderComponentAsync<TComponent>(ParameterView initialParameters)
{
var component = InstantiateComponent(typeof(TComponent));
var componentId = AssignRootComponentId(component);
await RenderRootComponentAsync(componentId, initialParameters);
}
}

private class TestComponent : IComponent, IHandleAfterRender
{
private RenderHandle _renderHandle;
Expand Down
Loading