diff --git a/AspNetCore.sln b/AspNetCore.sln index 813c654076b8..2cfc85e4fc35 100644 --- a/AspNetCore.sln +++ b/AspNetCore.sln @@ -1656,6 +1656,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.App.Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.App.Analyzers.Test", "src\Framework\AspNetCoreAnalyzers\test\Microsoft.AspNetCore.App.Analyzers.Test.csproj", "{B739B8B6-94F5-4F05-9497-28A7C6EBBC03}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.HttpSys.NonHelixTests", "src\Servers\HttpSys\test\NonHelixTests\Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj", "{37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DelegationSite", "src\Servers\HttpSys\test\testassets\DelegationSite\DelegationSite.csproj", "{14217994-9F24-4E14-87B6-58367ED0413B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -7907,6 +7911,30 @@ Global {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x64.Build.0 = Release|Any CPU {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x86.ActiveCfg = Release|Any CPU {B739B8B6-94F5-4F05-9497-28A7C6EBBC03}.Release|x86.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x64.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x64.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x86.ActiveCfg = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Debug|x86.Build.0 = Debug|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|Any CPU.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x64.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x64.Build.0 = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x86.ActiveCfg = Release|Any CPU + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1}.Release|x86.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x64.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x64.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x86.ActiveCfg = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Debug|x86.Build.0 = Debug|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|Any CPU.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x64.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x64.Build.0 = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x86.ActiveCfg = Release|Any CPU + {14217994-9F24-4E14-87B6-58367ED0413B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -8727,6 +8755,8 @@ Global {636B73F6-9EED-435D-9DA8-EB3C7FDFAB1C} = {23C56C5B-9D3F-4069-88C4-87ACCFE05DBC} {78D9A5AF-6089-44F4-93AB-F7E96925E4FD} = {23C56C5B-9D3F-4069-88C4-87ACCFE05DBC} {B739B8B6-94F5-4F05-9497-28A7C6EBBC03} = {12541C41-58FB-46F4-BA0F-0D56B5B45A18} + {37BDB2D5-EEEC-48C9-A7AD-5A2A73BD31B1} = {C3722C5D-E159-4AB3-AF60-769185B31B47} + {14217994-9F24-4E14-87B6-58367ED0413B} = {C3722C5D-E159-4AB3-AF60-769185B31B47} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F} diff --git a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs index aebe39281f04..114d5d1425e7 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs @@ -52,8 +52,7 @@ public static ComponentEndpointConventionBuilder MapBlazorHub( throw new ArgumentNullException(nameof(path)); } - // Only support the WebSockets transport type by default - return endpoints.MapBlazorHub(path, configureOptions: options => { options.Transports = HttpTransportType.WebSockets; }); + return endpoints.MapBlazorHub(path, configureOptions: _ => { }); } /// diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index a847a23e5487..81360eb0d9e1 100644 --- a/src/Components/Web.JS/dist/Release/blazor.server.js +++ b/src/Components/Web.JS/dist/Release/blazor.server.js @@ -1 +1 @@ -(()=>{"use strict";var e,t,n,r={};r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),function(e){window.DotNet=e;const t=[],n=new Map,r=new Map,o="__jsObjectId",s="__byte[]";class i{constructor(e){this._jsObject=e,this._cachedFunctions=new Map}findFunction(e){const t=this._cachedFunctions.get(e);if(t)return t;let n,r=this._jsObject;if(e.split(".").forEach((t=>{if(!(t in r))throw new Error(`Could not find '${e}' ('${t}' was undefined).`);n=r,r=r[t]})),r instanceof Function)return r=r.bind(n),this._cachedFunctions.set(e,r),r;throw new Error(`The value '${e}' is not a function.`)}getWrappedObject(){return this._jsObject}}const a={},c={0:new i(window)};c[0]._cachedFunctions.set("import",(e=>("string"==typeof e&&e.startsWith("./")&&(e=document.baseURI+e.substr(2)),import(e))));let l,h=1,u=1,d=null;function p(e){t.push(e)}function f(e){if(e&&"object"==typeof e){c[u]=new i(e);const t={[o]:u};return u++,t}throw new Error(`Cannot create a JSObjectReference from the value '${e}'.`)}function g(e){let t=-1;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),e instanceof Blob)t=e.size;else{if(!(e.buffer instanceof ArrayBuffer))throw new Error("Supplied value is not a typed array or blob.");if(void 0===e.byteLength)throw new Error(`Cannot create a JSStreamReference from the value '${e}' as it doesn't have a byteLength.`);t=e.byteLength}const n={__jsStreamReferenceLength:t};try{const t=f(e);n.__jsObjectId=t.__jsObjectId}catch{throw new Error(`Cannot create a JSStreamReference from the value '${e}'.`)}return n}function m(e){return e?JSON.parse(e,((e,n)=>t.reduce(((t,n)=>n(e,t)),n))):null}function y(e,t,n,r){const o=v();if(o.invokeDotNetFromJS){const s=x(r),i=o.invokeDotNetFromJS(e,t,n,s);return i?m(i):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function w(e,t,n,r){if(e&&n)throw new Error(`For instance method calls, assemblyName should be null. Received '${e}'.`);const o=h++,s=new Promise(((e,t)=>{a[o]={resolve:e,reject:t}}));try{const s=x(r);v().beginInvokeDotNetFromJS(o,e,t,n,s)}catch(e){b(o,!1,e)}return s}function v(){if(null!==d)return d;throw new Error("No .NET call dispatcher has been set.")}function b(e,t,n){if(!a.hasOwnProperty(e))throw new Error(`There is no pending async call with ID ${e}.`);const r=a[e];delete a[e],t?r.resolve(n):r.reject(n)}function _(e){return e instanceof Error?`${e.message}\n${e.stack}`:e?e.toString():"null"}function E(e,t){let n=c[t];if(n)return n.findFunction(e);throw new Error(`JS object instance with ID ${t} does not exist (has it been disposed?).`)}function S(e){delete c[e]}e.attachDispatcher=function(e){d=e},e.attachReviver=p,e.invokeMethod=function(e,t,...n){return y(e,t,null,n)},e.invokeMethodAsync=function(e,t,...n){return w(e,t,null,n)},e.createJSObjectReference=f,e.createJSStreamReference=g,e.disposeJSObjectReference=function(e){const t=e&&e.__jsObjectId;"number"==typeof t&&S(t)},function(e){e[e.Default=0]="Default",e[e.JSObjectReference=1]="JSObjectReference",e[e.JSStreamReference=2]="JSStreamReference",e[e.JSVoidResult=3]="JSVoidResult"}(l=e.JSCallResultType||(e.JSCallResultType={})),e.jsCallDispatcher={findJSFunction:E,disposeJSObjectReferenceById:S,invokeJSFromDotNet:(e,t,n,r)=>{const o=T(E(e,r).apply(null,m(t)),n);return null==o?null:x(o)},beginInvokeJSFromDotNet:(e,t,n,r,o)=>{const s=new Promise((e=>{e(E(t,o).apply(null,m(n)))}));e&&s.then((t=>v().endInvokeJSFromDotNet(e,!0,x([e,!0,T(t,r)]))),(t=>v().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,_(t)]))))},endInvokeDotNetFromJS:(e,t,n)=>{const r=t?m(n):new Error(n);b(parseInt(e),t,r)},receiveByteArray:(e,t)=>{n.set(e,t)},supplyDotNetStream:(e,t)=>{if(r.has(e)){const n=r.get(e);r.delete(e),n.resolve(t)}else{const n=new k;n.resolve(t),r.set(e,n)}}};class C{constructor(e){this._id=e}invokeMethod(e,...t){return y(null,e,this._id,t)}invokeMethodAsync(e,...t){return w(null,e,this._id,t)}dispose(){w(null,"__Dispose",this._id,null).catch((e=>console.error(e)))}serializeAsArg(){return{__dotNetObject:this._id}}}e.DotNetObject=C,p((function(e,t){if(t&&"object"==typeof t){if(t.hasOwnProperty("__dotNetObject"))return new C(t.__dotNetObject);if(t.hasOwnProperty(o)){const e=t.__jsObjectId,n=c[e];if(n)return n.getWrappedObject();throw new Error(`JS object instance with Id '${e}' does not exist. It may have been disposed.`)}if(t.hasOwnProperty(s)){const e=t["__byte[]"],r=n.get(e);if(void 0===r)throw new Error(`Byte array index '${e}' does not exist.`);return n.delete(e),r}if(t.hasOwnProperty("__dotNetStream"))return new I(t.__dotNetStream)}return t}));class I{constructor(e){var t;if(r.has(e))this._streamPromise=null===(t=r.get(e))||void 0===t?void 0:t.streamPromise,r.delete(e);else{const t=new k;r.set(e,t),this._streamPromise=t.streamPromise}}stream(){return this._streamPromise}async arrayBuffer(){return new Response(await this.stream()).arrayBuffer()}}class k{constructor(){this.streamPromise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}function T(e,t){switch(t){case l.Default:return e;case l.JSObjectReference:return f(e);case l.JSStreamReference:return g(e);case l.JSVoidResult:return null;default:throw new Error(`Invalid JS call result type '${t}'.`)}}let D=0;function x(e){return D=0,JSON.stringify(e,R)}function R(e,t){if(t instanceof C)return t.serializeAsArg();if(t instanceof Uint8Array){d.sendByteArray(D,t);const e={[s]:D};return D++,e}return t}}(e||(e={})),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t||(t={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(n||(n={}));class o{constructor(e,t){this.componentId=e,this.fieldValue=t}static fromEvent(e,t){const n=t.target;if(n instanceof Element){const t=function(e){return e instanceof HTMLInputElement?e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value}:e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?{value:e.value}:null}(n);if(t)return new o(e,t.value)}return null}}const s=new Map,i=new Map,a={createEventArgs:()=>({})},c=[];function l(e){return s.get(e)}function h(e){const t=s.get(e);return(null==t?void 0:t.browserEventName)||e}function u(e,t){e.forEach((e=>s.set(e,t)))}function d(e){const t=[];for(let n=0;ne.selected)).map((e=>e.value))}}return{value:function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(t)?!!t.checked:t.value}}}),u(["copy","cut","paste"],a),u(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...p(t=e),dataTransfer:t.dataTransfer?{dropEffect:t.dataTransfer.dropEffect,effectAllowed:t.dataTransfer.effectAllowed,files:Array.from(t.dataTransfer.files).map((e=>e.name)),items:Array.from(t.dataTransfer.items).map((e=>({kind:e.kind,type:e.type}))),types:t.dataTransfer.types}:null};var t}}),u(["focus","blur","focusin","focusout"],a),u(["keydown","keyup","keypress"],{createEventArgs:e=>{return{key:(t=e).key,code:t.code,location:t.location,repeat:t.repeat,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey};var t}}),u(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>p(e)}),u(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),u(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),u(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:d(t.touches),targetTouches:d(t.targetTouches),changedTouches:d(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),u(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...p(t=e),pointerId:t.pointerId,width:t.width,height:t.height,pressure:t.pressure,tiltX:t.tiltX,tiltY:t.tiltY,pointerType:t.pointerType,isPrimary:t.isPrimary};var t}}),u(["wheel","mousewheel"],{createEventArgs:e=>{return{...p(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),u(["toggle"],a);const f=["date","datetime-local","month","time","week"],g=new Map;let m,y,w=0;const v={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++w).toString();g.set(r,e);const o=await E().invokeMethodAsync("AddRootComponent",t,r),s=new _(o,y[t]);return await s.setParameters(n),s}};class b{invoke(e){return this._callback(e)}setCallback(t){this._selfJSObjectReference||(this._selfJSObjectReference=e.createJSObjectReference(this)),this._callback=t}getJSObjectReference(){return this._selfJSObjectReference}dispose(){this._selfJSObjectReference&&e.disposeJSObjectReference(this._selfJSObjectReference)}}class _{constructor(e,t){this._jsEventCallbackWrappers=new Map,this._componentId=e;for(const e of t)"eventcallback"===e.type&&this._jsEventCallbackWrappers.set(e.name.toLowerCase(),new b)}setParameters(e){const t={},n=Object.entries(e||{}),r=n.length;for(const[e,r]of n){const n=this._jsEventCallbackWrappers.get(e.toLowerCase());n&&r?(n.setCallback(r),t[e]=n.getJSObjectReference()):t[e]=r}return E().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await E().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function E(){if(!m)throw new Error("Dynamic root components have not been enabled in this application.");return m}const S=new Map;function C(e,t,n){return k(e,t.eventHandlerId,(()=>I(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function I(e){const t=S.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let k=(e,t,n)=>n();const T=A(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),D={submit:!0},x=A(["click","dblclick","mousedown","mousemove","mouseup"]);class R{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++R.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new P(this.onGlobalEvent.bind(this))}setListener(e,t,n,r){const o=this.getEventHandlerInfosForElement(e,!0),s=o.getHandler(t);if(s)this.eventInfoStore.update(s.eventHandlerId,n);else{const s={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(s),o.setHandler(t,s)}}getHandler(e){return this.eventInfoStore.get(e)}removeListener(e){const t=this.eventInfoStore.remove(e);if(t){const e=t.element,n=this.getEventHandlerInfosForElement(e,!1);n&&n.removeHandler(t.eventName)}}notifyAfterClick(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")}setStopPropagation(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)}setPreventDefault(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)}onGlobalEvent(e){if(!(e.target instanceof Element))return;this.dispatchGlobalEventToAllElements(e.type,e);const t=(n=e.type,i.get(n));var n;t&&t.forEach((t=>this.dispatchGlobalEventToAllElements(t,e))),"click"===e.type&&this.afterClickCallbacks.forEach((t=>t(e)))}dispatchGlobalEventToAllElements(e,t){const n=t.composedPath();let r=n.shift(),s=null,i=!1;const a=T.hasOwnProperty(e);let c=!1;for(;r;){const d=r,p=this.getEventHandlerInfosForElement(d,!1);if(p){const n=p.getHandler(e);if(n&&(h=d,u=t.type,!((h instanceof HTMLButtonElement||h instanceof HTMLInputElement||h instanceof HTMLTextAreaElement||h instanceof HTMLSelectElement)&&x.hasOwnProperty(u)&&h.disabled))){if(!i){const n=l(e);s=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},i=!0}D.hasOwnProperty(t.type)&&t.preventDefault(),C(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:o.fromEvent(n.renderingComponentId,t)},s)}p.stopPropagation(e)&&(c=!0),p.preventDefault(e)&&t.preventDefault()}r=a||c?void 0:n.shift()}var h,u}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new U:null}}R.nextEventDelegatorId=0;class P{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},c.push(this.handleEventNameAliasAdded.bind(this))}add(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error(`Event ${e.eventHandlerId} is already tracked`);this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)}get(e){return this.infosByEventHandlerId[e]}addGlobalListener(e){if(e=h(e),this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;const t=T.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}}update(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error(`Event ${t} is already tracked`);const n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n}remove(e){const t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];const n=h(t.eventName);0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t}handleEventNameAliasAdded(e,t){if(this.countByEventName.hasOwnProperty(e)){const n=this.countByEventName[e];delete this.countByEventName[e],document.removeEventListener(e,this.globalListener),this.addGlobalListener(t),this.countByEventName[t]+=n-1}}}class U{constructor(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}getHandler(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null}setHandler(e,t){this.handlers[e]=t}removeHandler(e){delete this.handlers[e]}preventDefault(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]}stopPropagation(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]}}function A(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const N=Y("_blazorLogicalChildren"),$=Y("_blazorLogicalParent"),B=Y("_blazorLogicalEnd");function L(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return N in e||(e[N]=[]),e}function M(e,t){const n=document.createComment("!");return O(n,e,t),n}function O(e,t,n){const r=e;if(e instanceof Comment&&z(r)&&z(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(H(r))throw new Error("Not implemented: moving existing logical children");const o=z(t);if(n0;)F(n,0)}const r=n;r.parentNode.removeChild(r)}function H(e){return e[$]||null}function j(e,t){return z(e)[t]}function W(e){var t=q(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function z(e){return e[N]}function J(e,t){const n=z(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=X(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):K(r,e)})),t.forEach((e=>{const t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd;let s=r;for(;s;){const e=s.nextSibling;if(n.insertBefore(s,t),s===o)break;s=e}n.removeChild(t)})),t.forEach((e=>{n[e.toSiblingIndex]=e.moveRangeStart}))}function q(e){if(e instanceof Element||e instanceof DocumentFragment)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function V(e){const t=z(H(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function K(e,t){if(t instanceof Element||t instanceof DocumentFragment)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error(`Cannot append node because the parent is not a valid logical element. Parent: ${t}`);{const n=V(t);n?n.parentNode.insertBefore(e,n):K(e,H(t))}}}function X(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=V(e);if(t)return t.previousSibling;{const t=H(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:X(t)}}function Y(e){return"function"==typeof Symbol?Symbol():e}function G(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${G(e)}]`;return document.querySelector(t)}(t.__internalId):t));const Q="_blazorDeferredValue",Z=document.createElement("template"),ee=document.createElementNS("http://www.w3.org/2000/svg","g"),te={},ne="__internal_",re="preventDefault_",oe="stopPropagation_";class se{constructor(e){this.rootComponentIds=new Set,this.childComponentLocations={},this.eventDelegator=new R(e),this.eventDelegator.notifyAfterClick((e=>{if(!pe)return;if(0!==e.button||function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e))return;if(e.defaultPrevented)return;const t=function(e){const t=!window._blazorDisableComposedPath&&e.composedPath&&e.composedPath();if(t){for(let e=0;eve(!1))))},enableNavigationInterception:function(){pe=!0},navigateTo:ye,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function ye(e,t,n=!1){const r=_e(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Se(r)?we(r,!1,o.replaceHistoryEntry):function(e,t){if(location.href===e){const t=e+"?";history.replaceState(null,"",t),location.replace(e)}else t?location.replace(e):location.href=e}(e,o.replaceHistoryEntry)}function we(e,t,n){de=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),ve(t)}async function ve(e){ge&&await ge(location.href,e)}let be;function _e(e){return be=be||document.createElement("a"),be.href=e,be.href}function Ee(e,t){return e?e.tagName===t?e:Ee(e.parentElement,t):null}function Se(e){const t=(n=document.baseURI).substr(0,n.lastIndexOf("/")+1);var n;return e.startsWith(t)}const Ce={focus:function(e,t){if(e instanceof HTMLElement)e.focus({preventScroll:t});else{if(!(e instanceof SVGElement))throw new Error("Unable to focus an invalid element.");if(!e.hasAttribute("tabindex"))throw new Error("Unable to focus an SVG element that does not have a tabindex.");e.focus({preventScroll:t})}},focusBySelector:function(e){const t=document.querySelector(e);t&&(t.hasAttribute("tabindex")||(t.tabIndex=-1),t.focus())}},Ie={init:function(e,t,n,r=50){const o=Te(t);(o||document.documentElement).style.overflowAnchor="none";const s=new IntersectionObserver((function(r){r.forEach((r=>{var o;if(!r.isIntersecting)return;const s=t.getBoundingClientRect(),i=n.getBoundingClientRect().top-s.bottom,a=null===(o=r.rootBounds)||void 0===o?void 0:o.height;r.target===t?e.invokeMethodAsync("OnSpacerBeforeVisible",r.intersectionRect.top-r.boundingClientRect.top,i,a):r.target===n&&n.offsetHeight>0&&e.invokeMethodAsync("OnSpacerAfterVisible",r.boundingClientRect.bottom-r.intersectionRect.bottom,i,a)}))}),{root:o,rootMargin:`${r}px`});s.observe(t),s.observe(n);const i=c(t),a=c(n);function c(e){const t=new MutationObserver((()=>{s.unobserve(e),s.observe(e)}));return t.observe(e,{attributes:!0}),t}ke[e._id]={intersectionObserver:s,mutationObserverBefore:i,mutationObserverAfter:a}},dispose:function(e){const t=ke[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete ke[e._id])}},ke={};function Te(e){return e?"visible"!==getComputedStyle(e).overflowY?e:Te(e.parentElement):null}const De={getAndRemoveExistingTitle:function(){var e;const t=document.getElementsByTagName("title");if(0===t.length)return null;let n=null;for(let r=t.length-1;r>=0;r--){const o=t[r],s=o.previousSibling;s instanceof Comment&&null!==H(s)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},xe={init:function(e,t){t._blazorInputFileNextFileId=0,t.addEventListener("click",(function(){t.value=""})),t.addEventListener("change",(function(){t._blazorFilesById={};const n=Array.prototype.map.call(t.files,(function(e){const n={id:++t._blazorInputFileNextFileId,lastModified:new Date(e.lastModified).toISOString(),name:e.name,size:e.size,contentType:e.type,readPromise:void 0,arrayBuffer:void 0,blob:e};return t._blazorFilesById[n.id]=n,n}));e.invokeMethodAsync("NotifyChange",n)}))},toImageFile:async function(e,t,n,r,o){const s=Re(e,t),i=await new Promise((function(e){const t=new Image;t.onload=function(){URL.revokeObjectURL(t.src),e(t)},t.onerror=function(){t.onerror=null,URL.revokeObjectURL(t.src)},t.src=URL.createObjectURL(s.blob)})),a=await new Promise((function(e){var t;const s=Math.min(1,r/i.width),a=Math.min(1,o/i.height),c=Math.min(s,a),l=document.createElement("canvas");l.width=Math.round(i.width*c),l.height=Math.round(i.height*c),null===(t=l.getContext("2d"))||void 0===t||t.drawImage(i,0,0,l.width,l.height),l.toBlob(e,n)})),c={id:++e._blazorInputFileNextFileId,lastModified:s.lastModified,name:s.name,size:(null==a?void 0:a.size)||0,contentType:n,blob:a||s.blob};return e._blazorFilesById[c.id]=c,c},readFileData:async function(e,t){return Re(e,t).blob}};function Re(e,t){const n=e._blazorFilesById[t];if(!n)throw new Error(`There is no file with ID ${t}. The file list may have changed.`);return n}async function Pe(e,t,n){return e instanceof Blob?await async function(e,t,n){const r=e.slice(t,t+n),o=await r.arrayBuffer();return new Uint8Array(o)}(e,t,n):function(e,t,n){return new Uint8Array(e.buffer,e.byteOffset+t,n)}(e,t,n)}const Ue=new Map,Ae={navigateTo:ye,registerCustomEventType:function(e,t){if(!t)throw new Error("The options parameter is required.");if(s.has(e))throw new Error(`The event '${e}' is already registered.`);if(t.browserEventName){const n=i.get(t.browserEventName);n?n.push(e):i.set(t.browserEventName,[e]),c.forEach((n=>n(e,t.browserEventName)))}s.set(e,t)},rootComponents:v,_internal:{navigationManager:me,domWrapper:Ce,Virtualize:Ie,PageTitle:De,InputFile:xe,getJSDataStreamChunk:Pe,receiveDotNetDataStream:function(t,n,r,o){let s=Ue.get(t);if(!s){const n=new ReadableStream({start(e){Ue.set(t,e),s=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(s.error(o),Ue.delete(t)):0===r?(s.close(),Ue.delete(t)):s.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(S.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);S.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(m)throw new Error("Dynamic root components have already been enabled.");m=t,y=n;for(const[t,o]of Object.entries(r)){const r=e.jsCallDispatcher.findJSFunction(t,0);for(const e of o)r(e,n[e])}}(I(t),r,o)}}};window.Blazor=Ae;const Ne=[0,2e3,1e4,3e4,null];class $e{constructor(e){this._retryDelays=void 0!==e?[...e,null]:Ne}nextRetryDelayInMilliseconds(e){return this._retryDelays[e.previousRetryCount]}}class Be extends Error{constructor(e,t){const n=new.target.prototype;super(`${e}: Status code '${t}'`),this.statusCode=t,this.__proto__=n}}class Le extends Error{constructor(e="A timeout occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Me extends Error{constructor(e="An abort occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Oe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="UnsupportedTransportError",this.__proto__=n}}class Fe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="DisabledTransportError",this.__proto__=n}}class He extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="FailedToStartTransportError",this.__proto__=n}}class je extends Error{constructor(e){const t=new.target.prototype;super(e),this.errorType="FailedToNegotiateWithServerError",this.__proto__=t}}class We extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.innerErrors=t,this.__proto__=n}}class ze{constructor(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}class Je{get(e,t){return this.send({...t,method:"GET",url:e})}post(e,t){return this.send({...t,method:"POST",url:e})}delete(e,t){return this.send({...t,method:"DELETE",url:e})}getCookieString(e){return""}}var qe,Ve,Ke,Xe,Ye;!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"}(qe||(qe={}));class Ge{constructor(){}log(e,t){}}Ge.instance=new Ge;class Qe{static isRequired(e,t){if(null==e)throw new Error(`The '${t}' argument is required.`)}static isNotEmpty(e,t){if(!e||e.match(/^\s*$/))throw new Error(`The '${t}' argument should not be empty.`)}static isIn(e,t,n){if(!(e in t))throw new Error(`Unknown ${n} value: ${e}.`)}}class Ze{static get isBrowser(){return"object"==typeof window}static get isWebWorker(){return"object"==typeof self&&"importScripts"in self}static get isNode(){return!this.isBrowser&&!this.isWebWorker}}function et(e,t){let n="";return tt(e)?(n=`Binary data of length ${e.byteLength}`,t&&(n+=`. Content: '${function(e){const t=new Uint8Array(e);let n="";return t.forEach((e=>{n+=`0x${e<16?"0":""}${e.toString(16)} `})),n.substr(0,n.length-1)}(e)}'`)):"string"==typeof e&&(n=`String data of length ${e.length}`,t&&(n+=`. Content: '${e}'`)),n}function tt(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}async function nt(e,t,n,r,o,s,i){let a={};if(o){const e=await o();e&&(a={Authorization:`Bearer ${e}`})}const[c,l]=st();a[c]=l,e.log(qe.Trace,`(${t} transport) sending data. ${et(s,i.logMessageContent)}.`);const h=tt(s)?"arraybuffer":"text",u=await n.post(r,{content:s,headers:{...a,...i.headers},responseType:h,timeout:i.timeout,withCredentials:i.withCredentials});e.log(qe.Trace,`(${t} transport) request complete. Response status: ${u.statusCode}.`)}class rt{constructor(e,t){this._subject=e,this._observer=t}dispose(){const e=this._subject.observers.indexOf(this._observer);e>-1&&this._subject.observers.splice(e,1),0===this._subject.observers.length&&this._subject.cancelCallback&&this._subject.cancelCallback().catch((e=>{}))}}class ot{constructor(e){this._minLevel=e,this.out=console}log(e,t){if(e>=this._minLevel){const n=`[${(new Date).toISOString()}] ${qe[e]}: ${t}`;switch(e){case qe.Critical:case qe.Error:this.out.error(n);break;case qe.Warning:this.out.warn(n);break;case qe.Information:this.out.info(n);break;default:this.out.log(n)}}}}function st(){let e="X-SignalR-User-Agent";return Ze.isNode&&(e="User-Agent"),[e,it("0.0.0-DEV_BUILD",at(),Ze.isNode?"NodeJS":"Browser",ct())]}function it(e,t,n,r){let o="Microsoft SignalR/";const s=e.split(".");return o+=`${s[0]}.${s[1]}`,o+=` (${e}; `,o+=t&&""!==t?`${t}; `:"Unknown OS; ",o+=`${n}`,o+=r?`; ${r}`:"; Unknown Runtime Version",o+=")",o}function at(){if(!Ze.isNode)return"";switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}function ct(){if(Ze.isNode)return process.versions.node}function lt(e){return e.stack?e.stack:e.message?e.message:`${e}`}class ht extends Je{constructor(e){if(super(),this._logger=e,"undefined"==typeof fetch){const e=require;this._jar=new(e("tough-cookie").CookieJar),this._fetchType=e("node-fetch"),this._fetchType=e("fetch-cookie")(this._fetchType,this._jar)}else this._fetchType=fetch.bind(function(){if("undefined"!=typeof globalThis)return globalThis;if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==r.g)return r.g;throw new Error("could not find global")}());if("undefined"==typeof AbortController){const e=require;this._abortControllerType=e("abort-controller")}else this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new Me;if(!e.method)throw new Error("No method defined.");if(!e.url)throw new Error("No url defined.");const t=new this._abortControllerType;let n;e.abortSignal&&(e.abortSignal.onabort=()=>{t.abort(),n=new Me});let r,o=null;if(e.timeout){const r=e.timeout;o=setTimeout((()=>{t.abort(),this._logger.log(qe.Warning,"Timeout from HTTP request."),n=new Le}),r)}try{r=await this._fetchType(e.url,{body:e.content,cache:"no-cache",credentials:!0===e.withCredentials?"include":"same-origin",headers:{"Content-Type":"text/plain;charset=UTF-8","X-Requested-With":"XMLHttpRequest",...e.headers},method:e.method,mode:"cors",redirect:"follow",signal:t.signal})}catch(e){if(n)throw n;throw this._logger.log(qe.Warning,`Error from HTTP request. ${e}.`),e}finally{o&&clearTimeout(o),e.abortSignal&&(e.abortSignal.onabort=null)}if(!r.ok){const e=await ut(r,"text");throw new Be(e||r.statusText,r.status)}const s=ut(r,e.responseType),i=await s;return new ze(r.status,r.statusText,i)}getCookieString(e){return""}}function ut(e,t){let n;switch(t){case"arraybuffer":n=e.arrayBuffer();break;case"text":n=e.text();break;case"blob":case"document":case"json":throw new Error(`${t} is not supported.`);default:n=e.text()}return n}class dt extends Je{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Me):e.method?e.url?new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open(e.method,e.url,!0),r.withCredentials=void 0===e.withCredentials||e.withCredentials,r.setRequestHeader("X-Requested-With","XMLHttpRequest"),r.setRequestHeader("Content-Type","text/plain;charset=UTF-8");const o=e.headers;o&&Object.keys(o).forEach((e=>{r.setRequestHeader(e,o[e])})),e.responseType&&(r.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=()=>{r.abort(),n(new Me)}),e.timeout&&(r.timeout=e.timeout),r.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),r.status>=200&&r.status<300?t(new ze(r.status,r.statusText,r.response||r.responseText)):n(new Be(r.response||r.responseText||r.statusText,r.status))},r.onerror=()=>{this._logger.log(qe.Warning,`Error from HTTP request. ${r.status}: ${r.statusText}.`),n(new Be(r.statusText,r.status))},r.ontimeout=()=>{this._logger.log(qe.Warning,"Timeout from HTTP request."),n(new Le)},r.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}}class pt extends Je{constructor(e){if(super(),"undefined"!=typeof fetch)this._httpClient=new ht(e);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");this._httpClient=new dt(e)}}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Me):e.method?e.url?this._httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}getCookieString(e){return this._httpClient.getCookieString(e)}}class ft{}ft.Authorization="Authorization",ft.Cookie="Cookie",function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(Ve||(Ve={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(Ke||(Ke={}));class gt{constructor(){this._isAborted=!1,this.onabort=null}abort(){this._isAborted||(this._isAborted=!0,this.onabort&&this.onabort())}get signal(){return this}get aborted(){return this._isAborted}}class mt{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._pollAbort=new gt,this._options=r,this._running=!1,this.onreceive=null,this.onclose=null}get pollAborted(){return this._pollAbort.aborted}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._url=e,this._logger.log(qe.Trace,"(LongPolling transport) Connecting."),t===Ke.Binary&&"undefined"!=typeof XMLHttpRequest&&"string"!=typeof(new XMLHttpRequest).responseType)throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");const[n,r]=st(),o={[n]:r,...this._options.headers},s={abortSignal:this._pollAbort.signal,headers:o,timeout:1e5,withCredentials:this._options.withCredentials};t===Ke.Binary&&(s.responseType="arraybuffer");const i=await this._getAccessToken();this._updateHeaderToken(s,i);const a=`${e}&_=${Date.now()}`;this._logger.log(qe.Trace,`(LongPolling transport) polling: ${a}.`);const c=await this._httpClient.get(a,s);200!==c.statusCode?(this._logger.log(qe.Error,`(LongPolling transport) Unexpected response code: ${c.statusCode}.`),this._closeError=new Be(c.statusText||"",c.statusCode),this._running=!1):this._running=!0,this._receiving=this._poll(this._url,s)}async _getAccessToken(){return this._accessTokenFactory?await this._accessTokenFactory():null}_updateHeaderToken(e,t){e.headers||(e.headers={}),t?e.headers[ft.Authorization]=`Bearer ${t}`:e.headers[ft.Authorization]&&delete e.headers[ft.Authorization]}async _poll(e,t){try{for(;this._running;){const n=await this._getAccessToken();this._updateHeaderToken(t,n);try{const n=`${e}&_=${Date.now()}`;this._logger.log(qe.Trace,`(LongPolling transport) polling: ${n}.`);const r=await this._httpClient.get(n,t);204===r.statusCode?(this._logger.log(qe.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):200!==r.statusCode?(this._logger.log(qe.Error,`(LongPolling transport) Unexpected response code: ${r.statusCode}.`),this._closeError=new Be(r.statusText||"",r.statusCode),this._running=!1):r.content?(this._logger.log(qe.Trace,`(LongPolling transport) data received. ${et(r.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(r.content)):this._logger.log(qe.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(e){this._running?e instanceof Le?this._logger.log(qe.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=e,this._running=!1):this._logger.log(qe.Trace,`(LongPolling transport) Poll errored after shutdown: ${e.message}`)}}}finally{this._logger.log(qe.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?nt(this._logger,"LongPolling",this._httpClient,this._url,this._accessTokenFactory,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}async stop(){this._logger.log(qe.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(qe.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);const e={},[t,n]=st();e[t]=n;const r={headers:{...e,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials},o=await this._getAccessToken();this._updateHeaderToken(r,o),await this._httpClient.delete(this._url,r),this._logger.log(qe.Trace,"(LongPolling transport) DELETE request sent.")}finally{this._logger.log(qe.Trace,"(LongPolling transport) Stop finished."),this._raiseOnClose()}}_raiseOnClose(){if(this.onclose){let e="(LongPolling transport) Firing onclose event.";this._closeError&&(e+=" Error: "+this._closeError),this._logger.log(qe.Trace,e),this.onclose(this._closeError)}}}class yt{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._options=r,this.onreceive=null,this.onclose=null}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._logger.log(qe.Trace,"(SSE transport) Connecting."),this._url=e,this._accessTokenFactory){const t=await this._accessTokenFactory();t&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(t)}`)}return new Promise(((n,r)=>{let o,s=!1;if(t===Ke.Text){if(Ze.isBrowser||Ze.isWebWorker)o=new this._options.EventSource(e,{withCredentials:this._options.withCredentials});else{const t=this._httpClient.getCookieString(e),n={};n.Cookie=t;const[r,s]=st();n[r]=s,o=new this._options.EventSource(e,{withCredentials:this._options.withCredentials,headers:{...n,...this._options.headers}})}try{o.onmessage=e=>{if(this.onreceive)try{this._logger.log(qe.Trace,`(SSE transport) data received. ${et(e.data,this._options.logMessageContent)}.`),this.onreceive(e.data)}catch(e){return void this._close(e)}},o.onerror=e=>{s?this._close():r(new Error("EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled."))},o.onopen=()=>{this._logger.log(qe.Information,`SSE connected to ${this._url}`),this._eventSource=o,s=!0,n()}}catch(e){return void r(e)}}else r(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"))}))}async send(e){return this._eventSource?nt(this._logger,"SSE",this._httpClient,this._url,this._accessTokenFactory,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}stop(){return this._close(),Promise.resolve()}_close(e){this._eventSource&&(this._eventSource.close(),this._eventSource=void 0,this.onclose&&this.onclose(e))}}class wt{constructor(e,t,n,r,o,s){this._logger=n,this._accessTokenFactory=t,this._logMessageContent=r,this._webSocketConstructor=o,this._httpClient=e,this.onreceive=null,this.onclose=null,this._headers=s}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._logger.log(qe.Trace,"(WebSockets transport) Connecting."),this._accessTokenFactory){const t=await this._accessTokenFactory();t&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(t)}`)}return new Promise(((n,r)=>{let o;e=e.replace(/^http/,"ws"),this._httpClient.getCookieString(e);let s=!1;o||(o=new this._webSocketConstructor(e)),t===Ke.Binary&&(o.binaryType="arraybuffer"),o.onopen=t=>{this._logger.log(qe.Information,`WebSocket connected to ${e}.`),this._webSocket=o,s=!0,n()},o.onerror=e=>{let t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:"There was an error with the transport",this._logger.log(qe.Information,`(WebSockets transport) ${t}.`)},o.onmessage=e=>{if(this._logger.log(qe.Trace,`(WebSockets transport) data received. ${et(e.data,this._logMessageContent)}.`),this.onreceive)try{this.onreceive(e.data)}catch(e){return void this._close(e)}},o.onclose=e=>{if(s)this._close(e);else{let t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:"WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.",r(new Error(t))}}}))}send(e){return this._webSocket&&this._webSocket.readyState===this._webSocketConstructor.OPEN?(this._logger.log(qe.Trace,`(WebSockets transport) sending data. ${et(e,this._logMessageContent)}.`),this._webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")}stop(){return this._webSocket&&this._close(void 0),Promise.resolve()}_close(e){this._webSocket&&(this._webSocket.onclose=()=>{},this._webSocket.onmessage=()=>{},this._webSocket.onerror=()=>{},this._webSocket.close(),this._webSocket=void 0),this._logger.log(qe.Trace,"(WebSockets transport) socket closed."),this.onclose&&(!this._isCloseEvent(e)||!1!==e.wasClean&&1e3===e.code?e instanceof Error?this.onclose(e):this.onclose():this.onclose(new Error(`WebSocket closed with status code: ${e.code} (${e.reason||"no reason given"}).`)))}_isCloseEvent(e){return e&&"boolean"==typeof e.wasClean&&"number"==typeof e.code}}class vt{constructor(e,t={}){var n;if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,Qe.isRequired(e,"url"),this._logger=void 0===(n=t.logger)?new ot(qe.Information):null===n?Ge.instance:void 0!==n.log?n:new ot(n),this.baseUrl=this._resolveUrl(e),(t=t||{}).logMessageContent=void 0!==t.logMessageContent&&t.logMessageContent,"boolean"!=typeof t.withCredentials&&void 0!==t.withCredentials)throw new Error("withCredentials option was not a 'boolean' or 'undefined' value");t.withCredentials=void 0===t.withCredentials||t.withCredentials,t.timeout=void 0===t.timeout?1e5:t.timeout,"undefined"==typeof WebSocket||t.WebSocket||(t.WebSocket=WebSocket),"undefined"==typeof EventSource||t.EventSource||(t.EventSource=EventSource),this._httpClient=t.httpClient||new pt(this._logger),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=t,this.onreceive=null,this.onclose=null}async start(e){if(e=e||Ke.Binary,Qe.isIn(e,Ke,"transferFormat"),this._logger.log(qe.Debug,`Starting connection with transfer format '${Ke[e]}'.`),"Disconnected"!==this._connectionState)return Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."));if(this._connectionState="Connecting",this._startInternalPromise=this._startInternal(e),await this._startInternalPromise,"Disconnecting"===this._connectionState){const e="Failed to start the HttpConnection before stop() was called.";return this._logger.log(qe.Error,e),await this._stopPromise,Promise.reject(new Error(e))}if("Connected"!==this._connectionState){const e="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!";return this._logger.log(qe.Error,e),Promise.reject(new Error(e))}this._connectionStarted=!0}send(e){return"Connected"!==this._connectionState?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this._sendQueue||(this._sendQueue=new bt(this.transport)),this._sendQueue.send(e))}async stop(e){return"Disconnected"===this._connectionState?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve()):"Disconnecting"===this._connectionState?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState="Disconnecting",this._stopPromise=new Promise((e=>{this._stopPromiseResolver=e})),await this._stopInternal(e),void await this._stopPromise)}async _stopInternal(e){this._stopError=e;try{await this._startInternalPromise}catch(e){}if(this.transport){try{await this.transport.stop()}catch(e){this._logger.log(qe.Error,`HttpConnection.transport.stop() threw error '${e}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(qe.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.")}async _startInternal(e){let t=this.baseUrl;this._accessTokenFactory=this._options.accessTokenFactory;try{if(this._options.skipNegotiation){if(this._options.transport!==Ve.WebSockets)throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");this.transport=this._constructTransport(Ve.WebSockets),await this._startTransport(t,e)}else{let n=null,r=0;do{if(n=await this._getNegotiationResponse(t),"Disconnecting"===this._connectionState||"Disconnected"===this._connectionState)throw new Error("The connection was stopped during negotiation.");if(n.error)throw new Error(n.error);if(n.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");if(n.url&&(t=n.url),n.accessToken){const e=n.accessToken;this._accessTokenFactory=()=>e}r++}while(n.url&&r<100);if(100===r&&n.url)throw new Error("Negotiate redirection limit exceeded.");await this._createTransport(t,this._options.transport,n,e)}this.transport instanceof mt&&(this.features.inherentKeepAlive=!0),"Connecting"===this._connectionState&&(this._logger.log(qe.Debug,"The HttpConnection connected successfully."),this._connectionState="Connected")}catch(e){return this._logger.log(qe.Error,"Failed to start the connection: "+e),this._connectionState="Disconnected",this.transport=void 0,this._stopPromiseResolver(),Promise.reject(e)}}async _getNegotiationResponse(e){const t={};if(this._accessTokenFactory){const e=await this._accessTokenFactory();e&&(t[ft.Authorization]=`Bearer ${e}`)}const[n,r]=st();t[n]=r;const o=this._resolveNegotiateUrl(e);this._logger.log(qe.Debug,`Sending negotiation request: ${o}.`);try{const e=await this._httpClient.post(o,{content:"",headers:{...t,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials});if(200!==e.statusCode)return Promise.reject(new Error(`Unexpected status code returned from negotiate '${e.statusCode}'`));const n=JSON.parse(e.content);return(!n.negotiateVersion||n.negotiateVersion<1)&&(n.connectionToken=n.connectionId),n}catch(e){let t="Failed to complete negotiation with the server: "+e;return e instanceof Be&&404===e.statusCode&&(t+=" Either this is not a SignalR endpoint or there is a proxy blocking the connection."),this._logger.log(qe.Error,t),Promise.reject(new je(t))}}_createConnectUrl(e,t){return t?e+(-1===e.indexOf("?")?"?":"&")+`id=${t}`:e}async _createTransport(e,t,n,r){let o=this._createConnectUrl(e,n.connectionToken);if(this._isITransport(t))return this._logger.log(qe.Debug,"Connection was provided an instance of ITransport, using that directly."),this.transport=t,await this._startTransport(o,r),void(this.connectionId=n.connectionId);const s=[],i=n.availableTransports||[];let a=n;for(const n of i){const i=this._resolveTransportOrError(n,t,r);if(i instanceof Error)s.push(`${n.transport} failed:`),s.push(i);else if(this._isITransport(i)){if(this.transport=i,!a){try{a=await this._getNegotiationResponse(e)}catch(e){return Promise.reject(e)}o=this._createConnectUrl(e,a.connectionToken)}try{return await this._startTransport(o,r),void(this.connectionId=a.connectionId)}catch(e){if(this._logger.log(qe.Error,`Failed to start the transport '${n.transport}': ${e}`),a=void 0,s.push(new He(`${n.transport} failed: ${e}`,Ve[n.transport])),"Connecting"!==this._connectionState){const e="Failed to select transport before stop() was called.";return this._logger.log(qe.Debug,e),Promise.reject(new Error(e))}}}}return s.length>0?Promise.reject(new We(`Unable to connect to the server with any of the available transports. ${s.join(" ")}`,s)):Promise.reject(new Error("None of the transports supported by the client are supported by the server."))}_constructTransport(e){switch(e){case Ve.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new wt(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case Ve.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new yt(this._httpClient,this._accessTokenFactory,this._logger,this._options);case Ve.LongPolling:return new mt(this._httpClient,this._accessTokenFactory,this._logger,this._options);default:throw new Error(`Unknown transport: ${e}.`)}}_startTransport(e,t){return this.transport.onreceive=this.onreceive,this.transport.onclose=e=>this._stopConnection(e),this.transport.connect(e,t)}_resolveTransportOrError(e,t,n){const r=Ve[e.transport];if(null==r)return this._logger.log(qe.Debug,`Skipping transport '${e.transport}' because it is not supported by this client.`),new Error(`Skipping transport '${e.transport}' because it is not supported by this client.`);if(!function(e,t){return!e||0!=(t&e)}(t,r))return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it was disabled by the client.`),new Fe(`'${Ve[r]}' is disabled by the client.`,r);if(!(e.transferFormats.map((e=>Ke[e])).indexOf(n)>=0))return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it does not support the requested transfer format '${Ke[n]}'.`),new Error(`'${Ve[r]}' does not support ${Ke[n]}.`);if(r===Ve.WebSockets&&!this._options.WebSocket||r===Ve.ServerSentEvents&&!this._options.EventSource)return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it is not supported in your environment.'`),new Oe(`'${Ve[r]}' is not supported in your environment.`,r);this._logger.log(qe.Debug,`Selecting transport '${Ve[r]}'.`);try{return this._constructTransport(r)}catch(e){return e}}_isITransport(e){return e&&"object"==typeof e&&"connect"in e}_stopConnection(e){if(this._logger.log(qe.Debug,`HttpConnection.stopConnection(${e}) called while in state ${this._connectionState}.`),this.transport=void 0,e=this._stopError||e,this._stopError=void 0,"Disconnected"!==this._connectionState){if("Connecting"===this._connectionState)throw this._logger.log(qe.Warning,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is still in the connecting state.`),new Error(`HttpConnection.stopConnection(${e}) was called while the connection is still in the connecting state.`);if("Disconnecting"===this._connectionState&&this._stopPromiseResolver(),e?this._logger.log(qe.Error,`Connection disconnected with error '${e}'.`):this._logger.log(qe.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch((e=>{this._logger.log(qe.Error,`TransportSendQueue.stop() threw error '${e}'.`)})),this._sendQueue=void 0),this.connectionId=void 0,this._connectionState="Disconnected",this._connectionStarted){this._connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(t){this._logger.log(qe.Error,`HttpConnection.onclose(${e}) threw error '${t}'.`)}}}else this._logger.log(qe.Debug,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is already in the disconnected state.`)}_resolveUrl(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!Ze.isBrowser||!window.document)throw new Error(`Cannot resolve '${e}'.`);const t=window.document.createElement("a");return t.href=e,this._logger.log(qe.Information,`Normalizing '${e}' to '${t.href}'.`),t.href}_resolveNegotiateUrl(e){const t=e.indexOf("?");let n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",n+=-1===t?"":e.substring(t),-1===n.indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this._negotiateVersion),n}}class bt{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new _t,this._transportResult=new _t,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new _t),this._transportResult.promise}stop(){return this._executing=!1,this._sendBufferedData.resolve(),this._sendLoopPromise}_bufferData(e){if(this._buffer.length&&typeof this._buffer[0]!=typeof e)throw new Error(`Expected data to be of type ${typeof this._buffer} but was of type ${typeof e}`);this._buffer.push(e),this._sendBufferedData.resolve()}async _sendLoop(){for(;;){if(await this._sendBufferedData.promise,!this._executing){this._transportResult&&this._transportResult.reject("Connection stopped.");break}this._sendBufferedData=new _t;const e=this._transportResult;this._transportResult=void 0;const t="string"==typeof this._buffer[0]?this._buffer.join(""):bt._concatBuffers(this._buffer);this._buffer.length=0;try{await this._transport.send(t),e.resolve()}catch(t){e.reject(t)}}}static _concatBuffers(e){const t=e.map((e=>e.byteLength)).reduce(((e,t)=>e+t)),n=new Uint8Array(t);let r=0;for(const t of e)n.set(new Uint8Array(t),r),r+=t.byteLength;return n.buffer}}class _t{constructor(){this.promise=new Promise(((e,t)=>[this._resolver,this._rejecter]=[e,t]))}resolve(){this._resolver()}reject(e){this._rejecter(e)}}class Et{static write(e){return`${e}${Et.RecordSeparator}`}static parse(e){if(e[e.length-1]!==Et.RecordSeparator)throw new Error("Message is incomplete.");const t=e.split(Et.RecordSeparator);return t.pop(),t}}Et.RecordSeparatorCode=30,Et.RecordSeparator=String.fromCharCode(Et.RecordSeparatorCode);class St{writeHandshakeRequest(e){return Et.write(JSON.stringify(e))}parseHandshakeResponse(e){let t,n;if(tt(e)){const r=new Uint8Array(e),o=r.indexOf(Et.RecordSeparatorCode);if(-1===o)throw new Error("Message is incomplete.");const s=o+1;t=String.fromCharCode.apply(null,Array.prototype.slice.call(r.slice(0,s))),n=r.byteLength>s?r.slice(s).buffer:null}else{const r=e,o=r.indexOf(Et.RecordSeparator);if(-1===o)throw new Error("Message is incomplete.");const s=o+1;t=r.substring(0,s),n=r.length>s?r.substring(s):null}const r=Et.parse(t),o=JSON.parse(r[0]);if(o.type)throw new Error("Expected a handshake response from the server.");return[n,o]}}!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"}(Xe||(Xe={}));class Ct{constructor(){this.observers=[]}next(e){for(const t of this.observers)t.next(e)}error(e){for(const t of this.observers)t.error&&t.error(e)}complete(){for(const e of this.observers)e.complete&&e.complete()}subscribe(e){return this.observers.push(e),new rt(this,e)}}!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(Ye||(Ye={}));class It{constructor(e,t,n,r){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(qe.Warning,"The page is being frozen, this will likely lead to the connection being closed and messages being lost. For more information see the docs at https://docs.microsoft.com/aspnet/core/signalr/javascript-client#bsleep")},Qe.isRequired(e,"connection"),Qe.isRequired(t,"logger"),Qe.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=3e4,this.keepAliveIntervalInMilliseconds=15e3,this._logger=t,this._protocol=n,this.connection=e,this._reconnectPolicy=r,this._handshakeProtocol=new St,this.connection.onreceive=e=>this._processIncomingData(e),this.connection.onclose=e=>this._connectionClosed(e),this._callbacks={},this._methods={},this._closedCallbacks=[],this._reconnectingCallbacks=[],this._reconnectedCallbacks=[],this._invocationId=0,this._receivedHandshakeResponse=!1,this._connectionState=Ye.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:Xe.Ping})}static create(e,t,n,r){return new It(e,t,n,r)}get state(){return this._connectionState}get connectionId(){return this.connection&&this.connection.connectionId||null}get baseUrl(){return this.connection.baseUrl||""}set baseUrl(e){if(this._connectionState!==Ye.Disconnected&&this._connectionState!==Ye.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e}start(){return this._startPromise=this._startWithStateTransitions(),this._startPromise}async _startWithStateTransitions(){if(this._connectionState!==Ye.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=Ye.Connecting,this._logger.log(qe.Debug,"Starting HubConnection.");try{await this._startInternal(),Ze.isBrowser&&document&&document.addEventListener("freeze",this._freezeEventListener),this._connectionState=Ye.Connected,this._connectionStarted=!0,this._logger.log(qe.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=Ye.Disconnected,this._logger.log(qe.Debug,`HubConnection failed to start successfully because of error '${e}'.`),Promise.reject(e)}}async _startInternal(){this._stopDuringStartError=void 0,this._receivedHandshakeResponse=!1;const e=new Promise(((e,t)=>{this._handshakeResolver=e,this._handshakeRejecter=t}));await this.connection.start(this._protocol.transferFormat);try{const t={protocol:this._protocol.name,version:this._protocol.version};if(this._logger.log(qe.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(t)),this._logger.log(qe.Information,`Using HubProtocol '${this._protocol.name}'.`),this._cleanupTimeout(),this._resetTimeoutPeriod(),this._resetKeepAliveInterval(),await e,this._stopDuringStartError)throw this._stopDuringStartError}catch(e){throw this._logger.log(qe.Debug,`Hub handshake failed with error '${e}' during start(). Stopping HubConnection.`),this._cleanupTimeout(),this._cleanupPingTimer(),await this.connection.stop(e),e}}async stop(){const e=this._startPromise;this._stopPromise=this._stopInternal(),await this._stopPromise;try{await e}catch(e){}}_stopInternal(e){return this._connectionState===Ye.Disconnected?(this._logger.log(qe.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve()):this._connectionState===Ye.Disconnecting?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState=Ye.Disconnecting,this._logger.log(qe.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(qe.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this._reconnectDelayHandle),this._reconnectDelayHandle=void 0,this._completeClose(),Promise.resolve()):(this._cleanupTimeout(),this._cleanupPingTimer(),this._stopDuringStartError=e||new Error("The connection was stopped before the hub handshake could complete."),this.connection.stop(e)))}stream(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._createStreamInvocation(e,t,r);let s;const i=new Ct;return i.cancelCallback=()=>{const e=this._createCancelInvocation(o.invocationId);return delete this._callbacks[o.invocationId],s.then((()=>this._sendWithProtocol(e)))},this._callbacks[o.invocationId]=(e,t)=>{t?i.error(t):e&&(e.type===Xe.Completion?e.error?i.error(new Error(e.error)):i.complete():i.next(e.item))},s=this._sendWithProtocol(o).catch((e=>{i.error(e),delete this._callbacks[o.invocationId]})),this._launchStreams(n,s),i}_sendMessage(e){return this._resetKeepAliveInterval(),this.connection.send(e)}_sendWithProtocol(e){return this._sendMessage(this._protocol.writeMessage(e))}send(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._sendWithProtocol(this._createInvocation(e,t,!0,r));return this._launchStreams(n,o),o}invoke(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._createInvocation(e,t,!1,r);return new Promise(((e,t)=>{this._callbacks[o.invocationId]=(n,r)=>{r?t(r):n&&(n.type===Xe.Completion?n.error?t(new Error(n.error)):e(n.result):t(new Error(`Unexpected message type: ${n.type}`)))};const r=this._sendWithProtocol(o).catch((e=>{t(e),delete this._callbacks[o.invocationId]}));this._launchStreams(n,r)}))}on(e,t){e&&t&&(e=e.toLowerCase(),this._methods[e]||(this._methods[e]=[]),-1===this._methods[e].indexOf(t)&&this._methods[e].push(t))}off(e,t){if(!e)return;e=e.toLowerCase();const n=this._methods[e];if(n)if(t){const r=n.indexOf(t);-1!==r&&(n.splice(r,1),0===n.length&&delete this._methods[e])}else delete this._methods[e]}onclose(e){e&&this._closedCallbacks.push(e)}onreconnecting(e){e&&this._reconnectingCallbacks.push(e)}onreconnected(e){e&&this._reconnectedCallbacks.push(e)}_processIncomingData(e){if(this._cleanupTimeout(),this._receivedHandshakeResponse||(e=this._processHandshakeResponse(e),this._receivedHandshakeResponse=!0),e){const t=this._protocol.parseMessages(e,this._logger);for(const e of t)switch(e.type){case Xe.Invocation:this._invokeClientMethod(e);break;case Xe.StreamItem:case Xe.Completion:{const t=this._callbacks[e.invocationId];if(t){e.type===Xe.Completion&&delete this._callbacks[e.invocationId];try{t(e)}catch(e){this._logger.log(qe.Error,`Stream callback threw error: ${lt(e)}`)}}break}case Xe.Ping:break;case Xe.Close:{this._logger.log(qe.Information,"Close message received from server.");const t=e.error?new Error("Server returned an error on close: "+e.error):void 0;!0===e.allowReconnect?this.connection.stop(t):this._stopPromise=this._stopInternal(t);break}default:this._logger.log(qe.Warning,`Invalid message type: ${e.type}.`)}}this._resetTimeoutPeriod()}_processHandshakeResponse(e){let t,n;try{[n,t]=this._handshakeProtocol.parseHandshakeResponse(e)}catch(e){const t="Error parsing handshake response: "+e;this._logger.log(qe.Error,t);const n=new Error(t);throw this._handshakeRejecter(n),n}if(t.error){const e="Server returned handshake error: "+t.error;this._logger.log(qe.Error,e);const n=new Error(e);throw this._handshakeRejecter(n),n}return this._logger.log(qe.Debug,"Server handshake complete."),this._handshakeResolver(),n}_resetKeepAliveInterval(){this.connection.features.inherentKeepAlive||(this._nextKeepAlive=(new Date).getTime()+this.keepAliveIntervalInMilliseconds,this._cleanupPingTimer())}_resetTimeoutPeriod(){if(!(this.connection.features&&this.connection.features.inherentKeepAlive||(this._timeoutHandle=setTimeout((()=>this.serverTimeout()),this.serverTimeoutInMilliseconds),void 0!==this._pingServerHandle))){let e=this._nextKeepAlive-(new Date).getTime();e<0&&(e=0),this._pingServerHandle=setTimeout((async()=>{if(this._connectionState===Ye.Connected)try{await this._sendMessage(this._cachedPingMessage)}catch{this._cleanupPingTimer()}}),e)}}serverTimeout(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))}_invokeClientMethod(e){const t=this._methods[e.target.toLowerCase()];if(t){try{t.forEach((t=>t.apply(this,e.arguments)))}catch(t){this._logger.log(qe.Error,`A callback for the method ${e.target.toLowerCase()} threw error '${t}'.`)}if(e.invocationId){const e="Server requested a response, which is not supported in this version of the client.";this._logger.log(qe.Error,e),this._stopPromise=this._stopInternal(new Error(e))}}else this._logger.log(qe.Warning,`No client method with the name '${e.target}' found.`)}_connectionClosed(e){this._logger.log(qe.Debug,`HubConnection.connectionClosed(${e}) called while in state ${this._connectionState}.`),this._stopDuringStartError=this._stopDuringStartError||e||new Error("The underlying connection was closed before the hub handshake could complete."),this._handshakeResolver&&this._handshakeResolver(),this._cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this._cleanupTimeout(),this._cleanupPingTimer(),this._connectionState===Ye.Disconnecting?this._completeClose(e):this._connectionState===Ye.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===Ye.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=Ye.Disconnected,this._connectionStarted=!1,Ze.isBrowser&&document&&document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(qe.Error,`An onclose callback called with error '${e}' threw error '${t}'.`)}}}async _reconnect(e){const t=Date.now();let n=0,r=void 0!==e?e:new Error("Attempting to reconnect due to a unknown error."),o=this._getNextRetryDelay(n++,0,r);if(null===o)return this._logger.log(qe.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),void this._completeClose(e);if(this._connectionState=Ye.Reconnecting,e?this._logger.log(qe.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(qe.Information,"Connection reconnecting."),0!==this._reconnectingCallbacks.length){try{this._reconnectingCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(qe.Error,`An onreconnecting callback called with error '${e}' threw error '${t}'.`)}if(this._connectionState!==Ye.Reconnecting)return void this._logger.log(qe.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.")}for(;null!==o;){if(this._logger.log(qe.Information,`Reconnect attempt number ${n} will start in ${o} ms.`),await new Promise((e=>{this._reconnectDelayHandle=setTimeout(e,o)})),this._reconnectDelayHandle=void 0,this._connectionState!==Ye.Reconnecting)return void this._logger.log(qe.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");try{if(await this._startInternal(),this._connectionState=Ye.Connected,this._logger.log(qe.Information,"HubConnection reconnected successfully."),0!==this._reconnectedCallbacks.length)try{this._reconnectedCallbacks.forEach((e=>e.apply(this,[this.connection.connectionId])))}catch(e){this._logger.log(qe.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${e}'.`)}return}catch(e){if(this._logger.log(qe.Information,`Reconnect attempt failed because of error '${e}'.`),this._connectionState!==Ye.Reconnecting)return this._logger.log(qe.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),void(this._connectionState===Ye.Disconnecting&&this._completeClose());r=e instanceof Error?e:new Error(e.toString()),o=this._getNextRetryDelay(n++,Date.now()-t,r)}}this._logger.log(qe.Information,`Reconnect retries have been exhausted after ${Date.now()-t} ms and ${n} failed attempts. Connection disconnecting.`),this._completeClose()}_getNextRetryDelay(e,t,n){try{return this._reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:t,previousRetryCount:e,retryReason:n})}catch(n){return this._logger.log(qe.Error,`IRetryPolicy.nextRetryDelayInMilliseconds(${e}, ${t}) threw error '${n}'.`),null}}_cancelCallbacksWithError(e){const t=this._callbacks;this._callbacks={},Object.keys(t).forEach((n=>{const r=t[n];try{r(null,e)}catch(t){this._logger.log(qe.Error,`Stream 'error' callback called with '${e}' threw error: ${lt(t)}`)}}))}_cleanupPingTimer(){this._pingServerHandle&&(clearTimeout(this._pingServerHandle),this._pingServerHandle=void 0)}_cleanupTimeout(){this._timeoutHandle&&clearTimeout(this._timeoutHandle)}_createInvocation(e,t,n,r){if(n)return 0!==r.length?{arguments:t,streamIds:r,target:e,type:Xe.Invocation}:{arguments:t,target:e,type:Xe.Invocation};{const n=this._invocationId;return this._invocationId++,0!==r.length?{arguments:t,invocationId:n.toString(),streamIds:r,target:e,type:Xe.Invocation}:{arguments:t,invocationId:n.toString(),target:e,type:Xe.Invocation}}}_launchStreams(e,t){if(0!==e.length){t||(t=Promise.resolve());for(const n in e)e[n].subscribe({complete:()=>{t=t.then((()=>this._sendWithProtocol(this._createCompletionMessage(n))))},error:e=>{let r;r=e instanceof Error?e.message:e&&e.toString?e.toString():"Unknown error",t=t.then((()=>this._sendWithProtocol(this._createCompletionMessage(n,r))))},next:e=>{t=t.then((()=>this._sendWithProtocol(this._createStreamItemMessage(n,e))))}})}}_replaceStreamingParams(e){const t=[],n=[];for(let r=0;r=55296&&o<=56319&&r65535&&(h-=65536,s.push(h>>>10&1023|55296),h=56320|1023&h),s.push(h)}else s.push(a);s.length>=4096&&(i+=String.fromCharCode.apply(String,s),s.length=0)}return s.length>0&&(i+=String.fromCharCode.apply(String,s)),i}var Mt,Ot=Ut?new TextDecoder:null,Ft=Ut?"undefined"!=typeof process&&"force"!==process.env.TEXT_DECODER?200:0:xt,Ht=function(e,t){this.type=e,this.data=t},jt=(Mt=function(e,t){return(Mt=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}Mt(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Wt=function(e){function t(n){var r=e.call(this,n)||this,o=Object.create(t.prototype);return Object.setPrototypeOf(r,o),Object.defineProperty(r,"name",{configurable:!0,enumerable:!1,value:t.name}),r}return jt(t,e),t}(Error),zt={type:-1,encode:function(e){var t,n,r,o;return e instanceof Date?function(e){var t,n=e.sec,r=e.nsec;if(n>=0&&r>=0&&n<=17179869183){if(0===r&&n<=4294967295){var o=new Uint8Array(4);return(t=new DataView(o.buffer)).setUint32(0,n),o}var s=n/4294967296,i=4294967295&n;return o=new Uint8Array(8),(t=new DataView(o.buffer)).setUint32(0,r<<2|3&s),t.setUint32(4,i),o}return o=new Uint8Array(12),(t=new DataView(o.buffer)).setUint32(0,r),Rt(t,4,n),o}((r=1e6*((t=e.getTime())-1e3*(n=Math.floor(t/1e3))),{sec:n+(o=Math.floor(r/1e9)),nsec:r-1e9*o})):null},decode:function(e){var t=function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);switch(e.byteLength){case 4:return{sec:t.getUint32(0),nsec:0};case 8:var n=t.getUint32(0);return{sec:4294967296*(3&n)+t.getUint32(4),nsec:n>>>2};case 12:return{sec:Pt(t,4),nsec:t.getUint32(0)};default:throw new Wt("Unrecognized data size for timestamp (expected 4, 8, or 12): "+e.length)}}(e);return new Date(1e3*t.sec+t.nsec/1e6)}},Jt=function(){function e(){this.builtInEncoders=[],this.builtInDecoders=[],this.encoders=[],this.decoders=[],this.register(zt)}return e.prototype.register=function(e){var t=e.type,n=e.encode,r=e.decode;if(t>=0)this.encoders[t]=n,this.decoders[t]=r;else{var o=1+t;this.builtInEncoders[o]=n,this.builtInDecoders[o]=r}},e.prototype.tryToEncode=function(e,t){for(var n=0;nthis.maxDepth)throw new Error("Too deep objects in depth "+t);null==e?this.encodeNil():"boolean"==typeof e?this.encodeBoolean(e):"number"==typeof e?this.encodeNumber(e):"string"==typeof e?this.encodeString(e):this.encodeObject(e,t)},e.prototype.ensureBufferSizeToWrite=function(e){var t=this.pos+e;this.view.byteLength=0?e<128?this.writeU8(e):e<256?(this.writeU8(204),this.writeU8(e)):e<65536?(this.writeU8(205),this.writeU16(e)):e<4294967296?(this.writeU8(206),this.writeU32(e)):(this.writeU8(207),this.writeU64(e)):e>=-32?this.writeU8(224|e+32):e>=-128?(this.writeU8(208),this.writeI8(e)):e>=-32768?(this.writeU8(209),this.writeI16(e)):e>=-2147483648?(this.writeU8(210),this.writeI32(e)):(this.writeU8(211),this.writeI64(e)):this.forceFloat32?(this.writeU8(202),this.writeF32(e)):(this.writeU8(203),this.writeF64(e))},e.prototype.writeStringHeader=function(e){if(e<32)this.writeU8(160+e);else if(e<256)this.writeU8(217),this.writeU8(e);else if(e<65536)this.writeU8(218),this.writeU16(e);else{if(!(e<4294967296))throw new Error("Too long string: "+e+" bytes in UTF-8");this.writeU8(219),this.writeU32(e)}},e.prototype.encodeString=function(e){if(e.length>$t){var t=At(e);this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),Bt(e,this.bytes,this.pos),this.pos+=t}else t=At(e),this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),function(e,t,n){for(var r=e.length,o=n,s=0;s>6&31|192;else{if(i>=55296&&i<=56319&&s>12&15|224,t[o++]=i>>6&63|128):(t[o++]=i>>18&7|240,t[o++]=i>>12&63|128,t[o++]=i>>6&63|128)}t[o++]=63&i|128}else t[o++]=i}}(e,this.bytes,this.pos),this.pos+=t},e.prototype.encodeObject=function(e,t){var n=this.extensionCodec.tryToEncode(e,this.context);if(null!=n)this.encodeExtension(n);else if(Array.isArray(e))this.encodeArray(e,t);else if(ArrayBuffer.isView(e))this.encodeBinary(e);else{if("object"!=typeof e)throw new Error("Unrecognized object: "+Object.prototype.toString.apply(e));this.encodeMap(e,t)}},e.prototype.encodeBinary=function(e){var t=e.byteLength;if(t<256)this.writeU8(196),this.writeU8(t);else if(t<65536)this.writeU8(197),this.writeU16(t);else{if(!(t<4294967296))throw new Error("Too large binary: "+t);this.writeU8(198),this.writeU32(t)}var n=qt(e);this.writeU8a(n)},e.prototype.encodeArray=function(e,t){var n=e.length;if(n<16)this.writeU8(144+n);else if(n<65536)this.writeU8(220),this.writeU16(n);else{if(!(n<4294967296))throw new Error("Too large array: "+n);this.writeU8(221),this.writeU32(n)}for(var r=0,o=e;r0&&e<=this.maxKeyLength},e.prototype.find=function(e,t,n){e:for(var r=0,o=this.caches[n-1];r=this.maxLengthPerKey?n[Math.random()*n.length|0]=r:n.push(r)},e.prototype.decode=function(e,t,n){var r=this.find(e,t,n);if(null!=r)return this.hit++,r;this.miss++;var o=Lt(e,t,n),s=Uint8Array.prototype.slice.call(e,t,t+n);return this.store(s,o),o},e}(),Yt=function(e,t){var n,r,o,s,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return s={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(s[Symbol.iterator]=function(){return this}),s;function a(s){return function(a){return function(s){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(o=2&s[0]?r.return:s[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,s[1])).done)return o;switch(r=0,o&&(s=[2&s[0],o.value]),s[0]){case 0:case 1:o=s;break;case 4:return i.label++,{value:s[1],done:!1};case 5:i.label++,r=s[1],s=[0];continue;case 7:s=i.ops.pop(),i.trys.pop();continue;default:if(!((o=(o=i.trys).length>0&&o[o.length-1])||6!==s[0]&&2!==s[0])){i=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]1||a(e,t)}))})}function a(e,t){try{(n=o[e](t)).value instanceof Qt?Promise.resolve(n.value.v).then(c,l):h(s[0][2],n)}catch(e){h(s[0][3],e)}var n}function c(e){a("next",e)}function l(e){a("throw",e)}function h(e,t){e(t),s.shift(),s.length&&a(s[0][0],s[0][1])}},en=new DataView(new ArrayBuffer(0)),tn=new Uint8Array(en.buffer),nn=function(){try{en.getInt8(0)}catch(e){return e.constructor}throw new Error("never reached")}(),rn=new nn("Insufficient data"),on=new Xt,sn=function(){function e(e,t,n,r,o,s,i,a){void 0===e&&(e=Jt.defaultCodec),void 0===t&&(t=void 0),void 0===n&&(n=xt),void 0===r&&(r=xt),void 0===o&&(o=xt),void 0===s&&(s=xt),void 0===i&&(i=xt),void 0===a&&(a=on),this.extensionCodec=e,this.context=t,this.maxStrLength=n,this.maxBinLength=r,this.maxArrayLength=o,this.maxMapLength=s,this.maxExtLength=i,this.keyDecoder=a,this.totalPos=0,this.pos=0,this.view=en,this.bytes=tn,this.headByte=-1,this.stack=[]}return e.prototype.reinitializeState=function(){this.totalPos=0,this.headByte=-1,this.stack.length=0},e.prototype.setBuffer=function(e){this.bytes=qt(e),this.view=function(e){if(e instanceof ArrayBuffer)return new DataView(e);var t=qt(e);return new DataView(t.buffer,t.byteOffset,t.byteLength)}(this.bytes),this.pos=0},e.prototype.appendBuffer=function(e){if(-1!==this.headByte||this.hasRemaining(1)){var t=this.bytes.subarray(this.pos),n=qt(e),r=new Uint8Array(t.length+n.length);r.set(t),r.set(n,t.length),this.setBuffer(r)}else this.setBuffer(e)},e.prototype.hasRemaining=function(e){return this.view.byteLength-this.pos>=e},e.prototype.createExtraByteError=function(e){var t=this.view,n=this.pos;return new RangeError("Extra "+(t.byteLength-n)+" of "+t.byteLength+" byte(s) found at buffer["+e+"]")},e.prototype.decode=function(e){this.reinitializeState(),this.setBuffer(e);var t=this.doDecodeSync();if(this.hasRemaining(1))throw this.createExtraByteError(this.pos);return t},e.prototype.decodeMulti=function(e){return Yt(this,(function(t){switch(t.label){case 0:this.reinitializeState(),this.setBuffer(e),t.label=1;case 1:return this.hasRemaining(1)?[4,this.doDecodeSync()]:[3,3];case 2:return t.sent(),[3,1];case 3:return[2]}}))},e.prototype.decodeAsync=function(e){var t,n,r,o,s,i,a;return s=this,void 0,a=function(){var s,i,a,c,l,h,u,d;return Yt(this,(function(p){switch(p.label){case 0:s=!1,p.label=1;case 1:p.trys.push([1,6,7,12]),t=Gt(e),p.label=2;case 2:return[4,t.next()];case 3:if((n=p.sent()).done)return[3,5];if(a=n.value,s)throw this.createExtraByteError(this.totalPos);this.appendBuffer(a);try{i=this.doDecodeSync(),s=!0}catch(e){if(!(e instanceof nn))throw e}this.totalPos+=this.pos,p.label=4;case 4:return[3,2];case 5:return[3,12];case 6:return c=p.sent(),r={error:c},[3,12];case 7:return p.trys.push([7,,10,11]),n&&!n.done&&(o=t.return)?[4,o.call(t)]:[3,9];case 8:p.sent(),p.label=9;case 9:return[3,11];case 10:if(r)throw r.error;return[7];case 11:return[7];case 12:if(s){if(this.hasRemaining(1))throw this.createExtraByteError(this.totalPos);return[2,i]}throw h=(l=this).headByte,u=l.pos,d=l.totalPos,new RangeError("Insufficient data in parsing "+Kt(h)+" at "+d+" ("+u+" in the current buffer)")}}))},new((i=void 0)||(i=Promise))((function(e,t){function n(e){try{o(a.next(e))}catch(e){t(e)}}function r(e){try{o(a.throw(e))}catch(e){t(e)}}function o(t){var o;t.done?e(t.value):(o=t.value,o instanceof i?o:new i((function(e){e(o)}))).then(n,r)}o((a=a.apply(s,[])).next())}))},e.prototype.decodeArrayStream=function(e){return this.decodeMultiAsync(e,!0)},e.prototype.decodeStream=function(e){return this.decodeMultiAsync(e,!1)},e.prototype.decodeMultiAsync=function(e,t){return Zt(this,arguments,(function(){var n,r,o,s,i,a,c,l,h;return Yt(this,(function(u){switch(u.label){case 0:n=t,r=-1,u.label=1;case 1:u.trys.push([1,13,14,19]),o=Gt(e),u.label=2;case 2:return[4,Qt(o.next())];case 3:if((s=u.sent()).done)return[3,12];if(i=s.value,t&&0===r)throw this.createExtraByteError(this.totalPos);this.appendBuffer(i),n&&(r=this.readArraySize(),n=!1,this.complete()),u.label=4;case 4:u.trys.push([4,9,,10]),u.label=5;case 5:return[4,Qt(this.doDecodeSync())];case 6:return[4,u.sent()];case 7:return u.sent(),0==--r?[3,8]:[3,5];case 8:return[3,10];case 9:if(!((a=u.sent())instanceof nn))throw a;return[3,10];case 10:this.totalPos+=this.pos,u.label=11;case 11:return[3,2];case 12:return[3,19];case 13:return c=u.sent(),l={error:c},[3,19];case 14:return u.trys.push([14,,17,18]),s&&!s.done&&(h=o.return)?[4,Qt(h.call(o))]:[3,16];case 15:u.sent(),u.label=16;case 16:return[3,18];case 17:if(l)throw l.error;return[7];case 18:return[7];case 19:return[2]}}))}))},e.prototype.doDecodeSync=function(){e:for(;;){var e=this.readHeadByte(),t=void 0;if(e>=224)t=e-256;else if(e<192)if(e<128)t=e;else if(e<144){if(0!=(r=e-128)){this.pushMapState(r),this.complete();continue e}t={}}else if(e<160){if(0!=(r=e-144)){this.pushArrayState(r),this.complete();continue e}t=[]}else{var n=e-160;t=this.decodeUtf8String(n,0)}else if(192===e)t=null;else if(194===e)t=!1;else if(195===e)t=!0;else if(202===e)t=this.readF32();else if(203===e)t=this.readF64();else if(204===e)t=this.readU8();else if(205===e)t=this.readU16();else if(206===e)t=this.readU32();else if(207===e)t=this.readU64();else if(208===e)t=this.readI8();else if(209===e)t=this.readI16();else if(210===e)t=this.readI32();else if(211===e)t=this.readI64();else if(217===e)n=this.lookU8(),t=this.decodeUtf8String(n,1);else if(218===e)n=this.lookU16(),t=this.decodeUtf8String(n,2);else if(219===e)n=this.lookU32(),t=this.decodeUtf8String(n,4);else if(220===e){if(0!==(r=this.readU16())){this.pushArrayState(r),this.complete();continue e}t=[]}else if(221===e){if(0!==(r=this.readU32())){this.pushArrayState(r),this.complete();continue e}t=[]}else if(222===e){if(0!==(r=this.readU16())){this.pushMapState(r),this.complete();continue e}t={}}else if(223===e){if(0!==(r=this.readU32())){this.pushMapState(r),this.complete();continue e}t={}}else if(196===e){var r=this.lookU8();t=this.decodeBinary(r,1)}else if(197===e)r=this.lookU16(),t=this.decodeBinary(r,2);else if(198===e)r=this.lookU32(),t=this.decodeBinary(r,4);else if(212===e)t=this.decodeExtension(1,0);else if(213===e)t=this.decodeExtension(2,0);else if(214===e)t=this.decodeExtension(4,0);else if(215===e)t=this.decodeExtension(8,0);else if(216===e)t=this.decodeExtension(16,0);else if(199===e)r=this.lookU8(),t=this.decodeExtension(r,1);else if(200===e)r=this.lookU16(),t=this.decodeExtension(r,2);else{if(201!==e)throw new Wt("Unrecognized type byte: "+Kt(e));r=this.lookU32(),t=this.decodeExtension(r,4)}this.complete();for(var o=this.stack;o.length>0;){var s=o[o.length-1];if(0===s.type){if(s.array[s.position]=t,s.position++,s.position!==s.size)continue e;o.pop(),t=s.array}else{if(1===s.type){if("string"!=(i=typeof t)&&"number"!==i)throw new Wt("The type of key must be string or number but "+typeof t);if("__proto__"===t)throw new Wt("The key __proto__ is not allowed");s.key=t,s.type=2;continue e}if(s.map[s.key]=t,s.readCount++,s.readCount!==s.size){s.key=null,s.type=1;continue e}o.pop(),t=s.map}}return t}var i},e.prototype.readHeadByte=function(){return-1===this.headByte&&(this.headByte=this.readU8()),this.headByte},e.prototype.complete=function(){this.headByte=-1},e.prototype.readArraySize=function(){var e=this.readHeadByte();switch(e){case 220:return this.readU16();case 221:return this.readU32();default:if(e<160)return e-144;throw new Wt("Unrecognized array type byte: "+Kt(e))}},e.prototype.pushMapState=function(e){if(e>this.maxMapLength)throw new Wt("Max length exceeded: map length ("+e+") > maxMapLengthLength ("+this.maxMapLength+")");this.stack.push({type:1,size:e,key:null,readCount:0,map:{}})},e.prototype.pushArrayState=function(e){if(e>this.maxArrayLength)throw new Wt("Max length exceeded: array length ("+e+") > maxArrayLength ("+this.maxArrayLength+")");this.stack.push({type:0,size:e,array:new Array(e),position:0})},e.prototype.decodeUtf8String=function(e,t){var n;if(e>this.maxStrLength)throw new Wt("Max length exceeded: UTF-8 byte length ("+e+") > maxStrLength ("+this.maxStrLength+")");if(this.bytes.byteLengthFt?function(e,t,n){var r=e.subarray(t,t+n);return Ot.decode(r)}(this.bytes,o,e):Lt(this.bytes,o,e),this.pos+=t+e,r},e.prototype.stateIsMapKey=function(){return this.stack.length>0&&1===this.stack[this.stack.length-1].type},e.prototype.decodeBinary=function(e,t){if(e>this.maxBinLength)throw new Wt("Max length exceeded: bin length ("+e+") > maxBinLength ("+this.maxBinLength+")");if(!this.hasRemaining(e+t))throw rn;var n=this.pos+t,r=this.bytes.subarray(n,n+e);return this.pos+=t+e,r},e.prototype.decodeExtension=function(e,t){if(e>this.maxExtLength)throw new Wt("Max length exceeded: ext length ("+e+") > maxExtLength ("+this.maxExtLength+")");var n=this.view.getInt8(this.pos+t),r=this.decodeBinary(e,t+1);return this.extensionCodec.decode(r,n,this.context)},e.prototype.lookU8=function(){return this.view.getUint8(this.pos)},e.prototype.lookU16=function(){return this.view.getUint16(this.pos)},e.prototype.lookU32=function(){return this.view.getUint32(this.pos)},e.prototype.readU8=function(){var e=this.view.getUint8(this.pos);return this.pos++,e},e.prototype.readI8=function(){var e=this.view.getInt8(this.pos);return this.pos++,e},e.prototype.readU16=function(){var e=this.view.getUint16(this.pos);return this.pos+=2,e},e.prototype.readI16=function(){var e=this.view.getInt16(this.pos);return this.pos+=2,e},e.prototype.readU32=function(){var e=this.view.getUint32(this.pos);return this.pos+=4,e},e.prototype.readI32=function(){var e=this.view.getInt32(this.pos);return this.pos+=4,e},e.prototype.readU64=function(){var e,t,n=(e=this.view,t=this.pos,4294967296*e.getUint32(t)+e.getUint32(t+4));return this.pos+=8,n},e.prototype.readI64=function(){var e=Pt(this.view,this.pos);return this.pos+=8,e},e.prototype.readF32=function(){var e=this.view.getFloat32(this.pos);return this.pos+=4,e},e.prototype.readF64=function(){var e=this.view.getFloat64(this.pos);return this.pos+=8,e},e}();class an{static write(e){let t=e.byteLength||e.length;const n=[];do{let e=127&t;t>>=7,t>0&&(e|=128),n.push(e)}while(t>0);t=e.byteLength||e.length;const r=new Uint8Array(n.length+t);return r.set(n,0),r.set(e,n.length),r.buffer}static parse(e){const t=[],n=new Uint8Array(e),r=[0,7,14,21,28];for(let 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}}const cn=new Uint8Array([145,Xe.Ping]);class ln{constructor(e){this.name="messagepack",this.version=1,this.transferFormat=Ke.Binary,this._errorResult=1,this._voidResult=2,this._nonVoidResult=3,e=e||{},this._encoder=new Vt(e.extensionCodec,e.context,e.maxDepth,e.initialBufferSize,e.sortKeys,e.forceFloat32,e.ignoreUndefined,e.forceIntegerToFloat),this._decoder=new sn(e.extensionCodec,e.context,e.maxStrLength,e.maxBinLength,e.maxArrayLength,e.maxMapLength,e.maxExtLength)}parseMessages(e,t){if(!(n=e)||"undefined"==typeof ArrayBuffer||!(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer.");var n;null===t&&(t=Ge.instance);const r=an.parse(e),o=[];for(const e of r){const n=this._parseMessage(e,t);n&&o.push(n)}return o}writeMessage(e){switch(e.type){case Xe.Invocation:return this._writeInvocation(e);case Xe.StreamInvocation:return this._writeStreamInvocation(e);case Xe.StreamItem:return this._writeStreamItem(e);case Xe.Completion:return this._writeCompletion(e);case Xe.Ping:return an.write(cn);case Xe.CancelInvocation:return this._writeCancelInvocation(e);default:throw new Error("Invalid message type.")}}_parseMessage(e,t){if(0===e.length)throw new Error("Invalid payload.");const n=this._decoder.decode(e);if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");const r=n[0];switch(r){case Xe.Invocation:return this._createInvocationMessage(this._readHeaders(n),n);case Xe.StreamItem:return this._createStreamItemMessage(this._readHeaders(n),n);case Xe.Completion:return this._createCompletionMessage(this._readHeaders(n),n);case Xe.Ping:return this._createPingMessage(n);case Xe.Close:return this._createCloseMessage(n);default:return t.log(qe.Information,"Unknown message type '"+r+"' ignored."),null}}_createCloseMessage(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:Xe.Close}}_createPingMessage(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:Xe.Ping}}_createInvocationMessage(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");const n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:Xe.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:Xe.Invocation}}_createStreamItemMessage(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:Xe.StreamItem}}_createCompletionMessage(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");const n=t[3];if(n!==this._voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");let r,o;switch(n){case this._errorResult:r=t[4];break;case this._nonVoidResult:o=t[4]}return{error:r,headers:e,invocationId:t[2],result:o,type:Xe.Completion}}_writeInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Xe.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]):this._encoder.encode([Xe.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments]),an.write(t.slice())}_writeStreamInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Xe.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]):this._encoder.encode([Xe.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments]),an.write(t.slice())}_writeStreamItem(e){const t=this._encoder.encode([Xe.StreamItem,e.headers||{},e.invocationId,e.item]);return an.write(t.slice())}_writeCompletion(e){const t=e.error?this._errorResult:e.result?this._nonVoidResult:this._voidResult;let n;switch(t){case this._errorResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t,e.error]);break;case this._voidResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t]);break;case this._nonVoidResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t,e.result])}return an.write(n.slice())}_writeCancelInvocation(e){const t=this._encoder.encode([Xe.CancelInvocation,e.headers||{},e.invocationId]);return an.write(t.slice())}_readHeaders(e){const t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t}}let hn=!1;async function un(e=""){let t=document.querySelector("#blazor-error-ui");t&&(t.style.display="block",e&&t.firstChild&&(t.firstChild.textContent=`\n\t${e}\t\n`)),hn||(hn=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach((e=>{e.onclick=function(e){location.reload(),e.preventDefault()}})),document.querySelectorAll("#blazor-error-ui .dismiss").forEach((e=>{e.onclick=function(e){const t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})))}const dn="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,pn=dn?dn.decode.bind(dn):function(e){let t=0;const n=e.length,r=[],o=[];for(;t65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")},fn=Math.pow(2,32),gn=Math.pow(2,21)-1;function mn(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function yn(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function wn(e,t){const n=yn(e,t+4);if(n>gn)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*fn+yn(e,t)}class vn{constructor(e){this.batchData=e;const t=new Sn(e);this.arrayRangeReader=new Cn(e),this.arrayBuilderSegmentReader=new In(e),this.diffReader=new bn(e),this.editReader=new _n(e,t),this.frameReader=new En(e,t)}updatedComponents(){return mn(this.batchData,this.batchData.length-20)}referenceFrames(){return mn(this.batchData,this.batchData.length-16)}disposedComponentIds(){return mn(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return mn(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return mn(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return mn(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return wn(this.batchData,n)}}class bn{constructor(e){this.batchDataUint8=e}componentId(e){return mn(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class _n{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return mn(this.batchDataUint8,e)}siblingIndex(e){return mn(this.batchDataUint8,e+4)}newTreeIndex(e){return mn(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return mn(this.batchDataUint8,e+8)}removedAttributeName(e){const t=mn(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class En{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return mn(this.batchDataUint8,e)}subtreeLength(e){return mn(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return mn(this.batchDataUint8,e+8)}elementName(e){const t=mn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=mn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return wn(this.batchDataUint8,e+12)}}class Sn{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=mn(e,e.length-4)}readString(e){if(-1===e)return null;{const n=mn(this.batchDataUint8,this.stringTableStartIndex+4*e),r=function(e,t){let n=0,r=0;for(let o=0;o<4;o++){const s=e[t+o];if(n|=(127&s)<this.nextBatchId)return this.fatalError?(this.logger.log(kn.Debug,`Received a new batch ${e} but errored out on a previous batch ${this.nextBatchId-1}`),void await n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())):void this.logger.log(kn.Debug,`Waiting for batch ${this.nextBatchId}. Batch ${e} not processed.`);try{this.nextBatchId++,this.logger.log(kn.Debug,`Applying batch ${e}.`),function(e,t){const n=ue[e];if(!n)throw new Error(`There is no browser renderer with ID ${e}.`);const r=t.arrayRangeReader,o=t.updatedComponents(),s=r.values(o),i=r.count(o),a=t.referenceFrames(),c=r.values(a),l=t.diffReader;for(let e=0;e=this.minLevel){const n=`[${(new Date).toISOString()}] ${kn[e]}: ${t}`;switch(e){case kn.Critical:case kn.Error:console.error(n);break;case kn.Warning:console.warn(n);break;case kn.Information:console.info(n);break;default:console.log(n)}}}}class Rn{constructor(e,t){this.circuitId=void 0,this.components=e,this.applicationState=t}reconnect(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.state!==Ye.Connected?Promise.resolve(!1):e.invoke("ConnectCircuit",this.circuitId)}initialize(e){if(this.circuitId)throw new Error(`Circuit host '${this.circuitId}' already initialized.`);this.circuitId=e}async startCircuit(e){if(e.state!==Ye.Connected)return!1;const t=await e.invoke("StartCircuit",me.getBaseURI(),me.getLocationHref(),JSON.stringify(this.components.map((e=>e.toRecord()))),this.applicationState||"");return!!t&&(this.initialize(t),!0)}resolveElement(e){const t=function(e){const t=g.get(e);if(t)return g.delete(e),t}(e);if(t)return L(t,!0);const n=Number.parseInt(e);if(!Number.isNaN(n))return function(e,t){if(!e.parentNode)throw new Error(`Comment not connected to the DOM ${e.textContent}`);const n=e.parentNode,r=L(n,!0),o=z(r);return Array.from(n.childNodes).forEach((e=>o.push(e))),e[$]=r,t&&(e[B]=t,L(t)),L(e)}(this.components[n].start,this.components[n].end);throw new Error(`Invalid sequence number or identifier '${e}'.`)}}const Pn={configureSignalR:e=>{},logLevel:kn.Warning,reconnectionOptions:{maxRetries:8,retryIntervalMilliseconds:2e4,dialogId:"components-reconnect-modal"}};class Un{constructor(e,t,n,r){this.maxRetries=t,this.document=n,this.logger=r,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e,this.maxRetries=t,this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1050","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold","transition: visibility 0s linear 500ms"].join(";"),this.modal.innerHTML='

Alternatively, reload

',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.loader=this.getLoader(),this.message.after(this.loader),this.button.addEventListener("click",(async()=>{this.show();try{await Ae.reconnect()||this.rejected()}catch(e){this.logger.log(kn.Error,e),this.failed()}})),this.reloadParagraph.querySelector("a").addEventListener("click",(()=>location.reload()))}show(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.loader.style.display="inline-block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server...",this.modal.style.visibility="hidden",setTimeout((()=>{this.modal.style.visibility="visible"}),0)}update(e){this.message.textContent=`Attempting to reconnect to the server: ${e} of ${this.maxRetries}`}hide(){this.modal.style.display="none"}failed(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.loader.style.display="none",this.message.innerHTML="Reconnection failed. Try reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",(()=>location.reload()))}rejected(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.loader.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",(()=>location.reload()))}getLoader(){const e=this.document.createElement("div");return e.style.cssText=["border: 0.3em solid #f3f3f3","border-top: 0.3em solid #3498db","border-radius: 50%","width: 2em","height: 2em","display: inline-block"].join(";"),e.animate([{transform:"rotate(0deg)"},{transform:"rotate(360deg)"}],{duration:2e3,iterations:1/0}),e}}class An{constructor(e,t,n){this.dialog=e,this.maxRetries=t,this.document=n,this.document=n;const r=this.document.getElementById(An.MaxRetriesId);r&&(r.innerText=this.maxRetries.toString())}show(){this.removeClasses(),this.dialog.classList.add(An.ShowClassName)}update(e){const t=this.document.getElementById(An.CurrentAttemptId);t&&(t.innerText=e.toString())}hide(){this.removeClasses(),this.dialog.classList.add(An.HideClassName)}failed(){this.removeClasses(),this.dialog.classList.add(An.FailedClassName)}rejected(){this.removeClasses(),this.dialog.classList.add(An.RejectedClassName)}removeClasses(){this.dialog.classList.remove(An.ShowClassName,An.HideClassName,An.FailedClassName,An.RejectedClassName)}}An.ShowClassName="components-reconnect-show",An.HideClassName="components-reconnect-hide",An.FailedClassName="components-reconnect-failed",An.RejectedClassName="components-reconnect-rejected",An.MaxRetriesId="components-reconnect-max-retries",An.CurrentAttemptId="components-reconnect-current-attempt";class Nn{constructor(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||Ae.reconnect}onConnectionDown(e,t){if(!this._reconnectionDisplay){const t=document.getElementById(e.dialogId);this._reconnectionDisplay=t?new An(t,e.maxRetries,document):new Un(e.dialogId,e.maxRetries,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new $n(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))}onConnectionUp(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)}}class $n{constructor(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}dispose(){this.isDisposed=!0,this.reconnectDisplay.hide()}async attemptPeriodicReconnection(e){for(let t=0;t$n.MaximumFirstRetryInterval?$n.MaximumFirstRetryInterval:e.retryIntervalMilliseconds;if(await this.delay(n),this.isDisposed)break;try{return await this.reconnectCallback()?void 0:void this.reconnectDisplay.rejected()}catch(e){this.logger.log(kn.Error,e)}}this.reconnectDisplay.failed()}delay(e){return new Promise((t=>setTimeout(t,e)))}}$n.MaximumFirstRetryInterval=3e3;const Bn=/^\s*Blazor-Component-State:(?[a-zA-Z0-9\+\/=]+)$/;function Ln(e){var t;if(e.nodeType===Node.COMMENT_NODE){const n=e.textContent||"",r=Bn.exec(n),o=r&&r.groups&&r.groups.state;return o&&(null===(t=e.parentNode)||void 0===t||t.removeChild(e)),o}if(!e.hasChildNodes())return;const n=e.childNodes;for(let e=0;e.*)$/);function Fn(e,t){const n=e.currentElement;if(n&&n.nodeType===Node.COMMENT_NODE&&n.textContent){const r=On.exec(n.textContent),o=r&&r.groups&&r.groups.descriptor;if(!o)return;try{const r=function(e){const t=JSON.parse(e),{type:n}=t;if("server"!==n&&"webassembly"!==n)throw new Error(`Invalid component type '${n}'.`);return t}(o);switch(t){case"webassembly":return function(e,t,n){const{type:r,assembly:o,typeName:s,parameterDefinitions:i,parameterValues:a,prerenderId:c}=e;if("webassembly"===r){if(!o)throw new Error("assembly must be defined when using a descriptor.");if(!s)throw new Error("typeName must be defined when using a descriptor.");if(c){const e=Hn(c,n);if(!e)throw new Error(`Could not find an end component comment for '${t}'`);return{type:r,assembly:o,typeName:s,parameterDefinitions:i&&atob(i),parameterValues:a&&atob(a),start:t,prerenderId:c,end:e}}return{type:r,assembly:o,typeName:s,parameterDefinitions:i&&atob(i),parameterValues:a&&atob(a),start:t}}}(r,n,e);case"server":return function(e,t,n){const{type:r,descriptor:o,sequence:s,prerenderId:i}=e;if("server"===r){if(!o)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===s)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(s))throw new Error(`Error parsing the sequence '${s}' for component '${JSON.stringify(e)}'`);if(i){const e=Hn(i,n);if(!e)throw new Error(`Could not find an end component comment for '${t}'`);return{type:r,sequence:s,descriptor:o,start:t,prerenderId:i,end:e}}return{type:r,sequence:s,descriptor:o,start:t}}}(r,n,e)}}catch(e){throw new Error(`Found malformed component comment at ${n.textContent}`)}}}function Hn(e,t){for(;t.next()&&t.currentElement;){const n=t.currentElement;if(n.nodeType!==Node.COMMENT_NODE)continue;if(!n.textContent)continue;const r=On.exec(n.textContent),o=r&&r[1];if(o)return jn(o,e),n}}function jn(e,t){const n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error(`Invalid end of component comment: '${e}'`);const r=n.prerenderId;if(!r)throw new Error(`End of component comment must have a value for the prerendered property: '${e}'`);if(r!==t)throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${t}', '${r}'`)}class Wn{constructor(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}next(){return this.currentIndex++,this.currentIndexasync function(e,n){const r=function(e){const t=document.baseURI;return t.endsWith("/")?`${t}${e}`:`${t}/${e}`}(n),o=await import(r);if(void 0===o)return;const{beforeStart:s,afterStarted:i}=o;return i&&e.afterStartedCallbacks.push(i),s?s(...t):void 0}(this,e))))}async invokeAfterStartedCallbacks(e){await Promise.all(this.afterStartedCallbacks.map((t=>t(e))))}}let Vn=!1,Kn=!1;async function Xn(e){if(Kn)throw new Error("Blazor has already started.");Kn=!0;const t=function(e){const t={...Pn,...e};return e&&e.reconnectionOptions&&(t.reconnectionOptions={...Pn.reconnectionOptions,...e.reconnectionOptions}),t}(e),n=await async function(e){const t=await fetch("_blazor/initializers",{method:"GET",credentials:"include",cache:"no-cache"}),n=await t.json(),r=new qn;return await r.importInitializersAsync(n,[e]),r}(t),r=new xn(t.logLevel);Ae.reconnect=async e=>{if(Vn)return!1;const n=e||await Yn(t,r,i);return await i.reconnect(n)?(t.reconnectionHandler.onConnectionUp(),!0):(r.log(kn.Information,"Reconnection attempt to the circuit was rejected by the server. This may indicate that the associated state is no longer available on the server."),!1)},Ae.defaultReconnectionHandler=new Nn(r),t.reconnectionHandler=t.reconnectionHandler||Ae.defaultReconnectionHandler,r.log(kn.Information,"Starting up Blazor server-side application.");const o=function(e,t){return function(e){const t=Mn(e,"server"),n=[];for(let e=0;ee.sequence-t.sequence))}(e)}(document),s=Ln(document),i=new Rn(o,s||""),a=await Yn(t,r,i);if(!await i.startCircuit(a))return void r.log(kn.Error,"Failed to start the circuit.");let c=!1;const l=()=>{if(!c){const e=new FormData,t=i.circuitId;e.append("circuitId",t),c=navigator.sendBeacon("_blazor/disconnect",e)}};Ae.disconnect=l,window.addEventListener("unload",l,{capture:!1,once:!0}),r.log(kn.Information,"Blazor server-side application started."),n.invokeAfterStartedCallbacks(Ae)}async function Yn(t,n,r){const o=new ln;o.name="blazorpack";const s=(new Dt).withUrl("_blazor",Ve.WebSockets).withHubProtocol(o);t.configureSignalR(s);const i=s.build();Ae._internal.navigationManager.listenForNavigationEvents(((e,t)=>i.send("OnLocationChanged",e,t))),i.on("JS.AttachComponent",((e,t)=>function(e,t,n,r){let o=ue[0];o||(o=ue[0]=new se(0)),o.attachRootComponentToLogicalElement(n,t,!1)}(0,r.resolveElement(t),e))),i.on("JS.BeginInvokeJS",e.jsCallDispatcher.beginInvokeJSFromDotNet),i.on("JS.EndInvokeDotNet",e.jsCallDispatcher.endInvokeDotNetFromJS),i.on("JS.ReceiveByteArray",e.jsCallDispatcher.receiveByteArray),i.on("JS.BeginTransmitStream",(t=>{const n=new ReadableStream({start(e){i.stream("SendDotNetStreamToJS",t).subscribe({next:t=>e.enqueue(t),complete:()=>e.close(),error:t=>e.error(t)})}});e.jsCallDispatcher.supplyDotNetStream(t,n)}));const a=Tn.getOrCreate(n);i.on("JS.RenderBatch",((e,t)=>{n.log(kn.Debug,`Received render batch with id ${e} and ${t.byteLength} bytes.`),a.processBatch(e,t,i)})),i.onclose((e=>!Vn&&t.reconnectionHandler.onConnectionDown(t.reconnectionOptions,e))),i.on("JS.Error",(e=>{Vn=!0,Gn(i,e,n),un()})),Ae._internal.forceCloseConnection=()=>i.stop(),Ae._internal.sendJSDataStream=(e,t,n)=>function(e,t,n,r){setTimeout((async()=>{let o=5,s=(new Date).valueOf();try{const i=t instanceof Blob?t.size:t.byteLength;let a=0,c=0;for(;a1)await e.send("ReceiveJSDataChunk",n,c,h,null);else{if(!await e.invoke("ReceiveJSDataChunk",n,c,h,null))break;const t=(new Date).valueOf(),r=t-s;s=t,o=Math.max(1,Math.round(500/Math.max(1,r)))}a+=l,c++}}catch(t){await e.send("ReceiveJSDataChunk",n,-1,null,t.toString())}}),0)}(i,e,t,n);try{await i.start()}catch(e){if(Gn(i,e,n),"FailedToNegotiateWithServerError"===e.errorType)throw e;(c=e)&&"innerErrors"in c?e.innerErrors&&e.innerErrors.some((e=>"UnsupportedTransportError"===e.errorType&&e.transport===Ve.WebSockets))?un("Unable to connect, please ensure you are using an updated browser that supports WebSockets."):e.innerErrors&&e.innerErrors.some((e=>"FailedToStartTransportError"===e.errorType&&e.transport===Ve.WebSockets))?un("Unable to connect, please ensure WebSockets are available. A VPN or proxy may be blocking the connection."):e.innerErrors&&e.innerErrors.some((e=>"DisabledTransportError"===e.errorType&&e.transport===Ve.LongPolling))&&(n.log(kn.Error,"Unable to initiate a SignalR connection to the server. This might be because the server is not configured to support WebSockets. To troubleshoot this, visit https://aka.ms/blazor-server-websockets-error."),un()):un()}var c;return e.attachDispatcher({beginInvokeDotNetFromJS:(e,t,n,r,o)=>{i.send("BeginInvokeDotNetFromJS",e?e.toString():null,t,n,r||0,o)},endInvokeJSFromDotNet:(e,t,n)=>{i.send("EndInvokeJSFromDotNet",e,t,n)},sendByteArray:(e,t)=>{i.send("ReceiveByteArray",e,t)}}),i}function Gn(e,t,n){n.log(kn.Error,t),e&&e.stop()}Ae.start=Xn,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&Xn()})(); \ No newline at end of file +(()=>{"use strict";var e,t,n,r={};r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),function(e){window.DotNet=e;const t=[],n=new Map,r=new Map,o="__jsObjectId",i="__byte[]";class s{constructor(e){this._jsObject=e,this._cachedFunctions=new Map}findFunction(e){const t=this._cachedFunctions.get(e);if(t)return t;let n,r=this._jsObject;if(e.split(".").forEach((t=>{if(!(t in r))throw new Error(`Could not find '${e}' ('${t}' was undefined).`);n=r,r=r[t]})),r instanceof Function)return r=r.bind(n),this._cachedFunctions.set(e,r),r;throw new Error(`The value '${e}' is not a function.`)}getWrappedObject(){return this._jsObject}}const a={},c={0:new s(window)};c[0]._cachedFunctions.set("import",(e=>("string"==typeof e&&e.startsWith("./")&&(e=document.baseURI+e.substr(2)),import(e))));let l,h=1,u=1,d=null;function p(e){t.push(e)}function f(e){if(e&&"object"==typeof e){c[u]=new s(e);const t={[o]:u};return u++,t}throw new Error(`Cannot create a JSObjectReference from the value '${e}'.`)}function g(e){let t=-1;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),e instanceof Blob)t=e.size;else{if(!(e.buffer instanceof ArrayBuffer))throw new Error("Supplied value is not a typed array or blob.");if(void 0===e.byteLength)throw new Error(`Cannot create a JSStreamReference from the value '${e}' as it doesn't have a byteLength.`);t=e.byteLength}const n={__jsStreamReferenceLength:t};try{const t=f(e);n.__jsObjectId=t.__jsObjectId}catch{throw new Error(`Cannot create a JSStreamReference from the value '${e}'.`)}return n}function m(e){return e?JSON.parse(e,((e,n)=>t.reduce(((t,n)=>n(e,t)),n))):null}function y(e,t,n,r){const o=v();if(o.invokeDotNetFromJS){const i=x(r),s=o.invokeDotNetFromJS(e,t,n,i);return s?m(s):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function w(e,t,n,r){if(e&&n)throw new Error(`For instance method calls, assemblyName should be null. Received '${e}'.`);const o=h++,i=new Promise(((e,t)=>{a[o]={resolve:e,reject:t}}));try{const i=x(r);v().beginInvokeDotNetFromJS(o,e,t,n,i)}catch(e){b(o,!1,e)}return i}function v(){if(null!==d)return d;throw new Error("No .NET call dispatcher has been set.")}function b(e,t,n){if(!a.hasOwnProperty(e))throw new Error(`There is no pending async call with ID ${e}.`);const r=a[e];delete a[e],t?r.resolve(n):r.reject(n)}function _(e){return e instanceof Error?`${e.message}\n${e.stack}`:e?e.toString():"null"}function E(e,t){let n=c[t];if(n)return n.findFunction(e);throw new Error(`JS object instance with ID ${t} does not exist (has it been disposed?).`)}function S(e){delete c[e]}e.attachDispatcher=function(e){d=e},e.attachReviver=p,e.invokeMethod=function(e,t,...n){return y(e,t,null,n)},e.invokeMethodAsync=function(e,t,...n){return w(e,t,null,n)},e.createJSObjectReference=f,e.createJSStreamReference=g,e.disposeJSObjectReference=function(e){const t=e&&e.__jsObjectId;"number"==typeof t&&S(t)},function(e){e[e.Default=0]="Default",e[e.JSObjectReference=1]="JSObjectReference",e[e.JSStreamReference=2]="JSStreamReference",e[e.JSVoidResult=3]="JSVoidResult"}(l=e.JSCallResultType||(e.JSCallResultType={})),e.jsCallDispatcher={findJSFunction:E,disposeJSObjectReferenceById:S,invokeJSFromDotNet:(e,t,n,r)=>{const o=T(E(e,r).apply(null,m(t)),n);return null==o?null:x(o)},beginInvokeJSFromDotNet:(e,t,n,r,o)=>{const i=new Promise((e=>{e(E(t,o).apply(null,m(n)))}));e&&i.then((t=>v().endInvokeJSFromDotNet(e,!0,x([e,!0,T(t,r)]))),(t=>v().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,_(t)]))))},endInvokeDotNetFromJS:(e,t,n)=>{const r=t?m(n):new Error(n);b(parseInt(e),t,r)},receiveByteArray:(e,t)=>{n.set(e,t)},supplyDotNetStream:(e,t)=>{if(r.has(e)){const n=r.get(e);r.delete(e),n.resolve(t)}else{const n=new k;n.resolve(t),r.set(e,n)}}};class C{constructor(e){this._id=e}invokeMethod(e,...t){return y(null,e,this._id,t)}invokeMethodAsync(e,...t){return w(null,e,this._id,t)}dispose(){w(null,"__Dispose",this._id,null).catch((e=>console.error(e)))}serializeAsArg(){return{__dotNetObject:this._id}}}e.DotNetObject=C,p((function(e,t){if(t&&"object"==typeof t){if(t.hasOwnProperty("__dotNetObject"))return new C(t.__dotNetObject);if(t.hasOwnProperty(o)){const e=t.__jsObjectId,n=c[e];if(n)return n.getWrappedObject();throw new Error(`JS object instance with Id '${e}' does not exist. It may have been disposed.`)}if(t.hasOwnProperty(i)){const e=t["__byte[]"],r=n.get(e);if(void 0===r)throw new Error(`Byte array index '${e}' does not exist.`);return n.delete(e),r}if(t.hasOwnProperty("__dotNetStream"))return new I(t.__dotNetStream)}return t}));class I{constructor(e){var t;if(r.has(e))this._streamPromise=null===(t=r.get(e))||void 0===t?void 0:t.streamPromise,r.delete(e);else{const t=new k;r.set(e,t),this._streamPromise=t.streamPromise}}stream(){return this._streamPromise}async arrayBuffer(){return new Response(await this.stream()).arrayBuffer()}}class k{constructor(){this.streamPromise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}function T(e,t){switch(t){case l.Default:return e;case l.JSObjectReference:return f(e);case l.JSStreamReference:return g(e);case l.JSVoidResult:return null;default:throw new Error(`Invalid JS call result type '${t}'.`)}}let D=0;function x(e){return D=0,JSON.stringify(e,R)}function R(e,t){if(t instanceof C)return t.serializeAsArg();if(t instanceof Uint8Array){d.sendByteArray(D,t);const e={[i]:D};return D++,e}return t}}(e||(e={})),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t||(t={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(n||(n={}));class o{constructor(e,t){this.componentId=e,this.fieldValue=t}static fromEvent(e,t){const n=t.target;if(n instanceof Element){const t=function(e){return e instanceof HTMLInputElement?e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value}:e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?{value:e.value}:null}(n);if(t)return new o(e,t.value)}return null}}const i=new Map,s=new Map,a={createEventArgs:()=>({})},c=[];function l(e){return i.get(e)}function h(e){const t=i.get(e);return(null==t?void 0:t.browserEventName)||e}function u(e,t){e.forEach((e=>i.set(e,t)))}function d(e){const t=[];for(let n=0;ne.selected)).map((e=>e.value))}}return{value:function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(t)?!!t.checked:t.value}}}),u(["copy","cut","paste"],a),u(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...p(t=e),dataTransfer:t.dataTransfer?{dropEffect:t.dataTransfer.dropEffect,effectAllowed:t.dataTransfer.effectAllowed,files:Array.from(t.dataTransfer.files).map((e=>e.name)),items:Array.from(t.dataTransfer.items).map((e=>({kind:e.kind,type:e.type}))),types:t.dataTransfer.types}:null};var t}}),u(["focus","blur","focusin","focusout"],a),u(["keydown","keyup","keypress"],{createEventArgs:e=>{return{key:(t=e).key,code:t.code,location:t.location,repeat:t.repeat,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey};var t}}),u(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>p(e)}),u(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),u(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),u(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:d(t.touches),targetTouches:d(t.targetTouches),changedTouches:d(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),u(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...p(t=e),pointerId:t.pointerId,width:t.width,height:t.height,pressure:t.pressure,tiltX:t.tiltX,tiltY:t.tiltY,pointerType:t.pointerType,isPrimary:t.isPrimary};var t}}),u(["wheel","mousewheel"],{createEventArgs:e=>{return{...p(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),u(["toggle"],a);const f=["date","datetime-local","month","time","week"],g=new Map;let m,y,w=0;const v={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++w).toString();g.set(r,e);const o=await E().invokeMethodAsync("AddRootComponent",t,r),i=new _(o,y[t]);return await i.setParameters(n),i}};class b{invoke(e){return this._callback(e)}setCallback(t){this._selfJSObjectReference||(this._selfJSObjectReference=e.createJSObjectReference(this)),this._callback=t}getJSObjectReference(){return this._selfJSObjectReference}dispose(){this._selfJSObjectReference&&e.disposeJSObjectReference(this._selfJSObjectReference)}}class _{constructor(e,t){this._jsEventCallbackWrappers=new Map,this._componentId=e;for(const e of t)"eventcallback"===e.type&&this._jsEventCallbackWrappers.set(e.name.toLowerCase(),new b)}setParameters(e){const t={},n=Object.entries(e||{}),r=n.length;for(const[e,r]of n){const n=this._jsEventCallbackWrappers.get(e.toLowerCase());n&&r?(n.setCallback(r),t[e]=n.getJSObjectReference()):t[e]=r}return E().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await E().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function E(){if(!m)throw new Error("Dynamic root components have not been enabled in this application.");return m}const S=new Map;function C(e,t,n){return k(e,t.eventHandlerId,(()=>I(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function I(e){const t=S.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let k=(e,t,n)=>n();const T=A(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),D={submit:!0},x=A(["click","dblclick","mousedown","mousemove","mouseup"]);class R{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++R.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new P(this.onGlobalEvent.bind(this))}setListener(e,t,n,r){const o=this.getEventHandlerInfosForElement(e,!0),i=o.getHandler(t);if(i)this.eventInfoStore.update(i.eventHandlerId,n);else{const i={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(i),o.setHandler(t,i)}}getHandler(e){return this.eventInfoStore.get(e)}removeListener(e){const t=this.eventInfoStore.remove(e);if(t){const e=t.element,n=this.getEventHandlerInfosForElement(e,!1);n&&n.removeHandler(t.eventName)}}notifyAfterClick(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")}setStopPropagation(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)}setPreventDefault(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)}onGlobalEvent(e){if(!(e.target instanceof Element))return;this.dispatchGlobalEventToAllElements(e.type,e);const t=(n=e.type,s.get(n));var n;t&&t.forEach((t=>this.dispatchGlobalEventToAllElements(t,e))),"click"===e.type&&this.afterClickCallbacks.forEach((t=>t(e)))}dispatchGlobalEventToAllElements(e,t){const n=t.composedPath();let r=n.shift(),i=null,s=!1;const a=T.hasOwnProperty(e);let c=!1;for(;r;){const d=r,p=this.getEventHandlerInfosForElement(d,!1);if(p){const n=p.getHandler(e);if(n&&(h=d,u=t.type,!((h instanceof HTMLButtonElement||h instanceof HTMLInputElement||h instanceof HTMLTextAreaElement||h instanceof HTMLSelectElement)&&x.hasOwnProperty(u)&&h.disabled))){if(!s){const n=l(e);i=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},s=!0}D.hasOwnProperty(t.type)&&t.preventDefault(),C(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:o.fromEvent(n.renderingComponentId,t)},i)}p.stopPropagation(e)&&(c=!0),p.preventDefault(e)&&t.preventDefault()}r=a||c?void 0:n.shift()}var h,u}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new U:null}}R.nextEventDelegatorId=0;class P{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},c.push(this.handleEventNameAliasAdded.bind(this))}add(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error(`Event ${e.eventHandlerId} is already tracked`);this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)}get(e){return this.infosByEventHandlerId[e]}addGlobalListener(e){if(e=h(e),this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;const t=T.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}}update(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error(`Event ${t} is already tracked`);const n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n}remove(e){const t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];const n=h(t.eventName);0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t}handleEventNameAliasAdded(e,t){if(this.countByEventName.hasOwnProperty(e)){const n=this.countByEventName[e];delete this.countByEventName[e],document.removeEventListener(e,this.globalListener),this.addGlobalListener(t),this.countByEventName[t]+=n-1}}}class U{constructor(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}getHandler(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null}setHandler(e,t){this.handlers[e]=t}removeHandler(e){delete this.handlers[e]}preventDefault(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]}stopPropagation(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]}}function A(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const N=Y("_blazorLogicalChildren"),$=Y("_blazorLogicalParent"),B=Y("_blazorLogicalEnd");function L(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return N in e||(e[N]=[]),e}function M(e,t){const n=document.createComment("!");return O(n,e,t),n}function O(e,t,n){const r=e;if(e instanceof Comment&&z(r)&&z(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(H(r))throw new Error("Not implemented: moving existing logical children");const o=z(t);if(n0;)F(n,0)}const r=n;r.parentNode.removeChild(r)}function H(e){return e[$]||null}function j(e,t){return z(e)[t]}function W(e){var t=q(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function z(e){return e[N]}function J(e,t){const n=z(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=X(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):K(r,e)})),t.forEach((e=>{const t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd;let i=r;for(;i;){const e=i.nextSibling;if(n.insertBefore(i,t),i===o)break;i=e}n.removeChild(t)})),t.forEach((e=>{n[e.toSiblingIndex]=e.moveRangeStart}))}function q(e){if(e instanceof Element||e instanceof DocumentFragment)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function V(e){const t=z(H(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function K(e,t){if(t instanceof Element||t instanceof DocumentFragment)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error(`Cannot append node because the parent is not a valid logical element. Parent: ${t}`);{const n=V(t);n?n.parentNode.insertBefore(e,n):K(e,H(t))}}}function X(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=V(e);if(t)return t.previousSibling;{const t=H(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:X(t)}}function Y(e){return"function"==typeof Symbol?Symbol():e}function G(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${G(e)}]`;return document.querySelector(t)}(t.__internalId):t));const Q="_blazorDeferredValue",Z=document.createElement("template"),ee=document.createElementNS("http://www.w3.org/2000/svg","g"),te={},ne="__internal_",re="preventDefault_",oe="stopPropagation_";class ie{constructor(e){this.rootComponentIds=new Set,this.childComponentLocations={},this.eventDelegator=new R(e),this.eventDelegator.notifyAfterClick((e=>{if(!pe)return;if(0!==e.button||function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e))return;if(e.defaultPrevented)return;const t=function(e){const t=!window._blazorDisableComposedPath&&e.composedPath&&e.composedPath();if(t){for(let e=0;eve(!1))))},enableNavigationInterception:function(){pe=!0},navigateTo:ye,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function ye(e,t,n=!1){const r=_e(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Se(r)?we(r,!1,o.replaceHistoryEntry):function(e,t){if(location.href===e){const t=e+"?";history.replaceState(null,"",t),location.replace(e)}else t?location.replace(e):location.href=e}(e,o.replaceHistoryEntry)}function we(e,t,n){de=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),ve(t)}async function ve(e){ge&&await ge(location.href,e)}let be;function _e(e){return be=be||document.createElement("a"),be.href=e,be.href}function Ee(e,t){return e?e.tagName===t?e:Ee(e.parentElement,t):null}function Se(e){const t=(n=document.baseURI).substr(0,n.lastIndexOf("/")+1);var n;return e.startsWith(t)}const Ce={focus:function(e,t){if(e instanceof HTMLElement)e.focus({preventScroll:t});else{if(!(e instanceof SVGElement))throw new Error("Unable to focus an invalid element.");if(!e.hasAttribute("tabindex"))throw new Error("Unable to focus an SVG element that does not have a tabindex.");e.focus({preventScroll:t})}},focusBySelector:function(e){const t=document.querySelector(e);t&&(t.hasAttribute("tabindex")||(t.tabIndex=-1),t.focus())}},Ie={init:function(e,t,n,r=50){const o=Te(t);(o||document.documentElement).style.overflowAnchor="none";const i=new IntersectionObserver((function(r){r.forEach((r=>{var o;if(!r.isIntersecting)return;const i=t.getBoundingClientRect(),s=n.getBoundingClientRect().top-i.bottom,a=null===(o=r.rootBounds)||void 0===o?void 0:o.height;r.target===t?e.invokeMethodAsync("OnSpacerBeforeVisible",r.intersectionRect.top-r.boundingClientRect.top,s,a):r.target===n&&n.offsetHeight>0&&e.invokeMethodAsync("OnSpacerAfterVisible",r.boundingClientRect.bottom-r.intersectionRect.bottom,s,a)}))}),{root:o,rootMargin:`${r}px`});i.observe(t),i.observe(n);const s=c(t),a=c(n);function c(e){const t=new MutationObserver((()=>{i.unobserve(e),i.observe(e)}));return t.observe(e,{attributes:!0}),t}ke[e._id]={intersectionObserver:i,mutationObserverBefore:s,mutationObserverAfter:a}},dispose:function(e){const t=ke[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete ke[e._id])}},ke={};function Te(e){return e?"visible"!==getComputedStyle(e).overflowY?e:Te(e.parentElement):null}const De={getAndRemoveExistingTitle:function(){var e;const t=document.getElementsByTagName("title");if(0===t.length)return null;let n=null;for(let r=t.length-1;r>=0;r--){const o=t[r],i=o.previousSibling;i instanceof Comment&&null!==H(i)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},xe={init:function(e,t){t._blazorInputFileNextFileId=0,t.addEventListener("click",(function(){t.value=""})),t.addEventListener("change",(function(){t._blazorFilesById={};const n=Array.prototype.map.call(t.files,(function(e){const n={id:++t._blazorInputFileNextFileId,lastModified:new Date(e.lastModified).toISOString(),name:e.name,size:e.size,contentType:e.type,readPromise:void 0,arrayBuffer:void 0,blob:e};return t._blazorFilesById[n.id]=n,n}));e.invokeMethodAsync("NotifyChange",n)}))},toImageFile:async function(e,t,n,r,o){const i=Re(e,t),s=await new Promise((function(e){const t=new Image;t.onload=function(){URL.revokeObjectURL(t.src),e(t)},t.onerror=function(){t.onerror=null,URL.revokeObjectURL(t.src)},t.src=URL.createObjectURL(i.blob)})),a=await new Promise((function(e){var t;const i=Math.min(1,r/s.width),a=Math.min(1,o/s.height),c=Math.min(i,a),l=document.createElement("canvas");l.width=Math.round(s.width*c),l.height=Math.round(s.height*c),null===(t=l.getContext("2d"))||void 0===t||t.drawImage(s,0,0,l.width,l.height),l.toBlob(e,n)})),c={id:++e._blazorInputFileNextFileId,lastModified:i.lastModified,name:i.name,size:(null==a?void 0:a.size)||0,contentType:n,blob:a||i.blob};return e._blazorFilesById[c.id]=c,c},readFileData:async function(e,t){return Re(e,t).blob}};function Re(e,t){const n=e._blazorFilesById[t];if(!n)throw new Error(`There is no file with ID ${t}. The file list may have changed.`);return n}async function Pe(e,t,n){return e instanceof Blob?await async function(e,t,n){const r=e.slice(t,t+n),o=await r.arrayBuffer();return new Uint8Array(o)}(e,t,n):function(e,t,n){return new Uint8Array(e.buffer,e.byteOffset+t,n)}(e,t,n)}const Ue=new Map,Ae={navigateTo:ye,registerCustomEventType:function(e,t){if(!t)throw new Error("The options parameter is required.");if(i.has(e))throw new Error(`The event '${e}' is already registered.`);if(t.browserEventName){const n=s.get(t.browserEventName);n?n.push(e):s.set(t.browserEventName,[e]),c.forEach((n=>n(e,t.browserEventName)))}i.set(e,t)},rootComponents:v,_internal:{navigationManager:me,domWrapper:Ce,Virtualize:Ie,PageTitle:De,InputFile:xe,getJSDataStreamChunk:Pe,receiveDotNetDataStream:function(t,n,r,o){let i=Ue.get(t);if(!i){const n=new ReadableStream({start(e){Ue.set(t,e),i=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(i.error(o),Ue.delete(t)):0===r?(i.close(),Ue.delete(t)):i.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(S.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);S.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(m)throw new Error("Dynamic root components have already been enabled.");m=t,y=n;for(const[t,o]of Object.entries(r)){const r=e.jsCallDispatcher.findJSFunction(t,0);for(const e of o)r(e,n[e])}}(I(t),r,o)}}};window.Blazor=Ae;const Ne=[0,2e3,1e4,3e4,null];class $e{constructor(e){this._retryDelays=void 0!==e?[...e,null]:Ne}nextRetryDelayInMilliseconds(e){return this._retryDelays[e.previousRetryCount]}}class Be extends Error{constructor(e,t){const n=new.target.prototype;super(`${e}: Status code '${t}'`),this.statusCode=t,this.__proto__=n}}class Le extends Error{constructor(e="A timeout occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Me extends Error{constructor(e="An abort occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Oe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="UnsupportedTransportError",this.__proto__=n}}class Fe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="DisabledTransportError",this.__proto__=n}}class He extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="FailedToStartTransportError",this.__proto__=n}}class je extends Error{constructor(e){const t=new.target.prototype;super(e),this.errorType="FailedToNegotiateWithServerError",this.__proto__=t}}class We extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.innerErrors=t,this.__proto__=n}}class ze{constructor(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}class Je{get(e,t){return this.send({...t,method:"GET",url:e})}post(e,t){return this.send({...t,method:"POST",url:e})}delete(e,t){return this.send({...t,method:"DELETE",url:e})}getCookieString(e){return""}}var qe,Ve,Ke,Xe,Ye;!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"}(qe||(qe={}));class Ge{constructor(){}log(e,t){}}Ge.instance=new Ge;class Qe{static isRequired(e,t){if(null==e)throw new Error(`The '${t}' argument is required.`)}static isNotEmpty(e,t){if(!e||e.match(/^\s*$/))throw new Error(`The '${t}' argument should not be empty.`)}static isIn(e,t,n){if(!(e in t))throw new Error(`Unknown ${n} value: ${e}.`)}}class Ze{static get isBrowser(){return"object"==typeof window}static get isWebWorker(){return"object"==typeof self&&"importScripts"in self}static get isNode(){return!this.isBrowser&&!this.isWebWorker}}function et(e,t){let n="";return tt(e)?(n=`Binary data of length ${e.byteLength}`,t&&(n+=`. Content: '${function(e){const t=new Uint8Array(e);let n="";return t.forEach((e=>{n+=`0x${e<16?"0":""}${e.toString(16)} `})),n.substr(0,n.length-1)}(e)}'`)):"string"==typeof e&&(n=`String data of length ${e.length}`,t&&(n+=`. Content: '${e}'`)),n}function tt(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}async function nt(e,t,n,r,o,i,s){let a={};if(o){const e=await o();e&&(a={Authorization:`Bearer ${e}`})}const[c,l]=it();a[c]=l,e.log(qe.Trace,`(${t} transport) sending data. ${et(i,s.logMessageContent)}.`);const h=tt(i)?"arraybuffer":"text",u=await n.post(r,{content:i,headers:{...a,...s.headers},responseType:h,timeout:s.timeout,withCredentials:s.withCredentials});e.log(qe.Trace,`(${t} transport) request complete. Response status: ${u.statusCode}.`)}class rt{constructor(e,t){this._subject=e,this._observer=t}dispose(){const e=this._subject.observers.indexOf(this._observer);e>-1&&this._subject.observers.splice(e,1),0===this._subject.observers.length&&this._subject.cancelCallback&&this._subject.cancelCallback().catch((e=>{}))}}class ot{constructor(e){this._minLevel=e,this.out=console}log(e,t){if(e>=this._minLevel){const n=`[${(new Date).toISOString()}] ${qe[e]}: ${t}`;switch(e){case qe.Critical:case qe.Error:this.out.error(n);break;case qe.Warning:this.out.warn(n);break;case qe.Information:this.out.info(n);break;default:this.out.log(n)}}}}function it(){let e="X-SignalR-User-Agent";return Ze.isNode&&(e="User-Agent"),[e,st("0.0.0-DEV_BUILD",at(),Ze.isNode?"NodeJS":"Browser",ct())]}function st(e,t,n,r){let o="Microsoft SignalR/";const i=e.split(".");return o+=`${i[0]}.${i[1]}`,o+=` (${e}; `,o+=t&&""!==t?`${t}; `:"Unknown OS; ",o+=`${n}`,o+=r?`; ${r}`:"; Unknown Runtime Version",o+=")",o}function at(){if(!Ze.isNode)return"";switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}function ct(){if(Ze.isNode)return process.versions.node}function lt(e){return e.stack?e.stack:e.message?e.message:`${e}`}class ht extends Je{constructor(e){if(super(),this._logger=e,"undefined"==typeof fetch){const e=require;this._jar=new(e("tough-cookie").CookieJar),this._fetchType=e("node-fetch"),this._fetchType=e("fetch-cookie")(this._fetchType,this._jar)}else this._fetchType=fetch.bind(function(){if("undefined"!=typeof globalThis)return globalThis;if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==r.g)return r.g;throw new Error("could not find global")}());if("undefined"==typeof AbortController){const e=require;this._abortControllerType=e("abort-controller")}else this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new Me;if(!e.method)throw new Error("No method defined.");if(!e.url)throw new Error("No url defined.");const t=new this._abortControllerType;let n;e.abortSignal&&(e.abortSignal.onabort=()=>{t.abort(),n=new Me});let r,o=null;if(e.timeout){const r=e.timeout;o=setTimeout((()=>{t.abort(),this._logger.log(qe.Warning,"Timeout from HTTP request."),n=new Le}),r)}try{r=await this._fetchType(e.url,{body:e.content,cache:"no-cache",credentials:!0===e.withCredentials?"include":"same-origin",headers:{"Content-Type":"text/plain;charset=UTF-8","X-Requested-With":"XMLHttpRequest",...e.headers},method:e.method,mode:"cors",redirect:"follow",signal:t.signal})}catch(e){if(n)throw n;throw this._logger.log(qe.Warning,`Error from HTTP request. ${e}.`),e}finally{o&&clearTimeout(o),e.abortSignal&&(e.abortSignal.onabort=null)}if(!r.ok){const e=await ut(r,"text");throw new Be(e||r.statusText,r.status)}const i=ut(r,e.responseType),s=await i;return new ze(r.status,r.statusText,s)}getCookieString(e){return""}}function ut(e,t){let n;switch(t){case"arraybuffer":n=e.arrayBuffer();break;case"text":n=e.text();break;case"blob":case"document":case"json":throw new Error(`${t} is not supported.`);default:n=e.text()}return n}class dt extends Je{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Me):e.method?e.url?new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open(e.method,e.url,!0),r.withCredentials=void 0===e.withCredentials||e.withCredentials,r.setRequestHeader("X-Requested-With","XMLHttpRequest"),r.setRequestHeader("Content-Type","text/plain;charset=UTF-8");const o=e.headers;o&&Object.keys(o).forEach((e=>{r.setRequestHeader(e,o[e])})),e.responseType&&(r.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=()=>{r.abort(),n(new Me)}),e.timeout&&(r.timeout=e.timeout),r.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),r.status>=200&&r.status<300?t(new ze(r.status,r.statusText,r.response||r.responseText)):n(new Be(r.response||r.responseText||r.statusText,r.status))},r.onerror=()=>{this._logger.log(qe.Warning,`Error from HTTP request. ${r.status}: ${r.statusText}.`),n(new Be(r.statusText,r.status))},r.ontimeout=()=>{this._logger.log(qe.Warning,"Timeout from HTTP request."),n(new Le)},r.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}}class pt extends Je{constructor(e){if(super(),"undefined"!=typeof fetch)this._httpClient=new ht(e);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");this._httpClient=new dt(e)}}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Me):e.method?e.url?this._httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}getCookieString(e){return this._httpClient.getCookieString(e)}}class ft{}ft.Authorization="Authorization",ft.Cookie="Cookie",function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(Ve||(Ve={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(Ke||(Ke={}));class gt{constructor(){this._isAborted=!1,this.onabort=null}abort(){this._isAborted||(this._isAborted=!0,this.onabort&&this.onabort())}get signal(){return this}get aborted(){return this._isAborted}}class mt{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._pollAbort=new gt,this._options=r,this._running=!1,this.onreceive=null,this.onclose=null}get pollAborted(){return this._pollAbort.aborted}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._url=e,this._logger.log(qe.Trace,"(LongPolling transport) Connecting."),t===Ke.Binary&&"undefined"!=typeof XMLHttpRequest&&"string"!=typeof(new XMLHttpRequest).responseType)throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");const[n,r]=it(),o={[n]:r,...this._options.headers},i={abortSignal:this._pollAbort.signal,headers:o,timeout:1e5,withCredentials:this._options.withCredentials};t===Ke.Binary&&(i.responseType="arraybuffer");const s=await this._getAccessToken();this._updateHeaderToken(i,s);const a=`${e}&_=${Date.now()}`;this._logger.log(qe.Trace,`(LongPolling transport) polling: ${a}.`);const c=await this._httpClient.get(a,i);200!==c.statusCode?(this._logger.log(qe.Error,`(LongPolling transport) Unexpected response code: ${c.statusCode}.`),this._closeError=new Be(c.statusText||"",c.statusCode),this._running=!1):this._running=!0,this._receiving=this._poll(this._url,i)}async _getAccessToken(){return this._accessTokenFactory?await this._accessTokenFactory():null}_updateHeaderToken(e,t){e.headers||(e.headers={}),t?e.headers[ft.Authorization]=`Bearer ${t}`:e.headers[ft.Authorization]&&delete e.headers[ft.Authorization]}async _poll(e,t){try{for(;this._running;){const n=await this._getAccessToken();this._updateHeaderToken(t,n);try{const n=`${e}&_=${Date.now()}`;this._logger.log(qe.Trace,`(LongPolling transport) polling: ${n}.`);const r=await this._httpClient.get(n,t);204===r.statusCode?(this._logger.log(qe.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):200!==r.statusCode?(this._logger.log(qe.Error,`(LongPolling transport) Unexpected response code: ${r.statusCode}.`),this._closeError=new Be(r.statusText||"",r.statusCode),this._running=!1):r.content?(this._logger.log(qe.Trace,`(LongPolling transport) data received. ${et(r.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(r.content)):this._logger.log(qe.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(e){this._running?e instanceof Le?this._logger.log(qe.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=e,this._running=!1):this._logger.log(qe.Trace,`(LongPolling transport) Poll errored after shutdown: ${e.message}`)}}}finally{this._logger.log(qe.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?nt(this._logger,"LongPolling",this._httpClient,this._url,this._accessTokenFactory,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}async stop(){this._logger.log(qe.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(qe.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);const e={},[t,n]=it();e[t]=n;const r={headers:{...e,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials},o=await this._getAccessToken();this._updateHeaderToken(r,o),await this._httpClient.delete(this._url,r),this._logger.log(qe.Trace,"(LongPolling transport) DELETE request sent.")}finally{this._logger.log(qe.Trace,"(LongPolling transport) Stop finished."),this._raiseOnClose()}}_raiseOnClose(){if(this.onclose){let e="(LongPolling transport) Firing onclose event.";this._closeError&&(e+=" Error: "+this._closeError),this._logger.log(qe.Trace,e),this.onclose(this._closeError)}}}class yt{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._options=r,this.onreceive=null,this.onclose=null}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._logger.log(qe.Trace,"(SSE transport) Connecting."),this._url=e,this._accessTokenFactory){const t=await this._accessTokenFactory();t&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(t)}`)}return new Promise(((n,r)=>{let o,i=!1;if(t===Ke.Text){if(Ze.isBrowser||Ze.isWebWorker)o=new this._options.EventSource(e,{withCredentials:this._options.withCredentials});else{const t=this._httpClient.getCookieString(e),n={};n.Cookie=t;const[r,i]=it();n[r]=i,o=new this._options.EventSource(e,{withCredentials:this._options.withCredentials,headers:{...n,...this._options.headers}})}try{o.onmessage=e=>{if(this.onreceive)try{this._logger.log(qe.Trace,`(SSE transport) data received. ${et(e.data,this._options.logMessageContent)}.`),this.onreceive(e.data)}catch(e){return void this._close(e)}},o.onerror=e=>{i?this._close():r(new Error("EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled."))},o.onopen=()=>{this._logger.log(qe.Information,`SSE connected to ${this._url}`),this._eventSource=o,i=!0,n()}}catch(e){return void r(e)}}else r(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"))}))}async send(e){return this._eventSource?nt(this._logger,"SSE",this._httpClient,this._url,this._accessTokenFactory,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}stop(){return this._close(),Promise.resolve()}_close(e){this._eventSource&&(this._eventSource.close(),this._eventSource=void 0,this.onclose&&this.onclose(e))}}class wt{constructor(e,t,n,r,o,i){this._logger=n,this._accessTokenFactory=t,this._logMessageContent=r,this._webSocketConstructor=o,this._httpClient=e,this.onreceive=null,this.onclose=null,this._headers=i}async connect(e,t){if(Qe.isRequired(e,"url"),Qe.isRequired(t,"transferFormat"),Qe.isIn(t,Ke,"transferFormat"),this._logger.log(qe.Trace,"(WebSockets transport) Connecting."),this._accessTokenFactory){const t=await this._accessTokenFactory();t&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(t)}`)}return new Promise(((n,r)=>{let o;e=e.replace(/^http/,"ws"),this._httpClient.getCookieString(e);let i=!1;o||(o=new this._webSocketConstructor(e)),t===Ke.Binary&&(o.binaryType="arraybuffer"),o.onopen=t=>{this._logger.log(qe.Information,`WebSocket connected to ${e}.`),this._webSocket=o,i=!0,n()},o.onerror=e=>{let t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:"There was an error with the transport",this._logger.log(qe.Information,`(WebSockets transport) ${t}.`)},o.onmessage=e=>{if(this._logger.log(qe.Trace,`(WebSockets transport) data received. ${et(e.data,this._logMessageContent)}.`),this.onreceive)try{this.onreceive(e.data)}catch(e){return void this._close(e)}},o.onclose=e=>{if(i)this._close(e);else{let t=null;t="undefined"!=typeof ErrorEvent&&e instanceof ErrorEvent?e.error:"WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.",r(new Error(t))}}}))}send(e){return this._webSocket&&this._webSocket.readyState===this._webSocketConstructor.OPEN?(this._logger.log(qe.Trace,`(WebSockets transport) sending data. ${et(e,this._logMessageContent)}.`),this._webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")}stop(){return this._webSocket&&this._close(void 0),Promise.resolve()}_close(e){this._webSocket&&(this._webSocket.onclose=()=>{},this._webSocket.onmessage=()=>{},this._webSocket.onerror=()=>{},this._webSocket.close(),this._webSocket=void 0),this._logger.log(qe.Trace,"(WebSockets transport) socket closed."),this.onclose&&(!this._isCloseEvent(e)||!1!==e.wasClean&&1e3===e.code?e instanceof Error?this.onclose(e):this.onclose():this.onclose(new Error(`WebSocket closed with status code: ${e.code} (${e.reason||"no reason given"}).`)))}_isCloseEvent(e){return e&&"boolean"==typeof e.wasClean&&"number"==typeof e.code}}class vt{constructor(e,t={}){var n;if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,Qe.isRequired(e,"url"),this._logger=void 0===(n=t.logger)?new ot(qe.Information):null===n?Ge.instance:void 0!==n.log?n:new ot(n),this.baseUrl=this._resolveUrl(e),(t=t||{}).logMessageContent=void 0!==t.logMessageContent&&t.logMessageContent,"boolean"!=typeof t.withCredentials&&void 0!==t.withCredentials)throw new Error("withCredentials option was not a 'boolean' or 'undefined' value");t.withCredentials=void 0===t.withCredentials||t.withCredentials,t.timeout=void 0===t.timeout?1e5:t.timeout,"undefined"==typeof WebSocket||t.WebSocket||(t.WebSocket=WebSocket),"undefined"==typeof EventSource||t.EventSource||(t.EventSource=EventSource),this._httpClient=t.httpClient||new pt(this._logger),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=t,this.onreceive=null,this.onclose=null}async start(e){if(e=e||Ke.Binary,Qe.isIn(e,Ke,"transferFormat"),this._logger.log(qe.Debug,`Starting connection with transfer format '${Ke[e]}'.`),"Disconnected"!==this._connectionState)return Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."));if(this._connectionState="Connecting",this._startInternalPromise=this._startInternal(e),await this._startInternalPromise,"Disconnecting"===this._connectionState){const e="Failed to start the HttpConnection before stop() was called.";return this._logger.log(qe.Error,e),await this._stopPromise,Promise.reject(new Error(e))}if("Connected"!==this._connectionState){const e="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!";return this._logger.log(qe.Error,e),Promise.reject(new Error(e))}this._connectionStarted=!0}send(e){return"Connected"!==this._connectionState?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this._sendQueue||(this._sendQueue=new bt(this.transport)),this._sendQueue.send(e))}async stop(e){return"Disconnected"===this._connectionState?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve()):"Disconnecting"===this._connectionState?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState="Disconnecting",this._stopPromise=new Promise((e=>{this._stopPromiseResolver=e})),await this._stopInternal(e),void await this._stopPromise)}async _stopInternal(e){this._stopError=e;try{await this._startInternalPromise}catch(e){}if(this.transport){try{await this.transport.stop()}catch(e){this._logger.log(qe.Error,`HttpConnection.transport.stop() threw error '${e}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(qe.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.")}async _startInternal(e){let t=this.baseUrl;this._accessTokenFactory=this._options.accessTokenFactory;try{if(this._options.skipNegotiation){if(this._options.transport!==Ve.WebSockets)throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");this.transport=this._constructTransport(Ve.WebSockets),await this._startTransport(t,e)}else{let n=null,r=0;do{if(n=await this._getNegotiationResponse(t),"Disconnecting"===this._connectionState||"Disconnected"===this._connectionState)throw new Error("The connection was stopped during negotiation.");if(n.error)throw new Error(n.error);if(n.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");if(n.url&&(t=n.url),n.accessToken){const e=n.accessToken;this._accessTokenFactory=()=>e}r++}while(n.url&&r<100);if(100===r&&n.url)throw new Error("Negotiate redirection limit exceeded.");await this._createTransport(t,this._options.transport,n,e)}this.transport instanceof mt&&(this.features.inherentKeepAlive=!0),"Connecting"===this._connectionState&&(this._logger.log(qe.Debug,"The HttpConnection connected successfully."),this._connectionState="Connected")}catch(e){return this._logger.log(qe.Error,"Failed to start the connection: "+e),this._connectionState="Disconnected",this.transport=void 0,this._stopPromiseResolver(),Promise.reject(e)}}async _getNegotiationResponse(e){const t={};if(this._accessTokenFactory){const e=await this._accessTokenFactory();e&&(t[ft.Authorization]=`Bearer ${e}`)}const[n,r]=it();t[n]=r;const o=this._resolveNegotiateUrl(e);this._logger.log(qe.Debug,`Sending negotiation request: ${o}.`);try{const e=await this._httpClient.post(o,{content:"",headers:{...t,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials});if(200!==e.statusCode)return Promise.reject(new Error(`Unexpected status code returned from negotiate '${e.statusCode}'`));const n=JSON.parse(e.content);return(!n.negotiateVersion||n.negotiateVersion<1)&&(n.connectionToken=n.connectionId),n}catch(e){let t="Failed to complete negotiation with the server: "+e;return e instanceof Be&&404===e.statusCode&&(t+=" Either this is not a SignalR endpoint or there is a proxy blocking the connection."),this._logger.log(qe.Error,t),Promise.reject(new je(t))}}_createConnectUrl(e,t){return t?e+(-1===e.indexOf("?")?"?":"&")+`id=${t}`:e}async _createTransport(e,t,n,r){let o=this._createConnectUrl(e,n.connectionToken);if(this._isITransport(t))return this._logger.log(qe.Debug,"Connection was provided an instance of ITransport, using that directly."),this.transport=t,await this._startTransport(o,r),void(this.connectionId=n.connectionId);const i=[],s=n.availableTransports||[];let a=n;for(const n of s){const s=this._resolveTransportOrError(n,t,r);if(s instanceof Error)i.push(`${n.transport} failed:`),i.push(s);else if(this._isITransport(s)){if(this.transport=s,!a){try{a=await this._getNegotiationResponse(e)}catch(e){return Promise.reject(e)}o=this._createConnectUrl(e,a.connectionToken)}try{return await this._startTransport(o,r),void(this.connectionId=a.connectionId)}catch(e){if(this._logger.log(qe.Error,`Failed to start the transport '${n.transport}': ${e}`),a=void 0,i.push(new He(`${n.transport} failed: ${e}`,Ve[n.transport])),"Connecting"!==this._connectionState){const e="Failed to select transport before stop() was called.";return this._logger.log(qe.Debug,e),Promise.reject(new Error(e))}}}}return i.length>0?Promise.reject(new We(`Unable to connect to the server with any of the available transports. ${i.join(" ")}`,i)):Promise.reject(new Error("None of the transports supported by the client are supported by the server."))}_constructTransport(e){switch(e){case Ve.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new wt(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case Ve.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new yt(this._httpClient,this._accessTokenFactory,this._logger,this._options);case Ve.LongPolling:return new mt(this._httpClient,this._accessTokenFactory,this._logger,this._options);default:throw new Error(`Unknown transport: ${e}.`)}}_startTransport(e,t){return this.transport.onreceive=this.onreceive,this.transport.onclose=e=>this._stopConnection(e),this.transport.connect(e,t)}_resolveTransportOrError(e,t,n){const r=Ve[e.transport];if(null==r)return this._logger.log(qe.Debug,`Skipping transport '${e.transport}' because it is not supported by this client.`),new Error(`Skipping transport '${e.transport}' because it is not supported by this client.`);if(!function(e,t){return!e||0!=(t&e)}(t,r))return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it was disabled by the client.`),new Fe(`'${Ve[r]}' is disabled by the client.`,r);if(!(e.transferFormats.map((e=>Ke[e])).indexOf(n)>=0))return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it does not support the requested transfer format '${Ke[n]}'.`),new Error(`'${Ve[r]}' does not support ${Ke[n]}.`);if(r===Ve.WebSockets&&!this._options.WebSocket||r===Ve.ServerSentEvents&&!this._options.EventSource)return this._logger.log(qe.Debug,`Skipping transport '${Ve[r]}' because it is not supported in your environment.'`),new Oe(`'${Ve[r]}' is not supported in your environment.`,r);this._logger.log(qe.Debug,`Selecting transport '${Ve[r]}'.`);try{return this._constructTransport(r)}catch(e){return e}}_isITransport(e){return e&&"object"==typeof e&&"connect"in e}_stopConnection(e){if(this._logger.log(qe.Debug,`HttpConnection.stopConnection(${e}) called while in state ${this._connectionState}.`),this.transport=void 0,e=this._stopError||e,this._stopError=void 0,"Disconnected"!==this._connectionState){if("Connecting"===this._connectionState)throw this._logger.log(qe.Warning,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is still in the connecting state.`),new Error(`HttpConnection.stopConnection(${e}) was called while the connection is still in the connecting state.`);if("Disconnecting"===this._connectionState&&this._stopPromiseResolver(),e?this._logger.log(qe.Error,`Connection disconnected with error '${e}'.`):this._logger.log(qe.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch((e=>{this._logger.log(qe.Error,`TransportSendQueue.stop() threw error '${e}'.`)})),this._sendQueue=void 0),this.connectionId=void 0,this._connectionState="Disconnected",this._connectionStarted){this._connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(t){this._logger.log(qe.Error,`HttpConnection.onclose(${e}) threw error '${t}'.`)}}}else this._logger.log(qe.Debug,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is already in the disconnected state.`)}_resolveUrl(e){if(0===e.lastIndexOf("https://",0)||0===e.lastIndexOf("http://",0))return e;if(!Ze.isBrowser||!window.document)throw new Error(`Cannot resolve '${e}'.`);const t=window.document.createElement("a");return t.href=e,this._logger.log(qe.Information,`Normalizing '${e}' to '${t.href}'.`),t.href}_resolveNegotiateUrl(e){const t=e.indexOf("?");let n=e.substring(0,-1===t?e.length:t);return"/"!==n[n.length-1]&&(n+="/"),n+="negotiate",n+=-1===t?"":e.substring(t),-1===n.indexOf("negotiateVersion")&&(n+=-1===t?"?":"&",n+="negotiateVersion="+this._negotiateVersion),n}}class bt{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new _t,this._transportResult=new _t,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new _t),this._transportResult.promise}stop(){return this._executing=!1,this._sendBufferedData.resolve(),this._sendLoopPromise}_bufferData(e){if(this._buffer.length&&typeof this._buffer[0]!=typeof e)throw new Error(`Expected data to be of type ${typeof this._buffer} but was of type ${typeof e}`);this._buffer.push(e),this._sendBufferedData.resolve()}async _sendLoop(){for(;;){if(await this._sendBufferedData.promise,!this._executing){this._transportResult&&this._transportResult.reject("Connection stopped.");break}this._sendBufferedData=new _t;const e=this._transportResult;this._transportResult=void 0;const t="string"==typeof this._buffer[0]?this._buffer.join(""):bt._concatBuffers(this._buffer);this._buffer.length=0;try{await this._transport.send(t),e.resolve()}catch(t){e.reject(t)}}}static _concatBuffers(e){const t=e.map((e=>e.byteLength)).reduce(((e,t)=>e+t)),n=new Uint8Array(t);let r=0;for(const t of e)n.set(new Uint8Array(t),r),r+=t.byteLength;return n.buffer}}class _t{constructor(){this.promise=new Promise(((e,t)=>[this._resolver,this._rejecter]=[e,t]))}resolve(){this._resolver()}reject(e){this._rejecter(e)}}class Et{static write(e){return`${e}${Et.RecordSeparator}`}static parse(e){if(e[e.length-1]!==Et.RecordSeparator)throw new Error("Message is incomplete.");const t=e.split(Et.RecordSeparator);return t.pop(),t}}Et.RecordSeparatorCode=30,Et.RecordSeparator=String.fromCharCode(Et.RecordSeparatorCode);class St{writeHandshakeRequest(e){return Et.write(JSON.stringify(e))}parseHandshakeResponse(e){let t,n;if(tt(e)){const r=new Uint8Array(e),o=r.indexOf(Et.RecordSeparatorCode);if(-1===o)throw new Error("Message is incomplete.");const i=o+1;t=String.fromCharCode.apply(null,Array.prototype.slice.call(r.slice(0,i))),n=r.byteLength>i?r.slice(i).buffer:null}else{const r=e,o=r.indexOf(Et.RecordSeparator);if(-1===o)throw new Error("Message is incomplete.");const i=o+1;t=r.substring(0,i),n=r.length>i?r.substring(i):null}const r=Et.parse(t),o=JSON.parse(r[0]);if(o.type)throw new Error("Expected a handshake response from the server.");return[n,o]}}!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"}(Xe||(Xe={}));class Ct{constructor(){this.observers=[]}next(e){for(const t of this.observers)t.next(e)}error(e){for(const t of this.observers)t.error&&t.error(e)}complete(){for(const e of this.observers)e.complete&&e.complete()}subscribe(e){return this.observers.push(e),new rt(this,e)}}!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(Ye||(Ye={}));class It{constructor(e,t,n,r){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(qe.Warning,"The page is being frozen, this will likely lead to the connection being closed and messages being lost. For more information see the docs at https://docs.microsoft.com/aspnet/core/signalr/javascript-client#bsleep")},Qe.isRequired(e,"connection"),Qe.isRequired(t,"logger"),Qe.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=3e4,this.keepAliveIntervalInMilliseconds=15e3,this._logger=t,this._protocol=n,this.connection=e,this._reconnectPolicy=r,this._handshakeProtocol=new St,this.connection.onreceive=e=>this._processIncomingData(e),this.connection.onclose=e=>this._connectionClosed(e),this._callbacks={},this._methods={},this._closedCallbacks=[],this._reconnectingCallbacks=[],this._reconnectedCallbacks=[],this._invocationId=0,this._receivedHandshakeResponse=!1,this._connectionState=Ye.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:Xe.Ping})}static create(e,t,n,r){return new It(e,t,n,r)}get state(){return this._connectionState}get connectionId(){return this.connection&&this.connection.connectionId||null}get baseUrl(){return this.connection.baseUrl||""}set baseUrl(e){if(this._connectionState!==Ye.Disconnected&&this._connectionState!==Ye.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e}start(){return this._startPromise=this._startWithStateTransitions(),this._startPromise}async _startWithStateTransitions(){if(this._connectionState!==Ye.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=Ye.Connecting,this._logger.log(qe.Debug,"Starting HubConnection.");try{await this._startInternal(),Ze.isBrowser&&document&&document.addEventListener("freeze",this._freezeEventListener),this._connectionState=Ye.Connected,this._connectionStarted=!0,this._logger.log(qe.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=Ye.Disconnected,this._logger.log(qe.Debug,`HubConnection failed to start successfully because of error '${e}'.`),Promise.reject(e)}}async _startInternal(){this._stopDuringStartError=void 0,this._receivedHandshakeResponse=!1;const e=new Promise(((e,t)=>{this._handshakeResolver=e,this._handshakeRejecter=t}));await this.connection.start(this._protocol.transferFormat);try{const t={protocol:this._protocol.name,version:this._protocol.version};if(this._logger.log(qe.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(t)),this._logger.log(qe.Information,`Using HubProtocol '${this._protocol.name}'.`),this._cleanupTimeout(),this._resetTimeoutPeriod(),this._resetKeepAliveInterval(),await e,this._stopDuringStartError)throw this._stopDuringStartError}catch(e){throw this._logger.log(qe.Debug,`Hub handshake failed with error '${e}' during start(). Stopping HubConnection.`),this._cleanupTimeout(),this._cleanupPingTimer(),await this.connection.stop(e),e}}async stop(){const e=this._startPromise;this._stopPromise=this._stopInternal(),await this._stopPromise;try{await e}catch(e){}}_stopInternal(e){return this._connectionState===Ye.Disconnected?(this._logger.log(qe.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve()):this._connectionState===Ye.Disconnecting?(this._logger.log(qe.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState=Ye.Disconnecting,this._logger.log(qe.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(qe.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this._reconnectDelayHandle),this._reconnectDelayHandle=void 0,this._completeClose(),Promise.resolve()):(this._cleanupTimeout(),this._cleanupPingTimer(),this._stopDuringStartError=e||new Error("The connection was stopped before the hub handshake could complete."),this.connection.stop(e)))}stream(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._createStreamInvocation(e,t,r);let i;const s=new Ct;return s.cancelCallback=()=>{const e=this._createCancelInvocation(o.invocationId);return delete this._callbacks[o.invocationId],i.then((()=>this._sendWithProtocol(e)))},this._callbacks[o.invocationId]=(e,t)=>{t?s.error(t):e&&(e.type===Xe.Completion?e.error?s.error(new Error(e.error)):s.complete():s.next(e.item))},i=this._sendWithProtocol(o).catch((e=>{s.error(e),delete this._callbacks[o.invocationId]})),this._launchStreams(n,i),s}_sendMessage(e){return this._resetKeepAliveInterval(),this.connection.send(e)}_sendWithProtocol(e){return this._sendMessage(this._protocol.writeMessage(e))}send(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._sendWithProtocol(this._createInvocation(e,t,!0,r));return this._launchStreams(n,o),o}invoke(e,...t){const[n,r]=this._replaceStreamingParams(t),o=this._createInvocation(e,t,!1,r);return new Promise(((e,t)=>{this._callbacks[o.invocationId]=(n,r)=>{r?t(r):n&&(n.type===Xe.Completion?n.error?t(new Error(n.error)):e(n.result):t(new Error(`Unexpected message type: ${n.type}`)))};const r=this._sendWithProtocol(o).catch((e=>{t(e),delete this._callbacks[o.invocationId]}));this._launchStreams(n,r)}))}on(e,t){e&&t&&(e=e.toLowerCase(),this._methods[e]||(this._methods[e]=[]),-1===this._methods[e].indexOf(t)&&this._methods[e].push(t))}off(e,t){if(!e)return;e=e.toLowerCase();const n=this._methods[e];if(n)if(t){const r=n.indexOf(t);-1!==r&&(n.splice(r,1),0===n.length&&delete this._methods[e])}else delete this._methods[e]}onclose(e){e&&this._closedCallbacks.push(e)}onreconnecting(e){e&&this._reconnectingCallbacks.push(e)}onreconnected(e){e&&this._reconnectedCallbacks.push(e)}_processIncomingData(e){if(this._cleanupTimeout(),this._receivedHandshakeResponse||(e=this._processHandshakeResponse(e),this._receivedHandshakeResponse=!0),e){const t=this._protocol.parseMessages(e,this._logger);for(const e of t)switch(e.type){case Xe.Invocation:this._invokeClientMethod(e);break;case Xe.StreamItem:case Xe.Completion:{const t=this._callbacks[e.invocationId];if(t){e.type===Xe.Completion&&delete this._callbacks[e.invocationId];try{t(e)}catch(e){this._logger.log(qe.Error,`Stream callback threw error: ${lt(e)}`)}}break}case Xe.Ping:break;case Xe.Close:{this._logger.log(qe.Information,"Close message received from server.");const t=e.error?new Error("Server returned an error on close: "+e.error):void 0;!0===e.allowReconnect?this.connection.stop(t):this._stopPromise=this._stopInternal(t);break}default:this._logger.log(qe.Warning,`Invalid message type: ${e.type}.`)}}this._resetTimeoutPeriod()}_processHandshakeResponse(e){let t,n;try{[n,t]=this._handshakeProtocol.parseHandshakeResponse(e)}catch(e){const t="Error parsing handshake response: "+e;this._logger.log(qe.Error,t);const n=new Error(t);throw this._handshakeRejecter(n),n}if(t.error){const e="Server returned handshake error: "+t.error;this._logger.log(qe.Error,e);const n=new Error(e);throw this._handshakeRejecter(n),n}return this._logger.log(qe.Debug,"Server handshake complete."),this._handshakeResolver(),n}_resetKeepAliveInterval(){this.connection.features.inherentKeepAlive||(this._nextKeepAlive=(new Date).getTime()+this.keepAliveIntervalInMilliseconds,this._cleanupPingTimer())}_resetTimeoutPeriod(){if(!(this.connection.features&&this.connection.features.inherentKeepAlive||(this._timeoutHandle=setTimeout((()=>this.serverTimeout()),this.serverTimeoutInMilliseconds),void 0!==this._pingServerHandle))){let e=this._nextKeepAlive-(new Date).getTime();e<0&&(e=0),this._pingServerHandle=setTimeout((async()=>{if(this._connectionState===Ye.Connected)try{await this._sendMessage(this._cachedPingMessage)}catch{this._cleanupPingTimer()}}),e)}}serverTimeout(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))}_invokeClientMethod(e){const t=this._methods[e.target.toLowerCase()];if(t){try{t.forEach((t=>t.apply(this,e.arguments)))}catch(t){this._logger.log(qe.Error,`A callback for the method ${e.target.toLowerCase()} threw error '${t}'.`)}if(e.invocationId){const e="Server requested a response, which is not supported in this version of the client.";this._logger.log(qe.Error,e),this._stopPromise=this._stopInternal(new Error(e))}}else this._logger.log(qe.Warning,`No client method with the name '${e.target}' found.`)}_connectionClosed(e){this._logger.log(qe.Debug,`HubConnection.connectionClosed(${e}) called while in state ${this._connectionState}.`),this._stopDuringStartError=this._stopDuringStartError||e||new Error("The underlying connection was closed before the hub handshake could complete."),this._handshakeResolver&&this._handshakeResolver(),this._cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this._cleanupTimeout(),this._cleanupPingTimer(),this._connectionState===Ye.Disconnecting?this._completeClose(e):this._connectionState===Ye.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===Ye.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=Ye.Disconnected,this._connectionStarted=!1,Ze.isBrowser&&document&&document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(qe.Error,`An onclose callback called with error '${e}' threw error '${t}'.`)}}}async _reconnect(e){const t=Date.now();let n=0,r=void 0!==e?e:new Error("Attempting to reconnect due to a unknown error."),o=this._getNextRetryDelay(n++,0,r);if(null===o)return this._logger.log(qe.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),void this._completeClose(e);if(this._connectionState=Ye.Reconnecting,e?this._logger.log(qe.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(qe.Information,"Connection reconnecting."),0!==this._reconnectingCallbacks.length){try{this._reconnectingCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(qe.Error,`An onreconnecting callback called with error '${e}' threw error '${t}'.`)}if(this._connectionState!==Ye.Reconnecting)return void this._logger.log(qe.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.")}for(;null!==o;){if(this._logger.log(qe.Information,`Reconnect attempt number ${n} will start in ${o} ms.`),await new Promise((e=>{this._reconnectDelayHandle=setTimeout(e,o)})),this._reconnectDelayHandle=void 0,this._connectionState!==Ye.Reconnecting)return void this._logger.log(qe.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");try{if(await this._startInternal(),this._connectionState=Ye.Connected,this._logger.log(qe.Information,"HubConnection reconnected successfully."),0!==this._reconnectedCallbacks.length)try{this._reconnectedCallbacks.forEach((e=>e.apply(this,[this.connection.connectionId])))}catch(e){this._logger.log(qe.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${e}'.`)}return}catch(e){if(this._logger.log(qe.Information,`Reconnect attempt failed because of error '${e}'.`),this._connectionState!==Ye.Reconnecting)return this._logger.log(qe.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),void(this._connectionState===Ye.Disconnecting&&this._completeClose());r=e instanceof Error?e:new Error(e.toString()),o=this._getNextRetryDelay(n++,Date.now()-t,r)}}this._logger.log(qe.Information,`Reconnect retries have been exhausted after ${Date.now()-t} ms and ${n} failed attempts. Connection disconnecting.`),this._completeClose()}_getNextRetryDelay(e,t,n){try{return this._reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:t,previousRetryCount:e,retryReason:n})}catch(n){return this._logger.log(qe.Error,`IRetryPolicy.nextRetryDelayInMilliseconds(${e}, ${t}) threw error '${n}'.`),null}}_cancelCallbacksWithError(e){const t=this._callbacks;this._callbacks={},Object.keys(t).forEach((n=>{const r=t[n];try{r(null,e)}catch(t){this._logger.log(qe.Error,`Stream 'error' callback called with '${e}' threw error: ${lt(t)}`)}}))}_cleanupPingTimer(){this._pingServerHandle&&(clearTimeout(this._pingServerHandle),this._pingServerHandle=void 0)}_cleanupTimeout(){this._timeoutHandle&&clearTimeout(this._timeoutHandle)}_createInvocation(e,t,n,r){if(n)return 0!==r.length?{arguments:t,streamIds:r,target:e,type:Xe.Invocation}:{arguments:t,target:e,type:Xe.Invocation};{const n=this._invocationId;return this._invocationId++,0!==r.length?{arguments:t,invocationId:n.toString(),streamIds:r,target:e,type:Xe.Invocation}:{arguments:t,invocationId:n.toString(),target:e,type:Xe.Invocation}}}_launchStreams(e,t){if(0!==e.length){t||(t=Promise.resolve());for(const n in e)e[n].subscribe({complete:()=>{t=t.then((()=>this._sendWithProtocol(this._createCompletionMessage(n))))},error:e=>{let r;r=e instanceof Error?e.message:e&&e.toString?e.toString():"Unknown error",t=t.then((()=>this._sendWithProtocol(this._createCompletionMessage(n,r))))},next:e=>{t=t.then((()=>this._sendWithProtocol(this._createStreamItemMessage(n,e))))}})}}_replaceStreamingParams(e){const t=[],n=[];for(let r=0;r=55296&&o<=56319&&r65535&&(h-=65536,i.push(h>>>10&1023|55296),h=56320|1023&h),i.push(h)}else i.push(a);i.length>=4096&&(s+=String.fromCharCode.apply(String,i),i.length=0)}return i.length>0&&(s+=String.fromCharCode.apply(String,i)),s}var Mt,Ot=Ut?new TextDecoder:null,Ft=Ut?"undefined"!=typeof process&&"force"!==process.env.TEXT_DECODER?200:0:xt,Ht=function(e,t){this.type=e,this.data=t},jt=(Mt=function(e,t){return(Mt=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}Mt(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Wt=function(e){function t(n){var r=e.call(this,n)||this,o=Object.create(t.prototype);return Object.setPrototypeOf(r,o),Object.defineProperty(r,"name",{configurable:!0,enumerable:!1,value:t.name}),r}return jt(t,e),t}(Error),zt={type:-1,encode:function(e){var t,n,r,o;return e instanceof Date?function(e){var t,n=e.sec,r=e.nsec;if(n>=0&&r>=0&&n<=17179869183){if(0===r&&n<=4294967295){var o=new Uint8Array(4);return(t=new DataView(o.buffer)).setUint32(0,n),o}var i=n/4294967296,s=4294967295&n;return o=new Uint8Array(8),(t=new DataView(o.buffer)).setUint32(0,r<<2|3&i),t.setUint32(4,s),o}return o=new Uint8Array(12),(t=new DataView(o.buffer)).setUint32(0,r),Rt(t,4,n),o}((r=1e6*((t=e.getTime())-1e3*(n=Math.floor(t/1e3))),{sec:n+(o=Math.floor(r/1e9)),nsec:r-1e9*o})):null},decode:function(e){var t=function(e){var t=new DataView(e.buffer,e.byteOffset,e.byteLength);switch(e.byteLength){case 4:return{sec:t.getUint32(0),nsec:0};case 8:var n=t.getUint32(0);return{sec:4294967296*(3&n)+t.getUint32(4),nsec:n>>>2};case 12:return{sec:Pt(t,4),nsec:t.getUint32(0)};default:throw new Wt("Unrecognized data size for timestamp (expected 4, 8, or 12): "+e.length)}}(e);return new Date(1e3*t.sec+t.nsec/1e6)}},Jt=function(){function e(){this.builtInEncoders=[],this.builtInDecoders=[],this.encoders=[],this.decoders=[],this.register(zt)}return e.prototype.register=function(e){var t=e.type,n=e.encode,r=e.decode;if(t>=0)this.encoders[t]=n,this.decoders[t]=r;else{var o=1+t;this.builtInEncoders[o]=n,this.builtInDecoders[o]=r}},e.prototype.tryToEncode=function(e,t){for(var n=0;nthis.maxDepth)throw new Error("Too deep objects in depth "+t);null==e?this.encodeNil():"boolean"==typeof e?this.encodeBoolean(e):"number"==typeof e?this.encodeNumber(e):"string"==typeof e?this.encodeString(e):this.encodeObject(e,t)},e.prototype.ensureBufferSizeToWrite=function(e){var t=this.pos+e;this.view.byteLength=0?e<128?this.writeU8(e):e<256?(this.writeU8(204),this.writeU8(e)):e<65536?(this.writeU8(205),this.writeU16(e)):e<4294967296?(this.writeU8(206),this.writeU32(e)):(this.writeU8(207),this.writeU64(e)):e>=-32?this.writeU8(224|e+32):e>=-128?(this.writeU8(208),this.writeI8(e)):e>=-32768?(this.writeU8(209),this.writeI16(e)):e>=-2147483648?(this.writeU8(210),this.writeI32(e)):(this.writeU8(211),this.writeI64(e)):this.forceFloat32?(this.writeU8(202),this.writeF32(e)):(this.writeU8(203),this.writeF64(e))},e.prototype.writeStringHeader=function(e){if(e<32)this.writeU8(160+e);else if(e<256)this.writeU8(217),this.writeU8(e);else if(e<65536)this.writeU8(218),this.writeU16(e);else{if(!(e<4294967296))throw new Error("Too long string: "+e+" bytes in UTF-8");this.writeU8(219),this.writeU32(e)}},e.prototype.encodeString=function(e){if(e.length>$t){var t=At(e);this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),Bt(e,this.bytes,this.pos),this.pos+=t}else t=At(e),this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),function(e,t,n){for(var r=e.length,o=n,i=0;i>6&31|192;else{if(s>=55296&&s<=56319&&i>12&15|224,t[o++]=s>>6&63|128):(t[o++]=s>>18&7|240,t[o++]=s>>12&63|128,t[o++]=s>>6&63|128)}t[o++]=63&s|128}else t[o++]=s}}(e,this.bytes,this.pos),this.pos+=t},e.prototype.encodeObject=function(e,t){var n=this.extensionCodec.tryToEncode(e,this.context);if(null!=n)this.encodeExtension(n);else if(Array.isArray(e))this.encodeArray(e,t);else if(ArrayBuffer.isView(e))this.encodeBinary(e);else{if("object"!=typeof e)throw new Error("Unrecognized object: "+Object.prototype.toString.apply(e));this.encodeMap(e,t)}},e.prototype.encodeBinary=function(e){var t=e.byteLength;if(t<256)this.writeU8(196),this.writeU8(t);else if(t<65536)this.writeU8(197),this.writeU16(t);else{if(!(t<4294967296))throw new Error("Too large binary: "+t);this.writeU8(198),this.writeU32(t)}var n=qt(e);this.writeU8a(n)},e.prototype.encodeArray=function(e,t){var n=e.length;if(n<16)this.writeU8(144+n);else if(n<65536)this.writeU8(220),this.writeU16(n);else{if(!(n<4294967296))throw new Error("Too large array: "+n);this.writeU8(221),this.writeU32(n)}for(var r=0,o=e;r0&&e<=this.maxKeyLength},e.prototype.find=function(e,t,n){e:for(var r=0,o=this.caches[n-1];r=this.maxLengthPerKey?n[Math.random()*n.length|0]=r:n.push(r)},e.prototype.decode=function(e,t,n){var r=this.find(e,t,n);if(null!=r)return this.hit++,r;this.miss++;var o=Lt(e,t,n),i=Uint8Array.prototype.slice.call(e,t,t+n);return this.store(i,o),o},e}(),Yt=function(e,t){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;s;)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 s.label++,{value:i[1],done:!1};case 5:s.label++,r=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!((o=(o=s.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]1||a(e,t)}))})}function a(e,t){try{(n=o[e](t)).value instanceof Qt?Promise.resolve(n.value.v).then(c,l):h(i[0][2],n)}catch(e){h(i[0][3],e)}var n}function c(e){a("next",e)}function l(e){a("throw",e)}function h(e,t){e(t),i.shift(),i.length&&a(i[0][0],i[0][1])}},en=new DataView(new ArrayBuffer(0)),tn=new Uint8Array(en.buffer),nn=function(){try{en.getInt8(0)}catch(e){return e.constructor}throw new Error("never reached")}(),rn=new nn("Insufficient data"),on=new Xt,sn=function(){function e(e,t,n,r,o,i,s,a){void 0===e&&(e=Jt.defaultCodec),void 0===t&&(t=void 0),void 0===n&&(n=xt),void 0===r&&(r=xt),void 0===o&&(o=xt),void 0===i&&(i=xt),void 0===s&&(s=xt),void 0===a&&(a=on),this.extensionCodec=e,this.context=t,this.maxStrLength=n,this.maxBinLength=r,this.maxArrayLength=o,this.maxMapLength=i,this.maxExtLength=s,this.keyDecoder=a,this.totalPos=0,this.pos=0,this.view=en,this.bytes=tn,this.headByte=-1,this.stack=[]}return e.prototype.reinitializeState=function(){this.totalPos=0,this.headByte=-1,this.stack.length=0},e.prototype.setBuffer=function(e){this.bytes=qt(e),this.view=function(e){if(e instanceof ArrayBuffer)return new DataView(e);var t=qt(e);return new DataView(t.buffer,t.byteOffset,t.byteLength)}(this.bytes),this.pos=0},e.prototype.appendBuffer=function(e){if(-1!==this.headByte||this.hasRemaining(1)){var t=this.bytes.subarray(this.pos),n=qt(e),r=new Uint8Array(t.length+n.length);r.set(t),r.set(n,t.length),this.setBuffer(r)}else this.setBuffer(e)},e.prototype.hasRemaining=function(e){return this.view.byteLength-this.pos>=e},e.prototype.createExtraByteError=function(e){var t=this.view,n=this.pos;return new RangeError("Extra "+(t.byteLength-n)+" of "+t.byteLength+" byte(s) found at buffer["+e+"]")},e.prototype.decode=function(e){this.reinitializeState(),this.setBuffer(e);var t=this.doDecodeSync();if(this.hasRemaining(1))throw this.createExtraByteError(this.pos);return t},e.prototype.decodeMulti=function(e){return Yt(this,(function(t){switch(t.label){case 0:this.reinitializeState(),this.setBuffer(e),t.label=1;case 1:return this.hasRemaining(1)?[4,this.doDecodeSync()]:[3,3];case 2:return t.sent(),[3,1];case 3:return[2]}}))},e.prototype.decodeAsync=function(e){var t,n,r,o,i,s,a;return i=this,void 0,a=function(){var i,s,a,c,l,h,u,d;return Yt(this,(function(p){switch(p.label){case 0:i=!1,p.label=1;case 1:p.trys.push([1,6,7,12]),t=Gt(e),p.label=2;case 2:return[4,t.next()];case 3:if((n=p.sent()).done)return[3,5];if(a=n.value,i)throw this.createExtraByteError(this.totalPos);this.appendBuffer(a);try{s=this.doDecodeSync(),i=!0}catch(e){if(!(e instanceof nn))throw e}this.totalPos+=this.pos,p.label=4;case 4:return[3,2];case 5:return[3,12];case 6:return c=p.sent(),r={error:c},[3,12];case 7:return p.trys.push([7,,10,11]),n&&!n.done&&(o=t.return)?[4,o.call(t)]:[3,9];case 8:p.sent(),p.label=9;case 9:return[3,11];case 10:if(r)throw r.error;return[7];case 11:return[7];case 12:if(i){if(this.hasRemaining(1))throw this.createExtraByteError(this.totalPos);return[2,s]}throw h=(l=this).headByte,u=l.pos,d=l.totalPos,new RangeError("Insufficient data in parsing "+Kt(h)+" at "+d+" ("+u+" in the current buffer)")}}))},new((s=void 0)||(s=Promise))((function(e,t){function n(e){try{o(a.next(e))}catch(e){t(e)}}function r(e){try{o(a.throw(e))}catch(e){t(e)}}function o(t){var o;t.done?e(t.value):(o=t.value,o instanceof s?o:new s((function(e){e(o)}))).then(n,r)}o((a=a.apply(i,[])).next())}))},e.prototype.decodeArrayStream=function(e){return this.decodeMultiAsync(e,!0)},e.prototype.decodeStream=function(e){return this.decodeMultiAsync(e,!1)},e.prototype.decodeMultiAsync=function(e,t){return Zt(this,arguments,(function(){var n,r,o,i,s,a,c,l,h;return Yt(this,(function(u){switch(u.label){case 0:n=t,r=-1,u.label=1;case 1:u.trys.push([1,13,14,19]),o=Gt(e),u.label=2;case 2:return[4,Qt(o.next())];case 3:if((i=u.sent()).done)return[3,12];if(s=i.value,t&&0===r)throw this.createExtraByteError(this.totalPos);this.appendBuffer(s),n&&(r=this.readArraySize(),n=!1,this.complete()),u.label=4;case 4:u.trys.push([4,9,,10]),u.label=5;case 5:return[4,Qt(this.doDecodeSync())];case 6:return[4,u.sent()];case 7:return u.sent(),0==--r?[3,8]:[3,5];case 8:return[3,10];case 9:if(!((a=u.sent())instanceof nn))throw a;return[3,10];case 10:this.totalPos+=this.pos,u.label=11;case 11:return[3,2];case 12:return[3,19];case 13:return c=u.sent(),l={error:c},[3,19];case 14:return u.trys.push([14,,17,18]),i&&!i.done&&(h=o.return)?[4,Qt(h.call(o))]:[3,16];case 15:u.sent(),u.label=16;case 16:return[3,18];case 17:if(l)throw l.error;return[7];case 18:return[7];case 19:return[2]}}))}))},e.prototype.doDecodeSync=function(){e:for(;;){var e=this.readHeadByte(),t=void 0;if(e>=224)t=e-256;else if(e<192)if(e<128)t=e;else if(e<144){if(0!=(r=e-128)){this.pushMapState(r),this.complete();continue e}t={}}else if(e<160){if(0!=(r=e-144)){this.pushArrayState(r),this.complete();continue e}t=[]}else{var n=e-160;t=this.decodeUtf8String(n,0)}else if(192===e)t=null;else if(194===e)t=!1;else if(195===e)t=!0;else if(202===e)t=this.readF32();else if(203===e)t=this.readF64();else if(204===e)t=this.readU8();else if(205===e)t=this.readU16();else if(206===e)t=this.readU32();else if(207===e)t=this.readU64();else if(208===e)t=this.readI8();else if(209===e)t=this.readI16();else if(210===e)t=this.readI32();else if(211===e)t=this.readI64();else if(217===e)n=this.lookU8(),t=this.decodeUtf8String(n,1);else if(218===e)n=this.lookU16(),t=this.decodeUtf8String(n,2);else if(219===e)n=this.lookU32(),t=this.decodeUtf8String(n,4);else if(220===e){if(0!==(r=this.readU16())){this.pushArrayState(r),this.complete();continue e}t=[]}else if(221===e){if(0!==(r=this.readU32())){this.pushArrayState(r),this.complete();continue e}t=[]}else if(222===e){if(0!==(r=this.readU16())){this.pushMapState(r),this.complete();continue e}t={}}else if(223===e){if(0!==(r=this.readU32())){this.pushMapState(r),this.complete();continue e}t={}}else if(196===e){var r=this.lookU8();t=this.decodeBinary(r,1)}else if(197===e)r=this.lookU16(),t=this.decodeBinary(r,2);else if(198===e)r=this.lookU32(),t=this.decodeBinary(r,4);else if(212===e)t=this.decodeExtension(1,0);else if(213===e)t=this.decodeExtension(2,0);else if(214===e)t=this.decodeExtension(4,0);else if(215===e)t=this.decodeExtension(8,0);else if(216===e)t=this.decodeExtension(16,0);else if(199===e)r=this.lookU8(),t=this.decodeExtension(r,1);else if(200===e)r=this.lookU16(),t=this.decodeExtension(r,2);else{if(201!==e)throw new Wt("Unrecognized type byte: "+Kt(e));r=this.lookU32(),t=this.decodeExtension(r,4)}this.complete();for(var o=this.stack;o.length>0;){var i=o[o.length-1];if(0===i.type){if(i.array[i.position]=t,i.position++,i.position!==i.size)continue e;o.pop(),t=i.array}else{if(1===i.type){if("string"!=(s=typeof t)&&"number"!==s)throw new Wt("The type of key must be string or number but "+typeof t);if("__proto__"===t)throw new Wt("The key __proto__ is not allowed");i.key=t,i.type=2;continue e}if(i.map[i.key]=t,i.readCount++,i.readCount!==i.size){i.key=null,i.type=1;continue e}o.pop(),t=i.map}}return t}var s},e.prototype.readHeadByte=function(){return-1===this.headByte&&(this.headByte=this.readU8()),this.headByte},e.prototype.complete=function(){this.headByte=-1},e.prototype.readArraySize=function(){var e=this.readHeadByte();switch(e){case 220:return this.readU16();case 221:return this.readU32();default:if(e<160)return e-144;throw new Wt("Unrecognized array type byte: "+Kt(e))}},e.prototype.pushMapState=function(e){if(e>this.maxMapLength)throw new Wt("Max length exceeded: map length ("+e+") > maxMapLengthLength ("+this.maxMapLength+")");this.stack.push({type:1,size:e,key:null,readCount:0,map:{}})},e.prototype.pushArrayState=function(e){if(e>this.maxArrayLength)throw new Wt("Max length exceeded: array length ("+e+") > maxArrayLength ("+this.maxArrayLength+")");this.stack.push({type:0,size:e,array:new Array(e),position:0})},e.prototype.decodeUtf8String=function(e,t){var n;if(e>this.maxStrLength)throw new Wt("Max length exceeded: UTF-8 byte length ("+e+") > maxStrLength ("+this.maxStrLength+")");if(this.bytes.byteLengthFt?function(e,t,n){var r=e.subarray(t,t+n);return Ot.decode(r)}(this.bytes,o,e):Lt(this.bytes,o,e),this.pos+=t+e,r},e.prototype.stateIsMapKey=function(){return this.stack.length>0&&1===this.stack[this.stack.length-1].type},e.prototype.decodeBinary=function(e,t){if(e>this.maxBinLength)throw new Wt("Max length exceeded: bin length ("+e+") > maxBinLength ("+this.maxBinLength+")");if(!this.hasRemaining(e+t))throw rn;var n=this.pos+t,r=this.bytes.subarray(n,n+e);return this.pos+=t+e,r},e.prototype.decodeExtension=function(e,t){if(e>this.maxExtLength)throw new Wt("Max length exceeded: ext length ("+e+") > maxExtLength ("+this.maxExtLength+")");var n=this.view.getInt8(this.pos+t),r=this.decodeBinary(e,t+1);return this.extensionCodec.decode(r,n,this.context)},e.prototype.lookU8=function(){return this.view.getUint8(this.pos)},e.prototype.lookU16=function(){return this.view.getUint16(this.pos)},e.prototype.lookU32=function(){return this.view.getUint32(this.pos)},e.prototype.readU8=function(){var e=this.view.getUint8(this.pos);return this.pos++,e},e.prototype.readI8=function(){var e=this.view.getInt8(this.pos);return this.pos++,e},e.prototype.readU16=function(){var e=this.view.getUint16(this.pos);return this.pos+=2,e},e.prototype.readI16=function(){var e=this.view.getInt16(this.pos);return this.pos+=2,e},e.prototype.readU32=function(){var e=this.view.getUint32(this.pos);return this.pos+=4,e},e.prototype.readI32=function(){var e=this.view.getInt32(this.pos);return this.pos+=4,e},e.prototype.readU64=function(){var e,t,n=(e=this.view,t=this.pos,4294967296*e.getUint32(t)+e.getUint32(t+4));return this.pos+=8,n},e.prototype.readI64=function(){var e=Pt(this.view,this.pos);return this.pos+=8,e},e.prototype.readF32=function(){var e=this.view.getFloat32(this.pos);return this.pos+=4,e},e.prototype.readF64=function(){var e=this.view.getFloat64(this.pos);return this.pos+=8,e},e}();class an{static write(e){let t=e.byteLength||e.length;const n=[];do{let e=127&t;t>>=7,t>0&&(e|=128),n.push(e)}while(t>0);t=e.byteLength||e.length;const r=new Uint8Array(n.length+t);return r.set(n,0),r.set(e,n.length),r.buffer}static parse(e){const t=[],n=new Uint8Array(e),r=[0,7,14,21,28];for(let o=0;o7)throw new Error("Messages bigger than 2GB are not supported.");if(!(n.byteLength>=o+s+a))throw new Error("Incomplete message.");t.push(n.slice?n.slice(o+s,o+s+a):n.subarray(o+s,o+s+a)),o=o+s+a}return t}}const cn=new Uint8Array([145,Xe.Ping]);class ln{constructor(e){this.name="messagepack",this.version=1,this.transferFormat=Ke.Binary,this._errorResult=1,this._voidResult=2,this._nonVoidResult=3,e=e||{},this._encoder=new Vt(e.extensionCodec,e.context,e.maxDepth,e.initialBufferSize,e.sortKeys,e.forceFloat32,e.ignoreUndefined,e.forceIntegerToFloat),this._decoder=new sn(e.extensionCodec,e.context,e.maxStrLength,e.maxBinLength,e.maxArrayLength,e.maxMapLength,e.maxExtLength)}parseMessages(e,t){if(!(n=e)||"undefined"==typeof ArrayBuffer||!(n instanceof ArrayBuffer||n.constructor&&"ArrayBuffer"===n.constructor.name))throw new Error("Invalid input for MessagePack hub protocol. Expected an ArrayBuffer.");var n;null===t&&(t=Ge.instance);const r=an.parse(e),o=[];for(const e of r){const n=this._parseMessage(e,t);n&&o.push(n)}return o}writeMessage(e){switch(e.type){case Xe.Invocation:return this._writeInvocation(e);case Xe.StreamInvocation:return this._writeStreamInvocation(e);case Xe.StreamItem:return this._writeStreamItem(e);case Xe.Completion:return this._writeCompletion(e);case Xe.Ping:return an.write(cn);case Xe.CancelInvocation:return this._writeCancelInvocation(e);default:throw new Error("Invalid message type.")}}_parseMessage(e,t){if(0===e.length)throw new Error("Invalid payload.");const n=this._decoder.decode(e);if(0===n.length||!(n instanceof Array))throw new Error("Invalid payload.");const r=n[0];switch(r){case Xe.Invocation:return this._createInvocationMessage(this._readHeaders(n),n);case Xe.StreamItem:return this._createStreamItemMessage(this._readHeaders(n),n);case Xe.Completion:return this._createCompletionMessage(this._readHeaders(n),n);case Xe.Ping:return this._createPingMessage(n);case Xe.Close:return this._createCloseMessage(n);default:return t.log(qe.Information,"Unknown message type '"+r+"' ignored."),null}}_createCloseMessage(e){if(e.length<2)throw new Error("Invalid payload for Close message.");return{allowReconnect:e.length>=3?e[2]:void 0,error:e[1],type:Xe.Close}}_createPingMessage(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:Xe.Ping}}_createInvocationMessage(e,t){if(t.length<5)throw new Error("Invalid payload for Invocation message.");const n=t[2];return n?{arguments:t[4],headers:e,invocationId:n,streamIds:[],target:t[3],type:Xe.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:Xe.Invocation}}_createStreamItemMessage(e,t){if(t.length<4)throw new Error("Invalid payload for StreamItem message.");return{headers:e,invocationId:t[2],item:t[3],type:Xe.StreamItem}}_createCompletionMessage(e,t){if(t.length<4)throw new Error("Invalid payload for Completion message.");const n=t[3];if(n!==this._voidResult&&t.length<5)throw new Error("Invalid payload for Completion message.");let r,o;switch(n){case this._errorResult:r=t[4];break;case this._nonVoidResult:o=t[4]}return{error:r,headers:e,invocationId:t[2],result:o,type:Xe.Completion}}_writeInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Xe.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]):this._encoder.encode([Xe.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments]),an.write(t.slice())}_writeStreamInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Xe.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]):this._encoder.encode([Xe.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments]),an.write(t.slice())}_writeStreamItem(e){const t=this._encoder.encode([Xe.StreamItem,e.headers||{},e.invocationId,e.item]);return an.write(t.slice())}_writeCompletion(e){const t=e.error?this._errorResult:e.result?this._nonVoidResult:this._voidResult;let n;switch(t){case this._errorResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t,e.error]);break;case this._voidResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t]);break;case this._nonVoidResult:n=this._encoder.encode([Xe.Completion,e.headers||{},e.invocationId,t,e.result])}return an.write(n.slice())}_writeCancelInvocation(e){const t=this._encoder.encode([Xe.CancelInvocation,e.headers||{},e.invocationId]);return an.write(t.slice())}_readHeaders(e){const t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t}}let hn=!1;async function un(){let e=document.querySelector("#blazor-error-ui");e&&(e.style.display="block"),hn||(hn=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach((e=>{e.onclick=function(e){location.reload(),e.preventDefault()}})),document.querySelectorAll("#blazor-error-ui .dismiss").forEach((e=>{e.onclick=function(e){const t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})))}const dn="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,pn=dn?dn.decode.bind(dn):function(e){let t=0;const n=e.length,r=[],o=[];for(;t65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")},fn=Math.pow(2,32),gn=Math.pow(2,21)-1;function mn(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function yn(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function wn(e,t){const n=yn(e,t+4);if(n>gn)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*fn+yn(e,t)}class vn{constructor(e){this.batchData=e;const t=new Sn(e);this.arrayRangeReader=new Cn(e),this.arrayBuilderSegmentReader=new In(e),this.diffReader=new bn(e),this.editReader=new _n(e,t),this.frameReader=new En(e,t)}updatedComponents(){return mn(this.batchData,this.batchData.length-20)}referenceFrames(){return mn(this.batchData,this.batchData.length-16)}disposedComponentIds(){return mn(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return mn(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return mn(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return mn(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return wn(this.batchData,n)}}class bn{constructor(e){this.batchDataUint8=e}componentId(e){return mn(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class _n{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return mn(this.batchDataUint8,e)}siblingIndex(e){return mn(this.batchDataUint8,e+4)}newTreeIndex(e){return mn(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return mn(this.batchDataUint8,e+8)}removedAttributeName(e){const t=mn(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class En{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return mn(this.batchDataUint8,e)}subtreeLength(e){return mn(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return mn(this.batchDataUint8,e+8)}elementName(e){const t=mn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=mn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=mn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return wn(this.batchDataUint8,e+12)}}class Sn{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=mn(e,e.length-4)}readString(e){if(-1===e)return null;{const n=mn(this.batchDataUint8,this.stringTableStartIndex+4*e),r=function(e,t){let n=0,r=0;for(let o=0;o<4;o++){const i=e[t+o];if(n|=(127&i)<this.nextBatchId)return this.fatalError?(this.logger.log(kn.Debug,`Received a new batch ${e} but errored out on a previous batch ${this.nextBatchId-1}`),void await n.send("OnRenderCompleted",this.nextBatchId-1,this.fatalError.toString())):void this.logger.log(kn.Debug,`Waiting for batch ${this.nextBatchId}. Batch ${e} not processed.`);try{this.nextBatchId++,this.logger.log(kn.Debug,`Applying batch ${e}.`),function(e,t){const n=ue[e];if(!n)throw new Error(`There is no browser renderer with ID ${e}.`);const r=t.arrayRangeReader,o=t.updatedComponents(),i=r.values(o),s=r.count(o),a=t.referenceFrames(),c=r.values(a),l=t.diffReader;for(let e=0;e=this.minLevel){const n=`[${(new Date).toISOString()}] ${kn[e]}: ${t}`;switch(e){case kn.Critical:case kn.Error:console.error(n);break;case kn.Warning:console.warn(n);break;case kn.Information:console.info(n);break;default:console.log(n)}}}}class Rn{constructor(e,t){this.circuitId=void 0,this.components=e,this.applicationState=t}reconnect(e){if(!this.circuitId)throw new Error("Circuit host not initialized.");return e.state!==Ye.Connected?Promise.resolve(!1):e.invoke("ConnectCircuit",this.circuitId)}initialize(e){if(this.circuitId)throw new Error(`Circuit host '${this.circuitId}' already initialized.`);this.circuitId=e}async startCircuit(e){if(e.state!==Ye.Connected)return!1;const t=await e.invoke("StartCircuit",me.getBaseURI(),me.getLocationHref(),JSON.stringify(this.components.map((e=>e.toRecord()))),this.applicationState||"");return!!t&&(this.initialize(t),!0)}resolveElement(e){const t=function(e){const t=g.get(e);if(t)return g.delete(e),t}(e);if(t)return L(t,!0);const n=Number.parseInt(e);if(!Number.isNaN(n))return function(e,t){if(!e.parentNode)throw new Error(`Comment not connected to the DOM ${e.textContent}`);const n=e.parentNode,r=L(n,!0),o=z(r);return Array.from(n.childNodes).forEach((e=>o.push(e))),e[$]=r,t&&(e[B]=t,L(t)),L(e)}(this.components[n].start,this.components[n].end);throw new Error(`Invalid sequence number or identifier '${e}'.`)}}const Pn={configureSignalR:e=>{},logLevel:kn.Warning,reconnectionOptions:{maxRetries:8,retryIntervalMilliseconds:2e4,dialogId:"components-reconnect-modal"}};class Un{constructor(e,t,n,r){this.maxRetries=t,this.document=n,this.logger=r,this.addedToDom=!1,this.modal=this.document.createElement("div"),this.modal.id=e,this.maxRetries=t,this.modal.style.cssText=["position: fixed","top: 0","right: 0","bottom: 0","left: 0","z-index: 1050","display: none","overflow: hidden","background-color: #fff","opacity: 0.8","text-align: center","font-weight: bold","transition: visibility 0s linear 500ms"].join(";"),this.modal.innerHTML='

Alternatively, reload

',this.message=this.modal.querySelector("h5"),this.button=this.modal.querySelector("button"),this.reloadParagraph=this.modal.querySelector("p"),this.loader=this.getLoader(),this.message.after(this.loader),this.button.addEventListener("click",(async()=>{this.show();try{await Ae.reconnect()||this.rejected()}catch(e){this.logger.log(kn.Error,e),this.failed()}})),this.reloadParagraph.querySelector("a").addEventListener("click",(()=>location.reload()))}show(){this.addedToDom||(this.addedToDom=!0,this.document.body.appendChild(this.modal)),this.modal.style.display="block",this.loader.style.display="inline-block",this.button.style.display="none",this.reloadParagraph.style.display="none",this.message.textContent="Attempting to reconnect to the server...",this.modal.style.visibility="hidden",setTimeout((()=>{this.modal.style.visibility="visible"}),0)}update(e){this.message.textContent=`Attempting to reconnect to the server: ${e} of ${this.maxRetries}`}hide(){this.modal.style.display="none"}failed(){this.button.style.display="block",this.reloadParagraph.style.display="none",this.loader.style.display="none",this.message.innerHTML="Reconnection failed. Try reloading the page if you're unable to reconnect.",this.message.querySelector("a").addEventListener("click",(()=>location.reload()))}rejected(){this.button.style.display="none",this.reloadParagraph.style.display="none",this.loader.style.display="none",this.message.innerHTML="Could not reconnect to the server. Reload the page to restore functionality.",this.message.querySelector("a").addEventListener("click",(()=>location.reload()))}getLoader(){const e=this.document.createElement("div");return e.style.cssText=["border: 0.3em solid #f3f3f3","border-top: 0.3em solid #3498db","border-radius: 50%","width: 2em","height: 2em","display: inline-block"].join(";"),e.animate([{transform:"rotate(0deg)"},{transform:"rotate(360deg)"}],{duration:2e3,iterations:1/0}),e}}class An{constructor(e,t,n){this.dialog=e,this.maxRetries=t,this.document=n,this.document=n;const r=this.document.getElementById(An.MaxRetriesId);r&&(r.innerText=this.maxRetries.toString())}show(){this.removeClasses(),this.dialog.classList.add(An.ShowClassName)}update(e){const t=this.document.getElementById(An.CurrentAttemptId);t&&(t.innerText=e.toString())}hide(){this.removeClasses(),this.dialog.classList.add(An.HideClassName)}failed(){this.removeClasses(),this.dialog.classList.add(An.FailedClassName)}rejected(){this.removeClasses(),this.dialog.classList.add(An.RejectedClassName)}removeClasses(){this.dialog.classList.remove(An.ShowClassName,An.HideClassName,An.FailedClassName,An.RejectedClassName)}}An.ShowClassName="components-reconnect-show",An.HideClassName="components-reconnect-hide",An.FailedClassName="components-reconnect-failed",An.RejectedClassName="components-reconnect-rejected",An.MaxRetriesId="components-reconnect-max-retries",An.CurrentAttemptId="components-reconnect-current-attempt";class Nn{constructor(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||Ae.reconnect}onConnectionDown(e,t){if(!this._reconnectionDisplay){const t=document.getElementById(e.dialogId);this._reconnectionDisplay=t?new An(t,e.maxRetries,document):new Un(e.dialogId,e.maxRetries,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new $n(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))}onConnectionUp(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)}}class $n{constructor(e,t,n,r){this.logger=t,this.reconnectCallback=n,this.isDisposed=!1,this.reconnectDisplay=r,this.reconnectDisplay.show(),this.attemptPeriodicReconnection(e)}dispose(){this.isDisposed=!0,this.reconnectDisplay.hide()}async attemptPeriodicReconnection(e){for(let t=0;t$n.MaximumFirstRetryInterval?$n.MaximumFirstRetryInterval:e.retryIntervalMilliseconds;if(await this.delay(n),this.isDisposed)break;try{return await this.reconnectCallback()?void 0:void this.reconnectDisplay.rejected()}catch(e){this.logger.log(kn.Error,e)}}this.reconnectDisplay.failed()}delay(e){return new Promise((t=>setTimeout(t,e)))}}$n.MaximumFirstRetryInterval=3e3;const Bn=/^\s*Blazor-Component-State:(?[a-zA-Z0-9\+\/=]+)$/;function Ln(e){var t;if(e.nodeType===Node.COMMENT_NODE){const n=e.textContent||"",r=Bn.exec(n),o=r&&r.groups&&r.groups.state;return o&&(null===(t=e.parentNode)||void 0===t||t.removeChild(e)),o}if(!e.hasChildNodes())return;const n=e.childNodes;for(let e=0;e.*)$/);function Fn(e,t){const n=e.currentElement;if(n&&n.nodeType===Node.COMMENT_NODE&&n.textContent){const r=On.exec(n.textContent),o=r&&r.groups&&r.groups.descriptor;if(!o)return;try{const r=function(e){const t=JSON.parse(e),{type:n}=t;if("server"!==n&&"webassembly"!==n)throw new Error(`Invalid component type '${n}'.`);return t}(o);switch(t){case"webassembly":return function(e,t,n){const{type:r,assembly:o,typeName:i,parameterDefinitions:s,parameterValues:a,prerenderId:c}=e;if("webassembly"===r){if(!o)throw new Error("assembly must be defined when using a descriptor.");if(!i)throw new Error("typeName must be defined when using a descriptor.");if(c){const e=Hn(c,n);if(!e)throw new Error(`Could not find an end component comment for '${t}'`);return{type:r,assembly:o,typeName:i,parameterDefinitions:s&&atob(s),parameterValues:a&&atob(a),start:t,prerenderId:c,end:e}}return{type:r,assembly:o,typeName:i,parameterDefinitions:s&&atob(s),parameterValues:a&&atob(a),start:t}}}(r,n,e);case"server":return function(e,t,n){const{type:r,descriptor:o,sequence:i,prerenderId:s}=e;if("server"===r){if(!o)throw new Error("descriptor must be defined when using a descriptor.");if(void 0===i)throw new Error("sequence must be defined when using a descriptor.");if(!Number.isInteger(i))throw new Error(`Error parsing the sequence '${i}' for component '${JSON.stringify(e)}'`);if(s){const e=Hn(s,n);if(!e)throw new Error(`Could not find an end component comment for '${t}'`);return{type:r,sequence:i,descriptor:o,start:t,prerenderId:s,end:e}}return{type:r,sequence:i,descriptor:o,start:t}}}(r,n,e)}}catch(e){throw new Error(`Found malformed component comment at ${n.textContent}`)}}}function Hn(e,t){for(;t.next()&&t.currentElement;){const n=t.currentElement;if(n.nodeType!==Node.COMMENT_NODE)continue;if(!n.textContent)continue;const r=On.exec(n.textContent),o=r&&r[1];if(o)return jn(o,e),n}}function jn(e,t){const n=JSON.parse(e);if(1!==Object.keys(n).length)throw new Error(`Invalid end of component comment: '${e}'`);const r=n.prerenderId;if(!r)throw new Error(`End of component comment must have a value for the prerendered property: '${e}'`);if(r!==t)throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${t}', '${r}'`)}class Wn{constructor(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}next(){return this.currentIndex++,this.currentIndexasync function(e,n){const r=function(e){const t=document.baseURI;return t.endsWith("/")?`${t}${e}`:`${t}/${e}`}(n),o=await import(r);if(void 0===o)return;const{beforeStart:i,afterStarted:s}=o;return s&&e.afterStartedCallbacks.push(s),i?i(...t):void 0}(this,e))))}async invokeAfterStartedCallbacks(e){await Promise.all(this.afterStartedCallbacks.map((t=>t(e))))}}let Vn=!1,Kn=!1;async function Xn(e){if(Kn)throw new Error("Blazor has already started.");Kn=!0;const t=function(e){const t={...Pn,...e};return e&&e.reconnectionOptions&&(t.reconnectionOptions={...Pn.reconnectionOptions,...e.reconnectionOptions}),t}(e),n=await async function(e){const t=await fetch("_blazor/initializers",{method:"GET",credentials:"include",cache:"no-cache"}),n=await t.json(),r=new qn;return await r.importInitializersAsync(n,[e]),r}(t),r=new xn(t.logLevel);Ae.reconnect=async e=>{if(Vn)return!1;const n=e||await Yn(t,r,s);return await s.reconnect(n)?(t.reconnectionHandler.onConnectionUp(),!0):(r.log(kn.Information,"Reconnection attempt to the circuit was rejected by the server. This may indicate that the associated state is no longer available on the server."),!1)},Ae.defaultReconnectionHandler=new Nn(r),t.reconnectionHandler=t.reconnectionHandler||Ae.defaultReconnectionHandler,r.log(kn.Information,"Starting up Blazor server-side application.");const o=function(e,t){return function(e){const t=Mn(e,"server"),n=[];for(let e=0;ee.sequence-t.sequence))}(e)}(document),i=Ln(document),s=new Rn(o,i||""),a=await Yn(t,r,s);if(!await s.startCircuit(a))return void r.log(kn.Error,"Failed to start the circuit.");let c=!1;const l=()=>{if(!c){const e=new FormData,t=s.circuitId;e.append("circuitId",t),c=navigator.sendBeacon("_blazor/disconnect",e)}};Ae.disconnect=l,window.addEventListener("unload",l,{capture:!1,once:!0}),r.log(kn.Information,"Blazor server-side application started."),n.invokeAfterStartedCallbacks(Ae)}async function Yn(t,n,r){const o=new ln;o.name="blazorpack";const i=(new Dt).withUrl("_blazor").withHubProtocol(o);t.configureSignalR(i);const s=i.build();Ae._internal.navigationManager.listenForNavigationEvents(((e,t)=>s.send("OnLocationChanged",e,t))),s.on("JS.AttachComponent",((e,t)=>function(e,t,n,r){let o=ue[0];o||(o=ue[0]=new ie(0)),o.attachRootComponentToLogicalElement(n,t,!1)}(0,r.resolveElement(t),e))),s.on("JS.BeginInvokeJS",e.jsCallDispatcher.beginInvokeJSFromDotNet),s.on("JS.EndInvokeDotNet",e.jsCallDispatcher.endInvokeDotNetFromJS),s.on("JS.ReceiveByteArray",e.jsCallDispatcher.receiveByteArray),s.on("JS.BeginTransmitStream",(t=>{const n=new ReadableStream({start(e){s.stream("SendDotNetStreamToJS",t).subscribe({next:t=>e.enqueue(t),complete:()=>e.close(),error:t=>e.error(t)})}});e.jsCallDispatcher.supplyDotNetStream(t,n)}));const a=Tn.getOrCreate(n);s.on("JS.RenderBatch",((e,t)=>{n.log(kn.Debug,`Received render batch with id ${e} and ${t.byteLength} bytes.`),a.processBatch(e,t,s)})),s.onclose((e=>!Vn&&t.reconnectionHandler.onConnectionDown(t.reconnectionOptions,e))),s.on("JS.Error",(e=>{Vn=!0,Gn(s,e,n),un()})),Ae._internal.forceCloseConnection=()=>s.stop(),Ae._internal.sendJSDataStream=(e,t,n)=>function(e,t,n,r){setTimeout((async()=>{let o=5,i=(new Date).valueOf();try{const s=t instanceof Blob?t.size:t.byteLength;let a=0,c=0;for(;a1)await e.send("ReceiveJSDataChunk",n,c,h,null);else{if(!await e.invoke("ReceiveJSDataChunk",n,c,h,null))break;const t=(new Date).valueOf(),r=t-i;i=t,o=Math.max(1,Math.round(500/Math.max(1,r)))}a+=l,c++}}catch(t){await e.send("ReceiveJSDataChunk",n,-1,null,t.toString())}}),0)}(s,e,t,n);try{await s.start()}catch(e){if(Gn(s,e,n),"FailedToNegotiateWithServerError"===e.errorType)throw e;un()}return e.attachDispatcher({beginInvokeDotNetFromJS:(e,t,n,r,o)=>{s.send("BeginInvokeDotNetFromJS",e?e.toString():null,t,n,r||0,o)},endInvokeJSFromDotNet:(e,t,n)=>{s.send("EndInvokeJSFromDotNet",e,t,n)},sendByteArray:(e,t)=>{s.send("ReceiveByteArray",e,t)}}),s}function Gn(e,t,n){n.log(kn.Error,t),e&&e.stop()}Ae.start=Xn,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&Xn()})(); \ No newline at end of file diff --git a/src/Components/Web.JS/dist/Release/blazor.webview.js b/src/Components/Web.JS/dist/Release/blazor.webview.js index ae32b75d30b6..239a6fbddece 100644 --- a/src/Components/Web.JS/dist/Release/blazor.webview.js +++ b/src/Components/Web.JS/dist/Release/blazor.webview.js @@ -1 +1 @@ -(()=>{"use strict";var e,t,n;!function(e){window.DotNet=e;const t=[],n=new Map,r=new Map,o="__jsObjectId",a="__byte[]";class s{constructor(e){this._jsObject=e,this._cachedFunctions=new Map}findFunction(e){const t=this._cachedFunctions.get(e);if(t)return t;let n,r=this._jsObject;if(e.split(".").forEach((t=>{if(!(t in r))throw new Error(`Could not find '${e}' ('${t}' was undefined).`);n=r,r=r[t]})),r instanceof Function)return r=r.bind(n),this._cachedFunctions.set(e,r),r;throw new Error(`The value '${e}' is not a function.`)}getWrappedObject(){return this._jsObject}}const i={},c={0:new s(window)};c[0]._cachedFunctions.set("import",(e=>("string"==typeof e&&e.startsWith("./")&&(e=document.baseURI+e.substr(2)),import(e))));let l,u=1,d=1,f=null;function h(e){t.push(e)}function m(e){if(e&&"object"==typeof e){c[d]=new s(e);const t={[o]:d};return d++,t}throw new Error(`Cannot create a JSObjectReference from the value '${e}'.`)}function p(e){let t=-1;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),e instanceof Blob)t=e.size;else{if(!(e.buffer instanceof ArrayBuffer))throw new Error("Supplied value is not a typed array or blob.");if(void 0===e.byteLength)throw new Error(`Cannot create a JSStreamReference from the value '${e}' as it doesn't have a byteLength.`);t=e.byteLength}const n={__jsStreamReferenceLength:t};try{const t=m(e);n.__jsObjectId=t.__jsObjectId}catch{throw new Error(`Cannot create a JSStreamReference from the value '${e}'.`)}return n}function b(e){return e?JSON.parse(e,((e,n)=>t.reduce(((t,n)=>n(e,t)),n))):null}function v(e,t,n,r){const o=y();if(o.invokeDotNetFromJS){const a=N(r),s=o.invokeDotNetFromJS(e,t,n,a);return s?b(s):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function g(e,t,n,r){if(e&&n)throw new Error(`For instance method calls, assemblyName should be null. Received '${e}'.`);const o=u++,a=new Promise(((e,t)=>{i[o]={resolve:e,reject:t}}));try{const a=N(r);y().beginInvokeDotNetFromJS(o,e,t,n,a)}catch(e){w(o,!1,e)}return a}function y(){if(null!==f)return f;throw new Error("No .NET call dispatcher has been set.")}function w(e,t,n){if(!i.hasOwnProperty(e))throw new Error(`There is no pending async call with ID ${e}.`);const r=i[e];delete i[e],t?r.resolve(n):r.reject(n)}function E(e){return e instanceof Error?`${e.message}\n${e.stack}`:e?e.toString():"null"}function I(e,t){let n=c[t];if(n)return n.findFunction(e);throw new Error(`JS object instance with ID ${t} does not exist (has it been disposed?).`)}function S(e){delete c[e]}e.attachDispatcher=function(e){f=e},e.attachReviver=h,e.invokeMethod=function(e,t,...n){return v(e,t,null,n)},e.invokeMethodAsync=function(e,t,...n){return g(e,t,null,n)},e.createJSObjectReference=m,e.createJSStreamReference=p,e.disposeJSObjectReference=function(e){const t=e&&e.__jsObjectId;"number"==typeof t&&S(t)},function(e){e[e.Default=0]="Default",e[e.JSObjectReference=1]="JSObjectReference",e[e.JSStreamReference=2]="JSStreamReference",e[e.JSVoidResult=3]="JSVoidResult"}(l=e.JSCallResultType||(e.JSCallResultType={})),e.jsCallDispatcher={findJSFunction:I,disposeJSObjectReferenceById:S,invokeJSFromDotNet:(e,t,n,r)=>{const o=k(I(e,r).apply(null,b(t)),n);return null==o?null:N(o)},beginInvokeJSFromDotNet:(e,t,n,r,o)=>{const a=new Promise((e=>{e(I(t,o).apply(null,b(n)))}));e&&a.then((t=>y().endInvokeJSFromDotNet(e,!0,N([e,!0,k(t,r)]))),(t=>y().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,E(t)]))))},endInvokeDotNetFromJS:(e,t,n)=>{const r=t?b(n):new Error(n);w(parseInt(e),t,r)},receiveByteArray:(e,t)=>{n.set(e,t)},supplyDotNetStream:(e,t)=>{if(r.has(e)){const n=r.get(e);r.delete(e),n.resolve(t)}else{const n=new A;n.resolve(t),r.set(e,n)}}};class C{constructor(e){this._id=e}invokeMethod(e,...t){return v(null,e,this._id,t)}invokeMethodAsync(e,...t){return g(null,e,this._id,t)}dispose(){g(null,"__Dispose",this._id,null).catch((e=>console.error(e)))}serializeAsArg(){return{__dotNetObject:this._id}}}e.DotNetObject=C,h((function(e,t){if(t&&"object"==typeof t){if(t.hasOwnProperty("__dotNetObject"))return new C(t.__dotNetObject);if(t.hasOwnProperty(o)){const e=t.__jsObjectId,n=c[e];if(n)return n.getWrappedObject();throw new Error(`JS object instance with Id '${e}' does not exist. It may have been disposed.`)}if(t.hasOwnProperty(a)){const e=t["__byte[]"],r=n.get(e);if(void 0===r)throw new Error(`Byte array index '${e}' does not exist.`);return n.delete(e),r}if(t.hasOwnProperty("__dotNetStream"))return new D(t.__dotNetStream)}return t}));class D{constructor(e){var t;if(r.has(e))this._streamPromise=null===(t=r.get(e))||void 0===t?void 0:t.streamPromise,r.delete(e);else{const t=new A;r.set(e,t),this._streamPromise=t.streamPromise}}stream(){return this._streamPromise}async arrayBuffer(){return new Response(await this.stream()).arrayBuffer()}}class A{constructor(){this.streamPromise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}function k(e,t){switch(t){case l.Default:return e;case l.JSObjectReference:return m(e);case l.JSStreamReference:return p(e);case l.JSVoidResult:return null;default:throw new Error(`Invalid JS call result type '${t}'.`)}}let R=0;function N(e){return R=0,JSON.stringify(e,T)}function T(e,t){if(t instanceof C)return t.serializeAsArg();if(t instanceof Uint8Array){f.sendByteArray(R,t);const e={[a]:R};return R++,e}return t}}(e||(e={})),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t||(t={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(n||(n={}));class r{constructor(e,t){this.componentId=e,this.fieldValue=t}static fromEvent(e,t){const n=t.target;if(n instanceof Element){const t=function(e){return e instanceof HTMLInputElement?e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value}:e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?{value:e.value}:null}(n);if(t)return new r(e,t.value)}return null}}const o=new Map,a=new Map,s={createEventArgs:()=>({})},i=[];function c(e){return o.get(e)}function l(e){const t=o.get(e);return(null==t?void 0:t.browserEventName)||e}function u(e,t){e.forEach((e=>o.set(e,t)))}function d(e){const t=[];for(let n=0;ne.selected)).map((e=>e.value))}}return{value:function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(t)?!!t.checked:t.value}}}),u(["copy","cut","paste"],s),u(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...f(t=e),dataTransfer:t.dataTransfer?{dropEffect:t.dataTransfer.dropEffect,effectAllowed:t.dataTransfer.effectAllowed,files:Array.from(t.dataTransfer.files).map((e=>e.name)),items:Array.from(t.dataTransfer.items).map((e=>({kind:e.kind,type:e.type}))),types:t.dataTransfer.types}:null};var t}}),u(["focus","blur","focusin","focusout"],s),u(["keydown","keyup","keypress"],{createEventArgs:e=>{return{key:(t=e).key,code:t.code,location:t.location,repeat:t.repeat,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey};var t}}),u(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>f(e)}),u(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),u(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),u(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:d(t.touches),targetTouches:d(t.targetTouches),changedTouches:d(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),u(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...f(t=e),pointerId:t.pointerId,width:t.width,height:t.height,pressure:t.pressure,tiltX:t.tiltX,tiltY:t.tiltY,pointerType:t.pointerType,isPrimary:t.isPrimary};var t}}),u(["wheel","mousewheel"],{createEventArgs:e=>{return{...f(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),u(["toggle"],s);const h=["date","datetime-local","month","time","week"],m=new Map;let p,b,v=0;const g={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++v).toString();m.set(r,e);const o=await E().invokeMethodAsync("AddRootComponent",t,r),a=new w(o,b[t]);return await a.setParameters(n),a}};class y{invoke(e){return this._callback(e)}setCallback(t){this._selfJSObjectReference||(this._selfJSObjectReference=e.createJSObjectReference(this)),this._callback=t}getJSObjectReference(){return this._selfJSObjectReference}dispose(){this._selfJSObjectReference&&e.disposeJSObjectReference(this._selfJSObjectReference)}}class w{constructor(e,t){this._jsEventCallbackWrappers=new Map,this._componentId=e;for(const e of t)"eventcallback"===e.type&&this._jsEventCallbackWrappers.set(e.name.toLowerCase(),new y)}setParameters(e){const t={},n=Object.entries(e||{}),r=n.length;for(const[e,r]of n){const n=this._jsEventCallbackWrappers.get(e.toLowerCase());n&&r?(n.setCallback(r),t[e]=n.getJSObjectReference()):t[e]=r}return E().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await E().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function E(){if(!p)throw new Error("Dynamic root components have not been enabled in this application.");return p}const I=new Map;function S(e,t,n){return D(e,t.eventHandlerId,(()=>C(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function C(e){const t=I.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let D=(e,t,n)=>n();const A=O(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),k={submit:!0},R=O(["click","dblclick","mousedown","mousemove","mouseup"]);class N{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++N.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new T(this.onGlobalEvent.bind(this))}setListener(e,t,n,r){const o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{const a={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(a),o.setHandler(t,a)}}getHandler(e){return this.eventInfoStore.get(e)}removeListener(e){const t=this.eventInfoStore.remove(e);if(t){const e=t.element,n=this.getEventHandlerInfosForElement(e,!1);n&&n.removeHandler(t.eventName)}}notifyAfterClick(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")}setStopPropagation(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)}setPreventDefault(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)}onGlobalEvent(e){if(!(e.target instanceof Element))return;this.dispatchGlobalEventToAllElements(e.type,e);const t=(n=e.type,a.get(n));var n;t&&t.forEach((t=>this.dispatchGlobalEventToAllElements(t,e))),"click"===e.type&&this.afterClickCallbacks.forEach((t=>t(e)))}dispatchGlobalEventToAllElements(e,t){const n=t.composedPath();let o=n.shift(),a=null,s=!1;const i=A.hasOwnProperty(e);let l=!1;for(;o;){const f=o,h=this.getEventHandlerInfosForElement(f,!1);if(h){const n=h.getHandler(e);if(n&&(u=f,d=t.type,!((u instanceof HTMLButtonElement||u instanceof HTMLInputElement||u instanceof HTMLTextAreaElement||u instanceof HTMLSelectElement)&&R.hasOwnProperty(d)&&u.disabled))){if(!s){const n=c(e);a=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},s=!0}k.hasOwnProperty(t.type)&&t.preventDefault(),S(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:r.fromEvent(n.renderingComponentId,t)},a)}h.stopPropagation(e)&&(l=!0),h.preventDefault(e)&&t.preventDefault()}o=i||l?void 0:n.shift()}var u,d}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new _:null}}N.nextEventDelegatorId=0;class T{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},i.push(this.handleEventNameAliasAdded.bind(this))}add(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error(`Event ${e.eventHandlerId} is already tracked`);this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)}get(e){return this.infosByEventHandlerId[e]}addGlobalListener(e){if(e=l(e),this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;const t=A.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}}update(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error(`Event ${t} is already tracked`);const n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n}remove(e){const t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];const n=l(t.eventName);0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t}handleEventNameAliasAdded(e,t){if(this.countByEventName.hasOwnProperty(e)){const n=this.countByEventName[e];delete this.countByEventName[e],document.removeEventListener(e,this.globalListener),this.addGlobalListener(t),this.countByEventName[t]+=n-1}}}class _{constructor(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}getHandler(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null}setHandler(e,t){this.handlers[e]=t}removeHandler(e){delete this.handlers[e]}preventDefault(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]}stopPropagation(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]}}function O(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const F=Y("_blazorLogicalChildren"),x=Y("_blazorLogicalParent"),L=Y("_blazorLogicalEnd");function P(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return F in e||(e[F]=[]),e}function j(e,t){const n=document.createComment("!");return M(n,e,t),n}function M(e,t,n){const r=e;if(e instanceof Comment&&$(r)&&$(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(H(r))throw new Error("Not implemented: moving existing logical children");const o=$(t);if(n0;)B(n,0)}const r=n;r.parentNode.removeChild(r)}function H(e){return e[x]||null}function U(e,t){return $(e)[t]}function J(e){var t=K(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function $(e){return e[F]}function z(e,t){const n=$(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=X(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):W(r,e)})),t.forEach((e=>{const t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd;let a=r;for(;a;){const e=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=e}n.removeChild(t)})),t.forEach((e=>{n[e.toSiblingIndex]=e.moveRangeStart}))}function K(e){if(e instanceof Element||e instanceof DocumentFragment)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function V(e){const t=$(H(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function W(e,t){if(t instanceof Element||t instanceof DocumentFragment)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error(`Cannot append node because the parent is not a valid logical element. Parent: ${t}`);{const n=V(t);n?n.parentNode.insertBefore(e,n):W(e,H(t))}}}function X(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=V(e);if(t)return t.previousSibling;{const t=H(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:X(t)}}function Y(e){return"function"==typeof Symbol?Symbol():e}function G(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${G(e)}]`;return document.querySelector(t)}(t.__internalId):t));const q="_blazorDeferredValue",Z=document.createElement("template"),Q=document.createElementNS("http://www.w3.org/2000/svg","g"),ee={},te="__internal_",ne="preventDefault_",re="stopPropagation_";class oe{constructor(e){this.rootComponentIds=new Set,this.childComponentLocations={},this.eventDelegator=new N(e),this.eventDelegator.notifyAfterClick((e=>{if(!fe)return;if(0!==e.button||function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e))return;if(e.defaultPrevented)return;const t=function(e){const t=!window._blazorDisableComposedPath&&e.composedPath&&e.composedPath();if(t){for(let e=0;ege(!1))))},enableNavigationInterception:function(){fe=!0},navigateTo:be,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function be(e,t,n=!1){const r=we(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Ie(r)?ve(r,!1,o.replaceHistoryEntry):function(e,t){if(location.href===e){const t=e+"?";history.replaceState(null,"",t),location.replace(e)}else t?location.replace(e):location.href=e}(e,o.replaceHistoryEntry)}function ve(e,t,n){de=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),ge(t)}async function ge(e){me&&await me(location.href,e)}let ye;function we(e){return ye=ye||document.createElement("a"),ye.href=e,ye.href}function Ee(e,t){return e?e.tagName===t?e:Ee(e.parentElement,t):null}function Ie(e){const t=(n=document.baseURI).substr(0,n.lastIndexOf("/")+1);var n;return e.startsWith(t)}const Se={focus:function(e,t){if(e instanceof HTMLElement)e.focus({preventScroll:t});else{if(!(e instanceof SVGElement))throw new Error("Unable to focus an invalid element.");if(!e.hasAttribute("tabindex"))throw new Error("Unable to focus an SVG element that does not have a tabindex.");e.focus({preventScroll:t})}},focusBySelector:function(e){const t=document.querySelector(e);t&&(t.hasAttribute("tabindex")||(t.tabIndex=-1),t.focus())}},Ce={init:function(e,t,n,r=50){const o=Ae(t);(o||document.documentElement).style.overflowAnchor="none";const a=new IntersectionObserver((function(r){r.forEach((r=>{var o;if(!r.isIntersecting)return;const a=t.getBoundingClientRect(),s=n.getBoundingClientRect().top-a.bottom,i=null===(o=r.rootBounds)||void 0===o?void 0:o.height;r.target===t?e.invokeMethodAsync("OnSpacerBeforeVisible",r.intersectionRect.top-r.boundingClientRect.top,s,i):r.target===n&&n.offsetHeight>0&&e.invokeMethodAsync("OnSpacerAfterVisible",r.boundingClientRect.bottom-r.intersectionRect.bottom,s,i)}))}),{root:o,rootMargin:`${r}px`});a.observe(t),a.observe(n);const s=c(t),i=c(n);function c(e){const t=new MutationObserver((()=>{a.unobserve(e),a.observe(e)}));return t.observe(e,{attributes:!0}),t}De[e._id]={intersectionObserver:a,mutationObserverBefore:s,mutationObserverAfter:i}},dispose:function(e){const t=De[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete De[e._id])}},De={};function Ae(e){return e?"visible"!==getComputedStyle(e).overflowY?e:Ae(e.parentElement):null}const ke={getAndRemoveExistingTitle:function(){var e;const t=document.getElementsByTagName("title");if(0===t.length)return null;let n=null;for(let r=t.length-1;r>=0;r--){const o=t[r],a=o.previousSibling;a instanceof Comment&&null!==H(a)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},Re={init:function(e,t){t._blazorInputFileNextFileId=0,t.addEventListener("click",(function(){t.value=""})),t.addEventListener("change",(function(){t._blazorFilesById={};const n=Array.prototype.map.call(t.files,(function(e){const n={id:++t._blazorInputFileNextFileId,lastModified:new Date(e.lastModified).toISOString(),name:e.name,size:e.size,contentType:e.type,readPromise:void 0,arrayBuffer:void 0,blob:e};return t._blazorFilesById[n.id]=n,n}));e.invokeMethodAsync("NotifyChange",n)}))},toImageFile:async function(e,t,n,r,o){const a=Ne(e,t),s=await new Promise((function(e){const t=new Image;t.onload=function(){URL.revokeObjectURL(t.src),e(t)},t.onerror=function(){t.onerror=null,URL.revokeObjectURL(t.src)},t.src=URL.createObjectURL(a.blob)})),i=await new Promise((function(e){var t;const a=Math.min(1,r/s.width),i=Math.min(1,o/s.height),c=Math.min(a,i),l=document.createElement("canvas");l.width=Math.round(s.width*c),l.height=Math.round(s.height*c),null===(t=l.getContext("2d"))||void 0===t||t.drawImage(s,0,0,l.width,l.height),l.toBlob(e,n)})),c={id:++e._blazorInputFileNextFileId,lastModified:a.lastModified,name:a.name,size:(null==i?void 0:i.size)||0,contentType:n,blob:i||a.blob};return e._blazorFilesById[c.id]=c,c},readFileData:async function(e,t){return Ne(e,t).blob}};function Ne(e,t){const n=e._blazorFilesById[t];if(!n)throw new Error(`There is no file with ID ${t}. The file list may have changed.`);return n}const Te=new Map,_e={navigateTo:be,registerCustomEventType:function(e,t){if(!t)throw new Error("The options parameter is required.");if(o.has(e))throw new Error(`The event '${e}' is already registered.`);if(t.browserEventName){const n=a.get(t.browserEventName);n?n.push(e):a.set(t.browserEventName,[e]),i.forEach((n=>n(e,t.browserEventName)))}o.set(e,t)},rootComponents:g,_internal:{navigationManager:pe,domWrapper:Se,Virtualize:Ce,PageTitle:ke,InputFile:Re,getJSDataStreamChunk:async function(e,t,n){return e instanceof Blob?await async function(e,t,n){const r=e.slice(t,t+n),o=await r.arrayBuffer();return new Uint8Array(o)}(e,t,n):function(e,t,n){return new Uint8Array(e.buffer,e.byteOffset+t,n)}(e,t,n)},receiveDotNetDataStream:function(t,n,r,o){let a=Te.get(t);if(!a){const n=new ReadableStream({start(e){Te.set(t,e),a=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(a.error(o),Te.delete(t)):0===r?(a.close(),Te.delete(t)):a.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(I.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);I.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(p)throw new Error("Dynamic root components have already been enabled.");p=t,b=n;for(const[t,o]of Object.entries(r)){const r=e.jsCallDispatcher.findJSFunction(t,0);for(const e of o)r(e,n[e])}}(C(t),r,o)}}};window.Blazor=_e;let Oe=!1;const Fe="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,xe=Fe?Fe.decode.bind(Fe):function(e){let t=0;const n=e.length,r=[],o=[];for(;t65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")},Le=Math.pow(2,32),Pe=Math.pow(2,21)-1;function je(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function Me(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function Be(e,t){const n=Me(e,t+4);if(n>Pe)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*Le+Me(e,t)}class He{constructor(e){this.batchData=e;const t=new ze(e);this.arrayRangeReader=new Ke(e),this.arrayBuilderSegmentReader=new Ve(e),this.diffReader=new Ue(e),this.editReader=new Je(e,t),this.frameReader=new $e(e,t)}updatedComponents(){return je(this.batchData,this.batchData.length-20)}referenceFrames(){return je(this.batchData,this.batchData.length-16)}disposedComponentIds(){return je(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return je(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return je(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return je(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return Be(this.batchData,n)}}class Ue{constructor(e){this.batchDataUint8=e}componentId(e){return je(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class Je{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return je(this.batchDataUint8,e)}siblingIndex(e){return je(this.batchDataUint8,e+4)}newTreeIndex(e){return je(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return je(this.batchDataUint8,e+8)}removedAttributeName(e){const t=je(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class $e{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return je(this.batchDataUint8,e)}subtreeLength(e){return je(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return je(this.batchDataUint8,e+8)}elementName(e){const t=je(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=je(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return Be(this.batchDataUint8,e+12)}}class ze{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=je(e,e.length-4)}readString(e){if(-1===e)return null;{const n=je(this.batchDataUint8,this.stringTableStartIndex+4*e),r=function(e,t){let n=0,r=0;for(let o=0;o<4;o++){const a=e[t+o];if(n|=(127&a)<async function(e,n){const r=function(e){const t=document.baseURI;return t.endsWith("/")?`${t}${e}`:`${t}/${e}`}(n),o=await import(r);if(void 0===o)return;const{beforeStart:a,afterStarted:s}=o;return s&&e.afterStartedCallbacks.push(s),a?a(...t):void 0}(this,e))))}async invokeAfterStartedCallbacks(e){await Promise.all(this.afterStartedCallbacks.map((t=>t(e))))}}let ot=!1;async function at(){if(ot)throw new Error("Blazor has already started.");ot=!0;const t=await async function(){const e=await fetch("_framework/blazor.modules.json",{method:"GET",credentials:"include",cache:"no-cache"}),t=await e.json(),n=new rt;return await n.importInitializersAsync(t,[]),n}();(function(){const t={AttachToDocument:(e,t)=>{!function(e,t,n){const r="::after";let o=!1;if(e.endsWith(r))e=e.slice(0,-r.length),o=!0;else if(e.endsWith("::before"))throw new Error("The '::before' selector is not supported.");const a=function(e){const t=m.get(e);if(t)return m.delete(e),t}(e)||document.querySelector(e);if(!a)throw new Error(`Could not find any element matching selector '${e}'.`);!function(e,t,n,r){let o=ue[0];o||(o=ue[0]=new oe(0)),o.attachRootComponentToLogicalElement(n,t,r)}(0,P(a,!0),t,o)}(t,e)},RenderBatch:(e,t)=>{try{const n=nt(t);(function(e,t){const n=ue[0];if(!n)throw new Error("There is no browser renderer with ID 0.");const r=t.arrayRangeReader,o=t.updatedComponents(),a=r.values(o),s=r.count(o),i=t.referenceFrames(),c=r.values(i),l=t.diffReader;for(let e=0;e{Xe=!0,console.error(`${e}\n${t}`),async function(e=""){let t=document.querySelector("#blazor-error-ui");t&&(t.style.display="block",e&&t.firstChild&&(t.firstChild.textContent=`\n\t${e}\t\n`)),Oe||(Oe=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach((e=>{e.onclick=function(e){location.reload(),e.preventDefault()}})),document.querySelectorAll("#blazor-error-ui .dismiss").forEach((e=>{e.onclick=function(e){const t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})))}()},BeginInvokeJS:e.jsCallDispatcher.beginInvokeJSFromDotNet,EndInvokeDotNet:e.jsCallDispatcher.endInvokeDotNetFromJS,SendByteArrayToJS:tt,Navigate:pe.navigateTo};window.external.receiveMessage((e=>{const n=function(e){if(Xe||!e||!e.startsWith(We))return null;const t=e.substring(We.length),[n,...r]=JSON.parse(t);return{messageType:n,args:r}}(e);if(n){if(!t.hasOwnProperty(n.messageType))throw new Error(`Unsupported IPC message type '${n.messageType}'`);t[n.messageType].apply(null,n.args)}}))})(),e.attachDispatcher({beginInvokeDotNetFromJS:Ge,endInvokeJSFromDotNet:qe,sendByteArray:Ze}),pe.enableNavigationInterception(),pe.listenForNavigationEvents(Qe),et("AttachPage",pe.getBaseURI(),pe.getLocationHref()),await t.invokeAfterStartedCallbacks(_e)}_e.start=at,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&at()})(); \ No newline at end of file +(()=>{"use strict";var e,t,n;!function(e){window.DotNet=e;const t=[],n=new Map,r=new Map,o="__jsObjectId",a="__byte[]";class s{constructor(e){this._jsObject=e,this._cachedFunctions=new Map}findFunction(e){const t=this._cachedFunctions.get(e);if(t)return t;let n,r=this._jsObject;if(e.split(".").forEach((t=>{if(!(t in r))throw new Error(`Could not find '${e}' ('${t}' was undefined).`);n=r,r=r[t]})),r instanceof Function)return r=r.bind(n),this._cachedFunctions.set(e,r),r;throw new Error(`The value '${e}' is not a function.`)}getWrappedObject(){return this._jsObject}}const i={},c={0:new s(window)};c[0]._cachedFunctions.set("import",(e=>("string"==typeof e&&e.startsWith("./")&&(e=document.baseURI+e.substr(2)),import(e))));let l,u=1,d=1,f=null;function h(e){t.push(e)}function m(e){if(e&&"object"==typeof e){c[d]=new s(e);const t={[o]:d};return d++,t}throw new Error(`Cannot create a JSObjectReference from the value '${e}'.`)}function p(e){let t=-1;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),e instanceof Blob)t=e.size;else{if(!(e.buffer instanceof ArrayBuffer))throw new Error("Supplied value is not a typed array or blob.");if(void 0===e.byteLength)throw new Error(`Cannot create a JSStreamReference from the value '${e}' as it doesn't have a byteLength.`);t=e.byteLength}const n={__jsStreamReferenceLength:t};try{const t=m(e);n.__jsObjectId=t.__jsObjectId}catch{throw new Error(`Cannot create a JSStreamReference from the value '${e}'.`)}return n}function b(e){return e?JSON.parse(e,((e,n)=>t.reduce(((t,n)=>n(e,t)),n))):null}function v(e,t,n,r){const o=y();if(o.invokeDotNetFromJS){const a=N(r),s=o.invokeDotNetFromJS(e,t,n,a);return s?b(s):null}throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeMethodAsync instead.")}function g(e,t,n,r){if(e&&n)throw new Error(`For instance method calls, assemblyName should be null. Received '${e}'.`);const o=u++,a=new Promise(((e,t)=>{i[o]={resolve:e,reject:t}}));try{const a=N(r);y().beginInvokeDotNetFromJS(o,e,t,n,a)}catch(e){w(o,!1,e)}return a}function y(){if(null!==f)return f;throw new Error("No .NET call dispatcher has been set.")}function w(e,t,n){if(!i.hasOwnProperty(e))throw new Error(`There is no pending async call with ID ${e}.`);const r=i[e];delete i[e],t?r.resolve(n):r.reject(n)}function E(e){return e instanceof Error?`${e.message}\n${e.stack}`:e?e.toString():"null"}function I(e,t){let n=c[t];if(n)return n.findFunction(e);throw new Error(`JS object instance with ID ${t} does not exist (has it been disposed?).`)}function S(e){delete c[e]}e.attachDispatcher=function(e){f=e},e.attachReviver=h,e.invokeMethod=function(e,t,...n){return v(e,t,null,n)},e.invokeMethodAsync=function(e,t,...n){return g(e,t,null,n)},e.createJSObjectReference=m,e.createJSStreamReference=p,e.disposeJSObjectReference=function(e){const t=e&&e.__jsObjectId;"number"==typeof t&&S(t)},function(e){e[e.Default=0]="Default",e[e.JSObjectReference=1]="JSObjectReference",e[e.JSStreamReference=2]="JSStreamReference",e[e.JSVoidResult=3]="JSVoidResult"}(l=e.JSCallResultType||(e.JSCallResultType={})),e.jsCallDispatcher={findJSFunction:I,disposeJSObjectReferenceById:S,invokeJSFromDotNet:(e,t,n,r)=>{const o=k(I(e,r).apply(null,b(t)),n);return null==o?null:N(o)},beginInvokeJSFromDotNet:(e,t,n,r,o)=>{const a=new Promise((e=>{e(I(t,o).apply(null,b(n)))}));e&&a.then((t=>y().endInvokeJSFromDotNet(e,!0,N([e,!0,k(t,r)]))),(t=>y().endInvokeJSFromDotNet(e,!1,JSON.stringify([e,!1,E(t)]))))},endInvokeDotNetFromJS:(e,t,n)=>{const r=t?b(n):new Error(n);w(parseInt(e),t,r)},receiveByteArray:(e,t)=>{n.set(e,t)},supplyDotNetStream:(e,t)=>{if(r.has(e)){const n=r.get(e);r.delete(e),n.resolve(t)}else{const n=new A;n.resolve(t),r.set(e,n)}}};class C{constructor(e){this._id=e}invokeMethod(e,...t){return v(null,e,this._id,t)}invokeMethodAsync(e,...t){return g(null,e,this._id,t)}dispose(){g(null,"__Dispose",this._id,null).catch((e=>console.error(e)))}serializeAsArg(){return{__dotNetObject:this._id}}}e.DotNetObject=C,h((function(e,t){if(t&&"object"==typeof t){if(t.hasOwnProperty("__dotNetObject"))return new C(t.__dotNetObject);if(t.hasOwnProperty(o)){const e=t.__jsObjectId,n=c[e];if(n)return n.getWrappedObject();throw new Error(`JS object instance with Id '${e}' does not exist. It may have been disposed.`)}if(t.hasOwnProperty(a)){const e=t["__byte[]"],r=n.get(e);if(void 0===r)throw new Error(`Byte array index '${e}' does not exist.`);return n.delete(e),r}if(t.hasOwnProperty("__dotNetStream"))return new D(t.__dotNetStream)}return t}));class D{constructor(e){var t;if(r.has(e))this._streamPromise=null===(t=r.get(e))||void 0===t?void 0:t.streamPromise,r.delete(e);else{const t=new A;r.set(e,t),this._streamPromise=t.streamPromise}}stream(){return this._streamPromise}async arrayBuffer(){return new Response(await this.stream()).arrayBuffer()}}class A{constructor(){this.streamPromise=new Promise(((e,t)=>{this.resolve=e,this.reject=t}))}}function k(e,t){switch(t){case l.Default:return e;case l.JSObjectReference:return m(e);case l.JSStreamReference:return p(e);case l.JSVoidResult:return null;default:throw new Error(`Invalid JS call result type '${t}'.`)}}let R=0;function N(e){return R=0,JSON.stringify(e,T)}function T(e,t){if(t instanceof C)return t.serializeAsArg();if(t instanceof Uint8Array){f.sendByteArray(R,t);const e={[a]:R};return R++,e}return t}}(e||(e={})),function(e){e[e.prependFrame=1]="prependFrame",e[e.removeFrame=2]="removeFrame",e[e.setAttribute=3]="setAttribute",e[e.removeAttribute=4]="removeAttribute",e[e.updateText=5]="updateText",e[e.stepIn=6]="stepIn",e[e.stepOut=7]="stepOut",e[e.updateMarkup=8]="updateMarkup",e[e.permutationListEntry=9]="permutationListEntry",e[e.permutationListEnd=10]="permutationListEnd"}(t||(t={})),function(e){e[e.element=1]="element",e[e.text=2]="text",e[e.attribute=3]="attribute",e[e.component=4]="component",e[e.region=5]="region",e[e.elementReferenceCapture=6]="elementReferenceCapture",e[e.markup=8]="markup"}(n||(n={}));class r{constructor(e,t){this.componentId=e,this.fieldValue=t}static fromEvent(e,t){const n=t.target;if(n instanceof Element){const t=function(e){return e instanceof HTMLInputElement?e.type&&"checkbox"===e.type.toLowerCase()?{value:e.checked}:{value:e.value}:e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?{value:e.value}:null}(n);if(t)return new r(e,t.value)}return null}}const o=new Map,a=new Map,s={createEventArgs:()=>({})},i=[];function c(e){return o.get(e)}function l(e){const t=o.get(e);return(null==t?void 0:t.browserEventName)||e}function u(e,t){e.forEach((e=>o.set(e,t)))}function d(e){const t=[];for(let n=0;ne.selected)).map((e=>e.value))}}return{value:function(e){return!!e&&"INPUT"===e.tagName&&"checkbox"===e.getAttribute("type")}(t)?!!t.checked:t.value}}}),u(["copy","cut","paste"],s),u(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...f(t=e),dataTransfer:t.dataTransfer?{dropEffect:t.dataTransfer.dropEffect,effectAllowed:t.dataTransfer.effectAllowed,files:Array.from(t.dataTransfer.files).map((e=>e.name)),items:Array.from(t.dataTransfer.items).map((e=>({kind:e.kind,type:e.type}))),types:t.dataTransfer.types}:null};var t}}),u(["focus","blur","focusin","focusout"],s),u(["keydown","keyup","keypress"],{createEventArgs:e=>{return{key:(t=e).key,code:t.code,location:t.location,repeat:t.repeat,ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey};var t}}),u(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>f(e)}),u(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),u(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),u(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:d(t.touches),targetTouches:d(t.targetTouches),changedTouches:d(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),u(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...f(t=e),pointerId:t.pointerId,width:t.width,height:t.height,pressure:t.pressure,tiltX:t.tiltX,tiltY:t.tiltY,pointerType:t.pointerType,isPrimary:t.isPrimary};var t}}),u(["wheel","mousewheel"],{createEventArgs:e=>{return{...f(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),u(["toggle"],s);const h=["date","datetime-local","month","time","week"],m=new Map;let p,b,v=0;const g={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++v).toString();m.set(r,e);const o=await E().invokeMethodAsync("AddRootComponent",t,r),a=new w(o,b[t]);return await a.setParameters(n),a}};class y{invoke(e){return this._callback(e)}setCallback(t){this._selfJSObjectReference||(this._selfJSObjectReference=e.createJSObjectReference(this)),this._callback=t}getJSObjectReference(){return this._selfJSObjectReference}dispose(){this._selfJSObjectReference&&e.disposeJSObjectReference(this._selfJSObjectReference)}}class w{constructor(e,t){this._jsEventCallbackWrappers=new Map,this._componentId=e;for(const e of t)"eventcallback"===e.type&&this._jsEventCallbackWrappers.set(e.name.toLowerCase(),new y)}setParameters(e){const t={},n=Object.entries(e||{}),r=n.length;for(const[e,r]of n){const n=this._jsEventCallbackWrappers.get(e.toLowerCase());n&&r?(n.setCallback(r),t[e]=n.getJSObjectReference()):t[e]=r}return E().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await E().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function E(){if(!p)throw new Error("Dynamic root components have not been enabled in this application.");return p}const I=new Map;function S(e,t,n){return D(e,t.eventHandlerId,(()=>C(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function C(e){const t=I.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let D=(e,t,n)=>n();const A=O(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),k={submit:!0},R=O(["click","dblclick","mousedown","mousemove","mouseup"]);class N{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++N.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new T(this.onGlobalEvent.bind(this))}setListener(e,t,n,r){const o=this.getEventHandlerInfosForElement(e,!0),a=o.getHandler(t);if(a)this.eventInfoStore.update(a.eventHandlerId,n);else{const a={element:e,eventName:t,eventHandlerId:n,renderingComponentId:r};this.eventInfoStore.add(a),o.setHandler(t,a)}}getHandler(e){return this.eventInfoStore.get(e)}removeListener(e){const t=this.eventInfoStore.remove(e);if(t){const e=t.element,n=this.getEventHandlerInfosForElement(e,!1);n&&n.removeHandler(t.eventName)}}notifyAfterClick(e){this.afterClickCallbacks.push(e),this.eventInfoStore.addGlobalListener("click")}setStopPropagation(e,t,n){this.getEventHandlerInfosForElement(e,!0).stopPropagation(t,n)}setPreventDefault(e,t,n){this.getEventHandlerInfosForElement(e,!0).preventDefault(t,n)}onGlobalEvent(e){if(!(e.target instanceof Element))return;this.dispatchGlobalEventToAllElements(e.type,e);const t=(n=e.type,a.get(n));var n;t&&t.forEach((t=>this.dispatchGlobalEventToAllElements(t,e))),"click"===e.type&&this.afterClickCallbacks.forEach((t=>t(e)))}dispatchGlobalEventToAllElements(e,t){const n=t.composedPath();let o=n.shift(),a=null,s=!1;const i=A.hasOwnProperty(e);let l=!1;for(;o;){const f=o,h=this.getEventHandlerInfosForElement(f,!1);if(h){const n=h.getHandler(e);if(n&&(u=f,d=t.type,!((u instanceof HTMLButtonElement||u instanceof HTMLInputElement||u instanceof HTMLTextAreaElement||u instanceof HTMLSelectElement)&&R.hasOwnProperty(d)&&u.disabled))){if(!s){const n=c(e);a=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},s=!0}k.hasOwnProperty(t.type)&&t.preventDefault(),S(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:r.fromEvent(n.renderingComponentId,t)},a)}h.stopPropagation(e)&&(l=!0),h.preventDefault(e)&&t.preventDefault()}o=i||l?void 0:n.shift()}var u,d}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new _:null}}N.nextEventDelegatorId=0;class T{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},i.push(this.handleEventNameAliasAdded.bind(this))}add(e){if(this.infosByEventHandlerId[e.eventHandlerId])throw new Error(`Event ${e.eventHandlerId} is already tracked`);this.infosByEventHandlerId[e.eventHandlerId]=e,this.addGlobalListener(e.eventName)}get(e){return this.infosByEventHandlerId[e]}addGlobalListener(e){if(e=l(e),this.countByEventName.hasOwnProperty(e))this.countByEventName[e]++;else{this.countByEventName[e]=1;const t=A.hasOwnProperty(e);document.addEventListener(e,this.globalListener,t)}}update(e,t){if(this.infosByEventHandlerId.hasOwnProperty(t))throw new Error(`Event ${t} is already tracked`);const n=this.infosByEventHandlerId[e];delete this.infosByEventHandlerId[e],n.eventHandlerId=t,this.infosByEventHandlerId[t]=n}remove(e){const t=this.infosByEventHandlerId[e];if(t){delete this.infosByEventHandlerId[e];const n=l(t.eventName);0==--this.countByEventName[n]&&(delete this.countByEventName[n],document.removeEventListener(n,this.globalListener))}return t}handleEventNameAliasAdded(e,t){if(this.countByEventName.hasOwnProperty(e)){const n=this.countByEventName[e];delete this.countByEventName[e],document.removeEventListener(e,this.globalListener),this.addGlobalListener(t),this.countByEventName[t]+=n-1}}}class _{constructor(){this.handlers={},this.preventDefaultFlags=null,this.stopPropagationFlags=null}getHandler(e){return this.handlers.hasOwnProperty(e)?this.handlers[e]:null}setHandler(e,t){this.handlers[e]=t}removeHandler(e){delete this.handlers[e]}preventDefault(e,t){return void 0!==t&&(this.preventDefaultFlags=this.preventDefaultFlags||{},this.preventDefaultFlags[e]=t),!!this.preventDefaultFlags&&this.preventDefaultFlags[e]}stopPropagation(e,t){return void 0!==t&&(this.stopPropagationFlags=this.stopPropagationFlags||{},this.stopPropagationFlags[e]=t),!!this.stopPropagationFlags&&this.stopPropagationFlags[e]}}function O(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const F=Y("_blazorLogicalChildren"),x=Y("_blazorLogicalParent"),L=Y("_blazorLogicalEnd");function P(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return F in e||(e[F]=[]),e}function j(e,t){const n=document.createComment("!");return M(n,e,t),n}function M(e,t,n){const r=e;if(e instanceof Comment&&$(r)&&$(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(H(r))throw new Error("Not implemented: moving existing logical children");const o=$(t);if(n0;)B(n,0)}const r=n;r.parentNode.removeChild(r)}function H(e){return e[x]||null}function U(e,t){return $(e)[t]}function J(e){var t=K(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function $(e){return e[F]}function z(e,t){const n=$(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=X(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):W(r,e)})),t.forEach((e=>{const t=e.moveToBeforeMarker,n=t.parentNode,r=e.moveRangeStart,o=e.moveRangeEnd;let a=r;for(;a;){const e=a.nextSibling;if(n.insertBefore(a,t),a===o)break;a=e}n.removeChild(t)})),t.forEach((e=>{n[e.toSiblingIndex]=e.moveRangeStart}))}function K(e){if(e instanceof Element||e instanceof DocumentFragment)return e;if(e instanceof Comment)return e.parentNode;throw new Error("Not a valid logical element")}function V(e){const t=$(H(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function W(e,t){if(t instanceof Element||t instanceof DocumentFragment)t.appendChild(e);else{if(!(t instanceof Comment))throw new Error(`Cannot append node because the parent is not a valid logical element. Parent: ${t}`);{const n=V(t);n?n.parentNode.insertBefore(e,n):W(e,H(t))}}}function X(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=V(e);if(t)return t.previousSibling;{const t=H(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:X(t)}}function Y(e){return"function"==typeof Symbol?Symbol():e}function G(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${G(e)}]`;return document.querySelector(t)}(t.__internalId):t));const q="_blazorDeferredValue",Z=document.createElement("template"),Q=document.createElementNS("http://www.w3.org/2000/svg","g"),ee={},te="__internal_",ne="preventDefault_",re="stopPropagation_";class oe{constructor(e){this.rootComponentIds=new Set,this.childComponentLocations={},this.eventDelegator=new N(e),this.eventDelegator.notifyAfterClick((e=>{if(!fe)return;if(0!==e.button||function(e){return e.ctrlKey||e.shiftKey||e.altKey||e.metaKey}(e))return;if(e.defaultPrevented)return;const t=function(e){const t=!window._blazorDisableComposedPath&&e.composedPath&&e.composedPath();if(t){for(let e=0;ege(!1))))},enableNavigationInterception:function(){fe=!0},navigateTo:be,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function be(e,t,n=!1){const r=we(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Ie(r)?ve(r,!1,o.replaceHistoryEntry):function(e,t){if(location.href===e){const t=e+"?";history.replaceState(null,"",t),location.replace(e)}else t?location.replace(e):location.href=e}(e,o.replaceHistoryEntry)}function ve(e,t,n){de=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),ge(t)}async function ge(e){me&&await me(location.href,e)}let ye;function we(e){return ye=ye||document.createElement("a"),ye.href=e,ye.href}function Ee(e,t){return e?e.tagName===t?e:Ee(e.parentElement,t):null}function Ie(e){const t=(n=document.baseURI).substr(0,n.lastIndexOf("/")+1);var n;return e.startsWith(t)}const Se={focus:function(e,t){if(e instanceof HTMLElement)e.focus({preventScroll:t});else{if(!(e instanceof SVGElement))throw new Error("Unable to focus an invalid element.");if(!e.hasAttribute("tabindex"))throw new Error("Unable to focus an SVG element that does not have a tabindex.");e.focus({preventScroll:t})}},focusBySelector:function(e){const t=document.querySelector(e);t&&(t.hasAttribute("tabindex")||(t.tabIndex=-1),t.focus())}},Ce={init:function(e,t,n,r=50){const o=Ae(t);(o||document.documentElement).style.overflowAnchor="none";const a=new IntersectionObserver((function(r){r.forEach((r=>{var o;if(!r.isIntersecting)return;const a=t.getBoundingClientRect(),s=n.getBoundingClientRect().top-a.bottom,i=null===(o=r.rootBounds)||void 0===o?void 0:o.height;r.target===t?e.invokeMethodAsync("OnSpacerBeforeVisible",r.intersectionRect.top-r.boundingClientRect.top,s,i):r.target===n&&n.offsetHeight>0&&e.invokeMethodAsync("OnSpacerAfterVisible",r.boundingClientRect.bottom-r.intersectionRect.bottom,s,i)}))}),{root:o,rootMargin:`${r}px`});a.observe(t),a.observe(n);const s=c(t),i=c(n);function c(e){const t=new MutationObserver((()=>{a.unobserve(e),a.observe(e)}));return t.observe(e,{attributes:!0}),t}De[e._id]={intersectionObserver:a,mutationObserverBefore:s,mutationObserverAfter:i}},dispose:function(e){const t=De[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete De[e._id])}},De={};function Ae(e){return e?"visible"!==getComputedStyle(e).overflowY?e:Ae(e.parentElement):null}const ke={getAndRemoveExistingTitle:function(){var e;const t=document.getElementsByTagName("title");if(0===t.length)return null;let n=null;for(let r=t.length-1;r>=0;r--){const o=t[r],a=o.previousSibling;a instanceof Comment&&null!==H(a)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},Re={init:function(e,t){t._blazorInputFileNextFileId=0,t.addEventListener("click",(function(){t.value=""})),t.addEventListener("change",(function(){t._blazorFilesById={};const n=Array.prototype.map.call(t.files,(function(e){const n={id:++t._blazorInputFileNextFileId,lastModified:new Date(e.lastModified).toISOString(),name:e.name,size:e.size,contentType:e.type,readPromise:void 0,arrayBuffer:void 0,blob:e};return t._blazorFilesById[n.id]=n,n}));e.invokeMethodAsync("NotifyChange",n)}))},toImageFile:async function(e,t,n,r,o){const a=Ne(e,t),s=await new Promise((function(e){const t=new Image;t.onload=function(){URL.revokeObjectURL(t.src),e(t)},t.onerror=function(){t.onerror=null,URL.revokeObjectURL(t.src)},t.src=URL.createObjectURL(a.blob)})),i=await new Promise((function(e){var t;const a=Math.min(1,r/s.width),i=Math.min(1,o/s.height),c=Math.min(a,i),l=document.createElement("canvas");l.width=Math.round(s.width*c),l.height=Math.round(s.height*c),null===(t=l.getContext("2d"))||void 0===t||t.drawImage(s,0,0,l.width,l.height),l.toBlob(e,n)})),c={id:++e._blazorInputFileNextFileId,lastModified:a.lastModified,name:a.name,size:(null==i?void 0:i.size)||0,contentType:n,blob:i||a.blob};return e._blazorFilesById[c.id]=c,c},readFileData:async function(e,t){return Ne(e,t).blob}};function Ne(e,t){const n=e._blazorFilesById[t];if(!n)throw new Error(`There is no file with ID ${t}. The file list may have changed.`);return n}const Te=new Map,_e={navigateTo:be,registerCustomEventType:function(e,t){if(!t)throw new Error("The options parameter is required.");if(o.has(e))throw new Error(`The event '${e}' is already registered.`);if(t.browserEventName){const n=a.get(t.browserEventName);n?n.push(e):a.set(t.browserEventName,[e]),i.forEach((n=>n(e,t.browserEventName)))}o.set(e,t)},rootComponents:g,_internal:{navigationManager:pe,domWrapper:Se,Virtualize:Ce,PageTitle:ke,InputFile:Re,getJSDataStreamChunk:async function(e,t,n){return e instanceof Blob?await async function(e,t,n){const r=e.slice(t,t+n),o=await r.arrayBuffer();return new Uint8Array(o)}(e,t,n):function(e,t,n){return new Uint8Array(e.buffer,e.byteOffset+t,n)}(e,t,n)},receiveDotNetDataStream:function(t,n,r,o){let a=Te.get(t);if(!a){const n=new ReadableStream({start(e){Te.set(t,e),a=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(a.error(o),Te.delete(t)):0===r?(a.close(),Te.delete(t)):a.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(I.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);I.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(p)throw new Error("Dynamic root components have already been enabled.");p=t,b=n;for(const[t,o]of Object.entries(r)){const r=e.jsCallDispatcher.findJSFunction(t,0);for(const e of o)r(e,n[e])}}(C(t),r,o)}}};window.Blazor=_e;let Oe=!1;const Fe="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,xe=Fe?Fe.decode.bind(Fe):function(e){let t=0;const n=e.length,r=[],o=[];for(;t65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o)}r.length>1024&&(o.push(String.fromCharCode.apply(null,r)),r.length=0)}return o.push(String.fromCharCode.apply(null,r)),o.join("")},Le=Math.pow(2,32),Pe=Math.pow(2,21)-1;function je(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function Me(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function Be(e,t){const n=Me(e,t+4);if(n>Pe)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*Le+Me(e,t)}class He{constructor(e){this.batchData=e;const t=new ze(e);this.arrayRangeReader=new Ke(e),this.arrayBuilderSegmentReader=new Ve(e),this.diffReader=new Ue(e),this.editReader=new Je(e,t),this.frameReader=new $e(e,t)}updatedComponents(){return je(this.batchData,this.batchData.length-20)}referenceFrames(){return je(this.batchData,this.batchData.length-16)}disposedComponentIds(){return je(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return je(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return je(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return je(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return Be(this.batchData,n)}}class Ue{constructor(e){this.batchDataUint8=e}componentId(e){return je(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class Je{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return je(this.batchDataUint8,e)}siblingIndex(e){return je(this.batchDataUint8,e+4)}newTreeIndex(e){return je(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return je(this.batchDataUint8,e+8)}removedAttributeName(e){const t=je(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class $e{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return je(this.batchDataUint8,e)}subtreeLength(e){return je(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return je(this.batchDataUint8,e+8)}elementName(e){const t=je(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=je(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=je(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return Be(this.batchDataUint8,e+12)}}class ze{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=je(e,e.length-4)}readString(e){if(-1===e)return null;{const n=je(this.batchDataUint8,this.stringTableStartIndex+4*e),r=function(e,t){let n=0,r=0;for(let o=0;o<4;o++){const a=e[t+o];if(n|=(127&a)<async function(e,n){const r=function(e){const t=document.baseURI;return t.endsWith("/")?`${t}${e}`:`${t}/${e}`}(n),o=await import(r);if(void 0===o)return;const{beforeStart:a,afterStarted:s}=o;return s&&e.afterStartedCallbacks.push(s),a?a(...t):void 0}(this,e))))}async invokeAfterStartedCallbacks(e){await Promise.all(this.afterStartedCallbacks.map((t=>t(e))))}}let ot=!1;async function at(){if(ot)throw new Error("Blazor has already started.");ot=!0;const t=await async function(){const e=await fetch("_framework/blazor.modules.json",{method:"GET",credentials:"include",cache:"no-cache"}),t=await e.json(),n=new rt;return await n.importInitializersAsync(t,[]),n}();(function(){const t={AttachToDocument:(e,t)=>{!function(e,t,n){const r="::after";let o=!1;if(e.endsWith(r))e=e.slice(0,-r.length),o=!0;else if(e.endsWith("::before"))throw new Error("The '::before' selector is not supported.");const a=function(e){const t=m.get(e);if(t)return m.delete(e),t}(e)||document.querySelector(e);if(!a)throw new Error(`Could not find any element matching selector '${e}'.`);!function(e,t,n,r){let o=ue[0];o||(o=ue[0]=new oe(0)),o.attachRootComponentToLogicalElement(n,t,r)}(0,P(a,!0),t,o)}(t,e)},RenderBatch:(e,t)=>{try{const n=nt(t);(function(e,t){const n=ue[0];if(!n)throw new Error("There is no browser renderer with ID 0.");const r=t.arrayRangeReader,o=t.updatedComponents(),a=r.values(o),s=r.count(o),i=t.referenceFrames(),c=r.values(i),l=t.diffReader;for(let e=0;e{Xe=!0,console.error(`${e}\n${t}`),async function(){let e=document.querySelector("#blazor-error-ui");e&&(e.style.display="block"),Oe||(Oe=!0,document.querySelectorAll("#blazor-error-ui .reload").forEach((e=>{e.onclick=function(e){location.reload(),e.preventDefault()}})),document.querySelectorAll("#blazor-error-ui .dismiss").forEach((e=>{e.onclick=function(e){const t=document.querySelector("#blazor-error-ui");t&&(t.style.display="none"),e.preventDefault()}})))}()},BeginInvokeJS:e.jsCallDispatcher.beginInvokeJSFromDotNet,EndInvokeDotNet:e.jsCallDispatcher.endInvokeDotNetFromJS,SendByteArrayToJS:tt,Navigate:pe.navigateTo};window.external.receiveMessage((e=>{const n=function(e){if(Xe||!e||!e.startsWith(We))return null;const t=e.substring(We.length),[n,...r]=JSON.parse(t);return{messageType:n,args:r}}(e);if(n){if(!t.hasOwnProperty(n.messageType))throw new Error(`Unsupported IPC message type '${n.messageType}'`);t[n.messageType].apply(null,n.args)}}))})(),e.attachDispatcher({beginInvokeDotNetFromJS:Ge,endInvokeJSFromDotNet:qe,sendByteArray:Ze}),pe.enableNavigationInterception(),pe.listenForNavigationEvents(Qe),et("AttachPage",pe.getBaseURI(),pe.getLocationHref()),await t.invokeAfterStartedCallbacks(_e)}_e.start=at,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&at()})(); \ No newline at end of file diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index 19eaa44204af..96befbbc0910 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -1,6 +1,6 @@ import { DotNet } from '@microsoft/dotnet-js-interop'; import { Blazor } from './GlobalExports'; -import { HubConnectionBuilder, HubConnection, HttpTransportType } from '@microsoft/signalr'; +import { HubConnectionBuilder, HubConnection } from '@microsoft/signalr'; import { MessagePackHubProtocol } from '@microsoft/signalr-protocol-msgpack'; import { showErrorNotification } from './BootErrors'; import { shouldAutoStart } from './BootCommon'; @@ -86,7 +86,7 @@ async function initializeConnection(options: CircuitStartOptions, logger: Logger (hubProtocol as unknown as { name: string }).name = 'blazorpack'; const connectionBuilder = new HubConnectionBuilder() - .withUrl('_blazor', HttpTransportType.WebSockets) + .withUrl('_blazor') .withHubProtocol(hubProtocol); options.configureSignalR(connectionBuilder); @@ -144,14 +144,7 @@ async function initializeConnection(options: CircuitStartOptions, logger: Logger // Throw this exception so it can be handled at the reconnection layer, and don't show the // error notification. throw ex; - } else if (!isNestedError(ex)) { - showErrorNotification(); - } else if (ex.innerErrors && ex.innerErrors.some(e => e.errorType === 'UnsupportedTransportError' && e.transport === HttpTransportType.WebSockets)) { - showErrorNotification('Unable to connect, please ensure you are using an updated browser that supports WebSockets.'); - } else if (ex.innerErrors && ex.innerErrors.some(e => e.errorType === 'FailedToStartTransportError' && e.transport === HttpTransportType.WebSockets)) { - showErrorNotification('Unable to connect, please ensure WebSockets are available. A VPN or proxy may be blocking the connection.'); - } else if (ex.innerErrors && ex.innerErrors.some(e => e.errorType === 'DisabledTransportError' && e.transport === HttpTransportType.LongPolling)) { - logger.log(LogLevel.Error, 'Unable to initiate a SignalR connection to the server. This might be because the server is not configured to support WebSockets. To troubleshoot this, visit https://aka.ms/blazor-server-websockets-error.'); + } else { showErrorNotification(); } } @@ -169,14 +162,8 @@ async function initializeConnection(options: CircuitStartOptions, logger: Logger }); return connection; - - function isNestedError(error: any): error is AggregateError { - return error && ('innerErrors' in error); - } } -type AggregateError = Error & { innerErrors: { errorType: string, transport: HttpTransportType }[] }; - function unhandledError(connection: HubConnection, err: Error, logger: Logger): void { logger.log(LogLevel.Error, err); diff --git a/src/Components/Web.JS/src/BootErrors.ts b/src/Components/Web.JS/src/BootErrors.ts index 4bcd660e85b1..3db688e427e6 100644 --- a/src/Components/Web.JS/src/BootErrors.ts +++ b/src/Components/Web.JS/src/BootErrors.ts @@ -1,13 +1,9 @@ let hasFailed = false; -export async function showErrorNotification(customErrorMessage: string = '') { +export async function showErrorNotification() { let errorUi = document.querySelector('#blazor-error-ui') as HTMLElement; if (errorUi) { errorUi.style.display = 'block'; - - if (customErrorMessage && errorUi.firstChild) { - errorUi.firstChild.textContent = `\n\t${customErrorMessage}\t\n`; - } } if (!hasFailed) { diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerTransportsTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerTransportsTest.cs deleted file mode 100644 index 03d73f2bdc1a..000000000000 --- a/src/Components/test/E2ETest/ServerExecutionTests/ServerTransportsTest.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Linq; -using System.Threading; -using BasicTestApp; -using BasicTestApp.Reconnection; -using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; -using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; -using Microsoft.AspNetCore.E2ETesting; -using OpenQA.Selenium; -using TestServer; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests -{ - public class ServerTransportsTest : ServerTestBase> - { - public ServerTransportsTest( - BrowserFixture browserFixture, - BasicTestAppServerSiteFixture serverFixture, - ITestOutputHelper output) - : base(browserFixture, serverFixture, output) - { - } - - [Fact] - public void DefaultTransportsWorksWithWebSockets() - { - Navigate("/defaultTransport/Transports"); - - Browser.Exists(By.Id("startBlazorServerBtn")).Click(); - - var javascript = (IJavaScriptExecutor)Browser; - Browser.True(() => (bool)javascript.ExecuteScript("return window['__aspnetcore__testing__blazor__start__script__executed__'] === true;")); - - AssertLogContainsMessages( - "Starting up Blazor server-side application.", - "WebSocket connected to ws://", - "Received render batch with", - "The HttpConnection connected successfully.", - "Blazor server-side application started."); - } - - [Fact] - public void ErrorIfClientAttemptsLongPollingWithServerOnWebSockets() - { - Navigate("/defaultTransport/Transports"); - - Browser.Exists(By.Id("startWithLongPollingBtn")).Click(); - - var javascript = (IJavaScriptExecutor)Browser; - Browser.True(() => (bool)javascript.ExecuteScript("return window['__aspnetcore__testing__blazor__start__script__executed__'] === true;")); - - AssertLogContainsMessages( - "Information: Starting up Blazor server-side application.", - "Failed to start the connection: Error: Unable to connect to the server with any of the available transports.", - "Failed to start the circuit."); - - var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10)); - Assert.NotNull(errorUiElem); - Assert.Contains("An unhandled exception has occurred. See browser dev tools for details.", errorUiElem.GetAttribute("innerHTML")); - Browser.Equal("block", () => errorUiElem.GetCssValue("display")); - } - - [Fact] - public void ErrorIfWebSocketsConnectionIsRejected() - { - Navigate("/defaultTransport/Transports"); - - Browser.Exists(By.Id("startAndRejectWebSocketConnectionBtn")).Click(); - - var javascript = (IJavaScriptExecutor)Browser; - Browser.True(() => (bool)javascript.ExecuteScript("return window['__aspnetcore__testing__blazor__start__script__executed__'] === true;")); - - AssertLogContainsMessages( - "Information: Starting up Blazor server-side application.", - "Selecting transport 'WebSockets'.", - "Error: Failed to start the transport 'WebSockets': Error: Don't allow Websockets.", - "Error: Failed to start the connection: Error: Unable to connect to the server with any of the available transports. Error: WebSockets failed: Error: Don't allow Websockets.", - "Failed to start the circuit."); - - // Ensure error ui is visible - var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10)); - Assert.NotNull(errorUiElem); - Assert.Contains("Unable to connect, please ensure WebSockets are available. A VPN or proxy may be blocking the connection.", errorUiElem.GetAttribute("innerHTML")); - Browser.Equal("block", () => errorUiElem.GetCssValue("display")); - } - - [Fact] - public void ErrorIfClientAttemptsWebSocketsWithServerOnLongPolling() - { - Navigate("/longPolling/Transports"); - - Browser.Exists(By.Id("startBlazorServerBtn")).Click(); - - var javascript = (IJavaScriptExecutor)Browser; - Browser.True(() => (bool)javascript.ExecuteScript("return window['__aspnetcore__testing__blazor__start__script__executed__'] === true;")); - - AssertLogContainsMessages( - "Starting up Blazor server-side application.", - "Unable to connect to the server with any of the available transports. LongPolling failed: Error: 'LongPolling' is disabled by the client.", - "Unable to initiate a SignalR connection to the server. This might be because the server is not configured to support WebSockets. To troubleshoot this, visit"); - - var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10)); - Assert.NotNull(errorUiElem); - Assert.Contains("An unhandled exception has occurred. See browser dev tools for details.", errorUiElem.GetAttribute("innerHTML")); - Browser.Equal("block", () => errorUiElem.GetCssValue("display")); - } - - void AssertLogContainsMessages(params string[] messages) - { - var log = Browser.Manage().Logs.GetLog(LogType.Browser); - foreach (var message in messages) - { - Assert.Contains(log, entry => - { - return entry.Message.Contains(message, StringComparison.InvariantCulture); - }); - } - } - } -} diff --git a/src/Components/test/testassets/TestServer/Pages/Transports.cshtml b/src/Components/test/testassets/TestServer/Pages/Transports.cshtml deleted file mode 100644 index 2476db63eb8b..000000000000 --- a/src/Components/test/testassets/TestServer/Pages/Transports.cshtml +++ /dev/null @@ -1,69 +0,0 @@ -@page -@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers" - - - - - - - - - - -
- An unhandled exception has occurred. See browser dev tools for details. - Reload - 🗙 -
- - - - - - - - - - diff --git a/src/Components/test/testassets/TestServer/ServerStartup.cs b/src/Components/test/testassets/TestServer/ServerStartup.cs index 972c80c1b6ef..e7e1079a163e 100644 --- a/src/Components/test/testassets/TestServer/ServerStartup.cs +++ b/src/Components/test/testassets/TestServer/ServerStartup.cs @@ -42,7 +42,7 @@ public void ConfigureServices(IServiceCollection services) } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env, ResourceRequestLog resourceRequestLog) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ResourceRequestLog resourceRequestLog) { var enUs = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = enUs; diff --git a/src/Components/test/testassets/TestServer/TransportsServerStartup.cs b/src/Components/test/testassets/TestServer/TransportsServerStartup.cs deleted file mode 100644 index 5bde0554bf72..000000000000 --- a/src/Components/test/testassets/TestServer/TransportsServerStartup.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Globalization; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace TestServer -{ - public class TransportsServerStartup : ServerStartup - { - public TransportsServerStartup(IConfiguration configuration) - : base (configuration) - { - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public override void Configure(IApplicationBuilder app, IWebHostEnvironment env, ResourceRequestLog resourceRequestLog) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.Map("/defaultTransport", app => - { - app.UseStaticFiles(); - - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_ServerHost"); - }); - }); - - app.Map("/longPolling", app => - { - app.UseStaticFiles(); - - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapBlazorHub(configureOptions: options => - { - options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling; - }); - endpoints.MapFallbackToPage("/_ServerHost"); - }); - }); - } - } -} diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMismatchedParameterOptionality.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMismatchedParameterOptionality.cs index 8ccde050a525..3f51a55756db 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMismatchedParameterOptionality.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMismatchedParameterOptionality.cs @@ -9,9 +9,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer +public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer { internal const string DetectMismatchedParameterOptionalityRuleId = "ASP0006"; diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMisplacedLambdaAttribute.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMisplacedLambdaAttribute.cs index cb5d66041056..f4754c9a00d9 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMisplacedLambdaAttribute.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DetectMisplacedLambdaAttribute.cs @@ -7,9 +7,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer +public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer { private static void DetectMisplacedLambdaAttribute( in OperationAnalysisContext context, diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs index 4cb94d5f26db..00ae39c892e1 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs @@ -3,23 +3,23 @@ using Microsoft.CodeAnalysis; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers { [System.Diagnostics.CodeAnalysis.SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking")] internal static class DiagnosticDescriptors { - internal static readonly DiagnosticDescriptor DoNotUseModelBindingAttributesOnDelegateEndpointParameters = new( + internal static readonly DiagnosticDescriptor DoNotUseModelBindingAttributesOnRouteHandlerParameters = new( "ASP0003", - "Do not use model binding attributes with Map handlers", + "Do not use model binding attributes with route handlers", "{0} should not be specified for a {1} Delegate parameter", "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, helpLinkUri: "https://aka.ms/aspnet/analyzers"); - internal static readonly DiagnosticDescriptor DoNotReturnActionResultsFromMapActions = new( + internal static readonly DiagnosticDescriptor DoNotReturnActionResultsFromRouteHandlers = new( "ASP0004", - "Do not use action results with Map actions", + "Do not use action results with route handlers", "IActionResult instances should not be returned from a {0} Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", "Usage", DiagnosticSeverity.Warning, @@ -28,8 +28,8 @@ internal static class DiagnosticDescriptors internal static readonly DiagnosticDescriptor DetectMisplacedLambdaAttribute = new( "ASP0005", - "Do not place attribute on route handlers", - "'{0}' should be placed on the endpoint delegate to be effective", + "Do not place attribute on method called by route handler lambda", + "'{0}' should be placed directly on the route handler lambda to be effective", "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowMvcBindArgumentsOnParameters.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowMvcBindArgumentsOnParameters.cs index 19636859c22b..cbf2fc1aa25f 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowMvcBindArgumentsOnParameters.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowMvcBindArgumentsOnParameters.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer +public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer { private static void DisallowMvcBindArgumentsOnParameters( in OperationAnalysisContext context, @@ -33,7 +33,7 @@ private static void DisallowMvcBindArgumentsOnParameters( var methodName = invocation.TargetMethod.Name; context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, + DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, location, modelBindingAttribute.AttributeClass.Name, methodName)); diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowReturningActionResultFromMapMethods.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowReturningActionResultFromMapMethods.cs index 1bcc02648907..12e208ea1824 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowReturningActionResultFromMapMethods.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DisallowReturningActionResultFromMapMethods.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer +public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer { private static void DisallowReturningActionResultFromMapMethods( in OperationAnalysisContext context, @@ -40,7 +40,7 @@ private static void DisallowReturningActionResultFromMapMethods( { // if we don't have a method body, and the action is IResult or ActionResult returning, produce diagnostics for the entire method. context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, + DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, invocationOperation.Arguments[2].Syntax.GetLocation(), invocationOperation.TargetMethod.Name)); return; @@ -74,7 +74,7 @@ private static void DisallowReturningActionResultFromMapMethods( if (wellKnownTypes.IActionResult.IsAssignableFrom(type)) { context.ReportDiagnostic(Diagnostic.Create( - DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, + DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, returnOperation.Syntax.GetLocation(), invocationOperation.TargetMethod.Name)); } diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DelegateEndpointAnalyzer.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlerAnalyzer.cs similarity index 86% rename from src/Framework/AspNetCoreAnalyzers/src/Analyzers/DelegateEndpointAnalyzer.cs rename to src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlerAnalyzer.cs index 927429ac5728..350dcab2f877 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/DelegateEndpointAnalyzer.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlerAnalyzer.cs @@ -9,15 +9,15 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; [DiagnosticAnalyzer(LanguageNames.CSharp)] -public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer +public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer { public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(new[] { - DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, - DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, + DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, + DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, DiagnosticDescriptors.DetectMisplacedLambdaAttribute, DiagnosticDescriptors.DetectMismatchedParameterOptionality }); @@ -40,7 +40,7 @@ public override void Initialize(AnalysisContext context) { var invocation = (IInvocationOperation)operationAnalysisContext.Operation; var targetMethod = invocation.TargetMethod; - if (IsDelegateHandlerInvocation(wellKnownTypes, invocation, targetMethod)) + if (!IsRouteHandlerInvocation(wellKnownTypes, invocation, targetMethod)) { return; } @@ -109,13 +109,15 @@ public override void Initialize(AnalysisContext context) }); } - private static bool IsDelegateHandlerInvocation( + private static bool IsRouteHandlerInvocation( WellKnownTypes wellKnownTypes, IInvocationOperation invocation, IMethodSymbol targetMethod) { - return !targetMethod.Name.StartsWith("Map", StringComparison.Ordinal) || - !SymbolEqualityComparer.Default.Equals(wellKnownTypes.DelegateEndpointRouteBuilderExtensions, targetMethod.ContainingType) || - invocation.Arguments.Length != 3; + return targetMethod.Name.StartsWith("Map", StringComparison.Ordinal) && + SymbolEqualityComparer.Default.Equals(wellKnownTypes.EndpointRouteBuilderExtensions, targetMethod.ContainingType) && + invocation.Arguments.Length == 3 && + targetMethod.Parameters.Length == 3 && + SymbolEqualityComparer.Default.Equals(wellKnownTypes.Delegate, targetMethod.Parameters[2].Type); } } diff --git a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/WellKnownTypes.cs b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/WellKnownTypes.cs index 040e511ad666..51b98592053b 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/Analyzers/WellKnownTypes.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/Analyzers/WellKnownTypes.cs @@ -4,15 +4,21 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; internal sealed class WellKnownTypes { public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out WellKnownTypes? wellKnownTypes) { wellKnownTypes = default; - const string DelegateEndpointRouteBuilderExtensions = "Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions"; - if (compilation.GetTypeByMetadataName(DelegateEndpointRouteBuilderExtensions) is not { } delegateEndpointRouteBuilderExtensions) + const string EndpointRouteBuilderExtensions = "Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions"; + if (compilation.GetTypeByMetadataName(EndpointRouteBuilderExtensions) is not { } endpointRouteBuilderExtensions) + { + return false; + } + + const string Delegate = "System.Delegate"; + if (compilation.GetTypeByMetadataName(Delegate) is not { } @delegate) { return false; } @@ -51,7 +57,8 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We wellKnownTypes = new WellKnownTypes { - DelegateEndpointRouteBuilderExtensions = delegateEndpointRouteBuilderExtensions, + EndpointRouteBuilderExtensions = endpointRouteBuilderExtensions, + Delegate = @delegate, IBinderTypeProviderMetadata = ibinderTypeProviderMetadata, BindAttribute = bindAttribute, IResult = iResult, @@ -62,7 +69,8 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We return true; } - public ITypeSymbol DelegateEndpointRouteBuilderExtensions { get; private init; } + public INamedTypeSymbol EndpointRouteBuilderExtensions { get; private init; } + public INamedTypeSymbol Delegate { get; private init; } public INamedTypeSymbol IBinderTypeProviderMetadata { get; private init; } public INamedTypeSymbol BindAttribute { get; private init; } public INamedTypeSymbol IResult { get; private init; } diff --git a/src/Framework/AspNetCoreAnalyzers/src/CodeFixes/DetectMismatchedParameterOptionalityFixer.cs b/src/Framework/AspNetCoreAnalyzers/src/CodeFixes/DetectMismatchedParameterOptionalityFixer.cs index 0b4f97ec0fe2..e893fb7147a6 100644 --- a/src/Framework/AspNetCoreAnalyzers/src/CodeFixes/DetectMismatchedParameterOptionalityFixer.cs +++ b/src/Framework/AspNetCoreAnalyzers/src/CodeFixes/DetectMismatchedParameterOptionalityFixer.cs @@ -5,7 +5,7 @@ using System.Threading; using System.Collections.Immutable; using System.Threading.Tasks; -using Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +using Microsoft.AspNetCore.Analyzers.RouteHandlers; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -13,7 +13,7 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Editing; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints.Fixers; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers; public class DetectMismatchedParameterOptionalityFixer : CodeFixProvider { diff --git a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMismatchedParameterOptionalityTest.cs b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMismatchedParameterOptionalityTest.cs similarity index 96% rename from src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMismatchedParameterOptionalityTest.cs rename to src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMismatchedParameterOptionalityTest.cs index baa4841bb0cb..cdcb1c9bb2e5 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMismatchedParameterOptionalityTest.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMismatchedParameterOptionalityTest.cs @@ -3,11 +3,11 @@ using Microsoft.CodeAnalysis.Testing; using Xunit; -using VerifyCS = Microsoft.AspNetCore.Analyzers.DelegateEndpoints.CSharpDelegateEndpointsCodeFixVerifier< - Microsoft.AspNetCore.Analyzers.DelegateEndpoints.DelegateEndpointAnalyzer, - Microsoft.AspNetCore.Analyzers.DelegateEndpoints.Fixers.DetectMismatchedParameterOptionalityFixer>; +using VerifyCS = Microsoft.AspNetCore.Analyzers.RouteHandlers.CSharpRouteHandlerCodeFixVerifier< + Microsoft.AspNetCore.Analyzers.RouteHandlers.RouteHandlerAnalyzer, + Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers.DetectMismatchedParameterOptionalityFixer>; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; public partial class DetectMismatchedParameterOptionalityTest { @@ -377,7 +377,7 @@ public async Task MatchingRequiredOptionality_WithDisabledNullability() public void RouteTokenizer_Works_ForSimpleRouteTemplates(string template, string[] expectedNames, string[] expectedQualifiers) { // Arrange - var tokenizer = new DelegateEndpointAnalyzer.RouteTokenEnumerator(template); + var tokenizer = new RouteHandlerAnalyzer.RouteTokenEnumerator(template); var actualNames = new List(); var actualQualifiers = new List(); diff --git a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMisplacedLambdaAttributeTest.cs b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMisplacedLambdaAttributeTest.cs similarity index 88% rename from src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMisplacedLambdaAttributeTest.cs rename to src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMisplacedLambdaAttributeTest.cs index c25bfbcbadb4..a83fe6aadaf8 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DetectMisplacedLambdaAttributeTest.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DetectMisplacedLambdaAttributeTest.cs @@ -5,11 +5,11 @@ using Microsoft.AspNetCore.Analyzer.Testing; using Xunit; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; public partial class DetectMisplacedLambdaAttributeTest { - private TestDiagnosticAnalyzerRunner Runner { get; } = new(new DelegateEndpointAnalyzer()); + private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RouteHandlerAnalyzer()); [Fact] public async Task MinimalAction_WithCorrectlyPlacedAttribute_Works() @@ -48,7 +48,7 @@ void Hello() { } var diagnostic = Assert.Single(diagnostics); Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } [Fact] @@ -70,7 +70,7 @@ public async Task MinimalAction_WithMisplacedAttributeAndBlockSyntax_ProducesDia var diagnostic = Assert.Single(diagnostics); Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } [Fact] @@ -95,12 +95,12 @@ void Hello() { } diagnostic => { Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); }, diagnostic => { Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'ProducesAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'ProducesAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } ); } @@ -126,7 +126,7 @@ void Hello() { } diagnostic => { Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'ProducesAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'ProducesAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } ); } @@ -215,7 +215,7 @@ public static void Hello() { } var diagnostic = Assert.Single(diagnostics); Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); - Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); + Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } [Fact] diff --git a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowMvcBindArgumentsOnParametersTest.cs b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowMvcBindArgumentsOnParametersTest.cs similarity index 93% rename from src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowMvcBindArgumentsOnParametersTest.cs rename to src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowMvcBindArgumentsOnParametersTest.cs index 2f3afa75cf1b..65b3733d0ab9 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowMvcBindArgumentsOnParametersTest.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowMvcBindArgumentsOnParametersTest.cs @@ -5,11 +5,11 @@ using Microsoft.AspNetCore.Analyzer.Testing; using Xunit; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; public partial class DisallowMvcBindArgumentsOnParametersTest { - private TestDiagnosticAnalyzerRunner Runner { get; } = new(new DelegateEndpointAnalyzer()); + private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RouteHandlerAnalyzer()); [Fact] public async Task MinimalAction_WithoutBindAttributes_Works() @@ -59,7 +59,7 @@ public async Task MinimalAction_Lambda_WithBindAttributes_ProducesDiagnostics() // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("BindAttribute should not be specified for a MapGet Delegate parameter", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } @@ -81,7 +81,7 @@ static void PostWithBind(/*MM*/[ModelBinder] string name) {} // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("ModelBinderAttribute should not be specified for a MapPost Delegate parameter", diagnostic.GetMessage(CultureInfo.InvariantCulture)); } diff --git a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowReturningActionResultsFromMapMethodsTest.cs b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowReturningActionResultsFromMapMethodsTest.cs similarity index 96% rename from src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowReturningActionResultsFromMapMethodsTest.cs rename to src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowReturningActionResultsFromMapMethodsTest.cs index ba1700e5e55c..82571b70a12b 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/MinimalActions/DisallowReturningActionResultsFromMapMethodsTest.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowReturningActionResultsFromMapMethodsTest.cs @@ -3,11 +3,11 @@ using Microsoft.AspNetCore.Analyzer.Testing; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; public partial class DisallowReturningActionResultsFromMapMethodsTest { - private TestDiagnosticAnalyzerRunner Runner { get; } = new(new DelegateEndpointAnalyzer()); + private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RouteHandlerAnalyzer()); [Fact] public async Task MinimalAction_ReturningIResult_Works() @@ -126,7 +126,7 @@ public async Task MinimalAction_ReturningActionResult_ProducesDiagnostics() // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("IActionResult instances should not be returned from a MapGet Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", diagnostic.GetMessage()); } @@ -149,7 +149,7 @@ public async Task MinimalAction_ReturningActionResultConditionally_ProducesDiagn // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("IActionResult instances should not be returned from a MapGet Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", diagnostic.GetMessage()); } @@ -177,7 +177,7 @@ static object OkObjectResultReturningMethod() // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("IActionResult instances should not be returned from a MapPost Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", diagnostic.GetMessage()); } @@ -209,7 +209,7 @@ public record Person(string Name); // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("IActionResult instances should not be returned from a MapPost Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", diagnostic.GetMessage()); } @@ -247,7 +247,7 @@ public record Person(string Name); // Assert var diagnostic = Assert.Single(diagnostics); - Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions, diagnostic.Descriptor); + Assert.Same(DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); Assert.Equal("IActionResult instances should not be returned from a MapPost Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.", diagnostic.GetMessage()); } diff --git a/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsAnalyzerVerifier.cs b/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerAnalyzerVerifier.cs similarity index 77% rename from src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsAnalyzerVerifier.cs rename to src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerAnalyzerVerifier.cs index 2fa14f67bccb..e8dc7a55cb61 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsAnalyzerVerifier.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerAnalyzerVerifier.cs @@ -11,13 +11,13 @@ using Microsoft.CodeAnalysis.Testing.Verifiers; using Xunit; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public static class CSharpDelegateEndpointsAnalyzerVerifier - where TAnalyzer : DelegateEndpointAnalyzer, new() +public static class CSharpRouteHandlerAnalyzerVerifier + where TAnalyzer : RouteHandlerAnalyzer, new() { public static DiagnosticResult Diagnostic(string diagnosticId = null) - => CSharpDelegateEndpointsAnalyzerVerifier.Diagnostic(diagnosticId); + => CSharpRouteHandlerAnalyzerVerifier.Diagnostic(diagnosticId); public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => new DiagnosticResult(descriptor); @@ -30,4 +30,4 @@ public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] } public class Test : CSharpCodeFixTest { } -} \ No newline at end of file +} diff --git a/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsCodeFixVerifier.cs b/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerCodeFixVerifier.cs similarity index 85% rename from src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsCodeFixVerifier.cs rename to src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerCodeFixVerifier.cs index 2883bb2fd389..9d4db29d17fd 100644 --- a/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpDelegateEndpointsCodeFixVerifier.cs +++ b/src/Framework/AspNetCoreAnalyzers/test/Verifiers/CSharpRouteHandlerCodeFixVerifier.cs @@ -3,7 +3,7 @@ using System.Collections.Immutable; using System.Globalization; -using Microsoft.AspNetCore.Analyzers.DelegateEndpoints.Fixers; +using Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers; using Microsoft.AspNetCore.Analyzer.Testing; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Testing; @@ -13,10 +13,10 @@ using Microsoft.CodeAnalysis.Testing.Verifiers; using Xunit; -namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints; +namespace Microsoft.AspNetCore.Analyzers.RouteHandlers; -public static class CSharpDelegateEndpointsCodeFixVerifier - where TAnalyzer : DelegateEndpointAnalyzer, new() +public static class CSharpRouteHandlerCodeFixVerifier + where TAnalyzer : RouteHandlerAnalyzer, new() where TCodeFix : DetectMismatchedParameterOptionalityFixer, new() { public static DiagnosticResult Diagnostic(string diagnosticId = null) @@ -27,7 +27,7 @@ public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) { - var test = new CSharpDelegateEndpointsAnalyzerVerifier.Test { TestCode = source }; + var test = new CSharpRouteHandlerAnalyzerVerifier.Test { TestCode = source }; test.ExpectedDiagnostics.AddRange(expected); return test.RunAsync(); } @@ -43,7 +43,7 @@ public static Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected public static Task VerifyCodeFixAsync(string sources, DiagnosticResult[] expected, string fixedSources, string usageSource = "") { - var test = new DelegateEndpointAnalyzerTest + var test = new RouteHandlerAnalyzerTest { TestState = { @@ -63,16 +63,16 @@ public static Task VerifyCodeFixAsync(string sources, DiagnosticResult[] expecte return test.RunAsync(); } - public class DelegateEndpointAnalyzerTest : CSharpCodeFixTest + public class RouteHandlerAnalyzerTest : CSharpCodeFixTest { - public DelegateEndpointAnalyzerTest() + public RouteHandlerAnalyzerTest() { // We populate the ReferenceAssemblies used in the tests with the locally-built AspNetCore // assemblies that are referenced in a minimal app to ensure that there are no reference // errors during the build. ReferenceAssemblies = ReferenceAssemblies.Net.Net60.AddAssemblies(ImmutableArray.Create( TrimAssemblyExtension(typeof(Microsoft.AspNetCore.Builder.WebApplication).Assembly.Location), - TrimAssemblyExtension(typeof(Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions).Assembly.Location), + TrimAssemblyExtension(typeof(Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions).Assembly.Location), TrimAssemblyExtension(typeof(Microsoft.AspNetCore.Builder.IApplicationBuilder).Assembly.Location), TrimAssemblyExtension(typeof(Microsoft.AspNetCore.Builder.IEndpointConventionBuilder).Assembly.Location), TrimAssemblyExtension(typeof(Microsoft.Extensions.Hosting.IHost).Assembly.Location), @@ -82,4 +82,4 @@ public DelegateEndpointAnalyzerTest() string TrimAssemblyExtension(string fullPath) => fullPath.Replace(".dll", string.Empty); } } -} \ No newline at end of file +} diff --git a/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs b/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs index 7acf196b4a75..ccc2063b8fee 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Deployers/SelfHostDeployer.cs @@ -150,7 +150,7 @@ public override async Task DeployAsync() HostProcess.EnableRaisingEvents = true; HostProcess.OutputDataReceived += (sender, dataArgs) => { - if (string.Equals(dataArgs.Data, ApplicationStartedMessage)) + if (!string.IsNullOrEmpty(dataArgs.Data) && dataArgs.Data.Contains(ApplicationStartedMessage)) { started.TrySetResult(); } diff --git a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs index 9355e5f0da4c..03bf3dee6eed 100644 --- a/src/Http/Http.Extensions/src/RequestDelegateFactory.cs +++ b/src/Http/Http.Extensions/src/RequestDelegateFactory.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Security.Claims; using System.Text; +using System.Text.Json; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Metadata; using Microsoft.Extensions.DependencyInjection; @@ -504,7 +505,7 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall, private static Func HandleRequestBodyAndCompileRequestDelegate(Expression responseWritingMethodCall, FactoryContext factoryContext) { - if (factoryContext.JsonRequestBodyType is null) + if (factoryContext.JsonRequestBodyParameter is null) { if (factoryContext.ParameterBinders.Count > 0) { @@ -533,7 +534,12 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall, responseWritingMethodCall, TargetExpr, HttpContextExpr).Compile(); } - var bodyType = factoryContext.JsonRequestBodyType; + var bodyType = factoryContext.JsonRequestBodyParameter.ParameterType; + var parameterTypeName = TypeNameHelper.GetTypeDisplayName(factoryContext.JsonRequestBodyParameter.ParameterType, fullName: false); + var parameterName = factoryContext.JsonRequestBodyParameter.Name; + + Debug.Assert(parameterName is not null, "CreateArgument() should throw if parameter.Name is null."); + object? defaultBodyValue = null; if (factoryContext.AllowEmptyRequestBody && bodyType.IsValueType) @@ -580,10 +586,10 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall, Log.RequestBodyIOException(httpContext, ex); return; } - catch (InvalidDataException ex) + catch (JsonException ex) { - Log.RequestBodyInvalidDataException(httpContext, ex, factoryContext.ThrowOnBadRequest); - httpContext.Response.StatusCode = 400; + Log.InvalidJsonRequestBody(httpContext, parameterTypeName, parameterName, ex, factoryContext.ThrowOnBadRequest); + httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; return; } } @@ -618,10 +624,10 @@ private static Expression AddResponseWritingToMethodCall(Expression methodCall, Log.RequestBodyIOException(httpContext, ex); return; } - catch (InvalidDataException ex) + catch (JsonException ex) { - Log.RequestBodyInvalidDataException(httpContext, ex, factoryContext.ThrowOnBadRequest); + Log.InvalidJsonRequestBody(httpContext, parameterTypeName, parameterName, ex, factoryContext.ThrowOnBadRequest); httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; return; } @@ -879,11 +885,14 @@ private static Expression BindParameterFromBindAsync(ParameterInfo parameter, Fa private static Expression BindParameterFromBody(ParameterInfo parameter, bool allowEmpty, FactoryContext factoryContext) { - if (factoryContext.JsonRequestBodyType is not null) + if (factoryContext.JsonRequestBodyParameter is not null) { factoryContext.HasMultipleBodyParameters = true; var parameterName = parameter.Name; - if (parameterName is not null && factoryContext.TrackedParameters.ContainsKey(parameterName)) + + Debug.Assert(parameterName is not null, "CreateArgument() should throw if parameter.Name is null."); + + if (factoryContext.TrackedParameters.ContainsKey(parameterName)) { factoryContext.TrackedParameters.Remove(parameterName); factoryContext.TrackedParameters.Add(parameterName, "UNKNOWN"); @@ -892,7 +901,7 @@ private static Expression BindParameterFromBody(ParameterInfo parameter, bool al var isOptional = IsOptionalParameter(parameter, factoryContext); - factoryContext.JsonRequestBodyType = parameter.ParameterType; + factoryContext.JsonRequestBodyParameter = parameter; factoryContext.AllowEmptyRequestBody = allowEmpty || isOptional; factoryContext.Metadata.Add(new AcceptsMetadata(parameter.ParameterType, factoryContext.AllowEmptyRequestBody, DefaultContentType)); @@ -1164,7 +1173,7 @@ private class FactoryContext public bool DisableInferredFromBody { get; init; } // Temporary State - public Type? JsonRequestBodyType { get; set; } + public ParameterInfo? JsonRequestBodyParameter { get; set; } public bool AllowEmptyRequestBody { get; set; } public bool UsingTempSourceString { get; set; } @@ -1197,7 +1206,8 @@ private static class RequestDelegateFactoryConstants private static partial class Log { - private const string RequestBodyInvalidDataExceptionMessage = "Reading the request body failed with an InvalidDataException."; + private const string InvalidJsonRequestBodyMessage = @"Failed to read parameter ""{ParameterType} {ParameterName}"" from the request body as JSON."; + private const string InvalidJsonRequestBodyExceptionMessage = @"Failed to read parameter ""{0} {1}"" from the request body as JSON."; private const string ParameterBindingFailedLogMessage = @"Failed to bind parameter ""{ParameterType} {ParameterName}"" from ""{SourceValue}""."; private const string ParameterBindingFailedExceptionMessage = @"Failed to bind parameter ""{0} {1}"" from ""{2}""."; @@ -1207,6 +1217,7 @@ private static partial class Log private const string UnexpectedContentTypeLogMessage = @"Expected a supported JSON media type but got ""{ContentType}""."; private const string UnexpectedContentTypeExceptionMessage = @"Expected a supported JSON media type but got ""{0}""."; + private const string ImplicitBodyNotProvidedLogMessage = @"Implicit body inferred for parameter ""{ParameterName}"" but no body was provided. Did you mean to use a Service instead?"; private const string ImplicitBodyNotProvidedExceptionMessage = @"Implicit body inferred for parameter ""{0}"" but no body was provided. Did you mean to use a Service instead?"; @@ -1218,18 +1229,19 @@ public static void RequestBodyIOException(HttpContext httpContext, IOException e [LoggerMessage(1, LogLevel.Debug, "Reading the request body failed with an IOException.", EventName = "RequestBodyIOException")] private static partial void RequestBodyIOException(ILogger logger, IOException exception); - public static void RequestBodyInvalidDataException(HttpContext httpContext, InvalidDataException exception, bool shouldThrow) + public static void InvalidJsonRequestBody(HttpContext httpContext, string parameterTypeName, string parameterName, Exception exception, bool shouldThrow) { if (shouldThrow) { - throw new BadHttpRequestException(RequestBodyInvalidDataExceptionMessage, exception); + var message = string.Format(CultureInfo.InvariantCulture, InvalidJsonRequestBodyExceptionMessage, parameterTypeName, parameterName); + throw new BadHttpRequestException(message, exception); } - RequestBodyInvalidDataException(GetLogger(httpContext), exception); + InvalidJsonRequestBody(GetLogger(httpContext), parameterTypeName, parameterName, exception); } - [LoggerMessage(2, LogLevel.Debug, RequestBodyInvalidDataExceptionMessage, EventName = "RequestBodyInvalidDataException")] - private static partial void RequestBodyInvalidDataException(ILogger logger, InvalidDataException exception); + [LoggerMessage(2, LogLevel.Debug, InvalidJsonRequestBodyMessage, EventName = "InvalidJsonRequestBody")] + private static partial void InvalidJsonRequestBody(ILogger logger, string parameterType, string parameterName, Exception exception); public static void ParameterBindingFailed(HttpContext httpContext, string parameterTypeName, string parameterName, string sourceValue, bool shouldThrow) { @@ -1259,16 +1271,6 @@ public static void RequiredParameterNotProvided(HttpContext httpContext, string [LoggerMessage(4, LogLevel.Debug, RequiredParameterNotProvidedLogMessage, EventName = "RequiredParameterNotProvided")] private static partial void RequiredParameterNotProvided(ILogger logger, string parameterType, string parameterName, string source); - public static void UnexpectedContentType(HttpContext httpContext, string? contentType, bool shouldThrow) - { - if (shouldThrow) - { - var message = string.Format(CultureInfo.InvariantCulture, UnexpectedContentTypeExceptionMessage, contentType); - throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType); - } - - UnexpectedContentType(GetLogger(httpContext), contentType ?? "(none)"); - } public static void ImplicitBodyNotProvided(HttpContext httpContext, string parameterName, bool shouldThrow) { if (shouldThrow) @@ -1283,8 +1285,16 @@ public static void ImplicitBodyNotProvided(HttpContext httpContext, string param [LoggerMessage(5, LogLevel.Debug, ImplicitBodyNotProvidedLogMessage, EventName = "ImplicitBodyNotProvided")] private static partial void ImplicitBodyNotProvided(ILogger logger, string parameterName); - public static void UnexpectedContentType(HttpContext httpContext, string? contentType) - => UnexpectedContentType(GetLogger(httpContext), contentType ?? "(none)"); + public static void UnexpectedContentType(HttpContext httpContext, string? contentType, bool shouldThrow) + { + if (shouldThrow) + { + var message = string.Format(CultureInfo.InvariantCulture, UnexpectedContentTypeExceptionMessage, contentType); + throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType); + } + + UnexpectedContentType(GetLogger(httpContext), contentType ?? "(none)"); + } [LoggerMessage(6, LogLevel.Debug, UnexpectedContentTypeLogMessage, EventName = "UnexpectedContentType")] private static partial void UnexpectedContentType(ILogger logger, string contentType); diff --git a/src/Http/Http.Extensions/test/ParameterBindingMethodCacheTests.cs b/src/Http/Http.Extensions/test/ParameterBindingMethodCacheTests.cs index 80edc7b2a3fd..852478e751bc 100644 --- a/src/Http/Http.Extensions/test/ParameterBindingMethodCacheTests.cs +++ b/src/Http/Http.Extensions/test/ParameterBindingMethodCacheTests.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Linq.Expressions; using System.Reflection; +using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Http.Extensions.Tests { @@ -76,6 +77,7 @@ public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvaria [Theory] [InlineData(typeof(TryParseStringRecord))] [InlineData(typeof(TryParseStringStruct))] + [InlineData(typeof(TryParseInheritClassWithFormatProvider))] public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvariantCultureCustomType(Type type) { var methodFound = new ParameterBindingMethodCache().FindTryParseMethod(@type); @@ -93,6 +95,24 @@ public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvaria Assert.True(((call.Arguments[1] as ConstantExpression)!.Value as CultureInfo)!.Equals(CultureInfo.InvariantCulture)); } + [Theory] + [InlineData(typeof(TryParseNoFormatProviderRecord))] + [InlineData(typeof(TryParseNoFormatProviderStruct))] + [InlineData(typeof(TryParseInheritClass))] + public void FindTryParseMethod_WithNoFormatProvider(Type type) + { + var methodFound = new ParameterBindingMethodCache().FindTryParseMethod(@type); + Assert.NotNull(methodFound); + + var call = methodFound!(Expression.Variable(type, "parsedValue")) as MethodCallExpression; + Assert.NotNull(call); + var parameters = call!.Method.GetParameters(); + + Assert.Equal(2, parameters.Length); + Assert.Equal(typeof(string), parameters[0].ParameterType); + Assert.True(parameters[1].IsOut); + } + public static IEnumerable TryParseStringParameterInfoData { get @@ -248,6 +268,14 @@ public static IEnumerable BindAsyncParameterInfoData new[] { GetFirstParameter((BindAsyncSingleArgStruct arg) => BindAsyncSingleArgStructMethod(arg)), + }, + new[] + { + GetFirstParameter((InheritBindAsync arg) => InheritBindAsyncMethod(arg)) + }, + new[] + { + GetFirstParameter((InheritBindAsyncWithParameterInfo arg) => InheritBindAsyncWithParameterInfoMethod(arg)) } }; } @@ -274,6 +302,66 @@ public void FindBindAsyncMethod_FindsNonNullableReturningBindAsyncMethodGivenNul Assert.True(new ParameterBindingMethodCache().HasBindAsyncMethod(parameterInfo)); } + [Theory] + [InlineData(typeof(InvalidVoidReturnTryParseStruct))] + [InlineData(typeof(InvalidVoidReturnTryParseClass))] + [InlineData(typeof(InvalidWrongTypeTryParseStruct))] + [InlineData(typeof(InvalidWrongTypeTryParseClass))] + [InlineData(typeof(InvalidTryParseNullableStruct))] + [InlineData(typeof(InvalidTooFewArgsTryParseStruct))] + [InlineData(typeof(InvalidTooFewArgsTryParseClass))] + [InlineData(typeof(InvalidNonStaticTryParseStruct))] + [InlineData(typeof(InvalidNonStaticTryParseClass))] + [InlineData(typeof(TryParseWrongTypeInheritClass))] + public void FindTryParseMethod_ThrowsIfInvalidTryParseOnType(Type type) + { + var ex = Assert.Throws( + () => new ParameterBindingMethodCache().FindTryParseMethod(type)); + Assert.StartsWith($"TryParse method found on {TypeNameHelper.GetTypeDisplayName(type, fullName: false)} with incorrect format. Must be a static method with format", ex.Message); + Assert.Contains($"bool TryParse(string, IFormatProvider, out {TypeNameHelper.GetTypeDisplayName(type, fullName: false)})", ex.Message); + Assert.Contains($"bool TryParse(string, out {TypeNameHelper.GetTypeDisplayName(type, fullName: false)})", ex.Message); + } + + [Theory] + [InlineData(typeof(TryParseClassWithGoodAndBad))] + [InlineData(typeof(TryParseStructWithGoodAndBad))] + public void FindTryParseMethod_IgnoresInvalidTryParseIfGoodOneFound(Type type) + { + var method = new ParameterBindingMethodCache().FindTryParseMethod(type); + Assert.NotNull(method); + } + + [Theory] + [InlineData(typeof(InvalidWrongReturnBindAsyncStruct))] + [InlineData(typeof(InvalidWrongReturnBindAsyncClass))] + [InlineData(typeof(InvalidWrongParamBindAsyncStruct))] + [InlineData(typeof(InvalidWrongParamBindAsyncClass))] + [InlineData(typeof(BindAsyncWrongTypeInherit))] + [InlineData(typeof(BindAsyncWithParameterInfoWrongTypeInherit))] + public void FindBindAsyncMethod_ThrowsIfInvalidBindAsyncOnType(Type type) + { + var cache = new ParameterBindingMethodCache(); + var parameter = new MockParameterInfo(type, "anything"); + var ex = Assert.Throws( + () => cache.FindBindAsyncMethod(parameter)); + Assert.StartsWith($"BindAsync method found on {TypeNameHelper.GetTypeDisplayName(type, fullName: false)} with incorrect format. Must be a static method with format", ex.Message); + Assert.Contains($"ValueTask<{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}> BindAsync(HttpContext context, ParameterInfo parameter)", ex.Message); + Assert.Contains($"ValueTask<{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}> BindAsync(HttpContext context)", ex.Message); + Assert.Contains($"ValueTask<{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}?> BindAsync(HttpContext context, ParameterInfo parameter)", ex.Message); + Assert.Contains($"ValueTask<{TypeNameHelper.GetTypeDisplayName(type, fullName: false)}?> BindAsync(HttpContext context)", ex.Message); + } + + [Theory] + [InlineData(typeof(BindAsyncStructWithGoodAndBad))] + [InlineData(typeof(BindAsyncClassWithGoodAndBad))] + public void FindBindAsyncMethod_IgnoresInvalidBindAsyncIfGoodOneFound(Type type) + { + var cache = new ParameterBindingMethodCache(); + var parameter = new MockParameterInfo(type, "anything"); + var (expression, _) = cache.FindBindAsyncMethod(parameter); + Assert.NotNull(expression); + } + enum Choice { One, @@ -292,8 +380,8 @@ private static void NullableReturningBindAsyncStructMethod(NullableReturningBind private static void BindAsyncSingleArgRecordMethod(BindAsyncSingleArgRecord arg) { } private static void BindAsyncSingleArgStructMethod(BindAsyncSingleArgStruct arg) { } - private static void BindAsyncNullableSingleArgStructMethod(BindAsyncSingleArgStruct? arg) { } - private static void NullableReturningBindAsyncSingleArgStructMethod(NullableReturningBindAsyncSingleArgStruct arg) { } + private static void InheritBindAsyncMethod(InheritBindAsync arg) { } + private static void InheritBindAsyncWithParameterInfoMethod(InheritBindAsyncWithParameterInfo args) { } private static ParameterInfo GetFirstParameter(Expression> expr) { @@ -331,6 +419,218 @@ public static bool TryParse(string? value, IFormatProvider formatProvider, out T } } + private record struct InvalidVoidReturnTryParseStruct(int Value) + { + public static void TryParse(string? value, IFormatProvider formatProvider, out InvalidVoidReturnTryParseStruct result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = default; + return; + } + + result = new InvalidVoidReturnTryParseStruct(val); + return; + } + } + + private record struct InvalidWrongTypeTryParseStruct(int Value) + { + public static bool TryParse(string? value, IFormatProvider formatProvider, out InvalidVoidReturnTryParseStruct result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = default; + return false; + } + + result = new InvalidVoidReturnTryParseStruct(val); + return true; + } + } + + private record struct InvalidTryParseNullableStruct(int Value) + { + public static bool TryParse(string? value, IFormatProvider formatProvider, out InvalidTryParseNullableStruct? result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = default; + return false; + } + + result = new InvalidTryParseNullableStruct(val); + return true; + } + } + + private record struct InvalidTooFewArgsTryParseStruct(int Value) + { + public static bool TryParse(out InvalidTooFewArgsTryParseStruct result) + { + result = default; + return false; + } + } + + private struct TryParseStructWithGoodAndBad + { + public static bool TryParse(string? value, out TryParseStructWithGoodAndBad result) + { + result = new(); + return false; + } + + public static void TryParse(out TryParseStructWithGoodAndBad result) + { + result = new(); + } + } + + private record struct InvalidNonStaticTryParseStruct(int Value) + { + public bool TryParse(string? value, IFormatProvider formatProvider, out InvalidVoidReturnTryParseStruct result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = default; + return false; + } + + result = new InvalidVoidReturnTryParseStruct(val); + return true; + } + } + + private class InvalidVoidReturnTryParseClass + { + public static void TryParse(string? value, IFormatProvider formatProvider, out InvalidVoidReturnTryParseClass result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = new(); + return; + } + + result = new(); + } + } + + private class InvalidWrongTypeTryParseClass + { + public static bool TryParse(string? value, IFormatProvider formatProvider, out InvalidVoidReturnTryParseClass result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = new(); + return false; + } + + result = new(); + return true; + } + } + + private class InvalidTooFewArgsTryParseClass + { + public static bool TryParse(out InvalidTooFewArgsTryParseClass result) + { + result = new(); + return false; + } + } + + private class TryParseClassWithGoodAndBad + { + public static bool TryParse(string? value, out TryParseClassWithGoodAndBad result) + { + result = new(); + return false; + } + + public static bool TryParse(out TryParseClassWithGoodAndBad result) + { + result = new(); + return false; + } + } + + private class InvalidNonStaticTryParseClass + { + public bool TryParse(string? value, IFormatProvider formatProvider, out InvalidNonStaticTryParseClass result) + { + if (!int.TryParse(value, NumberStyles.Integer, formatProvider, out var val)) + { + result = new(); + return false; + } + + result = new(); + return true; + } + } + + private record TryParseNoFormatProviderRecord(int Value) + { + public static bool TryParse(string? value, out TryParseNoFormatProviderRecord? result) + { + if (!int.TryParse(value, out var val)) + { + result = null; + return false; + } + + result = new TryParseNoFormatProviderRecord(val); + return true; + } + } + + private record struct TryParseNoFormatProviderStruct(int Value) + { + public static bool TryParse(string? value, out TryParseNoFormatProviderStruct result) + { + if (!int.TryParse(value, out var val)) + { + result = default; + return false; + } + + result = new TryParseNoFormatProviderStruct(val); + return true; + } + } + + private class BaseTryParseClass + { + public static bool TryParse(string? value, out T? result) + { + result = default(T); + return false; + } + } + + private class TryParseInheritClass : BaseTryParseClass + { + } + + // using wrong T on purpose + private class TryParseWrongTypeInheritClass : BaseTryParseClass + { + } + + private class BaseTryParseClassWithFormatProvider + { + public static bool TryParse(string? value, IFormatProvider formatProvider, out T? result) + { + result = default(T); + return false; + } + } + + private class TryParseInheritClassWithFormatProvider : BaseTryParseClassWithFormatProvider + { + } + private record BindAsyncRecord(int Value) { public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter) @@ -395,12 +695,82 @@ public static ValueTask BindAsync(HttpContext context) } } - private record struct NullableReturningBindAsyncSingleArgStruct(int Value) + private record struct InvalidWrongReturnBindAsyncStruct(int Value) { - public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter) => + public static Task BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private class InvalidWrongReturnBindAsyncClass + { + public static Task BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private record struct InvalidWrongParamBindAsyncStruct(int Value) + { + public static ValueTask BindAsync(ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private class InvalidWrongParamBindAsyncClass + { + public static Task BindAsync(ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private record struct BindAsyncStructWithGoodAndBad(int Value) + { + public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + + public static ValueTask BindAsync(ParameterInfo parameter) => throw new NotImplementedException(); } + private class BindAsyncClassWithGoodAndBad + { + public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + + public static ValueTask BindAsync(ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private class BaseBindAsync + { + public static ValueTask BindAsync(HttpContext context) + { + return new(default(T)); + } + } + + private class InheritBindAsync : BaseBindAsync + { + } + + // Using wrong T on purpose + private class BindAsyncWrongTypeInherit : BaseBindAsync + { + } + + private class BaseBindAsyncWithParameterInfo + { + public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter) + { + return new(default(T)); + } + } + + private class InheritBindAsyncWithParameterInfo : BaseBindAsyncWithParameterInfo + { + } + + // Using wrong T on purpose + private class BindAsyncWithParameterInfoWrongTypeInherit : BaseBindAsyncWithParameterInfo + { + } + private class MockParameterInfo : ParameterInfo { public MockParameterInfo(Type type, string name) diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs index c71c5d53a77b..0560be6e3337 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs @@ -904,7 +904,7 @@ void TestAction([FromRoute] int tryParsable, [FromRoute] int tryParsable2) } [Fact] - public async Task RequestDelegateLogsTryParsableFailuresAsDebugAndThrowsIfThrowOnBadRequest() + public async Task RequestDelegateThrowsForTryParsableFailuresIfThrowOnBadRequest() { var invoked = false; @@ -969,7 +969,7 @@ public async Task RequestDelegateLogsBindAsyncFailuresAndSets400Response() } [Fact] - public async Task RequestDelegateLogsBindAsyncFailuresAndThrowsIfThrowOnBadRequest() + public async Task RequestDelegateThrowsForBindAsyncFailuresIfThrowOnBadRequest() { // Not supplying any headers will cause the HttpContext BindAsync overload to return null. var httpContext = CreateHttpContext(); @@ -1084,7 +1084,7 @@ public async Task BindAsyncWithBodyArgument() var httpContext = CreateHttpContext(); var requestBodyBytes = JsonSerializer.SerializeToUtf8Bytes(originalTodo); - var stream = new MemoryStream(requestBodyBytes); ; + var stream = new MemoryStream(requestBodyBytes); httpContext.Request.Body = stream; httpContext.Request.Headers["Content-Type"] = "application/json"; @@ -1140,7 +1140,7 @@ public async Task BindAsyncRunsBeforeBodyBinding() var httpContext = CreateHttpContext(); var requestBodyBytes = JsonSerializer.SerializeToUtf8Bytes(originalTodo); - var stream = new MemoryStream(requestBodyBytes); ; + var stream = new MemoryStream(requestBodyBytes); httpContext.Request.Body = stream; httpContext.Request.Headers["Content-Type"] = "application/json"; @@ -1302,7 +1302,7 @@ public async Task RequestDelegatePopulatesFromBodyParameter(Delegate action) var httpContext = CreateHttpContext(); var requestBodyBytes = JsonSerializer.SerializeToUtf8Bytes(originalTodo); - var stream = new MemoryStream(requestBodyBytes); ; + var stream = new MemoryStream(requestBodyBytes); httpContext.Request.Body = stream; httpContext.Request.Headers["Content-Type"] = "application/json"; @@ -1421,7 +1421,7 @@ void TestAction([FromBody(AllowEmpty = true)] BodyStruct bodyStruct) [Theory] [InlineData(true)] [InlineData(false)] - public async Task RequestDelegateLogsFromBodyIOExceptionsAsDebugDoesNotAbortAndNeverThrows(bool throwOnBadRequests) + public async Task RequestDelegateLogsIOExceptionsAsDebugDoesNotAbortAndNeverThrows(bool throwOnBadRequests) { var invoked = false; @@ -1454,7 +1454,7 @@ void TestAction([FromBody] Todo todo) } [Fact] - public async Task RequestDelegateLogsFromBodyInvalidDataExceptionsAsDebugAndSets400Response() + public async Task RequestDelegateLogsJsonExceptionsAsDebugAndSets400Response() { var invoked = false; @@ -1463,12 +1463,12 @@ void TestAction([FromBody] Todo todo) invoked = true; } - var invalidDataException = new InvalidDataException(); + var jsonException = new JsonException(); var httpContext = CreateHttpContext(); httpContext.Request.Headers["Content-Type"] = "application/json"; httpContext.Request.Headers["Content-Length"] = "1"; - httpContext.Request.Body = new ExceptionThrowingRequestBodyStream(invalidDataException); + httpContext.Request.Body = new ExceptionThrowingRequestBodyStream(jsonException); httpContext.Features.Set(new RequestBodyDetectionFeature(true)); var factoryResult = RequestDelegateFactory.Create(TestAction); @@ -1482,14 +1482,85 @@ void TestAction([FromBody] Todo todo) Assert.False(httpContext.Response.HasStarted); var logMessage = Assert.Single(TestSink.Writes); - Assert.Equal(new EventId(2, "RequestBodyInvalidDataException"), logMessage.EventId); + Assert.Equal(new EventId(2, "InvalidJsonRequestBody"), logMessage.EventId); Assert.Equal(LogLevel.Debug, logMessage.LogLevel); - Assert.Equal("Reading the request body failed with an InvalidDataException.", logMessage.Message); - Assert.Same(invalidDataException, logMessage.Exception); + Assert.Equal(@"Failed to read parameter ""Todo todo"" from the request body as JSON.", logMessage.Message); + Assert.Same(jsonException, logMessage.Exception); + } + + [Fact] + public async Task RequestDelegateThrowsForJsonExceptionsIfThrowOnBadRequest() + { + var invoked = false; + + void TestAction([FromBody] Todo todo) + { + invoked = true; + } + + var jsonException = new JsonException(); + + var httpContext = CreateHttpContext(); + httpContext.Request.Headers["Content-Type"] = "application/json"; + httpContext.Request.Headers["Content-Length"] = "1"; + httpContext.Request.Body = new ExceptionThrowingRequestBodyStream(jsonException); + httpContext.Features.Set(new RequestBodyDetectionFeature(true)); + + var factoryResult = RequestDelegateFactory.Create(TestAction, new() { ThrowOnBadRequest = true }); + var requestDelegate = factoryResult.RequestDelegate; + + var badHttpRequestException = await Assert.ThrowsAsync(() => requestDelegate(httpContext)); + + Assert.False(invoked); + + // The httpContext should be untouched. + Assert.False(httpContext.RequestAborted.IsCancellationRequested); + Assert.Equal(200, httpContext.Response.StatusCode); + Assert.False(httpContext.Response.HasStarted); + + // We don't log bad requests when we throw. + Assert.Empty(TestSink.Writes); + + Assert.Equal(@"Failed to read parameter ""Todo todo"" from the request body as JSON.", badHttpRequestException.Message); + Assert.Equal(400, badHttpRequestException.StatusCode); + Assert.Same(jsonException, badHttpRequestException.InnerException); } [Fact] - public async Task RequestDelegateLogsFromBodyInvalidDataExceptionsAsDebugAndThrowsIfThrowOnBadRequest() + public async Task RequestDelegateLogsMalformedJsonAsDebugAndSets400Response() + { + var invoked = false; + + void TestAction([FromBody] Todo todo) + { + invoked = true; + } + + var httpContext = CreateHttpContext(); + httpContext.Request.Headers["Content-Type"] = "application/json"; + httpContext.Request.Headers["Content-Length"] = "1"; + httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("{")); + httpContext.Features.Set(new RequestBodyDetectionFeature(true)); + + var factoryResult = RequestDelegateFactory.Create(TestAction); + var requestDelegate = factoryResult.RequestDelegate; + + await requestDelegate(httpContext); + + Assert.False(invoked); + Assert.False(httpContext.RequestAborted.IsCancellationRequested); + Assert.Equal(400, httpContext.Response.StatusCode); + Assert.False(httpContext.Response.HasStarted); + + var logMessage = Assert.Single(TestSink.Writes); + Assert.Equal(new EventId(2, "InvalidJsonRequestBody"), logMessage.EventId); + Assert.Equal(LogLevel.Debug, logMessage.LogLevel); + Assert.Equal(@"Failed to read parameter ""Todo todo"" from the request body as JSON.", logMessage.Message); + Assert.IsType(logMessage.Exception); + } + + [Fact] + public async Task RequestDelegateThrowsForMalformedJsonIfThrowOnBadRequest() { var invoked = false; @@ -1503,7 +1574,7 @@ void TestAction([FromBody] Todo todo) var httpContext = CreateHttpContext(); httpContext.Request.Headers["Content-Type"] = "application/json"; httpContext.Request.Headers["Content-Length"] = "1"; - httpContext.Request.Body = new ExceptionThrowingRequestBodyStream(invalidDataException); + httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("{")); httpContext.Features.Set(new RequestBodyDetectionFeature(true)); var factoryResult = RequestDelegateFactory.Create(TestAction, new() { ThrowOnBadRequest = true }); @@ -1521,9 +1592,9 @@ void TestAction([FromBody] Todo todo) // We don't log bad requests when we throw. Assert.Empty(TestSink.Writes); - Assert.Equal("Reading the request body failed with an InvalidDataException.", badHttpRequestException.Message); + Assert.Equal(@"Failed to read parameter ""Todo todo"" from the request body as JSON.", badHttpRequestException.Message); Assert.Equal(400, badHttpRequestException.StatusCode); - Assert.Same(invalidDataException, badHttpRequestException.InnerException); + Assert.IsType(badHttpRequestException.InnerException); } [Fact] @@ -1538,6 +1609,51 @@ void TestBothInvalidAction(Todo value1, [FromBody] int value2) { } Assert.Throws(() => RequestDelegateFactory.Create(TestBothInvalidAction)); } + [Fact] + public void BuildRequestDelegateThrowsInvalidOperationExceptionForInvalidTryParse() + { + void TestTryParseStruct(BadTryParseStruct value1) { } + void TestTryParseClass(BadTryParseClass value1) { } + + Assert.Throws(() => RequestDelegateFactory.Create(TestTryParseStruct)); + Assert.Throws(() => RequestDelegateFactory.Create(TestTryParseClass)); + } + + private struct BadTryParseStruct + { + public static void TryParse(string? value, out BadTryParseStruct result) { } + } + + private class BadTryParseClass + { + public static void TryParse(string? value, out BadTryParseClass result) + { + result = new(); + } + } + + [Fact] + public void BuildRequestDelegateThrowsInvalidOperationExceptionForInvalidBindAsync() + { + void TestBindAsyncStruct(BadBindAsyncStruct value1) { } + void TestBindAsyncClass(BadBindAsyncClass value1) { } + + var ex = Assert.Throws(() => RequestDelegateFactory.Create(TestBindAsyncStruct)); + Assert.Throws(() => RequestDelegateFactory.Create(TestBindAsyncClass)); + } + + private struct BadBindAsyncStruct + { + public static Task BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + } + + private class BadBindAsyncClass + { + public static Task BindAsync(HttpContext context, ParameterInfo parameter) => + throw new NotImplementedException(); + } + public static object[][] ExplicitFromServiceActions { get diff --git a/src/Http/Routing/src/Builder/DelegateEndpointRouteBuilderExtensions.cs b/src/Http/Routing/src/Builder/DelegateEndpointRouteBuilderExtensions.cs deleted file mode 100644 index 23d815c183cc..000000000000 --- a/src/Http/Routing/src/Builder/DelegateEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,348 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Metadata; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Routing.Patterns; -using Microsoft.CodeAnalysis.CSharp.Symbols; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Builder -{ - /// - /// Provides extension methods for to define HTTP API endpoints. - /// - public static class DelegateEndpointRouteBuilderExtensions - { - // Avoid creating a new array every call - private static readonly string[] GetVerb = new[] { "GET" }; - private static readonly string[] PostVerb = new[] { "POST" }; - private static readonly string[] PutVerb = new[] { "PUT" }; - private static readonly string[] DeleteVerb = new[] { "DELETE" }; - - /// - /// Adds a to the that matches HTTP GET requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder MapGet( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - return MapMethods(endpoints, pattern, GetVerb, handler); - } - - /// - /// Adds a to the that matches HTTP POST requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder MapPost( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - return MapMethods(endpoints, pattern, PostVerb, handler); - } - - /// - /// Adds a to the that matches HTTP PUT requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder MapPut( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - return MapMethods(endpoints, pattern, PutVerb, handler); - } - - /// - /// Adds a to the that matches HTTP DELETE requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder MapDelete( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - return MapMethods(endpoints, pattern, DeleteVerb, handler); - } - - private static DelegateEndpointConventionBuilder Map( - this IEndpointRouteBuilder endpoints, - RoutePattern pattern, - Delegate handler, - bool DisableInferBodyFromParameters) - { - if (endpoints is null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - if (pattern is null) - { - throw new ArgumentNullException(nameof(pattern)); - } - - if (handler is null) - { - throw new ArgumentNullException(nameof(handler)); - } - - const int defaultOrder = 0; - - var routeParams = new List(pattern.Parameters.Count); - foreach (var part in pattern.Parameters) - { - routeParams.Add(part.Name); - } - - var routeHandlerOptions = endpoints.ServiceProvider?.GetService>(); - - var options = new RequestDelegateFactoryOptions - { - ServiceProvider = endpoints.ServiceProvider, - RouteParameterNames = routeParams, - ThrowOnBadRequest = routeHandlerOptions?.Value.ThrowOnBadRequest ?? false, - DisableInferBodyFromParameters = DisableInferBodyFromParameters, - }; - - var requestDelegateResult = RequestDelegateFactory.Create(handler, options); - - var builder = new RouteEndpointBuilder( - requestDelegateResult.RequestDelegate, - pattern, - defaultOrder) - { - DisplayName = pattern.RawText ?? pattern.DebuggerToString(), - }; - - // REVIEW: Should we add an IActionMethodMetadata with just MethodInfo on it so we are - // explicit about the MethodInfo representing the "handler" and not the RequestDelegate? - - // Add MethodInfo as metadata to assist with OpenAPI generation for the endpoint. - builder.Metadata.Add(handler.Method); - - // Methods defined in a top-level program are generated as statics so the delegate - // target will be null. Inline lambdas are compiler generated method so they can - // be filtered that way. - if (GeneratedNameParser.TryParseLocalFunctionName(handler.Method.Name, out var endpointName) - || !TypeHelper.IsCompilerGeneratedMethod(handler.Method)) - { - endpointName ??= handler.Method.Name; - builder.DisplayName = $"{builder.DisplayName} => {endpointName}"; - } - - // Add delegate attributes as metadata - var attributes = handler.Method.GetCustomAttributes(); - - // Add add request delegate metadata - foreach (var metadata in requestDelegateResult.EndpointMetadata) - { - builder.Metadata.Add(metadata); - } - - // This can be null if the delegate is a dynamic method or compiled from an expression tree - if (attributes is not null) - { - foreach (var attribute in attributes) - { - builder.Metadata.Add(attribute); - } - } - - var dataSource = endpoints.DataSources.OfType().FirstOrDefault(); - if (dataSource is null) - { - dataSource = new ModelEndpointDataSource(); - endpoints.DataSources.Add(dataSource); - } - - return new DelegateEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)); - } - - /// - /// Adds a to the that matches HTTP requests - /// for the specified HTTP methods and pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// HTTP methods that the endpoint will match. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder MapMethods( - this IEndpointRouteBuilder endpoints, - string pattern, - IEnumerable httpMethods, - Delegate handler) - { - if (httpMethods is null) - { - throw new ArgumentNullException(nameof(httpMethods)); - } - - var disableInferredBody = false; - foreach (var method in httpMethods) - { - disableInferredBody = ShouldDisableInferredBody(method); - if (disableInferredBody is true) - { - break; - } - } - - var builder = endpoints.Map(RoutePatternFactory.Parse(pattern), handler, disableInferredBody); - // Prepends the HTTP method to the DisplayName produced with pattern + method name - builder.Add(b => b.DisplayName = $"HTTP: {string.Join(", ", httpMethods)} {b.DisplayName}"); - builder.WithMetadata(new HttpMethodMetadata(httpMethods)); - return builder; - - static bool ShouldDisableInferredBody(string method) - { - // GET, DELETE, HEAD, CONNECT, TRACE, and OPTIONS normally do not contain bodies - return method.Equals(HttpMethods.Get, StringComparison.Ordinal) || - method.Equals(HttpMethods.Delete, StringComparison.Ordinal) || - method.Equals(HttpMethods.Head, StringComparison.Ordinal) || - method.Equals(HttpMethods.Options, StringComparison.Ordinal) || - method.Equals(HttpMethods.Trace, StringComparison.Ordinal) || - method.Equals(HttpMethods.Connect, StringComparison.Ordinal); - } - } - - /// - /// Adds a to the that matches HTTP requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Map( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - return Map(endpoints, RoutePatternFactory.Parse(pattern), handler); - } - - /// - /// Adds a to the that matches HTTP requests - /// for the specified pattern. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Map( - this IEndpointRouteBuilder endpoints, - RoutePattern pattern, - Delegate handler) - { - return Map(endpoints, pattern, handler, DisableInferBodyFromParameters: false); - } - - /// - /// Adds a specialized to the that will match - /// requests for non-file-names with the lowest possible priority. - /// - /// The to add the route to. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - /// - /// - /// is intended to handle cases where URL path of - /// the request does not contain a file name, and no other endpoint has matched. This is convenient for routing - /// requests for dynamic content to a SPA framework, while also allowing requests for non-existent files to - /// result in an HTTP 404. - /// - /// - /// registers an endpoint using the pattern - /// {*path:nonfile}. The order of the registered endpoint will be int.MaxValue. - /// - /// - public static DelegateEndpointConventionBuilder MapFallback(this IEndpointRouteBuilder endpoints, Delegate handler) - { - if (endpoints == null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - if (handler == null) - { - throw new ArgumentNullException(nameof(handler)); - } - - return endpoints.MapFallback("{*path:nonfile}", handler); - } - - /// - /// Adds a specialized to the that will match - /// the provided pattern with the lowest possible priority. - /// - /// The to add the route to. - /// The route pattern. - /// The delegate executed when the endpoint is matched. - /// A that can be used to further customize the endpoint. - /// - /// - /// is intended to handle cases where no - /// other endpoint has matched. This is convenient for routing requests to a SPA framework. - /// - /// - /// The order of the registered endpoint will be int.MaxValue. - /// - /// - /// This overload will use the provided verbatim. Use the :nonfile route constraint - /// to exclude requests for static files. - /// - /// - public static DelegateEndpointConventionBuilder MapFallback( - this IEndpointRouteBuilder endpoints, - string pattern, - Delegate handler) - { - if (endpoints == null) - { - throw new ArgumentNullException(nameof(endpoints)); - } - - if (pattern == null) - { - throw new ArgumentNullException(nameof(pattern)); - } - - if (handler == null) - { - throw new ArgumentNullException(nameof(handler)); - } - - var conventionBuilder = endpoints.Map(pattern, handler); - conventionBuilder.WithDisplayName("Fallback " + pattern); - conventionBuilder.Add(b => ((RouteEndpointBuilder)b).Order = int.MaxValue); - return conventionBuilder; - } - } -} diff --git a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs index e2e6f43ad77a..468fd4f54d94 100644 --- a/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/EndpointRouteBuilderExtensions.cs @@ -1,13 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Patterns; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Builder { @@ -187,5 +189,324 @@ public static IEndpointConventionBuilder Map( return dataSource.AddEndpointBuilder(builder); } + + + /// + /// Adds a to the that matches HTTP GET requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder MapGet( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + return MapMethods(endpoints, pattern, GetVerb, handler); + } + + /// + /// Adds a to the that matches HTTP POST requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder MapPost( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + return MapMethods(endpoints, pattern, PostVerb, handler); + } + + /// + /// Adds a to the that matches HTTP PUT requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder MapPut( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + return MapMethods(endpoints, pattern, PutVerb, handler); + } + + /// + /// Adds a to the that matches HTTP DELETE requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder MapDelete( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + return MapMethods(endpoints, pattern, DeleteVerb, handler); + } + + /// + /// Adds a to the that matches HTTP requests + /// for the specified HTTP methods and pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// HTTP methods that the endpoint will match. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder MapMethods( + this IEndpointRouteBuilder endpoints, + string pattern, + IEnumerable httpMethods, + Delegate handler) + { + if (httpMethods is null) + { + throw new ArgumentNullException(nameof(httpMethods)); + } + + var disableInferredBody = false; + foreach (var method in httpMethods) + { + disableInferredBody = ShouldDisableInferredBody(method); + if (disableInferredBody is true) + { + break; + } + } + + var builder = endpoints.Map(RoutePatternFactory.Parse(pattern), handler, disableInferredBody); + // Prepends the HTTP method to the DisplayName produced with pattern + method name + builder.Add(b => b.DisplayName = $"HTTP: {string.Join(", ", httpMethods)} {b.DisplayName}"); + builder.WithMetadata(new HttpMethodMetadata(httpMethods)); + return builder; + + static bool ShouldDisableInferredBody(string method) + { + // GET, DELETE, HEAD, CONNECT, TRACE, and OPTIONS normally do not contain bodies + return method.Equals(HttpMethods.Get, StringComparison.Ordinal) || + method.Equals(HttpMethods.Delete, StringComparison.Ordinal) || + method.Equals(HttpMethods.Head, StringComparison.Ordinal) || + method.Equals(HttpMethods.Options, StringComparison.Ordinal) || + method.Equals(HttpMethods.Trace, StringComparison.Ordinal) || + method.Equals(HttpMethods.Connect, StringComparison.Ordinal); + } + } + + /// + /// Adds a to the that matches HTTP requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Map( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + return Map(endpoints, RoutePatternFactory.Parse(pattern), handler); + } + + /// + /// Adds a to the that matches HTTP requests + /// for the specified pattern. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Map( + this IEndpointRouteBuilder endpoints, + RoutePattern pattern, + Delegate handler) + { + return Map(endpoints, pattern, handler, disableInferBodyFromParameters: false); + } + + /// + /// Adds a specialized to the that will match + /// requests for non-file-names with the lowest possible priority. + /// + /// The to add the route to. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + /// + /// + /// is intended to handle cases where URL path of + /// the request does not contain a file name, and no other endpoint has matched. This is convenient for routing + /// requests for dynamic content to a SPA framework, while also allowing requests for non-existent files to + /// result in an HTTP 404. + /// + /// + /// registers an endpoint using the pattern + /// {*path:nonfile}. The order of the registered endpoint will be int.MaxValue. + /// + /// + public static RouteHandlerBuilder MapFallback(this IEndpointRouteBuilder endpoints, Delegate handler) + { + if (endpoints == null) + { + throw new ArgumentNullException(nameof(endpoints)); + } + + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + return endpoints.MapFallback("{*path:nonfile}", handler); + } + + /// + /// Adds a specialized to the that will match + /// the provided pattern with the lowest possible priority. + /// + /// The to add the route to. + /// The route pattern. + /// The delegate executed when the endpoint is matched. + /// A that can be used to further customize the endpoint. + /// + /// + /// is intended to handle cases where no + /// other endpoint has matched. This is convenient for routing requests to a SPA framework. + /// + /// + /// The order of the registered endpoint will be int.MaxValue. + /// + /// + /// This overload will use the provided verbatim. Use the :nonfile route constraint + /// to exclude requests for static files. + /// + /// + public static RouteHandlerBuilder MapFallback( + this IEndpointRouteBuilder endpoints, + string pattern, + Delegate handler) + { + if (endpoints == null) + { + throw new ArgumentNullException(nameof(endpoints)); + } + + if (pattern == null) + { + throw new ArgumentNullException(nameof(pattern)); + } + + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + var conventionBuilder = endpoints.Map(pattern, handler); + conventionBuilder.WithDisplayName("Fallback " + pattern); + conventionBuilder.Add(b => ((RouteEndpointBuilder)b).Order = int.MaxValue); + return conventionBuilder; + } + + private static RouteHandlerBuilder Map( + this IEndpointRouteBuilder endpoints, + RoutePattern pattern, + Delegate handler, + bool disableInferBodyFromParameters) + { + if (endpoints is null) + { + throw new ArgumentNullException(nameof(endpoints)); + } + + if (pattern is null) + { + throw new ArgumentNullException(nameof(pattern)); + } + + if (handler is null) + { + throw new ArgumentNullException(nameof(handler)); + } + + const int defaultOrder = 0; + + var routeParams = new List(pattern.Parameters.Count); + foreach (var part in pattern.Parameters) + { + routeParams.Add(part.Name); + } + + var routeHandlerOptions = endpoints.ServiceProvider?.GetService>(); + + var options = new RequestDelegateFactoryOptions + { + ServiceProvider = endpoints.ServiceProvider, + RouteParameterNames = routeParams, + ThrowOnBadRequest = routeHandlerOptions?.Value.ThrowOnBadRequest ?? false, + DisableInferBodyFromParameters = disableInferBodyFromParameters, + }; + + var requestDelegateResult = RequestDelegateFactory.Create(handler, options); + + var builder = new RouteEndpointBuilder( + requestDelegateResult.RequestDelegate, + pattern, + defaultOrder) + { + DisplayName = pattern.RawText ?? pattern.DebuggerToString(), + }; + + // REVIEW: Should we add an IActionMethodMetadata with just MethodInfo on it so we are + // explicit about the MethodInfo representing the "handler" and not the RequestDelegate? + + // Add MethodInfo as metadata to assist with OpenAPI generation for the endpoint. + builder.Metadata.Add(handler.Method); + + // Methods defined in a top-level program are generated as statics so the delegate + // target will be null. Inline lambdas are compiler generated method so they can + // be filtered that way. + if (GeneratedNameParser.TryParseLocalFunctionName(handler.Method.Name, out var endpointName) + || !TypeHelper.IsCompilerGeneratedMethod(handler.Method)) + { + endpointName ??= handler.Method.Name; + builder.DisplayName = $"{builder.DisplayName} => {endpointName}"; + } + + // Add delegate attributes as metadata + var attributes = handler.Method.GetCustomAttributes(); + + // Add add request delegate metadata + foreach (var metadata in requestDelegateResult.EndpointMetadata) + { + builder.Metadata.Add(metadata); + } + + // This can be null if the delegate is a dynamic method or compiled from an expression tree + if (attributes is not null) + { + foreach (var attribute in attributes) + { + builder.Metadata.Add(attribute); + } + } + + var dataSource = endpoints.DataSources.OfType().FirstOrDefault(); + if (dataSource is null) + { + dataSource = new ModelEndpointDataSource(); + endpoints.DataSources.Add(dataSource); + } + + return new RouteHandlerBuilder(dataSource.AddEndpointBuilder(builder)); + } } } diff --git a/src/Http/Routing/src/Builder/OpenApiDelegateEndpointConventionBuilderExtensions.cs b/src/Http/Routing/src/Builder/OpenApiRouteHandlerBuilderExtensions.cs similarity index 71% rename from src/Http/Routing/src/Builder/OpenApiDelegateEndpointConventionBuilderExtensions.cs rename to src/Http/Routing/src/Builder/OpenApiRouteHandlerBuilderExtensions.cs index f6e65e088454..34a9d897ad0b 100644 --- a/src/Http/Routing/src/Builder/OpenApiDelegateEndpointConventionBuilderExtensions.cs +++ b/src/Http/Routing/src/Builder/OpenApiRouteHandlerBuilderExtensions.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Http /// Extension methods for adding that is /// meant to be consumed by OpenAPI libraries. ///
- public static class OpenApiDelegateEndpointConventionBuilderExtensions + public static class OpenApiRouteHandlerBuilderExtensions { private static readonly ExcludeFromDescriptionAttribute _excludeFromDescriptionMetadataAttribute = new(); @@ -20,9 +20,9 @@ public static class OpenApiDelegateEndpointConventionBuilderExtensions /// Adds the to for all builders /// produced by . /// - /// The . - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder ExcludeFromDescription(this DelegateEndpointConventionBuilder builder) + /// The . + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder ExcludeFromDescription(this RouteHandlerBuilder builder) { builder.WithMetadata(_excludeFromDescriptionMetadataAttribute); @@ -34,13 +34,13 @@ public static DelegateEndpointConventionBuilder ExcludeFromDescription(this Dele /// produced by . /// /// The type of the response. - /// The . - /// The response status code. Defaults to StatusCodes.Status200OK. + /// The . + /// The response status code. Defaults to . /// The response content type. Defaults to "application/json". /// Additional response content types the endpoint produces for the supplied status code. - /// A that can be used to further customize the endpoint. + /// A that can be used to further customize the endpoint. #pragma warning disable RS0026 - public static DelegateEndpointConventionBuilder Produces(this DelegateEndpointConventionBuilder builder, + public static RouteHandlerBuilder Produces(this RouteHandlerBuilder builder, #pragma warning restore RS0026 int statusCode = StatusCodes.Status200OK, string? contentType = null, @@ -53,14 +53,14 @@ public static DelegateEndpointConventionBuilder Produces(this Delegat /// Adds an to for all builders /// produced by . /// - /// The . + /// The . /// The response status code. /// The type of the response. Defaults to null. /// The response content type. Defaults to "application/json" if responseType is not null, otherwise defaults to null. /// Additional response content types the endpoint produces for the supplied status code. - /// A that can be used to further customize the endpoint. + /// A that can be used to further customize the endpoint. #pragma warning disable RS0026 - public static DelegateEndpointConventionBuilder Produces(this DelegateEndpointConventionBuilder builder, + public static RouteHandlerBuilder Produces(this RouteHandlerBuilder builder, #pragma warning restore RS0026 int statusCode, Type? responseType = null, @@ -87,11 +87,11 @@ public static DelegateEndpointConventionBuilder Produces(this DelegateEndpointCo /// Adds an with a type /// to for all builders produced by . /// - /// The . + /// The . /// The response status code. /// The response content type. Defaults to "application/problem+json". - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder ProducesProblem(this DelegateEndpointConventionBuilder builder, + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder ProducesProblem(this RouteHandlerBuilder builder, int statusCode, string? contentType = null) { @@ -107,17 +107,17 @@ public static DelegateEndpointConventionBuilder ProducesProblem(this DelegateEnd /// Adds an with a type /// to for all builders produced by . /// - /// The . - /// The response status code. Defaults to StatusCodes.Status400BadRequest. - /// The response content type. Defaults to "application/validationproblem+json". - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder ProducesValidationProblem(this DelegateEndpointConventionBuilder builder, + /// The . + /// The response status code. Defaults to . + /// The response content type. Defaults to "application/problem+json". + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder ProducesValidationProblem(this RouteHandlerBuilder builder, int statusCode = StatusCodes.Status400BadRequest, string? contentType = null) { if (string.IsNullOrEmpty(contentType)) { - contentType = "application/validationproblem+json"; + contentType = "application/problem+json"; } return Produces(builder, statusCode, contentType); @@ -132,10 +132,10 @@ public static DelegateEndpointConventionBuilder ProducesValidationProblem(this D /// into related groups. These tags are typically included in the generated specification /// and are typically used to group operations by tags in the UI. /// - /// The . + /// The . /// A collection of tags to be associated with the endpoint. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder WithTags(this DelegateEndpointConventionBuilder builder, params string[] tags) + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder WithTags(this RouteHandlerBuilder builder, params string[] tags) { builder.WithMetadata(new TagsAttribute(tags)); return builder; @@ -146,11 +146,11 @@ public static DelegateEndpointConventionBuilder WithTags(this DelegateEndpointCo /// produced by . /// /// The type of the request body. - /// The . + /// The . /// The request content type that the endpoint accepts. /// The list of additional request content types that the endpoint accepts. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Accepts(this DelegateEndpointConventionBuilder builder, + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Accepts(this RouteHandlerBuilder builder, string contentType, params string[] additionalContentTypes) where TRequest : notnull { Accepts(builder, typeof(TRequest), contentType, additionalContentTypes); @@ -163,12 +163,12 @@ public static DelegateEndpointConventionBuilder Accepts(this DelegateE /// produced by . /// /// The type of the request body. - /// The . + /// The . /// Sets a value that determines if the request body is optional. /// The request content type that the endpoint accepts. /// The list of additional request content types that the endpoint accepts. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Accepts(this DelegateEndpointConventionBuilder builder, + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Accepts(this RouteHandlerBuilder builder, bool isOptional, string contentType, params string[] additionalContentTypes) where TRequest : notnull { Accepts(builder, typeof(TRequest), isOptional, contentType, additionalContentTypes); @@ -180,12 +180,12 @@ public static DelegateEndpointConventionBuilder Accepts(this DelegateE /// Adds to for all builders /// produced by . /// - /// The . + /// The . /// The type of the request body. /// The request content type that the endpoint accepts. /// The list of additional request content types that the endpoint accepts. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Accepts(this DelegateEndpointConventionBuilder builder, + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Accepts(this RouteHandlerBuilder builder, Type requestType, string contentType, params string[] additionalContentTypes) { builder.WithMetadata(new AcceptsMetadata(requestType, false, GetAllContentTypes(contentType, additionalContentTypes))); @@ -197,13 +197,13 @@ public static DelegateEndpointConventionBuilder Accepts(this DelegateEndpointCon /// Adds to for all builders /// produced by . /// - /// The . + /// The . /// The type of the request body. /// Sets a value that determines if the request body is optional. /// The request content type that the endpoint accepts. /// The list of additional request content types that the endpoint accepts. - /// A that can be used to further customize the endpoint. - public static DelegateEndpointConventionBuilder Accepts(this DelegateEndpointConventionBuilder builder, + /// A that can be used to further customize the endpoint. + public static RouteHandlerBuilder Accepts(this RouteHandlerBuilder builder, Type requestType, bool isOptional, string contentType, params string[] additionalContentTypes) { builder.WithMetadata(new AcceptsMetadata(requestType, isOptional, GetAllContentTypes(contentType, additionalContentTypes))); diff --git a/src/Http/Routing/src/Builder/DelegateEndpointConventionBuilder.cs b/src/Http/Routing/src/Builder/RouteHandlerBuilder.cs similarity index 77% rename from src/Http/Routing/src/Builder/DelegateEndpointConventionBuilder.cs rename to src/Http/Routing/src/Builder/RouteHandlerBuilder.cs index d9a41767182f..c170e8244f00 100644 --- a/src/Http/Routing/src/Builder/DelegateEndpointConventionBuilder.cs +++ b/src/Http/Routing/src/Builder/RouteHandlerBuilder.cs @@ -9,26 +9,26 @@ namespace Microsoft.AspNetCore.Builder /// /// Builds conventions that will be used for customization of MapAction instances. /// - public sealed class DelegateEndpointConventionBuilder : IEndpointConventionBuilder + public sealed class RouteHandlerBuilder : IEndpointConventionBuilder { private readonly IEnumerable _endpointConventionBuilders; /// - /// Instantiates a new given a single + /// Instantiates a new given a single /// . /// /// The to instantiate with. - internal DelegateEndpointConventionBuilder(IEndpointConventionBuilder endpointConventionBuilder) + internal RouteHandlerBuilder(IEndpointConventionBuilder endpointConventionBuilder) { _endpointConventionBuilders = new List() { endpointConventionBuilder }; } /// - /// Instantiates a new given multiple + /// Instantiates a new given multiple /// instances. /// /// A list of instances. - public DelegateEndpointConventionBuilder(IEnumerable endpointConventionBuilders) + public RouteHandlerBuilder(IEnumerable endpointConventionBuilders) { _endpointConventionBuilders = endpointConventionBuilders; } diff --git a/src/Http/Routing/src/PublicAPI.Unshipped.txt b/src/Http/Routing/src/PublicAPI.Unshipped.txt index 03affad7bff7..7ed579ae8db2 100644 --- a/src/Http/Routing/src/PublicAPI.Unshipped.txt +++ b/src/Http/Routing/src/PublicAPI.Unshipped.txt @@ -5,10 +5,10 @@ *REMOVED*Microsoft.AspNetCore.Routing.IRouteNameMetadata.RouteName.get -> string! *REMOVED*Microsoft.AspNetCore.Routing.RouteNameMetadata.RouteName.get -> string! *REMOVED*Microsoft.AspNetCore.Routing.RouteNameMetadata.RouteNameMetadata(string! routeName) -> void -Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder -Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder.DelegateEndpointConventionBuilder(System.Collections.Generic.IEnumerable! endpointConventionBuilders) -> void -Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder.Add(System.Action! convention) -> void -Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions +Microsoft.AspNetCore.Builder.RouteHandlerBuilder +Microsoft.AspNetCore.Builder.RouteHandlerBuilder.Add(System.Action! convention) -> void +Microsoft.AspNetCore.Builder.RouteHandlerBuilder.RouteHandlerBuilder(System.Collections.Generic.IEnumerable! endpointConventionBuilders) -> void +Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions Microsoft.AspNetCore.Routing.DataTokensMetadata.DataTokens.get -> System.Collections.Generic.IReadOnlyDictionary! Microsoft.AspNetCore.Routing.DataTokensMetadata.DataTokensMetadata(System.Collections.Generic.IReadOnlyDictionary! dataTokens) -> void Microsoft.AspNetCore.Routing.IDataTokensMetadata.DataTokens.get -> System.Collections.Generic.IReadOnlyDictionary! @@ -29,15 +29,15 @@ Microsoft.AspNetCore.Routing.EndpointGroupNameAttribute.EndpointGroupName.get -> Microsoft.AspNetCore.Routing.EndpointNameAttribute Microsoft.AspNetCore.Routing.EndpointNameAttribute.EndpointNameAttribute(string! endpointName) -> void Microsoft.AspNetCore.Routing.EndpointNameAttribute.EndpointName.get -> string! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, Microsoft.AspNetCore.Routing.Patterns.RoutePattern! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapDelete(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Collections.Generic.IEnumerable! httpMethods, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, Microsoft.AspNetCore.Routing.Patterns.RoutePattern! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapDelete(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Collections.Generic.IEnumerable! httpMethods, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder! endpoints, string! pattern, System.Delegate! handler) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! static Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithName(this TBuilder builder, string! endpointName) -> TBuilder static Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions.WithGroupName(this TBuilder builder, string! endpointGroupName) -> TBuilder Microsoft.AspNetCore.Routing.IExcludeFromDescriptionMetadata @@ -45,14 +45,13 @@ Microsoft.AspNetCore.Routing.IExcludeFromDescriptionMetadata.ExcludeFromDescript Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute.ExcludeFromDescriptionAttribute() -> void Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute.ExcludeFromDescription.get -> bool -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.WithTags(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, params string![]! tags) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, System.Type! requestType, bool isOptional, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, System.Type! requestType, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, bool isOptional, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.ExcludeFromDescription(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Produces(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, int statusCode, System.Type? responseType = null, string? contentType = null, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.Produces(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, int statusCode = 200, string? contentType = null, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.ProducesProblem(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, int statusCode, string? contentType = null) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -static Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions.ProducesValidationProblem(this Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! builder, int statusCode = 400, string? contentType = null) -> Microsoft.AspNetCore.Builder.DelegateEndpointConventionBuilder! -Microsoft.AspNetCore.Http.OpenApiDelegateEndpointConventionBuilderExtensions +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, System.Type! requestType, bool isOptional, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, System.Type! requestType, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, bool isOptional, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, string! contentType, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ExcludeFromDescription(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, int statusCode, System.Type? responseType = null, string? contentType = null, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.Produces(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, int statusCode = 200, string? contentType = null, params string![]! additionalContentTypes) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesProblem(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, int statusCode, string? contentType = null) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.ProducesValidationProblem(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, int statusCode = 400, string? contentType = null) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! +static Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions.WithTags(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder! builder, params string![]! tags) -> Microsoft.AspNetCore.Builder.RouteHandlerBuilder! diff --git a/src/Http/Routing/src/RouteHandlerOptions.cs b/src/Http/Routing/src/RouteHandlerOptions.cs index c7297b86fe75..b16f6db6f201 100644 --- a/src/Http/Routing/src/RouteHandlerOptions.cs +++ b/src/Http/Routing/src/RouteHandlerOptions.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Routing { /// - /// Options for controlling the behavior of + /// Options for controlling the behavior of /// and similar methods. /// public sealed class RouteHandlerOptions diff --git a/src/Http/Routing/test/FunctionalTests/DelegateEndpointTest.cs b/src/Http/Routing/test/FunctionalTests/RouteHandlerTest.cs similarity index 98% rename from src/Http/Routing/test/FunctionalTests/DelegateEndpointTest.cs rename to src/Http/Routing/test/FunctionalTests/RouteHandlerTest.cs index a79195788be8..6dc71ddd22da 100644 --- a/src/Http/Routing/test/FunctionalTests/DelegateEndpointTest.cs +++ b/src/Http/Routing/test/FunctionalTests/RouteHandlerTest.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing.FunctionalTests { - public class DelegateEndpointTest + public class RouteHandlerTest { [Fact] public async Task MapPost_FromBodyWorksWithJsonPayload() diff --git a/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs similarity index 99% rename from src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs rename to src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs index 8d713234a316..f9079850eaa7 100644 --- a/src/Http/Routing/test/UnitTests/Builder/MapEndpointEndpointDataSourceBuilderExtensionsTest.cs +++ b/src/Http/Routing/test/UnitTests/Builder/RequestDelegateEndpointRouteBuilderExtensionsTest.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Builder { - public class MapEndpointEndpointDataSourceBuilderExtensionsTest + public class RequestDelegateEndpointRouteBuilderExtensionsTest { private ModelEndpointDataSource GetBuilderEndpointDataSource(IEndpointRouteBuilder endpointRouteBuilder) { diff --git a/src/Http/Routing/test/UnitTests/Builder/DelegateEndpointRouteBuilderExtensionsTest.cs b/src/Http/Routing/test/UnitTests/Builder/RouteHandlerEndpointRouteBuilderExtensionsTest.cs similarity index 99% rename from src/Http/Routing/test/UnitTests/Builder/DelegateEndpointRouteBuilderExtensionsTest.cs rename to src/Http/Routing/test/UnitTests/Builder/RouteHandlerEndpointRouteBuilderExtensionsTest.cs index 0746a5dbf23c..2a5e196fc3c0 100644 --- a/src/Http/Routing/test/UnitTests/Builder/DelegateEndpointRouteBuilderExtensionsTest.cs +++ b/src/Http/Routing/test/UnitTests/Builder/RouteHandlerEndpointRouteBuilderExtensionsTest.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Builder { - public class DelegateEndpointRouteBuilderExtensionsTest + public class RouteHandlerEndpointRouteBuilderExtensionsTest { private ModelEndpointDataSource GetBuilderEndpointDataSource(IEndpointRouteBuilder endpointRouteBuilder) { diff --git a/src/Identity/test/Identity.Test/SecurityStampValidatorTest.cs b/src/Identity/test/Identity.Test/SecurityStampValidatorTest.cs index 9a22add05c0a..663b7dc807b8 100644 --- a/src/Identity/test/Identity.Test/SecurityStampValidatorTest.cs +++ b/src/Identity/test/Identity.Test/SecurityStampValidatorTest.cs @@ -285,7 +285,11 @@ public async Task OnValidateIdentityDoesNotExtendExpirationWhenSlidingIsDisabled var services = new ServiceCollection(); services.AddSingleton(options.Object); services.AddSingleton(signInManager.Object); - var clock = new SystemClock(); + var clock = new TestClock() + { + // Second precision + UtcNow = new DateTimeOffset(2013, 6, 11, 12, 34, 56, 0, TimeSpan.Zero) + }; services.AddSingleton(new SecurityStampValidator(options.Object, signInManager.Object, clock, new LoggerFactory())); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); var id = new ClaimsIdentity(IdentityConstants.ApplicationScheme); diff --git a/src/Identity/test/InMemory.Test/TestClock.cs b/src/Identity/test/Shared/TestClock.cs similarity index 91% rename from src/Identity/test/InMemory.Test/TestClock.cs rename to src/Identity/test/Shared/TestClock.cs index 3219f29a3934..6a5ad364f3ac 100644 --- a/src/Identity/test/InMemory.Test/TestClock.cs +++ b/src/Identity/test/Shared/TestClock.cs @@ -4,7 +4,7 @@ using System; using Microsoft.AspNetCore.Authentication; -namespace Microsoft.AspNetCore.Identity.InMemory +namespace Microsoft.AspNetCore.Identity.Test { public class TestClock : ISystemClock { diff --git a/src/Installers/Windows/Common/dotnethome_x64.wxs b/src/Installers/Windows/Common/dotnethome_x64.wxs new file mode 100644 index 000000000000..53e0bc4819e4 --- /dev/null +++ b/src/Installers/Windows/Common/dotnethome_x64.wxs @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + ? + + + + + + NOT %PROCESSOR_ARCHITECTURE="$(var.InstallerArchitecture)" + + + + + + + + NON_NATIVE_ARCHITECTURE AND NOT DOTNETHOME + + + + \ No newline at end of file diff --git a/src/Installers/Windows/SharedFramework/Product.wxs b/src/Installers/Windows/SharedFramework/Product.wxs index 3375094918c0..98b5756c69de 100644 --- a/src/Installers/Windows/SharedFramework/Product.wxs +++ b/src/Installers/Windows/SharedFramework/Product.wxs @@ -35,6 +35,10 @@ + + + + @@ -52,6 +56,10 @@ + + + + @@ -66,16 +74,41 @@ + + + NOT NON_NATIVE_ARCHITECTURE + + + + NOT NON_NATIVE_ARCHITECTURE + + + + + + NON_NATIVE_ARCHITECTURE + + + + + + + NON_NATIVE_ARCHITECTURE + + + + + diff --git a/src/Installers/Windows/SharedFramework/SharedFramework.wixproj b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj index 9b9e4c6f0a7e..becd904b5ea6 100644 --- a/src/Installers/Windows/SharedFramework/SharedFramework.wixproj +++ b/src/Installers/Windows/SharedFramework/SharedFramework.wixproj @@ -46,6 +46,7 @@ + diff --git a/src/Installers/Windows/TargetingPack/Product.wxs b/src/Installers/Windows/TargetingPack/Product.wxs index 33b6173a7a5b..6317450b2670 100644 --- a/src/Installers/Windows/TargetingPack/Product.wxs +++ b/src/Installers/Windows/TargetingPack/Product.wxs @@ -39,6 +39,10 @@ + + + + @@ -55,6 +59,10 @@ + + + + @@ -65,16 +73,41 @@ + + + NOT NON_NATIVE_ARCHITECTURE + + + + NOT NON_NATIVE_ARCHITECTURE + + + + + + + NON_NATIVE_ARCHITECTURE + + + + + + NON_NATIVE_ARCHITECTURE + + + + + diff --git a/src/Installers/Windows/TargetingPack/TargetingPack.wixproj b/src/Installers/Windows/TargetingPack/TargetingPack.wixproj index 61f24ee3b14a..610d68da3d43 100644 --- a/src/Installers/Windows/TargetingPack/TargetingPack.wixproj +++ b/src/Installers/Windows/TargetingPack/TargetingPack.wixproj @@ -48,6 +48,7 @@ + diff --git a/src/Mvc/Mvc.ApiExplorer/test/ApiResponseTypeProviderTest.cs b/src/Mvc/Mvc.ApiExplorer/test/ApiResponseTypeProviderTest.cs index fe0225df8e97..92f04f4c3451 100644 --- a/src/Mvc/Mvc.ApiExplorer/test/ApiResponseTypeProviderTest.cs +++ b/src/Mvc/Mvc.ApiExplorer/test/ApiResponseTypeProviderTest.cs @@ -715,7 +715,7 @@ public void GetApiResponseTypes_HandlesActionWithMultipleContentTypesAndProduces // Arrange var actionDescriptor = GetControllerActionDescriptor(typeof(TestController), nameof(TestController.GetUser)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesAttribute("text/xml") { Type = typeof(BaseModel) }, FilterScope.Action)); - actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ValidationProblemDetails), 400, "application/validationproblem+json"), FilterScope.Action)); + actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ValidationProblemDetails), 400, "application/problem+json"), FilterScope.Action)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(typeof(ProblemDetails), 404, "application/problem+json"), FilterScope.Action)); actionDescriptor.FilterDescriptors.Add(new FilterDescriptor(new ProducesResponseTypeAttribute(409), FilterScope.Action)); @@ -738,7 +738,7 @@ public void GetApiResponseTypes_HandlesActionWithMultipleContentTypesAndProduces { Assert.Equal(typeof(ValidationProblemDetails), responseType.Type); Assert.Equal(400, responseType.StatusCode); - Assert.Equal(new[] { "application/validationproblem+json" }, GetSortedMediaTypes(responseType)); + Assert.Equal(new[] { "application/problem+json" }, GetSortedMediaTypes(responseType)); }, responseType => { diff --git a/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs b/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs index 05da4a0a9bbd..daafe295ee1c 100644 --- a/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs +++ b/src/Mvc/Mvc.ApiExplorer/test/EndpointMetadataApiDescriptionProviderTest.cs @@ -603,7 +603,7 @@ public void HandlesProducesWithProducesProblem() { Assert.Equal(typeof(HttpValidationProblemDetails), responseType.Type); Assert.Equal(400, responseType.StatusCode); - Assert.Equal(new[] { "application/validationproblem+json" }, GetSortedMediaTypes(responseType)); + Assert.Equal(new[] { "application/problem+json" }, GetSortedMediaTypes(responseType)); }, responseType => { diff --git a/src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-FSharp.fsproj.in b/src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-FSharp.fsproj.in index c6ddfee52e47..67cd7e941246 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-FSharp.fsproj.in +++ b/src/ProjectTemplates/Web.ProjectTemplates/StarterWeb-FSharp.fsproj.in @@ -9,7 +9,6 @@ - diff --git a/src/ProjectTemplates/Web.ProjectTemplates/WebApi-FSharp.fsproj.in b/src/ProjectTemplates/Web.ProjectTemplates/WebApi-FSharp.fsproj.in index ec9d1aa17b6e..8a9f8ed0e2e5 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/WebApi-FSharp.fsproj.in +++ b/src/ProjectTemplates/Web.ProjectTemplates/WebApi-FSharp.fsproj.in @@ -9,7 +9,6 @@ - diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Program.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Program.fs index 91d8b747cdc5..07d261f44762 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Program.fs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Program.fs @@ -1,27 +1,55 @@ namespace Company.WebApplication1 +#nowarn "20" + open System open System.Collections.Generic open System.IO open System.Linq open System.Threading.Tasks open Microsoft.AspNetCore +open Microsoft.AspNetCore.Builder open Microsoft.AspNetCore.Hosting +#if !NoHttps +open Microsoft.AspNetCore.HttpsPolicy +#endif open Microsoft.Extensions.Configuration +open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.Hosting open Microsoft.Extensions.Logging module Program = let exitCode = 0 - let CreateHostBuilder args = - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(fun webBuilder -> - webBuilder.UseStartup() |> ignore - ) - [] let main args = - CreateHostBuilder(args).Build().Run() + let builder = WebApplication.CreateBuilder(args) + + builder + .Services + .AddControllersWithViews() + .AddRazorRuntimeCompilation() + + builder.Services.AddRazorPages() + + let app = builder.Build() + + if not (builder.Environment.IsDevelopment()) then + app.UseExceptionHandler("/Home/Error") +#if !NoHttps + app.UseHsts() |> ignore // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + + app.UseHttpsRedirection() +#endif + + app.UseStaticFiles() + app.UseRouting() + app.UseAuthorization() + + app.MapControllerRoute(name = "default", pattern = "{controller=Home}/{action=Index}/{id?}") + + app.MapRazorPages() + + app.Run() exitCode diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs deleted file mode 100644 index 607ec13b55bf..000000000000 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/Startup.fs +++ /dev/null @@ -1,55 +0,0 @@ -namespace Company.WebApplication1 - -open System -open System.Collections.Generic -open System.Linq -open System.Threading.Tasks -open Microsoft.AspNetCore.Builder -open Microsoft.AspNetCore.Hosting -#if (!NoHttps) -open Microsoft.AspNetCore.HttpsPolicy; -#endif -open Microsoft.AspNetCore.Mvc -open Microsoft.Extensions.Configuration -open Microsoft.Extensions.DependencyInjection -open Microsoft.Extensions.Hosting - -type Startup private () = - new (configuration: IConfiguration) as this = - Startup() then - this.Configuration <- configuration - - // This method gets called by the runtime. Use this method to add services to the container. - member this.ConfigureServices(services: IServiceCollection) = - // Add framework services. - services.AddControllersWithViews().AddRazorRuntimeCompilation() |> ignore - services.AddRazorPages() |> ignore - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - member this.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) = - - if (env.IsDevelopment()) then - app.UseDeveloperExceptionPage() |> ignore - else - app.UseExceptionHandler("/Home/Error") |> ignore -#if (!NoHttps) - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts() |> ignore - - app.UseHttpsRedirection() |> ignore -#else - -#endif - app.UseStaticFiles() |> ignore - - app.UseRouting() |> ignore - - app.UseAuthorization() |> ignore - - app.UseEndpoints(fun endpoints -> - endpoints.MapControllerRoute( - name = "default", - pattern = "{controller=Home}/{action=Index}/{id?}") |> ignore - endpoints.MapRazorPages() |> ignore) |> ignore - - member val Configuration : IConfiguration = null with get, set diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Program.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Program.cs index 05bd50938689..5c53385a9fcb 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Program.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-CSharp/Program.cs @@ -43,6 +43,7 @@ builder.Services.AddControllers(); #if (EnableOpenAPI) +builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new() { Title = "Company.WebApplication1", Version = "v1" }); diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Program.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Program.fs index 91d8b747cdc5..0593d5111bd0 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Program.fs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Program.fs @@ -1,27 +1,40 @@ namespace Company.WebApplication1 - +#nowarn "20" open System open System.Collections.Generic open System.IO open System.Linq open System.Threading.Tasks open Microsoft.AspNetCore +open Microsoft.AspNetCore.Builder open Microsoft.AspNetCore.Hosting +#if !NoHttps +open Microsoft.AspNetCore.HttpsPolicy +#endif open Microsoft.Extensions.Configuration +open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.Hosting open Microsoft.Extensions.Logging module Program = let exitCode = 0 - let CreateHostBuilder args = - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(fun webBuilder -> - webBuilder.UseStartup() |> ignore - ) - [] let main args = - CreateHostBuilder(args).Build().Run() + + let builder = WebApplication.CreateBuilder(args) + + builder.Services.AddControllers() + + let app = builder.Build() + +#if !NoHttps + app.UseHttpsRedirection() +#endif + + app.UseAuthorization() + app.MapControllers() + + app.Run() exitCode diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs b/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs deleted file mode 100644 index 1a44dc3b0868..000000000000 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/WebApi-FSharp/Startup.fs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Company.WebApplication1 - -open System -open System.Collections.Generic -open System.Linq -open System.Threading.Tasks -open Microsoft.AspNetCore.Builder -open Microsoft.AspNetCore.Hosting -#if (!NoHttps) -open Microsoft.AspNetCore.HttpsPolicy; -#endif -open Microsoft.AspNetCore.Mvc -open Microsoft.Extensions.Configuration -open Microsoft.Extensions.DependencyInjection -open Microsoft.Extensions.Hosting - -type Startup(configuration: IConfiguration) = - member _.Configuration = configuration - - // This method gets called by the runtime. Use this method to add services to the container. - member _.ConfigureServices(services: IServiceCollection) = - // Add framework services. - services.AddControllers() |> ignore - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - member _.Configure(app: IApplicationBuilder, env: IWebHostEnvironment) = - if (env.IsDevelopment()) then - app.UseDeveloperExceptionPage() |> ignore -#if (!NoHttps) - app.UseHttpsRedirection() - .UseRouting() - .UseAuthorization() - .UseEndpoints(fun endpoints -> - endpoints.MapControllers() |> ignore - ) |> ignore -#else - app.UseRouting() - .UseAuthorization() - .UseEndpoints(fun endpoints -> - endpoints.MapControllers() |> ignore - ) |> ignore -#endif diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index eb3859aabb05..b707dcd78819 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -631,7 +631,6 @@ "appsettings.Development.json", "appsettings.json", "Program.fs", - "Startup.fs", "WeatherForecast.fs", "Controllers/WeatherForecastController.fs", "Properties/launchSettings.json" @@ -1142,7 +1141,6 @@ "appsettings.Development.json", "appsettings.json", "Program.fs", - "Startup.fs", "Controllers/HomeController.fs", "Models/ErrorViewModel.fs", "Properties/launchSettings.json", diff --git a/src/Servers/HttpSys/HttpSysServer.slnf b/src/Servers/HttpSys/HttpSysServer.slnf index 62fd45d3320f..3990e33925cb 100644 --- a/src/Servers/HttpSys/HttpSysServer.slnf +++ b/src/Servers/HttpSys/HttpSysServer.slnf @@ -31,7 +31,9 @@ "src\\Servers\\HttpSys\\samples\\TestClient\\TestClient.csproj", "src\\Servers\\HttpSys\\src\\Microsoft.AspNetCore.Server.HttpSys.csproj", "src\\Servers\\HttpSys\\test\\FunctionalTests\\Microsoft.AspNetCore.Server.HttpSys.FunctionalTests.csproj", + "src\\Servers\\HttpSys\\test\\NonHelixTests\\Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj", "src\\Servers\\HttpSys\\test\\Tests\\Microsoft.AspNetCore.Server.HttpSys.Tests.csproj", + "src\\Servers\\HttpSys\\test\\testassets\\DelegationSite\\DelegationSite.csproj", "src\\Servers\\IIS\\IISIntegration\\src\\Microsoft.AspNetCore.Server.IISIntegration.csproj", "src\\Servers\\IIS\\IIS\\src\\Microsoft.AspNetCore.Server.IIS.csproj", "src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", diff --git a/src/Servers/HttpSys/src/MessagePump.cs b/src/Servers/HttpSys/src/MessagePump.cs index fde21e41dcd0..2d4df374e534 100644 --- a/src/Servers/HttpSys/src/MessagePump.cs +++ b/src/Servers/HttpSys/src/MessagePump.cs @@ -55,7 +55,7 @@ public MessagePump(IOptions options, ILoggerFactory loggerFactor _serverAddresses = new ServerAddressesFeature(); Features.Set(_serverAddresses); - if (HttpApi.IsFeatureSupported(HttpApiTypes.HTTP_FEATURE_ID.HttpFeatureDelegateEx)) + if (HttpApi.SupportsDelegation) { var delegationProperty = new ServerDelegationPropertyFeature(Listener.RequestQueue, _logger); Features.Set(delegationProperty); diff --git a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj index 5ef4637d0772..dff0c5861c71 100644 --- a/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj +++ b/src/Servers/HttpSys/src/Microsoft.AspNetCore.Server.HttpSys.csproj @@ -28,4 +28,9 @@ + + + + + diff --git a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs index 83d56d3cfc8a..d371721197cd 100644 --- a/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs +++ b/src/Servers/HttpSys/src/NativeInterop/HttpApi.cs @@ -125,6 +125,7 @@ internal static HTTP_API_VERSION ApiVersion internal static bool SupportsTrailers { get; private set; } [MemberNotNullWhen(true, nameof(HttpSetRequestProperty))] internal static bool SupportsReset { get; private set; } + internal static bool SupportsDelegation { get; private set; } static HttpApi() { @@ -136,7 +137,7 @@ private static void InitHttpApi(ushort majorVersion, ushort minorVersion) version.HttpApiMajorVersion = majorVersion; version.HttpApiMinorVersion = minorVersion; - var statusCode = HttpInitialize(version, (uint)HTTP_FLAGS.HTTP_INITIALIZE_SERVER, null); + var statusCode = HttpInitialize(version, (uint)(HTTP_FLAGS.HTTP_INITIALIZE_SERVER | HTTP_FLAGS.HTTP_INITIALIZE_CONFIG), null); supported = statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS; @@ -144,10 +145,9 @@ private static void InitHttpApi(ushort majorVersion, ushort minorVersion) { HttpApiModule = SafeLibraryHandle.Open(HTTPAPI); HttpSetRequestProperty = HttpApiModule.GetProcAddress("HttpSetRequestProperty", throwIfNotFound: false); - SupportsReset = HttpSetRequestProperty != null; - // Trailers support was added in the same release as Reset, but there's no method we can export to check it directly. - SupportsTrailers = SupportsReset; + SupportsTrailers = IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureResponseTrailers); + SupportsDelegation = IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureDelegateEx); } } @@ -160,7 +160,7 @@ internal static bool Supported } } - internal static bool IsFeatureSupported(HTTP_FEATURE_ID feature) + private static bool IsFeatureSupported(HTTP_FEATURE_ID feature) { try { diff --git a/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs b/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs deleted file mode 100644 index c33e8da68ef0..000000000000 --- a/src/Servers/HttpSys/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.HttpSys.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Servers/HttpSys/src/StandardFeatureCollection.cs b/src/Servers/HttpSys/src/StandardFeatureCollection.cs index 9c79d2938a4c..c5eb1be5e577 100644 --- a/src/Servers/HttpSys/src/StandardFeatureCollection.cs +++ b/src/Servers/HttpSys/src/StandardFeatureCollection.cs @@ -48,7 +48,7 @@ static StandardFeatureCollection() _featureFuncLookup[typeof(ITlsHandshakeFeature)] = ctx => ctx.GetTlsHandshakeFeature(); } - if (HttpApi.IsFeatureSupported(HttpApiTypes.HTTP_FEATURE_ID.HttpFeatureDelegateEx)) + if (HttpApi.SupportsDelegation) { _featureFuncLookup[typeof(IHttpSysRequestDelegationFeature)] = _identityFunc; } diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs index 2a0d65bc2138..625dea9a27a3 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateSupportedConditionAttribute.cs @@ -1,13 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.AspNetCore.Testing; -using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes; namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests { @@ -17,14 +11,8 @@ public class DelegateSupportedConditionAttribute : Attribute, ITestCondition private readonly bool _isSupported; public DelegateSupportedConditionAttribute(bool isSupported) => _isSupported = isSupported; - private readonly Lazy _isDelegateSupported = new Lazy(CanDelegate); - public bool IsMet => (_isDelegateSupported.Value == _isSupported); + public bool IsMet => HttpApi.SupportsDelegation == _isSupported; public string SkipReason => $"Http.Sys does {(_isSupported ? "not" : "")} support delegating requests"; - - private static bool CanDelegate() - { - return HttpApi.IsFeatureSupported(HTTP_FEATURE_ID.HttpFeatureDelegateEx); - } } } diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs index e8db9c6e77a6..ca9dcf3a0736 100644 --- a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs +++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs @@ -148,6 +148,9 @@ public async Task DelegateAfterRequestBodyReadShouldThrow() [DelegateSupportedCondition(false)] public async Task DelegationFeaturesAreNull() { + // Testing the DelegateSupportedCondition + Assert.True(Environment.OSVersion.Version < new Version(10, 0, 22000), "This should be supported on Win 11."); + using var delegator = Utilities.CreateHttpServer(out var delegatorAddress, httpContext => { var delegateFeature = httpContext.Features.Get(); diff --git a/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs b/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs new file mode 100644 index 000000000000..16b229d1e2e3 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DelegateOutOfProcTests.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net.Http; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Testing; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Server.HttpSys.NonHelixTests +{ + public class DelegateOutOfProcTests : LoggedTest + { + public DelegateOutOfProcTests(ITestOutputHelper output) : base(output) { } + + [ConditionalFact] + [DelegateSupportedCondition(true)] + public async Task CanDelegateOutOfProcess() + { + using var _ = StartLog(out var loggerFactory); + + var logger = loggerFactory.CreateLogger("CanDelegateOutOfProcess"); + + // https://github.com/dotnet/aspnetcore/issues/8247 +#pragma warning disable 0618 + var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("HttpSysServer"), "test", "testassets", + "DelegationSite"); +#pragma warning restore 0618 + + var deploymentParameters = new DeploymentParameters( + applicationPath, + ServerType.HttpSys, + RuntimeFlavor.CoreClr, + RuntimeArchitecture.x64) + { + EnvironmentName = "Testing", + TargetFramework = Tfm.Default, + ApplicationType = ApplicationType.Portable, + PublishApplicationBeforeDeployment = true, + StatusMessagesEnabled = true + }; + + var queueName = Guid.NewGuid().ToString(); + deploymentParameters.EnvironmentVariables["queue"] = queueName; + + using var deployer = new SelfHostDeployer(deploymentParameters, loggerFactory); + var deploymentResult = await deployer.DeployAsync().DefaultTimeout(); + + // Make sure the deployment really worked + var responseString = await deploymentResult.HttpClient.GetStringAsync("").DefaultTimeout(); + Assert.Equal("Hello from delegatee", responseString); + + DelegationRule destination = default; + using var delegator = Utilities.CreateHttpServer(out var delegatorAddress, httpContext => + { + var delegateFeature = httpContext.Features.Get(); + delegateFeature.DelegateRequest(destination); + return Task.CompletedTask; + }); + + var delegationProperty = delegator.Features.Get(); + using (destination = delegationProperty.CreateDelegationRule(queueName, deploymentResult.ApplicationBaseUri)) + { + // Send a request to the delegator that gets transfered to the delegatee in the other process. + using var client = new HttpClient(); + responseString = await client.GetStringAsync(delegatorAddress).DefaultTimeout(); + Assert.Equal("Hello from delegatee", responseString); + } + } + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs b/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs new file mode 100644 index 000000000000..668c02485c41 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DelegateSupportedConditionAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Testing; + +namespace Microsoft.AspNetCore.Server.HttpSys.NonHelixTests +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class DelegateSupportedConditionAttribute : Attribute, ITestCondition + { + private readonly bool _isSupported; + public DelegateSupportedConditionAttribute(bool isSupported) => _isSupported = isSupported; + + public bool IsMet => HttpApi.SupportsDelegation == _isSupported; + + public string SkipReason => $"Http.Sys does {(_isSupported ? "not" : "")} support delegating requests"; + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs b/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs new file mode 100644 index 000000000000..55d6313ed5c0 --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/DummyApplication.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; + +namespace Microsoft.AspNetCore.Server.HttpSys +{ + internal class DummyApplication : IHttpApplication + { + private readonly RequestDelegate _requestDelegate; + + public DummyApplication() : this(context => Task.CompletedTask) { } + + public DummyApplication(RequestDelegate requestDelegate) + { + _requestDelegate = requestDelegate; + } + + public HttpContext CreateContext(IFeatureCollection contextFeatures) + { + return new DefaultHttpContext(contextFeatures); + } + + public void DisposeContext(HttpContext httpContext, Exception exception) + { + + } + + public async Task ProcessRequestAsync(HttpContext httpContext) + { + await _requestDelegate(httpContext); + } + } +} diff --git a/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj b/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj new file mode 100644 index 000000000000..58ca1a4d3baa --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Microsoft.AspNetCore.Server.HttpSys.NonHelixTests.csproj @@ -0,0 +1,30 @@ + + + + $(DefaultNetCoreTargetFramework) + HttpSys.NonHelixTests + true + + + + false + + + + + + + + + + + + 214124cd-d05b-4309-9af9-9caa44b2b74a + + + + + + + + diff --git a/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs b/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..c590df52068d --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Testing; +using Xunit; + +[assembly: OSSkipCondition(OperatingSystems.MacOSX)] +[assembly: OSSkipCondition(OperatingSystems.Linux)] +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs b/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs new file mode 100644 index 000000000000..301547ac25bb --- /dev/null +++ b/src/Servers/HttpSys/test/NonHelixTests/Utilities.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Server.HttpSys +{ + internal static class Utilities + { + internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15); + internal static readonly int WriteRetryLimit = 1000; + + // Minimum support for Windows 7 is assumed. + internal static readonly bool IsWin8orLater; + + static Utilities() + { + var win8Version = new Version(6, 2); + IsWin8orLater = (Environment.OSVersion.Version >= win8Version); + } + + internal static IServer CreateHttpServer(out string baseAddress, RequestDelegate app) + { + string root; + return CreateDynamicHttpServer(string.Empty, out root, out baseAddress, options => { }, app); + } + + internal static MessagePump CreatePump(ILoggerFactory loggerFactory = null) + => new MessagePump(Options.Create(new HttpSysOptions()), loggerFactory ?? new LoggerFactory(), new AuthenticationSchemeProvider(Options.Create(new AuthenticationOptions()))); + + internal static MessagePump CreatePump(Action configureOptions, ILoggerFactory loggerFactory = null) + { + var options = new HttpSysOptions(); + configureOptions(options); + return new MessagePump(Options.Create(options), loggerFactory ?? new LoggerFactory(), new AuthenticationSchemeProvider(Options.Create(new AuthenticationOptions()))); + } + + internal static IServer CreateDynamicHttpServer(string basePath, out string root, out string baseAddress, Action configureOptions, RequestDelegate app) + { + var prefix = UrlPrefix.Create("http", "localhost", "0", basePath); + + var server = CreatePump(configureOptions); + server.Features.Get().Addresses.Add(prefix.ToString()); + server.StartAsync(new DummyApplication(app), CancellationToken.None).Wait(); + + prefix = server.Listener.Options.UrlPrefixes.First(); // Has new port + root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; + baseAddress = prefix.ToString(); + + return server; + } + } +} diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj b/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj new file mode 100644 index 000000000000..e125cecc1622 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/DelegationSite.csproj @@ -0,0 +1,14 @@ + + + + $(DefaultNetCoreTargetFramework) + Exe + + + + + + + + + diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs b/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs new file mode 100644 index 000000000000..cf029c3beafb --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/Program.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DelegationSite; + +public static class Program +{ + public static void Main(string[] args) + { + var builder = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => + { + webHostBuilder.UseHttpSys(options => + { + options.RequestQueueName = Environment.GetEnvironmentVariable("queue"); + }) + .Configure(app => + { + app.Run(context => + { + return context.Response.WriteAsync("Hello from delegatee"); + }); + }); + }); + + using var host = builder.Build(); + host.Run(); + } +} + diff --git a/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json b/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json new file mode 100644 index 000000000000..454cdfd0b4c5 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/DelegationSite/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "DelegationSite": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000" + } + } +} diff --git a/src/Servers/HttpSys/test/testassets/Directory.Build.props b/src/Servers/HttpSys/test/testassets/Directory.Build.props new file mode 100644 index 000000000000..b49282fb6f94 --- /dev/null +++ b/src/Servers/HttpSys/test/testassets/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs index 60c8a2e11da0..2ecb2dac84cc 100644 --- a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs +++ b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs @@ -84,10 +84,10 @@ internal enum HTTP_DELEGATE_REQUEST_PROPERTY_ID : uint internal enum HTTP_FEATURE_ID { - HttpFeatureUnknown = 0, - HttpFeatureResponseTrailers = 1, - HttpFeatureApiTimings = 2, - HttpFeatureDelegateEx = 3, + HttpFeatureUnknown, + HttpFeatureResponseTrailers, + HttpFeatureApiTimings, + HttpFeatureDelegateEx, } [StructLayout(LayoutKind.Sequential, Pack = 4)] @@ -655,6 +655,7 @@ internal enum HTTP_FLAGS : uint HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001, HTTP_PROPERTY_FLAG_PRESENT = 0x00000001, HTTP_INITIALIZE_SERVER = 0x00000001, + HTTP_INITIALIZE_CONFIG = 0x00000002, HTTP_INITIALIZE_CBT = 0x00000004, HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040, HTTP_SEND_RESPONSE_FLAG_GOAWAY = 0x00000100, diff --git a/src/Shared/ParameterBindingMethodCache.cs b/src/Shared/ParameterBindingMethodCache.cs index 1d605195c74a..be7f48c77f2f 100644 --- a/src/Shared/ParameterBindingMethodCache.cs +++ b/src/Shared/ParameterBindingMethodCache.cs @@ -9,6 +9,8 @@ using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; +using System.Text; +using Microsoft.Extensions.Internal; #nullable enable @@ -104,9 +106,9 @@ public bool HasBindAsyncMethod(ParameterInfo parameter) => expression); } - methodInfo = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, new[] { typeof(string), typeof(IFormatProvider), type.MakeByRefType() }); + methodInfo = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, new[] { typeof(string), typeof(IFormatProvider), type.MakeByRefType() }); - if (methodInfo != null) + if (methodInfo is not null && methodInfo.ReturnType == typeof(bool)) { return (expression) => Expression.Call( methodInfo, @@ -115,13 +117,26 @@ public bool HasBindAsyncMethod(ParameterInfo parameter) => expression); } - methodInfo = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, new[] { typeof(string), type.MakeByRefType() }); + methodInfo = type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, new[] { typeof(string), type.MakeByRefType() }); - if (methodInfo != null) + if (methodInfo is not null && methodInfo.ReturnType == typeof(bool)) { return (expression) => Expression.Call(methodInfo, TempSourceStringExpr, expression); } + if (type.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy) is MethodInfo invalidMethod) + { + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"TryParse method found on {TypeNameHelper.GetTypeDisplayName(type, fullName: false)} with incorrect format. Must be a static method with format"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"bool TryParse(string, IFormatProvider, out {TypeNameHelper.GetTypeDisplayName(type, fullName: false)})"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"bool TryParse(string, out {TypeNameHelper.GetTypeDisplayName(type, fullName: false)})"); + stringBuilder.AppendLine("but found"); + stringBuilder.Append(invalidMethod.IsStatic ? "static " : "not-static "); + stringBuilder.Append(invalidMethod.ToString()); + + throw new InvalidOperationException(stringBuilder.ToString()); + } + return null; } @@ -134,11 +149,11 @@ public bool HasBindAsyncMethod(ParameterInfo parameter) => { var hasParameterInfo = true; // There should only be one BindAsync method with these parameters since C# does not allow overloading on return type. - var methodInfo = nonNullableParameterType.GetMethod("BindAsync", BindingFlags.Public | BindingFlags.Static, new[] { typeof(HttpContext), typeof(ParameterInfo) }); + var methodInfo = nonNullableParameterType.GetMethod("BindAsync", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, new[] { typeof(HttpContext), typeof(ParameterInfo) }); if (methodInfo is null) { hasParameterInfo = false; - methodInfo = nonNullableParameterType.GetMethod("BindAsync", BindingFlags.Public | BindingFlags.Static, new[] { typeof(HttpContext) }); + methodInfo = nonNullableParameterType.GetMethod("BindAsync", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, new[] { typeof(HttpContext) }); } // We're looking for a method with the following signatures: @@ -192,6 +207,21 @@ public bool HasBindAsyncMethod(ParameterInfo parameter) => } } + if (nonNullableParameterType.GetMethod("BindAsync", BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy) is MethodInfo invalidBindMethod) + { + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"BindAsync method found on {TypeNameHelper.GetTypeDisplayName(nonNullableParameterType, fullName: false)} with incorrect format. Must be a static method with format"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"ValueTask<{TypeNameHelper.GetTypeDisplayName(nonNullableParameterType, fullName: false)}> BindAsync(HttpContext context, ParameterInfo parameter)"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"ValueTask<{TypeNameHelper.GetTypeDisplayName(nonNullableParameterType, fullName: false)}> BindAsync(HttpContext context)"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"ValueTask<{TypeNameHelper.GetTypeDisplayName(nonNullableParameterType, fullName: false)}?> BindAsync(HttpContext context, ParameterInfo parameter)"); + stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"ValueTask<{TypeNameHelper.GetTypeDisplayName(nonNullableParameterType, fullName: false)}?> BindAsync(HttpContext context)"); + stringBuilder.AppendLine("but found"); + stringBuilder.Append(invalidBindMethod.IsStatic ? "static " : "not-static"); + stringBuilder.Append(invalidBindMethod.ToString()); + + throw new InvalidOperationException(stringBuilder.ToString()); + } + return (null, 0); }