From b45cad2117488662f3d22d93665b9d1fa4f81e79 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Tue, 22 May 2018 11:34:31 -0700 Subject: [PATCH] Fix #784 - allow complex content for HTML The logic that binds event handlers was interfering with the code that prevents component properties from receiving complex content. This check was a little overzealous. --- .../ComplexAttributeContentPass.cs | 9 ++-- .../ComponentRenderingRazorIntegrationTest.cs | 31 ++++++++++++- .../DesignTimeCodeGenerationTest.cs | 25 ++++++++++- .../RuntimeCodeGenerationTest.cs | 25 ++++++++++- .../Regression_784/TestComponent.codegen.cs | 45 +++++++++++++++++++ .../Regression_784/TestComponent.ir.txt | 40 +++++++++++++++++ .../Regression_784/TestComponent.mappings.txt | 27 +++++++++++ .../Regression_784/TestComponent.codegen.cs | 36 +++++++++++++++ .../Regression_784/TestComponent.ir.txt | 27 +++++++++++ .../Regression_784/TestComponent.mappings.txt | 17 +++++++ 10 files changed, 275 insertions(+), 7 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.ir.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.ir.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/ComplexAttributeContentPass.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/ComplexAttributeContentPass.cs index 1b3a4efff..641170ba2 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/ComplexAttributeContentPass.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/ComplexAttributeContentPass.cs @@ -1,6 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Linq; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -31,7 +32,7 @@ private void ProcessAttributes(TagHelperIntermediateNode node) { if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode) { - if (HasComplexChildContent(propertyNode)) + if (TrySimplifyContent(propertyNode) && node.TagHelpers.Any(t => t.IsComponentTagHelper())) { node.Diagnostics.Add(BlazorDiagnosticFactory.Create_UnsupportedComplexContent( propertyNode, @@ -42,7 +43,7 @@ private void ProcessAttributes(TagHelperIntermediateNode node) } else if (node.Children[i] is TagHelperHtmlAttributeIntermediateNode htmlNode) { - if (HasComplexChildContent(htmlNode)) + if (TrySimplifyContent(htmlNode) && node.TagHelpers.Any(t => t.IsComponentTagHelper())) { node.Diagnostics.Add(BlazorDiagnosticFactory.Create_UnsupportedComplexContent( htmlNode, @@ -54,7 +55,7 @@ private void ProcessAttributes(TagHelperIntermediateNode node) } } - private static bool HasComplexChildContent(IntermediateNode node) + private static bool TrySimplifyContent(IntermediateNode node) { if (node.Children.Count == 1 && node.Children[0] is HtmlAttributeIntermediateNode htmlNode && diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/ComponentRenderingRazorIntegrationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/ComponentRenderingRazorIntegrationTest.cs index e32d059e1..1fa64aeea 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/ComponentRenderingRazorIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/ComponentRenderingRazorIntegrationTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -442,5 +442,34 @@ public class SurveyPrompt : BlazorComponent frame => AssertFrame.Component(frame, "Test.SurveyPrompt", 2, 0), frame => AssertFrame.Attribute(frame, "Title", "
Test!
", 1)); } + + + [Fact] + public void Regression_784() + { + // Arrange + + // Act + var component = CompileToComponent(@" +

