Add indexer null-check for preallocated tag helper attributes
This commit is contained in:
parent
e3287ae672
commit
27ac5da6d5
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||||
|
|
||||||
|
|
@ -18,6 +19,8 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
public string ExecutionContextAddTagHelperAttributeMethodName { get; set; } = "AddTagHelperAttribute";
|
public string ExecutionContextAddTagHelperAttributeMethodName { get; set; } = "AddTagHelperAttribute";
|
||||||
|
|
||||||
|
public string FormatInvalidIndexerAssignmentMethodName { get; set; } = "InvalidTagHelperIndexerAssignment";
|
||||||
|
|
||||||
public void WriteDeclarePreallocatedTagHelperHtmlAttribute(CSharpRenderingContext context, DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
|
public void WriteDeclarePreallocatedTagHelperHtmlAttribute(CSharpRenderingContext context, DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
|
||||||
{
|
{
|
||||||
context.Writer
|
context.Writer
|
||||||
|
|
@ -74,8 +77,39 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
public void WriteSetPreallocatedTagHelperProperty(CSharpRenderingContext context, SetPreallocatedTagHelperPropertyIRNode node)
|
public void WriteSetPreallocatedTagHelperProperty(CSharpRenderingContext context, SetPreallocatedTagHelperPropertyIRNode node)
|
||||||
{
|
{
|
||||||
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
|
||||||
|
var propertyName = node.Descriptor.GetPropertyName();
|
||||||
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
|
var propertyValueAccessor = GetTagHelperPropertyAccessor(node.IsIndexerNameMatch, tagHelperVariableName, node.AttributeName, node.Descriptor);
|
||||||
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
|
var attributeValueAccessor = $"{node.VariableName}.Value" /* ORIGINAL: TagHelperAttributeValuePropertyName */;
|
||||||
|
|
||||||
|
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
||||||
|
if (node.IsIndexerNameMatch &&
|
||||||
|
context.TagHelperRenderingContext.VerifiedPropertyDictionaries.Add($"{node.TagHelperTypeName}.{propertyName}"))
|
||||||
|
{
|
||||||
|
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
||||||
|
context.Writer
|
||||||
|
.Write("if (")
|
||||||
|
.Write(tagHelperVariableName)
|
||||||
|
.Write(".")
|
||||||
|
.Write(propertyName)
|
||||||
|
.WriteLine(" == null)");
|
||||||
|
using (context.Writer.BuildScope())
|
||||||
|
{
|
||||||
|
// System is in Host.NamespaceImports for all MVC scenarios. No need to generate FullName
|
||||||
|
// of InvalidOperationException type.
|
||||||
|
context.Writer
|
||||||
|
.Write("throw ")
|
||||||
|
.WriteStartNewObject(nameof(InvalidOperationException))
|
||||||
|
.WriteStartMethodInvocation(FormatInvalidIndexerAssignmentMethodName)
|
||||||
|
.WriteStringLiteral(node.AttributeName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.WriteStringLiteral(node.TagHelperTypeName)
|
||||||
|
.WriteParameterSeparator()
|
||||||
|
.WriteStringLiteral(propertyName)
|
||||||
|
.WriteEndMethodInvocation(endLine: false) // End of method call
|
||||||
|
.WriteEndMethodInvocation(); // End of new expression / throw statement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context.Writer
|
context.Writer
|
||||||
.WriteStartAssignment(propertyValueAccessor)
|
.WriteStartAssignment(propertyValueAccessor)
|
||||||
.Write("(string)")
|
.Write("(string)")
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ namespace Microsoft.AspNetCore.Razor.Language.CodeGeneration
|
||||||
|
|
||||||
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
// Ensure that the property we're trying to set has initialized its dictionary bound properties.
|
||||||
if (node.IsIndexerNameMatch &&
|
if (node.IsIndexerNameMatch &&
|
||||||
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add(propertyName))
|
tagHelperRenderingContext.VerifiedPropertyDictionaries.Add($"{node.TagHelperTypeName}.{propertyName}"))
|
||||||
{
|
{
|
||||||
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
// Throw a reasonable Exception at runtime if the dictionary property is null.
|
||||||
context.Writer
|
context.Writer
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,8 @@ __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
|
||||||
var extension = new PreallocatedAttributeTargetExtension();
|
var extension = new PreallocatedAttributeTargetExtension();
|
||||||
var context = new CSharpRenderingContext()
|
var context = new CSharpRenderingContext()
|
||||||
{
|
{
|
||||||
Writer = new CSharpCodeWriter()
|
Writer = new CSharpCodeWriter(),
|
||||||
|
TagHelperRenderingContext = new TagHelperRenderingContext()
|
||||||
};
|
};
|
||||||
|
|
||||||
var descriptor = BoundAttributeDescriptorBuilder
|
var descriptor = BoundAttributeDescriptorBuilder
|
||||||
|
|
@ -197,7 +198,11 @@ __tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
|
||||||
// Assert
|
// Assert
|
||||||
var csharp = context.Writer.Builder.ToString();
|
var csharp = context.Writer.Builder.ToString();
|
||||||
Assert.Equal(
|
Assert.Equal(
|
||||||
@"__FooTagHelper.FooProp[""Foo""] = (string)_tagHelper1.Value;
|
@"if (__FooTagHelper.FooProp == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment(""pre-Foo"", ""FooTagHelper"", ""FooProp""));
|
||||||
|
}
|
||||||
|
__FooTagHelper.FooProp[""Foo""] = (string)_tagHelper1.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
|
__tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
|
||||||
",
|
",
|
||||||
csharp,
|
csharp,
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,10 @@ __TestNamespace_InputTagHelper1.IntDictionaryProperty["garlic"] = 37;
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("int-prefix-garlic", __TestNamespace_InputTagHelper1.IntDictionaryProperty["garlic"], global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
__tagHelperExecutionContext.AddTagHelperAttribute("int-prefix-garlic", __TestNamespace_InputTagHelper1.IntDictionaryProperty["garlic"], global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
|
if (__TestNamespace_InputTagHelper2.IntDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("int-prefix-garlic", "TestNamespace.InputTagHelper2", "IntDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper2.IntDictionaryProperty["garlic"] = __TestNamespace_InputTagHelper1.IntDictionaryProperty["garlic"];
|
__TestNamespace_InputTagHelper2.IntDictionaryProperty["garlic"] = __TestNamespace_InputTagHelper1.IntDictionaryProperty["garlic"];
|
||||||
#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
#line 17 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
||||||
__TestNamespace_InputTagHelper1.IntProperty = 42;
|
__TestNamespace_InputTagHelper1.IntProperty = 42;
|
||||||
|
|
@ -140,6 +144,10 @@ __TestNamespace_InputTagHelper1.IntProperty = 42;
|
||||||
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("int-prefix-grabber", "TestNamespace.InputTagHelper2", "IntDictionaryProperty"));
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("int-prefix-grabber", "TestNamespace.InputTagHelper2", "IntDictionaryProperty"));
|
||||||
}
|
}
|
||||||
__TestNamespace_InputTagHelper2.IntDictionaryProperty["grabber"] = __TestNamespace_InputTagHelper1.IntProperty;
|
__TestNamespace_InputTagHelper2.IntDictionaryProperty["grabber"] = __TestNamespace_InputTagHelper1.IntProperty;
|
||||||
|
if (__TestNamespace_InputTagHelper1.IntDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("int-prefix-salt", "TestNamespace.InputTagHelper1", "IntDictionaryProperty"));
|
||||||
|
}
|
||||||
#line 19 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
#line 19 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
||||||
__TestNamespace_InputTagHelper1.IntDictionaryProperty["salt"] = 37;
|
__TestNamespace_InputTagHelper1.IntDictionaryProperty["salt"] = 37;
|
||||||
|
|
||||||
|
|
@ -157,16 +165,20 @@ __TestNamespace_InputTagHelper1.IntDictionaryProperty["pepper"] = 98;
|
||||||
__tagHelperExecutionContext.AddHtmlAttribute(__tagHelperAttribute_3);
|
__tagHelperExecutionContext.AddHtmlAttribute(__tagHelperAttribute_3);
|
||||||
__TestNamespace_InputTagHelper1.StringProperty = (string)__tagHelperAttribute_4.Value;
|
__TestNamespace_InputTagHelper1.StringProperty = (string)__tagHelperAttribute_4.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_4);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_4);
|
||||||
|
if (__TestNamespace_InputTagHelper2.StringDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("string-prefix-grabber", "TestNamespace.InputTagHelper2", "StringDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper2.StringDictionaryProperty["grabber"] = (string)__tagHelperAttribute_4.Value;
|
__TestNamespace_InputTagHelper2.StringDictionaryProperty["grabber"] = (string)__tagHelperAttribute_4.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_4);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_4);
|
||||||
|
if (__TestNamespace_InputTagHelper1.StringDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("string-prefix-paprika", "TestNamespace.InputTagHelper1", "StringDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper1.StringDictionaryProperty["paprika"] = (string)__tagHelperAttribute_5.Value;
|
__TestNamespace_InputTagHelper1.StringDictionaryProperty["paprika"] = (string)__tagHelperAttribute_5.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_5);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_5);
|
||||||
__TestNamespace_InputTagHelper2.StringDictionaryProperty["paprika"] = (string)__tagHelperAttribute_5.Value;
|
__TestNamespace_InputTagHelper2.StringDictionaryProperty["paprika"] = (string)__tagHelperAttribute_5.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_5);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_5);
|
||||||
if (__TestNamespace_InputTagHelper1.StringDictionaryProperty == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("string-prefix-cumin", "TestNamespace.InputTagHelper1", "StringDictionaryProperty"));
|
|
||||||
}
|
|
||||||
BeginWriteTagHelperAttribute();
|
BeginWriteTagHelperAttribute();
|
||||||
WriteLiteral("literate ");
|
WriteLiteral("literate ");
|
||||||
#line 21 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
#line 21 "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PrefixedAttributeTagHelpers.cshtml"
|
||||||
|
|
@ -204,9 +216,21 @@ __TestNamespace_InputTagHelper1.IntDictionaryProperty["value"] = 37;
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute("int-prefix-value", __TestNamespace_InputTagHelper1.IntDictionaryProperty["value"], global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
__tagHelperExecutionContext.AddTagHelperAttribute("int-prefix-value", __TestNamespace_InputTagHelper1.IntDictionaryProperty["value"], global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
|
||||||
|
if (__TestNamespace_InputTagHelper2.IntDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("int-prefix-value", "TestNamespace.InputTagHelper2", "IntDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper2.IntDictionaryProperty["value"] = __TestNamespace_InputTagHelper1.IntDictionaryProperty["value"];
|
__TestNamespace_InputTagHelper2.IntDictionaryProperty["value"] = __TestNamespace_InputTagHelper1.IntDictionaryProperty["value"];
|
||||||
|
if (__TestNamespace_InputTagHelper1.StringDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("string-prefix-thyme", "TestNamespace.InputTagHelper1", "StringDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper1.StringDictionaryProperty["thyme"] = (string)__tagHelperAttribute_6.Value;
|
__TestNamespace_InputTagHelper1.StringDictionaryProperty["thyme"] = (string)__tagHelperAttribute_6.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_6);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_6);
|
||||||
|
if (__TestNamespace_InputTagHelper2.StringDictionaryProperty == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("string-prefix-thyme", "TestNamespace.InputTagHelper2", "StringDictionaryProperty"));
|
||||||
|
}
|
||||||
__TestNamespace_InputTagHelper2.StringDictionaryProperty["thyme"] = (string)__tagHelperAttribute_6.Value;
|
__TestNamespace_InputTagHelper2.StringDictionaryProperty["thyme"] = (string)__tagHelperAttribute_6.Value;
|
||||||
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_6);
|
__tagHelperExecutionContext.AddTagHelperAttribute(__tagHelperAttribute_6);
|
||||||
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue