From e0c32f42f46554a4c947d5ec249177245b1bd0e2 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 7 May 2019 18:22:10 +0100 Subject: [PATCH] Key support. Implements #8232 (#9850) * Store component/element keys on RenderTreeFrame Also refactored how RenderTreeFrame gets constructed. The previous arrangement of having ad-hoc ctor overloads for different scenarios became intractible (too many combinations to avoid clashes; risk of accidentally losing field values when cloning). There's now one constructor per RenderTreeFrameType, so you always know where to add any new field values, and implicitly guarantees you don't lose other field values because adding a new param forces updates at all the call sites. * Add StackObjectPool, which will be useful momentarily * Support keyed insertions/deletions * Refactor AppendDiffEntriesForRange to prepare for adding "move" logic * Apply permutations on the JS side * Handle keyed moves by writing a post-edit permutation list * Shrink KeyedItemInfo struct * Include sourcemaps when building client-side Blazor apps with ReferenceFromSource * Update struct length of edit frames now it's explicit layout It's longer now because all the reference-type fields, except the last, now have to be 8 bytes for compatibility with 64-bit runtimes. Previously on Mono WebAssembly the reference-type fields were all 4 bytes. * Tolerate clashing keys (i.e., produce a valid diff, even if suboptimal) * Tolerate keys being added/removed incorrectly * E2E test harness for 'key' * Some more unit test cases * Invert diffing logic to prefer matching by key over sequence Previously it preferred sequence over key, but that's wrong, and surfaces as bugs when you mix keyed and unkeyed items. We need to prefer key over sequence, because key is meant to guarantee preservation, whereas sequence is just best-effort preservation. * Make unit test cases more adversarial * First actual E2E test * In E2E test, verify correct preservation of components * E2E tests for simple insert/delete cases (with and without keys) * E2E test for reordering. Also extend other tests to verify simultaneous editing. * E2E test for many simultaneous changes * Update reference sources * CR: Avoid x = y = z * CR: Only use 'finally' for actual cleanup * CR: Clean up RenderTreeFrame assignment * CR: Include 'key' in RenderTreeFrame.ToString() * CR: Avoid "new T()" in StackObjectPool * CR: Make KeyedItemInfo readonly * CR: Handle change of frame type with matching keys (and sequence) * CR: Add E2E test showing form + key scenarios * Preserve focus across edits * Tweak E2E test case * In client-side Blazor, prevent recursive event handler invocations * Actual E2E tests for moving form elements --- .../Build/src/ReferenceFromSource.props | 2 +- .../Browser.JS/dist/Debug/blazor.server.js | 102 ++- .../dist/Debug/blazor.webassembly.js | 106 ++- .../Browser.JS/dist/Release/blazor.server.js | 6 +- .../dist/Release/blazor.webassembly.js | 2 +- .../src/Rendering/BrowserRenderer.ts | 24 +- .../src/Rendering/LogicalElements.ts | 96 ++- .../RenderBatch/OutOfProcessRenderBatch.ts | 4 + .../src/Rendering/RenderBatch/RenderBatch.ts | 3 + .../RenderBatch/SharedMemoryRenderBatch.ts | 7 +- .../src/RendererRegistryEventDispatcher.cs | 78 +- ...ft.AspNetCore.Components.netstandard2.0.cs | 10 +- .../src/RenderTree/RenderTreeBuilder.cs | 31 +- .../src/RenderTree/RenderTreeDiffBuilder.cs | 372 +++++++--- .../src/RenderTree/RenderTreeEdit.cs | 33 +- .../src/RenderTree/RenderTreeEditType.cs | 13 + .../src/RenderTree/RenderTreeFrame.cs | 172 +++-- .../src/RenderTree/StackObjectPool.cs | 75 ++ .../Components/src/Rendering/KeyedItemInfo.cs | 46 ++ .../src/Rendering/RenderBatchBuilder.cs | 3 + .../Components/test/RenderTreeBuilderTest.cs | 101 +++ .../test/RenderTreeDiffBuilderTest.cs | 691 ++++++++++++++++++ .../Components/test/StackObjectPoolTest.cs | 123 ++++ .../Server/src/Circuits/RenderBatchWriter.cs | 4 + src/Components/test/E2ETest/Tests/KeyTest.cs | 351 +++++++++ .../test/testassets/BasicTestApp/Index.razor | 2 + .../BasicTestApp/KeyCasesComponent.razor | 73 ++ .../BasicTestApp/KeyCasesTreeNode.razor | 53 ++ .../ReorderingFocusComponent.razor | 55 ++ .../ComponentsApp.App.csproj | 3 +- 30 files changed, 2438 insertions(+), 203 deletions(-) create mode 100644 src/Components/Components/src/RenderTree/StackObjectPool.cs create mode 100644 src/Components/Components/src/Rendering/KeyedItemInfo.cs create mode 100644 src/Components/Components/test/StackObjectPoolTest.cs create mode 100644 src/Components/test/E2ETest/Tests/KeyTest.cs create mode 100644 src/Components/test/testassets/BasicTestApp/KeyCasesComponent.razor create mode 100644 src/Components/test/testassets/BasicTestApp/KeyCasesTreeNode.razor create mode 100644 src/Components/test/testassets/BasicTestApp/ReorderingFocusComponent.razor diff --git a/src/Components/Blazor/Build/src/ReferenceFromSource.props b/src/Components/Blazor/Build/src/ReferenceFromSource.props index 209519e932..c98b209ff8 100644 --- a/src/Components/Blazor/Build/src/ReferenceFromSource.props +++ b/src/Components/Blazor/Build/src/ReferenceFromSource.props @@ -11,7 +11,7 @@ true - $(RepositoryRoot)src\Components\Browser.JS\dist\$(Configuration)\blazor.*.js + $(RepositoryRoot)src\Components\Browser.JS\dist\$(Configuration)\blazor.*.js.* diff --git a/src/Components/Browser.JS/dist/Debug/blazor.server.js b/src/Components/Browser.JS/dist/Debug/blazor.server.js index 51fade0f26..b8f0eb6fb4 100644 --- a/src/Components/Browser.JS/dist/Debug/blazor.server.js +++ b/src/Components/Browser.JS/dist/Debug/blazor.server.js @@ -13263,7 +13263,13 @@ var BrowserRenderer = /** @class */ (function () { clearBetween(rootElementToClear, rootElementToClearEnd); } } + var ownerDocument = LogicalElements_1.getClosestDomElement(element).ownerDocument; + var activeElementBefore = ownerDocument && ownerDocument.activeElement; this.applyEdits(batch, element, 0, edits, referenceFrames); + // Try to restore focus in case it was lost due to an element move + if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) { + activeElementBefore.focus(); + } }; BrowserRenderer.prototype.disposeComponent = function (componentId) { delete this.childComponentLocations[componentId]; @@ -13277,6 +13283,7 @@ var BrowserRenderer = /** @class */ (function () { BrowserRenderer.prototype.applyEdits = function (batch, parent, childIndex, edits, referenceFrames) { var currentDepth = 0; var childIndexAtCurrentDepth = childIndex; + var permutationList; var arraySegmentReader = batch.arraySegmentReader; var editReader = batch.editReader; var frameReader = batch.frameReader; @@ -13365,6 +13372,19 @@ var BrowserRenderer = /** @class */ (function () { childIndexAtCurrentDepth = currentDepth === 0 ? childIndex : 0; // The childIndex is only ever nonzero at zero depth break; } + case RenderBatch_1.EditType.permutationListEntry: { + permutationList = permutationList || []; + permutationList.push({ + fromSiblingIndex: childIndexAtCurrentDepth + editReader.siblingIndex(edit), + toSiblingIndex: childIndexAtCurrentDepth + editReader.moveToSiblingIndex(edit), + }); + break; + } + case RenderBatch_1.EditType.permutationListEnd: { + LogicalElements_1.permuteLogicalChildren(parent, permutationList); + permutationList = undefined; + break; + } default: { var unknownType = editType; // Compile-time verification that the switch was exhaustive throw new Error("Unknown edit type: " + unknownType); @@ -14169,11 +14189,54 @@ function getLogicalChildrenArray(element) { return element[logicalChildrenPropname]; } exports.getLogicalChildrenArray = getLogicalChildrenArray; -function getLogicalNextSibling(element) { - var siblings = getLogicalChildrenArray(getLogicalParent(element)); - var siblingIndex = Array.prototype.indexOf.call(siblings, element); - return siblings[siblingIndex + 1] || null; +function permuteLogicalChildren(parent, permutationList) { + // The permutationList must represent a valid permutation, i.e., the list of 'from' indices + // is distinct, and the list of 'to' indices is a permutation of it. The algorithm here + // relies on that assumption. + // Each of the phases here has to happen separately, because each one is designed not to + // interfere with the indices or DOM entries used by subsequent phases. + // Phase 1: track which nodes we will move + var siblings = getLogicalChildrenArray(parent); + permutationList.forEach(function (listEntry) { + listEntry.moveRangeStart = siblings[listEntry.fromSiblingIndex]; + listEntry.moveRangeEnd = findLastDomNodeInRange(listEntry.moveRangeStart); + }); + // Phase 2: insert markers + permutationList.forEach(function (listEntry) { + var marker = listEntry.moveToBeforeMarker = document.createComment('marker'); + var insertBeforeNode = siblings[listEntry.toSiblingIndex + 1]; + if (insertBeforeNode) { + insertBeforeNode.parentNode.insertBefore(marker, insertBeforeNode); + } + else { + appendDomNode(marker, parent); + } + }); + // Phase 3: move descendants & remove markers + permutationList.forEach(function (listEntry) { + var insertBefore = listEntry.moveToBeforeMarker; + var parentDomNode = insertBefore.parentNode; + var elementToMove = listEntry.moveRangeStart; + var moveEndNode = listEntry.moveRangeEnd; + var nextToMove = elementToMove; + while (nextToMove) { + var nextNext = nextToMove.nextSibling; + parentDomNode.insertBefore(nextToMove, insertBefore); + if (nextToMove === moveEndNode) { + break; + } + else { + nextToMove = nextNext; + } + } + parentDomNode.removeChild(insertBefore); + }); + // Phase 4: update siblings index + permutationList.forEach(function (listEntry) { + siblings[listEntry.toSiblingIndex] = listEntry.moveRangeStart; + }); } +exports.permuteLogicalChildren = permuteLogicalChildren; function getClosestDomElement(logicalElement) { if (logicalElement instanceof Element) { return logicalElement; @@ -14185,6 +14248,12 @@ function getClosestDomElement(logicalElement) { throw new Error('Not a valid logical element'); } } +exports.getClosestDomElement = getClosestDomElement; +function getLogicalNextSibling(element) { + var siblings = getLogicalChildrenArray(getLogicalParent(element)); + var siblingIndex = Array.prototype.indexOf.call(siblings, element); + return siblings[siblingIndex + 1] || null; +} function appendDomNode(child, parent) { // This function only puts 'child' into the DOM in the right place relative to 'parent' // It does not update the logical children array of anything @@ -14208,6 +14277,26 @@ function appendDomNode(child, parent) { throw new Error("Cannot append node because the parent is not a valid logical element. Parent: " + parent); } } +// Returns the final node (in depth-first evaluation order) that is a descendant of the logical element. +// As such, the entire subtree is between 'element' and 'findLastDomNodeInRange(element)' inclusive. +function findLastDomNodeInRange(element) { + if (element instanceof Element) { + return element; + } + var nextSibling = getLogicalNextSibling(element); + if (nextSibling) { + // Simple case: not the last logical sibling, so take the node before the next sibling + return nextSibling.previousSibling; + } + else { + // Harder case: there's no logical next-sibling, so recurse upwards until we find + // a logical ancestor that does have one, or a physical element + var logicalParent = getLogicalParent(element); + return logicalParent instanceof Element + ? logicalParent.lastChild + : findLastDomNodeInRange(logicalParent); + } +} function createSymbolOrFallback(fallback) { return typeof Symbol === 'function' ? Symbol() : fallback; } @@ -14303,6 +14392,9 @@ var OutOfProcessRenderTreeEditReader = /** @class */ (function () { OutOfProcessRenderTreeEditReader.prototype.newTreeIndex = function (edit) { return readInt32LE(this.batchDataUint8, edit + 8); // 3rd int }; + OutOfProcessRenderTreeEditReader.prototype.moveToSiblingIndex = function (edit) { + return readInt32LE(this.batchDataUint8, edit + 8); // 3rd int + }; OutOfProcessRenderTreeEditReader.prototype.removedAttributeName = function (edit) { var stringIndex = readInt32LE(this.batchDataUint8, edit + 12); // 4th int return this.stringReader.readString(stringIndex); @@ -14458,6 +14550,8 @@ var EditType; EditType[EditType["stepIn"] = 6] = "stepIn"; EditType[EditType["stepOut"] = 7] = "stepOut"; EditType[EditType["updateMarkup"] = 8] = "updateMarkup"; + EditType[EditType["permutationListEntry"] = 9] = "permutationListEntry"; + EditType[EditType["permutationListEnd"] = 10] = "permutationListEnd"; })(EditType = exports.EditType || (exports.EditType = {})); var FrameType; (function (FrameType) { diff --git a/src/Components/Browser.JS/dist/Debug/blazor.webassembly.js b/src/Components/Browser.JS/dist/Debug/blazor.webassembly.js index bae1381865..7df07ee7b4 100644 --- a/src/Components/Browser.JS/dist/Debug/blazor.webassembly.js +++ b/src/Components/Browser.JS/dist/Debug/blazor.webassembly.js @@ -1023,7 +1023,13 @@ var BrowserRenderer = /** @class */ (function () { clearBetween(rootElementToClear, rootElementToClearEnd); } } + var ownerDocument = LogicalElements_1.getClosestDomElement(element).ownerDocument; + var activeElementBefore = ownerDocument && ownerDocument.activeElement; this.applyEdits(batch, element, 0, edits, referenceFrames); + // Try to restore focus in case it was lost due to an element move + if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) { + activeElementBefore.focus(); + } }; BrowserRenderer.prototype.disposeComponent = function (componentId) { delete this.childComponentLocations[componentId]; @@ -1037,6 +1043,7 @@ var BrowserRenderer = /** @class */ (function () { BrowserRenderer.prototype.applyEdits = function (batch, parent, childIndex, edits, referenceFrames) { var currentDepth = 0; var childIndexAtCurrentDepth = childIndex; + var permutationList; var arraySegmentReader = batch.arraySegmentReader; var editReader = batch.editReader; var frameReader = batch.frameReader; @@ -1125,6 +1132,19 @@ var BrowserRenderer = /** @class */ (function () { childIndexAtCurrentDepth = currentDepth === 0 ? childIndex : 0; // The childIndex is only ever nonzero at zero depth break; } + case RenderBatch_1.EditType.permutationListEntry: { + permutationList = permutationList || []; + permutationList.push({ + fromSiblingIndex: childIndexAtCurrentDepth + editReader.siblingIndex(edit), + toSiblingIndex: childIndexAtCurrentDepth + editReader.moveToSiblingIndex(edit), + }); + break; + } + case RenderBatch_1.EditType.permutationListEnd: { + LogicalElements_1.permuteLogicalChildren(parent, permutationList); + permutationList = undefined; + break; + } default: { var unknownType = editType; // Compile-time verification that the switch was exhaustive throw new Error("Unknown edit type: " + unknownType); @@ -1929,11 +1949,54 @@ function getLogicalChildrenArray(element) { return element[logicalChildrenPropname]; } exports.getLogicalChildrenArray = getLogicalChildrenArray; -function getLogicalNextSibling(element) { - var siblings = getLogicalChildrenArray(getLogicalParent(element)); - var siblingIndex = Array.prototype.indexOf.call(siblings, element); - return siblings[siblingIndex + 1] || null; +function permuteLogicalChildren(parent, permutationList) { + // The permutationList must represent a valid permutation, i.e., the list of 'from' indices + // is distinct, and the list of 'to' indices is a permutation of it. The algorithm here + // relies on that assumption. + // Each of the phases here has to happen separately, because each one is designed not to + // interfere with the indices or DOM entries used by subsequent phases. + // Phase 1: track which nodes we will move + var siblings = getLogicalChildrenArray(parent); + permutationList.forEach(function (listEntry) { + listEntry.moveRangeStart = siblings[listEntry.fromSiblingIndex]; + listEntry.moveRangeEnd = findLastDomNodeInRange(listEntry.moveRangeStart); + }); + // Phase 2: insert markers + permutationList.forEach(function (listEntry) { + var marker = listEntry.moveToBeforeMarker = document.createComment('marker'); + var insertBeforeNode = siblings[listEntry.toSiblingIndex + 1]; + if (insertBeforeNode) { + insertBeforeNode.parentNode.insertBefore(marker, insertBeforeNode); + } + else { + appendDomNode(marker, parent); + } + }); + // Phase 3: move descendants & remove markers + permutationList.forEach(function (listEntry) { + var insertBefore = listEntry.moveToBeforeMarker; + var parentDomNode = insertBefore.parentNode; + var elementToMove = listEntry.moveRangeStart; + var moveEndNode = listEntry.moveRangeEnd; + var nextToMove = elementToMove; + while (nextToMove) { + var nextNext = nextToMove.nextSibling; + parentDomNode.insertBefore(nextToMove, insertBefore); + if (nextToMove === moveEndNode) { + break; + } + else { + nextToMove = nextNext; + } + } + parentDomNode.removeChild(insertBefore); + }); + // Phase 4: update siblings index + permutationList.forEach(function (listEntry) { + siblings[listEntry.toSiblingIndex] = listEntry.moveRangeStart; + }); } +exports.permuteLogicalChildren = permuteLogicalChildren; function getClosestDomElement(logicalElement) { if (logicalElement instanceof Element) { return logicalElement; @@ -1945,6 +2008,12 @@ function getClosestDomElement(logicalElement) { throw new Error('Not a valid logical element'); } } +exports.getClosestDomElement = getClosestDomElement; +function getLogicalNextSibling(element) { + var siblings = getLogicalChildrenArray(getLogicalParent(element)); + var siblingIndex = Array.prototype.indexOf.call(siblings, element); + return siblings[siblingIndex + 1] || null; +} function appendDomNode(child, parent) { // This function only puts 'child' into the DOM in the right place relative to 'parent' // It does not update the logical children array of anything @@ -1968,6 +2037,26 @@ function appendDomNode(child, parent) { throw new Error("Cannot append node because the parent is not a valid logical element. Parent: " + parent); } } +// Returns the final node (in depth-first evaluation order) that is a descendant of the logical element. +// As such, the entire subtree is between 'element' and 'findLastDomNodeInRange(element)' inclusive. +function findLastDomNodeInRange(element) { + if (element instanceof Element) { + return element; + } + var nextSibling = getLogicalNextSibling(element); + if (nextSibling) { + // Simple case: not the last logical sibling, so take the node before the next sibling + return nextSibling.previousSibling; + } + else { + // Harder case: there's no logical next-sibling, so recurse upwards until we find + // a logical ancestor that does have one, or a physical element + var logicalParent = getLogicalParent(element); + return logicalParent instanceof Element + ? logicalParent.lastChild + : findLastDomNodeInRange(logicalParent); + } +} function createSymbolOrFallback(fallback) { return typeof Symbol === 'function' ? Symbol() : fallback; } @@ -1996,6 +2085,8 @@ var EditType; EditType[EditType["stepIn"] = 6] = "stepIn"; EditType[EditType["stepOut"] = 7] = "stepOut"; EditType[EditType["updateMarkup"] = 8] = "updateMarkup"; + EditType[EditType["permutationListEntry"] = 9] = "permutationListEntry"; + EditType[EditType["permutationListEnd"] = 10] = "permutationListEnd"; })(EditType = exports.EditType || (exports.EditType = {})); var FrameType; (function (FrameType) { @@ -2089,15 +2180,16 @@ var diffReader = { }; // Keep in sync with memory layout in RenderTreeEdit.cs var editReader = { - structLength: 16, + structLength: 20, editType: function (edit) { return Environment_1.platform.readInt32Field(edit, 0); }, siblingIndex: function (edit) { return Environment_1.platform.readInt32Field(edit, 4); }, newTreeIndex: function (edit) { return Environment_1.platform.readInt32Field(edit, 8); }, - removedAttributeName: function (edit) { return Environment_1.platform.readStringField(edit, 12); }, + moveToSiblingIndex: function (edit) { return Environment_1.platform.readInt32Field(edit, 8); }, + removedAttributeName: function (edit) { return Environment_1.platform.readStringField(edit, 16); }, }; // Keep in sync with memory layout in RenderTreeFrame.cs var frameReader = { - structLength: 28, + structLength: 36, frameType: function (frame) { return Environment_1.platform.readInt32Field(frame, 4); }, subtreeLength: function (frame) { return Environment_1.platform.readInt32Field(frame, 8); }, elementReferenceCaptureId: function (frame) { return Environment_1.platform.readStringField(frame, 16); }, diff --git a/src/Components/Browser.JS/dist/Release/blazor.server.js b/src/Components/Browser.JS/dist/Release/blazor.server.js index a9f6e4c975..785cfa613a 100644 --- a/src/Components/Browser.JS/dist/Release/blazor.server.js +++ b/src/Components/Browser.JS/dist/Release/blazor.server.js @@ -1,15 +1,15 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=46)}([function(e,t,n){"use strict";var r;n.d(t,"a",function(){return r}),function(e){e[e.Trace=0]="Trace",e[e.Debug=1]="Debug",e[e.Information=2]="Information",e[e.Warning=3]="Warning",e[e.Error=4]="Error",e[e.Critical=5]="Critical",e[e.None=6]="None"}(r||(r={}))},function(e,t,n){"use strict";n.d(t,"a",function(){return s}),n.d(t,"e",function(){return u}),n.d(t,"f",function(){return c}),n.d(t,"g",function(){return l}),n.d(t,"d",function(){return f}),n.d(t,"c",function(){return h}),n.d(t,"b",function(){return d});var r=n(0),o=n(3),i=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},a=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:console.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:console.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:console.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),a=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return i(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return i(t,e),t}(Error),u=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return i(t,e),t}(Error),c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=200&&o.status<300?n(new l(o.status,o.statusText,o.response||o.responseText)):r(new a(o.statusText,o.status))},o.onerror=function(){t.logger.log(h.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new a(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(h.a.Warning,"Timeout from HTTP request."),r(new s)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(f),g=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();if("undefined"==typeof XMLHttpRequest){var y=require;o=y("./NodeHttpClient")}var v,b=function(e){function t(t){var n=e.call(this)||this;if("undefined"!=typeof XMLHttpRequest)n.httpClient=new d(t);else{if(void 0===o)throw new Error("No HttpClient could be created.");n.httpClient=new o.NodeHttpClient(t)}return n}return g(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new u):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(f),m=n(41);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(v||(v={}));var w,E=n(1),S=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},_=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=0){if((r!==C.WebSockets||this.options.WebSocket)&&(r!==C.ServerSentEvents||this.options.EventSource))return this.logger.log(h.a.Debug,"Selecting transport '"+C[r]+"'."),r;this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it is not supported in your environment.'")}else this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it does not support the requested transfer format '"+I[n]+"'.");else this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it was disabled by the client.")}return null},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.changeState=function(e,t){return this.connectionState===e&&(this.connectionState=t,!0)},e.prototype.stopConnection=function(e){this.transport=void 0,(e=this.stopError||e)?this.logger.log(h.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(h.a.Information,"Connection disconnected."),this.connectionState=2,this.onclose&&this.onclose(e)},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if("undefined"==typeof window||!window||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(h.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",n+=-1===t?"":e.substring(t)},e}();var Y=n(3),K=n(4),J="json",X=function(){function e(){this.name=J,this.version=1,this.transferFormat=I.Text}return e.prototype.parseMessages=function(e,t){if("string"!=typeof e)throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];null===t&&(t=Y.a.instance);for(var n=[],r=0,o=K.a.parse(e);r0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var a=c(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===function(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}(e).namespaceURI},t.getLogicalChildrenArray=c},function(e,t,n){"use strict";var r=n(18),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(15);i.inherits=n(7);var a=n(33),s=n(37);i.inherits(f,a);for(var u=o(s.prototype),c=0;c0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]-1&&this.subject.observers.splice(e,1),0===this.subject.observers.length&&this.subject.cancelCallback().catch(function(e){})},e}(),d=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.a.Critical:case r.a.Error:console.error("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Warning:console.warn("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;case r.a.Information:console.info("["+(new Date).toISOString()+"] "+r.a[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.a[e]+": "+t)}},e}()},function(e,t,n){"use strict";n.r(t);var r,o,i=(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),a=function(e){function t(t,n){var r=this,o=this.constructor.prototype;return(r=e.call(this,t)||this).statusCode=n,r.__proto__=o,r}return i(t,e),t}(Error),s=function(e){function t(t){void 0===t&&(t="A timeout occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return i(t,e),t}(Error),u=function(e){function t(t){void 0===t&&(t="An abort occurred.");var n=this,r=this.constructor.prototype;return(n=e.call(this,t)||this).__proto__=r,n}return i(t,e),t}(Error),c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=200&&o.status<300?n(new l(o.status,o.statusText,o.response||o.responseText)):r(new a(o.statusText,o.status))},o.onerror=function(){t.logger.log(h.a.Warning,"Error from HTTP request. "+o.status+": "+o.statusText+"."),r(new a(o.statusText,o.status))},o.ontimeout=function(){t.logger.log(h.a.Warning,"Timeout from HTTP request."),r(new s)},o.send(e.content||"")}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t}(f),g=function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();if("undefined"==typeof XMLHttpRequest){var y=require;o=y("./NodeHttpClient")}var v,m=function(e){function t(t){var n=e.call(this)||this;if("undefined"!=typeof XMLHttpRequest)n.httpClient=new d(t);else{if(void 0===o)throw new Error("No HttpClient could be created.");n.httpClient=new o.NodeHttpClient(t)}return n}return g(t,e),t.prototype.send=function(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new u):e.method?e.url?this.httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))},t.prototype.getCookieString=function(e){return this.httpClient.getCookieString(e)},t}(f),b=n(41);!function(e){e[e.Invocation=1]="Invocation",e[e.StreamItem=2]="StreamItem",e[e.Completion=3]="Completion",e[e.StreamInvocation=4]="StreamInvocation",e[e.CancelInvocation=5]="CancelInvocation",e[e.Ping=6]="Ping",e[e.Close=7]="Close"}(v||(v={}));var w,E=n(1),S=function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},_=function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=0){if((r!==C.WebSockets||this.options.WebSocket)&&(r!==C.ServerSentEvents||this.options.EventSource))return this.logger.log(h.a.Debug,"Selecting transport '"+C[r]+"'."),r;this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it is not supported in your environment.'")}else this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it does not support the requested transfer format '"+I[n]+"'.");else this.logger.log(h.a.Debug,"Skipping transport '"+C[r]+"' because it was disabled by the client.")}return null},e.prototype.isITransport=function(e){return e&&"object"==typeof e&&"connect"in e},e.prototype.changeState=function(e,t){return this.connectionState===e&&(this.connectionState=t,!0)},e.prototype.stopConnection=function(e){this.transport=void 0,(e=this.stopError||e)?this.logger.log(h.a.Error,"Connection disconnected with error '"+e+"'."):this.logger.log(h.a.Information,"Connection disconnected."),this.connectionState=2,this.onclose&&this.onclose(e)},e.prototype.resolveUrl=function(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if("undefined"==typeof window||!window||!window.document)throw new Error("Cannot resolve '"+e+"'.");var t=window.document.createElement("a");return t.href=e,this.logger.log(h.a.Information,"Normalizing '"+e+"' to '"+t.href+"'."),t.href},e.prototype.resolveNegotiateUrl=function(e){var t=e.indexOf("?"),n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",n+=-1===t?"":e.substring(t)},e}();var Y=n(3),K=n(4),J="json",X=function(){function e(){this.name=J,this.version=1,this.transferFormat=I.Text}return e.prototype.parseMessages=function(e,t){if("string"!=typeof e)throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];null===t&&(t=Y.a.instance);for(var n=[],r=0,o=K.a.parse(e);r0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function s(e,t,n){var i=e;if(e instanceof Comment&&(c(i)&&c(i).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(u(i))throw new Error("Not implemented: moving existing logical children");var a=c(t);if(n0;)e(r,0);var i=r;i.parentNode.removeChild(i)},t.getLogicalParent=u,t.getLogicalSiblingEnd=function(e){return e[i]||null},t.getLogicalChild=function(e,t){return c(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===l(e).namespaceURI},t.getLogicalChildrenArray=c,t.permuteLogicalChildren=function(e,t){var n=c(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=u(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):h(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,i=r;i;){var a=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=a}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=l},function(e,t,n){"use strict";var r=n(18),o=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=f;var i=n(15);i.inherits=n(7);var a=n(33),s=n(37);i.inherits(f,a);for(var u=o(s.prototype),c=0;c * @license MIT */ -var r=n(47),o=n(48),i=n(31);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,u/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;is&&(n=s-u),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function k(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(u=(15&c)<<12|(63&i)<<6|63&a)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(u=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=C)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return k(this,t,n);case"ascii":return I(this,t,n);case"latin1":case"binary":return x(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return m(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var C=4096;function I(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function M(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function A(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function B(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,i){return i||B(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||B(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||P(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||P(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||P(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||P(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||P(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||P(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||P(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||P(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||P(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||P(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):A(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):A(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):A(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):A(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(N,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(5))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t){for(var n=[],r=2;r1)for(var n=1;n0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.length||e<0)){var t=this._offset(e);return this._bufs[t[0]][t[1]]}},a.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},a.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,u=this._offset(n),c=r-n,l=c,f=s&&t||0,h=u[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){if(e=e||0,t="number"!=typeof t?this.length:t,e<0&&(e+=this.length),t<0&&(t+=this.length),e===t)return new a;var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;ethis.length?this.length:t;for(var r=this._offset(t),o=r[0],s=r[1];o=e.length){var c=u.indexOf(e,s);if(-1!==c)return this._reverseOffset([o,c]);s=u.length-e.length+1}else{var l=this._reverseOffset([o,s]);if(this._match(l,e))return l;s++}}s=0}return-1},a.prototype._match=function(e,t){if(this.length-e=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=n(22),i=n(8);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:i.attachRootComponentToElement,http:o.internalFunctions,uriHelper:r.internalFunctions}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),u=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),b(r.showHidden)&&(r.showHidden=!1),b(r.depth)&&(r.depth=2),b(r.colors)&&(r.colors=!1),b(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=u),l(r,e,r.depth)}function u(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function c(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&_(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(b(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(_(n)){var u=n.name?": "+n.name:"";return e.stylize("[Function"+u+"]","special")}if(m(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var c,w="",T=!1,k=["{","}"];(p(n)&&(T=!0,k=["[","]"]),_(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return m(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||T&&0!=n.length?r<0?m(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),c=T?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(c,w,k)):k[0]+w+k[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,u;if((u=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=u.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):u.set&&(s=e.stylize("[Setter]","special")),I(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(u.value)<0?(s=g(n)?l(e,u.value,null):l(e,u.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),b(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function b(e){return void 0===e}function m(e){return w(e)&&"[object RegExp]"===T(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===T(e)}function S(e){return w(e)&&("[object Error]"===T(e)||e instanceof Error)}function _(e){return"function"==typeof e}function T(e){return Object.prototype.toString.call(e)}function k(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(b(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=b,t.isRegExp=m,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=_,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(50);var C=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function I(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[k(e.getHours()),k(e.getMinutes()),k(e.getSeconds())].join(":"),[e.getDate(),C[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(7),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var x="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function R(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(x&&e[x]){var t;if("function"!=typeof(t=e[x]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,x,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):C(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function T(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(k,e):k(e))}function k(e){p("emit readable"),e.emit("readable"),O(e)}function C(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(I,e,t))}function I(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function M(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function A(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?M(this):T(this),null;if(0===(e=_(e,t))&&t.ended)return 0===t.length&&M(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?P(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&M(this)),null!==r&&this.emit("data",r),r},m.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},m.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:m;function c(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",b),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",c),n.removeListener("end",l),n.removeListener("end",m),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(u):n.once("end",u),e.on("unpipe",c);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,O(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==A(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),m(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",b),m()}function b(){p("onfinish"),e.removeListener("close",v),m()}function m(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",b),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},m.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&a.length>o&&!a.warned){a.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=a.length,s=u,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var u=o[e];if(void 0===u)return!1;if("function"==typeof u)i(u,this,t);else{var c=u.length,l=d(u,c);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(34).EventEmitter},function(e,t,n){"use strict";var r=n(18);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";(function(t,r,o){var i=n(18);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var s,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;b.WritableState=v;var c=n(15);c.inherits=n(7);var l={deprecate:n(56)},f=n(35),h=n(6).Buffer,p=o.Uint8Array||function(){};var d,g=n(36);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(T,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),T(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?u(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function b(e){if(s=s||n(10),!(d.call(b,this)||this instanceof s))return new b(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function m(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,u=!0;n;)o[s]=n,n.isBuf||(u=!1),n=n.next,s+=1;o.allBuffers=u,m(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,f=n.callback;if(m(e,t,!1,t.objectMode?1:c.length,c,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function _(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),T(e,t)})}function T(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(_,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(b,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===b&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var u=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=g.destroy,b.prototype._undestroy=g.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(14),n(54).setImmediate,n(5))},function(e,t,n){"use strict";var r=n(6).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(15);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]s?a.slice(s).buffer:null}else{var u,c=t;if(-1===(u=c.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=u+1;n=c.substring(0,s),i=c.length>s?c.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(11).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?r-4:r,f=0;f>16&255,s[u++]=t>>8&255,s[u++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[u++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[u++]=t>>8&255,s[u++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;as?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,u=a.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,u=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=c}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,u,c=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-a))<1&&(a--,u*=2),(t+=a+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(a++,u/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*u-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<0;e[n+p]=255&a,p+=d,a/=256,c-=8);e[n+p-d]|=128*g}},function(e,t,n){"use strict";(function(t){ +var r=n(47),o=n(48),i=n(31);function a(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function d(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return H(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,u/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;is&&(n=s-u),i=n;i>=0;i--){for(var f=!0,h=0;ho&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function T(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function k(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+f<=n)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=e[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(u=(15&c)<<12|(63&i)<<6|63&a)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(u=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,r.push(l>>>10&1023|55296),l=56320|1023&l),r.push(l),o+=f}return function(e){var t=e.length;if(t<=C)return String.fromCharCode.apply(String,e);var n="",r=0;for(;rthis.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return k(this,t,n);case"ascii":return I(this,t,n);case"latin1":case"binary":return x(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},u.prototype.compare=function(e,t,n,r,o){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),l=e.slice(t,n),f=0;fo)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return m(this,e,t,n);case"utf8":case"utf-8":return b(this,e,t,n);case"ascii":return w(this,e,t,n);case"latin1":case"binary":return E(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var C=4096;function I(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function M(e,t,n,r,o,i){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function L(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function A(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function B(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,i){return i||B(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function U(e,t,n,r,i){return i||B(e,0,n,8),o.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},u.prototype.readUInt8=function(e,t){return t||P(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||P(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||P(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||P(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||P(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},u.prototype.readInt8=function(e,t){return t||P(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||P(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||P(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||P(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||P(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||M(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):A(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):A(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);M(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):A(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||M(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):A(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return U(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return U(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function H(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(N,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(5))},function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,i=null;function a(e){t.push(e)}function s(e,t){for(var n=[],r=2;r1)for(var n=1;n0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.length||e<0)){var t=this._offset(e);return this._bufs[t[0]][t[1]]}},a.prototype.slice=function(e,t){return"number"==typeof e&&e<0&&(e+=this.length),"number"==typeof t&&t<0&&(t+=this.length),this.copy(null,0,e,t)},a.prototype.copy=function(e,t,n,r){if(("number"!=typeof n||n<0)&&(n=0),("number"!=typeof r||r>this.length)&&(r=this.length),n>=this.length)return e||i.alloc(0);if(r<=0)return e||i.alloc(0);var o,a,s=!!e,u=this._offset(n),c=r-n,l=c,f=s&&t||0,h=u[1];if(0===n&&r==this.length){if(!s)return 1===this._bufs.length?this._bufs[0]:i.concat(this._bufs,this.length);for(a=0;a(o=this._bufs[a].length-h))){this._bufs[a].copy(e,f,h,h+l);break}this._bufs[a].copy(e,f,h),f+=o,l-=o,h&&(h=0)}return e},a.prototype.shallowSlice=function(e,t){if(e=e||0,t="number"!=typeof t?this.length:t,e<0&&(e+=this.length),t<0&&(t+=this.length),e===t)return new a;var n=this._offset(e),r=this._offset(t),o=this._bufs.slice(n[0],r[0]+1);return 0==r[1]?o.pop():o[o.length-1]=o[o.length-1].slice(0,r[1]),0!=n[1]&&(o[0]=o[0].slice(n[1])),new a(o)},a.prototype.toString=function(e,t,n){return this.slice(t,n).toString(e)},a.prototype.consume=function(e){for(;this._bufs.length;){if(!(e>=this._bufs[0].length)){this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift()}return this},a.prototype.duplicate=function(){for(var e=0,t=new a;ethis.length?this.length:t;for(var r=this._offset(t),o=r[0],s=r[1];o=e.length){var c=u.indexOf(e,s);if(-1!==c)return this._reverseOffset([o,c]);s=u.length-e.length+1}else{var l=this._reverseOffset([o,s]);if(this._match(l,e))return l;s++}}s=0}return-1},a.prototype._match=function(e,t){if(this.length-e=0,"must have a non-negative type"),o(a,"must have a decode function"),this.registerEncoder(function(e){return e instanceof t},function(t){var o=i(),a=r.allocUnsafe(1);return a.writeInt8(e,0),o.append(a),o.append(n(t)),o}),this.registerDecoder(e,a),this},registerEncoder:function(e,n){return o(e,"must have an encode function"),o(n,"must have an encode function"),t.push({check:e,encode:n}),this},registerDecoder:function(e,t){return o(e>=0,"must have a non-negative type"),o(t,"must have a decode function"),n.push({type:e,decode:t}),this},encoder:a.encoder,decoder:a.decoder,buffer:!0,type:"msgpack5",IncompleteBufferError:s.IncompleteBufferError}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(16),o=n(22),i=n(8);window.Blazor={navigateTo:r.navigateTo,_internal:{attachRootComponentToElement:i.attachRootComponentToElement,http:o.internalFunctions,uriHelper:r.internalFunctions}}},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=i)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),u=r[n];n=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),d(n)?r.showHidden=n:n&&t._extend(r,n),m(r.showHidden)&&(r.showHidden=!1),m(r.depth)&&(r.depth=2),m(r.colors)&&(r.colors=!1),m(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=u),l(r,e,r.depth)}function u(e,t){var n=s.styles[t];return n?"["+s.colors[n][0]+"m"+e+"["+s.colors[n][1]+"m":e}function c(e,t){return e}function l(e,n,r){if(e.customInspect&&n&&_(n.inspect)&&n.inspect!==t.inspect&&(!n.constructor||n.constructor.prototype!==n)){var o=n.inspect(r,e);return v(o)||(o=l(e,o,r)),o}var i=function(e,t){if(m(t))return e.stylize("undefined","undefined");if(v(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(y(t))return e.stylize(""+t,"number");if(d(t))return e.stylize(""+t,"boolean");if(g(t))return e.stylize("null","null")}(e,n);if(i)return i;var a=Object.keys(n),s=function(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}(a);if(e.showHidden&&(a=Object.getOwnPropertyNames(n)),S(n)&&(a.indexOf("message")>=0||a.indexOf("description")>=0))return f(n);if(0===a.length){if(_(n)){var u=n.name?": "+n.name:"";return e.stylize("[Function"+u+"]","special")}if(b(n))return e.stylize(RegExp.prototype.toString.call(n),"regexp");if(E(n))return e.stylize(Date.prototype.toString.call(n),"date");if(S(n))return f(n)}var c,w="",T=!1,k=["{","}"];(p(n)&&(T=!0,k=["[","]"]),_(n))&&(w=" [Function"+(n.name?": "+n.name:"")+"]");return b(n)&&(w=" "+RegExp.prototype.toString.call(n)),E(n)&&(w=" "+Date.prototype.toUTCString.call(n)),S(n)&&(w=" "+f(n)),0!==a.length||T&&0!=n.length?r<0?b(n)?e.stylize(RegExp.prototype.toString.call(n),"regexp"):e.stylize("[Object]","special"):(e.seen.push(n),c=T?function(e,t,n,r,o){for(var i=[],a=0,s=t.length;a=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1];return n[0]+t+" "+e.join(", ")+" "+n[1]}(c,w,k)):k[0]+w+k[1]}function f(e){return"["+Error.prototype.toString.call(e)+"]"}function h(e,t,n,r,o,i){var a,s,u;if((u=Object.getOwnPropertyDescriptor(t,o)||{value:t[o]}).get?s=u.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):u.set&&(s=e.stylize("[Setter]","special")),I(r,o)||(a="["+o+"]"),s||(e.seen.indexOf(u.value)<0?(s=g(n)?l(e,u.value,null):l(e,u.value,n-1)).indexOf("\n")>-1&&(s=i?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),m(a)){if(i&&o.match(/^\d+$/))return s;(a=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function p(e){return Array.isArray(e)}function d(e){return"boolean"==typeof e}function g(e){return null===e}function y(e){return"number"==typeof e}function v(e){return"string"==typeof e}function m(e){return void 0===e}function b(e){return w(e)&&"[object RegExp]"===T(e)}function w(e){return"object"==typeof e&&null!==e}function E(e){return w(e)&&"[object Date]"===T(e)}function S(e){return w(e)&&("[object Error]"===T(e)||e instanceof Error)}function _(e){return"function"==typeof e}function T(e){return Object.prototype.toString.call(e)}function k(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(n){if(m(i)&&(i=e.env.NODE_DEBUG||""),n=n.toUpperCase(),!a[n])if(new RegExp("\\b"+n+"\\b","i").test(i)){var r=e.pid;a[n]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",n,r,e)}}else a[n]=function(){};return a[n]},t.inspect=s,s.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},s.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=d,t.isNull=g,t.isNullOrUndefined=function(e){return null==e},t.isNumber=y,t.isString=v,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=m,t.isRegExp=b,t.isObject=w,t.isDate=E,t.isError=S,t.isFunction=_,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=n(50);var C=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function I(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){var e,n;console.log("%s - %s",(e=new Date,n=[k(e.getHours()),k(e.getMinutes()),k(e.getSeconds())].join(":"),[e.getDate(),C[e.getMonth()],n].join(" ")),t.format.apply(t,arguments))},t.inherits=n(7),t._extend=function(e,t){if(!t||!w(t))return e;for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e};var x="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function R(e,t){if(!e){var n=new Error("Promise was rejected with a falsy value");n.reason=e,e=n}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(x&&e[x]){var t;if("function"!=typeof(t=e[x]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,x,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,n,r=new Promise(function(e,r){t=e,n=r}),o=[],i=0;i0?("string"==typeof t||a.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?a.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):E(e,a,t,!0):a.ended?e.emit("error",new Error("stream.push() after EOF")):(a.reading=!1,a.decoder&&!n?(t=a.decoder.write(t),a.objectMode||0!==t.length?E(e,a,t,!1):C(e,a)):E(e,a,t,!1))):r||(a.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.lengtht.highWaterMark&&(t.highWaterMark=function(e){return e>=S?e=S:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function T(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?o.nextTick(k,e):k(e))}function k(e){p("emit readable"),e.emit("readable"),O(e)}function C(e,t){t.readingMore||(t.readingMore=!0,o.nextTick(I,e,t))}function I(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;ei.length?i.length:e;if(a===i.length?o+=i:o+=i.slice(0,e),0===(e-=a)){a===i.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=i.slice(a));break}++r}return t.length-=r,o}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,o=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var i=r.data,a=e>i.length?i.length:e;if(i.copy(n,n.length-e,0,a),0===(e-=a)){a===i.length?(++o,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=i.slice(a));break}++o}return t.length-=o,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function M(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,o.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function A(e,t){for(var n=0,r=e.length;n=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?M(this):T(this),null;if(0===(e=_(e,t))&&t.ended)return 0===t.length&&M(this),null;var r,o=t.needReadable;return p("need readable",o),(0===t.length||t.length-e0?P(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&M(this)),null!==r&&this.emit("data",r),r},b.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},b.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,p("pipe count=%d opts=%j",i.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?l:b;function c(t,r){p("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,p("cleanup"),e.removeListener("close",v),e.removeListener("finish",m),e.removeListener("drain",f),e.removeListener("error",y),e.removeListener("unpipe",c),n.removeListener("end",l),n.removeListener("end",b),n.removeListener("data",g),h=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function l(){p("onend"),e.end()}i.endEmitted?o.nextTick(u):n.once("end",u),e.on("unpipe",c);var f=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&s(e,"data")&&(t.flowing=!0,O(e))}}(n);e.on("drain",f);var h=!1;var d=!1;function g(t){p("ondata"),d=!1,!1!==e.write(t)||d||((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==A(i.pipes,e))&&!h&&(p("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,d=!0),n.pause())}function y(t){p("onerror",t),b(),e.removeListener("error",y),0===s(e,"error")&&e.emit("error",t)}function v(){e.removeListener("finish",m),b()}function m(){p("onfinish"),e.removeListener("close",v),b()}function b(){p("unpipe"),n.unpipe(e)}return n.on("data",g),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?a(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",y),e.once("close",v),e.once("finish",m),e.emit("pipe",n),i.flowing||(p("pipe resume"),n.resume()),e},b.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n),this);if(!e){var r=t.pipes,o=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i0&&a.length>o&&!a.warned){a.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=a.length,s=u,console&&console.warn&&console.warn(s)}return e}function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){for(var e=[],t=0;t0&&(a=t[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var u=o[e];if(void 0===u)return!1;if("function"==typeof u)i(u,this,t);else{var c=u.length,l=d(u,c);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){a=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},s.prototype.listeners=function(e){return h(this,e,!0)},s.prototype.rawListeners=function(e){return h(this,e,!1)},s.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):p.call(e,t)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){e.exports=n(34).EventEmitter},function(e,t,n){"use strict";var r=n(18);function o(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,i=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return i||a?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(o,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(r.nextTick(o,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)}),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";(function(t,r,o){var i=n(18);function a(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var o=r.callback;t.pendingcb--,o(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=m;var s,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:i.nextTick;m.WritableState=v;var c=n(15);c.inherits=n(7);var l={deprecate:n(56)},f=n(35),h=n(6).Buffer,p=o.Uint8Array||function(){};var d,g=n(36);function y(){}function v(e,t){s=s||n(10),e=e||{};var r=t instanceof s;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var o=e.highWaterMark,c=e.writableHighWaterMark,l=this.objectMode?16:16384;this.highWaterMark=o||0===o?o:r&&(c||0===c)?c:l,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var f=!1===e.decodeStrings;this.decodeStrings=!f,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,o=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,o){--t.pendingcb,n?(i.nextTick(o,r),i.nextTick(T,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(o(r),e._writableState.errorEmitted=!0,e.emit("error",r),T(e,t))}(e,n,r,t,o);else{var a=S(n);a||n.corked||n.bufferProcessing||!n.bufferedRequest||E(e,n),r?u(w,e,n,a,o):w(e,n,a,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new a(this)}function m(e){if(s=s||n(10),!(d.call(m,this)||this instanceof s))return new m(e);this._writableState=new v(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),f.call(this)}function b(e,t,n,r,o,i,a){t.writelen=r,t.writecb=a,t.writing=!0,t.sync=!0,n?e._writev(o,t.onwrite):e._write(o,i,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function E(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),i=t.corkedRequestsFree;i.entry=n;for(var s=0,u=!0;n;)o[s]=n,n.isBuf||(u=!1),n=n.next,s+=1;o.allBuffers=u,b(e,t,!0,t.length,o,"",i.finish),t.pendingcb++,t.lastBufferedRequest=null,i.next?(t.corkedRequestsFree=i.next,i.next=null):t.corkedRequestsFree=new a(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,l=n.encoding,f=n.callback;if(b(e,t,!1,t.objectMode?1:c.length,c,l,f),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function _(e,t){e._final(function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),T(e,t)})}function T(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,i.nextTick(_,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(m,f),v.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(v.prototype,"buffer",{get:l.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(d=Function.prototype[Symbol.hasInstance],Object.defineProperty(m,Symbol.hasInstance,{value:function(e){return!!d.call(this,e)||this===m&&(e&&e._writableState instanceof v)}})):d=function(e){return e instanceof this},m.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},m.prototype.write=function(e,t,n){var r,o=this._writableState,a=!1,s=!o.objectMode&&(r=e,h.isBuffer(r)||r instanceof p);return s&&!h.isBuffer(e)&&(e=function(e){return h.from(e)}(e)),"function"==typeof t&&(n=t,t=null),s?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=y),o.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),i.nextTick(t,n)}(this,n):(s||function(e,t,n,r){var o=!0,a=!1;return null===n?a=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(a=new TypeError("Invalid non-string/buffer chunk")),a&&(e.emit("error",a),i.nextTick(r,a),o=!1),o}(this,o,e,n))&&(o.pendingcb++,a=function(e,t,n,r,o,i){if(!n){var a=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=h.from(t,n));return t}(t,r,o);r!==a&&(n=!0,o="buffer",r=a)}var s=t.objectMode?1:r.length;t.length+=s;var u=t.length-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(m.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),m.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},m.prototype._writev=null,m.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?i.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(m.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),m.prototype.destroy=g.destroy,m.prototype._undestroy=g.undestroy,m.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(14),n(54).setImmediate,n(5))},function(e,t,n){"use strict";var r=n(6).Buffer,o=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function i(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===o||!o(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=s,t=4;break;case"base64":this.text=l,this.end=f,t=3;break;default:return this.write=h,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function a(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function s(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function l(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function f(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function h(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=i,i.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n=0)return o>0&&(e.lastNeed=o-1),o;if(--r=0)return o>0&&(e.lastNeed=o-2),o;if(--r=0)return o>0&&(2===o?o=0:e.lastNeed=o-3),o;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},i.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";e.exports=a;var r=n(10),o=n(15);function i(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var o=this._readableState;o.reading=!1,(o.needReadable||o.length0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]s?a.slice(s).buffer:null}else{var u,c=t;if(-1===(u=c.indexOf(r.a.RecordSeparator)))throw new Error("Message is incomplete.");s=u+1;n=c.substring(0,s),i=c.length>s?c.substring(s):null}var l=r.a.parse(n),f=JSON.parse(l[0]);if(f.type)throw new Error("Expected a handshake response from the server.");return[i,f]},t}()}).call(this,n(11).Buffer)},,,,,function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0?r-4:r,f=0;f>16&255,s[u++]=t>>8&255,s[u++]=255&t;2===a&&(t=o[e.charCodeAt(f)]<<2|o[e.charCodeAt(f+1)]>>4,s[u++]=255&t);1===a&&(t=o[e.charCodeAt(f)]<<10|o[e.charCodeAt(f+1)]<<4|o[e.charCodeAt(f+2)]>>2,s[u++]=t>>8&255,s[u++]=255&t);return s},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,i=[],a=0,s=n-o;as?s:a+16383));1===o?(t=e[n-1],i.push(r[t>>2]+r[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],i.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return i.join("")};for(var r=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,u=a.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function l(e,t,n){for(var o,i,a=[],s=t;s>18&63]+r[i>>12&63]+r[i>>6&63]+r[63&i]);return a.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,n,r,o){var i,a,s=8*o-r-1,u=(1<>1,l=-7,f=n?o-1:0,h=n?-1:1,p=e[t+f];for(f+=h,i=p&(1<<-l)-1,p>>=-l,l+=s;l>0;i=256*i+e[t+f],f+=h,l-=8);for(a=i&(1<<-l)-1,i>>=-l,l+=r;l>0;a=256*a+e[t+f],f+=h,l-=8);if(0===i)i=1-c;else{if(i===u)return a?NaN:1/0*(p?-1:1);a+=Math.pow(2,r),i-=c}return(p?-1:1)*a*Math.pow(2,i-r)},t.write=function(e,t,n,r,o,i){var a,s,u,c=8*i-o-1,l=(1<>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,p=r?0:i-1,d=r?1:-1,g=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=l):(a=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-a))<1&&(a--,u*=2),(t+=a+f>=1?h/u:h*Math.pow(2,1-f))*u>=2&&(a++,u/=2),a+f>=l?(s=0,a=l):a+f>=1?(s=(t*u-1)*Math.pow(2,o),a+=f):(s=t*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;e[n+p]=255&s,p+=d,s/=256,o-=8);for(a=a<0;e[n+p]=255&a,p+=d,a/=256,c-=8);e[n+p-d]|=128*g}},function(e,t,n){"use strict";(function(t){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ -function r(e,t){if(e===t)return 0;for(var n=e.length,r=t.length,o=0,i=Math.min(n,r);o=0;c--)if(l[c]!==f[c])return!1;for(c=l.length-1;c>=0;c--)if(u=l[c],!b(e[u],t[u],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function m(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){b(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){b(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){b(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){b(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(5))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){},function(e,t,n){"use strict";var r=n(6).Buffer,o=n(53);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(55),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(5))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,u=1,c={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=u,e.exports.encoder=s},function(e,t,n){"use strict";var r=n(17);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(30).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:return i=e.readUInt32BE(r+1),s(e,r,i,5);case 212:return u(e,r,1);case 213:return u(e,r,2);case 214:return u(e,r,4);case 215:return u(e,r,8);case 216:return u(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?c(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?c(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?c(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],u=0;for(t+=o,a=0;a0&&l.write(u,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(u,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(u,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(u,5));else if(u&&(u.readUInt32LE||u instanceof Uint8Array))u instanceof Uint8Array&&(u=r.from(u)),u.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=u.length):u.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(u.length,1)),l=o([l,u]);else if(Array.isArray(u))u.length<16?(l=r.allocUnsafe(1))[0]=144|u.length:u.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(u.length,1)),l=u.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!a&&"function"==typeof u.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=r.allocUnsafe(10))[0]=215,t[1]=-1;var s=4*a,u=i/Math.pow(2,32),c=s+u&4294967295,l=4294967295&i;t.writeInt32BE(c,2),t.writeInt32BE(l,6)}else(t=r.allocUnsafe(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(u);if("object"==typeof u)l=function(t){var n,i,a=-1,s=[];for(n=0;n>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(u)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:a<65535?((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1)):((n=r.allocUnsafe(5))[0]=223,n.writeUInt32BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(u);else if("number"==typeof u){if(function(e){return e%1!=0}(u))return i(u,t);if(u>=0)if(u<128)(l=r.allocUnsafe(1))[0]=u;else if(u<256)(l=r.allocUnsafe(2))[0]=204,l[1]=u;else if(u<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(u,1);else if(u<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(u,1);else{if(!(u<=9007199254740991))return i(u,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,u)}else if(u>=-32)(l=r.allocUnsafe(1))[0]=256+u;else if(u>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(u,1);else if(u>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(u,1);else if(u>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(u,1);else{if(!(u>=-9007199254740991))return i(u,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var u=(255^e[s])+a;e[s]=255&u,a=u>>8}}(l,1,u)}}}if(!l)throw new Error("not implemented yet");return c?l:l.slice()}return s}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(40),o=function(){function e(e){this.document=e,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=r.AutoReconnectCircuitHandler.DialogId;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='
',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.button.addEventListener("click",function(){return window.Blazor.reconnect()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.message.textContent="Failed to reconnect to the server."},e}();t.DefaultReconnectDisplay=o},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId)this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed.");else try{this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),this.completeBatch(n,e)}catch(t){throw this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,t.toString()),t}},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e.renderQueues=new Map,e}();t.default=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(65),o=function(){function e(e){this.batchData=e;var t=new u(e);this.arrayRangeReader=new c(e),this.arraySegmentReader=new l(e),this.diffReader=new i(e),this.editReader=new a(e,t),this.frameReader=new s(e,t)}return e.prototype.updatedComponents=function(){return f(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return f(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return f(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return f(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+16*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e}();t.OutOfProcessRenderBatch=o;var i=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return f(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),a=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return f(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return f(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return f(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=f(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),s=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return f(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return f(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return f(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=f(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=f(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return f(this.batchDataUint8,e+12)},e}(),u=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=f(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=f(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(19),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}},a=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var s=n(16),u=n(68),c=function(){function e(e,t){this.circuitId=e,this.components=t}return e.prototype.reconnect=function(e){return e.invoke("ConnectCircuit",this.circuitId)},e}();function l(e){if(e.nodeType===Node.COMMENT_NODE&&e.textContent){var t=/\W+M.A.C.Component:[^{]*(.*)$/.exec(e.textContent),n=t&&t[1];if(n)try{var r=JSON.parse(n),o=r.componentId,i=r.circuitId,a=r.rendererId;if(!!o&&!!i&&!!a)return{node:e,circuitId:i,rendererId:Number.parseInt(a),componentId:Number.parseInt(o)};throw new Error("Found malformed start component comment at "+e.textContent)}catch(t){throw new Error("Found malformed start component comment at "+e.textContent)}}}function f(e,t,n,r){for(var o=n;o>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),u=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,u=a.parse(e);s=0;c--)if(l[c]!==f[c])return!1;for(c=l.length-1;c>=0;c--)if(u=l[c],!m(e[u],t[u],n,r))return!1;return!0}(e,t,n,a))}return n?e===t:e==t}function b(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function w(e,t){if(!e||!t)return!1;if("[object RegExp]"==Object.prototype.toString.call(t))return t.test(e);try{if(e instanceof t)return!0}catch(e){}return!Error.isPrototypeOf(t)&&!0===t.call({},e)}function E(e,t,n,r){var o;if("function"!=typeof t)throw new TypeError('"block" argument must be a function');"string"==typeof n&&(r=n,n=null),o=function(e){var t;try{e()}catch(e){t=e}return t}(t),r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!o&&y(o,n,"Missing expected exception"+r);var a="string"==typeof r,s=!e&&o&&!n;if((!e&&i.isError(o)&&a&&w(o,n)||s)&&y(o,n,"Got unwanted exception"+r),e&&o&&n&&!w(o,n)||!e&&o)throw o}f.AssertionError=function(e){var t;this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=d(g((t=this).actual),128)+" "+t.operator+" "+d(g(t.expected),128),this.generatedMessage=!0);var n=e.stackStartFunction||y;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var o=r.stack,i=p(n),a=o.indexOf("\n"+i);if(a>=0){var s=o.indexOf("\n",a+1);o=o.substring(s+1)}this.stack=o}}},i.inherits(f.AssertionError,Error),f.fail=y,f.ok=v,f.equal=function(e,t,n){e!=t&&y(e,t,n,"==",f.equal)},f.notEqual=function(e,t,n){e==t&&y(e,t,n,"!=",f.notEqual)},f.deepEqual=function(e,t,n){m(e,t,!1)||y(e,t,n,"deepEqual",f.deepEqual)},f.deepStrictEqual=function(e,t,n){m(e,t,!0)||y(e,t,n,"deepStrictEqual",f.deepStrictEqual)},f.notDeepEqual=function(e,t,n){m(e,t,!1)&&y(e,t,n,"notDeepEqual",f.notDeepEqual)},f.notDeepStrictEqual=function e(t,n,r){m(t,n,!0)&&y(t,n,r,"notDeepStrictEqual",e)},f.strictEqual=function(e,t,n){e!==t&&y(e,t,n,"===",f.strictEqual)},f.notStrictEqual=function(e,t,n){e===t&&y(e,t,n,"!==",f.notStrictEqual)},f.throws=function(e,t,n){E(!0,e,t,n)},f.doesNotThrow=function(e,t,n){E(!1,e,t,n)},f.ifError=function(e){if(e)throw e};var S=Object.keys||function(e){var t=[];for(var n in e)a.call(e,n)&&t.push(n);return t}}).call(this,n(5))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){},function(e,t,n){"use strict";var r=n(6).Buffer,o=n(53);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,o,i=r.allocUnsafe(e>>>0),a=this.head,s=0;a;)t=a.data,n=i,o=s,t.copy(n,o),s+=a.data.length,a=a.next;return i},e}(),o&&o.inspect&&o.inspect.custom&&(e.exports.prototype[o.inspect.custom]=function(){var e=o.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new i(o.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new i(o.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(55),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(5))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,o,i,a,s,u=1,c={},l=!1,f=e.document,h=Object.getPrototypeOf&&Object.getPrototypeOf(e);h=h&&h.setTimeout?h:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick(function(){d(e)})}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((i=new MessageChannel).port1.onmessage=function(e){d(e.data)},r=function(e){i.port2.postMessage(e)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,r=function(e){var t=f.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,o.removeChild(t),t=null},o.appendChild(t)}):r=function(e){setTimeout(d,0,e)}:(a="setImmediate$"+Math.random()+"$",s=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(a)&&d(+t.data.slice(a.length))},e.addEventListener?e.addEventListener("message",s,!1):e.attachEvent("onmessage",s),r=function(t){e.postMessage(a+t,"*")}),h.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n0?this._transform(null,t,n):n()},e.exports.decoder=u,e.exports.encoder=s},function(e,t,n){"use strict";var r=n(17);function o(e){Error.call(this),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.message=e||"unable to decode"}n(30).inherits(o,Error),e.exports=function(e){return function(e){e instanceof r||(e=r().append(e));var t=i(e);if(t)return e.consume(t.bytesConsumed),t.value;throw new o};function t(e,t,n){return t>=n+e}function n(e,t){return{value:e,bytesConsumed:t}}function i(e,r){r=void 0===r?0:r;var o=e.length-r;if(o<=0)return null;var i,l,f,h=e.readUInt8(r),p=0;if(!function(e,t){var n=function(e){switch(e){case 196:return 2;case 197:return 3;case 198:return 5;case 199:return 3;case 200:return 4;case 201:return 6;case 202:return 5;case 203:return 9;case 204:return 2;case 205:return 3;case 206:return 5;case 207:return 9;case 208:return 2;case 209:return 3;case 210:return 5;case 211:return 9;case 212:return 3;case 213:return 4;case 214:return 6;case 215:return 10;case 216:return 18;case 217:return 2;case 218:return 3;case 219:return 5;case 222:return 3;default:return-1}}(e);return!(-1!==n&&t=0;f--)p+=e.readUInt8(r+f+1)*Math.pow(2,8*(7-f));return n(p,9);case 208:return n(p=e.readInt8(r+1),2);case 209:return n(p=e.readInt16BE(r+1),3);case 210:return n(p=e.readInt32BE(r+1),5);case 211:return n(p=function(e,t){var n=128==(128&e[t]);if(n)for(var r=1,o=t+7;o>=t;o--){var i=(255^e[o])+r;e[o]=255&i,r=i>>8}var a=e.readUInt32BE(t+0),s=e.readUInt32BE(t+4);return(4294967296*a+s)*(n?-1:1)}(e.slice(r+1,r+9),0),9);case 202:return n(p=e.readFloatBE(r+1),5);case 203:return n(p=e.readDoubleBE(r+1),9);case 217:return t(i=e.readUInt8(r+1),o,2)?n(p=e.toString("utf8",r+2,r+2+i),2+i):null;case 218:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.toString("utf8",r+3,r+3+i),3+i):null;case 219:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.toString("utf8",r+5,r+5+i),5+i):null;case 196:return t(i=e.readUInt8(r+1),o,2)?n(p=e.slice(r+2,r+2+i),2+i):null;case 197:return t(i=e.readUInt16BE(r+1),o,3)?n(p=e.slice(r+3,r+3+i),3+i):null;case 198:return t(i=e.readUInt32BE(r+1),o,5)?n(p=e.slice(r+5,r+5+i),5+i):null;case 220:return o<3?null:(i=e.readUInt16BE(r+1),a(e,r,i,3));case 221:return o<5?null:(i=e.readUInt32BE(r+1),a(e,r,i,5));case 222:return i=e.readUInt16BE(r+1),s(e,r,i,3);case 223:return i=e.readUInt32BE(r+1),s(e,r,i,5);case 212:return u(e,r,1);case 213:return u(e,r,2);case 214:return u(e,r,4);case 215:return u(e,r,8);case 216:return u(e,r,16);case 199:return i=e.readUInt8(r+1),l=e.readUInt8(r+2),t(i,o,3)?c(e,r,l,i,3):null;case 200:return i=e.readUInt16BE(r+1),l=e.readUInt8(r+3),t(i,o,4)?c(e,r,l,i,4):null;case 201:return i=e.readUInt32BE(r+1),l=e.readUInt8(r+5),t(i,o,6)?c(e,r,l,i,6):null}if(144==(240&h))return a(e,r,i=15&h,1);if(128==(240&h))return s(e,r,i=15&h,1);if(160==(224&h))return t(i=31&h,o,1)?n(p=e.toString("utf8",r+1,r+i+1),i+1):null;if(h>=224)return n(p=h-256,1);if(h<128)return n(h,1);throw new Error("not implemented yet")}function a(e,t,r,o){var a,s=[],u=0;for(t+=o,a=0;a0&&l.write(u,1)):f<=255&&!n?((l=r.allocUnsafe(2+f))[0]=217,l[1]=f,l.write(u,2)):f<=65535?((l=r.allocUnsafe(3+f))[0]=218,l.writeUInt16BE(f,1),l.write(u,3)):((l=r.allocUnsafe(5+f))[0]=219,l.writeUInt32BE(f,1),l.write(u,5));else if(u&&(u.readUInt32LE||u instanceof Uint8Array))u instanceof Uint8Array&&(u=r.from(u)),u.length<=255?((l=r.allocUnsafe(2))[0]=196,l[1]=u.length):u.length<=65535?((l=r.allocUnsafe(3))[0]=197,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=198,l.writeUInt32BE(u.length,1)),l=o([l,u]);else if(Array.isArray(u))u.length<16?(l=r.allocUnsafe(1))[0]=144|u.length:u.length<65536?((l=r.allocUnsafe(3))[0]=220,l.writeUInt16BE(u.length,1)):((l=r.allocUnsafe(5))[0]=221,l.writeUInt32BE(u.length,1)),l=u.reduce(function(e,t){return e.append(s(t,!0)),e},o().append(l));else{if(!a&&"function"==typeof u.getDate)return function(e){var t,n=1*e,i=Math.floor(n/1e3),a=1e6*(n-1e3*i);if(a||i>4294967295){(t=r.allocUnsafe(10))[0]=215,t[1]=-1;var s=4*a,u=i/Math.pow(2,32),c=s+u&4294967295,l=4294967295&i;t.writeInt32BE(c,2),t.writeInt32BE(l,6)}else(t=r.allocUnsafe(6))[0]=214,t[1]=-1,t.writeUInt32BE(Math.floor(n/1e3),2);return o().append(t)}(u);if("object"==typeof u)l=function(t){var n,i,a=-1,s=[];for(n=0;n>8),s.push(255&a)):(s.push(201),s.push(a>>24),s.push(a>>16&255),s.push(a>>8&255),s.push(255&a));return o().append(r.from(s)).append(i)}(u)||function(e){var t,n,i=[],a=0;for(t in e)e.hasOwnProperty(t)&&void 0!==e[t]&&"function"!=typeof e[t]&&(++a,i.push(s(t,!0)),i.push(s(e[t],!0)));a<16?(n=r.allocUnsafe(1))[0]=128|a:a<65535?((n=r.allocUnsafe(3))[0]=222,n.writeUInt16BE(a,1)):((n=r.allocUnsafe(5))[0]=223,n.writeUInt32BE(a,1));return i.unshift(n),i.reduce(function(e,t){return e.append(t)},o())}(u);else if("number"==typeof u){if(function(e){return e%1!=0}(u))return i(u,t);if(u>=0)if(u<128)(l=r.allocUnsafe(1))[0]=u;else if(u<256)(l=r.allocUnsafe(2))[0]=204,l[1]=u;else if(u<65536)(l=r.allocUnsafe(3))[0]=205,l.writeUInt16BE(u,1);else if(u<=4294967295)(l=r.allocUnsafe(5))[0]=206,l.writeUInt32BE(u,1);else{if(!(u<=9007199254740991))return i(u,!0);(l=r.allocUnsafe(9))[0]=207,function(e,t){for(var n=7;n>=0;n--)e[n+1]=255&t,t/=256}(l,u)}else if(u>=-32)(l=r.allocUnsafe(1))[0]=256+u;else if(u>=-128)(l=r.allocUnsafe(2))[0]=208,l.writeInt8(u,1);else if(u>=-32768)(l=r.allocUnsafe(3))[0]=209,l.writeInt16BE(u,1);else if(u>-214748365)(l=r.allocUnsafe(5))[0]=210,l.writeInt32BE(u,1);else{if(!(u>=-9007199254740991))return i(u,!0);(l=r.allocUnsafe(9))[0]=211,function(e,t,n){var r=n<0;r&&(n=Math.abs(n));var o=n%4294967296,i=n/4294967296;if(e.writeUInt32BE(Math.floor(i),t+0),e.writeUInt32BE(o,t+4),r)for(var a=1,s=t+7;s>=t;s--){var u=(255^e[s])+a;e[s]=255&u,a=u>>8}}(l,1,u)}}}if(!l)throw new Error("not implemented yet");return c?l:l.slice()}return s}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e){this.dialog=e}return e.prototype.show=function(){this.removeClasses(),this.dialog.classList.add(e.ShowClassName)},e.prototype.hide=function(){this.removeClasses(),this.dialog.classList.add(e.HideClassName)},e.prototype.failed=function(){this.removeClasses(),this.dialog.classList.add(e.FailedClassName)},e.prototype.removeClasses=function(){this.dialog.classList.remove(e.ShowClassName,e.HideClassName,e.FailedClassName)},e.ShowClassName="components-reconnect-show",e.HideClassName="components-reconnect-hide",e.FailedClassName="components-reconnect-failed",e}();t.UserSpecifiedDisplay=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(40),o=function(){function e(e){this.document=e,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=r.AutoReconnectCircuitHandler.DialogId;this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1000","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold"].join(";"),this.modal.innerHTML='
',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.button.addEventListener("click",function(){return window.Blazor.reconnect()})}return e.prototype.show=function(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.button.style.display="none",this.message.textContent="Attempting to reconnect to the server..."},e.prototype.hide=function(){this.modal.style.display="none"},e.prototype.failed=function(){this.button.style.display="block",this.message.textContent="Failed to reconnect to the server."},e}();t.DefaultReconnectDisplay=o},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]this.nextBatchId)this.logger.log(s.LogLevel.Debug,"Waiting for batch "+this.nextBatchId+". Batch "+e+" not processed.");else try{this.nextBatchId++,this.logger.log(s.LogLevel.Debug,"Applying batch "+e+"."),i.renderBatch(this.browserRendererId,new a.OutOfProcessRenderBatch(t)),this.completeBatch(n,e)}catch(t){throw this.logger.log(s.LogLevel.Error,"There was an error applying batch "+e+"."),n.send("OnRenderCompleted",e,t.toString()),t}},e.prototype.getLastBatchid=function(){return this.nextBatchId-1},e.prototype.completeBatch=function(e,t){return r(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.send("OnRenderCompleted",t,null)];case 1:return n.sent(),[3,3];case 2:return n.sent(),this.logger.log(s.LogLevel.Warning,"Failed to deliver completion notification for render '"+t+"'."),[3,3];case 3:return[2]}})})},e.renderQueues=new Map,e}();t.default=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(65),o=function(){function e(e){this.batchData=e;var t=new u(e);this.arrayRangeReader=new c(e),this.arraySegmentReader=new l(e),this.diffReader=new i(e),this.editReader=new a(e,t),this.frameReader=new s(e,t)}return e.prototype.updatedComponents=function(){return f(this.batchData,this.batchData.length-20)},e.prototype.referenceFrames=function(){return f(this.batchData,this.batchData.length-16)},e.prototype.disposedComponentIds=function(){return f(this.batchData,this.batchData.length-12)},e.prototype.disposedEventHandlerIds=function(){return f(this.batchData,this.batchData.length-8)},e.prototype.updatedComponentsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e.prototype.referenceFramesEntry=function(e,t){return e+16*t},e.prototype.disposedComponentIdsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e.prototype.disposedEventHandlerIdsEntry=function(e,t){var n=e+4*t;return f(this.batchData,n)},e}();t.OutOfProcessRenderBatch=o;var i=function(){function e(e){this.batchDataUint8=e}return e.prototype.componentId=function(e){return f(this.batchDataUint8,e)},e.prototype.edits=function(e){return e+4},e.prototype.editsEntry=function(e,t){return e+16*t},e}(),a=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.editType=function(e){return f(this.batchDataUint8,e)},e.prototype.siblingIndex=function(e){return f(this.batchDataUint8,e+4)},e.prototype.newTreeIndex=function(e){return f(this.batchDataUint8,e+8)},e.prototype.moveToSiblingIndex=function(e){return f(this.batchDataUint8,e+8)},e.prototype.removedAttributeName=function(e){var t=f(this.batchDataUint8,e+12);return this.stringReader.readString(t)},e}(),s=function(){function e(e,t){this.batchDataUint8=e,this.stringReader=t}return e.prototype.frameType=function(e){return f(this.batchDataUint8,e)},e.prototype.subtreeLength=function(e){return f(this.batchDataUint8,e+4)},e.prototype.elementReferenceCaptureId=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.componentId=function(e){return f(this.batchDataUint8,e+8)},e.prototype.elementName=function(e){var t=f(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.textContent=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.markupContent=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeName=function(e){var t=f(this.batchDataUint8,e+4);return this.stringReader.readString(t)},e.prototype.attributeValue=function(e){var t=f(this.batchDataUint8,e+8);return this.stringReader.readString(t)},e.prototype.attributeEventHandlerId=function(e){return f(this.batchDataUint8,e+12)},e}(),u=function(){function e(e){this.batchDataUint8=e,this.stringTableStartIndex=f(e,e.length-4)}return e.prototype.readString=function(e){if(-1===e)return null;var t,n=f(this.batchDataUint8,this.stringTableStartIndex+4*e),o=function(e,t){for(var n=0,r=0,o=0;o<4;o++){var i=e[t+o];if(n|=(127&i)<65535&&(c-=65536,r.push(c>>>10&1023|55296),c=56320|1023&c),r.push(c)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(19),o=function(){function e(){}return e.prototype.log=function(e,t){},e.instance=new e,e}();t.NullLogger=o;var i=function(){function e(e){this.minimumLogLevel=e}return e.prototype.log=function(e,t){if(e>=this.minimumLogLevel)switch(e){case r.LogLevel.Critical:case r.LogLevel.Error:console.error("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Warning:console.warn("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;case r.LogLevel.Information:console.info("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t);break;default:console.log("["+(new Date).toISOString()+"] "+r.LogLevel[e]+": "+t)}},e}();t.ConsoleLogger=i},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(o,i){function a(e){try{u(r.next(e))}catch(e){i(e)}}function s(e){try{u(r.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new n(function(t){t(e.value)}).then(a,s)}u((r=r.apply(e,t||[])).next())})},o=this&&this.__generator||function(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}},a=this&&this.__read||function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a};Object.defineProperty(t,"__esModule",{value:!0});var s=n(16),u=n(68),c=function(){function e(e,t){this.circuitId=e,this.components=t}return e.prototype.reconnect=function(e){return e.invoke("ConnectCircuit",this.circuitId)},e}();function l(e){if(e.nodeType===Node.COMMENT_NODE&&e.textContent){var t=/\W+M.A.C.Component:[^{]*(.*)$/.exec(e.textContent),n=t&&t[1];if(n)try{var r=JSON.parse(n),o=r.componentId,i=r.circuitId,a=r.rendererId;if(!!o&&!!i&&!!a)return{node:e,circuitId:i,rendererId:Number.parseInt(a),componentId:Number.parseInt(o)};throw new Error("Found malformed start component comment at "+e.textContent)}catch(t){throw new Error("Found malformed start component comment at "+e.textContent)}}}function f(e,t,n,r){for(var o=n;o>=7)>0&&(r|=128),n.push(r)}while(t>0);t=e.byteLength||e.length;var o=new Uint8Array(n.length+t);return o.set(n,0),o.set(e,n.length),o.buffer},e.parse=function(e){for(var t=[],n=new Uint8Array(e),r=[0,7,14,21,28],o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+i+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+i,o+i+a):n.subarray(o+i,o+i+a)),o=o+i+a}return t},e}();var s=new Uint8Array([145,i.MessageType.Ping]),u=function(){function e(){this.name="messagepack",this.version=1,this.transferFormat=i.TransferFormat.Binary}return e.prototype.parseMessages=function(e,t){if(!(e instanceof r.Buffer||(n=e,n&&"undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer or Buffer.");var n;null===t&&(t=i.NullLogger.instance);for(var o=[],s=0,u=a.parse(e);s0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function u(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(l(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=l,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===function(e){if(e instanceof Element)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}(e).namespaceURI},t.getLogicalChildrenArray=s},,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function u(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]-1?a.substring(0,u):"",s=u>-1?a.substring(u+1):a,c=t.monoPlatform.findMethod(e,l,s,i);t.monoPlatform.callMethod(c,null,r)},callMethod:function(e,n,r){if(r.length>4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),u=Module.stackAlloc(4),l=0;l0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return e[r]=[],e}function u(e,t,n){var a=e;if(e instanceof Comment&&(s(a)&&s(a).length>0))throw new Error("Not implemented: inserting non-empty logical container");if(l(a))throw new Error("Not implemented: moving existing logical children");var i=s(t);if(n0;)e(r,0);var a=r;a.parentNode.removeChild(a)},t.getLogicalParent=l,t.getLogicalSiblingEnd=function(e){return e[a]||null},t.getLogicalChild=function(e,t){return s(e)[t]},t.isSvgElement=function(e){return"http://www.w3.org/2000/svg"===c(e).namespaceURI},t.getLogicalChildrenArray=s,t.permuteLogicalChildren=function(e,t){var n=s(e);t.forEach(function(e){e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=function e(t){if(t instanceof Element)return t;var n=f(t);if(n)return n.previousSibling;var r=l(t);return r instanceof Element?r.lastChild:e(r)}(e.moveRangeStart)}),t.forEach(function(t){var r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):d(r,e)}),t.forEach(function(e){for(var t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd,a=r;a;){var i=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=i}n.removeChild(t)}),t.forEach(function(e){n[e.toSiblingIndex]=e.moveRangeStart})},t.getClosestDomElement=c},,,function(e,t,n){"use strict";var r;!function(e){window.DotNet=e;var t=[],n={},r={},o=1,a=null;function i(e){t.push(e)}function u(e,t){for(var n=[],r=2;r0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]-1?a.substring(0,u):"",s=u>-1?a.substring(u+1):a,c=t.monoPlatform.findMethod(e,l,s,i);t.monoPlatform.callMethod(c,null,r)},callMethod:function(e,n,r){if(r.length>4)throw new Error("Currently, MonoPlatform supports passing a maximum of 4 arguments from JS to .NET. You tried to pass "+r.length+".");var o=Module.stackSave();try{for(var a=Module.stackAlloc(r.length),u=Module.stackAlloc(4),l=0;l, referenceFrames: ArrayValues) { let currentDepth = 0; let childIndexAtCurrentDepth = childIndex; + let permutationList: PermutationListEntry[] | undefined; const arraySegmentReader = batch.arraySegmentReader; const editReader = batch.editReader; @@ -152,6 +161,19 @@ export class BrowserRenderer { childIndexAtCurrentDepth = currentDepth === 0 ? childIndex : 0; // The childIndex is only ever nonzero at zero depth break; } + case EditType.permutationListEntry: { + permutationList = permutationList || []; + permutationList.push({ + fromSiblingIndex: childIndexAtCurrentDepth + editReader.siblingIndex(edit), + toSiblingIndex: childIndexAtCurrentDepth + editReader.moveToSiblingIndex(edit), + }); + break; + } + case EditType.permutationListEnd: { + permuteLogicalChildren(parent, permutationList!); + permutationList = undefined; + break; + } default: { const unknownType: never = editType; // Compile-time verification that the switch was exhaustive throw new Error(`Unknown edit type: ${unknownType}`); diff --git a/src/Components/Browser.JS/src/Rendering/LogicalElements.ts b/src/Components/Browser.JS/src/Rendering/LogicalElements.ts index f52e170fa4..dee2e78e25 100644 --- a/src/Components/Browser.JS/src/Rendering/LogicalElements.ts +++ b/src/Components/Browser.JS/src/Rendering/LogicalElements.ts @@ -155,13 +155,60 @@ export function getLogicalChildrenArray(element: LogicalElement) { return element[logicalChildrenPropname] as LogicalElement[]; } -function getLogicalNextSibling(element: LogicalElement): LogicalElement | null { - const siblings = getLogicalChildrenArray(getLogicalParent(element)!); - const siblingIndex = Array.prototype.indexOf.call(siblings, element); - return siblings[siblingIndex + 1] || null; +export function permuteLogicalChildren(parent: LogicalElement, permutationList: PermutationListEntry[]) { + // The permutationList must represent a valid permutation, i.e., the list of 'from' indices + // is distinct, and the list of 'to' indices is a permutation of it. The algorithm here + // relies on that assumption. + + // Each of the phases here has to happen separately, because each one is designed not to + // interfere with the indices or DOM entries used by subsequent phases. + + // Phase 1: track which nodes we will move + const siblings = getLogicalChildrenArray(parent); + permutationList.forEach((listEntry: PermutationListEntryWithTrackingData) => { + listEntry.moveRangeStart = siblings[listEntry.fromSiblingIndex]; + listEntry.moveRangeEnd = findLastDomNodeInRange(listEntry.moveRangeStart); + }); + + // Phase 2: insert markers + permutationList.forEach((listEntry: PermutationListEntryWithTrackingData) => { + const marker = listEntry.moveToBeforeMarker = document.createComment('marker'); + const insertBeforeNode = siblings[listEntry.toSiblingIndex + 1] as any as Node; + if (insertBeforeNode) { + insertBeforeNode.parentNode!.insertBefore(marker, insertBeforeNode); + } else { + appendDomNode(marker, parent); + } + }); + + // Phase 3: move descendants & remove markers + permutationList.forEach((listEntry: PermutationListEntryWithTrackingData) => { + const insertBefore = listEntry.moveToBeforeMarker!; + const parentDomNode = insertBefore.parentNode!; + const elementToMove = listEntry.moveRangeStart!; + const moveEndNode = listEntry.moveRangeEnd!; + let nextToMove = elementToMove as any as Node | null; + while (nextToMove) { + const nextNext = nextToMove.nextSibling; + parentDomNode.insertBefore(nextToMove, insertBefore); + + if (nextToMove === moveEndNode) { + break; + } else { + nextToMove = nextNext; + } + } + + parentDomNode.removeChild(insertBefore); + }); + + // Phase 4: update siblings index + permutationList.forEach((listEntry: PermutationListEntryWithTrackingData) => { + siblings[listEntry.toSiblingIndex] = listEntry.moveRangeStart!; + }); } -function getClosestDomElement(logicalElement: LogicalElement) { +export function getClosestDomElement(logicalElement: LogicalElement) { if (logicalElement instanceof Element) { return logicalElement; } else if (logicalElement instanceof Comment) { @@ -171,6 +218,24 @@ function getClosestDomElement(logicalElement: LogicalElement) { } } +export interface PermutationListEntry { + fromSiblingIndex: number, + toSiblingIndex: number, +} + +interface PermutationListEntryWithTrackingData extends PermutationListEntry { + // These extra properties are used internally when processing the permutation list + moveRangeStart?: LogicalElement, + moveRangeEnd?: Node, + moveToBeforeMarker?: Node, +} + +function getLogicalNextSibling(element: LogicalElement): LogicalElement | null { + const siblings = getLogicalChildrenArray(getLogicalParent(element)!); + const siblingIndex = Array.prototype.indexOf.call(siblings, element); + return siblings[siblingIndex + 1] || null; +} + function appendDomNode(child: Node, parent: LogicalElement) { // This function only puts 'child' into the DOM in the right place relative to 'parent' // It does not update the logical children array of anything @@ -192,6 +257,27 @@ function appendDomNode(child: Node, parent: LogicalElement) { } } +// Returns the final node (in depth-first evaluation order) that is a descendant of the logical element. +// As such, the entire subtree is between 'element' and 'findLastDomNodeInRange(element)' inclusive. +function findLastDomNodeInRange(element: LogicalElement) { + if (element instanceof Element) { + return element; + } + + const nextSibling = getLogicalNextSibling(element); + if (nextSibling) { + // Simple case: not the last logical sibling, so take the node before the next sibling + return (nextSibling as any as Node).previousSibling; + } else { + // Harder case: there's no logical next-sibling, so recurse upwards until we find + // a logical ancestor that does have one, or a physical element + const logicalParent = getLogicalParent(element)!; + return logicalParent instanceof Element + ? logicalParent.lastChild + : findLastDomNodeInRange(logicalParent); + } +} + function createSymbolOrFallback(fallback: string): symbol | string { return typeof Symbol === 'function' ? Symbol() : fallback; } diff --git a/src/Components/Browser.JS/src/Rendering/RenderBatch/OutOfProcessRenderBatch.ts b/src/Components/Browser.JS/src/Rendering/RenderBatch/OutOfProcessRenderBatch.ts index dde028624f..b33025e55d 100644 --- a/src/Components/Browser.JS/src/Rendering/RenderBatch/OutOfProcessRenderBatch.ts +++ b/src/Components/Browser.JS/src/Rendering/RenderBatch/OutOfProcessRenderBatch.ts @@ -100,6 +100,10 @@ class OutOfProcessRenderTreeEditReader implements RenderTreeEditReader { return readInt32LE(this.batchDataUint8, edit as any + 8); // 3rd int } + moveToSiblingIndex(edit: RenderTreeEdit) { + return readInt32LE(this.batchDataUint8, edit as any + 8); // 3rd int + } + removedAttributeName(edit: RenderTreeEdit) { const stringIndex = readInt32LE(this.batchDataUint8, edit as any + 12); // 4th int return this.stringReader.readString(stringIndex); diff --git a/src/Components/Browser.JS/src/Rendering/RenderBatch/RenderBatch.ts b/src/Components/Browser.JS/src/Rendering/RenderBatch/RenderBatch.ts index 3faddab664..88a162a447 100644 --- a/src/Components/Browser.JS/src/Rendering/RenderBatch/RenderBatch.ts +++ b/src/Components/Browser.JS/src/Rendering/RenderBatch/RenderBatch.ts @@ -37,6 +37,7 @@ export interface RenderTreeEditReader { editType(edit: RenderTreeEdit): EditType; siblingIndex(edit: RenderTreeEdit): number; newTreeIndex(edit: RenderTreeEdit): number; + moveToSiblingIndex(edit: RenderTreeEdit): number; removedAttributeName(edit: RenderTreeEdit): string | null; } @@ -71,6 +72,8 @@ export enum EditType { stepIn = 6, stepOut = 7, updateMarkup = 8, + permutationListEntry = 9, + permutationListEnd = 10, } export enum FrameType { diff --git a/src/Components/Browser.JS/src/Rendering/RenderBatch/SharedMemoryRenderBatch.ts b/src/Components/Browser.JS/src/Rendering/RenderBatch/SharedMemoryRenderBatch.ts index 4eb5792bda..2173cb1ecf 100644 --- a/src/Components/Browser.JS/src/Rendering/RenderBatch/SharedMemoryRenderBatch.ts +++ b/src/Components/Browser.JS/src/Rendering/RenderBatch/SharedMemoryRenderBatch.ts @@ -83,16 +83,17 @@ const diffReader = { // Keep in sync with memory layout in RenderTreeEdit.cs const editReader = { - structLength: 16, + structLength: 20, editType: (edit: RenderTreeEdit) => platform.readInt32Field(edit as any, 0) as EditType, siblingIndex: (edit: RenderTreeEdit) => platform.readInt32Field(edit as any, 4), newTreeIndex: (edit: RenderTreeEdit) => platform.readInt32Field(edit as any, 8), - removedAttributeName: (edit: RenderTreeEdit) => platform.readStringField(edit as any, 12), + moveToSiblingIndex: (edit: RenderTreeEdit) => platform.readInt32Field(edit as any, 8), + removedAttributeName: (edit: RenderTreeEdit) => platform.readStringField(edit as any, 16), }; // Keep in sync with memory layout in RenderTreeFrame.cs const frameReader = { - structLength: 28, + structLength: 36, frameType: (frame: RenderTreeFrame) => platform.readInt32Field(frame as any, 4) as FrameType, subtreeLength: (frame: RenderTreeFrame) => platform.readInt32Field(frame as any, 8), elementReferenceCaptureId: (frame: RenderTreeFrame) => platform.readStringField(frame as any, 16), diff --git a/src/Components/Browser/src/RendererRegistryEventDispatcher.cs b/src/Components/Browser/src/RendererRegistryEventDispatcher.cs index 469a0dcae0..1ddc01f335 100644 --- a/src/Components/Browser/src/RendererRegistryEventDispatcher.cs +++ b/src/Components/Browser/src/RendererRegistryEventDispatcher.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.JSInterop; @@ -13,6 +14,10 @@ namespace Microsoft.AspNetCore.Components.Browser /// public static class RendererRegistryEventDispatcher { + private static bool isDispatchingEvent; + private static Queue deferredIncomingEvents + = new Queue(); + /// /// For framework use only. /// @@ -20,9 +25,62 @@ namespace Microsoft.AspNetCore.Components.Browser public static Task DispatchEvent( BrowserEventDescriptor eventDescriptor, string eventArgsJson) { - var eventArgs = ParseEventArgsJson(eventDescriptor.EventArgsType, eventArgsJson); - var renderer = RendererRegistry.Current.Find(eventDescriptor.BrowserRendererId); - return renderer.DispatchEventAsync(eventDescriptor.EventHandlerId, eventArgs); + // Be sure we only run one event handler at once. Although they couldn't run + // simultaneously anyway (there's only one thread), they could run nested on + // the stack if somehow one event handler triggers another event synchronously. + // We need event handlers not to overlap because (a) that's consistent with + // server-side Blazor which uses a sync context, and (b) the rendering logic + // relies completely on the idea that within a given scope it's only building + // or processing one batch at a time. + // + // The only currently known case where this makes a difference is in the E2E + // tests in ReorderingFocusComponent, where we hit what seems like a Chrome bug + // where mutating the DOM cause an element's "change" to fire while its "input" + // handler is still running (i.e., nested on the stack) -- this doesn't happen + // in Firefox. Possibly a future version of Chrome may fix this, but even then, + // it's conceivable that DOM mutation events could trigger this too. + + if (isDispatchingEvent) + { + var info = new IncomingEventInfo(eventDescriptor, eventArgsJson); + deferredIncomingEvents.Enqueue(info); + return info.TaskCompletionSource.Task; + } + else + { + isDispatchingEvent = true; + try + { + var eventArgs = ParseEventArgsJson(eventDescriptor.EventArgsType, eventArgsJson); + var renderer = RendererRegistry.Current.Find(eventDescriptor.BrowserRendererId); + return renderer.DispatchEventAsync(eventDescriptor.EventHandlerId, eventArgs); + } + finally + { + isDispatchingEvent = false; + if (deferredIncomingEvents.Count > 0) + { + ProcessNextDeferredEvent(); + } + } + } + } + + private static void ProcessNextDeferredEvent() + { + var info = deferredIncomingEvents.Dequeue(); + var task = DispatchEvent(info.EventDescriptor, info.EventArgsJson); + task.ContinueWith(_ => + { + if (task.Exception != null) + { + info.TaskCompletionSource.SetException(task.Exception); + } + else + { + info.TaskCompletionSource.SetResult(null); + } + }); } private static UIEventArgs ParseEventArgsJson(string eventArgsType, string eventArgsJson) @@ -78,5 +136,19 @@ namespace Microsoft.AspNetCore.Components.Browser /// public string EventArgsType { get; set; } } + + readonly struct IncomingEventInfo + { + public readonly BrowserEventDescriptor EventDescriptor; + public readonly string EventArgsJson; + public readonly TaskCompletionSource TaskCompletionSource; + + public IncomingEventInfo(BrowserEventDescriptor eventDescriptor, string eventArgsJson) + { + EventDescriptor = eventDescriptor; + EventArgsJson = eventArgsJson; + TaskCompletionSource = new TaskCompletionSource(); + } + } } } diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs index 37431bbb56..95c356e520 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs @@ -771,12 +771,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree public readonly int ComponentId; public readonly System.ArraySegment Edits; } - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)] public readonly partial struct RenderTreeEdit { + [System.Runtime.InteropServices.FieldOffsetAttribute(8)] + public readonly int MoveToSiblingIndex; + [System.Runtime.InteropServices.FieldOffsetAttribute(8)] public readonly int ReferenceFrameIndex; + [System.Runtime.InteropServices.FieldOffsetAttribute(16)] public readonly string RemovedAttributeName; + [System.Runtime.InteropServices.FieldOffsetAttribute(4)] public readonly int SiblingIndex; + [System.Runtime.InteropServices.FieldOffsetAttribute(0)] public readonly Microsoft.AspNetCore.Components.RenderTree.RenderTreeEditType Type; } public enum RenderTreeEditType @@ -789,6 +795,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree StepIn = 6, StepOut = 7, UpdateMarkup = 8, + PermutationListEntry = 9, + PermutationListEnd = 10, } public enum RenderTreeFrameType { diff --git a/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs index 24f07042c4..78a174885b 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeBuilder.cs @@ -454,13 +454,30 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// The value for the key. public void SetKey(object value) { - // This is just a placeholder to enable work in parallel in the - // aspnetcore-tooling repo. - // - // The real implementation will involve multiple overloads, likely: - // SetKey(int value) -- underlying logic - // SetKey(T value) where T: struct -- avoids boxing 'value' before calling .GetHashCode() - // SetKey(object value) -- performs null check before calling .GetHashCode() + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + var parentFrameIndex = GetCurrentParentFrameIndex(); + if (!parentFrameIndex.HasValue) + { + throw new InvalidOperationException("Cannot set a key outside the scope of a component or element."); + } + + var parentFrameIndexValue = parentFrameIndex.Value; + ref var parentFrame = ref _entries.Buffer[parentFrameIndexValue]; + switch (parentFrame.FrameType) + { + case RenderTreeFrameType.Element: + parentFrame = parentFrame.WithElementKey(value); // It's a ref var, so this writes to the array + break; + case RenderTreeFrameType.Component: + parentFrame = parentFrame.WithComponentKey(value); // It's a ref var, so this writes to the array + break; + default: + throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}."); + } } private void OpenComponentUnchecked(int sequence, Type componentType) diff --git a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs index 6a0514462d..baaf6097de 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs @@ -3,13 +3,14 @@ using System; using System.Collections.Generic; -using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components.RenderTree { internal static class RenderTreeDiffBuilder { + enum DiffAction { Match, Insert, Delete } + public static RenderTreeDiff ComputeDiff( Renderer renderer, RenderBatchBuilder batchBuilder, @@ -35,107 +36,302 @@ namespace Microsoft.AspNetCore.Components.RenderTree int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) { + // This is deliberately a very large method. Parts of it could be factored out + // into other private methods, but doing so comes at a consequential perf cost, + // because it involves so much parameter passing. You can think of the code here + // as being several private methods (delimited by #region) pre-inlined. + // + // A naive "extract methods"-type refactoring will worsen perf by about 10%. So, + // if you plan to refactor this, be sure to benchmark the old and new versions + // on Mono WebAssembly. + var hasMoreOld = oldEndIndexExcl > oldStartIndex; var hasMoreNew = newEndIndexExcl > newStartIndex; var prevOldSeq = -1; var prevNewSeq = -1; var oldTree = diffContext.OldTree; var newTree = diffContext.NewTree; - while (hasMoreOld || hasMoreNew) + var matchWithNewTreeIndex = -1; // Only used when action == DiffAction.Match + Dictionary keyedItemInfos = null; + + try { - var oldSeq = hasMoreOld ? oldTree[oldStartIndex].Sequence : int.MaxValue; - var newSeq = hasMoreNew ? newTree[newStartIndex].Sequence : int.MaxValue; - - if (oldSeq == newSeq) + while (hasMoreOld || hasMoreNew) { - AppendDiffEntriesForFramesWithSameSequence(ref diffContext, oldStartIndex, newStartIndex); - oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); - newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); - hasMoreOld = oldEndIndexExcl > oldStartIndex; - hasMoreNew = newEndIndexExcl > newStartIndex; - prevOldSeq = oldSeq; - prevNewSeq = newSeq; - } - else - { - bool treatAsInsert; - var oldLoopedBack = oldSeq <= prevOldSeq; - var newLoopedBack = newSeq <= prevNewSeq; - if (oldLoopedBack == newLoopedBack) - { - // Both sequences are proceeding through the same loop block, so do a simple - // preordered merge join (picking from whichever side brings us closer to being - // back in sync) - treatAsInsert = newSeq < oldSeq; + DiffAction action; - if (oldLoopedBack) - { - // If both old and new have now looped back, we must reset their 'looped back' - // tracker so we can treat them as proceeding through the same loop block - prevOldSeq = prevNewSeq = -1; - } - } - else if (oldLoopedBack) + #region "Read keys and sequence numbers" + int oldSeq, newSeq; + object oldKey, newKey; + if (hasMoreOld) { - // Old sequence looped back but new one didn't - // The new sequence either has some extra trailing elements in the current loop block - // which we should insert, or omits some old trailing loop blocks which we should delete - // TODO: Find a way of not recomputing this next flag on every iteration - var newLoopsBackLater = false; - for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++) - { - if (newTree[testIndex].Sequence < newSeq) - { - newLoopsBackLater = true; - break; - } - } - - // If the new sequence loops back later to an earlier point than this, - // then we know it's part of the existing loop block (so should be inserted). - // If not, then it's unrelated to the previous loop block (so we should treat - // the old items as trailing loop blocks to be removed). - treatAsInsert = newLoopsBackLater; + ref var oldFrame = ref oldTree[oldStartIndex]; + oldSeq = oldFrame.Sequence; + oldKey = KeyValue(ref oldFrame); } else { - // New sequence looped back but old one didn't - // The old sequence either has some extra trailing elements in the current loop block - // which we should delete, or the new sequence has extra trailing loop blocks which we - // should insert - // TODO: Find a way of not recomputing this next flag on every iteration - var oldLoopsBackLater = false; - for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++) - { - if (oldTree[testIndex].Sequence < oldSeq) - { - oldLoopsBackLater = true; - break; - } - } - - // If the old sequence loops back later to an earlier point than this, - // then we know it's part of the existing loop block (so should be removed). - // If not, then it's unrelated to the previous loop block (so we should treat - // the new items as trailing loop blocks to be inserted). - treatAsInsert = !oldLoopsBackLater; + oldSeq = int.MaxValue; + oldKey = null; } - if (treatAsInsert) + if (hasMoreNew) { - InsertNewFrame(ref diffContext, newStartIndex); - newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); - hasMoreNew = newEndIndexExcl > newStartIndex; - prevNewSeq = newSeq; + ref var newFrame = ref newTree[newStartIndex]; + newSeq = newFrame.Sequence; + newKey = KeyValue(ref newFrame); } else { - RemoveOldFrame(ref diffContext, oldStartIndex); - oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); - hasMoreOld = oldEndIndexExcl > oldStartIndex; - prevOldSeq = oldSeq; + newSeq = int.MaxValue; + newKey = null; + } + #endregion + + // If there's a key on either side, prefer matching by key not sequence + if (oldKey != null || newKey != null) + { + #region "Get diff action by matching on key" + if (Equals(oldKey, newKey)) + { + // Keys match + action = DiffAction.Match; + matchWithNewTreeIndex = newStartIndex; + } + else + { + // Keys don't match + if (keyedItemInfos == null) + { + keyedItemInfos = BuildKeyToInfoLookup(diffContext, oldStartIndex, oldEndIndexExcl, newStartIndex, newEndIndexExcl); + } + + var oldKeyItemInfo = oldKey != null ? keyedItemInfos[oldKey] : new KeyedItemInfo(-1, -1, false); + var newKeyItemInfo = newKey != null ? keyedItemInfos[newKey] : new KeyedItemInfo(-1, -1, false); + var oldKeyIsInNewTree = oldKeyItemInfo.NewIndex >= 0 && oldKeyItemInfo.IsUnique; + var newKeyIsInOldTree = newKeyItemInfo.OldIndex >= 0 && newKeyItemInfo.IsUnique; + + // If either key is not in the other tree, we can handle it as an insert or a delete + // on this iteration. We're only forced to use the move logic that's not the case + // (i.e., both keys are in both trees) + if (oldKeyIsInNewTree && newKeyIsInOldTree) + { + // It's a move + // Since the recipient of the diff script already has the old frame (the one with oldKey) + // at the current siblingIndex, recurse into oldKey and update its descendants in place. + // We re-order the frames afterwards. + action = DiffAction.Match; + matchWithNewTreeIndex = oldKeyItemInfo.NewIndex; + + // Track the post-edit sibling indices of the moved items + // Since diffContext.SiblingIndex only increases, we can be sure the values we + // write at this point will remain correct, because there won't be any further + // insertions/deletions at smaller sibling indices. + keyedItemInfos[oldKey] = oldKeyItemInfo.WithOldSiblingIndex(diffContext.SiblingIndex); + keyedItemInfos[newKey] = newKeyItemInfo.WithNewSiblingIndex(diffContext.SiblingIndex); + } + else if (!hasMoreNew) + { + // If we've run out of new items, we must be looking at just an old item, so delete it + action = DiffAction.Delete; + } + else + { + // It's an insertion or a deletion, or both + // If the new key is in both trees, but the old key isn't, then the old item was deleted + // Otherwise, it's either an insertion or *both* insertion+deletion, so pick insertion and get the deletion on the next iteration if needed + action = newKeyIsInOldTree ? DiffAction.Delete : DiffAction.Insert; + } + } + #endregion + } + else + { + #region "Get diff action by matching on sequence number" + // Neither side is keyed, so match by sequence number + if (oldSeq == newSeq) + { + // Sequences match + action = DiffAction.Match; + matchWithNewTreeIndex = newStartIndex; + } + else + { + // Sequences don't match + var oldLoopedBack = oldSeq <= prevOldSeq; + var newLoopedBack = newSeq <= prevNewSeq; + if (oldLoopedBack == newLoopedBack) + { + // Both sequences are proceeding through the same loop block, so do a simple + // preordered merge join (picking from whichever side brings us closer to being + // back in sync) + action = newSeq < oldSeq ? DiffAction.Insert : DiffAction.Delete; + + if (oldLoopedBack) + { + // If both old and new have now looped back, we must reset their 'looped back' + // tracker so we can treat them as proceeding through the same loop block + prevOldSeq = -1; + prevNewSeq = -1; + } + } + else if (oldLoopedBack) + { + // Old sequence looped back but new one didn't + // The new sequence either has some extra trailing elements in the current loop block + // which we should insert, or omits some old trailing loop blocks which we should delete + // TODO: Find a way of not recomputing this next flag on every iteration + var newLoopsBackLater = false; + for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++) + { + if (newTree[testIndex].Sequence < newSeq) + { + newLoopsBackLater = true; + break; + } + } + + // If the new sequence loops back later to an earlier point than this, + // then we know it's part of the existing loop block (so should be inserted). + // If not, then it's unrelated to the previous loop block (so we should treat + // the old items as trailing loop blocks to be removed). + action = newLoopsBackLater ? DiffAction.Insert : DiffAction.Delete; + } + else + { + // New sequence looped back but old one didn't + // The old sequence either has some extra trailing elements in the current loop block + // which we should delete, or the new sequence has extra trailing loop blocks which we + // should insert + // TODO: Find a way of not recomputing this next flag on every iteration + var oldLoopsBackLater = false; + for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++) + { + if (oldTree[testIndex].Sequence < oldSeq) + { + oldLoopsBackLater = true; + break; + } + } + + // If the old sequence loops back later to an earlier point than this, + // then we know it's part of the existing loop block (so should be removed). + // If not, then it's unrelated to the previous loop block (so we should treat + // the new items as trailing loop blocks to be inserted). + action = oldLoopsBackLater ? DiffAction.Delete : DiffAction.Insert; + } + } + #endregion + } + + #region "Apply diff action" + switch (action) + { + case DiffAction.Match: + AppendDiffEntriesForFramesWithSameSequence(ref diffContext, oldStartIndex, matchWithNewTreeIndex); + oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); + newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); + hasMoreOld = oldEndIndexExcl > oldStartIndex; + hasMoreNew = newEndIndexExcl > newStartIndex; + prevOldSeq = oldSeq; + prevNewSeq = newSeq; + break; + case DiffAction.Insert: + InsertNewFrame(ref diffContext, newStartIndex); + newStartIndex = NextSiblingIndex(newTree[newStartIndex], newStartIndex); + hasMoreNew = newEndIndexExcl > newStartIndex; + prevNewSeq = newSeq; + break; + case DiffAction.Delete: + RemoveOldFrame(ref diffContext, oldStartIndex); + oldStartIndex = NextSiblingIndex(oldTree[oldStartIndex], oldStartIndex); + hasMoreOld = oldEndIndexExcl > oldStartIndex; + prevOldSeq = oldSeq; + break; + } + #endregion + } + + #region "Write permutations list" + if (keyedItemInfos != null) + { + var hasPermutations = false; + foreach (var keyValuePair in keyedItemInfos) + { + var value = keyValuePair.Value; + if (value.OldSiblingIndex >= 0 && value.NewSiblingIndex >= 0) + { + // This item moved + hasPermutations = true; + diffContext.Edits.Append( + RenderTreeEdit.PermutationListEntry(value.OldSiblingIndex, value.NewSiblingIndex)); + } + } + + if (hasPermutations) + { + // It's much easier for the recipient to handle if we're explicit about + // when the list is finished + diffContext.Edits.Append(RenderTreeEdit.PermutationListEnd()); } } + #endregion + } + finally + { + if (keyedItemInfos != null) + { + keyedItemInfos.Clear(); + diffContext.KeyedItemInfoDictionaryPool.Return(keyedItemInfos); + } + } + } + + private static Dictionary BuildKeyToInfoLookup(DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl) + { + var result = diffContext.KeyedItemInfoDictionaryPool.Get(); + var oldTree = diffContext.OldTree; + var newTree = diffContext.NewTree; + + while (oldStartIndex < oldEndIndexExcl) + { + ref var frame = ref oldTree[oldStartIndex]; + var key = KeyValue(ref frame); + if (key != null) + { + result[key] = new KeyedItemInfo(oldStartIndex, -1, isUnique: !result.ContainsKey(key)); + } + + oldStartIndex = NextSiblingIndex(frame, oldStartIndex); + } + + while (newStartIndex < newEndIndexExcl) + { + ref var frame = ref newTree[newStartIndex]; + var key = KeyValue(ref frame); + if (key != null) + { + result[key] = result.TryGetValue(key, out var existingEntry) + ? new KeyedItemInfo(existingEntry.OldIndex, newStartIndex, isUnique: existingEntry.NewIndex < 0) + : new KeyedItemInfo(-1, newStartIndex, isUnique: true); + } + + newStartIndex = NextSiblingIndex(frame, newStartIndex); + } + + return result; + } + + private static object KeyValue(ref RenderTreeFrame frame) + { + switch (frame.FrameType) + { + case RenderTreeFrameType.Element: + return frame.ElementKey; + case RenderTreeFrameType.Component: + return frame.ComponentKey; + default: + return null; } } @@ -315,11 +511,21 @@ namespace Microsoft.AspNetCore.Components.RenderTree ref var oldFrame = ref oldTree[oldFrameIndex]; ref var newFrame = ref newTree[newFrameIndex]; + // This can't happen for sequence-matched frames from .razor components, but it can happen if you write your + // builder logic manually or if two dissimilar frames matched by key. Treat as completely unrelated. + var newFrameType = newFrame.FrameType; + if (oldFrame.FrameType != newFrameType) + { + InsertNewFrame(ref diffContext, newFrameIndex); + RemoveOldFrame(ref diffContext, oldFrameIndex); + return; + } + // 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). // TODO: Consider supporting dissimilar types at same sequence for custom IComponent implementations. // It should only be a matter of calling RemoveOldFrame+InsertNewFrame - switch (newFrame.FrameType) + switch (newFrameType) { case RenderTreeFrameType.Text: { @@ -718,6 +924,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree public readonly ArrayBuilder Edits; public readonly ArrayBuilder ReferenceFrames; public readonly Dictionary AttributeDiffSet; + public readonly StackObjectPool> KeyedItemInfoDictionaryPool; public readonly int ComponentId; public int SiblingIndex; @@ -736,6 +943,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree Edits = batchBuilder.EditsBuffer; ReferenceFrames = batchBuilder.ReferenceFramesBuffer; AttributeDiffSet = batchBuilder.AttributeDiffSet; + KeyedItemInfoDictionaryPool = batchBuilder.KeyedItemInfoDictionaryPool; SiblingIndex = 0; } } diff --git a/src/Components/Components/src/RenderTree/RenderTreeEdit.cs b/src/Components/Components/src/RenderTree/RenderTreeEdit.cs index d7c0daa7b1..96f661924b 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeEdit.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeEdit.cs @@ -1,37 +1,47 @@ // 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 System.Runtime.InteropServices; namespace Microsoft.AspNetCore.Components.RenderTree { /// /// Represents a single edit operation on a component's render tree. /// + [StructLayout(LayoutKind.Explicit)] public readonly struct RenderTreeEdit { /// /// Gets the type of the edit operation. /// - public readonly RenderTreeEditType Type; + [FieldOffset(0)] public readonly RenderTreeEditType Type; /// /// Gets the index of the sibling frame that the edit relates to. /// - public readonly int SiblingIndex; + [FieldOffset(4)] public readonly int SiblingIndex; /// /// Gets the index of related data in an associated render frames array. For example, if the /// value is , gets the /// index of the new frame data in an associated render tree. /// - public readonly int ReferenceFrameIndex; + [FieldOffset(8)] public readonly int ReferenceFrameIndex; + + /// + /// If the value is , + /// gets the sibling index to which the frame should be moved. + /// + // NOTE: Other code relies on the assumption that ReferenceFrameIndex and + // MoveToSiblingIndex share a memory slot. If you change this, be sure to + // update affected usages of ReferenceFrameIndex. + [FieldOffset(8)] public readonly int MoveToSiblingIndex; /// /// If the value is , /// gets the name of the attribute that is being removed. /// - public readonly string RemovedAttributeName; + [FieldOffset(16)] public readonly string RemovedAttributeName; private RenderTreeEdit(RenderTreeEditType type) : this() { @@ -44,11 +54,14 @@ namespace Microsoft.AspNetCore.Components.RenderTree SiblingIndex = siblingIndex; } - private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, int referenceFrameIndex) : this() + private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, int referenceFrameOrMoveToSiblingIndex) : this() { Type = type; SiblingIndex = siblingIndex; - ReferenceFrameIndex = referenceFrameIndex; + + // MoveToSiblingIndex is stored in the same slot as ReferenceFrameIndex, + // so assigning to either one is equivalent + ReferenceFrameIndex = referenceFrameOrMoveToSiblingIndex; } private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, string removedAttributeName) : this() @@ -81,5 +94,11 @@ namespace Microsoft.AspNetCore.Components.RenderTree internal static RenderTreeEdit StepOut() => new RenderTreeEdit(RenderTreeEditType.StepOut); + + internal static RenderTreeEdit PermutationListEntry(int fromSiblingIndex, int toSiblingIndex) + => new RenderTreeEdit(RenderTreeEditType.PermutationListEntry, fromSiblingIndex, toSiblingIndex); + + internal static RenderTreeEdit PermutationListEnd() + => new RenderTreeEdit(RenderTreeEditType.PermutationListEnd); } } diff --git a/src/Components/Components/src/RenderTree/RenderTreeEditType.cs b/src/Components/Components/src/RenderTree/RenderTreeEditType.cs index aa7ca3a604..c2f3e4aba6 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeEditType.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeEditType.cs @@ -51,5 +51,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// should be updated. /// UpdateMarkup = 8, + + /// + /// An entry in a sparse permutation list. That is, a list of old indices with + /// corresponding new indices, which altogether describe a valid permutation of + /// the children at the current edit position. + /// + PermutationListEntry = 9, + + /// + /// Indicates that the preceding series of entries + /// is now complete. + /// + PermutationListEnd = 10, } } diff --git a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs b/src/Components/Components/src/RenderTree/RenderTreeFrame.cs index 920d0752bb..7bf18c150d 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeFrame.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeFrame.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.InteropServices; -using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components.RenderTree @@ -17,13 +16,22 @@ namespace Microsoft.AspNetCore.Components.RenderTree // Note that the struct layout has to be valid in both 32-bit and 64-bit runtime platforms, // which means that all reference-type fields need to take up 8 bytes (except for the last // one, which will be sized as either 4 or 8 bytes depending on the runtime platform). - // This is not optimal for the Mono-WebAssembly case because that's always 32-bit so the - // reference-type fields could be reduced to 4 bytes each. We could use ifdefs to have - // different fields offsets for the 32 and 64 bit compile targets, but then we'd have the - // complexity of needing different binaries when loaded into Mono-WASM vs desktop. - // Eventually we might stop using this shared memory interop altogether (and would have to - // if running as a web worker) so for now to keep things simple, treat reference types as - // 8 bytes here. + + // Although each frame type uses the slots for different purposes, the runtime does not + // allow reference type slots to overlap with each other or with value-type slots. + // Here's the current layout: + // + // Offset Type + // ------ ---- + // 0-3 Int32 (sequence number) + // 4-7 Int32 (frame type) + // 8-15 Value types (usage varies by frame type) + // 16-23 Reference type (usage varies by frame type) + // 24-31 Reference type (usage varies by frame type) + // 32-39 Reference type (usage varies by frame type) + // + // On Mono WebAssembly, because it's 32-bit, the final slot occupies bytes 32-35, + // so the struct length is only 36. // -------------------------------------------------------------------------------- // Common @@ -58,6 +66,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// [FieldOffset(16)] public readonly string ElementName; + /// + /// If the property equals , + /// gets the element's diffing key, or null if none was specified. + /// + [FieldOffset(24)] public readonly object ElementKey; + // -------------------------------------------------------------------------------- // RenderTreeFrameType.Text // -------------------------------------------------------------------------------- @@ -119,6 +133,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// [FieldOffset(24)] internal readonly ComponentState ComponentState; + /// + /// If the property equals , + /// gets the component's diffing key, or null if none was specified. + /// + [FieldOffset(32)] public readonly object ComponentKey; + /// /// If the property equals , /// gets the child component instance. Otherwise, the value is undefined. @@ -184,66 +204,72 @@ namespace Microsoft.AspNetCore.Components.RenderTree /// [FieldOffset(16)] public readonly string MarkupContent; - private RenderTreeFrame(int sequence, string elementName, int elementSubtreeLength) + // Element constructor + private RenderTreeFrame(int sequence, int elementSubtreeLength, string elementName, object elementKey) : this() { + Sequence = sequence; FrameType = RenderTreeFrameType.Element; - Sequence = sequence; - ElementName = elementName; ElementSubtreeLength = elementSubtreeLength; + ElementName = elementName; + ElementKey = elementKey; } - private RenderTreeFrame(int sequence, Type componentType, int componentSubtreeLength) + // Component constructor + private RenderTreeFrame(int sequence, int componentSubtreeLength, Type componentType, ComponentState componentState, object componentKey) : this() { + Sequence = sequence; FrameType = RenderTreeFrameType.Component; - Sequence = sequence; - ComponentType = componentType; ComponentSubtreeLength = componentSubtreeLength; + ComponentType = componentType; + ComponentKey = componentKey; + + if (componentState != null) + { + ComponentState = componentState; + ComponentId = componentState.ComponentId; + } } - private RenderTreeFrame(int sequence, Type componentType, int subtreeLength, ComponentState componentState) - : this(sequence, componentType, subtreeLength) - { - ComponentId = componentState.ComponentId; - ComponentState = componentState; - } - - private RenderTreeFrame(int sequence, string textContent) - : this() - { - FrameType = RenderTreeFrameType.Text; - Sequence = sequence; - TextContent = textContent; - } - - private RenderTreeFrame(int sequence, string attributeName, object attributeValue) - : this() - { - FrameType = RenderTreeFrameType.Attribute; - Sequence = sequence; - AttributeName = attributeName; - AttributeValue = attributeValue; - } - - private RenderTreeFrame(int sequence, string attributeName, object attributeValue, int eventHandlerId) - : this() - { - FrameType = RenderTreeFrameType.Attribute; - Sequence = sequence; - AttributeName = attributeName; - AttributeValue = attributeValue; - AttributeEventHandlerId = eventHandlerId; - } - + // Region constructor private RenderTreeFrame(int sequence, int regionSubtreeLength) : this() { - FrameType = RenderTreeFrameType.Region; Sequence = sequence; + FrameType = RenderTreeFrameType.Region; RegionSubtreeLength = regionSubtreeLength; } + // Text/markup constructor + private RenderTreeFrame(int sequence, bool isMarkup, string textOrMarkup) + : this() + { + Sequence = sequence; + if (isMarkup) + { + FrameType = RenderTreeFrameType.Markup; + MarkupContent = textOrMarkup; + } + else + { + FrameType = RenderTreeFrameType.Text; + TextContent = textOrMarkup; + } + } + + // Attribute constructor + private RenderTreeFrame(int sequence, string attributeName, object attributeValue, int attributeEventHandlerId) + : this() + { + FrameType = RenderTreeFrameType.Attribute; + Sequence = sequence; + AttributeName = attributeName; + AttributeValue = attributeValue; + AttributeEventHandlerId = attributeEventHandlerId; + } + + // Element reference capture constructor private RenderTreeFrame(int sequence, Action elementReferenceCaptureAction, string elementReferenceCaptureId) : this() { @@ -253,6 +279,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree ElementReferenceCaptureId = elementReferenceCaptureId; } + // Component reference capture constructor private RenderTreeFrame(int sequence, Action componentReferenceCaptureAction, int parentFrameIndex) : this() { @@ -262,36 +289,23 @@ namespace Microsoft.AspNetCore.Components.RenderTree ComponentReferenceCaptureParentFrameIndex = parentFrameIndex; } - // If we need further constructors whose signatures clash with the patterns above, - // we can add extra args to this general-purpose one. - private RenderTreeFrame(int sequence, RenderTreeFrameType frameType, string markupContent) - : this() - { - FrameType = frameType; - Sequence = sequence; - MarkupContent = markupContent; - } - internal static RenderTreeFrame Element(int sequence, string elementName) - => new RenderTreeFrame(sequence, elementName: elementName, elementSubtreeLength: 0); + => new RenderTreeFrame(sequence, elementSubtreeLength: 0, elementName, null); internal static RenderTreeFrame Text(int sequence, string textContent) - => new RenderTreeFrame(sequence, textContent: textContent); + => new RenderTreeFrame(sequence, isMarkup: false, textOrMarkup: textContent); internal static RenderTreeFrame Markup(int sequence, string markupContent) - => new RenderTreeFrame(sequence, RenderTreeFrameType.Markup, markupContent); - - internal static RenderTreeFrame Attribute(int sequence, string name, MulticastDelegate value) - => new RenderTreeFrame(sequence, attributeName: name, attributeValue: value); + => new RenderTreeFrame(sequence, isMarkup: true, textOrMarkup: markupContent); internal static RenderTreeFrame Attribute(int sequence, string name, object value) - => new RenderTreeFrame(sequence, attributeName: name, attributeValue: value); + => new RenderTreeFrame(sequence, attributeName: name, attributeValue: value, attributeEventHandlerId: 0); internal static RenderTreeFrame ChildComponent(int sequence, Type componentType) - => new RenderTreeFrame(sequence, componentType, 0); + => new RenderTreeFrame(sequence, componentSubtreeLength: 0, componentType, null, null); internal static RenderTreeFrame PlaceholderChildComponentWithSubtreeLength(int subtreeLength) - => new RenderTreeFrame(0, typeof(IComponent), subtreeLength); + => new RenderTreeFrame(0, componentSubtreeLength: subtreeLength, typeof(IComponent), null, null); internal static RenderTreeFrame Region(int sequence) => new RenderTreeFrame(sequence, regionSubtreeLength: 0); @@ -303,25 +317,31 @@ namespace Microsoft.AspNetCore.Components.RenderTree => new RenderTreeFrame(sequence, componentReferenceCaptureAction: componentReferenceCaptureAction, parentFrameIndex: parentFrameIndex); internal RenderTreeFrame WithElementSubtreeLength(int elementSubtreeLength) - => new RenderTreeFrame(Sequence, elementName: ElementName, elementSubtreeLength: elementSubtreeLength); + => new RenderTreeFrame(Sequence, elementSubtreeLength: elementSubtreeLength, ElementName, ElementKey); internal RenderTreeFrame WithComponentSubtreeLength(int componentSubtreeLength) - => new RenderTreeFrame(Sequence, componentType: ComponentType, componentSubtreeLength: componentSubtreeLength); + => new RenderTreeFrame(Sequence, componentSubtreeLength: componentSubtreeLength, ComponentType, ComponentState, ComponentKey); internal RenderTreeFrame WithAttributeSequence(int sequence) - => new RenderTreeFrame(sequence, attributeName: AttributeName, attributeValue: AttributeValue); + => new RenderTreeFrame(sequence, attributeName: AttributeName, AttributeValue, AttributeEventHandlerId); internal RenderTreeFrame WithComponent(ComponentState componentState) - => new RenderTreeFrame(Sequence, ComponentType, ComponentSubtreeLength, componentState); + => new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, componentState, ComponentKey); internal RenderTreeFrame WithAttributeEventHandlerId(int eventHandlerId) - => new RenderTreeFrame(Sequence, AttributeName, AttributeValue, eventHandlerId); + => new RenderTreeFrame(Sequence, attributeName: AttributeName, AttributeValue, eventHandlerId); internal RenderTreeFrame WithRegionSubtreeLength(int regionSubtreeLength) => new RenderTreeFrame(Sequence, regionSubtreeLength: regionSubtreeLength); internal RenderTreeFrame WithElementReferenceCaptureId(string elementReferenceCaptureId) - => new RenderTreeFrame(Sequence, ElementReferenceCaptureAction, elementReferenceCaptureId); + => new RenderTreeFrame(Sequence, elementReferenceCaptureAction: ElementReferenceCaptureAction, elementReferenceCaptureId); + + internal RenderTreeFrame WithElementKey(object elementKey) + => new RenderTreeFrame(Sequence, elementSubtreeLength: ElementSubtreeLength, ElementName, elementKey); + + internal RenderTreeFrame WithComponentKey(object componentKey) + => new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, ComponentState, componentKey); /// // Just to be nice for debugging and unit tests. @@ -333,10 +353,10 @@ namespace Microsoft.AspNetCore.Components.RenderTree return $"Attribute: (seq={Sequence}, id={AttributeEventHandlerId}) '{AttributeName}'='{AttributeValue}'"; case RenderTreeFrameType.Component: - return $"Component: (seq={Sequence}, len={ComponentSubtreeLength}) {ComponentType}"; + return $"Component: (seq={Sequence}, key={ComponentKey ?? "(none)"}, len={ComponentSubtreeLength}) {ComponentType}"; case RenderTreeFrameType.Element: - return $"Element: (seq={Sequence}, len={ElementSubtreeLength}) {ElementName}"; + return $"Element: (seq={Sequence}, key={ElementKey ?? "(none)"}, len={ElementSubtreeLength}) {ElementName}"; case RenderTreeFrameType.Region: return $"Region: (seq={Sequence}, len={RegionSubtreeLength})"; diff --git a/src/Components/Components/src/RenderTree/StackObjectPool.cs b/src/Components/Components/src/RenderTree/StackObjectPool.cs new file mode 100644 index 0000000000..a2c9c1f524 --- /dev/null +++ b/src/Components/Components/src/RenderTree/StackObjectPool.cs @@ -0,0 +1,75 @@ +// 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; + +namespace Microsoft.AspNetCore.Components.RenderTree +{ + // This is a very simple object pool that requires Get and Return calls to be + // balanced as in a stack. It retains up to 'maxPreservedItems' instances in + // memory, then for any further requests it supplies untracked instances. + + internal class StackObjectPool where T : class + { + private readonly int _maxPreservedItems; + private readonly Func _instanceFactory; + private readonly T[] _contents; + private int _numSuppliedItems; + private int _numTrackedItems; + + public StackObjectPool(int maxPreservedItems, Func instanceFactory) + { + _maxPreservedItems = maxPreservedItems; + _instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory)); + _contents = new T[_maxPreservedItems]; + } + + public T Get() + { + _numSuppliedItems++; + + if (_numSuppliedItems <= _maxPreservedItems) + { + if (_numTrackedItems < _numSuppliedItems) + { + // Need to allocate a new one + var newItem = _instanceFactory(); + _contents[_numTrackedItems++] = newItem; + return newItem; + } + else + { + // Can use one that's already in the pool + return _contents[_numSuppliedItems - 1]; + } + } + else + { + // Pool is full; return untracked instance + return _instanceFactory(); + } + } + + public void Return(T instance) + { + if (_numSuppliedItems <= 0) + { + throw new InvalidOperationException("There are no outstanding instances to return."); + } + else if (_numSuppliedItems <= _maxPreservedItems) + { + // We check you're returning the right instance only as a way of + // catching Get/Return mismatch bugs + var expectedInstance = _contents[_numSuppliedItems - 1]; + if (!ReferenceEquals(instance, expectedInstance)) + { + throw new ArgumentException($"Attempting to return wrong pooled instance. {nameof(Get)}/{nameof(Return)} calls must form a stack."); + } + } + + // It's a valid call. Track that we're no longer "supplying" the top item, + // but keep the instance in the _contents array for future reuse. + _numSuppliedItems--; + } + } +} diff --git a/src/Components/Components/src/Rendering/KeyedItemInfo.cs b/src/Components/Components/src/Rendering/KeyedItemInfo.cs new file mode 100644 index 0000000000..f2a56341e2 --- /dev/null +++ b/src/Components/Components/src/Rendering/KeyedItemInfo.cs @@ -0,0 +1,46 @@ +// 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. + +namespace Microsoft.AspNetCore.Components.Rendering +{ + // Used internally during diffing to track what we know about keyed items and their positions + internal readonly struct KeyedItemInfo + { + public readonly int OldIndex; + public readonly int NewIndex; + public readonly int OldSiblingIndex; + public readonly int NewSiblingIndex; + public readonly bool IsUnique; + + public KeyedItemInfo(int oldIndex, int newIndex, bool isUnique) + { + OldIndex = oldIndex; + NewIndex = newIndex; + OldSiblingIndex = -1; + NewSiblingIndex = -1; + + // Non-unique keys are problematic, because there's no way to know which instance + // should match with which other, plus they would force us to keep track of which + // usages have been consumed as we proceed through the diff. Since this is such + // an edge case, we "tolerate" it just by tracking which keys have duplicates, and + // for those ones, we never treat them as moved. Instead for those we fall back on + // insert+delete behavior, i.e., not preserving elements/components. + // + // Guidance for developers is therefore to use distinct keys. + IsUnique = isUnique; + } + + private KeyedItemInfo(in KeyedItemInfo copyFrom, int oldSiblingIndex, int newSiblingIndex) + { + this = copyFrom; + OldSiblingIndex = oldSiblingIndex; + NewSiblingIndex = newSiblingIndex; + } + + public KeyedItemInfo WithOldSiblingIndex(int oldSiblingIndex) + => new KeyedItemInfo(this, oldSiblingIndex, NewSiblingIndex); + + public KeyedItemInfo WithNewSiblingIndex(int newSiblingIndex) + => new KeyedItemInfo(this, OldSiblingIndex, newSiblingIndex); + } +} diff --git a/src/Components/Components/src/Rendering/RenderBatchBuilder.cs b/src/Components/Components/src/Rendering/RenderBatchBuilder.cs index 4bcdd82d0a..bb5daacec4 100644 --- a/src/Components/Components/src/Rendering/RenderBatchBuilder.cs +++ b/src/Components/Components/src/Rendering/RenderBatchBuilder.cs @@ -30,6 +30,9 @@ namespace Microsoft.AspNetCore.Components.Rendering // Scratch data structure for understanding attribute diffs. public Dictionary AttributeDiffSet { get; } = new Dictionary(); + internal StackObjectPool> KeyedItemInfoDictionaryPool { get; } + = new StackObjectPool>(maxPreservedItems: 10, () => new Dictionary()); + public void ClearStateForCurrentBatch() { // This method is used to reset the builder back to a default state so it can diff --git a/src/Components/Components/test/RenderTreeBuilderTest.cs b/src/Components/Components/test/RenderTreeBuilderTest.cs index 75a7616b1e..ac05e9b195 100644 --- a/src/Components/Components/test/RenderTreeBuilderTest.cs +++ b/src/Components/Components/test/RenderTreeBuilderTest.cs @@ -1047,6 +1047,107 @@ namespace Microsoft.AspNetCore.Components.Test frame => AssertFrame.Element(frame, "elem", 1, 0)); } + [Fact] + public void CanAddKeyToElement() + { + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + var keyValue = new object(); + + // Act + builder.OpenElement(0, "elem"); + builder.AddAttribute(1, "attribute before", "before value"); + builder.SetKey(keyValue); + builder.AddAttribute(2, "attribute after", "after value"); + builder.CloseElement(); + + // Assert + Assert.Collection( + builder.GetFrames().AsEnumerable(), + frame => + { + AssertFrame.Element(frame, "elem", 3, 0); + Assert.Same(keyValue, frame.ElementKey); + }, + frame => AssertFrame.Attribute(frame, "attribute before", "before value", 1), + frame => AssertFrame.Attribute(frame, "attribute after", "after value", 2)); + } + + [Fact] + public void CanAddKeyToComponent() + { + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + var keyValue = new object(); + + // Act + builder.OpenComponent(0); + builder.AddAttribute(1, "param before", 123); + builder.SetKey(keyValue); + builder.AddAttribute(2, "param after", 456); + builder.CloseComponent(); + + // Assert + Assert.Collection( + builder.GetFrames().AsEnumerable(), + frame => + { + AssertFrame.Component(frame, 3, 0); + Assert.Same(keyValue, frame.ComponentKey); + }, + frame => AssertFrame.Attribute(frame, "param before", 123, 1), + frame => AssertFrame.Attribute(frame, "param after", 456, 2)); + } + + [Fact] + public void CannotAddKeyOutsideComponentOrElement_TreeRoot() + { + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + + // Act/Assert + var ex = Assert.Throws(() => + { + builder.SetKey(new object()); + }); + Assert.Equal("Cannot set a key outside the scope of a component or element.", ex.Message); + } + + [Fact] + public void CannotAddKeyOutsideComponentOrElement_RegionRoot() + { + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + + // Act/Assert + builder.OpenElement(0, "some element"); + builder.OpenRegion(1); + var ex = Assert.Throws(() => + { + builder.SetKey(new object()); + }); + Assert.Equal($"Cannot set a key on a frame of type {RenderTreeFrameType.Region}.", ex.Message); + } + + [Fact] + public void CannotAddNullKey() + { + // Although we could translate 'null' into either some default "null key" + // instance, or just no-op the call, it almost certainly indicates a programming + // error so it's better to fail. + + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + + // Act/Assert + var ex = Assert.Throws(() => + { + builder.OpenElement(0, "elem"); + builder.SetKey(null); + }); + Assert.Equal("value", ex.ParamName); + } + private class TestComponent : IComponent { public void Configure(RenderHandle renderHandle) { } diff --git a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs b/src/Components/Components/test/RenderTreeDiffBuilderTest.cs index caafa7c7d5..b1dff64477 100644 --- a/src/Components/Components/test/RenderTreeDiffBuilderTest.cs +++ b/src/Components/Components/test/RenderTreeDiffBuilderTest.cs @@ -103,6 +103,417 @@ namespace Microsoft.AspNetCore.Components.Test entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); } + [Fact] + public void RecognizesKeyedElementInsertions() + { + // Arrange + oldTree.OpenElement(0, "container"); + oldTree.SetKey("retained key"); + oldTree.AddContent(1, "Existing"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "container"); + newTree.SetKey("new key"); + newTree.AddContent(1, "Inserted"); + newTree.CloseElement(); + + newTree.OpenElement(0, "container"); + newTree.SetKey("retained key"); + newTree.AddContent(1, "Existing"); + newTree.CloseElement(); + + // Without the key, it would change the text "Existing" to "Inserted", then insert a new "Existing" below it + // With the key, it just inserts a new "Inserted" at the top + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => + { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ElementKey); + }); + } + + [Fact] + public void RecognizesKeyedElementDeletions() + { + // Arrange + oldTree.OpenElement(0, "container"); + oldTree.SetKey("will delete"); + oldTree.AddContent(1, "First"); + oldTree.CloseElement(); + + oldTree.OpenElement(0, "container"); + oldTree.SetKey("will retain"); + oldTree.AddContent(1, "Second"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "container"); + newTree.SetKey("will retain"); + newTree.AddContent(1, "Second"); + newTree.CloseElement(); + + // Without the key, it changes the text content of "First" to "Second", then deletes the other "Second" + // With the key, it just deletes "First" + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0)); + } + + [Fact] + public void RecognizesSimultaneousKeyedElementInsertionsAndDeletions() + { + // Arrange + oldTree.OpenElement(0, "container"); + oldTree.SetKey("original key"); + oldTree.AddContent(1, "Original"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "container"); + newTree.SetKey("new key"); + newTree.AddContent(1, "Inserted"); + newTree.CloseElement(); + + // Without the key, it would change the text "Original" to "Inserted" + // With the key, it deletes the old element and inserts the new element + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => + { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ElementKey); + }, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); + } + + [Fact] + public void RecognizesKeyedComponentInsertions() + { + // Arrange + oldTree.OpenComponent(0); + oldTree.SetKey("retained key"); + oldTree.AddAttribute(1, "ParamName", "Param old value"); + oldTree.CloseComponent(); + GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree, false); // Assign initial IDs + var oldComponent = GetComponents(oldTree).Single(); + + newTree.OpenComponent(0); + newTree.SetKey("new key"); + newTree.AddAttribute(1, "ParamName", "New component param value"); + newTree.CloseComponent(); + + newTree.OpenComponent(0); + newTree.SetKey("retained key"); + newTree.AddAttribute(1, "ParamName", "Param new value"); + newTree.CloseComponent(); + + // Without the key, it would modify the param on the first component, + // then insert a new second component. + // With the key, it inserts a new first component, then modifies the + // param on the second component. + + // Act + var batch = GetRenderedBatch(initializeFromFrames: false); + var newComponents = GetComponents(newTree); + + // Assert: Inserts new component at position 0 + Assert.Equal(1, batch.UpdatedComponents.Count); + Assert.Collection(batch.UpdatedComponents.Array[0].Edits, + entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0)); + + // Assert: Retains old component instance in position 1, and updates its params + Assert.Same(oldComponent, newComponents[1]); + Assert.Equal(2, oldComponent.SetParametersCallCount); + } + + [Fact] + public void RecognizesKeyedComponentDeletions() + { + // Arrange + oldTree.OpenComponent(0); + oldTree.SetKey("will delete"); + oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Anything"); + oldTree.CloseComponent(); + + oldTree.OpenComponent(0); + oldTree.SetKey("will retain"); + oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Retained param value"); + oldTree.CloseComponent(); + + // Instantiate initial components + GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree, false); + var oldComponents = GetComponents(oldTree); + + newTree.OpenComponent(0); + newTree.SetKey("will retain"); + newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Retained param value"); + newTree.CloseComponent(); + + // Without the key, it updates the param on the first component, then + // deletes the second. + // With the key, it just deletes the first. + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + var newComponent = GetComponents(newTree).Single(); + + // Assert + Assert.Same(oldComponents[1], newComponent); + Assert.Collection(result.Edits, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 0)); + } + + [Fact] + public void RecognizesSimultaneousKeyedComponentInsertionsAndDeletions() + { + // Arrange + oldTree.OpenComponent(0); + oldTree.SetKey("original key"); + oldTree.CloseComponent(); + + // Instantiate initial component + GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree, false); + var oldComponent = GetComponents(oldTree).Single(); + Assert.NotNull(oldComponent); + + newTree.OpenComponent(0); + newTree.SetKey("new key"); + newTree.CloseComponent(); + + // Without the key, it would retain the component + // With the key, it deletes the old component and inserts the new component + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + var newComponent = GetComponents(newTree).Single(); + + // Assert + Assert.NotNull(newComponent); + Assert.NotSame(oldComponent, newComponent); + Assert.Collection(result.Edits, + entry => + { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("new key", referenceFrames[entry.ReferenceFrameIndex].ComponentKey); + }, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); + } + + [Fact] + public void HandlesClashingKeys_FirstUsage() + { + // This scenario is problematic for the algorithm if it uses a "first key + // usage wins" policy for duplicate keys. It would not end up with attrib1b + // anywhere in the output, because whenever it sees key1 in oldTree, it tries + // to diff against the first usage of key1 in newTree, which has attrib1a. + + // However, because of the actual "duplicated keys are excluded from the + // dictionary match" policy, we don't preserve any of the key1 items, and + // the diff is valid. + + // Arrange + AddWithKey(oldTree, "key3", "attrib3"); + AddWithKey(oldTree, "key1", "attrib1a"); + AddWithKey(oldTree, "key1", "attrib1a"); + AddWithKey(oldTree, "key2", "attrib2"); + + AddWithKey(newTree, "key1", "attrib1a"); + AddWithKey(newTree, "key2", "attrib2"); + AddWithKey(newTree, "key1", "attrib1b"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + // Insert key1+attrib1a at the top + edit => + { + AssertEdit(edit, RenderTreeEditType.PrependFrame, 0); + Assert.Equal("attrib1a", referenceFrames[edit.ReferenceFrameIndex + 1].AttributeValue); + }, + // Delete key3+attrib3 + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1), + // Delete key1+attrib1a + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1), + // Delete the other key1+attrib1a + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1), + // Insert key1+attrib1b at the bottom + edit => + { + AssertEdit(edit, RenderTreeEditType.PrependFrame, 2); + Assert.Equal("attrib1b", referenceFrames[edit.ReferenceFrameIndex + 1].AttributeValue); + }); + } + + [Fact] + public void HandlesClashingKeys_LastUsage() + { + // This scenario is problematic for the algorithm if it uses a "last key + // usage wins" policy for duplicate keys. It would not end up with attrib1b + // anywhere in the output, because when it sees key1 in oldTree, it tries + // to diff against the last usage of key1 in newTree, which has attrib1a. + + // However, because of the actual "duplicated keys are excluded from the + // dictionary match" policy, we don't preserve any of the key1 items, and + // the diff is valid. + + // Arrange + AddWithKey(oldTree, "key1", "attrib1a"); + AddWithKey(oldTree, "key2", "attrib2"); + AddWithKey(oldTree, "key1", "attrib1b"); + + AddWithKey(newTree, "key2", "attrib2"); + AddWithKey(newTree, "key1", "attrib1b"); + AddWithKey(newTree, "key1", "attrib1a"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + // Delete key1+attrib1a + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 0), + // Insert a new key1+attrib1a at the bottom + edit => + { + AssertEdit(edit, RenderTreeEditType.PrependFrame, 2); + Assert.Equal("attrib1a", referenceFrames[edit.ReferenceFrameIndex + 1].AttributeValue); + }); + } + + [Fact] + public void HandlesInsertionOfUnkeyedItemsAroundKey() + { + // The fact that the new sequence numbers are descending makes this + // problematic if it prefers matching by sequence over key. + // However, since the policy is to prefer key over sequence, it works OK. + + // Arrange + oldTree.OpenElement(1, "el"); + oldTree.SetKey("some key"); + oldTree.CloseElement(); + + newTree.OpenElement(2, "other"); + newTree.CloseElement(); + + newTree.OpenElement(1, "el"); + newTree.SetKey("some key"); + newTree.CloseElement(); + + newTree.OpenElement(0, "other 2"); + newTree.CloseElement(); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 0), + edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 2)); + } + + [Fact] + public void HandlesDeletionOfUnkeyedItemsAroundKey() + { + // The fact that the old sequence numbers are descending makes this + // problematic if it prefers matching by sequence over key. + // However, since the policy is to prefer key over sequence, it works OK. + + // Arrange + oldTree.OpenElement(2, "other"); + oldTree.CloseElement(); + + oldTree.OpenElement(1, "el"); + oldTree.SetKey("some key"); + oldTree.CloseElement(); + + oldTree.OpenElement(0, "other 2"); + oldTree.CloseElement(); + + newTree.OpenElement(1, "el"); + newTree.SetKey("some key"); + newTree.CloseElement(); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 0), + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); + } + + [Fact] + public void HandlesKeyBeingAdded() + { + // This is an anomolous situation that can't occur with .razor components. + // It represents the case where, for the same sequence number, we have an + // old frame without a key and a new frame with a key. + + // Arrange + oldTree.OpenElement(0, "el"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "el"); + newTree.SetKey("some key"); + newTree.CloseElement(); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + // Insert new + edit => + { + AssertEdit(edit, RenderTreeEditType.PrependFrame, 0); + Assert.Equal("some key", referenceFrames[edit.ReferenceFrameIndex].ElementKey); + }, + // Delete old + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); + } + + [Fact] + public void HandlesKeyBeingRemoved() + { + // This is an anomolous situation that can't occur with .razor components. + // It represents the case where, for the same sequence number, we have an + // old frame with a key and a new frame without a key. + + // Arrange + oldTree.OpenElement(0, "el"); + oldTree.SetKey("some key"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "el"); + newTree.CloseElement(); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + // Insert new + edit => AssertEdit(edit, RenderTreeEditType.PrependFrame, 0), + // Delete old + edit => AssertEdit(edit, RenderTreeEditType.RemoveFrame, 1)); + } + [Fact] public void RecognizesTrailingSequenceWithinLoopBlockBeingRemoved() { @@ -1492,6 +1903,254 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Empty(referenceFrames); } + [Fact] + public void RecognizesKeyedElementMoves() + { + // Arrange + oldTree.OpenElement(0, "container"); + oldTree.SetKey("first key"); + oldTree.AddContent(1, "First"); + oldTree.CloseElement(); + + oldTree.AddContent(2, "Unkeyed item"); + + oldTree.OpenElement(0, "container"); + oldTree.SetKey("second key"); + oldTree.AddContent(1, "Second"); + oldTree.CloseElement(); + + newTree.OpenElement(0, "container"); + newTree.SetKey("second key"); + newTree.AddContent(1, "Second"); + newTree.CloseElement(); + + newTree.AddContent(2, "Unkeyed item"); + + newTree.OpenElement(0, "container"); + newTree.SetKey("first key"); + newTree.AddContent(1, "First modified"); + newTree.CloseElement(); + + // Without the key, it changes the text contents of both + // With the key, it reorders them and just updates the text content of one + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + // First we update the modified descendants in place + entry => AssertEdit(entry, RenderTreeEditType.StepIn, 0), + entry => + { + AssertEdit(entry, RenderTreeEditType.UpdateText, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("First modified", referenceFrames[entry.ReferenceFrameIndex].TextContent); + }, + entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0), + + // Then we have the permutation list + entry => AssertPermutationListEntry(entry, 0, 2), + entry => AssertPermutationListEntry(entry, 2, 0), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void RecognizesKeyedComponentMoves() + { + // Arrange + oldTree.OpenComponent(0); + oldTree.SetKey("first key"); + oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "First param"); + oldTree.CloseComponent(); + + oldTree.AddContent(2, "Unkeyed item"); + + oldTree.OpenComponent(0); + oldTree.SetKey("second key"); + oldTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Second param"); + oldTree.CloseComponent(); + + GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree, false); // Assign initial IDs + var oldComponents = GetComponents(oldTree); + + newTree.OpenComponent(0); + newTree.SetKey("second key"); + newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "Second param"); + newTree.CloseComponent(); + + newTree.AddContent(2, "Unkeyed item"); + + newTree.OpenComponent(0); + newTree.SetKey("first key"); + newTree.AddAttribute(1, nameof(FakeComponent.StringProperty), "First param modified"); + newTree.CloseComponent(); + + // Without the key, it changes the parameter on both + // With the key, it reorders them and just updates the parameter of one + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + var newComponents = GetComponents(newTree); + + // Assert: Retains component instances + Assert.Same(oldComponents[0], newComponents[1]); + Assert.Same(oldComponents[1], newComponents[0]); + + // Assert: Supplies updated params only to (originally) first component + Assert.Equal(2, oldComponents[0].SetParametersCallCount); + Assert.Equal(1, oldComponents[1].SetParametersCallCount); + + // Assert: Correct diff + Assert.Collection(result.Edits, + entry => AssertPermutationListEntry(entry, 0, 2), + entry => AssertPermutationListEntry(entry, 2, 0), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void CanMoveBeforeInsertedItem() + { + // Arrange + AddWithKey(oldTree, "will retain"); + AddWithKey(oldTree, "will move"); + + AddWithKey(newTree, "will move"); + AddWithKey(newTree, "newly inserted"); + AddWithKey(newTree, "will retain"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 1); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("newly inserted", referenceFrames[entry.ReferenceFrameIndex].ElementKey); + }, + entry => AssertPermutationListEntry(entry, 0, 2), + entry => AssertPermutationListEntry(entry, 2, 0), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void CanMoveBeforeDeletedItem() + { + // Arrange + AddWithKey(oldTree, "will retain"); + AddWithKey(oldTree, "will delete"); + AddWithKey(oldTree, "will move"); + + AddWithKey(newTree, "will move"); + AddWithKey(newTree, "will retain"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), + entry => AssertPermutationListEntry(entry, 0, 1), + entry => AssertPermutationListEntry(entry, 1, 0), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void CanMoveAfterInsertedItem() + { + // Arrange + AddWithKey(oldTree, "will move"); + AddWithKey(oldTree, "will retain"); + + AddWithKey(newTree, "newly inserted"); + AddWithKey(newTree, "will retain"); + AddWithKey(newTree, "will move"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("newly inserted", referenceFrames[entry.ReferenceFrameIndex].ElementKey); + }, + entry => AssertPermutationListEntry(entry, 1, 2), + entry => AssertPermutationListEntry(entry, 2, 1), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void CanMoveAfterDeletedItem() + { + // Arrange + AddWithKey(oldTree, "will move"); + AddWithKey(oldTree, "will delete"); + AddWithKey(oldTree, "will retain"); + + AddWithKey(newTree, "will retain"); + AddWithKey(newTree, "will move"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1), + entry => AssertPermutationListEntry(entry, 0, 1), + entry => AssertPermutationListEntry(entry, 1, 0), + entry => AssertEdit(entry, RenderTreeEditType.PermutationListEnd, 0)); + } + + [Fact] + public void CanChangeFrameTypeWithMatchingSequenceNumber() + { + oldTree.OpenElement(0, "some elem"); + oldTree.AddContent(1, "Hello!"); + oldTree.CloseElement(); + + newTree.AddContent(0, "some text"); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => + { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("some text", referenceFrames[entry.ReferenceFrameIndex].TextContent); + }, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); + } + + [Fact] + public void CanChangeFrameTypeWithMatchingKey() + { + oldTree.OpenComponent(0); + oldTree.CloseComponent(); + + newTree.OpenElement(0, "some elem"); + newTree.SetKey("my key"); + newTree.CloseElement(); + + // Act + var (result, referenceFrames) = GetSingleUpdatedComponent(); + + // Assert + Assert.Collection(result.Edits, + entry => + { + AssertEdit(entry, RenderTreeEditType.PrependFrame, 0); + Assert.Equal(0, entry.ReferenceFrameIndex); + Assert.Equal("some elem", referenceFrames[entry.ReferenceFrameIndex].ElementName); + }, + entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1)); + } + private (RenderTreeDiff, RenderTreeFrame[]) GetSingleUpdatedComponent(bool initializeFromFrames = false) { var result = GetSingleUpdatedComponentWithBatch(initializeFromFrames); @@ -1524,6 +2183,28 @@ namespace Microsoft.AspNetCore.Components.Test return batchBuilder.ToBatch(); } + private static IList GetComponents(RenderTreeBuilder builder) + => GetComponents(builder); + + private static IList GetComponents(RenderTreeBuilder builder) where T : IComponent + => builder.GetFrames().AsEnumerable() + .Where(x => x.FrameType == RenderTreeFrameType.Component) + .Select(x => (T)x.Component) + .ToList(); + + private static void AddWithKey(RenderTreeBuilder builder, object key, string attributeValue = null) + { + builder.OpenElement(0, "el"); + builder.SetKey(key); + + if (attributeValue != null) + { + builder.AddAttribute(1, "attrib", attributeValue); + } + + builder.CloseElement(); + } + private class FakeRenderer : Renderer { public FakeRenderer() : base(new TestServiceProvider(), new RendererSynchronizationContext()) @@ -1613,5 +2294,15 @@ namespace Microsoft.AspNetCore.Components.Test Assert.Equal(type, edit.Type); Assert.Equal(siblingIndex, edit.SiblingIndex); } + + private static void AssertPermutationListEntry( + RenderTreeEdit edit, + int fromSiblingIndex, + int toSiblingIndex) + { + Assert.Equal(RenderTreeEditType.PermutationListEntry, edit.Type); + Assert.Equal(fromSiblingIndex, edit.SiblingIndex); + Assert.Equal(toSiblingIndex, edit.MoveToSiblingIndex); + } } } diff --git a/src/Components/Components/test/StackObjectPoolTest.cs b/src/Components/Components/test/StackObjectPoolTest.cs new file mode 100644 index 0000000000..33b9becc05 --- /dev/null +++ b/src/Components/Components/test/StackObjectPoolTest.cs @@ -0,0 +1,123 @@ +// 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 System.Linq; +using Xunit; + +namespace Microsoft.AspNetCore.Components.RenderTree +{ + public class StackObjectPoolTest + { + [Fact] + public void CanGetInstances() + { + // Arrange + var stackObjectPool = new StackObjectPool(10, () => new object()); + + // Act + var instance1 = stackObjectPool.Get(); + var instance2 = stackObjectPool.Get(); + + // Assert + Assert.NotNull(instance1); + Assert.NotNull(instance2); + Assert.NotSame(instance1, instance2); + } + + [Fact] + public void CanReturnInstances() + { + // Arrange + var stackObjectPool = new StackObjectPool(10, () => new object()); + var instance1 = stackObjectPool.Get(); + var instance2 = stackObjectPool.Get(); + + // Act/Assert + // No exception means success + stackObjectPool.Return(instance2); + stackObjectPool.Return(instance1); + } + + [Fact] + public void ReusesInstancesInPoolUpToCapacity() + { + // Arrange + var stackObjectPool = new StackObjectPool(10, () => new object()); + var instance1 = stackObjectPool.Get(); + var instance2 = stackObjectPool.Get(); + stackObjectPool.Return(instance2); + stackObjectPool.Return(instance1); + + // Act + var instance1b = stackObjectPool.Get(); + var instance2b = stackObjectPool.Get(); + var instance3 = stackObjectPool.Get(); + + // Assert + Assert.Same(instance1, instance1b); + Assert.Same(instance2, instance2b); + Assert.NotNull(instance3); + Assert.NotSame(instance1, instance3); + Assert.NotSame(instance2, instance3); + } + + [Fact] + public void SuppliesTransientInstancesWhenExceedingCapacity() + { + // Arrange + var stackObjectPool = new StackObjectPool(1, () => new object()); + + // Act 1: Returns distinct instances beyond capacity + var instance1 = stackObjectPool.Get(); + var instance2 = stackObjectPool.Get(); + var instance3 = stackObjectPool.Get(); + Assert.NotNull(instance1); + Assert.NotNull(instance2); + Assert.NotNull(instance3); + Assert.Equal(3, new[] { instance1, instance2, instance3 }.Distinct().Count()); + + // Act 2: Can return all instances, including transient ones + stackObjectPool.Return(instance3); + stackObjectPool.Return(instance2); + stackObjectPool.Return(instance1); + + // Act 3: Reuses only the non-transient instances + var instance1b = stackObjectPool.Get(); + var instance2b = stackObjectPool.Get(); + Assert.Same(instance1, instance1b); + Assert.NotSame(instance2b, instance2); + Assert.Equal(4, new[] { instance1, instance2, instance3, instance2b }.Distinct().Count()); + } + + [Fact] + public void CannotReturnWhenEmpty() + { + // Arrange + var stackObjectPool = new StackObjectPool(10, () => new object()); + + // Act/Assert + var ex = Assert.Throws(() => + { + stackObjectPool.Return(new object()); + }); + Assert.Equal("There are no outstanding instances to return.", ex.Message); + } + + [Fact] + public void CannotReturnMismatchingTrackedItem() + { + // Arrange + var stackObjectPool = new StackObjectPool(10, () => new object()); + var instance1 = stackObjectPool.Get(); + var instance2 = stackObjectPool.Get(); + + // Act/Assert + var ex = Assert.Throws(() => + { + stackObjectPool.Return(instance1); + }); + Assert.Equal("Attempting to return wrong pooled instance. Get/Return calls must form a stack.", ex.Message); + } + } +} diff --git a/src/Components/Server/src/Circuits/RenderBatchWriter.cs b/src/Components/Server/src/Circuits/RenderBatchWriter.cs index 321bef1084..d66c5de2a5 100644 --- a/src/Components/Server/src/Circuits/RenderBatchWriter.cs +++ b/src/Components/Server/src/Circuits/RenderBatchWriter.cs @@ -105,7 +105,11 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits // for this specific RenderTreeEditType. _binaryWriter.Write((int)edit.Type); _binaryWriter.Write(edit.SiblingIndex); + + // ReferenceFrameIndex and MoveToSiblingIndex share a slot, so this writes + // whichever one applies to the edit type _binaryWriter.Write(edit.ReferenceFrameIndex); + WriteString(edit.RemovedAttributeName, allowDeduplication: true); } diff --git a/src/Components/test/E2ETest/Tests/KeyTest.cs b/src/Components/test/E2ETest/Tests/KeyTest.cs new file mode 100644 index 0000000000..32f3ad5e3f --- /dev/null +++ b/src/Components/test/E2ETest/Tests/KeyTest.cs @@ -0,0 +1,351 @@ +// 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 System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using Microsoft.JSInterop; +using OpenQA.Selenium; +using OpenQA.Selenium.Interactions; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests +{ + public class KeyTest : BasicTestAppTestBase + { + public KeyTest( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + protected override void InitializeAsyncCore() + { + // On WebAssembly, page reloads are expensive so skip if possible + Navigate(ServerPathBase, noReload: !_serverFixture.UsingAspNetHost); + } + + [Fact] + public void CanInsert() + { + PerformTest( + before: new[] + { + new Node("orig1", "A"), + new Node("orig2", "B"), + }, + after: new[] + { + new Node("new1", "Inserted before") { IsNew = true }, + new Node("orig1", "A"), + new Node("new2", "Inserted between") { IsNew = true }, + new Node("orig2", "B edited"), + new Node("new3", "Inserted after") { IsNew = true }, + }); + } + + [Fact] + public void CanDelete() + { + PerformTest( + before: new[] + { + new Node("orig1", "A"), // Will delete first + new Node("orig2", "B"), + new Node("orig3", "C"), // Will delete in middle + new Node("orig4", "D"), + new Node("orig5", "E"), // Will delete at end + }, + after: new[] + { + new Node("orig2", "B"), + new Node("orig4", "D edited"), + }); + } + + [Fact] + public void CanInsertUnkeyed() + { + PerformTest( + before: new[] + { + new Node("orig1", "A"), + new Node("orig2", "B"), + }, + after: new[] + { + new Node(null, "Inserted before") { IsNew = true }, + new Node("orig1", "A edited"), + new Node(null, "Inserted between") { IsNew = true }, + new Node("orig2", "B"), + new Node(null, "Inserted after") { IsNew = true }, + }); + } + + [Fact] + public void CanDeleteUnkeyed() + { + PerformTest( + before: new[] + { + new Node(null, "A"), // Will delete first + new Node("orig2", "B"), + new Node(null, "C"), // Will delete in middle + new Node("orig4", "D"), + new Node(null, "E"), // Will delete at end + }, + after: new[] + { + new Node("orig2", "B edited"), + new Node("orig4", "D"), + }); + } + + [Fact] + public void CanReorder() + { + PerformTest( + before: new[] + { + new Node("keyA", "A", + new Node("keyA1", "A1"), + new Node("keyA2", "A2"), + new Node("keyA3", "A3")), + new Node("keyB", "B", + new Node("keyB1", "B1"), + new Node("keyB2", "B2"), + new Node("keyB3", "B3")), + new Node("keyC", "C", + new Node("keyC1", "C1"), + new Node("keyC2", "C2"), + new Node("keyC3", "C3")), + }, + after: new[] + { + // We're implicitly verifying that all the component instances were preserved, + // because we're not marking any with "IsNew = true" + new Node("keyC", "C", // Rotate all three (ABC->CAB) + // Swap first and last + new Node("keyC3", "C3"), + new Node("keyC2", "C2 edited"), + new Node("keyC1", "C1")), + new Node("keyA", "A", + // Swap first two + new Node("keyA2", "A2 edited"), + new Node("keyA1", "A1"), + new Node("keyA3", "A3")), + new Node("keyB", "B edited", + // Swap last two + new Node("keyB1", "B1"), + new Node("keyB3", "B3"), + new Node("keyB2", "B2 edited")), + }); + } + + [Fact] + public void CanReorderInsertDeleteAndEdit_WithAndWithoutKeys() + { + // This test is a complex bundle of many types of changes happening simultaneously + PerformTest( + before: new[] + { + new Node("keyA", "A", + new Node("keyA1", "A1"), + new Node(null, "A2 unkeyed"), + new Node("keyA3", "A3"), + new Node("keyA4", "A4")), + new Node("keyB", "B", + new Node(null, "B1 unkeyed"), + new Node("keyB2", "B2"), + new Node("keyB3", "B3"), + new Node("keyB4", "B4")), + new Node("keyC", "C", + new Node("keyC1", "C1"), + new Node("keyC2", "C2"), + new Node("keyC3", "C3"), + new Node(null, "C4 unkeyed")), + }, + after: new[] + { + // Swapped A and C + new Node("keyC", "C", + // C1-4 were reordered + // C5 was inserted + new Node("keyC5", "C5 inserted") { IsNew = true }, + new Node("keyC2", "C2"), + // C6 was inserted with no key + new Node(null, "C6 unkeyed inserted") { IsNew = true }, + // C1 was edited + new Node("keyC1", "C1 edited"), + new Node("keyC3", "C3") + // C4 unkeyed was deleted + ), + // B was deleted + // D was inserted + new Node("keyD", "D inserted", + new Node("keyB1", "D1") { IsNew = true }, // Matches an old key, but treated as new because we don't move between parents + new Node("keyD2", "D2") { IsNew = true }, + new Node(null, "D3 unkeyed") { IsNew = true }) + { IsNew = true }, + new Node("keyA", "A", + new Node("keyA1", "A1"), + // A2 (unkeyed) was edited + new Node(null, "A2 unkeyed edited"), + new Node("keyA3", "A3"), + // A4 was deleted + // A5 was inserted + new Node("keyA5", "A5 inserted") { IsNew = true }), + }); + } + + [Fact] + public async Task CanRetainFocusWhileMovingTextBox() + { + var appElem = MountTestComponent(); + Func textboxFinder = () => appElem.FindElement(By.CssSelector(".incomplete-items .item-1 input[type=text]")); + var textToType = "Hello this is a long string that should be typed"; + var expectedTextTyped = ""; + + textboxFinder().Clear(); + + // On each keystroke, the boxes will be shuffled. The text will only + // be inserted correctly if focus is retained. + textboxFinder().Click(); + while (textToType.Length > 0) + { + var nextBlockLength = Math.Min(5, textToType.Length); + var nextBlock = textToType.Substring(0, nextBlockLength); + textToType = textToType.Substring(nextBlockLength); + expectedTextTyped += nextBlock; + + // Send keys to whatever has focus + new Actions(Browser).SendKeys(nextBlock).Perform(); + Browser.Equal(expectedTextTyped, () => textboxFinder().GetAttribute("value")); + + // We delay between typings to ensure the events aren't all collapsed into one. + await Task.Delay(100); + } + + // Verify that after all this, we can still move the edited item + // This was broken originally because of unexpected event-handling behavior + // in Chrome (it raised events recursively) + appElem.FindElement( + By.CssSelector(".incomplete-items .item-1 input[type=checkbox]")).Click(); + Browser.Equal(expectedTextTyped, () => appElem + .FindElement(By.CssSelector(".complete-items .item-1 input[type=text]")) + .GetAttribute("value")); + } + + [Fact] + public void CanUpdateCheckboxStateWhileMovingIt() + { + var appElem = MountTestComponent(); + Func checkboxFinder = () => appElem.FindElement(By.CssSelector(".item-2 input[type=checkbox]")); + Func> incompleteItemStates = () => appElem + .FindElements(By.CssSelector(".incomplete-items input[type=checkbox]")) + .Select(elem => elem.Selected); + Func> completeItemStates = () => appElem + .FindElements(By.CssSelector(".complete-items input[type=checkbox]")) + .Select(elem => elem.Selected); + + // Verify initial state + Browser.Equal(new[] { false, false, false, false, false }, incompleteItemStates); + Browser.Equal(Array.Empty(), completeItemStates); + + // Check a box; see it moves and becomes the sole checked item + checkboxFinder().Click(); + Browser.True(() => checkboxFinder().Selected); + Browser.Equal(new[] { false, false, false, false }, incompleteItemStates); + Browser.Equal(new[] { true }, completeItemStates); + + // Also uncheck it; see it moves and becomes unchecked + checkboxFinder().Click(); + Browser.False(() => checkboxFinder().Selected); + Browser.Equal(new[] { false, false, false, false, false }, incompleteItemStates); + Browser.Equal(Array.Empty(), completeItemStates); + } + + private void PerformTest(Node[] before, Node[] after) + { + var rootBefore = new Node(null, "root", before); + var rootAfter = new Node(null, "root", after); + var jsonBefore = Json.Serialize(rootBefore); + var jsonAfter = Json.Serialize(rootAfter); + + var appElem = MountTestComponent(); + var textbox = appElem.FindElement(By.TagName("textarea")); + var updateButton = appElem.FindElement(By.TagName("button")); + + SetTextAreaValueFast(textbox, jsonBefore); + updateButton.Click(); + ValidateRenderedOutput(appElem, rootBefore, validatePreservation: false); + + SetTextAreaValueFast(textbox, jsonAfter); + updateButton.Click(); + ValidateRenderedOutput(appElem, rootAfter, validatePreservation: true); + } + + private static void ValidateRenderedOutput(IWebElement appElem, Node expectedRootNode, bool validatePreservation) + { + var actualRootElem = appElem.FindElement(By.CssSelector(".render-output > .node")); + var actualRootNode = ReadNodeFromDOM(actualRootElem); + AssertNodesEqual(expectedRootNode, actualRootNode, validatePreservation); + } + + private static void AssertNodesEqual(Node expectedRootNode, Node actualRootNode, bool validatePreservation) + { + Assert.Equal(expectedRootNode.Label, actualRootNode.Label); + + if (validatePreservation) + { + Assert.Equal(expectedRootNode.IsNew, actualRootNode.IsNew); + } + + Assert.Collection( + actualRootNode.Children, + expectedRootNode.Children.Select>(expectedChild => + (actualChild => AssertNodesEqual(expectedChild, actualChild, validatePreservation))).ToArray()); + } + + private static Node ReadNodeFromDOM(IWebElement nodeElem) + { + var label = nodeElem.FindElement(By.ClassName("label")).Text; + var childNodes = nodeElem + .FindElements(By.XPath("*[@class='children']/*[@class='node']")); + return new Node(key: null, label, childNodes.Select(ReadNodeFromDOM).ToArray()) + { + IsNew = nodeElem.FindElement(By.ClassName("is-new")).Text == "true" + }; + } + + private void SetTextAreaValueFast(IWebElement textAreaElementWithId, string value) + { + var javascript = (IJavaScriptExecutor)Browser; + javascript.ExecuteScript($"document.getElementById('{textAreaElementWithId.GetAttribute("id")}').value = {Json.Serialize(value)}"); + textAreaElementWithId.SendKeys(" "); // So it fires the change event + } + + class Node + { + public string Key { get; } + public string Label { get; } + public Node[] Children { get; } + public bool IsNew { get; set; } + + public Node(string key, string label, params Node[] children) + { + Key = key; + Label = label; + Children = children ?? Array.Empty(); + } + } + } +} diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor index 76c5881080..92f8d65b94 100644 --- a/src/Components/test/testassets/BasicTestApp/Index.razor +++ b/src/Components/test/testassets/BasicTestApp/Index.razor @@ -50,6 +50,8 @@ + + @if (SelectedComponentType != null) diff --git a/src/Components/test/testassets/BasicTestApp/KeyCasesComponent.razor b/src/Components/test/testassets/BasicTestApp/KeyCasesComponent.razor new file mode 100644 index 0000000000..9ef1a5bffa --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/KeyCasesComponent.razor @@ -0,0 +1,73 @@ +@using Microsoft.JSInterop +
+
+

