Lazily initialize `TagHelperAttributeList`s.
- Not all `TagHelper`s have unbound HTML attributes or any attributes at all. A great example of this is MVC's input `TagHelper` which usually takes the format of `<input asp-for="..." />`. By lazily initializing we don't build extra attribute lists where not needed. - Moved `TagHelperContext` and `TagHelperOutput` creation to CreateX methods on `TagHelperExecutionContext`. #604
This commit is contained in:
parent
84ac19571c
commit
b7b3273fa4
|
|
@ -14,12 +14,17 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TagHelperExecutionContext
|
public class TagHelperExecutionContext
|
||||||
{
|
{
|
||||||
|
private readonly string _tagName;
|
||||||
|
private readonly string _uniqueId;
|
||||||
|
private readonly TagMode _tagMode;
|
||||||
private readonly List<ITagHelper> _tagHelpers;
|
private readonly List<ITagHelper> _tagHelpers;
|
||||||
private readonly Func<Task> _executeChildContentAsync;
|
private readonly Func<Task> _executeChildContentAsync;
|
||||||
private readonly Action<HtmlEncoder> _startTagHelperWritingScope;
|
private readonly Action<HtmlEncoder> _startTagHelperWritingScope;
|
||||||
private readonly Func<TagHelperContent> _endTagHelperWritingScope;
|
private readonly Func<TagHelperContent> _endTagHelperWritingScope;
|
||||||
private TagHelperContent _childContent;
|
private TagHelperContent _childContent;
|
||||||
private Dictionary<HtmlEncoder, TagHelperContent> _perEncoderChildContent;
|
private Dictionary<HtmlEncoder, TagHelperContent> _perEncoderChildContent;
|
||||||
|
private TagHelperAttributeList _htmlAttributes;
|
||||||
|
private TagHelperAttributeList _allAttributes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal for testing purposes only.
|
/// Internal for testing purposes only.
|
||||||
|
|
@ -93,19 +98,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
_startTagHelperWritingScope = startTagHelperWritingScope;
|
_startTagHelperWritingScope = startTagHelperWritingScope;
|
||||||
_endTagHelperWritingScope = endTagHelperWritingScope;
|
_endTagHelperWritingScope = endTagHelperWritingScope;
|
||||||
|
|
||||||
TagMode = tagMode;
|
_tagMode = tagMode;
|
||||||
HtmlAttributes = new TagHelperAttributeList();
|
_tagName = tagName;
|
||||||
AllAttributes = new TagHelperAttributeList();
|
|
||||||
TagName = tagName;
|
|
||||||
Items = items;
|
Items = items;
|
||||||
UniqueId = uniqueId;
|
_uniqueId = uniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the HTML syntax of the element in the Razor source.
|
|
||||||
/// </summary>
|
|
||||||
public TagMode TagMode { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if <see cref="GetChildContentAsync"/> has been called.
|
/// Indicates if <see cref="GetChildContentAsync"/> has been called.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -122,21 +120,6 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<object, object> Items { get; }
|
public IDictionary<object, object> Items { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// HTML attributes.
|
|
||||||
/// </summary>
|
|
||||||
public TagHelperAttributeList HtmlAttributes { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <see cref="ITagHelper"/> bound attributes and HTML attributes.
|
|
||||||
/// </summary>
|
|
||||||
public TagHelperAttributeList AllAttributes { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An identifier unique to the HTML element this context is for.
|
|
||||||
/// </summary>
|
|
||||||
public string UniqueId { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <see cref="ITagHelper"/>s that should be run.
|
/// <see cref="ITagHelper"/>s that should be run.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -148,16 +131,19 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The HTML tag name in the Razor source.
|
|
||||||
/// </summary>
|
|
||||||
public string TagName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ITagHelper"/>s' output.
|
/// The <see cref="ITagHelper"/>s' output.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TagHelperOutput Output { get; set; }
|
public TagHelperOutput Output { get; set; }
|
||||||
|
|
||||||
|
public TagHelperContext CreateTagHelperContext() =>
|
||||||
|
new TagHelperContext(_allAttributes, Items, _uniqueId);
|
||||||
|
public TagHelperOutput CreateTagHelperOutput() =>
|
||||||
|
new TagHelperOutput(_tagName, _htmlAttributes, GetChildContentAsync)
|
||||||
|
{
|
||||||
|
TagMode = _tagMode
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tracks the given <paramref name="tagHelper"/>.
|
/// Tracks the given <paramref name="tagHelper"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -183,9 +169,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
throw new ArgumentNullException(nameof(name));
|
throw new ArgumentNullException(nameof(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnsureHtmlAttributes();
|
||||||
|
EnsureAllAttributes();
|
||||||
|
|
||||||
var attribute = new TagHelperAttribute(name);
|
var attribute = new TagHelperAttribute(name);
|
||||||
HtmlAttributes.Add(attribute);
|
_htmlAttributes.Add(attribute);
|
||||||
AllAttributes.Add(attribute);
|
_allAttributes.Add(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -200,8 +189,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
throw new ArgumentNullException(nameof(name));
|
throw new ArgumentNullException(nameof(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
HtmlAttributes.Add(name, value);
|
EnsureHtmlAttributes();
|
||||||
AllAttributes.Add(name, value);
|
EnsureAllAttributes();
|
||||||
|
|
||||||
|
var attribute = new TagHelperAttribute(name, value);
|
||||||
|
_htmlAttributes.Add(attribute);
|
||||||
|
_allAttributes.Add(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -216,24 +209,13 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
throw new ArgumentNullException(nameof(name));
|
throw new ArgumentNullException(nameof(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
AllAttributes.Add(name, value);
|
EnsureAllAttributes();
|
||||||
|
|
||||||
|
_allAttributes.Add(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// Internal for testing.
|
||||||
/// Executes children asynchronously with the given <paramref name="encoder"/> in scope and returns their
|
internal async Task<TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
|
||||||
/// rendered content.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="useCachedResult">
|
|
||||||
/// If <c>true</c>, multiple calls with the same <see cref="HtmlEncoder"/> will not cause children to
|
|
||||||
/// re-execute; returns cached content.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="encoder">
|
|
||||||
/// The <see cref="HtmlEncoder"/> to use when the page handles
|
|
||||||
/// non-<see cref="Microsoft.AspNetCore.Html.IHtmlContent"/> C# expressions. If <c>null</c>, executes children with
|
|
||||||
/// the page's current <see cref="HtmlEncoder"/>.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A <see cref="Task"/> that on completion returns the rendered child content.</returns>
|
|
||||||
public async Task<TagHelperContent> GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder)
|
|
||||||
{
|
{
|
||||||
// Get cached content for this encoder.
|
// Get cached content for this encoder.
|
||||||
TagHelperContent childContent;
|
TagHelperContent childContent;
|
||||||
|
|
@ -272,5 +254,21 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
|
|
||||||
return new DefaultTagHelperContent().SetContent(childContent);
|
return new DefaultTagHelperContent().SetContent(childContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EnsureHtmlAttributes()
|
||||||
|
{
|
||||||
|
if (_htmlAttributes == null)
|
||||||
|
{
|
||||||
|
_htmlAttributes = new TagHelperAttributeList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureAllAttributes()
|
||||||
|
{
|
||||||
|
if (_allAttributes == null)
|
||||||
|
{
|
||||||
|
_allAttributes = new TagHelperAttributeList();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,10 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
throw new ArgumentNullException(nameof(executionContext));
|
throw new ArgumentNullException(nameof(executionContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagHelperContext = new TagHelperContext(
|
var tagHelperContext = executionContext.CreateTagHelperContext();
|
||||||
executionContext.AllAttributes,
|
|
||||||
executionContext.Items,
|
|
||||||
executionContext.UniqueId);
|
|
||||||
|
|
||||||
OrderTagHelpers(executionContext.TagHelpers);
|
OrderTagHelpers(executionContext.TagHelpers);
|
||||||
|
|
||||||
|
|
@ -39,13 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
executionContext.TagHelpers[i].Init(tagHelperContext);
|
executionContext.TagHelpers[i].Init(tagHelperContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagHelperOutput = new TagHelperOutput(
|
var tagHelperOutput = executionContext.CreateTagHelperOutput();
|
||||||
executionContext.TagName,
|
|
||||||
executionContext.HtmlAttributes,
|
|
||||||
executionContext.GetChildContentAsync)
|
|
||||||
{
|
|
||||||
TagMode = executionContext.TagMode,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < executionContext.TagHelpers.Count; i++)
|
for (var i = 0; i < executionContext.TagHelpers.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// <paramref name="attributes"/>.
|
/// <paramref name="attributes"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributes">The collection to wrap.</param>
|
/// <param name="attributes">The collection to wrap.</param>
|
||||||
public ReadOnlyTagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
|
public ReadOnlyTagHelperAttributeList(IList<TagHelperAttribute> attributes)
|
||||||
: base(new List<TagHelperAttribute>(attributes))
|
: base(attributes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,20 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributes">The collection to wrap.</param>
|
/// <param name="attributes">The collection to wrap.</param>
|
||||||
public TagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
|
public TagHelperAttributeList(IEnumerable<TagHelperAttribute> attributes)
|
||||||
|
: base (new List<TagHelperAttribute>(attributes))
|
||||||
|
{
|
||||||
|
if (attributes == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(attributes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a new instance of <see cref="TagHelperAttributeList"/> with the specified
|
||||||
|
/// <paramref name="attributes"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attributes">The collection to wrap.</param>
|
||||||
|
public TagHelperAttributeList(List<TagHelperAttribute> attributes)
|
||||||
: base(attributes)
|
: base(attributes)
|
||||||
{
|
{
|
||||||
if (attributes == null)
|
if (attributes == null)
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TagHelperContext
|
public class TagHelperContext
|
||||||
{
|
{
|
||||||
private ReadOnlyTagHelperAttributeList _allAttributes;
|
private static ReadOnlyTagHelperAttributeList EmptyAttributes = new TagHelperAttributeList();
|
||||||
private IEnumerable<TagHelperAttribute> _allAttributesData;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new <see cref="TagHelperContext"/>.
|
/// Instantiates a new <see cref="TagHelperContext"/>.
|
||||||
|
|
@ -22,15 +21,10 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
|
/// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
|
||||||
/// applies to.</param>
|
/// applies to.</param>
|
||||||
public TagHelperContext(
|
public TagHelperContext(
|
||||||
IEnumerable<TagHelperAttribute> allAttributes,
|
ReadOnlyTagHelperAttributeList allAttributes,
|
||||||
IDictionary<object, object> items,
|
IDictionary<object, object> items,
|
||||||
string uniqueId)
|
string uniqueId)
|
||||||
{
|
{
|
||||||
if (allAttributes == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(allAttributes));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items == null)
|
if (items == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(items));
|
throw new ArgumentNullException(nameof(items));
|
||||||
|
|
@ -41,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
throw new ArgumentNullException(nameof(uniqueId));
|
throw new ArgumentNullException(nameof(uniqueId));
|
||||||
}
|
}
|
||||||
|
|
||||||
_allAttributesData = allAttributes;
|
AllAttributes = allAttributes ?? EmptyAttributes;
|
||||||
Items = items;
|
Items = items;
|
||||||
UniqueId = uniqueId;
|
UniqueId = uniqueId;
|
||||||
}
|
}
|
||||||
|
|
@ -49,18 +43,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Every attribute associated with the current HTML element.
|
/// Every attribute associated with the current HTML element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyTagHelperAttributeList AllAttributes
|
public ReadOnlyTagHelperAttributeList AllAttributes { get; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_allAttributes == null)
|
|
||||||
{
|
|
||||||
_allAttributes = new TagHelperAttributeList(_allAttributesData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _allAttributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s.
|
/// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s.
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
public class TagHelperOutput : IHtmlContent
|
public class TagHelperOutput : IHtmlContent
|
||||||
{
|
{
|
||||||
private readonly Func<bool, HtmlEncoder, Task<TagHelperContent>> _getChildContentAsync;
|
private readonly Func<bool, HtmlEncoder, Task<TagHelperContent>> _getChildContentAsync;
|
||||||
|
private TagHelperAttributeList _attributes;
|
||||||
private TagHelperContent _preElement;
|
private TagHelperContent _preElement;
|
||||||
private TagHelperContent _preContent;
|
private TagHelperContent _preContent;
|
||||||
private TagHelperContent _content;
|
private TagHelperContent _content;
|
||||||
|
|
@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
internal TagHelperOutput(string tagName)
|
internal TagHelperOutput(string tagName)
|
||||||
: this(
|
: this(
|
||||||
tagName,
|
tagName,
|
||||||
new TagHelperAttributeList(),
|
null,
|
||||||
(useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()))
|
(useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -45,19 +46,14 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
TagHelperAttributeList attributes,
|
TagHelperAttributeList attributes,
|
||||||
Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContentAsync)
|
Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContentAsync)
|
||||||
{
|
{
|
||||||
if (attributes == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(attributes));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getChildContentAsync == null)
|
if (getChildContentAsync == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(getChildContentAsync));
|
throw new ArgumentNullException(nameof(getChildContentAsync));
|
||||||
}
|
}
|
||||||
|
|
||||||
TagName = tagName;
|
TagName = tagName;
|
||||||
Attributes = attributes;
|
|
||||||
_getChildContentAsync = getChildContentAsync;
|
_getChildContentAsync = getChildContentAsync;
|
||||||
|
_attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -187,7 +183,18 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
/// a <c>Microsoft.AspNetCore.Mvc.Rendering.HtmlString</c> instance. MVC converts most other types to a
|
/// a <c>Microsoft.AspNetCore.Mvc.Rendering.HtmlString</c> instance. MVC converts most other types to a
|
||||||
/// <see cref="string"/>, then HTML encodes the result.
|
/// <see cref="string"/>, then HTML encodes the result.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public TagHelperAttributeList Attributes { get; }
|
public TagHelperAttributeList Attributes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_attributes == null)
|
||||||
|
{
|
||||||
|
_attributes = new TagHelperAttributeList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes <see cref="TagHelperOutput"/> to generate nothing.
|
/// Changes <see cref="TagHelperOutput"/> to generate nothing.
|
||||||
|
|
@ -287,9 +294,9 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
writer.Write(TagName);
|
writer.Write(TagName);
|
||||||
|
|
||||||
// Perf: Avoid allocating enumerator
|
// Perf: Avoid allocating enumerator
|
||||||
for (var i = 0; i < Attributes.Count; i++)
|
for (var i = 0; i < (_attributes?.Count ?? 0); i++)
|
||||||
{
|
{
|
||||||
var attribute = Attributes[i];
|
var attribute = _attributes[i];
|
||||||
writer.Write(" ");
|
writer.Write(" ");
|
||||||
writer.Write(attribute.Name);
|
writer.Write(attribute.Name);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,16 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
[InlineData(TagMode.SelfClosing)]
|
[InlineData(TagMode.SelfClosing)]
|
||||||
[InlineData(TagMode.StartTagAndEndTag)]
|
[InlineData(TagMode.StartTagAndEndTag)]
|
||||||
[InlineData(TagMode.StartTagOnly)]
|
[InlineData(TagMode.StartTagOnly)]
|
||||||
public void TagMode_ReturnsExpectedValue(TagMode tagMode)
|
public void ExecutionContext_CreateTagHelperOutput_ReturnsExpectedTagMode(TagMode tagMode)
|
||||||
{
|
{
|
||||||
// Arrange & Act
|
// Arrange
|
||||||
var executionContext = new TagHelperExecutionContext("p", tagMode);
|
var executionContext = new TagHelperExecutionContext("p", tagMode);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(tagMode, executionContext.TagMode);
|
Assert.Equal(tagMode, output.TagMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -270,51 +273,6 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
Assert.NotSame(content1, content2);
|
Assert.NotSame(content1, content2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TheoryData<string, string> DictionaryCaseTestingData
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new TheoryData<string, string>
|
|
||||||
{
|
|
||||||
{ "class", "CLaSS" },
|
|
||||||
{ "Class", "class" },
|
|
||||||
{ "Class", "claSS" }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(DictionaryCaseTestingData))]
|
|
||||||
public void HtmlAttributes_IgnoresCase(string originalName, string updatedName)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var executionContext = new TagHelperExecutionContext("p", TagMode.StartTagAndEndTag);
|
|
||||||
executionContext.HtmlAttributes.SetAttribute(originalName, "hello");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
executionContext.HtmlAttributes.SetAttribute(updatedName, "something else");
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var attribute = Assert.Single(executionContext.HtmlAttributes);
|
|
||||||
Assert.Equal(new TagHelperAttribute(originalName, "something else"), attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[MemberData(nameof(DictionaryCaseTestingData))]
|
|
||||||
public void AllAttributes_IgnoresCase(string originalName, string updatedName)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var executionContext = new TagHelperExecutionContext("p", tagMode: TagMode.StartTagAndEndTag);
|
|
||||||
executionContext.AllAttributes.SetAttribute(originalName, value: false);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
executionContext.AllAttributes.SetAttribute(updatedName, true);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var attribute = Assert.Single(executionContext.AllAttributes);
|
|
||||||
Assert.Equal(new TagHelperAttribute(originalName, true), attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddHtmlAttribute_MaintainsHtmlAttributes()
|
public void AddHtmlAttribute_MaintainsHtmlAttributes()
|
||||||
{
|
{
|
||||||
|
|
@ -329,11 +287,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
// Act
|
// Act
|
||||||
executionContext.AddHtmlAttribute("class", "btn");
|
executionContext.AddHtmlAttribute("class", "btn");
|
||||||
executionContext.AddHtmlAttribute("foo", "bar");
|
executionContext.AddHtmlAttribute("foo", "bar");
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
expectedAttributes,
|
expectedAttributes,
|
||||||
executionContext.HtmlAttributes,
|
output.Attributes,
|
||||||
CaseSensitiveTagHelperAttributeComparer.Default);
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -351,11 +310,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
// Act
|
// Act
|
||||||
executionContext.AddMinimizedHtmlAttribute("checked");
|
executionContext.AddMinimizedHtmlAttribute("checked");
|
||||||
executionContext.AddMinimizedHtmlAttribute("visible");
|
executionContext.AddMinimizedHtmlAttribute("visible");
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
expectedAttributes,
|
expectedAttributes,
|
||||||
executionContext.HtmlAttributes,
|
output.Attributes,
|
||||||
CaseSensitiveTagHelperAttributeComparer.Default);
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,11 +337,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
executionContext.AddHtmlAttribute("foo", "bar");
|
executionContext.AddHtmlAttribute("foo", "bar");
|
||||||
executionContext.AddMinimizedHtmlAttribute("checked");
|
executionContext.AddMinimizedHtmlAttribute("checked");
|
||||||
executionContext.AddMinimizedHtmlAttribute("visible");
|
executionContext.AddMinimizedHtmlAttribute("visible");
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
expectedAttributes,
|
expectedAttributes,
|
||||||
executionContext.HtmlAttributes,
|
output.Attributes,
|
||||||
CaseSensitiveTagHelperAttributeComparer.Default);
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,11 +362,12 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
executionContext.AddHtmlAttribute("class", "btn");
|
executionContext.AddHtmlAttribute("class", "btn");
|
||||||
executionContext.AddTagHelperAttribute("something", true);
|
executionContext.AddTagHelperAttribute("something", true);
|
||||||
executionContext.AddHtmlAttribute("foo", "bar");
|
executionContext.AddHtmlAttribute("foo", "bar");
|
||||||
|
var context = executionContext.CreateTagHelperContext();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
expectedAttributes,
|
expectedAttributes,
|
||||||
executionContext.AllAttributes,
|
context.AllAttributes,
|
||||||
CaseSensitiveTagHelperAttributeComparer.Default);
|
CaseSensitiveTagHelperAttributeComparer.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,16 +125,17 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Begin_CreatesContextWithAppropriateTagName()
|
public void Begin_CreatesContexts_TagHelperOutput_WithAppropriateTagName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("p", executionContext.TagName);
|
Assert.Equal("p", output.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -146,25 +147,27 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
// Act
|
// Act
|
||||||
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
||||||
executionContext = BeginDefaultScope(scopeManager, tagName: "div");
|
executionContext = BeginDefaultScope(scopeManager, tagName: "div");
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("div", executionContext.TagName);
|
Assert.Equal("div", output.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(TagMode.SelfClosing)]
|
[InlineData(TagMode.SelfClosing)]
|
||||||
[InlineData(TagMode.StartTagAndEndTag)]
|
[InlineData(TagMode.StartTagAndEndTag)]
|
||||||
[InlineData(TagMode.StartTagOnly)]
|
[InlineData(TagMode.StartTagOnly)]
|
||||||
public void Begin_SetsExecutionContextTagMode(TagMode tagMode)
|
public void Begin_SetsExecutionContexts_TagHelperOutputTagMode(TagMode tagMode)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var scopeManager = new TagHelperScopeManager();
|
var scopeManager = new TagHelperScopeManager();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var executionContext = BeginDefaultScope(scopeManager, "p", tagMode);
|
var executionContext = BeginDefaultScope(scopeManager, "p", tagMode);
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(tagMode, executionContext.TagMode);
|
Assert.Equal(tagMode, output.TagMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -177,9 +180,10 @@ namespace Microsoft.AspNetCore.Razor.Runtime.TagHelpers
|
||||||
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
var executionContext = BeginDefaultScope(scopeManager, tagName: "p");
|
||||||
executionContext = BeginDefaultScope(scopeManager, tagName: "div");
|
executionContext = BeginDefaultScope(scopeManager, tagName: "div");
|
||||||
executionContext = scopeManager.End();
|
executionContext = scopeManager.End();
|
||||||
|
var output = executionContext.CreateTagHelperOutput();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("p", executionContext.TagName);
|
Assert.Equal("p", output.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -730,7 +730,7 @@ namespace Microsoft.AspNetCore.Razor.TagHelpers
|
||||||
private class TestableReadOnlyTagHelperAttributes : ReadOnlyTagHelperAttributeList
|
private class TestableReadOnlyTagHelperAttributes : ReadOnlyTagHelperAttributeList
|
||||||
{
|
{
|
||||||
public TestableReadOnlyTagHelperAttributes(IEnumerable<TagHelperAttribute> attributes)
|
public TestableReadOnlyTagHelperAttributes(IEnumerable<TagHelperAttribute> attributes)
|
||||||
: base(attributes)
|
: base(new List<TagHelperAttribute>(attributes))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue