Generate deterministic unique ids for tag helpers
This commit is contained in:
parent
21f2edce16
commit
7f6b05149d
|
|
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds];
|
var uniqueId = (string)context.Items[CodeRenderingContext.SuppressUniqueIds];
|
||||||
if (uniqueId == null)
|
if (uniqueId == null)
|
||||||
{
|
{
|
||||||
uniqueId = Guid.NewGuid().ToString("N");
|
uniqueId = GetDeterministicId(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.CodeWriter.WriteStringLiteral(node.TagName)
|
context.CodeWriter.WriteStringLiteral(node.TagName)
|
||||||
|
|
@ -637,6 +637,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal for testing
|
||||||
|
internal static string GetDeterministicId(CodeRenderingContext context)
|
||||||
|
{
|
||||||
|
// Use the file checksum along with the absolute position in the generated code to create a unique id for each tag helper call site.
|
||||||
|
var checksum = Checksum.BytesToString(context.SourceDocument.GetChecksum());
|
||||||
|
var uniqueId = checksum + context.CodeWriter.Location.AbsoluteIndex;
|
||||||
|
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetPropertyAccessor(DefaultTagHelperPropertyIntermediateNode node)
|
private static string GetPropertyAccessor(DefaultTagHelperPropertyIntermediateNode node)
|
||||||
{
|
{
|
||||||
var propertyAccessor = $"{node.FieldName}.{node.PropertyName}";
|
var propertyAccessor = $"{node.FieldName}.{node.PropertyName}";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
|
@ -568,6 +567,28 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.Views.pdb");
|
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.Views.pdb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("SimpleMvc")]
|
||||||
|
public async Task Build_WithDeterministicFlagSet_OutputsDeterministicViewsAssembly()
|
||||||
|
{
|
||||||
|
// Build 1
|
||||||
|
var result = await DotnetMSBuild("Build", $"/p:Deterministic=true");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.Views.dll");
|
||||||
|
var filePath = Path.Combine(result.Project.DirectoryPath, IntermediateOutputPath, "SimpleMvc.Views.dll");
|
||||||
|
var firstAssemblyBytes = File.ReadAllBytes(filePath);
|
||||||
|
|
||||||
|
// Build 2
|
||||||
|
result = await DotnetMSBuild("Rebuild", $"/p:Deterministic=true");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.Views.dll");
|
||||||
|
var secondAssemblyBytes = File.ReadAllBytes(filePath);
|
||||||
|
|
||||||
|
Assert.Equal(firstAssemblyBytes, secondAssemblyBytes);
|
||||||
|
}
|
||||||
|
|
||||||
private static DependencyContext ReadDependencyContext(string depsFilePath)
|
private static DependencyContext ReadDependencyContext(string depsFilePath)
|
||||||
{
|
{
|
||||||
var reader = new DependencyContextJsonReader();
|
var reader = new DependencyContextJsonReader();
|
||||||
|
|
|
||||||
|
|
@ -1118,6 +1118,20 @@ private global::Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeMana
|
||||||
ignoreLineEndingDifferences: true);
|
ignoreLineEndingDifferences: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDeterministicId_IsDeterministic()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var context = TestCodeRenderingContext.CreateRuntime(suppressUniqueIds: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var firstId = DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||||
|
var secondId = DefaultTagHelperTargetExtension.GetDeterministicId(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(firstId, secondId);
|
||||||
|
}
|
||||||
|
|
||||||
private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node)
|
private static void Push(CodeRenderingContext context, TagHelperIntermediateNode node)
|
||||||
{
|
{
|
||||||
((DefaultCodeRenderingContext)context).AncestorsInternal.Push(node);
|
((DefaultCodeRenderingContext)context).AncestorsInternal.Push(node);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue