diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts index fa6b5aa5f3..fcda826d6b 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts @@ -1,6 +1,6 @@ import { System_Array, MethodHandle } from '../Platform/Platform'; import { getRenderTreeEditPtr, renderTreeEdit, RenderTreeEditPointer, EditType } from './RenderTreeEdit'; -import { getTreeNodePtr, renderTreeNode, NodeType, RenderTreeNodePointer } from './RenderTreeNode'; +import { getTreeFramePtr, renderTreeFrame, FrameType, RenderTreeFramePointer } from './RenderTreeFrame'; import { platform } from '../Environment'; let raiseEventMethod: MethodHandle; let renderComponentMethod: MethodHandle; @@ -15,7 +15,7 @@ export class BrowserRenderer { this.childComponentLocations[componentId] = element; } - public updateComponent(componentId: number, edits: System_Array, editsLength: number, referenceTree: System_Array) { + public updateComponent(componentId: number, edits: System_Array, editsLength: number, referenceTree: System_Array) { const element = this.childComponentLocations[componentId]; if (!element) { throw new Error(`No element is currently associated with component ${componentId}`); @@ -28,31 +28,31 @@ export class BrowserRenderer { delete this.childComponentLocations[componentId]; } - applyEdits(componentId: number, parent: Element, childIndex: number, edits: System_Array, editsLength: number, referenceTree: System_Array) { + applyEdits(componentId: number, parent: Element, childIndex: number, edits: System_Array, editsLength: number, referenceTree: System_Array) { let currentDepth = 0; let childIndexAtCurrentDepth = childIndex; for (let editIndex = 0; editIndex < editsLength; editIndex++) { const edit = getRenderTreeEditPtr(edits, editIndex); const editType = renderTreeEdit.type(edit); switch (editType) { - case EditType.prependNode: { - const nodeIndex = renderTreeEdit.newTreeIndex(edit); - const node = getTreeNodePtr(referenceTree, nodeIndex); + case EditType.prependFrame: { + const frameIndex = renderTreeEdit.newTreeIndex(edit); + const frame = getTreeFramePtr(referenceTree, frameIndex); const siblingIndex = renderTreeEdit.siblingIndex(edit); - this.insertNode(componentId, parent, childIndexAtCurrentDepth + siblingIndex, referenceTree, node, nodeIndex); + this.insertFrame(componentId, parent, childIndexAtCurrentDepth + siblingIndex, referenceTree, frame, frameIndex); break; } - case EditType.removeNode: { + case EditType.removeFrame: { const siblingIndex = renderTreeEdit.siblingIndex(edit); removeNodeFromDOM(parent, childIndexAtCurrentDepth + siblingIndex); break; } case EditType.setAttribute: { - const nodeIndex = renderTreeEdit.newTreeIndex(edit); - const node = getTreeNodePtr(referenceTree, nodeIndex); + const frameIndex = renderTreeEdit.newTreeIndex(edit); + const frame = getTreeFramePtr(referenceTree, frameIndex); const siblingIndex = renderTreeEdit.siblingIndex(edit); const element = parent.childNodes[childIndexAtCurrentDepth + siblingIndex] as HTMLElement; - this.applyAttribute(componentId, element, node, nodeIndex); + this.applyAttribute(componentId, element, frame, frameIndex); break; } case EditType.removeAttribute: { @@ -61,11 +61,11 @@ export class BrowserRenderer { break; } case EditType.updateText: { - const nodeIndex = renderTreeEdit.newTreeIndex(edit); - const node = getTreeNodePtr(referenceTree, nodeIndex); + const frameIndex = renderTreeEdit.newTreeIndex(edit); + const frame = getTreeFramePtr(referenceTree, frameIndex); const siblingIndex = renderTreeEdit.siblingIndex(edit); const domTextNode = parent.childNodes[childIndexAtCurrentDepth + siblingIndex] as Text; - domTextNode.textContent = renderTreeNode.textContent(node); + domTextNode.textContent = renderTreeFrame.textContent(frame); break; } case EditType.stepIn: { @@ -89,79 +89,79 @@ export class BrowserRenderer { } } - insertNode(componentId: number, parent: Element, childIndex: number, nodes: System_Array, node: RenderTreeNodePointer, nodeIndex: number) { - const nodeType = renderTreeNode.nodeType(node); - switch (nodeType) { - case NodeType.element: - this.insertElement(componentId, parent, childIndex, nodes, node, nodeIndex); + insertFrame(componentId: number, parent: Element, childIndex: number, frames: System_Array, frame: RenderTreeFramePointer, frameIndex: number) { + const frameType = renderTreeFrame.frameType(frame); + switch (frameType) { + case FrameType.element: + this.insertElement(componentId, parent, childIndex, frames, frame, frameIndex); break; - case NodeType.text: - this.insertText(parent, childIndex, node); + case FrameType.text: + this.insertText(parent, childIndex, frame); break; - case NodeType.attribute: - throw new Error('Attribute nodes should only be present as leading children of element nodes.'); - case NodeType.component: - this.insertComponent(parent, childIndex, node); + case FrameType.attribute: + throw new Error('Attribute frames should only be present as leading children of element frames.'); + case FrameType.component: + this.insertComponent(parent, childIndex, frame); break; default: - const unknownType: never = nodeType; // Compile-time verification that the switch was exhaustive - throw new Error(`Unknown node type: ${unknownType}`); + const unknownType: never = frameType; // Compile-time verification that the switch was exhaustive + throw new Error(`Unknown frame type: ${unknownType}`); } } - insertElement(componentId: number, parent: Element, childIndex: number, nodes: System_Array, node: RenderTreeNodePointer, nodeIndex: number) { - const tagName = renderTreeNode.elementName(node)!; + insertElement(componentId: number, parent: Element, childIndex: number, frames: System_Array, frame: RenderTreeFramePointer, frameIndex: number) { + const tagName = renderTreeFrame.elementName(frame)!; const newDomElement = document.createElement(tagName); insertNodeIntoDOM(newDomElement, parent, childIndex); // Apply attributes - const descendantsEndIndex = renderTreeNode.descendantsEndIndex(node); - for (let descendantIndex = nodeIndex + 1; descendantIndex <= descendantsEndIndex; descendantIndex++) { - const descendantNode = getTreeNodePtr(nodes, descendantIndex); - if (renderTreeNode.nodeType(descendantNode) === NodeType.attribute) { - this.applyAttribute(componentId, newDomElement, descendantNode, descendantIndex); + const descendantsEndIndex = renderTreeFrame.descendantsEndIndex(frame); + for (let descendantIndex = frameIndex + 1; descendantIndex <= descendantsEndIndex; descendantIndex++) { + const descendantFrame = getTreeFramePtr(frames, descendantIndex); + if (renderTreeFrame.frameType(descendantFrame) === FrameType.attribute) { + this.applyAttribute(componentId, newDomElement, descendantFrame, descendantIndex); } else { - // As soon as we see a non-attribute child, all the subsequent child nodes are + // As soon as we see a non-attribute child, all the subsequent child frames are // not attributes, so bail out and insert the remnants recursively - this.insertNodeRange(componentId, newDomElement, 0, nodes, descendantIndex, descendantsEndIndex); + this.insertFrameRange(componentId, newDomElement, 0, frames, descendantIndex, descendantsEndIndex); break; } } } - insertComponent(parent: Element, childIndex: number, node: RenderTreeNodePointer) { - // Currently, to support O(1) lookups from render tree nodes to DOM nodes, we rely on + insertComponent(parent: Element, childIndex: number, frame: RenderTreeFramePointer) { + // Currently, to support O(1) lookups from render tree frames to DOM nodes, we rely on // each child component existing as a single top-level element in the DOM. To guarantee // that, we wrap child components in these 'blazor-component' wrappers. // To improve on this in the future: // - If we can statically detect that a given component always produces a single top-level // element anyway, then don't wrap it in a further nonstandard element - // - If we really want to support child components producing multiple top-level nodes and + // - If we really want to support child components producing multiple top-level frames and // not being wrapped in a container at all, then every time a component is refreshed in // the DOM, we could update an array on the parent element that specifies how many DOM - // nodes correspond to each of its render tree nodes. Then when that parent wants to - // locate the first DOM node for a render tree node, it can sum all the node counts for - // all the preceding render trees nodes. It's O(N), but where N is the number of siblings + // nodes correspond to each of its render tree frames. Then when that parent wants to + // locate the first DOM node for a render tree frame, it can sum all the frame counts for + // all the preceding render trees frames. It's O(N), but where N is the number of siblings // (counting child components as a single item), so N will rarely if ever be large. // We could even keep track of whether all the child components happen to have exactly 1 - // top level node, and in that case, there's no need to sum as we can do direct lookups. + // top level frames, and in that case, there's no need to sum as we can do direct lookups. const containerElement = document.createElement('blazor-component'); insertNodeIntoDOM(containerElement, parent, childIndex); // All we have to do is associate the child component ID with its location. We don't actually // do any rendering here, because the diff for the child will appear later in the render batch. - const childComponentId = renderTreeNode.componentId(node); + const childComponentId = renderTreeFrame.componentId(frame); this.attachComponentToElement(childComponentId, containerElement); } - insertText(parent: Element, childIndex: number, textNode: RenderTreeNodePointer) { - const textContent = renderTreeNode.textContent(textNode)!; + insertText(parent: Element, childIndex: number, textFrame: RenderTreeFramePointer) { + const textContent = renderTreeFrame.textContent(textFrame)!; const newDomTextNode = document.createTextNode(textContent); insertNodeIntoDOM(newDomTextNode, parent, childIndex); } - applyAttribute(componentId: number, toDomElement: Element, attributeNode: RenderTreeNodePointer, attributeNodeIndex: number) { - const attributeName = renderTreeNode.attributeName(attributeNode)!; + applyAttribute(componentId: number, toDomElement: Element, attributeFrame: RenderTreeFramePointer, attributeFrameIndex: number) { + const attributeName = renderTreeFrame.attributeName(attributeFrame)!; const browserRendererId = this.browserRendererId; // TODO: Instead of applying separate event listeners to each DOM element, use event delegation @@ -169,7 +169,7 @@ export class BrowserRenderer { switch (attributeName) { case 'onclick': { toDomElement.removeEventListener('click', toDomElement['_blazorClickListener']); - const listener = () => raiseEvent(browserRendererId, componentId, attributeNodeIndex, 'mouse', { Type: 'click' }); + const listener = () => raiseEvent(browserRendererId, componentId, attributeFrameIndex, 'mouse', { Type: 'click' }); toDomElement['_blazorClickListener'] = listener; toDomElement.addEventListener('click', listener); break; @@ -181,7 +181,7 @@ export class BrowserRenderer { // just to establish that we can pass parameters when raising events. // We use C#-style PascalCase on the eventInfo to simplify deserialization, but this could // change if we introduced a richer JSON library on the .NET side. - raiseEvent(browserRendererId, componentId, attributeNodeIndex, 'keyboard', { Type: evt.type, Key: (evt as any).key }); + raiseEvent(browserRendererId, componentId, attributeFrameIndex, 'keyboard', { Type: evt.type, Key: (evt as any).key }); }; toDomElement['_blazorKeypressListener'] = listener; toDomElement.addEventListener('keypress', listener); @@ -191,20 +191,20 @@ export class BrowserRenderer { // Treat as a regular string-valued attribute toDomElement.setAttribute( attributeName, - renderTreeNode.attributeValue(attributeNode)! + renderTreeFrame.attributeValue(attributeFrame)! ); break; } } - insertNodeRange(componentId: number, parent: Element, childIndex: number, nodes: System_Array, startIndex: number, endIndex: number) { + insertFrameRange(componentId: number, parent: Element, childIndex: number, frames: System_Array, startIndex: number, endIndex: number) { for (let index = startIndex; index <= endIndex; index++) { - const node = getTreeNodePtr(nodes, index); - this.insertNode(componentId, parent, childIndex, nodes, node, index); + const frame = getTreeFramePtr(frames, index); + this.insertFrame(componentId, parent, childIndex, frames, frame, index); childIndex++; // Skip over any descendants, since they are already dealt with recursively - const descendantsEndIndex = renderTreeNode.descendantsEndIndex(node); + const descendantsEndIndex = renderTreeFrame.descendantsEndIndex(frame); if (descendantsEndIndex > 0) { index = descendantsEndIndex; } @@ -229,7 +229,7 @@ function removeAttributeFromDOM(parent: Element, childIndex: number, attributeNa element.removeAttribute(attributeName); } -function raiseEvent(browserRendererId: number, componentId: number, renderTreeNodeIndex: number, eventInfoType: EventInfoType, eventInfo: any) { +function raiseEvent(browserRendererId: number, componentId: number, renderTreeFrameIndex: number, eventInfoType: EventInfoType, eventInfo: any) { if (!raiseEventMethod) { raiseEventMethod = platform.findMethod( 'Microsoft.AspNetCore.Blazor.Browser', 'Microsoft.AspNetCore.Blazor.Browser.Rendering', 'BrowserRendererEventDispatcher', 'DispatchEvent' @@ -239,7 +239,7 @@ function raiseEvent(browserRendererId: number, componentId: number, renderTreeNo const eventDescriptor = { BrowserRendererId: browserRendererId, ComponentId: componentId, - RenderTreeNodeIndex: renderTreeNodeIndex, + RenderTreeFrameIndex: renderTreeFrameIndex, EventArgsType: eventInfoType }; diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderBatch.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderBatch.ts index fd4f728a65..bb7d8cb7a2 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderBatch.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderBatch.ts @@ -1,6 +1,6 @@ import { Pointer, System_Array } from '../Platform/Platform'; import { platform } from '../Environment'; -import { RenderTreeNodePointer } from './RenderTreeNode'; +import { RenderTreeFramePointer } from './RenderTreeFrame'; import { RenderTreeEditPointer } from './RenderTreeEdit'; // Keep in sync with the structs in .NET code @@ -20,7 +20,7 @@ export const renderTreeDiffStructLength = 4 + 2 * arrayRangeStructLength; export const renderTreeDiff = { componentId: (obj: RenderTreeDiffPointer) => platform.readInt32Field(obj, 0), edits: (obj: RenderTreeDiffPointer) => platform.readStructField>(obj, 4), - currentState: (obj: RenderTreeDiffPointer) => platform.readStructField>(obj, 4 + arrayRangeStructLength), + currentState: (obj: RenderTreeDiffPointer) => platform.readStructField>(obj, 4 + arrayRangeStructLength), }; // Nominal types to ensure only valid pointers are passed to the functions above. diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeEdit.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeEdit.ts index 0a610fc23f..265f7d0ef0 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeEdit.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeEdit.ts @@ -15,8 +15,8 @@ export const renderTreeEdit = { }; export enum EditType { - prependNode = 1, - removeNode = 2, + prependFrame = 1, + removeFrame = 2, setAttribute = 3, removeAttribute = 4, updateText = 5, diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeFrame.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeFrame.ts new file mode 100644 index 0000000000..c4d74c889f --- /dev/null +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeFrame.ts @@ -0,0 +1,34 @@ +import { System_String, System_Array, Pointer } from '../Platform/Platform'; +import { platform } from '../Environment'; +const renderTreeFrameStructLength = 40; + +// To minimise GC pressure, instead of instantiating a JS object to represent each tree frame, +// we work in terms of pointers to the structs on the .NET heap, and use static functions that +// know how to read property values from those structs. + +export function getTreeFramePtr(renderTreeEntries: System_Array, index: number) { + return platform.getArrayEntryPtr(renderTreeEntries, index, renderTreeFrameStructLength); +} + +export const renderTreeFrame = { + // The properties and memory layout must be kept in sync with the .NET equivalent in RenderTreeFrame.cs + frameType: (frame: RenderTreeFramePointer) => platform.readInt32Field(frame, 4) as FrameType, + elementName: (frame: RenderTreeFramePointer) => platform.readStringField(frame, 8), + descendantsEndIndex: (frame: RenderTreeFramePointer) => platform.readInt32Field(frame, 12) as FrameType, + textContent: (frame: RenderTreeFramePointer) => platform.readStringField(frame, 16), + attributeName: (frame: RenderTreeFramePointer) => platform.readStringField(frame, 20), + attributeValue: (frame: RenderTreeFramePointer) => platform.readStringField(frame, 24), + componentId: (frame: RenderTreeFramePointer) => platform.readInt32Field(frame, 32), +}; + +export enum FrameType { + // The values must be kept in sync with the .NET equivalent in RenderTreeFrameType.cs + element = 1, + text = 2, + attribute = 3, + component = 4, +} + +// Nominal type to ensure only valid pointers are passed to the renderTreeFrame functions. +// At runtime the values are just numbers. +export interface RenderTreeFramePointer extends Pointer { RenderTreeFramePointer__DO_NOT_IMPLEMENT: any } diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeNode.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeNode.ts deleted file mode 100644 index 2f6a0d2ab4..0000000000 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/RenderTreeNode.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { System_String, System_Array, Pointer } from '../Platform/Platform'; -import { platform } from '../Environment'; -const renderTreeNodeStructLength = 40; - -// 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 -// know how to read property values from those structs. - -export function getTreeNodePtr(renderTreeEntries: System_Array, index: number) { - return platform.getArrayEntryPtr(renderTreeEntries, index, renderTreeNodeStructLength); -} - -export const renderTreeNode = { - // The properties and memory layout must be kept in sync with the .NET equivalent in RenderTreeNode.cs - nodeType: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 4) as NodeType, - elementName: (node: RenderTreeNodePointer) => platform.readStringField(node, 8), - descendantsEndIndex: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 12) as NodeType, - textContent: (node: RenderTreeNodePointer) => platform.readStringField(node, 16), - attributeName: (node: RenderTreeNodePointer) => platform.readStringField(node, 20), - attributeValue: (node: RenderTreeNodePointer) => platform.readStringField(node, 24), - componentId: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 32), -}; - -export enum NodeType { - // The values must be kept in sync with the .NET equivalent in RenderTreeNodeType.cs - element = 1, - text = 2, - attribute = 3, - component = 4, -} - -// Nominal type to ensure only valid pointers are passed to the renderTreeNode functions. -// At runtime the values are just numbers. -export interface RenderTreeNodePointer extends Pointer { RenderTreeNodePointer__DO_NOT_IMPLEMENT: any } diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/Renderer.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/Renderer.ts index 9c1818ca44..15a2a4b17a 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/Renderer.ts +++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/Renderer.ts @@ -1,7 +1,5 @@ import { System_Object, System_String, System_Array, MethodHandle, Pointer } from '../Platform/Platform'; import { platform } from '../Environment'; -import { getTreeNodePtr, renderTreeNode, NodeType, RenderTreeNodePointer } from './RenderTreeNode'; -import { RenderTreeEditPointer } from './RenderTreeEdit'; import { renderBatch as renderBatchStruct, arrayRange, renderTreeDiffStructLength, renderTreeDiff, RenderBatchPointer, RenderTreeDiffPointer } from './RenderBatch'; import { BrowserRenderer } from './BrowserRenderer'; diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs index 20e93cd35c..a82582a3a8 100644 --- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs +++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs @@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering var browserRenderer = BrowserRendererRegistry.Find(eventDescriptor.BrowserRendererId); browserRenderer.DispatchBrowserEvent( eventDescriptor.ComponentId, - eventDescriptor.RenderTreeNodeIndex, + eventDescriptor.RenderTreeFrameIndex, eventArgs); } @@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering { public int BrowserRendererId { get; set; } public int ComponentId { get; set; } - public int RenderTreeNodeIndex { get; set; } + public int RenderTreeFrameIndex { get; set; } public string EventArgsType { get; set; } } } diff --git a/src/Microsoft.AspNetCore.Blazor.Build/Core/RazorCompilation/Engine/BlazorIntermediateNodeWriter.cs b/src/Microsoft.AspNetCore.Blazor.Build/Core/RazorCompilation/Engine/BlazorIntermediateNodeWriter.cs index d6de896b0a..0223715639 100644 --- a/src/Microsoft.AspNetCore.Blazor.Build/Core/RazorCompilation/Engine/BlazorIntermediateNodeWriter.cs +++ b/src/Microsoft.AspNetCore.Blazor.Build/Core/RazorCompilation/Engine/BlazorIntermediateNodeWriter.cs @@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.RazorCompilation.Engine // To support syntax like (which in turn supports syntax // like ), check whether we are currently in the middle of // writing an element. If so, treat this C# expression as something that should evaluate - // as a RenderTreeNode of type Attribute. + // as a RenderTreeFrame of type Attribute. if (_unconsumedHtml != null) { var token = (IntermediateToken)node.Children.Single(); @@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Core.RazorCompilation.Engine var codeWriter = context.CodeWriter; // TODO: As an optimization, identify static subtrees (i.e., HTML elements in the Razor source - // that contain no C#) and represent them as a new RenderTreeNodeType called StaticElement or + // that contain no C#) and represent them as a new RenderTreeFrameType called StaticElement or // similar. This means you can have arbitrarily deep static subtrees without paying any per- // node cost during rendering or diffing. HtmlToken nextToken; diff --git a/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs b/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs index 11d4696d0c..90f7c30186 100644 --- a/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs +++ b/src/Microsoft.AspNetCore.Blazor/Components/BlazorComponent.cs @@ -44,9 +44,9 @@ namespace Microsoft.AspNetCore.Blazor.Components /// Handles click events by invoking . /// /// The handler to be invoked when the event occurs. - /// A that represents the event handler. - protected RenderTreeNode onclick(Action handler) + /// A that represents the event handler. + protected RenderTreeFrame onclick(Action handler) // Note that the 'sequence' value is updated later when inserted into the tree - => RenderTreeNode.Attribute(0, "onclick", _ => handler()); + => RenderTreeFrame.Attribute(0, "onclick", _ => handler()); } } diff --git a/src/Microsoft.AspNetCore.Blazor/Components/IComponent.cs b/src/Microsoft.AspNetCore.Blazor/Components/IComponent.cs index 4b4e3c143b..446c620b74 100644 --- a/src/Microsoft.AspNetCore.Blazor/Components/IComponent.cs +++ b/src/Microsoft.AspNetCore.Blazor/Components/IComponent.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Blazor.Components /// /// Builds a representing the current state of the component. /// - /// A to which the rendered nodes should be appended. + /// A to which the rendered frames should be appended. void BuildRenderTree(RenderTreeBuilder builder); } } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs index 1969876988..79ff25b5d1 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs @@ -9,14 +9,14 @@ using System.Collections.Generic; namespace Microsoft.AspNetCore.Blazor.RenderTree { /// - /// Provides methods for building a collection of entries. + /// Provides methods for building a collection of entries. /// public class RenderTreeBuilder { private readonly Renderer _renderer; - private readonly ArrayBuilder _entries = new ArrayBuilder(10); + private readonly ArrayBuilder _entries = new ArrayBuilder(10); private readonly Stack _openElementIndices = new Stack(); - private RenderTreeNodeType? _lastNonAttributeNodeType; + private RenderTreeFrameType? _lastNonAttributeFrameType; /// /// Constructs an instance of . @@ -28,21 +28,21 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree } /// - /// Appends a node representing an element, i.e., a container for other nodes. + /// Appends a frame representing an element, i.e., a container for other frames. /// In order for the state to be valid, you must /// also call immediately after appending the - /// new element's child nodes. + /// new element's child frames. /// /// An integer that represents the position of the instruction in the source code. /// A value representing the type of the element. public void OpenElement(int sequence, string elementName) { _openElementIndices.Push(_entries.Count); - Append(RenderTreeNode.Element(sequence, elementName)); + Append(RenderTreeFrame.Element(sequence, elementName)); } /// - /// Marks a previously appended element node as closed. Calls to this method + /// Marks a previously appended element frame as closed. Calls to this method /// must be balanced with calls to . /// public void CloseElement() @@ -52,23 +52,23 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree } /// - /// Appends a node representing text content. + /// Appends a frame representing text content. /// /// An integer that represents the position of the instruction in the source code. - /// Content for the new text node. + /// Content for the new text frame. public void AddText(int sequence, string textContent) - => Append(RenderTreeNode.Text(sequence, textContent)); + => Append(RenderTreeFrame.Text(sequence, textContent)); /// - /// Appends a node representing text content. + /// Appends a frame representing text content. /// /// An integer that represents the position of the instruction in the source code. - /// Content for the new text node. + /// Content for the new text frame. public void AddText(int sequence, object textContent) => AddText(sequence, textContent?.ToString()); /// - /// Appends a node representing a string-valued attribute. + /// Appends a frame representing a string-valued attribute. /// The attribute is associated with the most recently added element. /// /// An integer that represents the position of the instruction in the source code. @@ -77,11 +77,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree public void AddAttribute(int sequence, string name, string value) { AssertCanAddAttribute(); - Append(RenderTreeNode.Attribute(sequence, name, value)); + Append(RenderTreeFrame.Attribute(sequence, name, value)); } /// - /// Appends a node representing an -valued attribute. + /// Appends a frame representing an -valued attribute. /// The attribute is associated with the most recently added element. /// /// An integer that represents the position of the instruction in the source code. @@ -90,11 +90,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree public void AddAttribute(int sequence, string name, UIEventHandler value) { AssertCanAddAttribute(); - Append(RenderTreeNode.Attribute(sequence, name, value)); + Append(RenderTreeFrame.Attribute(sequence, name, value)); } /// - /// Appends a node representing a string-valued attribute. + /// Appends a frame representing a string-valued attribute. /// The attribute is associated with the most recently added element. /// /// An integer that represents the position of the instruction in the source code. @@ -102,14 +102,14 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// The value of the attribute. public void AddAttribute(int sequence, string name, object value) { - if (_lastNonAttributeNodeType == RenderTreeNodeType.Element) + if (_lastNonAttributeFrameType == RenderTreeFrameType.Element) { // Element attribute values can only be strings or UIEventHandler - Append(RenderTreeNode.Attribute(sequence, name, value.ToString())); + Append(RenderTreeFrame.Attribute(sequence, name, value.ToString())); } - else if (_lastNonAttributeNodeType == RenderTreeNodeType.Component) + else if (_lastNonAttributeFrameType == RenderTreeFrameType.Component) { - Append(RenderTreeNode.Attribute(sequence, name, value)); + Append(RenderTreeFrame.Attribute(sequence, name, value)); } else { @@ -119,26 +119,26 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree } /// - /// Appends a node representing an attribute. + /// Appends a frame representing an attribute. /// The attribute is associated with the most recently added element. /// /// An integer that represents the position of the instruction in the source code. /// The name of the attribute. /// The value of the attribute. - public void AddAttribute(int sequence, RenderTreeNode node) + public void AddAttribute(int sequence, RenderTreeFrame frame) { - if (node.NodeType != RenderTreeNodeType.Attribute) + if (frame.FrameType != RenderTreeFrameType.Attribute) { - throw new ArgumentException($"The {nameof(node.NodeType)} must be {RenderTreeNodeType.Attribute}."); + throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}."); } AssertCanAddAttribute(); - node.SetSequence(sequence); - Append(node); + frame.SetSequence(sequence); + Append(frame); } /// - /// Appends a node representing a child component. + /// Appends a frame representing a child component. /// /// The type of the child component. /// An integer that represents the position of the instruction in the source code. @@ -146,21 +146,21 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree { // Currently, child components can't have further grandchildren of their own, so it would // technically be possible to skip their CloseElement calls and not track them in _openElementIndices. - // However at some point we might want to have the grandchildren nodes available at runtime + // However at some point we might want to have the grandchildren frames available at runtime // (rather than being parsed as attributes at compile time) so that we could have APIs for - // components to query the complete hierarchy of transcluded nodes instead of forcing the + // components to query the complete hierarchy of transcluded frames instead of forcing the // transcluded subtree to be in a particular shape such as representing key/value pairs. - // So it's more flexible if we track open/close nodes for components explicitly. + // So it's more flexible if we track open/close frames for components explicitly. _openElementIndices.Push(_entries.Count); - Append(RenderTreeNode.ChildComponent(sequence)); + Append(RenderTreeFrame.ChildComponent(sequence)); } private void AssertCanAddAttribute() { - if (_lastNonAttributeNodeType != RenderTreeNodeType.Element - && _lastNonAttributeNodeType != RenderTreeNodeType.Component) + if (_lastNonAttributeFrameType != RenderTreeFrameType.Element + && _lastNonAttributeFrameType != RenderTreeFrameType.Component) { - throw new InvalidOperationException($"Attributes may only be added immediately after nodes of type {RenderTreeNodeType.Element} or {RenderTreeNodeType.Component}"); + throw new InvalidOperationException($"Attributes may only be added immediately after frames of type {RenderTreeFrameType.Element} or {RenderTreeFrameType.Component}"); } } @@ -171,24 +171,24 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree { _entries.Clear(); _openElementIndices.Clear(); - _lastNonAttributeNodeType = null; + _lastNonAttributeFrameType = null; } /// - /// Returns the values that have been appended. + /// Returns the values that have been appended. /// - /// An array range of values. - public ArrayRange GetNodes() => + /// An array range of values. + public ArrayRange GetFrames() => _entries.ToRange(); - private void Append(in RenderTreeNode node) + private void Append(in RenderTreeFrame frame) { - _entries.Append(node); + _entries.Append(frame); - var nodeType = node.NodeType; - if (nodeType != RenderTreeNodeType.Attribute) + var frameType = frame.FrameType; + if (frameType != RenderTreeFrameType.Attribute) { - _lastNonAttributeNodeType = node.NodeType; + _lastNonAttributeFrameType = frame.FrameType; } } } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs index 0c117937c5..7da223a010 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs @@ -25,12 +25,12 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// Gets the latest render tree. That is, the result of applying the /// to the previous state. /// - public ArrayRange CurrentState { get; } + public ArrayRange CurrentState { get; } internal RenderTreeDiff( int componentId, ArrayRange entries, - ArrayRange referenceTree) + ArrayRange referenceTree) { ComponentId = componentId; Edits = entries; diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs index 57dedac2d0..b04c16e2b0 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs @@ -20,15 +20,15 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// /// As well as computing the diff between the two trees, this method also has the side-effect - /// of instantiating child components on newly-inserted Component nodes, and copying the existing - /// component instances onto retained Component nodes. It's particularly convenient to do that + /// of instantiating child components on newly-inserted Component frames, and copying the existing + /// component instances onto retained Component frames. It's particularly convenient to do that /// here because we have the right information and are already walking the trees to do the diff. /// public void ApplyNewRenderTreeVersion( RenderBatchBuilder batchBuilder, int componentId, - ArrayRange oldTree, - ArrayRange newTree) + ArrayRange oldTree, + ArrayRange newTree) { _entries.Clear(); var siblingIndex = 0; @@ -42,8 +42,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree private void AppendDiffEntriesForRange( RenderBatchBuilder batchBuilder, - RenderTreeNode[] oldTree, int oldStartIndex, int oldEndIndexExcl, - RenderTreeNode[] newTree, int newStartIndex, int newEndIndexExcl, + RenderTreeFrame[] oldTree, int oldStartIndex, int oldEndIndexExcl, + RenderTreeFrame[] newTree, int newStartIndex, int newEndIndexExcl, ref int siblingIndex) { var hasMoreOld = oldEndIndexExcl > oldStartIndex; @@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree if (oldSeq == newSeq) { - AppendDiffEntriesForNodesWithSameSequence(batchBuilder, oldTree, oldStartIndex, newTree, newStartIndex, ref siblingIndex); + AppendDiffEntriesForFramesWithSameSequence(batchBuilder, oldTree, oldStartIndex, newTree, newStartIndex, ref siblingIndex); oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); hasMoreOld = oldEndIndexExcl > oldStartIndex; @@ -132,22 +132,22 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree if (treatAsInsert) { - ref var newNode = ref newTree[newStartIndex]; - var newNodeType = newNode.NodeType; - if (newNodeType == RenderTreeNodeType.Attribute) + ref var newFrame = ref newTree[newStartIndex]; + var newFrameType = newFrame.FrameType; + if (newFrameType == RenderTreeFrameType.Attribute) { Append(RenderTreeEdit.SetAttribute(siblingIndex, newStartIndex)); newStartIndex++; } else { - if (newNodeType == RenderTreeNodeType.Element || newNodeType == RenderTreeNodeType.Component) + if (newFrameType == RenderTreeFrameType.Element || newFrameType == RenderTreeFrameType.Component) { InstantiateChildComponents(batchBuilder, newTree, newStartIndex); } - Append(RenderTreeEdit.PrependNode(siblingIndex, newStartIndex)); - newStartIndex = NextSiblingIndex(newNode, newStartIndex); + Append(RenderTreeEdit.PrependFrame(siblingIndex, newStartIndex)); + newStartIndex = NextSiblingIndex(newFrame, newStartIndex); siblingIndex++; } @@ -156,22 +156,22 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree } else { - ref var oldNode = ref oldTree[oldStartIndex]; - var oldNodeType = oldNode.NodeType; - if (oldNodeType == RenderTreeNodeType.Attribute) + ref var oldFrame = ref oldTree[oldStartIndex]; + var oldFrameType = oldFrame.FrameType; + if (oldFrameType == RenderTreeFrameType.Attribute) { - Append(RenderTreeEdit.RemoveAttribute(siblingIndex, oldNode.AttributeName)); + Append(RenderTreeEdit.RemoveAttribute(siblingIndex, oldFrame.AttributeName)); oldStartIndex++; } else { - if (oldNodeType == RenderTreeNodeType.Element || oldNodeType == RenderTreeNodeType.Component) + if (oldFrameType == RenderTreeFrameType.Element || oldFrameType == RenderTreeFrameType.Component) { DisposeChildComponents(batchBuilder, oldTree, oldStartIndex); } - Append(RenderTreeEdit.RemoveNode(siblingIndex)); - oldStartIndex = NextSiblingIndex(oldNode, oldStartIndex); + Append(RenderTreeEdit.RemoveFrame(siblingIndex)); + oldStartIndex = NextSiblingIndex(oldFrame, oldStartIndex); } hasMoreOld = oldEndIndexExcl > oldStartIndex; prevOldSeq = oldSeq; @@ -182,28 +182,28 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree private void UpdateRetainedChildComponent( RenderBatchBuilder batchBuilder, - RenderTreeNode[] oldTree, int oldComponentIndex, - RenderTreeNode[] newTree, int newComponentIndex) + RenderTreeFrame[] oldTree, int oldComponentIndex, + RenderTreeFrame[] newTree, int newComponentIndex) { // The algorithm here is the same as in AppendDiffEntriesForRange, except that // here we don't optimise for loops - we assume that both sequences are forward-only. // That's because this is true for all currently supported scenarios, and it means // fewer steps here. - ref var oldComponentNode = ref oldTree[oldComponentIndex]; - ref var newComponentNode = ref newTree[newComponentIndex]; - var componentId = oldComponentNode.ComponentId; - var componentInstance = oldComponentNode.Component; + ref var oldComponentFrame = ref oldTree[oldComponentIndex]; + ref var newComponentFrame = ref newTree[newComponentIndex]; + var componentId = oldComponentFrame.ComponentId; + var componentInstance = oldComponentFrame.Component; var hasSetAnyProperty = false; // Preserve the actual componentInstance - newComponentNode.SetChildComponentInstance(componentId, componentInstance); + newComponentFrame.SetChildComponentInstance(componentId, componentInstance); // Now locate any added/changed/removed properties var oldStartIndex = oldComponentIndex + 1; var newStartIndex = newComponentIndex + 1; - var oldEndIndexIncl = oldComponentNode.ElementDescendantsEndIndex; - var newEndIndexIncl = newComponentNode.ElementDescendantsEndIndex; + var oldEndIndexIncl = oldComponentFrame.ElementDescendantsEndIndex; + var newEndIndexIncl = newComponentFrame.ElementDescendantsEndIndex; var hasMoreOld = oldEndIndexIncl >= oldStartIndex; var hasMoreNew = newEndIndexIncl >= newStartIndex; while (hasMoreOld || hasMoreNew) @@ -213,15 +213,15 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree if (oldSeq == newSeq) { - ref var oldNode = ref oldTree[oldStartIndex]; - ref var newNode = ref newTree[newStartIndex]; - var oldName = oldNode.AttributeName; - var newName = newNode.AttributeName; - var newPropertyValue = newNode.AttributeValue; + ref var oldFrame = ref oldTree[oldStartIndex]; + ref var newFrame = ref newTree[newStartIndex]; + var oldName = oldFrame.AttributeName; + var newName = newFrame.AttributeName; + var newPropertyValue = newFrame.AttributeValue; if (string.Equals(oldName, newName, StringComparison.Ordinal)) { // Using Equals to account for string comparisons, nulls, etc. - var oldPropertyValue = oldNode.AttributeValue; + var oldPropertyValue = oldFrame.AttributeValue; if (!Equals(oldPropertyValue, newPropertyValue)) { SetChildComponentProperty(componentInstance, newName, newPropertyValue); @@ -252,16 +252,16 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree if (treatAsInsert) { - ref var newNode = ref newTree[newStartIndex]; - SetChildComponentProperty(componentInstance, newNode.AttributeName, newNode.AttributeValue); + ref var newFrame = ref newTree[newStartIndex]; + SetChildComponentProperty(componentInstance, newFrame.AttributeName, newFrame.AttributeValue); hasSetAnyProperty = true; newStartIndex++; hasMoreNew = newEndIndexIncl >= newStartIndex; } else { - ref var oldNode = ref oldTree[oldStartIndex]; - RemoveChildComponentProperty(componentInstance, oldNode.AttributeName); + ref var oldFrame = ref oldTree[oldStartIndex]; + RemoveChildComponentProperty(componentInstance, oldFrame.AttributeName); hasSetAnyProperty = true; oldStartIndex++; hasMoreOld = oldEndIndexIncl >= oldStartIndex; @@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree if (hasSetAnyProperty) { - TriggerChildComponentRender(batchBuilder, newComponentNode); + TriggerChildComponentRender(batchBuilder, newComponentFrame); } } @@ -312,67 +312,67 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree return property; } - private static int NextSiblingIndex(in RenderTreeNode node, int nodeIndex) + private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex) { - var descendantsEndIndex = node.ElementDescendantsEndIndex; - return (descendantsEndIndex == 0 ? nodeIndex : descendantsEndIndex) + 1; + var descendantsEndIndex = frame.ElementDescendantsEndIndex; + return (descendantsEndIndex == 0 ? frameIndex : descendantsEndIndex) + 1; } - private void AppendDiffEntriesForNodesWithSameSequence( + private void AppendDiffEntriesForFramesWithSameSequence( RenderBatchBuilder batchBuilder, - RenderTreeNode[] oldTree, int oldNodeIndex, - RenderTreeNode[] newTree, int newNodeIndex, + RenderTreeFrame[] oldTree, int oldFrameIndex, + RenderTreeFrame[] newTree, int newFrameIndex, ref int siblingIndex) { - ref var oldNode = ref oldTree[oldNodeIndex]; - ref var newNode = ref newTree[newNodeIndex]; + ref var oldFrame = ref oldTree[oldFrameIndex]; + ref var newFrame = ref newTree[newFrameIndex]; - // We can assume that the old and new nodes are of the same type, because they correspond + // We can assume that the old and new frames are of the same type, because they correspond // to the same sequence number (and if not, the behaviour is undefined). - switch (newTree[newNodeIndex].NodeType) + switch (newTree[newFrameIndex].FrameType) { - case RenderTreeNodeType.Text: + case RenderTreeFrameType.Text: { - var oldText = oldNode.TextContent; - var newText = newNode.TextContent; + var oldText = oldFrame.TextContent; + var newText = newFrame.TextContent; if (!string.Equals(oldText, newText, StringComparison.Ordinal)) { - Append(RenderTreeEdit.UpdateText(siblingIndex, newNodeIndex)); + Append(RenderTreeEdit.UpdateText(siblingIndex, newFrameIndex)); } siblingIndex++; break; } - case RenderTreeNodeType.Element: + case RenderTreeFrameType.Element: { - var oldElementName = oldNode.ElementName; - var newElementName = newNode.ElementName; + var oldElementName = oldFrame.ElementName; + var newElementName = newFrame.ElementName; if (string.Equals(oldElementName, newElementName, StringComparison.Ordinal)) { - var oldNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldNodeIndex); - var newNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(newTree, newNodeIndex); + var oldFrameAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldFrameIndex); + var newFrameAttributesEndIndexExcl = GetAttributesEndIndexExclusive(newTree, newFrameIndex); // Diff the attributes AppendDiffEntriesForRange( batchBuilder, - oldTree, oldNodeIndex + 1, oldNodeAttributesEndIndexExcl, - newTree, newNodeIndex + 1, newNodeAttributesEndIndexExcl, + oldTree, oldFrameIndex + 1, oldFrameAttributesEndIndexExcl, + newTree, newFrameIndex + 1, newFrameAttributesEndIndexExcl, ref siblingIndex); // Diff the children - var oldNodeChildrenEndIndexExcl = oldNode.ElementDescendantsEndIndex + 1; - var newNodeChildrenEndIndexExcl = newNode.ElementDescendantsEndIndex + 1; + var oldFrameChildrenEndIndexExcl = oldFrame.ElementDescendantsEndIndex + 1; + var newFrameChildrenEndIndexExcl = newFrame.ElementDescendantsEndIndex + 1; var hasChildrenToProcess = - oldNodeChildrenEndIndexExcl > oldNodeAttributesEndIndexExcl || - newNodeChildrenEndIndexExcl > newNodeAttributesEndIndexExcl; + oldFrameChildrenEndIndexExcl > oldFrameAttributesEndIndexExcl || + newFrameChildrenEndIndexExcl > newFrameAttributesEndIndexExcl; if (hasChildrenToProcess) { Append(RenderTreeEdit.StepIn(siblingIndex)); var childSiblingIndex = 0; AppendDiffEntriesForRange( batchBuilder, - oldTree, oldNodeAttributesEndIndexExcl, oldNodeChildrenEndIndexExcl, - newTree, newNodeAttributesEndIndexExcl, newNodeChildrenEndIndexExcl, + oldTree, oldFrameAttributesEndIndexExcl, oldFrameChildrenEndIndexExcl, + newTree, newFrameAttributesEndIndexExcl, newFrameChildrenEndIndexExcl, ref childSiblingIndex); Append(RenderTreeEdit.StepOut()); siblingIndex++; @@ -385,51 +385,51 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree else { // Elements with different names are treated as completely unrelated - InstantiateChildComponents(batchBuilder, newTree, newNodeIndex); - DisposeChildComponents(batchBuilder, oldTree, oldNodeIndex); - Append(RenderTreeEdit.PrependNode(siblingIndex, newNodeIndex)); + InstantiateChildComponents(batchBuilder, newTree, newFrameIndex); + DisposeChildComponents(batchBuilder, oldTree, oldFrameIndex); + Append(RenderTreeEdit.PrependFrame(siblingIndex, newFrameIndex)); siblingIndex++; - Append(RenderTreeEdit.RemoveNode(siblingIndex)); + Append(RenderTreeEdit.RemoveFrame(siblingIndex)); } break; } - case RenderTreeNodeType.Component: + case RenderTreeFrameType.Component: { - var oldComponentType = oldNode.ComponentType; - var newComponentType = newNode.ComponentType; + var oldComponentType = oldFrame.ComponentType; + var newComponentType = newFrame.ComponentType; if (oldComponentType == newComponentType) { UpdateRetainedChildComponent( batchBuilder, - oldTree, oldNodeIndex, - newTree, newNodeIndex); + oldTree, oldFrameIndex, + newTree, newFrameIndex); siblingIndex++; } else { // Child components of different types are treated as completely unrelated - InstantiateChildComponents(batchBuilder, newTree, newNodeIndex); - DisposeChildComponents(batchBuilder, oldTree, oldNodeIndex); - Append(RenderTreeEdit.PrependNode(siblingIndex, newNodeIndex)); + InstantiateChildComponents(batchBuilder, newTree, newFrameIndex); + DisposeChildComponents(batchBuilder, oldTree, oldFrameIndex); + Append(RenderTreeEdit.PrependFrame(siblingIndex, newFrameIndex)); siblingIndex++; - Append(RenderTreeEdit.RemoveNode(siblingIndex)); + Append(RenderTreeEdit.RemoveFrame(siblingIndex)); } break; } - case RenderTreeNodeType.Attribute: + case RenderTreeFrameType.Attribute: { - var oldName = oldNode.AttributeName; - var newName = newNode.AttributeName; + var oldName = oldFrame.AttributeName; + var newName = newFrame.AttributeName; if (string.Equals(oldName, newName, StringComparison.Ordinal)) { // Using Equals to account for string comparisons, nulls, etc. - var valueChanged = !Equals(oldNode.AttributeValue, newNode.AttributeValue); + var valueChanged = !Equals(oldFrame.AttributeValue, newFrame.AttributeValue); if (valueChanged) { - Append(RenderTreeEdit.SetAttribute(siblingIndex, newNodeIndex)); + Append(RenderTreeEdit.SetAttribute(siblingIndex, newFrameIndex)); } } else @@ -437,24 +437,24 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree // Since this code path is never reachable for Razor components (because you // can't have two different attribute names from the same source sequence), we // could consider removing the 'name equality' check entirely for perf - Append(RenderTreeEdit.SetAttribute(siblingIndex, newNodeIndex)); + Append(RenderTreeEdit.SetAttribute(siblingIndex, newFrameIndex)); Append(RenderTreeEdit.RemoveAttribute(siblingIndex, oldName)); } break; } default: - throw new NotImplementedException($"Encountered unsupported node type during diffing: {newTree[newNodeIndex].NodeType}"); + throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}"); } } - private int GetAttributesEndIndexExclusive(RenderTreeNode[] tree, int rootIndex) + private int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex) { var descendantsEndIndex = tree[rootIndex].ElementDescendantsEndIndex; var index = rootIndex + 1; for (; index <= descendantsEndIndex; index++) { - if (tree[index].NodeType != RenderTreeNodeType.Attribute) + if (tree[index].FrameType != RenderTreeFrameType.Attribute) { break; } @@ -467,7 +467,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree { if (entry.Type == RenderTreeEditType.StepOut) { - // If the preceding node is a StepIn, then the StepOut cancels it out + // If the preceding frame is a StepIn, then the StepOut cancels it out var previousIndex = _entries.Count - 1; if (previousIndex >= 0 && _entries.Buffer[previousIndex].Type == RenderTreeEditType.StepIn) { @@ -479,41 +479,41 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree _entries.Append(entry); } - private void InstantiateChildComponents(RenderBatchBuilder batchBuilder, RenderTreeNode[] nodes, int elementOrComponentIndex) + private void InstantiateChildComponents(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int elementOrComponentIndex) { - var endIndex = nodes[elementOrComponentIndex].ElementDescendantsEndIndex; + var endIndex = frames[elementOrComponentIndex].ElementDescendantsEndIndex; for (var i = elementOrComponentIndex; i <= endIndex; i++) { - ref var node = ref nodes[i]; - if (node.NodeType == RenderTreeNodeType.Component) + ref var frame = ref frames[i]; + if (frame.FrameType == RenderTreeFrameType.Component) { - if (node.Component != null) + if (frame.Component != null) { throw new InvalidOperationException($"Child component already exists during {nameof(InstantiateChildComponents)}"); } - _renderer.InstantiateChildComponent(nodes, i); - var childComponentInstance = node.Component; + _renderer.InstantiateChildComponent(frames, i); + var childComponentInstance = frame.Component; // All descendants of a component are its properties - var componentDescendantsEndIndex = node.ElementDescendantsEndIndex; - for (var attributeNodeIndex = i + 1; attributeNodeIndex <= componentDescendantsEndIndex; attributeNodeIndex++) + var componentDescendantsEndIndex = frame.ElementDescendantsEndIndex; + for (var attributeFrameIndex = i + 1; attributeFrameIndex <= componentDescendantsEndIndex; attributeFrameIndex++) { - ref var attributeNode = ref nodes[attributeNodeIndex]; + ref var attributeFrame = ref frames[attributeFrameIndex]; SetChildComponentProperty( childComponentInstance, - attributeNode.AttributeName, - attributeNode.AttributeValue); + attributeFrame.AttributeName, + attributeFrame.AttributeValue); } - TriggerChildComponentRender(batchBuilder, node); + TriggerChildComponentRender(batchBuilder, frame); } } } - private void TriggerChildComponentRender(RenderBatchBuilder batchBuilder, in RenderTreeNode node) + private void TriggerChildComponentRender(RenderBatchBuilder batchBuilder, in RenderTreeFrame frame) { - if (node.Component is IHandlePropertiesChanged notifyableComponent) + if (frame.Component is IHandlePropertiesChanged notifyableComponent) { // TODO: Ensure any exceptions thrown here are handled equivalently to // unhandled exceptions during rendering. @@ -525,18 +525,18 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree // can control whether any given set of property changes cause re-rendering. // Not doing so yet because it's unclear that the usage patterns would be // good to use. - _renderer.RenderInExistingBatch(batchBuilder, node.ComponentId); + _renderer.RenderInExistingBatch(batchBuilder, frame.ComponentId); } - private void DisposeChildComponents(RenderBatchBuilder batchBuilder, RenderTreeNode[] nodes, int elementOrComponentIndex) + private void DisposeChildComponents(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int elementOrComponentIndex) { - var endIndex = nodes[elementOrComponentIndex].ElementDescendantsEndIndex; + var endIndex = frames[elementOrComponentIndex].ElementDescendantsEndIndex; for (var i = elementOrComponentIndex; i <= endIndex; i++) { - ref var node = ref nodes[i]; - if (node.NodeType == RenderTreeNodeType.Component) + ref var frame = ref frames[i]; + if (frame.FrameType == RenderTreeFrameType.Component) { - _renderer.DisposeInExistingBatch(batchBuilder, node.ComponentId); + _renderer.DisposeInExistingBatch(batchBuilder, frame.ComponentId); } } } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs index 6f1556a4af..460c9f6f20 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs @@ -14,14 +14,14 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree public RenderTreeEditType Type { get; private set; } /// - /// Gets the index of the sibling node that the edit relates to. + /// Gets the index of the sibling frame that the edit relates to. /// public int SiblingIndex { get; private set; } /// /// Gets the index of related data in an associated render tree. For example, if the - /// value is , gets the - /// index of the new node data in an associated render tree. + /// value is , gets the + /// index of the new frame data in an associated render tree. /// public int NewTreeIndex { get; private set; } @@ -31,15 +31,15 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// public string RemovedAttributeName { get; private set; } - internal static RenderTreeEdit RemoveNode(int siblingIndex) => new RenderTreeEdit + internal static RenderTreeEdit RemoveFrame(int siblingIndex) => new RenderTreeEdit { - Type = RenderTreeEditType.RemoveNode, + Type = RenderTreeEditType.RemoveFrame, SiblingIndex = siblingIndex }; - internal static RenderTreeEdit PrependNode(int siblingIndex, int newTreeIndex) => new RenderTreeEdit + internal static RenderTreeEdit PrependFrame(int siblingIndex, int newTreeIndex) => new RenderTreeEdit { - Type = RenderTreeEditType.PrependNode, + Type = RenderTreeEditType.PrependFrame, SiblingIndex = siblingIndex, NewTreeIndex = newTreeIndex }; @@ -51,11 +51,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree NewTreeIndex = newTreeIndex }; - internal static RenderTreeEdit SetAttribute(int siblingIndex, int newNodeIndex) => new RenderTreeEdit + internal static RenderTreeEdit SetAttribute(int siblingIndex, int newFrameIndex) => new RenderTreeEdit { Type = RenderTreeEditType.SetAttribute, SiblingIndex = siblingIndex, - NewTreeIndex = newNodeIndex + NewTreeIndex = newFrameIndex }; internal static RenderTreeEdit RemoveAttribute(int siblingIndex, string name) => new RenderTreeEdit diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEditType.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEditType.cs index cfa5589079..7fcec8b7ca 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEditType.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEditType.cs @@ -9,40 +9,40 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree public enum RenderTreeEditType: int { /// - /// Indicates that a new node should be inserted before the specified tree node. + /// Indicates that a new frame should be inserted before the specified tree frame. /// - PrependNode = 1, + PrependFrame = 1, /// - /// Indicates that the specified tree node should be removed. + /// Indicates that the specified tree frame should be removed. /// - RemoveNode = 2, + RemoveFrame = 2, /// - /// Indicates that an attribute value should be applied to the specified node. + /// Indicates that an attribute value should be applied to the specified frame. /// This may be a change to an existing attribute, or the addition of a new attribute. /// SetAttribute = 3, /// - /// Indicates that a named attribute should be removed from the specified node. + /// Indicates that a named attribute should be removed from the specified frame. /// RemoveAttribute = 4, /// - /// Indicates that the text content of the specified node (which must be a text node) + /// Indicates that the text content of the specified frame (which must be a text frame) /// should be updated. /// UpdateText = 5, /// - /// Indicates that the edit position should move inside the specified node. + /// Indicates that the edit position should move inside the specified frame. /// StepIn = 6, /// - /// Indicates that there are no further edit operations on the current node, and the - /// edit position should move back to the parent node. + /// Indicates that there are no further edit operations on the current frame, and the + /// edit position should move back to the parent frame. /// StepOut = 7, } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNode.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrame.cs similarity index 55% rename from src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNode.cs rename to src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrame.cs index 89399caadb..24da02990a 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNode.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrame.cs @@ -13,111 +13,111 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree /// /// Represents an entry in a tree of user interface (UI) items. /// - public struct RenderTreeNode + public struct RenderTreeFrame { /// - /// Gets the sequence number of the node. Sequence numbers indicate the relative source - /// positions of the instructions that inserted the nodes. Sequence numbers are only + /// Gets the sequence number of the frame. Sequence numbers indicate the relative source + /// positions of the instructions that inserted the frames. Sequence numbers are only /// comparable within the same sequence (typically, the same source method). /// public int Sequence { get; private set; } /// - /// Describes the type of this node. + /// Describes the type of this frame. /// - public RenderTreeNodeType NodeType { get; private set; } + public RenderTreeFrameType FrameType { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets a name representing the type of the element. Otherwise, the value is . /// public string ElementName { get; private set; } /// - /// If the property equals , - /// gets the index of the final descendant node in the tree. The value is - /// zero if the node is of a different type, or if it has not yet been closed. + /// If the property equals , + /// gets the index of the final descendant frame in the tree. The value is + /// zero if the frame is of a different type, or if it has not yet been closed. /// public int ElementDescendantsEndIndex { get; private set; } /// - /// If the property equals , - /// gets the content of the text node. Otherwise, the value is . + /// If the property equals , + /// gets the content of the text frame. Otherwise, the value is . /// public string TextContent { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets the attribute name. Otherwise, the value is . /// public string AttributeName { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets the attribute value. Otherwise, the value is . /// public object AttributeValue { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets the type of the child component. /// public Type ComponentType { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets the child component instance identifier. /// public int ComponentId { get; private set; } /// - /// If the property equals , + /// If the property equals , /// gets the child component instance. Otherwise, the value is . /// public IComponent Component { get; private set; } - internal static RenderTreeNode Element(int sequence, string elementName) => new RenderTreeNode + internal static RenderTreeFrame Element(int sequence, string elementName) => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Element, + FrameType = RenderTreeFrameType.Element, ElementName = elementName, }; - internal static RenderTreeNode Text(int sequence, string textContent) => new RenderTreeNode + internal static RenderTreeFrame Text(int sequence, string textContent) => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Text, + FrameType = RenderTreeFrameType.Text, TextContent = textContent ?? string.Empty, }; - internal static RenderTreeNode Attribute(int sequence, string name, string value) => new RenderTreeNode + internal static RenderTreeFrame Attribute(int sequence, string name, string value) => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Attribute, + FrameType = RenderTreeFrameType.Attribute, AttributeName = name, AttributeValue = value }; - internal static RenderTreeNode Attribute(int sequence, string name, UIEventHandler value) => new RenderTreeNode + internal static RenderTreeFrame Attribute(int sequence, string name, UIEventHandler value) => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Attribute, + FrameType = RenderTreeFrameType.Attribute, AttributeName = name, AttributeValue = value }; - internal static RenderTreeNode Attribute(int sequence, string name, object value) => new RenderTreeNode + internal static RenderTreeFrame Attribute(int sequence, string name, object value) => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Attribute, + FrameType = RenderTreeFrameType.Attribute, AttributeName = name, AttributeValue = value }; - internal static RenderTreeNode ChildComponent(int sequence) where T: IComponent => new RenderTreeNode + internal static RenderTreeFrame ChildComponent(int sequence) where T: IComponent => new RenderTreeFrame { Sequence = sequence, - NodeType = RenderTreeNodeType.Component, + FrameType = RenderTreeFrameType.Component, ComponentType = typeof(T) }; @@ -134,8 +134,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree internal void SetSequence(int sequence) { - // This is only used when appending attribute nodes, because helpers such as @onclick - // need to construct the attribute node in a context where they don't know the sequence + // This is only used when appending attribute frames, because helpers such as @onclick + // need to construct the attribute frame in a context where they don't know the sequence // number, so we assign it later Sequence = sequence; } diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNodeType.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrameType.cs similarity index 78% rename from src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNodeType.cs rename to src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrameType.cs index faec2139d6..9a899c84ec 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeNodeType.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeFrameType.cs @@ -4,12 +4,12 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree { /// - /// Describes the type of a . + /// Describes the type of a . /// - public enum RenderTreeNodeType: int + public enum RenderTreeFrameType: int { /// - /// Represents a container for other nodes. + /// Represents a container for other frames. /// Element = 1, @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree Text = 2, /// - /// Represents a key-value pair associated with another . + /// Represents a key-value pair associated with another . /// Attribute = 3, diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventHandler.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventHandler.cs index 88de0ec25f..37b78f6b0f 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventHandler.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/UIEventHandler.cs @@ -4,7 +4,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree { /// - /// Handles an event raised for a . + /// Handles an event raised for a . /// public delegate void UIEventHandler(UIEventArgs eventArgs); } diff --git a/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs b/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs index c38b050d38..3c8c441f12 100644 --- a/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs +++ b/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs @@ -51,14 +51,14 @@ namespace Microsoft.AspNetCore.Blazor.Rendering _diffComputer.ApplyNewRenderTreeVersion( batchBuilder, _componentId, - _renderTreeBuilderPrevious.GetNodes(), - _renderTreeBuilderCurrent.GetNodes()); + _renderTreeBuilderPrevious.GetFrames(), + _renderTreeBuilderCurrent.GetFrames()); } /// /// Invokes the handler corresponding to an event. /// - /// The index of the current render tree node that holds the event handler to be invoked. + /// The index of the current render tree frame that holds the event handler to be invoked. /// Arguments to be passed to the event handler. public void DispatchEvent(int renderTreeIndex, UIEventArgs eventArgs) { @@ -67,11 +67,11 @@ namespace Microsoft.AspNetCore.Blazor.Rendering throw new ArgumentNullException(nameof(eventArgs)); } - var nodes = _renderTreeBuilderCurrent.GetNodes(); - var eventHandler = nodes.Array[renderTreeIndex].AttributeValue as UIEventHandler; + var frames = _renderTreeBuilderCurrent.GetFrames(); + var eventHandler = frames.Array[renderTreeIndex].AttributeValue as UIEventHandler; if (eventHandler == null) { - throw new ArgumentException($"The render tree node at index {renderTreeIndex} does not specify a {nameof(UIEventHandler)}."); + throw new ArgumentException($"The render tree frame at index {renderTreeIndex} does not specify a {nameof(UIEventHandler)}."); } eventHandler.Invoke(eventArgs); diff --git a/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs b/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs index d9626a881d..9fa9e43c29 100644 --- a/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs +++ b/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs @@ -111,22 +111,22 @@ namespace Microsoft.AspNetCore.Blazor.Rendering protected void DispatchEvent(int componentId, int renderTreeIndex, UIEventArgs eventArgs) => GetRequiredComponentState(componentId).DispatchEvent(renderTreeIndex, eventArgs); - internal void InstantiateChildComponent(RenderTreeNode[] nodes, int componentNodeIndex) + internal void InstantiateChildComponent(RenderTreeFrame[] frames, int componentFrameIndex) { - ref var node = ref nodes[componentNodeIndex]; - if (node.NodeType != RenderTreeNodeType.Component) + ref var frame = ref frames[componentFrameIndex]; + if (frame.FrameType != RenderTreeFrameType.Component) { - throw new ArgumentException($"The node's {nameof(RenderTreeNode.NodeType)} property must equal {RenderTreeNodeType.Component}", nameof(node)); + throw new ArgumentException($"The frame's {nameof(RenderTreeFrame.FrameType)} property must equal {RenderTreeFrameType.Component}", nameof(frame)); } - if (node.Component != null) + if (frame.Component != null) { - throw new ArgumentException($"The node already has a non-null component instance", nameof(node)); + throw new ArgumentException($"The frame already has a non-null component instance", nameof(frame)); } - var newComponent = (IComponent)Activator.CreateInstance(node.ComponentType); + var newComponent = (IComponent)Activator.CreateInstance(frame.ComponentType); var newComponentId = AssignComponentId(newComponent); - node.SetChildComponentInstance(newComponentId, newComponent); + frame.SetChildComponentInstance(newComponentId, newComponent); } private ComponentState GetRequiredComponentState(int componentId) diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj b/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj index cce46f7ba1..366f470b55 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/Microsoft.AspNetCore.Blazor.Build.Test.csproj @@ -18,7 +18,7 @@ - + diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/RazorCompilerTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/RazorCompilerTest.cs index 8c47c253bb..fcfb919532 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/RazorCompilerTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/RazorCompilerTest.cs @@ -96,8 +96,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test component.BuildRenderTree(treeBuilder); // Assert - Assert.Collection(treeBuilder.GetNodes(), - node => AssertNode.Text(node, "Some plain text", 0)); + Assert.Collection(treeBuilder.GetFrames(), + frame => AssertFrame.Text(frame, "Some plain text", 0)); } [Fact] @@ -112,17 +112,17 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test "); // Assert - var nodes = GetRenderTree(component); - Assert.Collection(nodes, - node => AssertNode.Whitespace(node, 0), - node => AssertNode.Text(node, "Hello", 1), - node => AssertNode.Whitespace(node, 2), - node => AssertNode.Whitespace(node, 3), // @((object)null) - node => AssertNode.Whitespace(node, 4), - node => AssertNode.Text(node, "123", 5), - node => AssertNode.Whitespace(node, 6), - node => AssertNode.Text(node, new object().ToString(), 7), - node => AssertNode.Whitespace(node, 8)); + var frames = GetRenderTree(component); + Assert.Collection(frames, + frame => AssertFrame.Whitespace(frame, 0), + frame => AssertFrame.Text(frame, "Hello", 1), + frame => AssertFrame.Whitespace(frame, 2), + frame => AssertFrame.Whitespace(frame, 3), // @((object)null) + frame => AssertFrame.Whitespace(frame, 4), + frame => AssertFrame.Text(frame, "123", 5), + frame => AssertFrame.Whitespace(frame, 6), + frame => AssertFrame.Text(frame, new object().ToString(), 7), + frame => AssertFrame.Whitespace(frame, 8)); } [Fact] @@ -139,14 +139,14 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test "); // Assert - var nodes = GetRenderTree(component); - Assert.Collection(nodes, - node => AssertNode.Whitespace(node, 0), - node => AssertNode.Text(node, "First", 1), - node => AssertNode.Text(node, "Second", 1), - node => AssertNode.Text(node, "Third", 1), - node => AssertNode.Whitespace(node, 2), - node => AssertNode.Whitespace(node, 3)); + var frames = GetRenderTree(component); + Assert.Collection(frames, + frame => AssertFrame.Whitespace(frame, 0), + frame => AssertFrame.Text(frame, "First", 1), + frame => AssertFrame.Text(frame, "Second", 1), + frame => AssertFrame.Text(frame, "Third", 1), + frame => AssertFrame.Whitespace(frame, 2), + frame => AssertFrame.Whitespace(frame, 3)); } [Fact] @@ -157,8 +157,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "myelem", 1, 0), - node => AssertNode.Text(node, "Hello", 1)); + frame => AssertFrame.Element(frame, "myelem", 1, 0), + frame => AssertFrame.Text(frame, "Hello", 1)); } [Fact] @@ -169,8 +169,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Text(node, "Some text so elem isn't at position 0 ", 0), - node => AssertNode.Element(node, "myelem", 1, 1)); + frame => AssertFrame.Text(frame, "Some text so elem isn't at position 0 ", 0), + frame => AssertFrame.Element(frame, "myelem", 1, 1)); } [Fact] @@ -181,8 +181,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Text(node, "Some text so elem isn't at position 0 ", 0), - node => AssertNode.Element(node, "img", 1, 1)); + frame => AssertFrame.Text(frame, "Some text so elem isn't at position 0 ", 0), + frame => AssertFrame.Element(frame, "img", 1, 1)); } [Fact] @@ -193,9 +193,9 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 2, 0), - node => AssertNode.Attribute(node, "attrib-one", "Value 1", 1), - node => AssertNode.Attribute(node, "a2", "v2", 2)); + frame => AssertFrame.Element(frame, "elem", 2, 0), + frame => AssertFrame.Attribute(frame, "attrib-one", "Value 1", 1), + frame => AssertFrame.Attribute(frame, "a2", "v2", 2)); } [Fact] @@ -208,8 +208,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 1, 0), - node => AssertNode.Attribute(node, "attr", "My string", 1)); + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => AssertFrame.Attribute(frame, "attr", "My string", 1)); } [Fact] @@ -222,8 +222,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 1, 0), - node => AssertNode.Attribute(node, "attr", "123", 1)); + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => AssertFrame.Attribute(frame, "attr", "123", 1)); } [Fact] @@ -236,8 +236,8 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 1, 0), - node => AssertNode.Attribute(node, "attr", "Hello, WORLD with number 246!", 1)); + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => AssertFrame.Attribute(frame, "attr", "Hello, WORLD with number 246!", 1)); } [Fact] @@ -259,17 +259,17 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.False((bool)handlerWasCalledProperty.GetValue(component)); Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 1, 0), - node => + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => { - Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType); - Assert.Equal(1, node.Sequence); - Assert.NotNull(node.AttributeValue); + Assert.Equal(RenderTreeFrameType.Attribute, frame.FrameType); + Assert.Equal(1, frame.Sequence); + Assert.NotNull(frame.AttributeValue); - ((UIEventHandler)node.AttributeValue)(null); + ((UIEventHandler)frame.AttributeValue)(null); Assert.True((bool)handlerWasCalledProperty.GetValue(component)); }, - node => AssertNode.Whitespace(node, 2)); + frame => AssertFrame.Whitespace(frame, 2)); } [Fact] @@ -282,22 +282,22 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test public bool DidInvokeCode { get; set; } = false; }"); var didInvokeCodeProperty = component.GetType().GetProperty("DidInvokeCode"); - var nodes = GetRenderTree(component); + var frames = GetRenderTree(component); // Assert Assert.False((bool)didInvokeCodeProperty.GetValue(component)); - Assert.Collection(nodes, - node => AssertNode.Element(node, "elem", 1, 0), - node => + Assert.Collection(frames, + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => { - Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType); - Assert.NotNull(node.AttributeValue); - Assert.Equal(1, node.Sequence); + Assert.Equal(RenderTreeFrameType.Attribute, frame.FrameType); + Assert.NotNull(frame.AttributeValue); + Assert.Equal(1, frame.Sequence); - ((UIEventHandler)node.AttributeValue)(null); + ((UIEventHandler)frame.AttributeValue)(null); Assert.True((bool)didInvokeCodeProperty.GetValue(component)); }, - node => AssertNode.Whitespace(node, 2)); + frame => AssertFrame.Whitespace(frame, 2)); } [Fact] @@ -313,13 +313,13 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test component.BuildRenderTree(treeBuilder); // Assert - Assert.Collection(treeBuilder.GetNodes(), - node => AssertNode.Whitespace(node, 0), - node => AssertNode.Text(node, typeof(List).FullName, 1)); + Assert.Collection(treeBuilder.GetFrames(), + frame => AssertFrame.Whitespace(frame, 0), + frame => AssertFrame.Text(frame, typeof(List).FullName, 1)); } [Fact] - public void SupportsAttributeNodesEvaluatedInline() + public void SupportsAttributeFramesEvaluatedInline() { // Arrange/Act var component = CompileToComponent( @@ -336,17 +336,17 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test // Assert Assert.False((bool)didInvokeCodeProperty.GetValue(component)); Assert.Collection(GetRenderTree(component), - node => AssertNode.Element(node, "elem", 1, 0), - node => + frame => AssertFrame.Element(frame, "elem", 1, 0), + frame => { - Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType); - Assert.NotNull(node.AttributeValue); - Assert.Equal(1, node.Sequence); + Assert.Equal(RenderTreeFrameType.Attribute, frame.FrameType); + Assert.NotNull(frame.AttributeValue); + Assert.Equal(1, frame.Sequence); - ((UIEventHandler)node.AttributeValue)(null); + ((UIEventHandler)frame.AttributeValue)(null); Assert.True((bool)didInvokeCodeProperty.GetValue(component)); }, - node => AssertNode.Whitespace(node, 2)); + frame => AssertFrame.Whitespace(frame, 2)); } [Fact] @@ -361,15 +361,15 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test component.BuildRenderTree(treeBuilder); // Assert - Assert.Collection(treeBuilder.GetNodes(), - node => AssertNode.Component(node, 0)); + Assert.Collection(treeBuilder.GetFrames(), + frame => AssertFrame.Component(frame, 0)); } - private static ArrayRange GetRenderTree(IComponent component) + private static ArrayRange GetRenderTree(IComponent component) { var treeBuilder = new RenderTreeBuilder(new TestRenderer()); component.BuildRenderTree(treeBuilder); - return treeBuilder.GetNodes(); + return treeBuilder.GetFrames(); } private static IComponent CompileToComponent(string cshtmlSource) diff --git a/test/Microsoft.AspNetCore.Blazor.Test/Microsoft.AspNetCore.Blazor.Test.csproj b/test/Microsoft.AspNetCore.Blazor.Test/Microsoft.AspNetCore.Blazor.Test.csproj index 180994bd04..299fa84e0f 100644 --- a/test/Microsoft.AspNetCore.Blazor.Test/Microsoft.AspNetCore.Blazor.Test.csproj +++ b/test/Microsoft.AspNetCore.Blazor.Test/Microsoft.AspNetCore.Blazor.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs index 80f12bbdbc..d039cac7c8 100644 --- a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs @@ -29,9 +29,9 @@ namespace Microsoft.AspNetCore.Blazor.Test var builder = new RenderTreeBuilder(new TestRenderer()); // Assert - var nodes = builder.GetNodes(); - Assert.NotNull(nodes.Array); - Assert.Empty(nodes); + var frames = builder.GetFrames(); + Assert.NotNull(frames.Array); + Assert.Empty(frames); } [Fact] @@ -47,11 +47,11 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.AddText(0, "Second item"); // Assert - var nodes = builder.GetNodes(); - Assert.Collection(nodes, - node => AssertNode.Text(node, "First item"), - node => AssertNode.Text(node, string.Empty), - node => AssertNode.Text(node, "Second item")); + var frames = builder.GetFrames(); + Assert.Collection(frames, + frame => AssertFrame.Text(frame, "First item"), + frame => AssertFrame.Text(frame, string.Empty), + frame => AssertFrame.Text(frame, "Second item")); } [Fact] @@ -66,10 +66,10 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.AddText(0, nullObject); // Assert - var nodes = builder.GetNodes(); - Assert.Collection(nodes, - node => AssertNode.Text(node, "1234"), - node => AssertNode.Text(node, string.Empty)); + var frames = builder.GetFrames(); + Assert.Collection(frames, + frame => AssertFrame.Text(frame, "1234"), + frame => AssertFrame.Text(frame, string.Empty)); } [Fact] @@ -82,8 +82,8 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.OpenElement(0, "my element"); // Assert - var node = builder.GetNodes().Single(); - AssertNode.Element(node, "my element", 0); + var frame = builder.GetFrames().Single(); + AssertFrame.Element(frame, "my element", 0); } [Fact] @@ -93,14 +93,14 @@ namespace Microsoft.AspNetCore.Blazor.Test var builder = new RenderTreeBuilder(new TestRenderer()); // Act - builder.AddText(0, "some node so that the element isn't at position zero"); + builder.AddText(0, "some frame so that the element isn't at position zero"); builder.OpenElement(0, "my element"); builder.CloseElement(); // Assert - var nodes = builder.GetNodes(); - Assert.Equal(2, nodes.Count); - AssertNode.Element(nodes.Array[1], "my element", 1); + var frames = builder.GetFrames(); + Assert.Equal(2, frames.Count); + AssertFrame.Element(frames.Array[1], "my element", 1); } [Fact] @@ -117,9 +117,9 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.AddText(0, "unrelated item"); // Assert - var nodes = builder.GetNodes(); - Assert.Equal(4, nodes.Count); - AssertNode.Element(nodes.Array[0], "my element", 2); + var frames = builder.GetFrames(); + Assert.Equal(4, frames.Count); + AssertFrame.Element(frames.Array[0], "my element", 2); } [Fact] @@ -147,19 +147,19 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.AddText(0, "standalone text 2"); // 11: standalone text 2 // Assert - Assert.Collection(builder.GetNodes(), - node => AssertNode.Text(node, "standalone text 1"), - node => AssertNode.Element(node, "root", 10), - node => AssertNode.Text(node, "root text 1"), - node => AssertNode.Text(node, "root text 2"), - node => AssertNode.Element(node, "child", 8), - node => AssertNode.Text(node, "child text"), - node => AssertNode.Element(node, "grandchild", 8), - node => AssertNode.Text(node, "grandchild text 1"), - node => AssertNode.Text(node, "grandchild text 2"), - node => AssertNode.Text(node, "root text 3"), - node => AssertNode.Element(node, "child 2", 10), - node => AssertNode.Text(node, "standalone text 2")); + Assert.Collection(builder.GetFrames(), + frame => AssertFrame.Text(frame, "standalone text 1"), + frame => AssertFrame.Element(frame, "root", 10), + frame => AssertFrame.Text(frame, "root text 1"), + frame => AssertFrame.Text(frame, "root text 2"), + frame => AssertFrame.Element(frame, "child", 8), + frame => AssertFrame.Text(frame, "child text"), + frame => AssertFrame.Element(frame, "grandchild", 8), + frame => AssertFrame.Text(frame, "grandchild text 1"), + frame => AssertFrame.Text(frame, "grandchild text 2"), + frame => AssertFrame.Text(frame, "root text 3"), + frame => AssertFrame.Element(frame, "child 2", 10), + frame => AssertFrame.Text(frame, "standalone text 2")); } [Fact] @@ -180,13 +180,13 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.CloseElement(); // // Assert - Assert.Collection(builder.GetNodes(), - node => AssertNode.Element(node, "myelement", 5), - node => AssertNode.Attribute(node, "attribute1", "value 1"), - node => AssertNode.Attribute(node, "attribute2", "123"), - node => AssertNode.Element(node, "child", 5), - node => AssertNode.Attribute(node, "childevent", eventHandler), - node => AssertNode.Text(node, "some text")); + Assert.Collection(builder.GetFrames(), + frame => AssertFrame.Element(frame, "myelement", 5), + frame => AssertFrame.Attribute(frame, "attribute1", "value 1"), + frame => AssertFrame.Attribute(frame, "attribute2", "123"), + frame => AssertFrame.Element(frame, "child", 5), + frame => AssertFrame.Attribute(frame, "childevent", eventHandler), + frame => AssertFrame.Text(frame, "some text")); } [Fact] @@ -263,13 +263,13 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.CloseElement(); // // Assert - Assert.Collection(builder.GetNodes(), - node => AssertNode.Element(node, "parent", 5), - node => AssertNode.Component(node), - node => AssertNode.Attribute(node, "child1attribute1", "A"), - node => AssertNode.Attribute(node, "child1attribute2", "B"), - node => AssertNode.Component(node), - node => AssertNode.Attribute(node, "child2attribute", "C")); + Assert.Collection(builder.GetFrames(), + frame => AssertFrame.Element(frame, "parent", 5), + frame => AssertFrame.Component(frame), + frame => AssertFrame.Attribute(frame, "child1attribute1", "A"), + frame => AssertFrame.Attribute(frame, "child1attribute2", "B"), + frame => AssertFrame.Component(frame), + frame => AssertFrame.Attribute(frame, "child2attribute", "C")); } [Fact] @@ -286,7 +286,7 @@ namespace Microsoft.AspNetCore.Blazor.Test builder.Clear(); // Assert - Assert.Empty(builder.GetNodes()); + Assert.Empty(builder.GetFrames()); } private class TestComponent : IComponent diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs index 41a2b67288..64541ab5ab 100644 --- a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs @@ -28,8 +28,8 @@ namespace Microsoft.AspNetCore.Blazor.Test } [Theory] - [MemberData(nameof(RecognizesEquivalentNodesAsSameCases))] - public void RecognizesEquivalentNodesAsSame(Action appendAction) + [MemberData(nameof(RecognizesEquivalentFramesAsSameCases))] + public void RecognizesEquivalentFramesAsSame(Action appendAction) { // Arrange appendAction(oldTree); @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Empty(result.Edits); } - public static IEnumerable RecognizesEquivalentNodesAsSameCases() + public static IEnumerable RecognizesEquivalentFramesAsSameCases() => new Action[] { builder => builder.AddText(0, "Hello"), @@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(result.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 1); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); Assert.Equal(1, entry.NewTreeIndex); }); } @@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); } [Fact] @@ -112,8 +112,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1), - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); } [Fact] @@ -134,12 +134,12 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(result.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 1); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); Assert.Equal(1, entry.NewTreeIndex); }, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 2); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); Assert.Equal(2, entry.NewTreeIndex); }); } @@ -160,8 +160,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 2), - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 2)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2), + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2)); } [Fact] @@ -182,12 +182,12 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(result.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 2); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); Assert.Equal(2, entry.NewTreeIndex); }, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 3); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 3); Assert.Equal(3, entry.NewTreeIndex); }); } @@ -210,12 +210,12 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(result.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 1); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); Assert.Equal(1, entry.NewTreeIndex); }, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 2); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 2); Assert.Equal(2, entry.NewTreeIndex); }); } @@ -236,8 +236,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1), - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); } [Fact] @@ -252,8 +252,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(result.Edits, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 0), - entry => AssertEdit(entry, RenderTreeEditType.PrependNode, 0)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0), + entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0)); } [Fact] @@ -302,10 +302,10 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(result.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 0); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); Assert.Equal(0, entry.NewTreeIndex); }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); } [Fact] @@ -330,18 +330,18 @@ namespace Microsoft.AspNetCore.Blazor.Test Assert.Collection(updatedComponent1.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 0); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); Assert.Equal(0, entry.NewTreeIndex); Assert.IsType(updatedComponent1.CurrentState.Array[0].Component); }, - entry => AssertEdit(entry, RenderTreeEditType.RemoveNode, 1)); + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); // Assert: Second updated component is the new FakeComponent2 var updatedComponent2 = renderBatch.UpdatedComponents.Array[1]; Assert.Collection(updatedComponent2.Edits, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 0); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); Assert.Equal(0, entry.NewTreeIndex); }); } @@ -577,7 +577,7 @@ namespace Microsoft.AspNetCore.Blazor.Test } [Fact] - public void InstantiatesChildComponentsForInsertedNodes() + public void InstantiatesChildComponentsForInsertedFrames() { // Arrange oldTree.AddText(10, "text1"); // 0: text1 @@ -603,37 +603,37 @@ namespace Microsoft.AspNetCore.Blazor.Test entry => AssertEdit(entry, RenderTreeEditType.StepIn, 1), entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 0); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); Assert.Equal(2, entry.NewTreeIndex); - var newTreeNode = newTree.GetNodes().Array[entry.NewTreeIndex]; - Assert.Equal(0, newTreeNode.ComponentId); - Assert.IsType(newTreeNode.Component); + var newTreeFrame = newTree.GetFrames().Array[entry.NewTreeIndex]; + Assert.Equal(0, newTreeFrame.ComponentId); + Assert.IsType(newTreeFrame.Component); }, entry => { - AssertEdit(entry, RenderTreeEditType.PrependNode, 1); + AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); Assert.Equal(3, entry.NewTreeIndex); - var newTreeNode = newTree.GetNodes().Array[entry.NewTreeIndex]; - Assert.Equal(1, newTreeNode.ComponentId); - Assert.IsType(newTreeNode.Component); + var newTreeFrame = newTree.GetFrames().Array[entry.NewTreeIndex]; + Assert.Equal(1, newTreeFrame.ComponentId); + Assert.IsType(newTreeFrame.Component); }, entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0)); // Second in batch is the first child component var secondComponentDiff = renderBatch.UpdatedComponents.Array[1]; Assert.Equal(0, secondComponentDiff.ComponentId); - Assert.Empty(secondComponentDiff.Edits); // Because FakeComponent produces no nodes - Assert.Empty(secondComponentDiff.CurrentState); // Because FakeComponent produces no nodes + Assert.Empty(secondComponentDiff.Edits); // Because FakeComponent produces no frames + Assert.Empty(secondComponentDiff.CurrentState); // Because FakeComponent produces no frames // Third in batch is the second child component var thirdComponentDiff = renderBatch.UpdatedComponents.Array[2]; Assert.Equal(1, thirdComponentDiff.ComponentId); Assert.Collection(thirdComponentDiff.Edits, - entry => AssertEdit(entry, RenderTreeEditType.PrependNode, 0)); + entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0)); Assert.Collection(thirdComponentDiff.CurrentState, - node => AssertNode.Text(node, $"Hello from {nameof(FakeComponent2)}")); + frame => AssertFrame.Text(frame, $"Hello from {nameof(FakeComponent2)}")); } [Fact] @@ -649,13 +649,13 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act var renderBatch = GetRenderedBatch(); - var componentInstance = newTree.GetNodes().First().Component as FakeComponent; + var componentInstance = newTree.GetFrames().First().Component as FakeComponent; // Assert Assert.Equal(2, renderBatch.UpdatedComponents.Count); var rootComponentDiff = renderBatch.UpdatedComponents.Array[0]; - AssertEdit(rootComponentDiff.Edits.Single(), RenderTreeEditType.PrependNode, 0); + AssertEdit(rootComponentDiff.Edits.Single(), RenderTreeEditType.PrependFrame, 0); Assert.NotNull(componentInstance); Assert.Equal(123, componentInstance.IntProperty); Assert.Equal("some string", componentInstance.StringProperty); @@ -674,7 +674,7 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert var ex = Assert.Throws(() => { - diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, oldTree.GetNodes(), newTree.GetNodes()); + diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, oldTree.GetFrames(), newTree.GetFrames()); }); Assert.Equal($"Component of type '{typeof(FakeComponent).FullName}' does not have a property matching the name 'SomeUnknownProperty'.", ex.Message); } @@ -691,14 +691,14 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert var ex = Assert.Throws(() => { - diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, oldTree.GetNodes(), newTree.GetNodes()); + diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, oldTree.GetFrames(), newTree.GetFrames()); }); Assert.StartsWith($"Unable to set property '{nameof(FakeComponent.ReadonlyProperty)}' on " + $"component of type '{typeof(FakeComponent).FullName}'.", ex.Message); } [Fact] - public void RetainsChildComponentsForExistingNodes() + public void RetainsChildComponentsForExistingFrames() { // Arrange oldTree.AddText(10, "text1"); // 0: text1 @@ -716,21 +716,21 @@ namespace Microsoft.AspNetCore.Blazor.Test newTree.CloseElement(); // newTree.CloseElement(); // AssertNode.Text(node, "Notifications: 1", 0)); + frame => AssertFrame.Text(frame, "Notifications: 1", 0)); } [Fact] @@ -797,11 +797,11 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert 0: Initial render var batch0 = GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree); var diffForChildComponent0 = batch0.UpdatedComponents.Array[1]; - var childComponentNode = batch0.UpdatedComponents.Array[0].CurrentState.Array[0]; - var childComponentInstance = (HandlePropertiesChangedComponent)childComponentNode.Component; + var childComponentFrame = batch0.UpdatedComponents.Array[0].CurrentState.Array[0]; + var childComponentInstance = (HandlePropertiesChangedComponent)childComponentFrame.Component; Assert.Equal(1, childComponentInstance.NotificationsCount); Assert.Collection(diffForChildComponent0.CurrentState, - node => AssertNode.Text(node, "Notifications: 1", 0)); + frame => AssertFrame.Text(frame, "Notifications: 1", 0)); // Act/Assert 1: If properties didn't change, we don't notify GetRenderedBatch(oldTree, newTree1); @@ -812,7 +812,7 @@ namespace Microsoft.AspNetCore.Blazor.Test var diffForChildComponent2 = batch2.UpdatedComponents.Array[1]; Assert.Equal(2, childComponentInstance.NotificationsCount); Assert.Collection(diffForChildComponent2.CurrentState, - node => AssertNode.Text(node, "Notifications: 2", 0)); + frame => AssertFrame.Text(frame, "Notifications: 2", 0)); } [Fact] @@ -828,10 +828,10 @@ namespace Microsoft.AspNetCore.Blazor.Test newTree.OpenComponentElement(30); // newTree.CloseElement(); // - diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, new RenderTreeBuilder(renderer).GetNodes(), oldTree.GetNodes()); - var disposableComponent1 = (DisposableComponent)oldTree.GetNodes().Array[0].Component; - var nonDisposableComponent = (NonDisposableComponent)oldTree.GetNodes().Array[1].Component; - var disposableComponent2 = (DisposableComponent)oldTree.GetNodes().Array[2].Component; + diff.ApplyNewRenderTreeVersion(new RenderBatchBuilder(), 0, new RenderTreeBuilder(renderer).GetFrames(), oldTree.GetFrames()); + var disposableComponent1 = (DisposableComponent)oldTree.GetFrames().Array[0].Component; + var nonDisposableComponent = (NonDisposableComponent)oldTree.GetFrames().Array[1].Component; + var disposableComponent2 = (DisposableComponent)oldTree.GetFrames().Array[2].Component; // Act var renderedBatch = GetRenderedBatch(); @@ -859,7 +859,7 @@ namespace Microsoft.AspNetCore.Blazor.Test private RenderBatch GetRenderedBatch(RenderTreeBuilder from, RenderTreeBuilder to) { var batchBuilder = new RenderBatchBuilder(); - diff.ApplyNewRenderTreeVersion(batchBuilder, 0, from.GetNodes(), to.GetNodes()); + diff.ApplyNewRenderTreeVersion(batchBuilder, 0, from.GetFrames(), to.GetFrames()); return batchBuilder.ToBatch(); } diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs index 9ef2eb0235..a2966c3e63 100644 --- a/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs @@ -32,8 +32,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[componentId], - node => AssertNode.Element(node, "my element", 1), - node => AssertNode.Text(node, "some text")); + frame => AssertFrame.Element(frame, "my element", 1), + frame => AssertFrame.Text(frame, "some text")); } [Fact] @@ -52,16 +52,16 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert var componentId = renderer.AssignComponentId(component); renderer.RenderNewBatch(componentId); - var componentNode = renderer.Batches.Single().RenderTreesByComponentId[componentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component); - var nestedComponentId = componentNode.ComponentId; + var componentFrame = renderer.Batches.Single().RenderTreesByComponentId[componentId] + .Single(frame => frame.FrameType == RenderTreeFrameType.Component); + var nestedComponentId = componentFrame.ComponentId; // The nested component exists - Assert.IsType(componentNode.Component); + Assert.IsType(componentFrame.Component); // The nested component was rendered as part of the batch Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[nestedComponentId], - node => AssertNode.Text(node, "Nested component output")); + frame => AssertFrame.Text(frame, "Nested component output")); } [Fact] @@ -75,13 +75,13 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert: first render renderer.RenderNewBatch(componentId); Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[componentId], - node => AssertNode.Text(node, "Initial message")); + frame => AssertFrame.Text(frame, "Initial message")); // Act/Assert: second render component.Message = "Modified message"; renderer.RenderNewBatch(componentId); Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[componentId], - node => AssertNode.Text(node, "Modified message")); + frame => AssertFrame.Text(frame, "Modified message")); } [Fact] @@ -96,22 +96,22 @@ namespace Microsoft.AspNetCore.Blazor.Test }); var parentComponentId = renderer.AssignComponentId(parentComponent); renderer.RenderNewBatch(parentComponentId); - var nestedComponentNode = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component); - var nestedComponent = (MessageComponent)nestedComponentNode.Component; - var nestedComponentId = nestedComponentNode.ComponentId; + var nestedComponentFrame = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId] + .Single(frame => frame.FrameType == RenderTreeFrameType.Component); + var nestedComponent = (MessageComponent)nestedComponentFrame.Component; + var nestedComponentId = nestedComponentFrame.ComponentId; // Act/Assert: inital render nestedComponent.Message = "Render 1"; renderer.RenderNewBatch(nestedComponentId); Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[nestedComponentId], - node => AssertNode.Text(node, "Render 1")); + frame => AssertFrame.Text(frame, "Render 1")); // Act/Assert: re-render nestedComponent.Message = "Render 2"; renderer.RenderNewBatch(nestedComponentId); Assert.Collection(renderer.Batches[2].RenderTreesByComponentId[nestedComponentId], - node => AssertNode.Text(node, "Render 2")); + frame => AssertFrame.Text(frame, "Render 2")); } [Fact] @@ -128,16 +128,16 @@ namespace Microsoft.AspNetCore.Blazor.Test var componentId = renderer.AssignComponentId(component); renderer.RenderNewBatch(componentId); - var (eventHandlerNodeIndex, _) = FirstWithIndex( + var (eventHandlerFrameIndex, _) = FirstWithIndex( renderer.Batches.Single().RenderTreesByComponentId[componentId], - node => node.AttributeValue != null); + frame => frame.AttributeValue != null); // Assert: Event not yet fired Assert.Null(receivedArgs); // Act/Assert: Event can be fired var eventArgs = new UIEventArgs(); - renderer.DispatchEvent(componentId, eventHandlerNodeIndex, eventArgs); + renderer.DispatchEvent(componentId, eventHandlerFrameIndex, eventArgs); Assert.Same(eventArgs, receivedArgs); } @@ -157,24 +157,24 @@ namespace Microsoft.AspNetCore.Blazor.Test renderer.RenderNewBatch(parentComponentId); // Arrange: Render nested component - var nestedComponentNode = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component); - var nestedComponent = (EventComponent)nestedComponentNode.Component; + var nestedComponentFrame = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId] + .Single(frame => frame.FrameType == RenderTreeFrameType.Component); + var nestedComponent = (EventComponent)nestedComponentFrame.Component; nestedComponent.Handler = args => { receivedArgs = args; }; - var nestedComponentId = nestedComponentNode.ComponentId; + var nestedComponentId = nestedComponentFrame.ComponentId; renderer.RenderNewBatch(nestedComponentId); // Find nested component's event handler ndoe - var (eventHandlerNodeIndex, _) = FirstWithIndex( + var (eventHandlerFrameIndex, _) = FirstWithIndex( renderer.Batches[1].RenderTreesByComponentId[nestedComponentId], - node => node.AttributeValue != null); + frame => frame.AttributeValue != null); // Assert: Event not yet fired Assert.Null(receivedArgs); // Act/Assert: Event can be fired var eventArgs = new UIEventArgs(); - renderer.DispatchEvent(nestedComponentId, eventHandlerNodeIndex, eventArgs); + renderer.DispatchEvent(nestedComponentId, eventHandlerFrameIndex, eventArgs); Assert.Same(eventArgs, receivedArgs); } @@ -314,7 +314,7 @@ namespace Microsoft.AspNetCore.Blazor.Test renderer.RenderNewBatch(rootComponentId); var nestedComponentInstance = (MessageComponent)renderer.Batches.Single().RenderTreesByComponentId[rootComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component) + .Single(frame => frame.FrameType == RenderTreeFrameType.Component) .Component; // Act: Second render @@ -323,8 +323,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Assert Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[rootComponentId], - node => AssertNode.Text(node, "Modified message"), - node => Assert.Same(nestedComponentInstance, node.Component)); + frame => AssertFrame.Text(frame, "Modified message"), + frame => Assert.Same(nestedComponentInstance, frame.Component)); } [Fact] @@ -347,7 +347,7 @@ namespace Microsoft.AspNetCore.Blazor.Test renderer.RenderNewBatch(rootComponentId); var originalComponentInstance = (FakeComponent)renderer.Batches.Single().RenderTreesByComponentId[rootComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component) + .Single(frame => frame.FrameType == RenderTreeFrameType.Component) .Component; // Assert 1: properties were assigned @@ -360,7 +360,7 @@ namespace Microsoft.AspNetCore.Blazor.Test renderer.RenderNewBatch(rootComponentId); var updatedComponentInstance = (FakeComponent)renderer.Batches[1].RenderTreesByComponentId[rootComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component) + .Single(frame => frame.FrameType == RenderTreeFrameType.Component) .Component; // Assert @@ -387,19 +387,19 @@ namespace Microsoft.AspNetCore.Blazor.Test renderer.RenderNewBatch(rootComponentId); var childComponentId = renderer.Batches.Single().RenderTreesByComponentId[rootComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component) + .Single(frame => frame.FrameType == RenderTreeFrameType.Component) .ComponentId; // Act: Second render firstRender = false; renderer.RenderNewBatch(rootComponentId); - var updatedComponentNode = renderer.Batches[1].RenderTreesByComponentId[rootComponentId] - .Single(node => node.NodeType == RenderTreeNodeType.Component); + var updatedComponentFrame = renderer.Batches[1].RenderTreesByComponentId[rootComponentId] + .Single(frame => frame.FrameType == RenderTreeFrameType.Component); // Assert - Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[updatedComponentNode.ComponentId], - node => AssertNode.Text(node, "second")); + Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[updatedComponentFrame.ComponentId], + frame => AssertFrame.Text(frame, "second")); } [Fact] @@ -428,8 +428,8 @@ namespace Microsoft.AspNetCore.Blazor.Test // Act/Assert 1: First render, capturing child component IDs renderer.RenderNewBatch(rootComponentId); var childComponentIds = renderer.Batches.Single().RenderTreesByComponentId[rootComponentId] - .Where(node => node.NodeType == RenderTreeNodeType.Component) - .Select(node => node.ComponentId) + .Where(frame => frame.FrameType == RenderTreeFrameType.Component) + .Select(frame => frame.ComponentId) .ToList(); Assert.Equal(childComponentIds, new[] { 1, 2, 3 }); @@ -486,8 +486,8 @@ namespace Microsoft.AspNetCore.Blazor.Test private class CapturedBatch { - public IDictionary RenderTreesByComponentId { get; } - = new Dictionary(); + public IDictionary RenderTreesByComponentId { get; } + = new Dictionary(); public IList DisposedComponentIDs { get; set; } } diff --git a/test/shared/AssertFrame.cs b/test/shared/AssertFrame.cs new file mode 100644 index 0000000000..def4f2fc4e --- /dev/null +++ b/test/shared/AssertFrame.cs @@ -0,0 +1,70 @@ +// 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. + +using System; +using Microsoft.AspNetCore.Blazor.Components; +using Microsoft.AspNetCore.Blazor.RenderTree; +using Xunit; + +namespace Microsoft.AspNetCore.Blazor.Test.Shared +{ + internal static class AssertFrame + { + public static void Sequence(RenderTreeFrame frame, int? sequence = null) + { + if (sequence.HasValue) + { + Assert.Equal(sequence.Value, frame.Sequence); + } + } + + public static void Text(RenderTreeFrame frame, string textContent, int? sequence = null) + { + Assert.Equal(RenderTreeFrameType.Text, frame.FrameType); + Assert.Equal(textContent, frame.TextContent); + Assert.Equal(0, frame.ElementDescendantsEndIndex); + AssertFrame.Sequence(frame, sequence); + } + + public static void Element(RenderTreeFrame frame, string elementName, int descendantsEndIndex, int? sequence = null) + { + Assert.Equal(RenderTreeFrameType.Element, frame.FrameType); + Assert.Equal(elementName, frame.ElementName); + Assert.Equal(descendantsEndIndex, frame.ElementDescendantsEndIndex); + AssertFrame.Sequence(frame, sequence); + } + + public static void Attribute(RenderTreeFrame frame, string attributeName, int? sequence = null) + { + Assert.Equal(RenderTreeFrameType.Attribute, frame.FrameType); + Assert.Equal(attributeName, frame.AttributeName); + AssertFrame.Sequence(frame, sequence); + } + + public static void Attribute(RenderTreeFrame frame, string attributeName, string attributeValue, int? sequence = null) + { + AssertFrame.Attribute(frame, attributeName, sequence); + Assert.Equal(attributeValue, frame.AttributeValue); + } + + public static void Attribute(RenderTreeFrame frame, string attributeName, UIEventHandler attributeEventHandlerValue, int? sequence = null) + { + AssertFrame.Attribute(frame, attributeName, sequence); + Assert.Equal(attributeEventHandlerValue, frame.AttributeValue); + } + + public static void Component(RenderTreeFrame frame, int? sequence = null) where T : IComponent + { + Assert.Equal(RenderTreeFrameType.Component, frame.FrameType); + Assert.Equal(typeof(T), frame.ComponentType); + AssertFrame.Sequence(frame, sequence); + } + + public static void Whitespace(RenderTreeFrame frame, int? sequence = null) + { + Assert.Equal(RenderTreeFrameType.Text, frame.FrameType); + AssertFrame.Sequence(frame, sequence); + Assert.True(string.IsNullOrWhiteSpace(frame.TextContent)); + } + } +} diff --git a/test/shared/AssertNode.cs b/test/shared/AssertNode.cs deleted file mode 100644 index afd040832d..0000000000 --- a/test/shared/AssertNode.cs +++ /dev/null @@ -1,70 +0,0 @@ -// 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. - -using System; -using Microsoft.AspNetCore.Blazor.Components; -using Microsoft.AspNetCore.Blazor.RenderTree; -using Xunit; - -namespace Microsoft.AspNetCore.Blazor.Test.Shared -{ - internal static class AssertNode - { - public static void Sequence(RenderTreeNode node, int? sequence = null) - { - if (sequence.HasValue) - { - Assert.Equal(sequence.Value, node.Sequence); - } - } - - public static void Text(RenderTreeNode node, string textContent, int? sequence = null) - { - Assert.Equal(RenderTreeNodeType.Text, node.NodeType); - Assert.Equal(textContent, node.TextContent); - Assert.Equal(0, node.ElementDescendantsEndIndex); - AssertNode.Sequence(node, sequence); - } - - public static void Element(RenderTreeNode node, string elementName, int descendantsEndIndex, int? sequence = null) - { - Assert.Equal(RenderTreeNodeType.Element, node.NodeType); - Assert.Equal(elementName, node.ElementName); - Assert.Equal(descendantsEndIndex, node.ElementDescendantsEndIndex); - AssertNode.Sequence(node, sequence); - } - - public static void Attribute(RenderTreeNode node, string attributeName, int? sequence = null) - { - Assert.Equal(RenderTreeNodeType.Attribute, node.NodeType); - Assert.Equal(attributeName, node.AttributeName); - AssertNode.Sequence(node, sequence); - } - - public static void Attribute(RenderTreeNode node, string attributeName, string attributeValue, int? sequence = null) - { - AssertNode.Attribute(node, attributeName, sequence); - Assert.Equal(attributeValue, node.AttributeValue); - } - - public static void Attribute(RenderTreeNode node, string attributeName, UIEventHandler attributeEventHandlerValue, int? sequence = null) - { - AssertNode.Attribute(node, attributeName, sequence); - Assert.Equal(attributeEventHandlerValue, node.AttributeValue); - } - - public static void Component(RenderTreeNode node, int? sequence = null) where T : IComponent - { - Assert.Equal(RenderTreeNodeType.Component, node.NodeType); - Assert.Equal(typeof(T), node.ComponentType); - AssertNode.Sequence(node, sequence); - } - - public static void Whitespace(RenderTreeNode node, int? sequence = null) - { - Assert.Equal(RenderTreeNodeType.Text, node.NodeType); - AssertNode.Sequence(node, sequence); - Assert.True(string.IsNullOrWhiteSpace(node.TextContent)); - } - } -}