Give attribute nodes a single object-valued value so they can be used for component properties too.
This commit is contained in:
parent
9dcb1c4fc4
commit
1b4fa4781a
|
|
@ -1,6 +1,6 @@
|
||||||
import { System_String, System_Array, Pointer } from '../Platform/Platform';
|
import { System_String, System_Array, Pointer } from '../Platform/Platform';
|
||||||
import { platform } from '../Environment';
|
import { platform } from '../Environment';
|
||||||
const renderTreeNodeStructLength = 44;
|
const renderTreeNodeStructLength = 40;
|
||||||
|
|
||||||
// To minimise GC pressure, instead of instantiating a JS object to represent each tree node,
|
// To minimise GC pressure, instead of instantiating a JS object to represent each tree node,
|
||||||
// we work in terms of pointers to the structs on the .NET heap, and use static functions that
|
// we work in terms of pointers to the structs on the .NET heap, and use static functions that
|
||||||
|
|
@ -18,9 +18,8 @@ export const renderTreeNode = {
|
||||||
textContent: (node: RenderTreeNodePointer) => platform.readStringField(node, 16),
|
textContent: (node: RenderTreeNodePointer) => platform.readStringField(node, 16),
|
||||||
attributeName: (node: RenderTreeNodePointer) => platform.readStringField(node, 20),
|
attributeName: (node: RenderTreeNodePointer) => platform.readStringField(node, 20),
|
||||||
attributeValue: (node: RenderTreeNodePointer) => platform.readStringField(node, 24),
|
attributeValue: (node: RenderTreeNodePointer) => platform.readStringField(node, 24),
|
||||||
attributeEventHandlerValue: (node: RenderTreeNodePointer) => platform.readObjectField(node, 28),
|
componentId: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 32),
|
||||||
componentId: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 36),
|
component: (node: RenderTreeNodePointer) => platform.readObjectField(node, 36),
|
||||||
component: (node: RenderTreeNodePointer) => platform.readObjectField(node, 40),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum NodeType {
|
export enum NodeType {
|
||||||
|
|
|
||||||
|
|
@ -271,10 +271,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
var newName = newTree[newNodeIndex].AttributeName;
|
var newName = newTree[newNodeIndex].AttributeName;
|
||||||
if (string.Equals(oldName, newName, StringComparison.Ordinal))
|
if (string.Equals(oldName, newName, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var changed =
|
// Using Equals to account for string comparisons, nulls, etc.
|
||||||
!string.Equals(oldTree[oldNodeIndex].AttributeValue, newTree[newNodeIndex].AttributeValue, StringComparison.Ordinal)
|
var valueChanged = !Equals(
|
||||||
|| oldTree[oldNodeIndex].AttributeEventHandlerValue != newTree[newNodeIndex].AttributeEventHandlerValue;
|
oldTree[oldNodeIndex].AttributeValue,
|
||||||
if (changed)
|
newTree[newNodeIndex].AttributeValue);
|
||||||
|
if (valueChanged)
|
||||||
{
|
{
|
||||||
Append(RenderTreeEdit.SetAttribute(siblingIndex, newNodeIndex));
|
Append(RenderTreeEdit.SetAttribute(siblingIndex, newNodeIndex));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
/// If the <see cref="NodeType"/> property equals <see cref="RenderTreeNodeType.Attribute"/>,
|
/// If the <see cref="NodeType"/> property equals <see cref="RenderTreeNodeType.Attribute"/>,
|
||||||
/// gets the attribute value. Otherwise, the value is <see langword="null"/>.
|
/// gets the attribute value. Otherwise, the value is <see langword="null"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AttributeValue { get; private set; }
|
public object AttributeValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If the <see cref="NodeType"/> property equals <see cref="RenderTreeNodeType.Attribute"/>,
|
|
||||||
/// gets the attribute's event handle, if any. Otherwise, the value is <see langword="null"/>.
|
|
||||||
/// </summary>
|
|
||||||
public UIEventHandler AttributeEventHandlerValue { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the <see cref="NodeType"/> property equals <see cref="RenderTreeNodeType.Component"/>,
|
/// If the <see cref="NodeType"/> property equals <see cref="RenderTreeNodeType.Component"/>,
|
||||||
|
|
@ -109,7 +103,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
Sequence = sequence,
|
Sequence = sequence,
|
||||||
NodeType = RenderTreeNodeType.Attribute,
|
NodeType = RenderTreeNodeType.Attribute,
|
||||||
AttributeName = name,
|
AttributeName = name,
|
||||||
AttributeEventHandlerValue = value
|
AttributeValue = value
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static RenderTreeNode ChildComponent<T>(int sequence) where T: IComponent => new RenderTreeNode
|
internal static RenderTreeNode ChildComponent<T>(int sequence) where T: IComponent => new RenderTreeNode
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,10 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodes = _renderTreeBuilderCurrent.GetNodes();
|
var nodes = _renderTreeBuilderCurrent.GetNodes();
|
||||||
var eventHandler = nodes.Array[renderTreeIndex].AttributeEventHandlerValue;
|
var eventHandler = nodes.Array[renderTreeIndex].AttributeValue as UIEventHandler;
|
||||||
if (eventHandler == null)
|
if (eventHandler == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"The render tree node at index {renderTreeIndex} has a null value for {nameof(RenderTreeNode.AttributeEventHandlerValue)}.");
|
throw new ArgumentException($"The render tree node at index {renderTreeIndex} does not specify a {nameof(UIEventHandler)}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandler.Invoke(eventArgs);
|
eventHandler.Invoke(eventArgs);
|
||||||
|
|
|
||||||
|
|
@ -254,9 +254,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
node =>
|
node =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
||||||
Assert.NotNull(node.AttributeEventHandlerValue);
|
Assert.NotNull(node.AttributeValue);
|
||||||
|
|
||||||
node.AttributeEventHandlerValue(null);
|
((UIEventHandler)node.AttributeValue)(null);
|
||||||
Assert.True((bool)handlerWasCalledProperty.GetValue(component));
|
Assert.True((bool)handlerWasCalledProperty.GetValue(component));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -279,9 +279,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
node =>
|
node =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
||||||
Assert.NotNull(node.AttributeEventHandlerValue);
|
Assert.NotNull(node.AttributeValue);
|
||||||
|
|
||||||
node.AttributeEventHandlerValue(null);
|
((UIEventHandler)node.AttributeValue)(null);
|
||||||
Assert.True((bool)didInvokeCodeProperty.GetValue(component));
|
Assert.True((bool)didInvokeCodeProperty.GetValue(component));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -325,9 +325,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
node =>
|
node =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType);
|
||||||
Assert.NotNull(node.AttributeEventHandlerValue);
|
Assert.NotNull(node.AttributeValue);
|
||||||
|
|
||||||
node.AttributeEventHandlerValue(null);
|
((UIEventHandler)node.AttributeValue)(null);
|
||||||
Assert.True((bool)didInvokeCodeProperty.GetValue(component));
|
Assert.True((bool)didInvokeCodeProperty.GetValue(component));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
var (eventHandlerNodeIndex, _) = FirstWithIndex(
|
var (eventHandlerNodeIndex, _) = FirstWithIndex(
|
||||||
renderer.RenderTreesByComponentId[componentId],
|
renderer.RenderTreesByComponentId[componentId],
|
||||||
node => node.AttributeEventHandlerValue != null);
|
node => node.AttributeValue != null);
|
||||||
|
|
||||||
// Assert: Event not yet fired
|
// Assert: Event not yet fired
|
||||||
Assert.Null(receivedArgs);
|
Assert.Null(receivedArgs);
|
||||||
|
|
@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
// Find nested component's event handler ndoe
|
// Find nested component's event handler ndoe
|
||||||
var (eventHandlerNodeIndex, _) = FirstWithIndex(
|
var (eventHandlerNodeIndex, _) = FirstWithIndex(
|
||||||
renderer.RenderTreesByComponentId[nestedComponentId],
|
renderer.RenderTreesByComponentId[nestedComponentId],
|
||||||
node => node.AttributeEventHandlerValue != null);
|
node => node.AttributeValue != null);
|
||||||
|
|
||||||
// Assert: Event not yet fired
|
// Assert: Event not yet fired
|
||||||
Assert.Null(receivedArgs);
|
Assert.Null(receivedArgs);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Blazor.Test.Shared
|
||||||
public static void Attribute(RenderTreeNode node, string attributeName, UIEventHandler attributeEventHandlerValue)
|
public static void Attribute(RenderTreeNode node, string attributeName, UIEventHandler attributeEventHandlerValue)
|
||||||
{
|
{
|
||||||
AssertNode.Attribute(node, attributeName);
|
AssertNode.Attribute(node, attributeName);
|
||||||
Assert.Equal(attributeEventHandlerValue, node.AttributeEventHandlerValue);
|
Assert.Equal(attributeEventHandlerValue, node.AttributeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Component<T>(RenderTreeNode node) where T : IComponent
|
public static void Component<T>(RenderTreeNode node) where T : IComponent
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue