[Fixes #815] Fix Debug.Assert failure for malformed tags in expression

This commit is contained in:
Ajay Bhargav Baaskaran 2016-08-04 14:48:25 -07:00
parent f0f3832c14
commit 687b3f6911
2 changed files with 39 additions and 8 deletions

View File

@ -60,12 +60,12 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
public void Rewrite(RewritingContext context) public void Rewrite(RewritingContext context)
{ {
RewriteTags(context.SyntaxTree, context); RewriteTags(context.SyntaxTree, context, depth: 0);
context.SyntaxTree = _currentBlock.Build(); context.SyntaxTree = _currentBlock.Build();
} }
private void RewriteTags(Block input, RewritingContext context) private void RewriteTags(Block input, RewritingContext context, int depth)
{ {
// We want to start a new block without the children from existing (we rebuild them). // We want to start a new block without the children from existing (we rebuild them).
TrackBlock(new BlockBuilder TrackBlock(new BlockBuilder
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
// Non-TagHelper tag. // Non-TagHelper tag.
ValidateParentAllowsPlainTag(childBlock, context.ErrorSink); ValidateParentAllowsPlainTag(childBlock, context.ErrorSink);
TrackTagBlock(childBlock); TrackTagBlock(childBlock, depth);
} }
// If we get to here it means that we're a normal html tag. No need to iterate any deeper into // If we get to here it means that we're a normal html tag. No need to iterate any deeper into
@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
else else
{ {
// We're not an Html tag so iterate through children recursively. // We're not an Html tag so iterate through children recursively.
RewriteTags(childBlock, context); RewriteTags(childBlock, context, depth + 1);
continue; continue;
} }
} }
@ -133,7 +133,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
BuildCurrentlyTrackedBlock(); BuildCurrentlyTrackedBlock();
} }
private void TrackTagBlock(Block childBlock) private void TrackTagBlock(Block childBlock, int depth)
{ {
var tagName = GetTagName(childBlock); var tagName = GetTagName(childBlock);
@ -148,6 +148,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
var parentTracker = _trackerStack.Count > 0 ? _trackerStack.Peek() : null; var parentTracker = _trackerStack.Count > 0 ? _trackerStack.Peek() : null;
if (parentTracker != null && if (parentTracker != null &&
!parentTracker.IsTagHelper && !parentTracker.IsTagHelper &&
depth == parentTracker.Depth &&
string.Equals(parentTracker.TagName, tagName, StringComparison.OrdinalIgnoreCase)) string.Equals(parentTracker.TagName, tagName, StringComparison.OrdinalIgnoreCase))
{ {
PopTrackerStack(); PopTrackerStack();
@ -157,7 +158,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
{ {
// If it's not a void element and it's not self-closing then we need to create a tag // If it's not a void element and it's not self-closing then we need to create a tag
// tracker for it. // tracker for it.
var tracker = new TagBlockTracker(tagName, isTagHelper: false); var tracker = new TagBlockTracker(tagName, isTagHelper: false, depth: depth);
PushTrackerStack(tracker); PushTrackerStack(tracker);
} }
} }
@ -802,15 +803,18 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
private class TagBlockTracker private class TagBlockTracker
{ {
public TagBlockTracker(string tagName, bool isTagHelper) public TagBlockTracker(string tagName, bool isTagHelper, int depth)
{ {
TagName = tagName; TagName = tagName;
IsTagHelper = isTagHelper; IsTagHelper = isTagHelper;
Depth = depth;
} }
public string TagName { get; } public string TagName { get; }
public bool IsTagHelper { get; } public bool IsTagHelper { get; }
public int Depth { get; }
} }
private class TagHelperBlockTracker : TagBlockTracker private class TagHelperBlockTracker : TagBlockTracker
@ -818,7 +822,7 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
private IEnumerable<string> _prefixedAllowedChildren; private IEnumerable<string> _prefixedAllowedChildren;
public TagHelperBlockTracker(TagHelperBlockBuilder builder) public TagHelperBlockTracker(TagHelperBlockBuilder builder)
: base(builder.TagName, isTagHelper: true) : base(builder.TagName, isTagHelper: true, depth: 0)
{ {
Builder = builder; Builder = builder;

View File

@ -4486,5 +4486,32 @@ namespace Microsoft.AspNetCore.Razor.Parser.TagHelpers.Internal
{ {
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div"); RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div");
} }
[Fact]
public void Rewrite_HandlesMalformedNestedNonTagHelperTags_Correctly()
{
var documentContent = "<div>@{</div>}";
var expectedOutput = new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("<div>")),
new StatementBlock(
Factory.CodeTransition(),
Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
new MarkupBlock(
new MarkupTagBlock(
Factory.Markup("</div>").Accepts(AcceptedCharacters.None))),
Factory.EmptyCSharp().AsStatement(),
Factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
Factory.EmptyHtml());
var expectedErrors = new[]
{
new RazorError(
"Encountered end tag \"div\" with no matching start tag. Are your start/end tags properly balanced?",
new SourceLocation(9, 0, 9),
3),
};
RunParseTreeRewriterTest(documentContent, expectedOutput, expectedErrors);
}
} }
} }