Model

+ + +
+
+

Output

+ + + +
+
+ + + +@functions { + string modelJson = @"{ + ""label"": ""root"", + ""children"": [ + { + ""key"": ""a"", + ""label"": ""A"", + ""children"": [ + { ""key"": ""a1"", ""label"": ""A1"" }, + { ""key"": ""a2"", ""label"": ""A2"" }, + { ""key"": ""a3"", ""label"": ""A3"" } + ] + }, + { + ""key"": ""b"", + ""label"": ""B"", + ""children"": [ + { ""key"": ""b1"", ""label"": ""B1"" }, + { ""key"": ""b2"", ""label"": ""B2"" }, + { ""key"": ""b3"", ""label"": ""B3"" } + ] + } + ] +}"; + + KeyCasesTreeNode.Node parsedRootNode; + RenderContext renderContext = new RenderContext(); + + protected override void OnInit() + { + Update(); + } + + void Update() + { + renderContext.UpdateCount++; + parsedRootNode = Json.Deserialize(modelJson); + } + + public class RenderContext + { + // This is so the descendants can detect and display whether they are + // newly-instantiated on any given render + public int UpdateCount { get; set; } + } +} diff --git a/src/Components/test/testassets/BasicTestApp/KeyCasesTreeNode.razor b/src/Components/test/testassets/BasicTestApp/KeyCasesTreeNode.razor new file mode 100644 index 0000000000..16ed8de0eb --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/KeyCasesTreeNode.razor @@ -0,0 +1,53 @@ +
+ @Data.Label +   [ + Instance: @instanceId; + + Is new: + @if (firstCreatedOnUpdateCount == RenderContext.UpdateCount) + { + true + } + else + { + false + } + ] + + @if (Data.Children?.Any() ?? false) + { +
@{ + foreach (var child in Data.Children) + { + if (child.Key != null) + { + + } + else + { + + } + } + }
+ } +
+ +@functions { + public class Node + { + public object Key { get; set; } + public string Label { get; set; } + public List Children { get; set; } + } + + string instanceId = Guid.NewGuid().ToString("D").Substring(0, 6); + int firstCreatedOnUpdateCount; + + [Parameter] Node Data { get; set; } + [CascadingParameter] KeyCasesComponent.RenderContext RenderContext { get; set; } + + protected override void OnInit() + { + firstCreatedOnUpdateCount = RenderContext.UpdateCount; + } +} diff --git a/src/Components/test/testassets/BasicTestApp/ReorderingFocusComponent.razor b/src/Components/test/testassets/BasicTestApp/ReorderingFocusComponent.razor new file mode 100644 index 0000000000..acede2b465 --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/ReorderingFocusComponent.razor @@ -0,0 +1,55 @@ +

To do

+ +

+ This component will randomly reorder the todo items on each keystroke. + The point of this is to show that focus is correctly preserved even + when items are moved around. Also, by checking the boxes to move items + between the two lists, we show that use of key causes the + form element state to behave as expected. +

+ +
    + @foreach (var item in todoItems.Where(item => !item.IsDone)) + { +
  • + + +
  • + } +
+ +

Done

+ +
    + @foreach (var item in todoItems.Where(item => item.IsDone)) + { +
  • + + +
  • + } +
+ +@functions { + Random rng = new Random(); + TodoItem[] todoItems = new[] + { + new TodoItem { Id = 1, Text = "First" }, + new TodoItem { Id = 2, Text = "Second" }, + new TodoItem { Id = 3, Text = "Third" }, + new TodoItem { Id = 4, Text = "Fourth" }, + new TodoItem { Id = 5, Text = "Fifth" }, + }; + + void Shuffle() + { + todoItems = todoItems.OrderBy(x => rng.Next()).ToArray(); + } + + class TodoItem + { + public int Id { get; set; } + public string Text { get; set; } + public bool IsDone { get; set; } + } +} diff --git a/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj b/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj index 3e79d4f6a1..aa193e9210 100644 --- a/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj +++ b/src/Components/test/testassets/ComponentsApp.App/ComponentsApp.App.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -11,4 +11,3 @@ -