DefaultRazorIRLoweringPhase is too agressive
This change fixes a bug where DefaultRazorIRLoweringPhase is too
aggressive in merging HTML spans. You can hit the bug by delimiting two
html spans with a metacode character like:
<foo>@{ <bar/> }</foo>
The lowering phase will combine these HTML nodes, which is invalid as they
don't have contiguous spans.
The change here is to merge spans only when they both have an invalid
location or are contiguous.
This commit is contained in:
parent
7a1a6dd1d6
commit
e35ee53ee5
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Evolution
|
||||
{
|
||||
|
|
@ -176,16 +177,21 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
_builder.Pop();
|
||||
}
|
||||
|
||||
protected SourceSpan BuildSourceSpanFromNode(SyntaxTreeNode node)
|
||||
protected SourceSpan? BuildSourceSpanFromNode(SyntaxTreeNode node)
|
||||
{
|
||||
var location = node.Start;
|
||||
var sourceRange = new SourceSpan(
|
||||
if (location == SourceLocation.Undefined)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var span = new SourceSpan(
|
||||
node.Start.FilePath ?? Filename,
|
||||
node.Start.AbsoluteIndex,
|
||||
node.Start.LineIndex,
|
||||
node.Start.CharacterIndex,
|
||||
node.Length);
|
||||
return sourceRange;
|
||||
return span;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +233,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MainSourceVisitor : LoweringVisitor
|
||||
{
|
||||
private DeclareTagHelperFieldsIRNode _tagHelperFields;
|
||||
|
|
@ -399,27 +405,43 @@ namespace Microsoft.AspNetCore.Razor.Evolution
|
|||
if (currentChildren.Count > 0 && currentChildren[currentChildren.Count - 1] is HtmlContentIRNode)
|
||||
{
|
||||
var existingHtmlContent = (HtmlContentIRNode)currentChildren[currentChildren.Count - 1];
|
||||
existingHtmlContent.Content = string.Concat(existingHtmlContent.Content, span.Content);
|
||||
|
||||
if (existingHtmlContent.Source != null)
|
||||
var source = BuildSourceSpanFromNode(span);
|
||||
if (existingHtmlContent.Source == null && source == null)
|
||||
{
|
||||
var contentLength = existingHtmlContent.Source.Value.Length + span.Content.Length;
|
||||
Combine(existingHtmlContent, span);
|
||||
return;
|
||||
}
|
||||
|
||||
existingHtmlContent.Source = new SourceSpan(
|
||||
existingHtmlContent.Source.Value.FilePath ?? Filename,
|
||||
existingHtmlContent.Source.Value.AbsoluteIndex,
|
||||
existingHtmlContent.Source.Value.LineIndex,
|
||||
existingHtmlContent.Source.Value.CharacterIndex,
|
||||
contentLength);
|
||||
if (source != null &&
|
||||
existingHtmlContent.Source != null &&
|
||||
existingHtmlContent.Source.Value.FilePath == source.Value.FilePath &&
|
||||
existingHtmlContent.Source.Value.AbsoluteIndex + existingHtmlContent.Source.Value.Length == source.Value.AbsoluteIndex)
|
||||
{
|
||||
Combine(existingHtmlContent, span);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
_builder.Add(new HtmlContentIRNode()
|
||||
{
|
||||
_builder.Add(new HtmlContentIRNode()
|
||||
{
|
||||
Content = span.Content,
|
||||
Source = BuildSourceSpanFromNode(span),
|
||||
});
|
||||
Content = span.Content,
|
||||
Source = BuildSourceSpanFromNode(span),
|
||||
});
|
||||
}
|
||||
private void Combine(HtmlContentIRNode node, Span span)
|
||||
{
|
||||
node.Content = node.Content + span.Content;
|
||||
if (node.Source != null)
|
||||
{
|
||||
Debug.Assert(node.Source.Value.FilePath != null);
|
||||
|
||||
node.Source = new SourceSpan(
|
||||
node.Source.Value.FilePath,
|
||||
node.Source.Value.AbsoluteIndex,
|
||||
node.Source.Value.LineIndex,
|
||||
node.Source.Value.CharacterIndex,
|
||||
node.Content.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests.TestFiles
|
|||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n <p>Basic Asynchronous Statement Nested: <b>");
|
||||
WriteLiteral("</p>\r\n <p>Basic Asynchronous Statement Nested: ");
|
||||
WriteLiteral(" <b>");
|
||||
#line 13 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await.cshtml"
|
||||
Write(await Foo());
|
||||
|
||||
|
|
@ -70,7 +71,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests.TestFiles
|
|||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("</p>\r\n <p>Advanced Asynchronous Statement Nested: <b>");
|
||||
WriteLiteral("</p>\r\n <p>Advanced Asynchronous Statement Nested: ");
|
||||
WriteLiteral(" <b>");
|
||||
#line 24 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await.cshtml"
|
||||
Write(await Foo(boolValue: false));
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,18 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests.TestFiles
|
|||
#pragma warning disable 1998
|
||||
public async System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n <p class=\"Hello World\" ");
|
||||
WriteLiteral("\r\n<");
|
||||
WriteLiteral("div class=\"randomNonTagHelperAttribute\">\r\n <");
|
||||
WriteLiteral("p class=\"Hello World\" ");
|
||||
#line 4 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EscapedTagHelpers.cshtml"
|
||||
Write(DateTime.Now);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(">\r\n <input type=\"text\" />\r\n <em>Not a TagHelper: </em> ");
|
||||
WriteLiteral(">\r\n <");
|
||||
WriteLiteral("input type=\"text\" />\r\n <");
|
||||
WriteLiteral("em>Not a TagHelper: </");
|
||||
WriteLiteral("em> ");
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "test", async() => {
|
||||
}
|
||||
);
|
||||
|
|
@ -66,7 +71,9 @@ __TestNamespace_InputTagHelper2.Checked = true;
|
|||
}
|
||||
Write(__tagHelperExecutionContext.Output);
|
||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||
WriteLiteral("\r\n </p>\r\n</div>");
|
||||
WriteLiteral("\r\n </");
|
||||
WriteLiteral("p>\r\n</");
|
||||
WriteLiteral("div>");
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests.TestFiles
|
|||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral(" Hello, World\r\n <p>Hello, World</p>\r\n");
|
||||
WriteLiteral(" ");
|
||||
WriteLiteral("Hello, World\r\n <p>Hello, World</p>\r\n");
|
||||
WriteLiteral("\r\n");
|
||||
#line 8 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented.cshtml"
|
||||
while(i <= 10) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests.TestFiles
|
|||
#pragma warning disable 1998
|
||||
public async System.Threading.Tasks.Task ExecuteAsync()
|
||||
{
|
||||
WriteLiteral("\r\n<p>This should be shown</p>\r\n\r\n");
|
||||
WriteLiteral("\r\n<p>This should ");
|
||||
WriteLiteral(" be shown</p>\r\n\r\n");
|
||||
#line 5 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml"
|
||||
|
||||
Exception foo =
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ WriteTo(__razor_template_writer, item);
|
|||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteralTo(__razor_template_writer, " <ul>\r\n <li>Child Items... ?</li>\r\n </ul>\r\n </li>");
|
||||
WriteLiteralTo(__razor_template_writer, " <ul>\r\n <li>Child Items... ?</li>\r\n");
|
||||
WriteLiteralTo(__razor_template_writer, " </ul>\r\n </li>");
|
||||
}
|
||||
)));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue