private static void AssertEdit( RenderTreeEdit edit, RenderTreeEditType type, int siblingIndex) { Assert.Equal(type, edit.Type); Assert.Equal(siblingIndex, edit.SiblingIndex); }
private static void AssertPrependText(CapturedBatch batch, RenderTreeEdit edit, string text) { Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); ref var referenceFrame = ref batch.ReferenceFrames[edit.ReferenceFrameIndex];
private static ArrayRange <RenderTreeDiff> ReadUpdatedComponents(ReadOnlySpan <byte> data, ReadOnlySpan <byte> indexes, string[] strings) { var result = new RenderTreeDiff[indexes.Length / 4]; for (var i = 0; i < indexes.Length; i += 4) { var index = BitConverter.ToInt32(indexes.Slice(i, 4)); var componentId = BitConverter.ToInt32(data.Slice(index, 4)); var editCount = BitConverter.ToInt32(data.Slice(index + 4, 4)); var editData = data.Slice(index + 8); var edits = new RenderTreeEdit[editCount]; for (var j = 0; j < editCount; j++) { var type = (RenderTreeEditType)BitConverter.ToInt32(editData.Slice(0, 4)); var siblingIndex = BitConverter.ToInt32(editData.Slice(4, 4)); // ReferenceFrameIndex and MoveToSiblingIndex share a slot, so this reads // whichever one applies to the edit type var referenceFrameIndex = BitConverter.ToInt32(editData.Slice(8, 4)); var removedAttributeName = ReadString(editData.Slice(12, 4), strings); editData = editData.Slice(16); switch (type) { case RenderTreeEditType.UpdateText: edits[j] = RenderTreeEdit.UpdateText(siblingIndex, referenceFrameIndex); break; case RenderTreeEditType.UpdateMarkup: edits[j] = RenderTreeEdit.UpdateMarkup(siblingIndex, referenceFrameIndex); break; case RenderTreeEditType.SetAttribute: edits[j] = RenderTreeEdit.SetAttribute(siblingIndex, referenceFrameIndex); break; case RenderTreeEditType.RemoveAttribute: edits[j] = RenderTreeEdit.RemoveAttribute(siblingIndex, removedAttributeName); break; case RenderTreeEditType.PrependFrame: edits[j] = RenderTreeEdit.PrependFrame(siblingIndex, referenceFrameIndex); break; case RenderTreeEditType.RemoveFrame: edits[j] = RenderTreeEdit.RemoveFrame(siblingIndex); break; case RenderTreeEditType.StepIn: edits[j] = RenderTreeEdit.StepIn(siblingIndex); break; case RenderTreeEditType.StepOut: edits[j] = RenderTreeEdit.StepOut(); break; case RenderTreeEditType.PermutationListEntry: edits[j] = RenderTreeEdit.PermutationListEntry(siblingIndex, referenceFrameIndex); break; case RenderTreeEditType.PermutationListEnd: edits[j] = RenderTreeEdit.PermutationListEnd(); break; default: throw new InvalidOperationException("Unknown edit type:" + type); } } result[i / 4] = new RenderTreeDiff(componentId, ToArrayBuilderSegment(edits)); } return(new ArrayRange <RenderTreeDiff>(result, result.Length)); }
void ProcessTree(RenderTreeEdit edit, RenderBatch batch, int startIndex, int subLength) { for (int i = 0; i < subLength; i++) { int currentIndex = startIndex + i; var frame = batch.ReferenceFrames.Array[currentIndex]; switch (edit.Type) { case RenderTreeEditType.PrependFrame: { switch (frame.FrameType) { case RenderTreeFrameType.Component: { CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.Component.GetType().Name); //Sequences.Push(frame.Sequence); var childRenderer = new ComponentRenderer(frame.Component, WebViewRenderer, this); WebViewRenderer.Renderers[frame.ComponentId] = childRenderer; //we dont need to process the subtree of components as the Renderer will process it again //ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1); i += frame.ComponentSubtreeLength - 1; //Sequences.Pop(); CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode); } break; case RenderTreeFrameType.Element: { CurrentNode = WebViewRenderer.DOMBuilder.CreateElement(CurrentNode, frame.Sequence, frame.ElementName); //Sequences.Push(frame.Sequence); ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1); i += frame.ElementSubtreeLength - 1; //Sequences.Pop(); CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode); } break; case RenderTreeFrameType.Attribute: { if (frame.AttributeValue is EventCallback callback) { WebViewRenderer.DOMBuilder.SetEvent(CurrentNode, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName); } else { WebViewRenderer.DOMBuilder.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue); } } break; case RenderTreeFrameType.Text: WebViewRenderer.DOMBuilder.InsertText(CurrentNode, frame.Sequence, frame.TextContent); break; case RenderTreeFrameType.Markup: { WebViewRenderer.DOMBuilder.InsertMarkup(CurrentNode, frame.Sequence, frame.MarkupContent); } break; case RenderTreeFrameType.Region: { CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.AttributeName); //Sequences.Push(frame.Sequence); ProcessTree(edit, batch, currentIndex + 1, frame.RegionSubtreeLength - 1); i += frame.RegionSubtreeLength - 1; //Sequences.Pop(); CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode); } break; case RenderTreeFrameType.ElementReferenceCapture: ElementReference reference = new ElementReference(CurrentNode.ToString()); //WebViewRenderer.DOMBuilder.Reference(); frame.ElementReferenceCaptureAction(reference); break; case RenderTreeFrameType.None: break; default: throw new NotImplementedException($"Invalid Frame type: {frame.FrameType}"); } } break; case RenderTreeEditType.UpdateText: { WebViewRenderer.DOMBuilder.UpdateText(CurrentNode, frame.Sequence, frame.TextContent); } break; case RenderTreeEditType.RemoveFrame: { WebViewRenderer.DOMBuilder.RemoveAt(CurrentNode, edit.SiblingIndex); } break; case RenderTreeEditType.UpdateMarkup: { WebViewRenderer.DOMBuilder.UpdateMarkup(CurrentNode, frame.Sequence, frame.TextContent); } break; case RenderTreeEditType.SetAttribute: { var node = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex); if (frame.AttributeValue is EventCallback callback) { WebViewRenderer.DOMBuilder.SetEvent(node, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName); } else { WebViewRenderer.DOMBuilder.SetAttribute(node, frame.Sequence, frame.AttributeName, frame.AttributeValue); } //WebViewRenderer.DOMManager.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue); } break; case RenderTreeEditType.RemoveAttribute: { WebViewRenderer.DOMBuilder.RemoveAttribute(CurrentNode, frame.Sequence, frame.AttributeName); } break; case RenderTreeEditType.StepIn: CurrentNode = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex); break; case RenderTreeEditType.StepOut: CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode); break; case RenderTreeEditType.PermutationListEntry: case RenderTreeEditType.PermutationListEnd: default: throw new NotImplementedException($"Invalid edit type: {edit.Type}"); } } }