Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Moved AddTagHelperHtmlAttribute from renderer to writer
Browse files Browse the repository at this point in the history
  • Loading branch information
ajaybhargavb committed Apr 14, 2017
1 parent cf44f10 commit 0b17f14
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
Context.TagHelperWriter.WriteCreateTagHelper(Context, node);
}

public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
Context.TagHelperWriter.WriteAddTagHelperHtmlAttribute(Context, node);
}

public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
Context.TagHelperWriter.WriteExecuteTagHelpers(Context, node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public override void WriteDeclareTagHelperFields(CSharpRenderingContext context,

public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
{
throw new NotImplementedException();
context.RenderChildren(node);
}

public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class RuntimeBasicWriter : BasicWriter

public string WriteHtmlContentMethod { get; set; } = "WriteLiteral";

public string WriteAttributeValueMethod { get; set; } = "WriteAttributeValue";

public override void WriteCSharpExpression(CSharpRenderingContext context, CSharpExpressionIRNode node)
{
if (context == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,77 +278,6 @@ public override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedT
.WriteEndMethodInvocation();
}

public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);

// All simple text and minimized attributes will be pre-allocated.
if (isConditionalAttributeValue)
{
// Dynamic attribute value should be run through the conditional attribute removal system. It's
// unbound and contains C#.

// TagHelper attribute rendering is buffered by default. We do not want to write to the current
// writer.
var valuePieceCount = node.Children.Count(
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);

Context.Writer
.WriteStartMethodInvocation("BeginAddHtmlAttributeValues" /* ORIGINAL: BeginAddHtmlAttributeValuesMethodName */)
.Write("__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */)
.WriteParameterSeparator()
.WriteStringLiteral(node.Name)
.WriteParameterSeparator()
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.Write(attributeValueStyleParameter)
.WriteEndMethodInvocation();

var initialRenderingConventions = Context.RenderingConventions;
Context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(Context.Writer);
VisitDefault(node);
Context.RenderingConventions = initialRenderingConventions;

Context.Writer
.WriteMethodInvocation(
"EndAddHtmlAttributeValues" /* ORIGINAL: EndAddHtmlAttributeValuesMethodName */,
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */);
}
else
{
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
// determine its final value.

// Attribute value is not plain text, must be buffered to determine its final value.
Context.Writer.WriteMethodInvocation("BeginWriteTagHelperAttribute" /* ORIGINAL: BeginWriteTagHelperAttributeMethodName */);

// We're building a writing scope around the provided chunks which captures everything written from the
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
// ensure we capture all content that's written, directly or indirectly.
var initialRenderingConventions = Context.RenderingConventions;
Context.RenderingConventions = new CSharpRenderingConventions(Context.Writer);
VisitDefault(node);
Context.RenderingConventions = initialRenderingConventions;

Context.Writer
.WriteStartAssignment("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
.WriteMethodInvocation("EndWriteTagHelperAttribute" /* ORIGINAL: EndWriteTagHelperAttributeMethodName */)
.WriteStartInstanceMethodInvocation(
"__tagHelperExecutionContext" /* ORIGINAL: ExecutionContextVariableName */,
"AddHtmlAttribute" /* ORIGINAL: ExecutionContextAddHtmlAttributeMethodName */)
.WriteStringLiteral(node.Name)
.WriteParameterSeparator()
.WriteStartMethodInvocation("Html.Raw" /* ORIGINAL: MarkAsHtmlEncodedMethodName */)
.Write("__tagHelperStringValueBuffer" /* ORIGINAL: StringValueBufferVariableName */)
.WriteEndMethodInvocation(endLine: false)
.WriteParameterSeparator()
.Write(attributeValueStyleParameter)
.WriteEndMethodInvocation();
}
}

public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Intermediate;

namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
Expand All @@ -20,6 +22,8 @@ public class RuntimeTagHelperWriter : TagHelperWriter

public string ExecutionContextSetOutputContentAsyncMethodName { get; set; } = "SetOutputContentAsync";

public string ExecutionContextAddHtmlAttributeMethodName { get; set; } = "AddHtmlAttribute";

public string RunnerTypeName { get; set; } = "global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner";

public string RunnerVariableName { get; set; } = "__tagHelperRunner";
Expand All @@ -44,6 +48,16 @@ public class RuntimeTagHelperWriter : TagHelperWriter

public string TagHelperOutputIsContentModifiedPropertyName { get; set; } = "IsContentModified";

public string BeginAddHtmlAttributeValuesMethodName { get; set; } = "BeginAddHtmlAttributeValues";

public string EndAddHtmlAttributeValuesMethodName { get; set; } = "EndAddHtmlAttributeValues";

public string BeginWriteTagHelperAttributeMethodName { get; set; } = "BeginWriteTagHelperAttribute";

public string EndWriteTagHelperAttributeMethodName { get; set; } = "EndWriteTagHelperAttribute";

public string MarkAsHtmlEncodedMethodName { get; set; } = "Html.Raw";

public string WriteTagHelperOutputMethod { get; set; } = "Write";

public override void WriteDeclareTagHelperFields(CSharpRenderingContext context, DeclareTagHelperFieldsIRNode node)
Expand Down Expand Up @@ -127,7 +141,82 @@ public override void WriteDeclareTagHelperFields(CSharpRenderingContext context,

public override void WriteAddTagHelperHtmlAttribute(CSharpRenderingContext context, AddTagHelperHtmlAttributeIRNode node)
{
throw new NotImplementedException();
var attributeValueStyleParameter = $"global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.{node.ValueStyle}";
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);

// All simple text and minimized attributes will be pre-allocated.
if (isConditionalAttributeValue)
{
// Dynamic attribute value should be run through the conditional attribute removal system. It's
// unbound and contains C#.

// TagHelper attribute rendering is buffered by default. We do not want to write to the current
// writer.
var valuePieceCount = node.Children.Count(
child => child is HtmlAttributeValueIRNode || child is CSharpAttributeValueIRNode);

context.Writer
.WriteStartMethodInvocation(BeginAddHtmlAttributeValuesMethodName)
.Write(ExecutionContextVariableName)
.WriteParameterSeparator()
.WriteStringLiteral(node.Name)
.WriteParameterSeparator()
.Write(valuePieceCount.ToString(CultureInfo.InvariantCulture))
.WriteParameterSeparator()
.Write(attributeValueStyleParameter)
.WriteEndMethodInvocation();

// This can be removed once all the tag helper nodes are moved out of the renderers.
var initialRenderingConventions = context.RenderingConventions;
context.RenderingConventions = new TagHelperHtmlAttributeRenderingConventions(context.Writer);
using (context.Push(new TagHelperHtmlAttributeRuntimeBasicWriter()))
{
context.RenderChildren(node);
}
context.RenderingConventions = initialRenderingConventions;

context.Writer
.WriteMethodInvocation(
EndAddHtmlAttributeValuesMethodName,
ExecutionContextVariableName);
}
else
{
// This is a data-* attribute which includes C#. Do not perform the conditional attribute removal or
// other special cases used when IsDynamicAttributeValue(). But the attribute must still be buffered to
// determine its final value.

// Attribute value is not plain text, must be buffered to determine its final value.
context.Writer.WriteMethodInvocation(BeginWriteTagHelperAttributeMethodName);

// We're building a writing scope around the provided chunks which captures everything written from the
// page. Therefore, we do not want to write to any other buffer since we're using the pages buffer to
// ensure we capture all content that's written, directly or indirectly.
// This can be removed once all the tag helper nodes are moved out of the renderers.
var initialRenderingConventions = context.RenderingConventions;
context.RenderingConventions = new CSharpRenderingConventions(context.Writer);
using (context.Push(new RuntimeBasicWriter()))
using (context.Push(new RuntimeTagHelperWriter()))
{
context.RenderChildren(node);
}
context.RenderingConventions = initialRenderingConventions;

context.Writer
.WriteStartAssignment(StringValueBufferVariableName)
.WriteMethodInvocation(EndWriteTagHelperAttributeMethodName)
.WriteStartInstanceMethodInvocation(
ExecutionContextVariableName,
ExecutionContextAddHtmlAttributeMethodName)
.WriteStringLiteral(node.Name)
.WriteParameterSeparator()
.WriteStartMethodInvocation(MarkAsHtmlEncodedMethodName)
.Write(StringValueBufferVariableName)
.WriteEndMethodInvocation(endLine: false)
.WriteParameterSeparator()
.Write(attributeValueStyleParameter)
.WriteEndMethodInvocation();
}
}

public override void WriteCreateTagHelper(CSharpRenderingContext context, CreateTagHelperIRNode node)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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.

namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
{
internal class TagHelperHtmlAttributeRuntimeBasicWriter : RuntimeBasicWriter
{
// This will be used when HtmlAttributeValueIRNode and CSharpAttributeValueIRNode are moved to writers.
public new string WriteAttributeValueMethod { get; set; } = "AddHtmlAttributeValue";
}
}
Loading

0 comments on commit 0b17f14

Please sign in to comment.