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)
{
// 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
{
@ -391,6 +392,12 @@ namespace Microsoft.AspNetCore.Blazor.Razor
// We generally expect all children to be CSharp, this is here just in case.
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)

View File

@ -80,6 +80,21 @@ namespace Microsoft.AspNetCore.Blazor.Razor
RewriteChildren(_source, node);
}
}
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)
{

View File

@ -409,5 +409,38 @@ namespace Test
GetFrames((RenderFragment)innerFrames[1].AttributeValue),
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
var generated = CompileToCSharp(@"
@addTagHelper *, TestAssembly
@page ""/""
<h1>Hello, world!</h1>
@ -437,6 +438,7 @@ Welcome to your new app.
// Assert
AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
CompileToAssembly(generated);
}
[Fact]

View File

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

View File

@ -31,7 +31,6 @@ global::System.Object __typeHelper = "/";
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
__o = ;
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
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
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
private void __RazorDirectiveTokenHelpers__() {
((System.Action)(() => {
global::System.Object __typeHelper = "*, TestAssembly";
}
))();
((System.Action)(() => {
global::System.Object __typeHelper = "/";
}
))();
@ -27,6 +31,9 @@ global::System.Object __typeHelper = "/";
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => {
}
));
}
#pragma warning restore 1998
}

View File

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

View File

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