Fix #773 (for real this time)

The problem is that the new HTML rewrite pass was traversing into
attributes of all kinds and would turn any HTML content inside those
attributes into elements where possible. The solution is to not do
that.
This commit is contained in:
Ryan Nowak 2018-05-14 09:59:13 -07:00
parent 3142217bec
commit e4cf7a6d3e
14 changed files with 110 additions and 31 deletions

View File

@ -355,7 +355,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor
else if (node.Children.Count == 1 && node.Children[0] is HtmlContentIntermediateNode htmlNode) else if (node.Children.Count == 1 && node.Children[0] is HtmlContentIntermediateNode htmlNode)
{ {
// This is how string attributes are lowered by default, a single HTML node with a single HTML token. // This is how string attributes are lowered by default, a single HTML node with a single HTML token.
context.CodeWriter.WriteStringLiteral(((IntermediateToken)htmlNode.Children[0]).Content); var content = string.Join(string.Empty, GetHtmlTokens(htmlNode).Select(t => t.Content));
context.CodeWriter.WriteStringLiteral(content);
} }
else else
{ {
@ -391,6 +392,12 @@ namespace Microsoft.AspNetCore.Blazor.Razor
// We generally expect all children to be CSharp, this is here just in case. // We generally expect all children to be CSharp, this is here just in case.
return attribute.FindDescendantNodes<IntermediateToken>().Where(t => t.IsCSharp).ToArray(); return attribute.FindDescendantNodes<IntermediateToken>().Where(t => t.IsCSharp).ToArray();
} }
IReadOnlyList<IntermediateToken> GetHtmlTokens(HtmlContentIntermediateNode html)
{
// We generally expect all children to be HTML, this is here just in case.
return html.FindDescendantNodes<IntermediateToken>().Where(t => t.IsHtml).ToArray();
}
} }
public override void WriteReferenceCapture(CodeRenderingContext context, RefExtensionNode node) public override void WriteReferenceCapture(CodeRenderingContext context, RefExtensionNode node)

View File

@ -81,6 +81,21 @@ namespace Microsoft.AspNetCore.Blazor.Razor
} }
} }
public override void VisitHtmlAttribute(HtmlAttributeIntermediateNode node)
{
// Don't rewrite inside of attributes
}
public override void VisitTagHelperHtmlAttribute(TagHelperHtmlAttributeIntermediateNode node)
{
// Don't rewrite inside of attributes
}
public override void VisitTagHelperProperty(TagHelperPropertyIntermediateNode node)
{
// Don't rewrite inside of attributes
}
private void RewriteChildren(RazorSourceDocument source, IntermediateNode node) private void RewriteChildren(RazorSourceDocument source, IntermediateNode node)
{ {
// We expect all of the immediate children of a node (together) to comprise // We expect all of the immediate children of a node (together) to comprise

View File

@ -409,5 +409,38 @@ namespace Test
GetFrames((RenderFragment)innerFrames[1].AttributeValue), GetFrames((RenderFragment)innerFrames[1].AttributeValue),
frame => AssertFrame.Text(frame, "Some text", 4)); frame => AssertFrame.Text(frame, "Some text", 4));
} }
[Fact] // https://github.com/aspnet/Blazor/issues/773
public void Regression_773()
{
// Arrange
AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Blazor.Components;
namespace Test
{
public class SurveyPrompt : BlazorComponent
{
[Parameter] private string Title { get; set; }
}
}
"));
var component = CompileToComponent(@"
@addTagHelper *, TestAssembly
@page ""/""
<SurveyPrompt Title=""<div>Test!</div>"" />
");
// Act
var frames = GetRenderTree(component);
// Assert
Assert.Collection(
frames,
frame => AssertFrame.Component(frame, "Test.SurveyPrompt", 2, 0),
frame => AssertFrame.Attribute(frame, "Title", "<div>Test!</div>", 1));
}
} }
} }

View File

@ -425,6 +425,7 @@ namespace Test
// Act // Act
var generated = CompileToCSharp(@" var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@page ""/"" @page ""/""
<h1>Hello, world!</h1> <h1>Hello, world!</h1>
@ -437,6 +438,7 @@ Welcome to your new app.
// Assert // Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
} }
[Fact] [Fact]

View File

@ -660,6 +660,8 @@ Welcome to your new app.
[Fact] // https://github.com/aspnet/Blazor/issues/773 [Fact] // https://github.com/aspnet/Blazor/issues/773
public void Regression_773() public void Regression_773()
{ {
GenerateBaselines = true;
// Arrange // Arrange
AdditionalSyntaxTrees.Add(Parse(@" AdditionalSyntaxTrees.Add(Parse(@"
using Microsoft.AspNetCore.Blazor.Components; using Microsoft.AspNetCore.Blazor.Components;
@ -675,6 +677,7 @@ namespace Test
// Act // Act
var generated = CompileToCSharp(@" var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@page ""/"" @page ""/""
<h1>Hello, world!</h1> <h1>Hello, world!</h1>
@ -687,6 +690,7 @@ Welcome to your new app.
// Assert // Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
} }
[Fact] [Fact]

View File

@ -31,7 +31,6 @@ global::System.Object __typeHelper = "/";
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{ {
base.BuildRenderTree(builder); base.BuildRenderTree(builder);
__o = ;
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => { builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
} }
)); ));

View File

@ -33,3 +33,5 @@ Document -
IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n
ComponentExtensionNode - (98:7,0 [23] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt ComponentExtensionNode - (98:7,0 [23] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt
ComponentAttributeExtensionNode - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title ComponentAttributeExtensionNode - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title
HtmlContent - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Html -

View File

@ -15,6 +15,10 @@ namespace Test
#pragma warning disable 219 #pragma warning disable 219
private void __RazorDirectiveTokenHelpers__() { private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => { ((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
((System.Action)(() => {
global::System.Object __typeHelper = "/"; global::System.Object __typeHelper = "/";
} }
))(); ))();
@ -27,6 +31,9 @@ global::System.Object __typeHelper = "/";
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{ {
base.BuildRenderTree(builder); base.BuildRenderTree(builder);
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
} }
#pragma warning restore 1998 #pragma warning restore 1998
} }

View File

@ -11,7 +11,8 @@ Document -
DesignTimeDirective - DesignTimeDirective -
DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor" DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor"
DirectiveToken - (14:0,14 [9] ) - "*, Test" DirectiveToken - (14:0,14 [9] ) - "*, Test"
DirectiveToken - (6:0,6 [3] x:\dir\subdir\Test\TestComponent.cshtml) - "/" DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly
DirectiveToken - (37:1,6 [3] x:\dir\subdir\Test\TestComponent.cshtml) - "/"
CSharpCode - CSharpCode -
IntermediateToken - - CSharp - #pragma warning disable 0414 IntermediateToken - - CSharp - #pragma warning disable 0414
CSharpCode - CSharpCode -
@ -21,16 +22,18 @@ Document -
MethodDeclaration - - protected override - void - BuildRenderTree MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode - CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder); IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlContent - (11:1,0 [2] x:\dir\subdir\Test\TestComponent.cshtml) HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (11:1,0 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
HtmlElement - (13:2,0 [22] x:\dir\subdir\Test\TestComponent.cshtml) - h1 HtmlContent - (42:2,0 [2] x:\dir\subdir\Test\TestComponent.cshtml)
HtmlContent - (17:2,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) IntermediateToken - (42:2,0 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
IntermediateToken - (17:2,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello, world! HtmlElement - (44:3,0 [22] x:\dir\subdir\Test\TestComponent.cshtml) - h1
HtmlContent - (35:2,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) HtmlContent - (48:3,4 [13] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (35:2,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n IntermediateToken - (48:3,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello, world!
HtmlElement - (67:6,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - surveyprompt HtmlContent - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml)
HtmlAttribute - - - IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n
HtmlAttributeValue - - ComponentExtensionNode - (98:7,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt
IntermediateToken - - Html - <div>Test!</div> ComponentAttributeExtensionNode - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title
HtmlContent - (108:6,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) HtmlContent - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (108:6,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n IntermediateToken - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <div>Test!</div>
HtmlContent - (139:7,41 [2] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (139:7,41 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n

View File

@ -1,5 +1,10 @@
Source Location: (6:0,6 [3] x:\dir\subdir\Test\TestComponent.cshtml) Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml)
|*, TestAssembly|
Generated Location: (625:17,38 [15] )
|*, TestAssembly|
Source Location: (37:1,6 [3] x:\dir\subdir\Test\TestComponent.cshtml)
|"/"| |"/"|
Generated Location: (624:17,37 [3] ) Generated Location: (741:21,37 [3] )
|"/"| |"/"|

View File

@ -21,7 +21,7 @@ namespace Test
builder.CloseElement(); builder.CloseElement();
builder.AddContent(2, "\n\nWelcome to your new app.\n\n"); builder.AddContent(2, "\n\nWelcome to your new app.\n\n");
builder.OpenComponent<Test.SurveyPrompt>(3); builder.OpenComponent<Test.SurveyPrompt>(3);
builder.AddAttribute(4, "Title", ); builder.AddAttribute(4, "Title", "");
builder.CloseComponent(); builder.CloseComponent();
} }
#pragma warning restore 1998 #pragma warning restore 1998

View File

@ -18,3 +18,5 @@ Document -
IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n
ComponentExtensionNode - (98:7,0 [23] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt ComponentExtensionNode - (98:7,0 [23] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt
ComponentAttributeExtensionNode - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title ComponentAttributeExtensionNode - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title
HtmlContent - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (119:7,21 [0] x:\dir\subdir\Test\TestComponent.cshtml) - Html -

View File

@ -20,9 +20,9 @@ namespace Test
builder.AddContent(1, "Hello, world!"); builder.AddContent(1, "Hello, world!");
builder.CloseElement(); builder.CloseElement();
builder.AddContent(2, "\n\nWelcome to your new app.\n\n"); builder.AddContent(2, "\n\nWelcome to your new app.\n\n");
builder.OpenElement(3, "surveyprompt"); builder.OpenComponent<Test.SurveyPrompt>(3);
builder.AddAttribute(4, "title", "<div>Test!</div>"); builder.AddAttribute(4, "Title", "<div>Test!</div>");
builder.CloseElement(); builder.CloseComponent();
} }
#pragma warning restore 1998 #pragma warning restore 1998
} }

View File

@ -11,12 +11,12 @@ Document -
MethodDeclaration - - protected override - void - BuildRenderTree MethodDeclaration - - protected override - void - BuildRenderTree
CSharpCode - CSharpCode -
IntermediateToken - - CSharp - base.BuildRenderTree(builder); IntermediateToken - - CSharp - base.BuildRenderTree(builder);
HtmlElement - (13:2,0 [22] x:\dir\subdir\Test\TestComponent.cshtml) - h1 HtmlElement - (44:3,0 [22] x:\dir\subdir\Test\TestComponent.cshtml) - h1
HtmlContent - (17:2,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) HtmlContent - (48:3,4 [13] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (17:2,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello, world! IntermediateToken - (48:3,4 [13] x:\dir\subdir\Test\TestComponent.cshtml) - Html - Hello, world!
HtmlContent - (35:2,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) HtmlContent - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - (35:2,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n IntermediateToken - (66:3,22 [32] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\nWelcome to your new app.\n\n
HtmlElement - (67:6,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - surveyprompt ComponentExtensionNode - (98:7,0 [41] x:\dir\subdir\Test\TestComponent.cshtml) - SurveyPrompt - Test.SurveyPrompt
HtmlAttribute - - - ComponentAttributeExtensionNode - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml) - Title - Title
HtmlAttributeValue - - HtmlContent - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml)
IntermediateToken - - Html - <div>Test!</div> IntermediateToken - (119:7,21 [16] x:\dir\subdir\Test\TestComponent.cshtml) - Html - <div>Test!</div>