diff --git a/src/Microsoft.AspNet.Razor.Runtime/NotNullArgument.cs b/src/Microsoft.AspNet.Razor.Runtime/NotNullArgument.cs deleted file mode 100644 index 4b9755cce9..0000000000 --- a/src/Microsoft.AspNet.Razor.Runtime/NotNullArgument.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNet.Razor.Runtime -{ - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - internal sealed class NotNullAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/HtmlElementNameAttribute.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/HtmlElementNameAttribute.cs index e2b0f56de6..4e2227468d 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/HtmlElementNameAttribute.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/HtmlElementNameAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContext.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContext.cs index 2f751e3ddb..940be2501e 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContext.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperContext.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { @@ -18,15 +19,19 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// Instantiates a new . /// /// Every attribute associated with the current HTML element. + /// Collection of items used to communicate with other s. /// The unique identifier for the source element this /// applies to. /// A delegate used to execute and retrieve the rendered child content /// asynchronously. - public TagHelperContext([NotNull] IDictionary allAttributes, - [NotNull] string uniqueId, - [NotNull] Func> getChildContentAsync) + public TagHelperContext( + [NotNull] IDictionary allAttributes, + [NotNull] IDictionary items, + [NotNull] string uniqueId, + [NotNull] Func> getChildContentAsync) { AllAttributes = allAttributes; + Items = items; UniqueId = uniqueId; _getChildContentAsync = getChildContentAsync; } @@ -36,6 +41,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// public IDictionary AllAttributes { get; } + /// + /// Gets the collection of items used to communicate with other s. + /// + /// + /// This is copy-on-write in order to ensure items added to this + /// collection are visible only to other s targeting child elements. + /// + public IDictionary Items { get; } + /// /// An identifier unique to the HTML element this context is for. /// diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs index b053673d4a..2602a5a8d5 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs @@ -9,6 +9,7 @@ using System.Text.RegularExpressions; using Microsoft.AspNet.Razor.Parser; using Microsoft.AspNet.Razor.TagHelpers; using Microsoft.AspNet.Razor.Text; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs index ada91b1458..0401bedb6b 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperExecutionContext.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { @@ -25,6 +27,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers internal TagHelperExecutionContext(string tagName, bool selfClosing) : this(tagName, selfClosing, + items: new Dictionary(), uniqueId: string.Empty, executeChildContentAsync: async () => await Task.FromResult(result: true), startWritingScope: () => { }, @@ -37,18 +40,21 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// /// The HTML tag name in the Razor source. /// - /// indicating whether or not the tag in the Razor source was self-closing. - /// + /// indicating whether or not the tag in the Razor source was self-closing. + /// The collection of items used to communicate with other + /// s /// An identifier unique to the HTML element this context is for. /// A delegate used to execute the child content asynchronously. /// A delegate used to start a writing scope in a Razor page. /// A delegate used to end a writing scope in a Razor page. - public TagHelperExecutionContext([NotNull] string tagName, - bool selfClosing, - [NotNull] string uniqueId, - [NotNull] Func executeChildContentAsync, - [NotNull] Action startWritingScope, - [NotNull] Func endWritingScope) + public TagHelperExecutionContext( + [NotNull] string tagName, + bool selfClosing, + [NotNull] IDictionary items, + [NotNull] string uniqueId, + [NotNull] Func executeChildContentAsync, + [NotNull] Action startWritingScope, + [NotNull] Func endWritingScope) { _tagHelpers = new List(); _executeChildContentAsync = executeChildContentAsync; @@ -59,6 +65,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers AllAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase); HTMLAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase); TagName = tagName; + Items = items; UniqueId = uniqueId; } @@ -78,6 +85,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers } } + /// + /// Gets the collection of items used to communicate with other s. + /// + public IDictionary Items { get; } + /// /// HTML attributes. /// diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperOutput.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperOutput.cs index b94aed2c03..b428c37ab8 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperOutput.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperOutput.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Globalization; using System.Net; using System.Text; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs index 5325bf2d8c..70c52939d3 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperRunner.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { @@ -22,6 +23,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { var tagHelperContext = new TagHelperContext( executionContext.AllAttributes, + executionContext.Items, executionContext.UniqueId, executionContext.GetChildContentAsync); var tagHelperOutput = new TagHelperOutput(executionContext.TagName, executionContext.HTMLAttributes) diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs index 2ab6163840..d7f10400f2 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperScopeManager.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { @@ -35,19 +36,36 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers /// A delegate used to start a writing scope in a Razor page. /// A delegate used to end a writing scope in a Razor page. /// A to use. - public TagHelperExecutionContext Begin([NotNull] string tagName, - bool selfClosing, - [NotNull] string uniqueId, - [NotNull] Func executeChildContentAsync, - [NotNull] Action startWritingScope, - [NotNull] Func endWritingScope) + public TagHelperExecutionContext Begin( + [NotNull] string tagName, + bool selfClosing, + [NotNull] string uniqueId, + [NotNull] Func executeChildContentAsync, + [NotNull] Action startWritingScope, + [NotNull] Func endWritingScope) { - var executionContext = new TagHelperExecutionContext(tagName, - selfClosing, - uniqueId, - executeChildContentAsync, - startWritingScope, - endWritingScope); + IDictionary items; + + // If we're not wrapped by another TagHelper, then there will not be a parentExecutionContext. + if (_executionScopes.Count > 0) + { + items = new CopyOnWriteDictionary( + _executionScopes.Peek().Items, + comparer: EqualityComparer.Default); + } + else + { + items = new Dictionary(); + } + + var executionContext = new TagHelperExecutionContext( + tagName, + selfClosing, + items, + uniqueId, + executeChildContentAsync, + startWritingScope, + endWritingScope); _executionScopes.Push(executionContext); diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs index 60a399140e..f5f05ffbc1 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs +++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using Microsoft.AspNet.Razor.Parser; using Microsoft.AspNet.Razor.Text; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { diff --git a/src/Microsoft.AspNet.Razor.Runtime/project.json b/src/Microsoft.AspNet.Razor.Runtime/project.json index 3728d59c00..cdd44fec8e 100644 --- a/src/Microsoft.AspNet.Razor.Runtime/project.json +++ b/src/Microsoft.AspNet.Razor.Runtime/project.json @@ -2,7 +2,9 @@ "description": "Runtime components for rendering Razor pages.", "version": "4.0.0-*", "dependencies": { - "Microsoft.AspNet.Razor": "4.0.0-*" + "Microsoft.AspNet.Razor": "4.0.0-*", + "Microsoft.Framework.CopyOnWriteDictionary.Internal": { "type": "build", "version": "1.0.0-*" }, + "Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" } }, "frameworks": { "net45": { },