[wip] Update Razor SDK and resolve issues

I'm still chasing one more issue.
This commit is contained in:
Ryan Nowak 2019-02-19 18:10:17 -08:00
parent 6d8c8f8c64
commit 616a4a36f5
11 changed files with 760 additions and 135 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
This file is used by automation to update Versions.props and may be used for other purposes, such as This file is used by automation to update Versions.props and may be used for other purposes, such as
@ -9,21 +9,21 @@
--> -->
<Dependencies> <Dependencies>
<ProductDependencies> <ProductDependencies>
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview-19107-04"> <Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview3.19119.5">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>408b123a6454841884c1d840fb853eec8de12c10</Sha> <Sha>182b2c81a5a3c2d5219cf20205e49dbe86823e18</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview-19107-04"> <Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview3.19119.5">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>408b123a6454841884c1d840fb853eec8de12c10</Sha> <Sha>182b2c81a5a3c2d5219cf20205e49dbe86823e18</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview-19107-04"> <Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview3.19119.5">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>408b123a6454841884c1d840fb853eec8de12c10</Sha> <Sha>182b2c81a5a3c2d5219cf20205e49dbe86823e18</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview-19107-04"> <Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview3.19119.5">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>408b123a6454841884c1d840fb853eec8de12c10</Sha> <Sha>182b2c81a5a3c2d5219cf20205e49dbe86823e18</Sha>
</Dependency> </Dependency>
<Dependency Name="dotnet-ef" Version="3.0.0-preview.19080.1"> <Dependency Name="dotnet-ef" Version="3.0.0-preview.19080.1">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>

View File

@ -1,4 +1,4 @@

<!-- <!--
This file defines the versions of external dependencies used by ASP.NET Core. This file defines the versions of external dependencies used by ASP.NET Core.
@ -112,10 +112,10 @@
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview.19080.1</MicrosoftEntityFrameworkCoreToolsPackageVersion> <MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview.19080.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview.19080.1</MicrosoftEntityFrameworkCorePackageVersion> <MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview.19080.1</MicrosoftEntityFrameworkCorePackageVersion>
<!-- Packages from aspnet/AspNetCore-Tooling --> <!-- Packages from aspnet/AspNetCore-Tooling -->
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview-19107-04</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion> <MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview3.19119.5</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview-19107-04</MicrosoftAspNetCoreRazorLanguagePackageVersion> <MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview3.19119.5</MicrosoftAspNetCoreRazorLanguagePackageVersion>
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview-19107-04</MicrosoftCodeAnalysisRazorPackageVersion> <MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview3.19119.5</MicrosoftCodeAnalysisRazorPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview-19107-04</MicrosoftNETSdkRazorPackageVersion> <MicrosoftNETSdkRazorPackageVersion>3.0.0-preview3.19119.5</MicrosoftNETSdkRazorPackageVersion>
</PropertyGroup> </PropertyGroup>
<!-- <!--

View File

@ -91,7 +91,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0), frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1), frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(Action<UIEventArgs>), 2)); frame => AssertFrame.Attribute(frame, "ValueChanged", typeof(EventCallback<UIChangeEventArgs>), 2));
} }
[Fact] [Fact]
@ -167,7 +167,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0), frame => AssertFrame.Component(frame, "Test.MyComponent", 3, 0),
frame => AssertFrame.Attribute(frame, "Value", 42, 1), frame => AssertFrame.Attribute(frame, "Value", 42, 1),
frame => AssertFrame.Attribute(frame, "OnChanged", typeof(Action<UIEventArgs>), 2)); frame => AssertFrame.Attribute(frame, "OnChanged", typeof(EventCallback<UIChangeEventArgs>), 2));
} }
[Fact] [Fact]
@ -201,7 +201,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Element(frame, "div", 3, 0), frame => AssertFrame.Element(frame, "div", 3, 0),
frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1), frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1),
frame => AssertFrame.Attribute(frame, "myevent", typeof(Action<UIEventArgs>), 2)); frame => AssertFrame.Attribute(frame, "myevent", typeof(EventCallback), 2));
} }
[Fact] [Fact]
@ -235,7 +235,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Element(frame, "div", 3, 0), frame => AssertFrame.Element(frame, "div", 3, 0),
frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1), frame => AssertFrame.Attribute(frame, "myvalue", "hi", 1),
frame => AssertFrame.Attribute(frame, "myevent", typeof(Action<UIEventArgs>), 2)); frame => AssertFrame.Attribute(frame, "myevent", typeof(EventCallback), 2));
} }
[Fact] [Fact]
@ -292,7 +292,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "value", "42", 1), frame => AssertFrame.Attribute(frame, "value", "42", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 2)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 2));
} }
[Fact] [Fact]
@ -315,7 +315,7 @@ namespace Test
frame => AssertFrame.Element(frame, "input", 4, 0), frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2), frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] [Fact]
@ -340,7 +340,7 @@ namespace Test
frame => AssertFrame.Element(frame, "input", 4, 0), frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2), frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd/yyyy"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] [Fact]
@ -363,7 +363,7 @@ namespace Test
frame => AssertFrame.Element(frame, "input", 4, 0), frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", "42", 2), frame => AssertFrame.Attribute(frame, "value", "42", 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] [Fact]
@ -385,7 +385,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
frame => AssertFrame.Attribute(frame, "type", "checkbox", 1), frame => AssertFrame.Attribute(frame, "type", "checkbox", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] [Fact]
@ -408,7 +408,7 @@ namespace Test
frame => AssertFrame.Element(frame, "input", 4, 0), frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", "42", 2), frame => AssertFrame.Attribute(frame, "value", "42", 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] [Fact]
@ -431,7 +431,7 @@ namespace Test
frame => AssertFrame.Element(frame, "input", 4, 0), frame => AssertFrame.Element(frame, "input", 4, 0),
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd"), 2), frame => AssertFrame.Attribute(frame, "value", new DateTime(2018, 1, 1).ToString("MM/dd"), 2),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 3)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 3));
} }
[Fact] // Additional coverage of OrphanTagHelperLoweringPass [Fact] // Additional coverage of OrphanTagHelperLoweringPass
@ -455,7 +455,7 @@ namespace Test
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "visible", 2), frame => AssertFrame.Attribute(frame, "visible", 2),
frame => AssertFrame.Attribute(frame, "value", "42", 3), frame => AssertFrame.Attribute(frame, "value", "42", 3),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 4)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 4));
} }
[Fact] // See https://github.com/aspnet/Blazor/issues/703 [Fact] // See https://github.com/aspnet/Blazor/issues/703
@ -482,7 +482,7 @@ namespace Test
frame => AssertFrame.Attribute(frame, "type", "text", 1), frame => AssertFrame.Attribute(frame, "type", "text", 1),
frame => AssertFrame.Attribute(frame, "visible", 2), frame => AssertFrame.Attribute(frame, "visible", 2),
frame => AssertFrame.Attribute(frame, "value", "42", 3), frame => AssertFrame.Attribute(frame, "value", "42", 3),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 4)); frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 4));
} }
[Fact] // Additional coverage of OrphanTagHelperLoweringPass [Fact] // Additional coverage of OrphanTagHelperLoweringPass
@ -506,7 +506,7 @@ namespace Test
frames, frames,
frame => AssertFrame.Element(frame, "div", 7, 0), frame => AssertFrame.Element(frame, "div", 7, 0),
frame => AssertFrame.Attribute(frame, "value", "42", 1), frame => AssertFrame.Attribute(frame, "value", "42", 1),
frame => AssertFrame.Attribute(frame, "onchange", typeof(Action<UIEventArgs>), 2), frame => AssertFrame.Attribute(frame, "onchange", typeof(EventCallback), 2),
frame => AssertFrame.Whitespace(frame, 3), frame => AssertFrame.Whitespace(frame, 3),
frame => AssertFrame.Element(frame, "span", 2, 4), frame => AssertFrame.Element(frame, "span", 2, 4),
frame => AssertFrame.Text(frame, "42", 5), frame => AssertFrame.Text(frame, "42", 5),

View File

@ -365,7 +365,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
@ -373,11 +373,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
await renderer.Invoke(() => setter(new UIChangeEventArgs { Value = "Modified value", })); //
// This should always complete synchronously.
var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = "Modified value", }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal("Modified value", myValueProperty.GetValue(component)); Assert.Equal("Modified value", myValueProperty.GetValue(component));
} }
@ -395,7 +400,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "textarea", 3, 0), frame => AssertFrame.Element(frame, "textarea", 3, 0),
@ -403,11 +408,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
await renderer.Invoke(() => setter(new UIChangeEventArgs() { Value = "Modified value", })); //
// This should always complete synchronously.
var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = "Modified value", }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal("Modified value", myValueProperty.GetValue(component)); Assert.Equal("Modified value", myValueProperty.GetValue(component));
} }
@ -425,7 +435,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
@ -433,12 +443,18 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
// Trigger the change event to show it updates the property
//
// This should always complete synchronously.
var newDateValue = new DateTime(2018, 3, 5, 4, 5, 6); var newDateValue = new DateTime(2018, 3, 5, 4, 5, 6);
await renderer.Invoke(() => setter(new UIChangeEventArgs() { Value = newDateValue.ToString(), })); var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = newDateValue.ToString(), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(newDateValue, myDateProperty.GetValue(component)); Assert.Equal(newDateValue, myDateProperty.GetValue(component));
} }
@ -457,7 +473,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
@ -465,11 +481,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
await renderer.Invoke(() => setter(new UIChangeEventArgs() { Value = new DateTime(2018, 3, 5).ToString(testDateFormat), })); //
// This should always complete synchronously.
var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = new DateTime(2018, 3, 5).ToString(testDateFormat), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(new DateTime(2018, 3, 5), myDateProperty.GetValue(component)); Assert.Equal(new DateTime(2018, 3, 5), myDateProperty.GetValue(component));
} }
@ -540,18 +561,22 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
// Assert // Assert
Assert.Collection(frames, Action<UIMouseEventArgs> func = default; // Since this is a method group, we don't need to create an EventCallback
Assert.Collection(
frames,
frame => AssertFrame.Element(frame, "button", 2, 0), frame => AssertFrame.Element(frame, "button", 2, 0),
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onclick", 1); AssertFrame.Attribute(frame, "onclick", 1);
var func = Assert.IsType<Action<UIMouseEventArgs>>(frame.AttributeValue); func = Assert.IsType<Action<UIMouseEventArgs>>(frame.AttributeValue);
Assert.False((bool)clicked.GetValue(component)); Assert.False((bool)clicked.GetValue(component));
func(new UIMouseEventArgs());
Assert.True((bool)clicked.GetValue(component));
}); });
func.Invoke(new UIMouseEventArgs());
Assert.True((bool)clicked.GetValue(component));
} }
[Fact] [Fact]
@ -568,7 +593,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
@ -576,11 +601,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
await renderer.Invoke(() => setter(new UIChangeEventArgs() { Value = false, })); //
// This should always complete synchronously.
var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs() { Value = false, }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.False((bool)myValueProperty.GetValue(component)); Assert.False((bool)myValueProperty.GetValue(component));
} }
@ -599,7 +629,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
var renderer = new TestRenderer(); var renderer = new TestRenderer();
// Assert // Assert
Action<UIEventArgs> setter = null; EventCallback setter = default;
var frames = GetRenderTree(renderer, component); var frames = GetRenderTree(renderer, component);
Assert.Collection(frames, Assert.Collection(frames,
frame => AssertFrame.Element(frame, "input", 3, 0), frame => AssertFrame.Element(frame, "input", 3, 0),
@ -607,11 +637,16 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
frame => frame =>
{ {
AssertFrame.Attribute(frame, "onchange", 2); AssertFrame.Attribute(frame, "onchange", 2);
setter = Assert.IsType<Action<UIEventArgs>>(frame.AttributeValue); setter = Assert.IsType<EventCallback>(frame.AttributeValue);
}); });
// Trigger the change event to show it updates the property // Trigger the change event to show it updates the property
await renderer.Invoke(() => setter(new UIChangeEventArgs() { Value = MyEnum.SecondValue.ToString(), })); //
// This should always complete synchronously.
var task = renderer.InvokeAsync(() => setter.InvokeAsync(new UIChangeEventArgs { Value = MyEnum.SecondValue.ToString(), }));
Assert.Equal(TaskStatus.RanToCompletion, task.Status);
await task;
Assert.Equal(MyEnum.SecondValue, (MyEnum)myValueProperty.GetValue(component)); Assert.Equal(MyEnum.SecondValue, (MyEnum)myValueProperty.GetValue(component));
} }

View File

@ -44,11 +44,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore(receiver, callback); return CreateCore(receiver, callback);
} }
@ -66,11 +61,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore(receiver, callback); return CreateCore(receiver, callback);
} }
@ -88,11 +78,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore(receiver, callback); return CreateCore(receiver, callback);
} }
@ -110,11 +95,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore(receiver, callback); return CreateCore(receiver, callback);
} }
@ -135,6 +115,23 @@ namespace Microsoft.AspNetCore.Components
return callback; return callback;
} }
/// <summary>
/// Returns the provided <paramref name="callback"/>. For internal framework use only.
/// </summary>
/// <param name="receiver"></param>
/// <param name="callback"></param>
/// <returns></returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public EventCallback<T> Create<T>(object receiver, EventCallback callback)
{
if (receiver == null)
{
throw new ArgumentNullException(nameof(receiver));
}
return new EventCallback<T>(callback.Receiver, callback.Delegate);
}
/// <summary> /// <summary>
/// Returns the provided <paramref name="callback"/>. For internal framework use only. /// Returns the provided <paramref name="callback"/>. For internal framework use only.
/// </summary> /// </summary>
@ -166,11 +163,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore<T>(receiver, callback); return CreateCore<T>(receiver, callback);
} }
@ -188,11 +180,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore<T>(receiver, callback); return CreateCore<T>(receiver, callback);
} }
@ -210,11 +197,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore<T>(receiver, callback); return CreateCore<T>(receiver, callback);
} }
@ -232,11 +214,6 @@ namespace Microsoft.AspNetCore.Components
throw new ArgumentNullException(nameof(receiver)); throw new ArgumentNullException(nameof(receiver));
} }
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
return CreateCore<T>(receiver, callback); return CreateCore<T>(receiver, callback);
} }
@ -270,22 +247,12 @@ namespace Microsoft.AspNetCore.Components
private EventCallback CreateCore(object receiver, MulticastDelegate callback) private EventCallback CreateCore(object receiver, MulticastDelegate callback)
{ {
if (!object.ReferenceEquals(receiver, callback.Target) && receiver is IHandleEvent handler) return new EventCallback(callback?.Target as IHandleEvent ?? receiver as IHandleEvent, callback);
{
return new EventCallback(handler, callback);
}
return new EventCallback(callback.Target as IHandleEvent, callback);
} }
private EventCallback<T> CreateCore<T>(object receiver, MulticastDelegate callback) private EventCallback<T> CreateCore<T>(object receiver, MulticastDelegate callback)
{ {
if (!object.ReferenceEquals(receiver, callback.Target) && receiver is IHandleEvent handler) return new EventCallback<T>(callback?.Target as IHandleEvent ?? receiver as IHandleEvent, callback);
{
return new EventCallback<T>(handler, callback);
}
return new EventCallback<T>(callback.Target as IHandleEvent, callback);
} }
} }
} }

View File

@ -2,10 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Forms;
namespace Microsoft.AspNetCore.Components namespace Microsoft.AspNetCore.Components
{ {
/// <summary> /// <summary>
/// Used by generated code produced by the Blazor code generator. Not intended or supported /// Used by generated code produced by the Components code generator. Not intended or supported
/// for use in application code. /// for use in application code.
/// </summary> /// </summary>
public static class RuntimeHelpers public static class RuntimeHelpers
@ -17,5 +21,502 @@ namespace Microsoft.AspNetCore.Components
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public static T TypeCheck<T>(T value) => value; public static T TypeCheck<T>(T value) => value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<EditContext> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<EditContext, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIChangeEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIChangeEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIClipboardEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIClipboardEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIDataTransferItem> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIDataTransferItem, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIDragEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIDragEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIErrorEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIErrorEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIFocusEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIFocusEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIKeyboardEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIKeyboardEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIMouseEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIMouseEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIPointerEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIPointerEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIProgressEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIProgressEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UITouchEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UITouchEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<UIWheelEventArgs> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<UIWheelEventArgs, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<int> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<int, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<int?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<int?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<long> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<long, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<long?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<long?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<decimal> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<decimal, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<decimal?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<decimal?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<float> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<float, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<float?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<float?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<double> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<double, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<double?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<double?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<DateTime> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<DateTime, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<DateTime?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<DateTime?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<bool> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<bool, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<bool?> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<bool?, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<string> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<string, Task> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Action<object> value) => (T)(object)value;
/// <summary>
/// Not intended for use by application code.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T TypeCheck<T>(Func<object, Task> value) => (T)(object)value;
} }
} }

View File

@ -58,8 +58,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -80,6 +80,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void Create_Action_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create(component, (Action)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void Create_ActionT_AlreadyBoundToReceiver() public void Create_ActionT_AlreadyBoundToReceiver()
{ {
@ -110,8 +125,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -132,6 +147,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void Create_ActionT_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create(component, (Action<string>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void Create_FuncTask_AlreadyBoundToReceiver() public void Create_FuncTask_AlreadyBoundToReceiver()
{ {
@ -162,8 +192,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -200,6 +230,21 @@ namespace Microsoft.AspNetCore.Components
Assert.False(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact]
public void Create_FuncTask_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create(component, (Func<Task>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void Create_FuncTTask_DifferentReceiver() public void Create_FuncTTask_DifferentReceiver()
{ {
@ -214,8 +259,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -236,6 +281,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void Create_FuncTTask_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create(component, (Func<string, Task>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void CreateT_String_ReturnsInput() public void CreateT_String_ReturnsInput()
{ {
@ -299,8 +359,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -321,6 +381,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void CreateT_Action_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create<string>(component, (Action)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void CreateT_ActionT_AlreadyBoundToReceiver() public void CreateT_ActionT_AlreadyBoundToReceiver()
{ {
@ -351,7 +426,22 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.False(callback.RequiresExplicitReceiver);
}
[Fact]
public void CreateT_ActionT_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create<string>(component, (Action<string>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
@ -403,8 +493,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -425,6 +515,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void CreateT_FuncTask_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create<string>(component, (Func<Task>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void CreateT_FuncTTask_AlreadyBoundToReceiver() public void CreateT_FuncTTask_AlreadyBoundToReceiver()
{ {
@ -455,8 +560,8 @@ namespace Microsoft.AspNetCore.Components
// Assert // Assert
Assert.Same(@delegate, callback.Delegate); Assert.Same(@delegate, callback.Delegate);
Assert.Same(anotherComponent, callback.Receiver); Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver); Assert.False(callback.RequiresExplicitReceiver);
} }
[Fact] [Fact]
@ -477,6 +582,21 @@ namespace Microsoft.AspNetCore.Components
Assert.True(callback.RequiresExplicitReceiver); Assert.True(callback.RequiresExplicitReceiver);
} }
[Fact]
public void CreateT_FuncTTask_Null()
{
// Arrange
var component = new EventComponent();
// Act
var callback = EventCallback.Factory.Create<string>(component, (Func<string, Task>)null);
// Assert
Assert.Null(callback.Delegate);
Assert.Same(component, callback.Receiver);
Assert.True(callback.RequiresExplicitReceiver);
}
[Fact] [Fact]
public void CreateInferred_ActionT() public void CreateInferred_ActionT()
{ {

View File

@ -11,6 +11,8 @@
<p> <p>
@(nameof(CascadingValueReceiveFixedByInterface)) render count: @(nameof(CascadingValueReceiveFixedByInterface)) render count:
<strong id="receive-by-interface-num-renders">@numRenders</strong> <strong id="receive-by-interface-num-renders">@numRenders</strong>
@* Prevent rerendering this component when the button is clicked. *@
<button id="decrement-count" onclick=@Ancestor.DecrementCount>Decrement</button> <button id="decrement-count" onclick=@Ancestor.DecrementCount>Decrement</button>
</p> </p>

View File

@ -10,29 +10,29 @@
</div> </div>
<div id="capturing_lambda"> <div id="capturing_lambda">
<h3>Passing Capturing Lambda to Button</h3> <h3>Passing Capturing Lambda to Button</h3>
<InnerButton OnClick="@EventCallback.Factory.Create(this, () => { GC.KeepAlive(this); })" Text="Capturing Lambda" /> <InnerButton OnClick="@(() => { GC.KeepAlive(this); })" Text="Capturing Lambda" />
</div> </div>
<div id="unbound_lambda"> <div id="unbound_lambda">
<h3>Passing Unbound Lambda to Button</h3> <h3>Passing Unbound Lambda to Button</h3>
<InnerButton OnClick="@EventCallback.Factory.Create(this, () => { })" Text="Unbound Lambda" /> <InnerButton OnClick="@(() => { })" Text="Unbound Lambda" />
</div> </div>
<div id="unbound_lambda_nested"> <div id="unbound_lambda_nested">
<h3>Passing Unbound Lambda to Nested Button</h3> <h3>Passing Unbound Lambda to Nested Button</h3>
<MiddleButton OnClick="@EventCallback.Factory.Create(this, () => { })" Text="Unbound Lambda Nested" /> <MiddleButton OnClick="@(() => { })" Text="Unbound Lambda Nested" />
</div> </div>
<div id="unbound_lambda_strongly_typed"> <div id="unbound_lambda_strongly_typed">
<h3>Passing Capturing Lambda to Strongly Typed Button</h3> <h3>Passing Capturing Lambda to Strongly Typed Button</h3>
<StronglyTypedButton OnClick="@(EventCallback.Factory.Create<UIMouseEventArgs>(this, () => { GC.KeepAlive(this); }))" Text="Unbound Lambda Strongly-Typed" /> <StronglyTypedButton OnClick="@(() => { GC.KeepAlive(this); })" Text="Unbound Lambda Strongly-Typed" />
</div> </div>
<div id="unbound_lambda_child_content"> <div id="unbound_lambda_child_content">
<h3>Passing Child Content</h3> <h3>Passing Child Content</h3>
<TemplatedControl> <TemplatedControl>
<button onclick="@EventCallback.Factory.Create(this, () => { })">Unbound Lambda Child Content</button> <button onclick="@(() => { })">Unbound Lambda Child Content</button>
</TemplatedControl> </TemplatedControl>
</div> </div>
<div id="unbound_lambda_bind_to_component"> <div id="unbound_lambda_bind_to_component">
<h3>Passing Child Content</h3> <h3>Passing Child Content</h3>
<ButtonComponent Count="@buttonComponentCount" CountChanged="@(EventCallback.Factory.Create<int>(this, () => { }))" Text="Unbound Lambda Bind-To-Component" /> <ButtonComponent bind-Count="buttonComponentCount" Text="Unbound Lambda Bind-To-Component" />
</div> </div>
@functions { @functions {

View File

@ -1,7 +1,7 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
<EditForm Model="@this" OnValidSubmit="@(EventCallback.Factory.Create<EditContext>(this, HandleValidSubmit))" OnInvalidSubmit="@(EventCallback.Factory.Create<EditContext>(this, HandleInvalidSubmit))"> <EditForm Model="@this" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<p class="user-name"> <p class="user-name">

View File

@ -1,34 +1,34 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
<EditForm Model="@person" OnValidSubmit="@(EventCallback.Factory.Create<EditContext>(this, HandleValidSubmit))"> <EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<p class="name"> <p class="name">
Name: <InputText bind-Value="@person.Name" ValueExpression="@(() => person.Name)" /> Name: <InputText bind-Value="@person.Name" />
</p> </p>
<p class="email"> <p class="email">
Email: <InputText bind-Value="@person.Email" ValueExpression="@(() => person.Email)" /> Email: <InputText bind-Value="@person.Email" />
<ValidationMessage For="@(() => person.Email)" /> <ValidationMessage For="@(() => person.Email)" />
</p> </p>
<p class="age"> <p class="age">
Age (years): <InputNumber bind-Value="@person.AgeInYears" ValueExpression="@(() => person.AgeInYears)" /> Age (years): <InputNumber bind-Value="@person.AgeInYears" />
</p> </p>
<p class="height"> <p class="height">
Height (optional): <InputNumber bind-Value="@person.OptionalHeight" ValueExpression="@(() => person.OptionalHeight)" /> Height (optional): <InputNumber bind-Value="@person.OptionalHeight" />
</p> </p>
<p class="description"> <p class="description">
Description: <InputTextArea bind-Value="@person.Description" ValueExpression="@(() => person.Description)" /> Description: <InputTextArea bind-Value="@person.Description" />
</p> </p>
<p class="renewal-date"> <p class="renewal-date">
Renewal date: <InputDate bind-Value="@person.RenewalDate" ValueExpression="@(() => person.RenewalDate)" /> Renewal date: <InputDate bind-Value="@person.RenewalDate" />
</p> </p>
<p class="expiry-date"> <p class="expiry-date">
Expiry date (optional): <InputDate bind-Value="@person.OptionalExpiryDate" ValueExpression="@(() => person.OptionalExpiryDate)" /> Expiry date (optional): <InputDate bind-Value="@person.OptionalExpiryDate" />
</p> </p>
<p class="ticket-class"> <p class="ticket-class">
Ticket class: Ticket class:
<InputSelect bind-Value="@person.TicketClass" ValueExpression="@(() => person.TicketClass)"> <InputSelect bind-Value="@person.TicketClass">
<option>(select)</option> <option>(select)</option>
<option value="@TicketClass.Economy">Economy class</option> <option value="@TicketClass.Economy">Economy class</option>
<option value="@TicketClass.Premium">Premium class</option> <option value="@TicketClass.Premium">Premium class</option>
@ -36,7 +36,7 @@
</InputSelect> </InputSelect>
</p> </p>
<p class="accepts-terms"> <p class="accepts-terms">
Accepts terms: <InputCheckbox bind-Value="@person.AcceptsTerms" ValueExpression="@(() => person.AcceptsTerms)" /> Accepts terms: <InputCheckbox bind-Value="@person.AcceptsTerms" />
</p> </p>
<button type="submit">Submit</button> <button type="submit">Submit</button>