+@functions { + public string ParentBgColor { get; set; } = ""#FFFFFF""; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +} +"); + + // Act + var frames = GetRenderTree(component); + + // Assert + Assert.Collection( + frames, + frame => AssertFrame.Element(frame, "p", 3, 0), + frame => AssertFrame.Attribute(frame, "onmouseover", 1), + frame => AssertFrame.Attribute(frame, "style", "background: #FFFFFF;", 2)); + } } } diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs index 88037c1d7..6b359d3ac 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq; @@ -441,6 +441,29 @@ public class SurveyPrompt : BlazorComponent CompileToAssembly(generated); } + [Fact] + public void Regression_784() + { + // Arrange + + // Act + var generated = CompileToCSharp(@" +

+@functions { + public string ParentBgColor { get; set; } = ""#FFFFFF""; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [Fact] public void BindToComponent_SpecifiesValue_WithMatchingProperties() { diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs index a1674e3ec..3278500a9 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq; @@ -693,6 +693,29 @@ public class SurveyPrompt : BlazorComponent CompileToAssembly(generated); } + [Fact] + public void Regression_784() + { + // Arrange + + // Act + var generated = CompileToCSharp(@" +

+@functions { + public string ParentBgColor { get; set; } = ""#FFFFFF""; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +} +"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [Fact] public void BindToComponent_SpecifiesValue_WithMatchingProperties() { diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs new file mode 100644 index 000000000..ef3954362 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs @@ -0,0 +1,45 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Blazor; + using Microsoft.AspNetCore.Blazor.Components; + public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent + { + #pragma warning disable 219 + private void __RazorDirectiveTokenHelpers__() { + } + #pragma warning restore 219 + #pragma warning disable 0414 + private static System.Object __o = null; + #pragma warning restore 0414 + #pragma warning disable 1998 + protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) + { + base.BuildRenderTree(builder); + __o = Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue(OnComponentHover); +#line 1 "x:\dir\subdir\Test\TestComponent.cshtml" + __o = ParentBgColor; + +#line default +#line hidden + } + #pragma warning restore 1998 +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } + +#line default +#line hidden + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.ir.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.ir.txt new file mode 100644 index 000000000..ec6d1a0a0 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.ir.txt @@ -0,0 +1,40 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [12] ) - System + UsingDirective - (18:2,1 [32] ) - System.Collections.Generic + UsingDirective - (53:3,1 [17] ) - System.Linq + UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks + UsingDirective - (104:5,1 [33] ) - Microsoft.AspNetCore.Blazor + UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components + ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent - + DesignTimeDirective - + DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor" + DirectiveToken - (14:0,14 [9] ) - "*, Test" + CSharpCode - + IntermediateToken - - CSharp - #pragma warning disable 0414 + CSharpCode - + IntermediateToken - - CSharp - private static System.Object __o = null; + CSharpCode - + IntermediateToken - - CSharp - #pragma warning restore 0414 + MethodDeclaration - - protected override - void - BuildRenderTree + CSharpCode - + IntermediateToken - - CSharp - base.BuildRenderTree(builder); + HtmlElement - (0:0,0 [73] x:\dir\subdir\Test\TestComponent.cshtml) - p + HtmlAttribute - (16:0,16 [17] x:\dir\subdir\Test\TestComponent.cshtml) - onmouseover=" - " + CSharpExpressionAttributeValue - - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue( + IntermediateToken - (17:0,17 [16] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - OnComponentHover + IntermediateToken - - CSharp - ) + HtmlAttribute - - style=" - " + HtmlAttributeValue - (42:0,42 [11] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (42:0,42 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - background: + CSharpExpressionAttributeValue - (53:0,53 [15] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (55:0,55 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentBgColor + HtmlAttributeValue - (68:0,68 [1] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (68:0,68 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ; + HtmlContent - (73:0,73 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (73:0,73 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + HtmlContent - (220:7,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (220:7,1 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + CSharpCode - (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentBgColor { get; set; } = "#FFFFFF";\n\n public void OnComponentHover(UIMouseEventArgs e)\n {\n }\n diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt new file mode 100644 index 000000000..ef9ed398e --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt @@ -0,0 +1,27 @@ +Source Location: (17:0,17 [16] x:\dir\subdir\Test\TestComponent.cshtml) +|OnComponentHover| +Generated Location: (1005:24,136 [16] ) +|OnComponentHover| + +Source Location: (55:0,55 [13] x:\dir\subdir\Test\TestComponent.cshtml) +|ParentBgColor| +Generated Location: (1131:26,55 [13] ) +|ParentBgColor| + +Source Location: (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) +| + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +| +Generated Location: (1290:33,12 [132] ) +| + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +| + diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs new file mode 100644 index 000000000..8e74e6311 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.codegen.cs @@ -0,0 +1,36 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Blazor; + using Microsoft.AspNetCore.Blazor.Components; + public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent + { + #pragma warning disable 1998 + protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) + { + base.BuildRenderTree(builder); + builder.OpenElement(0, "p"); + builder.AddAttribute(1, "onmouseover", Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue(OnComponentHover)); + builder.AddAttribute(2, "style", "background:" + " " + (ParentBgColor) + ";"); + builder.CloseElement(); + } + #pragma warning restore 1998 +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } + +#line default +#line hidden + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.ir.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.ir.txt new file mode 100644 index 000000000..a3fc81907 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.ir.txt @@ -0,0 +1,27 @@ +Document - + NamespaceDeclaration - - Test + UsingDirective - (3:1,1 [14] ) - System + UsingDirective - (18:2,1 [34] ) - System.Collections.Generic + UsingDirective - (53:3,1 [19] ) - System.Linq + UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks + UsingDirective - (104:5,1 [35] ) - Microsoft.AspNetCore.Blazor + UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components + ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent - + MethodDeclaration - - protected override - void - BuildRenderTree + CSharpCode - + IntermediateToken - - CSharp - base.BuildRenderTree(builder); + HtmlElement - (0:0,0 [73] x:\dir\subdir\Test\TestComponent.cshtml) - p + HtmlAttribute - (16:0,16 [17] x:\dir\subdir\Test\TestComponent.cshtml) - onmouseover=" - " + CSharpExpressionAttributeValue - - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue( + IntermediateToken - (17:0,17 [16] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - OnComponentHover + IntermediateToken - - CSharp - ) + HtmlAttribute - - style=" - " + HtmlAttributeValue - (42:0,42 [11] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (42:0,42 [11] x:\dir\subdir\Test\TestComponent.cshtml) - Html - background: + CSharpExpressionAttributeValue - (53:0,53 [15] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (55:0,55 [13] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentBgColor + HtmlAttributeValue - (68:0,68 [1] x:\dir\subdir\Test\TestComponent.cshtml) - + IntermediateToken - (68:0,68 [1] x:\dir\subdir\Test\TestComponent.cshtml) - Html - ; + CSharpCode - (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentBgColor { get; set; } = "#FFFFFF";\n\n public void OnComponentHover(UIMouseEventArgs e)\n {\n }\n diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt new file mode 100644 index 000000000..f0d4f820c --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/Regression_784/TestComponent.mappings.txt @@ -0,0 +1,17 @@ +Source Location: (87:1,12 [132] x:\dir\subdir\Test\TestComponent.cshtml) +| + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +| +Generated Location: (1074:24,12 [132] ) +| + public string ParentBgColor { get; set; } = "#FFFFFF"; + + public void OnComponentHover(UIMouseEventArgs e) + { + } +| +