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];
Ejemplo n.º 3
0
        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}");
                }
            }
        }