From 632809c7f1b0b15af689ddea29a2db9a0a34f515 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 21 Apr 2021 07:27:30 -0700 Subject: [PATCH 01/27] Custom JS initializer sample --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 63 +++++++++++++++++-- .../Web.JS/src/Platform/BootConfig.ts | 4 +- .../src/Platform/WebAssemblyStartOptions.ts | 14 +++++ src/Components/Web.JS/tsconfig.json | 1 + 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index 13b6f2b44322..028f7eb5297a 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -80,11 +80,14 @@ async function boot(options?: Partial): Promise { ); }); - // Get the custom environment setting if defined - const environment = options?.environment; + const candidateOptions = options ?? {}; + + // Get the custom environment setting and blazorBootJson loader if defined + const environment = candidateOptions.environment; + const loadBlazorBootJson = candidateOptions.loadBlazorBootJson ?? BootConfigResult.initAsync; // Fetch the resources and prepare the Mono runtime - const bootConfigPromise = BootConfigResult.initAsync(environment); + const bootConfigPromise = loadBlazorBootJson(environment); // Leverage the time while we are loading boot.config.json from the network to discover any potentially registered component on // the document. @@ -110,7 +113,54 @@ async function boot(options?: Partial): Promise { } }; + type BeforeBlazorStartedCallback = (options: Partial | undefined, bootConfigResul: BootConfigResult) => Promise; + type AfterBlazorStartedCallback = () => Promise; + type BlazorInitializer = { beforeBlazorStarts: BeforeBlazorStartedCallback, afterBlazorStarted: AfterBlazorStartedCallback }; + const bootConfigResult = await bootConfigPromise; + const bootConfig = bootConfigResult.bootConfig; + const libraryInitializersTimeout = options?.libraryInitializersTimeout ?? 30; + const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; + if (bootConfigResult.bootConfig.libraryInitializers) { + const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; + try { + await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); + } catch (error) { + console.warn(`A library initializer produced an error: '${error}'`); + } + } + + function adjustPath(path: string): string { + // This is the same we do in JS interop with the import callback + const base = document.baseURI; + path = base.endsWith('/') ? `${base}${path}` : `${base}/${path}`; + return path; + } + + async function importAndInvokeInitializer(path: string, signature: string): Promise { + const adjustedPath = adjustPath(path); + const initializer = await import(/* webpackIgnore: true */ adjustedPath) as Partial; + if (initializer === undefined) { + return; + } + const { beforeBlazorStarts, afterBlazorStarted } = initializer; + if (afterBlazorStarted) { + afterBlazorStartedCallbacks.push(afterBlazorStarted); + } + if (beforeBlazorStarts) { + const timeout = libraryInitializersTimeout * 1000; + await Promise.race([ + beforeBlazorStarts(candidateOptions, bootConfigResult), + // By default we give each library 30 seconds to load and do whatever they have to do, before we continue loading. + new Promise((resolve) => + setTimeout(() => { + console.log(`Library '${path}' took longer than '${libraryInitializersTimeout}' to initialize.`); + resolve(); + }, + timeout))]); + } + } + const [resourceLoader] = await Promise.all([ WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), WebAssemblyConfigLoader.initAsync(bootConfigResult)]); @@ -122,7 +172,12 @@ async function boot(options?: Partial): Promise { } // Start up the application - platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly); + invokeBlazorStartedCallbacks(platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly)); + + async function invokeBlazorStartedCallbacks(applicationStarted: Promise) { + await applicationStarted; + await Promise.all(afterBlazorStartedCallbacks.map(c => c())); + } } function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any { diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 6a0079e5f164..e69a0ad28923 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -29,6 +29,8 @@ export interface BootJsonData { readonly cacheBootResources: boolean; readonly config: string[]; readonly icuDataMode: ICUDataMode; + readonly libraryInitializers?: ResourceList, + readonly extensions?: { [extensionName: string]: ResourceList } // These properties are tacked on, and not found in the boot.json file modifiableAssemblies: string | null; @@ -39,7 +41,7 @@ export interface ResourceGroups { readonly lazyAssembly: ResourceList; readonly pdb?: ResourceList; readonly runtime: ResourceList; - readonly satelliteResources?: { [cultureName: string] : ResourceList }; + readonly satelliteResources?: { [cultureName: string]: ResourceList }; } export type ResourceList = { [name: string]: string }; diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts b/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts index ffacdbb11f4d..8acdf7722159 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts @@ -1,3 +1,5 @@ +import { BootConfigResult, BootJsonData } from "./BootConfig"; + export interface WebAssemblyStartOptions { /** * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched @@ -10,11 +12,23 @@ export interface WebAssemblyStartOptions { */ loadBootResource(type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) : string | Promise | null | undefined; + /** + * Overrides the built-in way of loading blazor.boot.json + * @param environment The built-in environment setting on start. + */ + loadBlazorBootJson(environment?: string) : BootConfigResult; + /** * Override built-in environment setting on start. */ environment?: string; + /** + * The timeout in seconds before Blazor continues loading after invoking beforeBlazorStarts on a + * library initializer. + */ + libraryInitializersTimeout?: number; + /** * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 */ diff --git a/src/Components/Web.JS/tsconfig.json b/src/Components/Web.JS/tsconfig.json index a7813ded5916..e1595b625dff 100644 --- a/src/Components/Web.JS/tsconfig.json +++ b/src/Components/Web.JS/tsconfig.json @@ -6,6 +6,7 @@ "removeComments": false, "sourceMap": true, "target": "es2019", + "module": "es2020", "lib": ["es2019", "dom"], "strict": true } From be2fed89067178bedcd58bdd2f33080d690166b0 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 5 Aug 2021 04:16:54 -0700 Subject: [PATCH 02/27] Option 1 --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 15 +------ .../Web.JS/src/Platform/BootConfig.ts | 23 +++++++--- .../src/Platform/WebAssemblyResourceLoader.ts | 42 +++++++++++-------- .../src/Platform/WebAssemblyStartOptions.ts | 14 +------ 4 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index 028f7eb5297a..e8fb87ac6620 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -84,7 +84,6 @@ async function boot(options?: Partial): Promise { // Get the custom environment setting and blazorBootJson loader if defined const environment = candidateOptions.environment; - const loadBlazorBootJson = candidateOptions.loadBlazorBootJson ?? BootConfigResult.initAsync; // Fetch the resources and prepare the Mono runtime const bootConfigPromise = loadBlazorBootJson(environment); @@ -118,8 +117,6 @@ async function boot(options?: Partial): Promise { type BlazorInitializer = { beforeBlazorStarts: BeforeBlazorStartedCallback, afterBlazorStarted: AfterBlazorStartedCallback }; const bootConfigResult = await bootConfigPromise; - const bootConfig = bootConfigResult.bootConfig; - const libraryInitializersTimeout = options?.libraryInitializersTimeout ?? 30; const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; if (bootConfigResult.bootConfig.libraryInitializers) { const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; @@ -147,17 +144,9 @@ async function boot(options?: Partial): Promise { if (afterBlazorStarted) { afterBlazorStartedCallbacks.push(afterBlazorStarted); } + if (beforeBlazorStarts) { - const timeout = libraryInitializersTimeout * 1000; - await Promise.race([ - beforeBlazorStarts(candidateOptions, bootConfigResult), - // By default we give each library 30 seconds to load and do whatever they have to do, before we continue loading. - new Promise((resolve) => - setTimeout(() => { - console.log(`Library '${path}' took longer than '${libraryInitializersTimeout}' to initialize.`); - resolve(); - }, - timeout))]); + return beforeBlazorStarts(candidateOptions, bootConfigResult); } } diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index e69a0ad28923..22782f312046 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -1,13 +1,15 @@ +import { WebAssemblyBootResourceType } from "./WebAssemblyStartOptions"; + export class BootConfigResult { private constructor(public bootConfig: BootJsonData, public applicationEnvironment: string) { } - static async initAsync(environment?: string): Promise { - const bootConfigResponse = await fetch('_framework/blazor.boot.json', { - method: 'GET', - credentials: 'include', - cache: 'no-cache' - }); + static async initAsync(loadBootResource: (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined, environment?: string): Promise { + let loaderResponse = loadBootResource('manifest', 'blazor.boot.json', '_framework/blazor.boot.json', ''); + + const bootConfigResponse = loaderResponse instanceof Promise ? + await loaderResponse : + await defaultLoadBlazorBootJson; // While we can expect an ASP.NET Core hosted application to include the environment, other // hosts may not. Assume 'Production' in the absence of any specified value. @@ -17,8 +19,17 @@ export class BootConfigResult { return new BootConfigResult(bootConfig, applicationEnvironment); }; + + public static async defaultLoadBlazorBootJson(url: string) : Promise { + return fetch(url, { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + } } + // Keep in sync with bootJsonData from the BlazorWebAssemblySDK export interface BootJsonData { readonly entryAssembly: string; diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts index 399703c48de8..6a5921011982 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts @@ -1,5 +1,5 @@ import { toAbsoluteUri } from '../Services/NavigationManager'; -import { BootJsonData, ResourceList } from './BootConfig'; +import { BootConfigResult, BootJsonData, ResourceList } from './BootConfig'; import { WebAssemblyStartOptions, WebAssemblyBootResourceType } from './WebAssemblyStartOptions'; const networkFetchCacheMode = 'no-cache'; @@ -7,16 +7,20 @@ export class WebAssemblyResourceLoader { private usedCacheKeys: { [key: string]: boolean } = {}; private networkLoads: { [name: string]: LoadLogEntry } = {}; private cacheLoads: { [name: string]: LoadLogEntry } = {}; + private cacheIfUsed?: Cache; + private bootConfig?: BootJsonData; - static async initAsync(bootConfig: BootJsonData, startOptions: Partial): Promise { - const cache = await getCacheToUseIfEnabled(bootConfig); - return new WebAssemblyResourceLoader(bootConfig, cache, startOptions); + constructor(readonly startOptions: Partial) { } - constructor(readonly bootConfig: BootJsonData, readonly cacheIfUsed: Cache | null, readonly startOptions: Partial) { - } + async loadResources(resources: ResourceList, url: (name: string) => string, resourceType: WebAssemblyBootResourceType): Promise { + const bootConfigResult = await BootConfigResult.initAsync( + this.startOptions.loadBootResource ?? this.loadResourceWithoutCaching, + this.startOptions.environment); + + this.bootConfig = bootConfigResult.bootConfig; + this.cacheIfUsed = await getCacheToUseIfEnabled(bootConfigResult.bootConfig); - loadResources(resources: ResourceList, url: (name: string) => string, resourceType: WebAssemblyBootResourceType): LoadingResource[] { return Object.keys(resources) .map(name => this.loadResource(name, url(name), resources[name], resourceType)); } @@ -24,7 +28,7 @@ export class WebAssemblyResourceLoader { loadResource(name: string, url: string, contentHash: string, resourceType: WebAssemblyBootResourceType): LoadingResource { const response = this.cacheIfUsed ? this.loadResourceWithCaching(this.cacheIfUsed, name, url, contentHash, resourceType) - : this.loadResourceWithoutCaching(name, url, contentHash, resourceType); + : this.loadResourceWithoutCaching(resourceType, name, url, contentHash); return { name, url, response }; } @@ -40,7 +44,7 @@ export class WebAssemblyResourceLoader { return; } - const linkerDisabledWarning = this.bootConfig.linkerEnabled ? '%c' : '\n%cThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.'; + const linkerDisabledWarning = this.bootConfig!.linkerEnabled ? '%c' : '\n%cThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.'; console.groupCollapsed(`%cblazor%c Loaded ${toDataSizeString(totalResponseBytes)} resources${linkerDisabledWarning}`, 'background: purple; color: white; padding: 1px 3px; border-radius: 3px;', 'font-weight: bold;', 'font-weight: normal;'); if (cacheLoadsEntries.length) { @@ -100,13 +104,13 @@ export class WebAssemblyResourceLoader { return cachedResponse; } else { // It's not in the cache. Fetch from network. - const networkResponse = await this.loadResourceWithoutCaching(name, url, contentHash, resourceType); + const networkResponse = await this.loadResourceWithoutCaching(resourceType, name, url, contentHash); this.addToCacheAsync(cache, name, cacheKey, networkResponse); // Don't await - add to cache in background return networkResponse; } } - private loadResourceWithoutCaching(name: string, url: string, contentHash: string, resourceType: WebAssemblyBootResourceType): Promise { + private loadResourceWithoutCaching(resourceType: WebAssemblyBootResourceType, name: string, url: string, contentHash: string): Promise { // Allow developers to override how the resource is loaded if (this.startOptions.loadBootResource) { const customLoadResult = this.startOptions.loadBootResource(resourceType, name, url, contentHash); @@ -117,6 +121,8 @@ export class WebAssemblyResourceLoader { // They are supplying a custom URL, so use that with the default fetch behavior url = customLoadResult; } + }else if(resourceType === 'manifest'){ + return BootConfigResult.defaultLoadBlazorBootJson(url); } // Note that if cacheBootResources was explicitly disabled, we also bypass hash checking @@ -124,7 +130,7 @@ export class WebAssemblyResourceLoader { // there's anything they don't like about it. return fetch(url, { cache: networkFetchCacheMode, - integrity: this.bootConfig.cacheBootResources ? contentHash : undefined + integrity: this.bootConfig?.cacheBootResources ? contentHash : undefined }); } @@ -159,16 +165,16 @@ export class WebAssemblyResourceLoader { } } -async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise { +async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise { // caches will be undefined if we're running on an insecure origin (secure means https or localhost) if (!bootConfig.cacheBootResources || typeof caches === 'undefined') { - return null; + return undefined; } // cache integrity is compromised if the first request has been served over http (except localhost) // in this case, we want to disable caching and integrity validation if (window.isSecureContext === false) { - return null; + return undefined; } // Define a separate cache for each base href, so we're isolated from any other @@ -184,12 +190,12 @@ async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise | null | undefined; - /** - * Overrides the built-in way of loading blazor.boot.json - * @param environment The built-in environment setting on start. - */ - loadBlazorBootJson(environment?: string) : BootConfigResult; - /** * Override built-in environment setting on start. */ environment?: string; - /** - * The timeout in seconds before Blazor continues loading after invoking beforeBlazorStarts on a - * library initializer. - */ - libraryInitializersTimeout?: number; - /** * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 */ @@ -38,4 +26,4 @@ export interface WebAssemblyStartOptions { // This type doesn't have to align with anything in BootConfig. // Instead, this represents the public API through which certain aspects // of boot resource loading can be customized. -export type WebAssemblyBootResourceType = 'assembly' | 'pdb' | 'dotnetjs' | 'dotnetwasm' | 'globalization'; +export type WebAssemblyBootResourceType = 'assembly' | 'pdb' | 'dotnetjs' | 'dotnetwasm' | 'globalization' | 'manifest'; From 7aac021fca6d34ea7d8e2e113edd2ee8d0f8c457 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 5 Aug 2021 05:13:26 -0700 Subject: [PATCH 03/27] tmp --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 47 +++--------------- src/Components/Web.JS/src/GlobalExports.ts | 2 +- .../Web.JS/src/Platform/BootConfig.ts | 12 +++-- .../WebAssemblyJSInitializers.ts | 48 +++++++++++++++++++ .../src/Platform/WebAssemblyResourceLoader.ts | 10 ++-- 5 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index e8fb87ac6620..2ba03201dd7c 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -1,6 +1,6 @@ /* eslint-disable array-element-newline */ import { DotNet } from '@microsoft/dotnet-js-interop'; -import { Blazor } from './GlobalExports'; +import { Blazor, IBlazor } from './GlobalExports'; import * as Environment from './Environment'; import { byteArrayBeingTransferred, monoPlatform } from './Platform/Mono/MonoPlatform'; import { renderBatch, getRendererer, attachRootComponentToElement, attachRootComponentToLogicalElement } from './Rendering/Renderer'; @@ -8,12 +8,13 @@ import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRen import { shouldAutoStart } from './BootCommon'; import { WebAssemblyResourceLoader } from './Platform/WebAssemblyResourceLoader'; import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader'; -import { BootConfigResult } from './Platform/BootConfig'; +import { BootConfigResult, BootJsonData, BootJsonDataExtension } from './Platform/BootConfig'; import { Pointer, System_Array, System_Boolean, System_Byte, System_Int, System_Object, System_String } from './Platform/Platform'; import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions'; import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher'; import { discoverComponents, discoverPersistedState, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { setDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods'; +import { WebAssemblyJSInitializers } from './Platform/Initialization/WebAssemblyJSInitializers'; declare var Module: EmscriptenModule; let started = false; @@ -86,7 +87,7 @@ async function boot(options?: Partial): Promise { const environment = candidateOptions.environment; // Fetch the resources and prepare the Mono runtime - const bootConfigPromise = loadBlazorBootJson(environment); + const bootConfigPromise = BootConfigResult.initAsync(candidateOptions.loadBootResource, environment); // Leverage the time while we are loading boot.config.json from the network to discover any potentially registered component on // the document. @@ -112,43 +113,9 @@ async function boot(options?: Partial): Promise { } }; - type BeforeBlazorStartedCallback = (options: Partial | undefined, bootConfigResul: BootConfigResult) => Promise; - type AfterBlazorStartedCallback = () => Promise; - type BlazorInitializer = { beforeBlazorStarts: BeforeBlazorStartedCallback, afterBlazorStarted: AfterBlazorStartedCallback }; + const bootConfigResult : BootConfigResult = await bootConfigPromise; - const bootConfigResult = await bootConfigPromise; - const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; - if (bootConfigResult.bootConfig.libraryInitializers) { - const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; - try { - await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); - } catch (error) { - console.warn(`A library initializer produced an error: '${error}'`); - } - } - - function adjustPath(path: string): string { - // This is the same we do in JS interop with the import callback - const base = document.baseURI; - path = base.endsWith('/') ? `${base}${path}` : `${base}/${path}`; - return path; - } - - async function importAndInvokeInitializer(path: string, signature: string): Promise { - const adjustedPath = adjustPath(path); - const initializer = await import(/* webpackIgnore: true */ adjustedPath) as Partial; - if (initializer === undefined) { - return; - } - const { beforeBlazorStarts, afterBlazorStarted } = initializer; - if (afterBlazorStarted) { - afterBlazorStartedCallbacks.push(afterBlazorStarted); - } - - if (beforeBlazorStarts) { - return beforeBlazorStarts(candidateOptions, bootConfigResult); - } - } + await WebAssemblyJSInitializers.invokeInitializersAsync(bootConfigResult, candidateOptions); const [resourceLoader] = await Promise.all([ WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), @@ -165,7 +132,7 @@ async function boot(options?: Partial): Promise { async function invokeBlazorStartedCallbacks(applicationStarted: Promise) { await applicationStarted; - await Promise.all(afterBlazorStartedCallbacks.map(c => c())); + await Promise.all(afterBlazorStartedCallbacks.map(c => c(Blazor))); } } diff --git a/src/Components/Web.JS/src/GlobalExports.ts b/src/Components/Web.JS/src/GlobalExports.ts index 21ab215dda89..5a0adb48387a 100644 --- a/src/Components/Web.JS/src/GlobalExports.ts +++ b/src/Components/Web.JS/src/GlobalExports.ts @@ -13,7 +13,7 @@ import { getNextChunk, receiveDotNetDataStream } from './StreamingInterop'; import { RootComponentsFunctions } from './Rendering/JSRootComponents'; import { attachWebRendererInterop } from './Rendering/WebRendererInteropMethods'; -interface IBlazor { +export interface IBlazor { navigateTo: (uri: string, options: NavigationOptions) => void; registerCustomEventType: (eventName: string, options: EventTypeOptions) => void; diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 22782f312046..7c19312f0799 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -4,12 +4,14 @@ export class BootConfigResult { private constructor(public bootConfig: BootJsonData, public applicationEnvironment: string) { } - static async initAsync(loadBootResource: (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined, environment?: string): Promise { - let loaderResponse = loadBootResource('manifest', 'blazor.boot.json', '_framework/blazor.boot.json', ''); + static async initAsync(loadBootResource?: (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined, environment?: string): Promise { + let loaderResponse = loadBootResource !== undefined ? + loadBootResource('manifest', 'blazor.boot.json', '_framework/blazor.boot.json', '') : + this.defaultLoadBlazorBootJson('_framework/blazor.boot.json'); const bootConfigResponse = loaderResponse instanceof Promise ? await loaderResponse : - await defaultLoadBlazorBootJson; + await BootConfigResult.defaultLoadBlazorBootJson(loaderResponse ?? '_framework/blazor.boot.json'); // While we can expect an ASP.NET Core hosted application to include the environment, other // hosts may not. Assume 'Production' in the absence of any specified value. @@ -41,12 +43,14 @@ export interface BootJsonData { readonly config: string[]; readonly icuDataMode: ICUDataMode; readonly libraryInitializers?: ResourceList, - readonly extensions?: { [extensionName: string]: ResourceList } + readonly extensions?: BootJsonDataExtension // These properties are tacked on, and not found in the boot.json file modifiableAssemblies: string | null; } +export type BootJsonDataExtension = { [extensionName: string]: ResourceList }; + export interface ResourceGroups { readonly assembly: ResourceList; readonly lazyAssembly: ResourceList; diff --git a/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts b/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts new file mode 100644 index 000000000000..75375b9ca9c7 --- /dev/null +++ b/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts @@ -0,0 +1,48 @@ +import { IBlazor } from "../../GlobalExports"; +import { BootConfigResult, BootJsonDataExtension } from "../BootConfig"; +import { WebAssemblyStartOptions } from "../WebAssemblyStartOptions"; + +type BeforeBlazorStartedCallback = (options: Partial | undefined, bootConfigResul?: BootJsonDataExtension) => Promise; +type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; +type BlazorInitializer = { beforeBlazorStarts: BeforeBlazorStartedCallback, afterBlazorStarted: AfterBlazorStartedCallback }; + +export class WebAssemblyJSInitializers { + + static async invokeInitializersAsync(bootConfigResult: BootConfigResult, candidateOptions: Partial): Promise { + + const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; + if (bootConfigResult.bootConfig.libraryInitializers) { + const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; + try { + await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); + } catch (error) { + console.warn(`A library initializer produced an error: '${error}'`); + } + } + + return afterBlazorStartedCallbacks; + + function adjustPath(path: string): string { + // This is the same we do in JS interop with the import callback + const base = document.baseURI; + path = base.endsWith('/') ? `${base}${path}` : `${base}/${path}`; + return path; + } + + async function importAndInvokeInitializer(path: string, signature: string): Promise { + const adjustedPath = adjustPath(path); + const initializer = await import(/* webpackIgnore: true */ adjustedPath) as Partial; + if (initializer === undefined) { + return; + } + const { beforeBlazorStarts, afterBlazorStarted } = initializer; + if (afterBlazorStarted) { + afterBlazorStartedCallbacks.push(afterBlazorStarted); + } + + if (beforeBlazorStarts) { + return beforeBlazorStarts(candidateOptions, bootConfigResult.bootConfig.extensions); + } + } + } +} diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts index 6a5921011982..085604632982 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts @@ -8,9 +8,8 @@ export class WebAssemblyResourceLoader { private networkLoads: { [name: string]: LoadLogEntry } = {}; private cacheLoads: { [name: string]: LoadLogEntry } = {}; private cacheIfUsed?: Cache; - private bootConfig?: BootJsonData; - constructor(readonly startOptions: Partial) { + constructor(public bootConfig: BootJsonData, readonly startOptions: Partial) { } async loadResources(resources: ResourceList, url: (name: string) => string, resourceType: WebAssemblyBootResourceType): Promise { @@ -110,6 +109,10 @@ export class WebAssemblyResourceLoader { } } + private static loadBlazorBootJson(){ + + } + private loadResourceWithoutCaching(resourceType: WebAssemblyBootResourceType, name: string, url: string, contentHash: string): Promise { // Allow developers to override how the resource is loaded if (this.startOptions.loadBootResource) { @@ -121,7 +124,8 @@ export class WebAssemblyResourceLoader { // They are supplying a custom URL, so use that with the default fetch behavior url = customLoadResult; } - }else if(resourceType === 'manifest'){ + } + else if(resourceType === 'manifest'){ return BootConfigResult.defaultLoadBlazorBootJson(url); } From 7a4d14cb421c15796e112ed9db504b5b69afdd20 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 5 Aug 2021 05:14:40 -0700 Subject: [PATCH 04/27] undo changes on loader --- .../src/Platform/WebAssemblyResourceLoader.ts | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts index 085604632982..399703c48de8 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyResourceLoader.ts @@ -1,5 +1,5 @@ import { toAbsoluteUri } from '../Services/NavigationManager'; -import { BootConfigResult, BootJsonData, ResourceList } from './BootConfig'; +import { BootJsonData, ResourceList } from './BootConfig'; import { WebAssemblyStartOptions, WebAssemblyBootResourceType } from './WebAssemblyStartOptions'; const networkFetchCacheMode = 'no-cache'; @@ -7,19 +7,16 @@ export class WebAssemblyResourceLoader { private usedCacheKeys: { [key: string]: boolean } = {}; private networkLoads: { [name: string]: LoadLogEntry } = {}; private cacheLoads: { [name: string]: LoadLogEntry } = {}; - private cacheIfUsed?: Cache; - constructor(public bootConfig: BootJsonData, readonly startOptions: Partial) { + static async initAsync(bootConfig: BootJsonData, startOptions: Partial): Promise { + const cache = await getCacheToUseIfEnabled(bootConfig); + return new WebAssemblyResourceLoader(bootConfig, cache, startOptions); } - async loadResources(resources: ResourceList, url: (name: string) => string, resourceType: WebAssemblyBootResourceType): Promise { - const bootConfigResult = await BootConfigResult.initAsync( - this.startOptions.loadBootResource ?? this.loadResourceWithoutCaching, - this.startOptions.environment); - - this.bootConfig = bootConfigResult.bootConfig; - this.cacheIfUsed = await getCacheToUseIfEnabled(bootConfigResult.bootConfig); + constructor(readonly bootConfig: BootJsonData, readonly cacheIfUsed: Cache | null, readonly startOptions: Partial) { + } + loadResources(resources: ResourceList, url: (name: string) => string, resourceType: WebAssemblyBootResourceType): LoadingResource[] { return Object.keys(resources) .map(name => this.loadResource(name, url(name), resources[name], resourceType)); } @@ -27,7 +24,7 @@ export class WebAssemblyResourceLoader { loadResource(name: string, url: string, contentHash: string, resourceType: WebAssemblyBootResourceType): LoadingResource { const response = this.cacheIfUsed ? this.loadResourceWithCaching(this.cacheIfUsed, name, url, contentHash, resourceType) - : this.loadResourceWithoutCaching(resourceType, name, url, contentHash); + : this.loadResourceWithoutCaching(name, url, contentHash, resourceType); return { name, url, response }; } @@ -43,7 +40,7 @@ export class WebAssemblyResourceLoader { return; } - const linkerDisabledWarning = this.bootConfig!.linkerEnabled ? '%c' : '\n%cThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.'; + const linkerDisabledWarning = this.bootConfig.linkerEnabled ? '%c' : '\n%cThis application was built with linking (tree shaking) disabled. Published applications will be significantly smaller.'; console.groupCollapsed(`%cblazor%c Loaded ${toDataSizeString(totalResponseBytes)} resources${linkerDisabledWarning}`, 'background: purple; color: white; padding: 1px 3px; border-radius: 3px;', 'font-weight: bold;', 'font-weight: normal;'); if (cacheLoadsEntries.length) { @@ -103,17 +100,13 @@ export class WebAssemblyResourceLoader { return cachedResponse; } else { // It's not in the cache. Fetch from network. - const networkResponse = await this.loadResourceWithoutCaching(resourceType, name, url, contentHash); + const networkResponse = await this.loadResourceWithoutCaching(name, url, contentHash, resourceType); this.addToCacheAsync(cache, name, cacheKey, networkResponse); // Don't await - add to cache in background return networkResponse; } } - private static loadBlazorBootJson(){ - - } - - private loadResourceWithoutCaching(resourceType: WebAssemblyBootResourceType, name: string, url: string, contentHash: string): Promise { + private loadResourceWithoutCaching(name: string, url: string, contentHash: string, resourceType: WebAssemblyBootResourceType): Promise { // Allow developers to override how the resource is loaded if (this.startOptions.loadBootResource) { const customLoadResult = this.startOptions.loadBootResource(resourceType, name, url, contentHash); @@ -125,16 +118,13 @@ export class WebAssemblyResourceLoader { url = customLoadResult; } } - else if(resourceType === 'manifest'){ - return BootConfigResult.defaultLoadBlazorBootJson(url); - } // Note that if cacheBootResources was explicitly disabled, we also bypass hash checking // This is to give developers an easy opt-out from the entire caching/validation flow if // there's anything they don't like about it. return fetch(url, { cache: networkFetchCacheMode, - integrity: this.bootConfig?.cacheBootResources ? contentHash : undefined + integrity: this.bootConfig.cacheBootResources ? contentHash : undefined }); } @@ -169,16 +159,16 @@ export class WebAssemblyResourceLoader { } } -async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise { +async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise { // caches will be undefined if we're running on an insecure origin (secure means https or localhost) if (!bootConfig.cacheBootResources || typeof caches === 'undefined') { - return undefined; + return null; } // cache integrity is compromised if the first request has been served over http (except localhost) // in this case, we want to disable caching and integrity validation if (window.isSecureContext === false) { - return undefined; + return null; } // Define a separate cache for each base href, so we're isolated from any other @@ -194,12 +184,12 @@ async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise Date: Thu, 5 Aug 2021 05:28:30 -0700 Subject: [PATCH 05/27] Addresses feedback from Steve --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 10 +++++----- .../Initialization/WebAssemblyJSInitializers.ts | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index 2ba03201dd7c..d59a3c3f2c08 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -1,6 +1,6 @@ /* eslint-disable array-element-newline */ import { DotNet } from '@microsoft/dotnet-js-interop'; -import { Blazor, IBlazor } from './GlobalExports'; +import { Blazor } from './GlobalExports'; import * as Environment from './Environment'; import { byteArrayBeingTransferred, monoPlatform } from './Platform/Mono/MonoPlatform'; import { renderBatch, getRendererer, attachRootComponentToElement, attachRootComponentToLogicalElement } from './Rendering/Renderer'; @@ -113,9 +113,9 @@ async function boot(options?: Partial): Promise { } }; - const bootConfigResult : BootConfigResult = await bootConfigPromise; + const bootConfigResult: BootConfigResult = await bootConfigPromise; - await WebAssemblyJSInitializers.invokeInitializersAsync(bootConfigResult, candidateOptions); + var afterBlazorStartedCallbacks = await WebAssemblyJSInitializers.invokeInitializersAsync(bootConfigResult, candidateOptions); const [resourceLoader] = await Promise.all([ WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), @@ -128,9 +128,9 @@ async function boot(options?: Partial): Promise { } // Start up the application - invokeBlazorStartedCallbacks(platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly)); + invokeBlazorStartedCallbacks(platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly), afterBlazorStartedCallbacks); - async function invokeBlazorStartedCallbacks(applicationStarted: Promise) { + async function invokeBlazorStartedCallbacks(applicationStarted: Promise, afterBlazorStartedCallbacks: AfterBlazorStartedCallback[]) { await applicationStarted; await Promise.all(afterBlazorStartedCallbacks.map(c => c(Blazor))); } diff --git a/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts b/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts index 75375b9ca9c7..e00e1f0a74c3 100644 --- a/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts +++ b/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts @@ -3,8 +3,8 @@ import { BootConfigResult, BootJsonDataExtension } from "../BootConfig"; import { WebAssemblyStartOptions } from "../WebAssemblyStartOptions"; type BeforeBlazorStartedCallback = (options: Partial | undefined, bootConfigResul?: BootJsonDataExtension) => Promise; -type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; -type BlazorInitializer = { beforeBlazorStarts: BeforeBlazorStartedCallback, afterBlazorStarted: AfterBlazorStartedCallback }; +export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; +type BlazorInitializer = { beforeStart: BeforeBlazorStartedCallback, afterStarted: AfterBlazorStartedCallback }; export class WebAssemblyJSInitializers { @@ -35,13 +35,13 @@ export class WebAssemblyJSInitializers { if (initializer === undefined) { return; } - const { beforeBlazorStarts, afterBlazorStarted } = initializer; - if (afterBlazorStarted) { - afterBlazorStartedCallbacks.push(afterBlazorStarted); + const { beforeStart: beforeStart, afterStarted: afterStarted } = initializer; + if (afterStarted) { + afterBlazorStartedCallbacks.push(afterStarted); } - if (beforeBlazorStarts) { - return beforeBlazorStarts(candidateOptions, bootConfigResult.bootConfig.extensions); + if (beforeStart) { + return beforeStart(candidateOptions, bootConfigResult.bootConfig.extensions); } } } From b04e6510076506bbdb52d02feb80a308c14bf732 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 5 Aug 2021 05:40:25 -0700 Subject: [PATCH 06/27] Cleanup --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 9 +++++++-- ...blyJSInitializers.ts => JSInitializers.ts} | 19 +++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) rename src/Components/Web.JS/src/{Platform/Initialization/WebAssemblyJSInitializers.ts => JSInitializers.ts} (63%) diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index d59a3c3f2c08..5f0ab6c28c67 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -114,8 +114,13 @@ async function boot(options?: Partial): Promise { }; const bootConfigResult: BootConfigResult = await bootConfigPromise; - - var afterBlazorStartedCallbacks = await WebAssemblyJSInitializers.invokeInitializersAsync(bootConfigResult, candidateOptions); + let afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; + if (bootConfigResult.bootConfig.libraryInitializers) { + const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; + afterBlazorStartedCallbacks = await WebAssemblyJSInitializers.invokeInitializersAsync( + Object.keys(initializerFiles), + [candidateOptions, bootConfigResult.bootConfig.extensions]); + } const [resourceLoader] = await Promise.all([ WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), diff --git a/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts b/src/Components/Web.JS/src/JSInitializers.ts similarity index 63% rename from src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts rename to src/Components/Web.JS/src/JSInitializers.ts index e00e1f0a74c3..1682a4089de8 100644 --- a/src/Components/Web.JS/src/Platform/Initialization/WebAssemblyJSInitializers.ts +++ b/src/Components/Web.JS/src/JSInitializers.ts @@ -2,22 +2,21 @@ import { IBlazor } from "../../GlobalExports"; import { BootConfigResult, BootJsonDataExtension } from "../BootConfig"; import { WebAssemblyStartOptions } from "../WebAssemblyStartOptions"; -type BeforeBlazorStartedCallback = (options: Partial | undefined, bootConfigResul?: BootJsonDataExtension) => Promise; +type BeforeBlazorStartedCallback = (...args: unknown[]) => Promise; export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; type BlazorInitializer = { beforeStart: BeforeBlazorStartedCallback, afterStarted: AfterBlazorStartedCallback }; export class WebAssemblyJSInitializers { - static async invokeInitializersAsync(bootConfigResult: BootConfigResult, candidateOptions: Partial): Promise { + static async invokeInitializersAsync( + initializerFiles: string[], + initializerArguments: unknown[]): Promise { const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; - if (bootConfigResult.bootConfig.libraryInitializers) { - const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; - try { - await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); - } catch (error) { - console.warn(`A library initializer produced an error: '${error}'`); - } + try { + await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); + } catch (error) { + console.warn(`A library initializer produced an error: '${error}'`); } return afterBlazorStartedCallbacks; @@ -41,7 +40,7 @@ export class WebAssemblyJSInitializers { } if (beforeStart) { - return beforeStart(candidateOptions, bootConfigResult.bootConfig.extensions); + return beforeStart(...initializerArguments); } } } From 013195f183a084ff6c996b1010ed2b9e0321f7a1 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 5 Aug 2021 07:05:04 -0700 Subject: [PATCH 07/27] Cleanups and Blazor server implementation --- .../ComponentEndpointConventionBuilder.cs | 5 ++- ...ComponentEndpointRouteBuilderExtensions.cs | 10 +++++- ...rcuitJavaScriptInitializationMiddleware.cs | 24 ++++++++++++++ src/Components/Server/src/CircuitOptions.cs | 9 +++-- ...ionsJavaScriptInitializersConfiguration.cs | 33 +++++++++++++++++++ src/Components/Server/src/ComponentHub.cs | 1 + .../ComponentServiceCollectionExtensions.cs | 1 + .../Server/src/PublicAPI.Unshipped.txt | 1 + src/Components/Web.JS/src/Boot.Server.ts | 13 +++++++- src/Components/Web.JS/src/Boot.WebAssembly.ts | 6 ++-- src/Components/Web.JS/src/JSInitializers.ts | 8 ++--- 11 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs create mode 100644 src/Components/Server/src/Circuits/CircuitOptionsJavaScriptInitializersConfiguration.cs diff --git a/src/Components/Server/src/Builder/ComponentEndpointConventionBuilder.cs b/src/Components/Server/src/Builder/ComponentEndpointConventionBuilder.cs index 66c8c260e8c8..e8f40cb25a75 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointConventionBuilder.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointConventionBuilder.cs @@ -12,11 +12,13 @@ public sealed class ComponentEndpointConventionBuilder : IHubEndpointConventionB { private readonly IEndpointConventionBuilder _hubEndpoint; private readonly IEndpointConventionBuilder _disconnectEndpoint; + private readonly IEndpointConventionBuilder _jsInitializersEndpoint; - internal ComponentEndpointConventionBuilder(IEndpointConventionBuilder hubEndpoint, IEndpointConventionBuilder disconnectEndpoint) + internal ComponentEndpointConventionBuilder(IEndpointConventionBuilder hubEndpoint, IEndpointConventionBuilder disconnectEndpoint, IEndpointConventionBuilder jsInitializersEndpoint) { _hubEndpoint = hubEndpoint; _disconnectEndpoint = disconnectEndpoint; + _jsInitializersEndpoint = jsInitializersEndpoint; } /// @@ -27,6 +29,7 @@ public void Add(Action convention) { _hubEndpoint.Add(convention); _disconnectEndpoint.Add(convention); + _jsInitializersEndpoint.Add(convention); } } } diff --git a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs index 2b021d4aa08b..aebe39281f04 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs @@ -3,9 +3,12 @@ using System; using Microsoft.AspNetCore.Components.Server; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace Microsoft.AspNetCore.Builder { @@ -110,7 +113,12 @@ public static ComponentEndpointConventionBuilder MapBlazorHub( endpoints.CreateApplicationBuilder().UseMiddleware().Build()) .WithDisplayName("Blazor disconnect"); - return new ComponentEndpointConventionBuilder(hubEndpoint, disconnectEndpoint); + var jsInitializersEndpoint = endpoints.Map( + (path.EndsWith('/') ? path : path + "/") + "initializers/", + endpoints.CreateApplicationBuilder().UseMiddleware().Build()) + .WithDisplayName("Blazor initializers"); + + return new ComponentEndpointConventionBuilder(hubEndpoint, disconnectEndpoint, jsInitializersEndpoint); } } } diff --git a/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs b/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs new file mode 100644 index 000000000000..673a67a124d9 --- /dev/null +++ b/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs @@ -0,0 +1,24 @@ +// 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.Components.Server; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Builder +{ + internal class CircuitJavaScriptInitializationMiddleware + { + private readonly IList _initializers; + + public CircuitJavaScriptInitializationMiddleware(IOptions options) + { + _initializers = options.Value.JavaScriptInitializers; + } + + public async Task InvokeAsync(HttpContext context) + { + await context.Response.WriteAsJsonAsync(_initializers); + } + } +} diff --git a/src/Components/Server/src/CircuitOptions.cs b/src/Components/Server/src/CircuitOptions.cs index 1d6323e53f38..2a689fff2265 100644 --- a/src/Components/Server/src/CircuitOptions.cs +++ b/src/Components/Server/src/CircuitOptions.cs @@ -1,8 +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 Microsoft.AspNetCore.Components.Web; +using Microsoft.Extensions.Hosting; namespace Microsoft.AspNetCore.Components.Server { @@ -82,5 +81,11 @@ public sealed class CircuitOptions /// Gets options for root components within the circuit. /// public CircuitRootComponentOptions RootComponents { get; } = new CircuitRootComponentOptions(); + + /// + /// Gets the list of JavaScript initializers used by Blazor server. By default this list gets populated by + /// the .modules.json manifest file in the web root if present. + /// + public IList JavaScriptInitializers { get; } = new List(); } } diff --git a/src/Components/Server/src/Circuits/CircuitOptionsJavaScriptInitializersConfiguration.cs b/src/Components/Server/src/Circuits/CircuitOptionsJavaScriptInitializersConfiguration.cs new file mode 100644 index 000000000000..e1e70427b9a6 --- /dev/null +++ b/src/Components/Server/src/Circuits/CircuitOptionsJavaScriptInitializersConfiguration.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.Json; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Components.Server.Circuits +{ + internal class CircuitOptionsJavaScriptInitializersConfiguration : IConfigureOptions + { + private readonly IWebHostEnvironment _environment; + + public CircuitOptionsJavaScriptInitializersConfiguration(IWebHostEnvironment environment) + { + _environment = environment; + } + + public void Configure(CircuitOptions options) + { + var file = _environment.WebRootFileProvider.GetFileInfo($"{_environment.ApplicationName}.modules.json"); + if (file.Exists) + { + var initializers = JsonSerializer.Deserialize(file.CreateReadStream()); + for (var i = 0; i < initializers.Length; i++) + { + var initializer = initializers[i]; + options.JavaScriptInitializers.Add(initializer); + } + } + } + } +} diff --git a/src/Components/Server/src/ComponentHub.cs b/src/Components/Server/src/ComponentHub.cs index bb802199a7ab..256b3f2e787a 100644 --- a/src/Components/Server/src/ComponentHub.cs +++ b/src/Components/Server/src/ComponentHub.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Components.Server { diff --git a/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs b/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs index 3a7cd4ce8426..43bd3c85c997 100644 --- a/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs +++ b/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs @@ -83,6 +83,7 @@ public static IServerSideBlazorBuilder AddServerSideBlazor(this IServiceCollecti services.AddScoped(); services.TryAddEnumerable(ServiceDescriptor.Singleton, CircuitOptionsJSInteropDetailedErrorsConfiguration>()); + services.TryAddEnumerable(ServiceDescriptor.Singleton, CircuitOptionsJavaScriptInitializersConfiguration>()); if (configure != null) { diff --git a/src/Components/Server/src/PublicAPI.Unshipped.txt b/src/Components/Server/src/PublicAPI.Unshipped.txt index 172a7b628066..d1622d7741be 100644 --- a/src/Components/Server/src/PublicAPI.Unshipped.txt +++ b/src/Components/Server/src/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable +Microsoft.AspNetCore.Components.Server.CircuitOptions.JavaScriptInitializers.get -> System.Collections.Generic.IList! Microsoft.AspNetCore.Components.Server.CircuitOptions.RootComponents.get -> Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions! Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions.CircuitRootComponentOptions() -> void diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index 5e23268a67da..d3e5458bc513 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -13,6 +13,7 @@ import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnect import { attachRootComponentToLogicalElement } from './Rendering/Renderer'; import { discoverComponents, discoverPersistedState, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { sendJSDataStream } from './Platform/Circuits/CircuitStreamingInterop'; +import { JSInitializers } from './JSInitializers'; let renderingFailed = false; let started = false; @@ -25,6 +26,15 @@ async function boot(userOptions?: Partial): Promise { // Establish options to be used const options = resolveOptions(userOptions); + const jsInitializersResponse = await fetch('_blazor/initializers', { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + + const initializers: string[] = await jsInitializersResponse.json(); + const afterStartedCallbacks = await JSInitializers.invokeInitializersAsync(initializers, [options]); + const logger = new ConsoleLogger(options.logLevel); Blazor.defaultReconnectionHandler = new DefaultReconnectionHandler(logger); @@ -35,7 +45,6 @@ async function boot(userOptions?: Partial): Promise { const appState = discoverPersistedState(document); const circuit = new CircuitDescriptor(components, appState || ''); - const initialConnection = await initializeConnection(options, logger, circuit); const circuitStarted = await circuit.startCircuit(initialConnection); if (!circuitStarted) { @@ -57,6 +66,8 @@ async function boot(userOptions?: Partial): Promise { options.reconnectionHandler!.onConnectionUp(); + Promise.all(afterStartedCallbacks.map(c => c(Blazor))); + return true; }; diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index 5f0ab6c28c67..9dbbeb7e6e67 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -8,13 +8,13 @@ import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRen import { shouldAutoStart } from './BootCommon'; import { WebAssemblyResourceLoader } from './Platform/WebAssemblyResourceLoader'; import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader'; -import { BootConfigResult, BootJsonData, BootJsonDataExtension } from './Platform/BootConfig'; +import { BootConfigResult } from './Platform/BootConfig'; import { Pointer, System_Array, System_Boolean, System_Byte, System_Int, System_Object, System_String } from './Platform/Platform'; import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions'; import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher'; import { discoverComponents, discoverPersistedState, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { setDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods'; -import { WebAssemblyJSInitializers } from './Platform/Initialization/WebAssemblyJSInitializers'; +import { AfterBlazorStartedCallback, JSInitializers } from './JSInitializers'; declare var Module: EmscriptenModule; let started = false; @@ -117,7 +117,7 @@ async function boot(options?: Partial): Promise { let afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; if (bootConfigResult.bootConfig.libraryInitializers) { const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; - afterBlazorStartedCallbacks = await WebAssemblyJSInitializers.invokeInitializersAsync( + afterBlazorStartedCallbacks = await JSInitializers.invokeInitializersAsync( Object.keys(initializerFiles), [candidateOptions, bootConfigResult.bootConfig.extensions]); } diff --git a/src/Components/Web.JS/src/JSInitializers.ts b/src/Components/Web.JS/src/JSInitializers.ts index 1682a4089de8..05b05b8154af 100644 --- a/src/Components/Web.JS/src/JSInitializers.ts +++ b/src/Components/Web.JS/src/JSInitializers.ts @@ -1,12 +1,12 @@ -import { IBlazor } from "../../GlobalExports"; -import { BootConfigResult, BootJsonDataExtension } from "../BootConfig"; -import { WebAssemblyStartOptions } from "../WebAssemblyStartOptions"; +import { IBlazor } from "./GlobalExports"; +import { BootConfigResult, BootJsonDataExtension } from "./Platform/BootConfig"; +import { WebAssemblyStartOptions } from "./Platform/WebAssemblyStartOptions"; type BeforeBlazorStartedCallback = (...args: unknown[]) => Promise; export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; type BlazorInitializer = { beforeStart: BeforeBlazorStartedCallback, afterStarted: AfterBlazorStartedCallback }; -export class WebAssemblyJSInitializers { +export class JSInitializers { static async invokeInitializersAsync( initializerFiles: string[], From 2c596709faf23495c3fd0a8f08348d5a3e9d120b Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 6 Aug 2021 12:03:40 -0700 Subject: [PATCH 08/27] Webassembly fixes --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 24 +++++++-------- src/Components/Web.JS/src/JSInitializers.ts | 30 +++++++++++-------- .../Web.JS/src/Platform/BootConfig.ts | 4 +-- ...dBlazorWebassemblyApp.Client.lib.module.js | 7 +++++ .../Server/Properties/launchSettings.json | 16 +++++----- 5 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index 9dbbeb7e6e67..fe5eb59c0d9e 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -14,7 +14,7 @@ import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions'; import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher'; import { discoverComponents, discoverPersistedState, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { setDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods'; -import { AfterBlazorStartedCallback, JSInitializers } from './JSInitializers'; +import { AfterBlazorStartedCallback, JSInitializer } from './JSInitializers'; declare var Module: EmscriptenModule; let started = false; @@ -114,12 +114,12 @@ async function boot(options?: Partial): Promise { }; const bootConfigResult: BootConfigResult = await bootConfigPromise; - let afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; - if (bootConfigResult.bootConfig.libraryInitializers) { - const initializerFiles = bootConfigResult.bootConfig.libraryInitializers; - afterBlazorStartedCallbacks = await JSInitializers.invokeInitializersAsync( - Object.keys(initializerFiles), - [candidateOptions, bootConfigResult.bootConfig.extensions]); + const initializers = bootConfigResult.bootConfig.resources.libraryInitializers; + const jsInitializer = new JSInitializer(); + if (initializers) { + await jsInitializer.importInitializersAsync( + Object.keys(initializers), + [candidateOptions, bootConfigResult.bootConfig.resources.extensions]); } const [resourceLoader] = await Promise.all([ @@ -133,12 +133,10 @@ async function boot(options?: Partial): Promise { } // Start up the application - invokeBlazorStartedCallbacks(platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly), afterBlazorStartedCallbacks); - - async function invokeBlazorStartedCallbacks(applicationStarted: Promise, afterBlazorStartedCallbacks: AfterBlazorStartedCallback[]) { - await applicationStarted; - await Promise.all(afterBlazorStartedCallbacks.map(c => c(Blazor))); - } + platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly); + // At this point .NET has been initialized (and has yielded), we can't await the promise becasue it will + // only end when the app finishes running + jsInitializer.invokeAfterStartedCallbacks(Blazor); } function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any { diff --git a/src/Components/Web.JS/src/JSInitializers.ts b/src/Components/Web.JS/src/JSInitializers.ts index 05b05b8154af..5a1de229976c 100644 --- a/src/Components/Web.JS/src/JSInitializers.ts +++ b/src/Components/Web.JS/src/JSInitializers.ts @@ -1,26 +1,22 @@ import { IBlazor } from "./GlobalExports"; -import { BootConfigResult, BootJsonDataExtension } from "./Platform/BootConfig"; -import { WebAssemblyStartOptions } from "./Platform/WebAssemblyStartOptions"; type BeforeBlazorStartedCallback = (...args: unknown[]) => Promise; export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; type BlazorInitializer = { beforeStart: BeforeBlazorStartedCallback, afterStarted: AfterBlazorStartedCallback }; -export class JSInitializers { +export class JSInitializer { + private afterStartedCallbacks: AfterBlazorStartedCallback[] = []; - static async invokeInitializersAsync( + async importInitializersAsync( initializerFiles: string[], - initializerArguments: unknown[]): Promise { + initializerArguments: unknown[]): Promise { - const afterBlazorStartedCallbacks: AfterBlazorStartedCallback[] = []; try { - await Promise.all(Object.entries(initializerFiles).map(f => importAndInvokeInitializer(...f))); + await Promise.all(initializerFiles.map(f => importAndInvokeInitializer(this, f))); } catch (error) { - console.warn(`A library initializer produced an error: '${error}'`); + console.warn(`A library initializer produced an error before starting: '${error}'`); } - return afterBlazorStartedCallbacks; - function adjustPath(path: string): string { // This is the same we do in JS interop with the import callback const base = document.baseURI; @@ -28,7 +24,7 @@ export class JSInitializers { return path; } - async function importAndInvokeInitializer(path: string, signature: string): Promise { + async function importAndInvokeInitializer(jsInitializer: JSInitializer, path: string): Promise { const adjustedPath = adjustPath(path); const initializer = await import(/* webpackIgnore: true */ adjustedPath) as Partial; if (initializer === undefined) { @@ -36,7 +32,7 @@ export class JSInitializers { } const { beforeStart: beforeStart, afterStarted: afterStarted } = initializer; if (afterStarted) { - afterBlazorStartedCallbacks.push(afterStarted); + jsInitializer.afterStartedCallbacks.push(afterStarted); } if (beforeStart) { @@ -44,4 +40,14 @@ export class JSInitializers { } } } + + async invokeAfterStartedCallbacks(blazor: IBlazor) { + await Promise.all(this.afterStartedCallbacks.map(async callback => { + try { + await callback(blazor); + } catch (error) { + console.warn(`A library initializer produced an error after starting: '${error}'`); + } + })); + } } diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 7c19312f0799..77f1c52a85f8 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -42,8 +42,6 @@ export interface BootJsonData { readonly cacheBootResources: boolean; readonly config: string[]; readonly icuDataMode: ICUDataMode; - readonly libraryInitializers?: ResourceList, - readonly extensions?: BootJsonDataExtension // These properties are tacked on, and not found in the boot.json file modifiableAssemblies: string | null; @@ -57,6 +55,8 @@ export interface ResourceGroups { readonly pdb?: ResourceList; readonly runtime: ResourceList; readonly satelliteResources?: { [cultureName: string]: ResourceList }; + readonly libraryInitializers?: ResourceList, + readonly extensions?: BootJsonDataExtension } export type ResourceList = { [name: string]: string }; diff --git a/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js b/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js new file mode 100644 index 000000000000..1dba3c8e5195 --- /dev/null +++ b/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js @@ -0,0 +1,7 @@ +export function beforeStart(serverOptions) { + console.log('starting!'); +} + +export function afterStarted(blazor) { + console.log('started!'); +} diff --git a/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Server/Properties/launchSettings.json b/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Server/Properties/launchSettings.json index 6ef6d4adc398..4b10fb01378b 100644 --- a/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Server/Properties/launchSettings.json +++ b/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Server/Properties/launchSettings.json @@ -8,13 +8,6 @@ } }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "HostedBlazorWebassemblyApp.Server": { "commandName": "Project", "launchBrowser": true, @@ -22,6 +15,13 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "https://localhost:5001;http://localhost:5000" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } } } -} \ No newline at end of file +} From 299ee4dd3a8d0c4951bce93be4df7892963f6570 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 6 Aug 2021 12:07:25 -0700 Subject: [PATCH 09/27] Add blazor server support --- .../wwwroot/BlazorServerApp.lib.module.js | 7 +++++++ .../src/CircuitJavaScriptInitializationMiddleware.cs | 4 +++- src/Components/Web.JS/src/Boot.Server.ts | 9 +++++---- 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js diff --git a/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js b/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js new file mode 100644 index 000000000000..1dba3c8e5195 --- /dev/null +++ b/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js @@ -0,0 +1,7 @@ +export function beforeStart(serverOptions) { + console.log('starting!'); +} + +export function afterStarted(blazor) { + console.log('started!'); +} diff --git a/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs b/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs index 673a67a124d9..845f65308eac 100644 --- a/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs +++ b/src/Components/Server/src/CircuitJavaScriptInitializationMiddleware.cs @@ -11,7 +11,9 @@ internal class CircuitJavaScriptInitializationMiddleware { private readonly IList _initializers; - public CircuitJavaScriptInitializationMiddleware(IOptions options) + // We don't need the request delegate for anything, however we need to inject it to satisfy the middleware + // contract. + public CircuitJavaScriptInitializationMiddleware(IOptions options, RequestDelegate _) { _initializers = options.Value.JavaScriptInitializers; } diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index d3e5458bc513..2687b6de225f 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -13,7 +13,7 @@ import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnect import { attachRootComponentToLogicalElement } from './Rendering/Renderer'; import { discoverComponents, discoverPersistedState, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { sendJSDataStream } from './Platform/Circuits/CircuitStreamingInterop'; -import { JSInitializers } from './JSInitializers'; +import { JSInitializer } from './JSInitializers'; let renderingFailed = false; let started = false; @@ -33,7 +33,8 @@ async function boot(userOptions?: Partial): Promise { }); const initializers: string[] = await jsInitializersResponse.json(); - const afterStartedCallbacks = await JSInitializers.invokeInitializersAsync(initializers, [options]); + const jsInitializer = new JSInitializer(); + await jsInitializer.importInitializersAsync(initializers, [options]); const logger = new ConsoleLogger(options.logLevel); Blazor.defaultReconnectionHandler = new DefaultReconnectionHandler(logger); @@ -66,8 +67,6 @@ async function boot(userOptions?: Partial): Promise { options.reconnectionHandler!.onConnectionUp(); - Promise.all(afterStartedCallbacks.map(c => c(Blazor))); - return true; }; @@ -88,6 +87,8 @@ async function boot(userOptions?: Partial): Promise { Blazor.reconnect = reconnect; logger.log(LogLevel.Information, 'Blazor server-side application started.'); + + jsInitializer.invokeAfterStartedCallbacks(Blazor); } async function initializeConnection(options: CircuitStartOptions, logger: Logger, circuit: CircuitDescriptor): Promise { From 583b0f865c7d8c6e09cc9884a8cb061b0cfec37b Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 6 Aug 2021 12:08:43 -0700 Subject: [PATCH 10/27] Partial cleanup of the static web assets implementation --- .../WebView/src/StaticWebAssetsLoader.cs | 292 ------------------ .../src/Microsoft.AspNetCore.Hosting.csproj | 1 + .../StaticWebAssets/StaticWebAssetsLoader.cs | 63 +--- .../StaticWebAssets/StaticWebAssetsReader.cs | 75 ----- ...anifestStaticWebAssetsFileProviderTests.cs | 5 +- .../StaticWebAssetsFileProviderTests.cs | 210 ------------- .../StaticWebAssetsLoaderTests.cs | 116 ------- .../StaticWebAssetsFileProvider.cs | 149 +-------- 8 files changed, 22 insertions(+), 889 deletions(-) delete mode 100644 src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs delete mode 100644 src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsReader.cs delete mode 100644 src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsFileProviderTests.cs delete mode 100644 src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsLoaderTests.cs rename src/{Hosting/Hosting/src => Shared}/StaticWebAssets/StaticWebAssetsFileProvider.cs (74%) diff --git a/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs b/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs deleted file mode 100644 index f1202ba0a9b6..000000000000 --- a/src/Components/WebView/WebView/src/StaticWebAssetsLoader.cs +++ /dev/null @@ -1,292 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Xml.Linq; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Primitives; - -namespace Microsoft.AspNetCore.Components.WebView -{ - internal class StaticWebAssetsLoader - { - internal const string StaticWebAssetsManifestName = "Microsoft.AspNetCore.StaticWebAssets.xml"; - - internal static IFileProvider UseStaticWebAssets(IFileProvider systemProvider) - { - using var manifest = GetManifestStream(); - if (manifest != null) - { - return UseStaticWebAssetsCore(systemProvider, manifest); - } - else - { - return systemProvider; - } - - static Stream? GetManifestStream() - { - try - { - var filePath = ResolveRelativeToAssembly(); - - if (filePath != null && File.Exists(filePath)) - { - return File.OpenRead(filePath); - } - else - { - // A missing manifest might simply mean that the feature is not enabled, so we simply - // return early. Misconfigurations will be uncommon given that the entire process is automated - // at build time. - return null; - } - } - catch - { - return null; - } - } - } - - internal static IFileProvider UseStaticWebAssetsCore(IFileProvider systemProvider, Stream manifest) - { - var webRootFileProvider = systemProvider; - - var additionalFiles = StaticWebAssetsReader.Parse(manifest) - .Select(cr => new StaticWebAssetsFileProvider(cr.BasePath, cr.Path)) - .OfType() // Upcast so we can insert on the resulting list. - .ToList(); - - if (additionalFiles.Count == 0) - { - return systemProvider; - } - else - { - additionalFiles.Insert(0, webRootFileProvider); - return new CompositeFileProvider(additionalFiles); - } - } - - private static string? ResolveRelativeToAssembly() - { - var assembly = Assembly.GetEntryAssembly(); - if (string.IsNullOrEmpty(assembly?.Location)) - { - return null; - } - - var name = Path.GetFileNameWithoutExtension(assembly.Location); - - return Path.Combine(Path.GetDirectoryName(assembly.Location)!, $"{name}.StaticWebAssets.xml"); - } - - internal static class StaticWebAssetsReader - { - private const string ManifestRootElementName = "StaticWebAssets"; - private const string VersionAttributeName = "Version"; - private const string ContentRootElementName = "ContentRoot"; - - internal static IEnumerable Parse(Stream manifest) - { - var document = XDocument.Load(manifest); - if (!string.Equals(document.Root!.Name.LocalName, ManifestRootElementName, StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidOperationException($"Invalid manifest format. Manifest root must be '{ManifestRootElementName}'"); - } - - var version = document.Root.Attribute(VersionAttributeName); - if (version == null) - { - throw new InvalidOperationException($"Invalid manifest format. Manifest root element must contain a version '{VersionAttributeName}' attribute"); - } - - if (version.Value != "1.0") - { - throw new InvalidOperationException($"Unknown manifest version. Manifest version must be '1.0'"); - } - - foreach (var element in document.Root.Elements()) - { - if (!string.Equals(element.Name.LocalName, ContentRootElementName, StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidOperationException($"Invalid manifest format. Invalid element '{element.Name.LocalName}'. All {StaticWebAssetsLoader.StaticWebAssetsManifestName} child elements must be '{ContentRootElementName}' elements."); - } - if (!element.IsEmpty) - { - throw new InvalidOperationException($"Invalid manifest format. {ContentRootElementName} can't have content."); - } - - var basePath = ParseRequiredAttribute(element, "BasePath"); - var path = ParseRequiredAttribute(element, "Path"); - yield return new ContentRootMapping(basePath, path); - } - } - - private static string ParseRequiredAttribute(XElement element, string attributeName) - { - var attribute = element.Attribute(attributeName); - if (attribute == null) - { - throw new InvalidOperationException($"Invalid manifest format. Missing {attributeName} attribute in '{ContentRootElementName}' element."); - } - return attribute.Value; - } - - internal readonly struct ContentRootMapping - { - public ContentRootMapping(string basePath, string path) - { - BasePath = basePath; - Path = path; - } - - public string BasePath { get; } - public string Path { get; } - } - } - - internal class StaticWebAssetsFileProvider : IFileProvider - { - private static readonly StringComparison FilePathComparison = OperatingSystem.IsWindows() ? - StringComparison.OrdinalIgnoreCase : - StringComparison.Ordinal; - - public StaticWebAssetsFileProvider(string pathPrefix, string contentRoot) - { - BasePath = NormalizePath(pathPrefix); - InnerProvider = new PhysicalFileProvider(contentRoot); - } - - public PhysicalFileProvider InnerProvider { get; } - - public PathString BasePath { get; } - - /// - public IDirectoryContents GetDirectoryContents(string subpath) - { - var modifiedSub = NormalizePath(subpath); - - if (BasePath == "/") - { - return InnerProvider.GetDirectoryContents(modifiedSub); - } - - if (StartsWithBasePath(modifiedSub, out var physicalPath)) - { - return InnerProvider.GetDirectoryContents(physicalPath.Value); - } - else if (string.Equals(subpath, string.Empty) || string.Equals(modifiedSub, "/")) - { - return new StaticWebAssetsDirectoryRoot(BasePath); - } - else if (BasePath.StartsWithSegments(modifiedSub, FilePathComparison, out var remaining)) - { - return new StaticWebAssetsDirectoryRoot(remaining); - } - - return NotFoundDirectoryContents.Singleton; - } - - /// - public IFileInfo GetFileInfo(string subpath) - { - var modifiedSub = NormalizePath(subpath); - - if (BasePath == "/") - { - return InnerProvider.GetFileInfo(subpath); - } - - if (!StartsWithBasePath(modifiedSub, out var physicalPath)) - { - return new NotFoundFileInfo(subpath); - } - else - { - return InnerProvider.GetFileInfo(physicalPath.Value); - } - } - - /// - public IChangeToken Watch(string filter) - { - return InnerProvider.Watch(filter); - } - - private static string NormalizePath(string path) - { - path = path.Replace('\\', '/'); - return path.StartsWith('/') ? path : "/" + path; - } - - private bool StartsWithBasePath(string subpath, out PathString rest) - { - return new PathString(subpath).StartsWithSegments(BasePath, FilePathComparison, out rest); - } - - private class StaticWebAssetsDirectoryRoot : IDirectoryContents - { - private readonly string _nextSegment; - - public StaticWebAssetsDirectoryRoot(PathString remainingPath) - { - // We MUST use the Value property here because it is unescaped. - _nextSegment = remainingPath.Value?.Split("/", StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? string.Empty; - } - - public bool Exists => true; - - public IEnumerator GetEnumerator() - { - return GenerateEnum(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GenerateEnum(); - } - - private IEnumerator GenerateEnum() - { - return new[] { new StaticWebAssetsFileInfo(_nextSegment) } - .Cast().GetEnumerator(); - } - - private class StaticWebAssetsFileInfo : IFileInfo - { - public StaticWebAssetsFileInfo(string name) - { - Name = name; - } - - public bool Exists => true; - - public long Length => throw new NotImplementedException(); - - public string PhysicalPath => throw new NotImplementedException(); - - public DateTimeOffset LastModified => throw new NotImplementedException(); - - public bool IsDirectory => true; - - public string Name { get; } - - public Stream CreateReadStream() - { - throw new NotImplementedException(); - } - } - } - } - } -} -#nullable restore diff --git a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj index d64782593742..107e1d40c68a 100644 --- a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs index 483fff518cfe..f353900b93e0 100644 --- a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs +++ b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsLoader.cs @@ -8,6 +8,7 @@ using System.Reflection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.FileProviders; +using Microsoft.AspNetCore.StaticWebAssets; namespace Microsoft.AspNetCore.Hosting.StaticWebAssets { @@ -16,8 +17,6 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets /// public class StaticWebAssetsLoader { - internal const string StaticWebAssetsManifestName = "Microsoft.AspNetCore.StaticWebAssets.xml"; - /// /// Configure the to use static web assets. /// @@ -25,61 +24,34 @@ public class StaticWebAssetsLoader /// The host . public static void UseStaticWebAssets(IWebHostEnvironment environment, IConfiguration configuration) { - var (manifest, isJson) = ResolveManifest(environment, configuration); - using (manifest) + var manifest = ResolveManifest(environment, configuration); + if (manifest != null) { - if (manifest != null) + using (manifest) { - UseStaticWebAssetsCore(environment, manifest, isJson); + UseStaticWebAssetsCore(environment, manifest); } } } - internal static void UseStaticWebAssetsCore(IWebHostEnvironment environment, Stream manifest, bool isJson) + internal static void UseStaticWebAssetsCore(IWebHostEnvironment environment, Stream manifest) { - if (isJson) - { - var staticWebAssetManifest = ManifestStaticWebAssetFileProvider.StaticWebAssetManifest.Parse(manifest); - var provider = new ManifestStaticWebAssetFileProvider( - staticWebAssetManifest, - (contentRoot) => new PhysicalFileProvider(contentRoot)); - - environment.WebRootFileProvider = new CompositeFileProvider(new[] { environment.WebRootFileProvider, provider }); - return; - } - - var webRootFileProvider = environment.WebRootFileProvider; - - var additionalFiles = StaticWebAssetsReader.Parse(manifest) - .Select(cr => new StaticWebAssetsFileProvider(cr.BasePath, cr.Path)) - .OfType() // Upcast so we can insert on the resulting list. - .ToList(); + var staticWebAssetManifest = ManifestStaticWebAssetFileProvider.StaticWebAssetManifest.Parse(manifest); + var provider = new ManifestStaticWebAssetFileProvider( + staticWebAssetManifest, + (contentRoot) => new PhysicalFileProvider(contentRoot)); - if (additionalFiles.Count == 0) - { - return; - } - else - { - additionalFiles.Insert(0, webRootFileProvider); - environment.WebRootFileProvider = new CompositeFileProvider(additionalFiles); - } + environment.WebRootFileProvider = new CompositeFileProvider(new[] { provider, environment.WebRootFileProvider }); } - internal static (Stream, bool) ResolveManifest(IWebHostEnvironment environment, IConfiguration configuration) + internal static Stream? ResolveManifest(IWebHostEnvironment environment, IConfiguration configuration) { try { - var manifestPath = configuration.GetValue(WebHostDefaults.StaticWebAssetsKey); - var isJson = manifestPath != null && Path.GetExtension(manifestPath).EndsWith(".json", OperatingSystem.IsWindows() ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); - var candidates = manifestPath != null ? new[] { (manifestPath, isJson) } : ResolveRelativeToAssembly(environment); - - foreach (var (candidate, json) in candidates) + var candidate = configuration.GetValue(WebHostDefaults.StaticWebAssetsKey) ?? ResolveRelativeToAssembly(environment); + if (candidate != null && File.Exists(candidate)) { - if (candidate != null && File.Exists(candidate)) - { - return (File.OpenRead(candidate), json); - } + return File.OpenRead(candidate); } // A missing manifest might simply mean that the feature is not enabled, so we simply @@ -93,12 +65,11 @@ internal static (Stream, bool) ResolveManifest(IWebHostEnvironment environment, } } - private static IEnumerable<(string candidatePath, bool isJson)> ResolveRelativeToAssembly(IWebHostEnvironment environment) + private static string ResolveRelativeToAssembly(IWebHostEnvironment environment) { var assembly = Assembly.Load(environment.ApplicationName); var basePath = string.IsNullOrEmpty(assembly.Location) ? AppContext.BaseDirectory : Path.GetDirectoryName(assembly.Location); - yield return (Path.Combine(basePath!, $"{environment.ApplicationName}.staticwebassets.runtime.json"), isJson: true); - yield return (Path.Combine(basePath!, $"{environment.ApplicationName}.StaticWebAssets.xml"), isJson: false); + return Path.Combine(basePath!, $"{environment.ApplicationName}.staticwebassets.runtime.json"); } } } diff --git a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsReader.cs b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsReader.cs deleted file mode 100644 index 6f1bae0b6824..000000000000 --- a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsReader.cs +++ /dev/null @@ -1,75 +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.IO; -using System.Xml.Linq; - -namespace Microsoft.AspNetCore.Hosting.StaticWebAssets -{ - internal static class StaticWebAssetsReader - { - private const string ManifestRootElementName = "StaticWebAssets"; - private const string VersionAttributeName = "Version"; - private const string ContentRootElementName = "ContentRoot"; - - internal static IEnumerable Parse(Stream manifest) - { - var document = XDocument.Load(manifest); - if (!string.Equals(document.Root!.Name.LocalName, ManifestRootElementName, StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidOperationException($"Invalid manifest format. Manifest root must be '{ManifestRootElementName}'"); - } - - var version = document.Root.Attribute(VersionAttributeName); - if (version == null) - { - throw new InvalidOperationException($"Invalid manifest format. Manifest root element must contain a version '{VersionAttributeName}' attribute"); - } - - if (version.Value != "1.0") - { - throw new InvalidOperationException($"Unknown manifest version. Manifest version must be '1.0'"); - } - - foreach (var element in document.Root.Elements()) - { - if (!string.Equals(element.Name.LocalName, ContentRootElementName, StringComparison.OrdinalIgnoreCase)) - { - throw new InvalidOperationException($"Invalid manifest format. Invalid element '{element.Name.LocalName}'. All {StaticWebAssetsLoader.StaticWebAssetsManifestName} child elements must be '{ContentRootElementName}' elements."); - } - if (!element.IsEmpty) - { - throw new InvalidOperationException($"Invalid manifest format. {ContentRootElementName} can't have content."); - } - - var basePath = ParseRequiredAttribute(element, "BasePath"); - var path = ParseRequiredAttribute(element, "Path"); - yield return new ContentRootMapping(basePath, path); - } - } - - private static string ParseRequiredAttribute(XElement element, string attributeName) - { - var attribute = element.Attribute(attributeName); - if (attribute == null) - { - throw new InvalidOperationException($"Invalid manifest format. Missing {attributeName} attribute in '{ContentRootElementName}' element."); - } - return attribute.Value; - } - - internal readonly struct ContentRootMapping - { - public ContentRootMapping(string basePath, string path) - { - BasePath = basePath; - Path = path; - } - - public string BasePath { get; } - public string Path { get; } - } - } -} diff --git a/src/Hosting/Hosting/test/StaticWebAssets/ManifestStaticWebAssetsFileProviderTests.cs b/src/Hosting/Hosting/test/StaticWebAssets/ManifestStaticWebAssetsFileProviderTests.cs index 198ce8932f09..24f537afc6e6 100644 --- a/src/Hosting/Hosting/test/StaticWebAssets/ManifestStaticWebAssetsFileProviderTests.cs +++ b/src/Hosting/Hosting/test/StaticWebAssets/ManifestStaticWebAssetsFileProviderTests.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting.StaticWebAssets; +using Microsoft.AspNetCore.StaticWebAssets; using Microsoft.Extensions.FileProviders; using Moq; using Xunit; @@ -23,7 +24,7 @@ public void GetFileInfoPrefixRespectsOsCaseSensitivity() var comparer = ManifestStaticWebAssetFileProvider.StaticWebAssetManifest.PathComparer; var expectedResult = OperatingSystem.IsWindows(); var manifest = new ManifestStaticWebAssetFileProvider.StaticWebAssetManifest(); - manifest.ContentRoots = new[] { Path.GetDirectoryName(typeof(StaticWebAssetsFileProviderTests).Assembly.Location) }; + manifest.ContentRoots = new[] { Path.GetDirectoryName(typeof(ManifestStaticWebAssetsFileProviderTest).Assembly.Location) }; manifest.Root = new() { Children = new(comparer) @@ -360,7 +361,7 @@ public void GetDirectoryContentsPrefixRespectsOsCaseSensitivity() var comparer = ManifestStaticWebAssetFileProvider.StaticWebAssetManifest.PathComparer; var expectedResult = OperatingSystem.IsWindows(); var manifest = new ManifestStaticWebAssetFileProvider.StaticWebAssetManifest(); - manifest.ContentRoots = new[] { Path.GetDirectoryName(typeof(StaticWebAssetsFileProviderTests).Assembly.Location) }; + manifest.ContentRoots = new[] { Path.GetDirectoryName(typeof(ManifestStaticWebAssetsFileProviderTest).Assembly.Location) }; manifest.Root = new() { Children = new(comparer) diff --git a/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsFileProviderTests.cs b/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsFileProviderTests.cs deleted file mode 100644 index fa13a43c4979..000000000000 --- a/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsFileProviderTests.cs +++ /dev/null @@ -1,210 +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.IO; -using Xunit; - -namespace Microsoft.AspNetCore.Hosting.StaticWebAssets -{ - public class StaticWebAssetsFileProviderTests - { - [Fact] - public void StaticWebAssetsFileProvider_ConstructorThrows_WhenPathIsNotFound() - { - // Arrange, Act & Assert - var provider = Assert.Throws(() => new StaticWebAssetsFileProvider("/prefix", "/nonexisting")); - } - - [Fact] - public void StaticWebAssetsFileProvider_Constructor_PrependsPrefixWithSlashIfMissing() - { - // Arrange & Act - var provider = new StaticWebAssetsFileProvider("_content", AppContext.BaseDirectory); - - // Assert - Assert.Equal("/_content", provider.BasePath); - } - - [Fact] - public void StaticWebAssetsFileProvider_Constructor_DoesNotPrependPrefixWithSlashIfPresent() - { - // Arrange & Act - var provider = new StaticWebAssetsFileProvider("/_content", AppContext.BaseDirectory); - - // Assert - Assert.Equal("/_content", provider.BasePath); - } - - [Theory] - [InlineData("\\", "_content")] - [InlineData("\\_content\\RazorClassLib\\Dir", "Castle.Core.dll")] - [InlineData("", "_content")] - [InlineData("/", "_content")] - [InlineData("/_content", "RazorClassLib")] - [InlineData("/_content/RazorClassLib", "Dir")] - [InlineData("/_content/RazorClassLib/Dir", "Microsoft.AspNetCore.Hosting.Tests.dll")] - [InlineData("/_content/RazorClassLib/Dir/testroot/", "TextFile.txt")] - [InlineData("/_content/RazorClassLib/Dir/testroot/wwwroot/", "README")] - public void GetDirectoryContents_WalksUpContentRoot(string searchDir, string expected) - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/_content/RazorClassLib/Dir", AppContext.BaseDirectory); - - // Act - var directory = provider.GetDirectoryContents(searchDir); - - // Assert - Assert.NotEmpty(directory); - Assert.Contains(directory, file => string.Equals(file.Name, expected)); - } - - [Fact] - public void GetDirectoryContents_DoesNotFindNonExistentFiles() - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/_content/RazorClassLib/", AppContext.BaseDirectory); - - // Act - var directory = provider.GetDirectoryContents("/_content/RazorClassLib/False"); - - // Assert - Assert.Empty(directory); - } - - [Theory] - [InlineData("/False/_content/RazorClassLib/")] - [InlineData("/_content/RazorClass")] - public void GetDirectoryContents_PartialMatchFails(string requestedUrl) - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/_content/RazorClassLib", AppContext.BaseDirectory); - - // Act - var directory = provider.GetDirectoryContents(requestedUrl); - - // Assert - Assert.Empty(directory); - } - - [Fact] - public void GetDirectoryContents_HandlersEmptyPath() - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/_content", - Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot")); - - // Act - var directory = provider.GetDirectoryContents(""); - - // Assert - Assert.True(directory.Exists); - } - - [Fact] - public void GetDirectoryContents_HandlesWhitespaceInBase() - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/_content/Static Web Assets", - Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot")); - - // Act - var directory = provider.GetDirectoryContents("/_content/Static Web Assets/Static Web/"); - - // Assert - Assert.Collection(directory, - file => - { - Assert.Equal("Static Web.txt", file.Name); - }); - } - - [Fact] - public void StaticWebAssetsFileProvider_FindsFileWithSpaces() - { - // Arrange & Act - var provider = new StaticWebAssetsFileProvider("/_content", - Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot")); - - // Assert - Assert.True(provider.GetFileInfo("/_content/Static Web Assets.txt").Exists); - } - - [Fact] - public void GetDirectoryContents_HandlesEmptyBasePath() - { - // Arrange - var provider = new StaticWebAssetsFileProvider("/", - Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot")); - - // Act - var directory = provider.GetDirectoryContents("/Static Web/"); - - // Assert - Assert.Collection(directory, - file => - { - Assert.Equal("Static Web.txt", file.Name); - }); - } - - [Fact] - public void StaticWebAssetsFileProviderWithEmptyBasePath_FindsFile() - { - // Arrange & Act - var provider = new StaticWebAssetsFileProvider("/", - Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot")); - - // Assert - Assert.True(provider.GetFileInfo("/Static Web Assets.txt").Exists); - } - - [Fact] - public void GetFileInfo_DoesNotMatch_IncompletePrefixSegments() - { - // Arrange - var expectedResult = OperatingSystem.IsWindows(); - var provider = new StaticWebAssetsFileProvider( - "_cont", - Path.GetDirectoryName(typeof(StaticWebAssetsFileProviderTests).Assembly.Location)); - - // Act - var file = provider.GetFileInfo("/_content/Microsoft.AspNetCore.TestHost.StaticWebAssets.xml"); - - // Assert - Assert.False(file.Exists, "File exists"); - } - - [Fact] - public void GetFileInfo_Prefix_RespectsOsCaseSensitivity() - { - // Arrange - var expectedResult = OperatingSystem.IsWindows(); - var provider = new StaticWebAssetsFileProvider( - "_content", - Path.GetDirectoryName(typeof(StaticWebAssetsFileProviderTests).Assembly.Location)); - - // Act - var file = provider.GetFileInfo("/_CONTENT/Microsoft.AspNetCore.Hosting.StaticWebAssets.xml"); - - // Assert - Assert.Equal(expectedResult, file.Exists); - } - - [Fact] - public void GetDirectoryContents_Prefix_RespectsOsCaseSensitivity() - { - // Arrange - var expectedResult = OperatingSystem.IsWindows(); - var provider = new StaticWebAssetsFileProvider( - "_content", - Path.GetDirectoryName(typeof(StaticWebAssetsFileProviderTests).Assembly.Location)); - - // Act - var directory = provider.GetDirectoryContents("/_CONTENT"); - - // Assert - Assert.Equal(expectedResult, directory.Exists); - } - } -} diff --git a/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsLoaderTests.cs b/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsLoaderTests.cs deleted file mode 100644 index f714b3440716..000000000000 --- a/src/Hosting/Hosting/test/StaticWebAssets/StaticWebAssetsLoaderTests.cs +++ /dev/null @@ -1,116 +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.IO; -using System.Linq; -using System.Text; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Hosting; -using Xunit; - -namespace Microsoft.AspNetCore.Hosting.StaticWebAssets -{ - public class StaticWebAssetsLoaderTests - { - [Fact] - public void UseStaticWebAssetsCore_CreatesCompositeRoot_WhenThereAreContentRootsInTheManifest() - { - // Arrange - var manifestContent = @$" - -"; - - var manifest = CreateManifest(manifestContent); - var originalRoot = new NullFileProvider(); - var environment = new HostingEnvironment() - { - WebRootFileProvider = originalRoot - }; - - // Act - StaticWebAssetsLoader.UseStaticWebAssetsCore(environment, manifest, false); - - // Assert - var composite = Assert.IsType(environment.WebRootFileProvider); - Assert.Equal(2, composite.FileProviders.Count()); - Assert.Equal(originalRoot, composite.FileProviders.First()); - } - - [Fact] - public void UseStaticWebAssetsCore_DoesNothing_WhenManifestDoesNotContainEntries() - { - // Arrange - var manifestContent = @$" -"; - - var manifest = CreateManifest(manifestContent); - var originalRoot = new NullFileProvider(); - var environment = new HostingEnvironment() - { - WebRootFileProvider = originalRoot - }; - - // Act - StaticWebAssetsLoader.UseStaticWebAssetsCore(environment, manifest, false); - - // Assert - Assert.Equal(originalRoot, environment.WebRootFileProvider); - } - - [Fact] - public void ResolveManifest_ManifestFromFile() - { - // Arrange - var expectedManifest = @" - - -"; - - var environment = new HostingEnvironment() - { - ApplicationName = "Microsoft.AspNetCore.Hosting" - }; - - // Act - var (manifest,_) = StaticWebAssetsLoader.ResolveManifest(environment, new ConfigurationBuilder().Build()); - - // Assert - Assert.Equal(expectedManifest, new StreamReader(manifest).ReadToEnd()); - } - - [Fact] - public void ResolveManifest_UsesConfigurationKey_WhenProvided() - { - // Arrange - var expectedManifest = @" - - -"; - var path = Path.ChangeExtension(typeof(StaticWebAssetsLoader).Assembly.Location, ".StaticWebAssets.xml"); - var environment = new HostingEnvironment() - { - ApplicationName = "NonExistingDll" - }; - - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary() { - [WebHostDefaults.StaticWebAssetsKey] = path - }).Build(); - - // Act - var (manifest,_) = StaticWebAssetsLoader.ResolveManifest(environment, configuration); - - // Assert - Assert.Equal(expectedManifest, new StreamReader(manifest).ReadToEnd()); - } - - - private Stream CreateManifest(string manifestContent) - { - return new MemoryStream(Encoding.UTF8.GetBytes(manifestContent)); - } - } -} diff --git a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs b/src/Shared/StaticWebAssets/StaticWebAssetsFileProvider.cs similarity index 74% rename from src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs rename to src/Shared/StaticWebAssets/StaticWebAssetsFileProvider.cs index fd8b8cffa589..a5a5ed15598b 100644 --- a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs +++ b/src/Shared/StaticWebAssets/StaticWebAssetsFileProvider.cs @@ -6,159 +6,12 @@ using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.Primitives; -namespace Microsoft.AspNetCore.Hosting.StaticWebAssets +namespace Microsoft.AspNetCore.StaticWebAssets { - // A file provider used for serving static web assets from referenced projects and packages during development. - // The file provider maps folders from referenced projects and packages and prepends a prefix to their relative - // paths. - // At publish time the assets end up in the wwwroot folder of the published app under the prefix indicated here - // as the base path. - // For example, for a referenced project mylibrary with content under <>\wwwroot will expose - // static web assets under _content/mylibrary (this is by convention). The path prefix or base path we apply - // is that (_content/mylibrary). - // when the app gets published, the build pipeline puts the static web assets for mylibrary under - // publish/wwwroot/_content/mylibrary/sample-asset.js - // To allow for the same experience during development, StaticWebAssetsFileProvider maps the contents of - // <>\wwwroot\** to _content/mylibrary/** - internal class StaticWebAssetsFileProvider : IFileProvider - { - private static readonly StringComparison FilePathComparison = OperatingSystem.IsWindows() ? - StringComparison.OrdinalIgnoreCase : - StringComparison.Ordinal; - - public StaticWebAssetsFileProvider(string pathPrefix, string contentRoot) - { - BasePath = NormalizePath(pathPrefix); - InnerProvider = new PhysicalFileProvider(contentRoot); - } - - public PhysicalFileProvider InnerProvider { get; } - - public PathString BasePath { get; } - - /// - public IDirectoryContents GetDirectoryContents(string subpath) - { - var modifiedSub = NormalizePath(subpath); - - if (BasePath == "/") - { - return InnerProvider.GetDirectoryContents(modifiedSub); - } - - if (StartsWithBasePath(modifiedSub, out var physicalPath)) - { - return InnerProvider.GetDirectoryContents(physicalPath.Value); - } - else if (string.Equals(subpath, string.Empty) || string.Equals(modifiedSub, "/")) - { - return new StaticWebAssetsDirectoryRoot(BasePath); - } - else if (BasePath.StartsWithSegments(modifiedSub, FilePathComparison, out var remaining)) - { - return new StaticWebAssetsDirectoryRoot(remaining); - } - - return NotFoundDirectoryContents.Singleton; - } - - /// - public IFileInfo GetFileInfo(string subpath) - { - var modifiedSub = NormalizePath(subpath); - - if (BasePath == "/") - { - return InnerProvider.GetFileInfo(subpath); - } - - if (!StartsWithBasePath(modifiedSub, out var physicalPath)) - { - return new NotFoundFileInfo(subpath); - } - else - { - return InnerProvider.GetFileInfo(physicalPath.Value); - } - } - - /// - public IChangeToken Watch(string filter) - { - return InnerProvider.Watch(filter); - } - - private static string NormalizePath(string path) - { - path = path.Replace('\\', '/'); - return path.StartsWith('/') ? path : "/" + path; - } - - private bool StartsWithBasePath(string subpath, out PathString rest) - { - return new PathString(subpath).StartsWithSegments(BasePath, FilePathComparison, out rest); - } - - private class StaticWebAssetsDirectoryRoot : IDirectoryContents - { - private readonly string _nextSegment; - - public StaticWebAssetsDirectoryRoot(PathString remainingPath) - { - // We MUST use the Value property here because it is unescaped. - _nextSegment = remainingPath.Value?.Split("/", StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? string.Empty; - } - - public bool Exists => true; - - public IEnumerator GetEnumerator() - { - return GenerateEnum(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GenerateEnum(); - } - - private IEnumerator GenerateEnum() - { - return new[] { new StaticWebAssetsFileInfo(_nextSegment) } - .Cast().GetEnumerator(); - } - - private class StaticWebAssetsFileInfo : IFileInfo - { - public StaticWebAssetsFileInfo(string name) - { - Name = name; - } - - public bool Exists => true; - - public long Length => throw new NotImplementedException(); - - public string PhysicalPath => throw new NotImplementedException(); - - public DateTimeOffset LastModified => throw new NotImplementedException(); - - public bool IsDirectory => true; - - public string Name { get; } - - public Stream CreateReadStream() - { - throw new NotImplementedException(); - } - } - } - } - internal sealed class ManifestStaticWebAssetFileProvider : IFileProvider { private static readonly StringComparison _fsComparison = OperatingSystem.IsWindows() ? From 449cb7e2e80cb33d8b6f6a971cd013f6a113adb8 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 6 Aug 2021 12:09:05 -0700 Subject: [PATCH 11/27] Support for Blazor webview --- src/Components/Web.JS/src/Boot.WebView.ts | 12 +++++++ .../PhotinoPlatform/src/BlazorWindow.cs | 4 --- .../PhotinoTestApp/PhotinoTestApp.csproj | 4 ++- .../wwwroot/PhotinoTestApp.lib.module.js | 7 ++++ ...osoft.AspNetCore.Components.WebView.csproj | 8 ++++- .../WebView/WebView/src/WebViewManager.cs | 35 +++++++++++++++++++ .../WebView/WebView/src/blazor.modules.json | 1 + ...rosoft.AspNetCore.Components.WebView.props | 5 +++ 8 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js create mode 100644 src/Components/WebView/WebView/src/blazor.modules.json create mode 100644 src/Components/WebView/WebView/src/buildTransitive/any/Microsoft.AspNetCore.Components.WebView.props diff --git a/src/Components/Web.JS/src/Boot.WebView.ts b/src/Components/Web.JS/src/Boot.WebView.ts index 0b5a5f17767c..4d5491205350 100644 --- a/src/Components/Web.JS/src/Boot.WebView.ts +++ b/src/Components/Web.JS/src/Boot.WebView.ts @@ -4,6 +4,7 @@ import { shouldAutoStart } from './BootCommon'; import { internalFunctions as navigationManagerFunctions } from './Services/NavigationManager'; import { startIpcReceiver } from './Platform/WebView/WebViewIpcReceiver'; import { sendAttachPage, sendBeginInvokeDotNetFromJS, sendEndInvokeJSFromDotNet, sendByteArray, sendLocationChanged } from './Platform/WebView/WebViewIpcSender'; +import { JSInitializer as JSInitializer } from './JSInitializers'; let started = false; @@ -13,6 +14,16 @@ async function boot(): Promise { } started = true; + const jsInitializersResponse = await fetch('_framework/blazor.modules.json', { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + + const initializers: string[] = await jsInitializersResponse.json(); + const jsInitializer = new JSInitializer(); + await jsInitializer.importInitializersAsync(initializers, []); + startIpcReceiver(); DotNet.attachDispatcher({ @@ -25,6 +36,7 @@ async function boot(): Promise { navigationManagerFunctions.listenForNavigationEvents(sendLocationChanged); sendAttachPage(navigationManagerFunctions.getBaseURI(), navigationManagerFunctions.getLocationHref()); + await jsInitializer.invokeAfterStartedCallbacks(Blazor); } Blazor.start = boot; diff --git a/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs b/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs index 486f011fb3f0..b54de9d2639c 100644 --- a/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs +++ b/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs @@ -4,11 +4,7 @@ using System; using System.Collections.Generic; using System.IO; -using Microsoft.AspNetCore.Components.Web; using Microsoft.Extensions.FileProviders; -using PhotinoNET; - -namespace Microsoft.AspNetCore.Components.WebView.Photino { /// /// A window containing a Blazor web view. diff --git a/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/PhotinoTestApp.csproj b/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/PhotinoTestApp.csproj index b9bdce6a5ea5..2e581d2a73f9 100644 --- a/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/PhotinoTestApp.csproj +++ b/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/PhotinoTestApp.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) @@ -7,6 +7,8 @@ false + + diff --git a/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js b/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js new file mode 100644 index 000000000000..1dba3c8e5195 --- /dev/null +++ b/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js @@ -0,0 +1,7 @@ +export function beforeStart(serverOptions) { + console.log('starting!'); +} + +export function afterStarted(blazor) { + console.log('started!'); +} diff --git a/src/Components/WebView/WebView/src/Microsoft.AspNetCore.Components.WebView.csproj b/src/Components/WebView/WebView/src/Microsoft.AspNetCore.Components.WebView.csproj index 075ed8d99f99..89f647db6b44 100644 --- a/src/Components/WebView/WebView/src/Microsoft.AspNetCore.Components.WebView.csproj +++ b/src/Components/WebView/WebView/src/Microsoft.AspNetCore.Components.WebView.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) @@ -26,11 +26,16 @@ + + + + + @@ -72,6 +77,7 @@ + diff --git a/src/Components/WebView/WebView/src/WebViewManager.cs b/src/Components/WebView/WebView/src/WebViewManager.cs index 885473032c26..cc285129f61f 100644 --- a/src/Components/WebView/WebView/src/WebViewManager.cs +++ b/src/Components/WebView/WebView/src/WebViewManager.cs @@ -4,12 +4,14 @@ using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.JSInterop; +using Microsoft.AspNetCore.StaticWebAssets; namespace Microsoft.AspNetCore.Components.WebView { @@ -244,5 +246,38 @@ public async ValueTask DisposeAsync() GC.SuppressFinalize(this); await DisposeAsyncCore(); } + + private class StaticWebAssetsLoader + { + internal static IFileProvider UseStaticWebAssets(IFileProvider fileProvider) + { + var manifestPath = ResolveRelativeToAssembly(); + if (File.Exists(manifestPath)) + { + using var manifestStream = File.OpenRead(manifestPath); + var manifest = ManifestStaticWebAssetFileProvider.StaticWebAssetManifest.Parse(manifestStream); + if (manifest.ContentRoots.Length > 0) + { + var manifestProvider = new ManifestStaticWebAssetFileProvider(manifest, (path) => new PhysicalFileProvider(path)); + return new CompositeFileProvider(manifestProvider, fileProvider); + } + } + + return fileProvider; + } + + private static string? ResolveRelativeToAssembly() + { + var assembly = Assembly.GetEntryAssembly(); + if (string.IsNullOrEmpty(assembly?.Location)) + { + return null; + } + + var name = Path.GetFileNameWithoutExtension(assembly.Location); + + return Path.Combine(Path.GetDirectoryName(assembly.Location)!, $"{name}.staticwebassets.runtime.json"); + } + } } } diff --git a/src/Components/WebView/WebView/src/blazor.modules.json b/src/Components/WebView/WebView/src/blazor.modules.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/src/Components/WebView/WebView/src/blazor.modules.json @@ -0,0 +1 @@ +[] diff --git a/src/Components/WebView/WebView/src/buildTransitive/any/Microsoft.AspNetCore.Components.WebView.props b/src/Components/WebView/WebView/src/buildTransitive/any/Microsoft.AspNetCore.Components.WebView.props new file mode 100644 index 000000000000..f43c2047fb31 --- /dev/null +++ b/src/Components/WebView/WebView/src/buildTransitive/any/Microsoft.AspNetCore.Components.WebView.props @@ -0,0 +1,5 @@ + + + _framework/blazor.modules.json + + From d6d7a9588dd04b93e7ed6146693f41a21eaa8aed Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 6 Aug 2021 15:44:00 -0700 Subject: [PATCH 12/27] Fix tests --- .../test/ComponentEndpointRouteBuilderExtensionsTest.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs b/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs index 7a6e892fc50d..977228551a24 100644 --- a/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs +++ b/src/Components/Server/test/ComponentEndpointRouteBuilderExtensionsTest.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Moq; using Xunit; @@ -54,6 +55,9 @@ public void MapBlazorHub_MostGeneralOverload_MapsUnderlyingHub() private IApplicationBuilder CreateAppBuilder() { + var environment = new Mock(); + environment.SetupGet(e => e.ApplicationName).Returns("app"); + environment.SetupGet(e => e.WebRootFileProvider).Returns(new NullFileProvider()); var services = new ServiceCollection(); services.AddSingleton(Mock.Of()); services.AddLogging(); @@ -64,6 +68,7 @@ private IApplicationBuilder CreateAppBuilder() services.AddRouting(); services.AddSignalR(); services.AddServerSideBlazor(); + services.AddSingleton(environment.Object); services.AddSingleton(new ConfigurationBuilder().Build()); var serviceProvider = services.BuildServiceProvider(); From 2c98236e153900b1a6240ac93b9886cd679ecc08 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Sat, 7 Aug 2021 11:02:09 -0700 Subject: [PATCH 13/27] Add E2E tests --- src/Components/Web.JS/src/Boot.WebAssembly.ts | 2 +- .../JsInitializersTest.cs | 36 ++++++++++++++ .../test/E2ETest/Tests/JsInitializersTest.cs | 36 ++++++++++++++ .../wwwroot/BasicTestApp.lib.module.js | 48 +++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs create mode 100644 src/Components/test/E2ETest/Tests/JsInitializersTest.cs create mode 100644 src/Components/test/testassets/BasicTestApp/wwwroot/BasicTestApp.lib.module.js diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index fe5eb59c0d9e..f208ef62460f 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -123,7 +123,7 @@ async function boot(options?: Partial): Promise { } const [resourceLoader] = await Promise.all([ - WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), + WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, candidateOptions || {}), WebAssemblyConfigLoader.initAsync(bootConfigResult)]); try { diff --git a/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs new file mode 100644 index 000000000000..6f64edd455ed --- /dev/null +++ b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.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 BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests +{ + public class ServerJsInitializersTest : ServerTestBase> + { + public ServerJsInitializersTest( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture.WithServerExecution(), output) + { + } + + protected override void InitializeAsyncCore() + { + Navigate(ServerPathBase + "#initializer"); + } + + [Fact] + public void InitializersWork() + { + Browser.Exists(By.Id("initializer-start")); + Browser.Exists(By.Id("initializer-end")); + } + } +} diff --git a/src/Components/test/E2ETest/Tests/JsInitializersTest.cs b/src/Components/test/E2ETest/Tests/JsInitializersTest.cs new file mode 100644 index 000000000000..1c40c968dd0b --- /dev/null +++ b/src/Components/test/E2ETest/Tests/JsInitializersTest.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 BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests +{ + public class JsInitializersTest : ServerTestBase> + { + public JsInitializersTest( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + protected override void InitializeAsyncCore() + { + Navigate(ServerPathBase + "#initializer"); + } + + [Fact] + public void InitializersWork() + { + Browser.Exists(By.Id("initializer-start")); + Browser.Exists(By.Id("initializer-end")); + } + } +} diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/BasicTestApp.lib.module.js b/src/Components/test/testassets/BasicTestApp/wwwroot/BasicTestApp.lib.module.js new file mode 100644 index 000000000000..d0e8652a3c48 --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/BasicTestApp.lib.module.js @@ -0,0 +1,48 @@ +let runInitializer = false; +let resourceRequests = []; +export async function beforeStart(options) { + const url = new URL(document.URL); + runInitializer = url.hash.indexOf('initializer') !== -1; + if (runInitializer) { + if (!options.logLevel) { + // Simple way of detecting we are in web assembly + options.loadBootResource = function (type, name, defaultUri, integrity) { + resourceRequests.push([type, name, defaultUri, integrity]); + return defaultUri; + } + } + const start = document.createElement('p'); + start.innerText = 'Before starting'; + start.style = 'background-color: green; color: white'; + start.setAttribute('id', 'initializer-start'); + document.body.appendChild(start); + } +} + +export async function afterStarted() { + if (runInitializer) { + const end = document.createElement('p'); + end.setAttribute('id', 'initializer-end'); + end.innerText = 'After started'; + end.style = 'background-color: pink'; + document.body.appendChild(end); + + if (resourceRequests.length > 0) { + + const resourceRow = (row) => `${row[0]}${row[1]}${row[2]}${row[3]}`; + const rows = resourceRequests.reduce((previewRows, currentRow) => previewRows + resourceRow(currentRow), ''); + + const requestTable = document.createElement('table'); + requestTable.setAttribute('id', 'total-requests'); + requestTable.innerHTML = ` + type + name + default-uri + integrity + +${rows} +`; + document.body.appendChild(requestTable); + } + } +} From 64c3a1dd41b2394e09818d367139ae5026ee66c1 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Sat, 7 Aug 2021 11:47:49 -0700 Subject: [PATCH 14/27] Sample JS module sample --- .../ComponentFromPackage.razor | 21 ++++++++++++++++++- .../ComponentFromPackage.razor.js | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js diff --git a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor index 22c9c43e8293..3fd8b11d4671 100644 --- a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor +++ b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor @@ -1,4 +1,12 @@ -
+@using Microsoft.JSInterop +@inject IJSRuntime JS + +
+ The behavior for this button was imported from a JS module shipping with the component. + +
+ +
This component, including the CSS and image required to produce its elegant styling, is in an external NuGet package. @@ -6,6 +14,17 @@ @code { string buttonLabel = "Click me"; + private IJSObjectReference _module = null; + + protected async override Task OnInitializedAsync() + { + _module = await JS.InvokeAsync("import", "./_content/TestContentPackage/ComponentFromPackage.razor.js"); + } + + async Task TriggerPrompt() + { + await _module.InvokeVoidAsync("showPrompt", "Hello from module"); + } void ChangeLabel() { diff --git a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js new file mode 100644 index 000000000000..f984193fa449 --- /dev/null +++ b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js @@ -0,0 +1,3 @@ +export function showPrompt(message) { + window.TestContentPackage.showPrompt(message); +} From de1973db2a25daa2fb328e95b68cd984e64b16b4 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 10 Aug 2021 04:59:31 -0700 Subject: [PATCH 15/27] Address feedback --- .../wwwroot/BlazorServerApp.lib.module.js | 7 ------- src/Components/Web.JS/src/Boot.Server.ts | 12 ++---------- src/Components/Web.JS/src/Boot.WebAssembly.ts | 11 +++-------- src/Components/Web.JS/src/Boot.WebView.ts | 12 ++---------- .../src/JSInitializers/JSInitializers.Server.ts | 16 ++++++++++++++++ .../JSInitializers/JSInitializers.WebAssembly.ts | 15 +++++++++++++++ .../src/JSInitializers/JSInitializers.WebView.ts | 14 ++++++++++++++ .../src/{ => JSInitializers}/JSInitializers.ts | 16 +++------------- src/Components/Web.JS/src/Platform/BootConfig.ts | 9 ++++++--- .../src/Platform/WebAssemblyStartOptions.ts | 2 -- src/Components/Web.JS/tsconfig.json | 1 - ...stedBlazorWebassemblyApp.Client.lib.module.js | 7 ------- .../wwwroot/PhotinoTestApp.lib.module.js | 7 ------- .../ServerExecutionTests/JsInitializersTest.cs | 4 ++-- 14 files changed, 63 insertions(+), 70 deletions(-) delete mode 100644 src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js create mode 100644 src/Components/Web.JS/src/JSInitializers/JSInitializers.Server.ts create mode 100644 src/Components/Web.JS/src/JSInitializers/JSInitializers.WebAssembly.ts create mode 100644 src/Components/Web.JS/src/JSInitializers/JSInitializers.WebView.ts rename src/Components/Web.JS/src/{ => JSInitializers}/JSInitializers.ts (77%) delete mode 100644 src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js delete mode 100644 src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js diff --git a/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js b/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js deleted file mode 100644 index 1dba3c8e5195..000000000000 --- a/src/Components/Samples/BlazorServerApp/wwwroot/BlazorServerApp.lib.module.js +++ /dev/null @@ -1,7 +0,0 @@ -export function beforeStart(serverOptions) { - console.log('starting!'); -} - -export function afterStarted(blazor) { - console.log('started!'); -} diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index 2687b6de225f..9f5fc9e608b4 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -13,7 +13,7 @@ import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnect import { attachRootComponentToLogicalElement } from './Rendering/Renderer'; import { discoverComponents, discoverPersistedState, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { sendJSDataStream } from './Platform/Circuits/CircuitStreamingInterop'; -import { JSInitializer } from './JSInitializers'; +import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.Server'; let renderingFailed = false; let started = false; @@ -26,15 +26,7 @@ async function boot(userOptions?: Partial): Promise { // Establish options to be used const options = resolveOptions(userOptions); - const jsInitializersResponse = await fetch('_blazor/initializers', { - method: 'GET', - credentials: 'include', - cache: 'no-cache' - }); - - const initializers: string[] = await jsInitializersResponse.json(); - const jsInitializer = new JSInitializer(); - await jsInitializer.importInitializersAsync(initializers, [options]); + const jsInitializer = await fetchAndInvokeInitializers(options); const logger = new ConsoleLogger(options.logLevel); Blazor.defaultReconnectionHandler = new DefaultReconnectionHandler(logger); diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index f208ef62460f..76e103a1f12d 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -14,7 +14,8 @@ import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions'; import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher'; import { discoverComponents, discoverPersistedState, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery'; import { setDispatchEventMiddleware } from './Rendering/WebRendererInteropMethods'; -import { AfterBlazorStartedCallback, JSInitializer } from './JSInitializers'; +import { AfterBlazorStartedCallback, JSInitializer } from './JSInitializers/JSInitializers'; +import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.WebAssembly'; declare var Module: EmscriptenModule; let started = false; @@ -114,13 +115,7 @@ async function boot(options?: Partial): Promise { }; const bootConfigResult: BootConfigResult = await bootConfigPromise; - const initializers = bootConfigResult.bootConfig.resources.libraryInitializers; - const jsInitializer = new JSInitializer(); - if (initializers) { - await jsInitializer.importInitializersAsync( - Object.keys(initializers), - [candidateOptions, bootConfigResult.bootConfig.resources.extensions]); - } + const jsInitializer = await fetchAndInvokeInitializers(bootConfigResult.bootConfig, candidateOptions); const [resourceLoader] = await Promise.all([ WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, candidateOptions || {}), diff --git a/src/Components/Web.JS/src/Boot.WebView.ts b/src/Components/Web.JS/src/Boot.WebView.ts index 4d5491205350..b77409285506 100644 --- a/src/Components/Web.JS/src/Boot.WebView.ts +++ b/src/Components/Web.JS/src/Boot.WebView.ts @@ -4,7 +4,7 @@ import { shouldAutoStart } from './BootCommon'; import { internalFunctions as navigationManagerFunctions } from './Services/NavigationManager'; import { startIpcReceiver } from './Platform/WebView/WebViewIpcReceiver'; import { sendAttachPage, sendBeginInvokeDotNetFromJS, sendEndInvokeJSFromDotNet, sendByteArray, sendLocationChanged } from './Platform/WebView/WebViewIpcSender'; -import { JSInitializer as JSInitializer } from './JSInitializers'; +import { fetchAndInvokeInitializers } from './JSInitializers/JSInitializers.WebView'; let started = false; @@ -14,15 +14,7 @@ async function boot(): Promise { } started = true; - const jsInitializersResponse = await fetch('_framework/blazor.modules.json', { - method: 'GET', - credentials: 'include', - cache: 'no-cache' - }); - - const initializers: string[] = await jsInitializersResponse.json(); - const jsInitializer = new JSInitializer(); - await jsInitializer.importInitializersAsync(initializers, []); + const jsInitializer = await fetchAndInvokeInitializers(); startIpcReceiver(); diff --git a/src/Components/Web.JS/src/JSInitializers/JSInitializers.Server.ts b/src/Components/Web.JS/src/JSInitializers/JSInitializers.Server.ts new file mode 100644 index 000000000000..44a941690146 --- /dev/null +++ b/src/Components/Web.JS/src/JSInitializers/JSInitializers.Server.ts @@ -0,0 +1,16 @@ +import { BootJsonData } from "../Platform/BootConfig"; +import { CircuitStartOptions } from "../Platform/Circuits/CircuitStartOptions"; +import { JSInitializer } from "./JSInitializers"; + +export async function fetchAndInvokeInitializers(options: Partial) : Promise { + const jsInitializersResponse = await fetch('_blazor/initializers', { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + + const initializers: string[] = await jsInitializersResponse.json(); + const jsInitializer = new JSInitializer(); + await jsInitializer.importInitializersAsync(initializers, [options]); + return jsInitializer; +} diff --git a/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebAssembly.ts b/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebAssembly.ts new file mode 100644 index 000000000000..23127e0b6621 --- /dev/null +++ b/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebAssembly.ts @@ -0,0 +1,15 @@ +import { BootJsonData } from "../Platform/BootConfig"; +import { WebAssemblyStartOptions } from "../Platform/WebAssemblyStartOptions"; +import { JSInitializer } from "./JSInitializers"; + +export async function fetchAndInvokeInitializers(bootConfig: BootJsonData, options: Partial) : Promise { + const initializers = bootConfig.resources.libraryInitializers; + const jsInitializer = new JSInitializer(); + if (initializers) { + await jsInitializer.importInitializersAsync( + Object.keys(initializers), + [options, bootConfig.resources.extensions]); + } + + return jsInitializer; +} diff --git a/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebView.ts b/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebView.ts new file mode 100644 index 000000000000..1cfd05092c48 --- /dev/null +++ b/src/Components/Web.JS/src/JSInitializers/JSInitializers.WebView.ts @@ -0,0 +1,14 @@ +import { JSInitializer } from "./JSInitializers"; + +export async function fetchAndInvokeInitializers() : Promise { + const jsInitializersResponse = await fetch('_framework/blazor.modules.json', { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + + const initializers: string[] = await jsInitializersResponse.json(); + const jsInitializer = new JSInitializer(); + await jsInitializer.importInitializersAsync(initializers, []); + return jsInitializer; +} diff --git a/src/Components/Web.JS/src/JSInitializers.ts b/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts similarity index 77% rename from src/Components/Web.JS/src/JSInitializers.ts rename to src/Components/Web.JS/src/JSInitializers/JSInitializers.ts index 5a1de229976c..27242648d615 100644 --- a/src/Components/Web.JS/src/JSInitializers.ts +++ b/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts @@ -1,4 +1,5 @@ -import { IBlazor } from "./GlobalExports"; +import { Blazor } from '../GlobalExports' +type IBlazor = typeof Blazor; type BeforeBlazorStartedCallback = (...args: unknown[]) => Promise; export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; @@ -10,12 +11,7 @@ export class JSInitializer { async importInitializersAsync( initializerFiles: string[], initializerArguments: unknown[]): Promise { - - try { await Promise.all(initializerFiles.map(f => importAndInvokeInitializer(this, f))); - } catch (error) { - console.warn(`A library initializer produced an error before starting: '${error}'`); - } function adjustPath(path: string): string { // This is the same we do in JS interop with the import callback @@ -42,12 +38,6 @@ export class JSInitializer { } async invokeAfterStartedCallbacks(blazor: IBlazor) { - await Promise.all(this.afterStartedCallbacks.map(async callback => { - try { - await callback(blazor); - } catch (error) { - console.warn(`A library initializer produced an error after starting: '${error}'`); - } - })); + await Promise.all(this.afterStartedCallbacks.map(callback => callback(blazor))); } } diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 77f1c52a85f8..91420e99fa54 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -1,11 +1,14 @@ -import { WebAssemblyBootResourceType } from "./WebAssemblyStartOptions"; +import { WebAssemblyBootResourceType } from './WebAssemblyStartOptions'; + +type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => + string | Promise | null | undefined; export class BootConfigResult { private constructor(public bootConfig: BootJsonData, public applicationEnvironment: string) { } - static async initAsync(loadBootResource?: (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined, environment?: string): Promise { - let loaderResponse = loadBootResource !== undefined ? + static async initAsync(loadBootResource?: LoadBootResourceCallback, environment?: string): Promise { + const loaderResponse = loadBootResource !== undefined ? loadBootResource('manifest', 'blazor.boot.json', '_framework/blazor.boot.json', '') : this.defaultLoadBlazorBootJson('_framework/blazor.boot.json'); diff --git a/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts b/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts index c3a421271e7b..c48a5100a5d3 100644 --- a/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts +++ b/src/Components/Web.JS/src/Platform/WebAssemblyStartOptions.ts @@ -1,5 +1,3 @@ -import { BootConfigResult, BootJsonData } from "./BootConfig"; - export interface WebAssemblyStartOptions { /** * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched diff --git a/src/Components/Web.JS/tsconfig.json b/src/Components/Web.JS/tsconfig.json index e1595b625dff..a7813ded5916 100644 --- a/src/Components/Web.JS/tsconfig.json +++ b/src/Components/Web.JS/tsconfig.json @@ -6,7 +6,6 @@ "removeComments": false, "sourceMap": true, "target": "es2019", - "module": "es2020", "lib": ["es2019", "dom"], "strict": true } diff --git a/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js b/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js deleted file mode 100644 index 1dba3c8e5195..000000000000 --- a/src/Components/WebAssembly/Samples/HostedBlazorWebassemblyApp/Client/wwwroot/HostedBlazorWebassemblyApp.Client.lib.module.js +++ /dev/null @@ -1,7 +0,0 @@ -export function beforeStart(serverOptions) { - console.log('starting!'); -} - -export function afterStarted(blazor) { - console.log('started!'); -} diff --git a/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js b/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js deleted file mode 100644 index 1dba3c8e5195..000000000000 --- a/src/Components/WebView/Samples/PhotinoPlatform/testassets/PhotinoTestApp/wwwroot/PhotinoTestApp.lib.module.js +++ /dev/null @@ -1,7 +0,0 @@ -export function beforeStart(serverOptions) { - console.log('starting!'); -} - -export function afterStarted(blazor) { - console.log('started!'); -} diff --git a/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs index 6f64edd455ed..ab74bff5aabd 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using BasicTestApp; -using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.Components.E2ETest.Tests; using Microsoft.AspNetCore.E2ETesting; using OpenQA.Selenium; using Xunit; @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests { - public class ServerJsInitializersTest : ServerTestBase> + public class ServerJsInitializersTest : JsInitializersTest { public ServerJsInitializersTest( BrowserFixture browserFixture, From 74cd9d5d932857b82c868ca81a9b40afbb1bb9dc Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 10 Aug 2021 05:02:38 -0700 Subject: [PATCH 16/27] Enable dynamic import --- src/Components/Web.JS/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/Web.JS/tsconfig.json b/src/Components/Web.JS/tsconfig.json index a7813ded5916..e1595b625dff 100644 --- a/src/Components/Web.JS/tsconfig.json +++ b/src/Components/Web.JS/tsconfig.json @@ -6,6 +6,7 @@ "removeComments": false, "sourceMap": true, "target": "es2019", + "module": "es2020", "lib": ["es2019", "dom"], "strict": true } From 3b50ebba85fd5e13668ada023195dd7abc0b9989 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 10 Aug 2021 06:29:20 -0700 Subject: [PATCH 17/27] Fix build --- .../ServerExecutionTests/JsInitializersTest.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs index ab74bff5aabd..d39e70a2d6a5 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/JsInitializersTest.cs @@ -20,17 +20,5 @@ public ServerJsInitializersTest( : base(browserFixture, serverFixture.WithServerExecution(), output) { } - - protected override void InitializeAsyncCore() - { - Navigate(ServerPathBase + "#initializer"); - } - - [Fact] - public void InitializersWork() - { - Browser.Exists(By.Id("initializer-start")); - Browser.Exists(By.Id("initializer-end")); - } } } From 77bb124cc082199ac947a04bc926b1b3f8da57a2 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 11 Aug 2021 14:50:04 -0700 Subject: [PATCH 18/27] Fix bad merge --- .../WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs b/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs index b54de9d2639c..486f011fb3f0 100644 --- a/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs +++ b/src/Components/WebView/Samples/PhotinoPlatform/src/BlazorWindow.cs @@ -4,7 +4,11 @@ using System; using System.Collections.Generic; using System.IO; +using Microsoft.AspNetCore.Components.Web; using Microsoft.Extensions.FileProviders; +using PhotinoNET; + +namespace Microsoft.AspNetCore.Components.WebView.Photino { /// /// A window containing a Blazor web view. From ca60dd2b609491a2118902decf9614fb1bc54ac7 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 01:08:04 -0700 Subject: [PATCH 19/27] Address missing feedback --- src/Components/Web.JS/src/GlobalExports.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Web.JS/src/GlobalExports.ts b/src/Components/Web.JS/src/GlobalExports.ts index 5a0adb48387a..21ab215dda89 100644 --- a/src/Components/Web.JS/src/GlobalExports.ts +++ b/src/Components/Web.JS/src/GlobalExports.ts @@ -13,7 +13,7 @@ import { getNextChunk, receiveDotNetDataStream } from './StreamingInterop'; import { RootComponentsFunctions } from './Rendering/JSRootComponents'; import { attachWebRendererInterop } from './Rendering/WebRendererInteropMethods'; -export interface IBlazor { +interface IBlazor { navigateTo: (uri: string, options: NavigationOptions) => void; registerCustomEventType: (eventName: string, options: EventTypeOptions) => void; From 8835f8de9c4330684a027400f8ecd4f2aebe3278 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 02:37:38 -0700 Subject: [PATCH 20/27] Fix build break --- .../src/Infrastructure/ConfigureCompatibilityOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs index ce0ea19de6ed..893bc9208f10 100644 --- a/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs +++ b/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs @@ -88,7 +88,7 @@ private void ConfigureSwitch(ICompatibilitySwitch @switch, IReadOnlyDictionary Date: Thu, 12 Aug 2021 03:35:40 -0700 Subject: [PATCH 21/27] Address feedback --- .../src/JSInitializers/JSInitializers.ts | 13 +++++------- .../Web.JS/src/Platform/BootConfig.ts | 20 +++++++++---------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts b/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts index 27242648d615..da0634357ffc 100644 --- a/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts +++ b/src/Components/Web.JS/src/JSInitializers/JSInitializers.ts @@ -1,17 +1,14 @@ -import { Blazor } from '../GlobalExports' -type IBlazor = typeof Blazor; +import { Blazor } from '../GlobalExports'; type BeforeBlazorStartedCallback = (...args: unknown[]) => Promise; -export type AfterBlazorStartedCallback = (blazor: IBlazor) => Promise; +export type AfterBlazorStartedCallback = (blazor: typeof Blazor) => Promise; type BlazorInitializer = { beforeStart: BeforeBlazorStartedCallback, afterStarted: AfterBlazorStartedCallback }; export class JSInitializer { private afterStartedCallbacks: AfterBlazorStartedCallback[] = []; - async importInitializersAsync( - initializerFiles: string[], - initializerArguments: unknown[]): Promise { - await Promise.all(initializerFiles.map(f => importAndInvokeInitializer(this, f))); + async importInitializersAsync(initializerFiles: string[], initializerArguments: unknown[]): Promise { + await Promise.all(initializerFiles.map(f => importAndInvokeInitializer(this, f))); function adjustPath(path: string): string { // This is the same we do in JS interop with the import callback @@ -37,7 +34,7 @@ export class JSInitializer { } } - async invokeAfterStartedCallbacks(blazor: IBlazor) { + async invokeAfterStartedCallbacks(blazor: typeof Blazor) { await Promise.all(this.afterStartedCallbacks.map(callback => callback(blazor))); } } diff --git a/src/Components/Web.JS/src/Platform/BootConfig.ts b/src/Components/Web.JS/src/Platform/BootConfig.ts index 91420e99fa54..55ad90380d08 100644 --- a/src/Components/Web.JS/src/Platform/BootConfig.ts +++ b/src/Components/Web.JS/src/Platform/BootConfig.ts @@ -10,11 +10,11 @@ export class BootConfigResult { static async initAsync(loadBootResource?: LoadBootResourceCallback, environment?: string): Promise { const loaderResponse = loadBootResource !== undefined ? loadBootResource('manifest', 'blazor.boot.json', '_framework/blazor.boot.json', '') : - this.defaultLoadBlazorBootJson('_framework/blazor.boot.json'); + defaultLoadBlazorBootJson('_framework/blazor.boot.json'); const bootConfigResponse = loaderResponse instanceof Promise ? await loaderResponse : - await BootConfigResult.defaultLoadBlazorBootJson(loaderResponse ?? '_framework/blazor.boot.json'); + await defaultLoadBlazorBootJson(loaderResponse ?? '_framework/blazor.boot.json'); // While we can expect an ASP.NET Core hosted application to include the environment, other // hosts may not. Assume 'Production' in the absence of any specified value. @@ -23,18 +23,18 @@ export class BootConfigResult { bootConfig.modifiableAssemblies = bootConfigResponse.headers.get('DOTNET-MODIFIABLE-ASSEMBLIES'); return new BootConfigResult(bootConfig, applicationEnvironment); + + async function defaultLoadBlazorBootJson(url: string) : Promise { + return fetch(url, { + method: 'GET', + credentials: 'include', + cache: 'no-cache' + }); + } }; - public static async defaultLoadBlazorBootJson(url: string) : Promise { - return fetch(url, { - method: 'GET', - credentials: 'include', - cache: 'no-cache' - }); - } } - // Keep in sync with bootJsonData from the BlazorWebAssemblySDK export interface BootJsonData { readonly entryAssembly: string; From eae8344365365fad371bdcec68d839ed1adceb2f Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 03:36:07 -0700 Subject: [PATCH 22/27] Make public API internal --- src/Components/Server/src/CircuitOptions.cs | 6 +----- src/Components/Server/src/PublicAPI.Unshipped.txt | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Components/Server/src/CircuitOptions.cs b/src/Components/Server/src/CircuitOptions.cs index 2a689fff2265..2eb51b174f4a 100644 --- a/src/Components/Server/src/CircuitOptions.cs +++ b/src/Components/Server/src/CircuitOptions.cs @@ -82,10 +82,6 @@ public sealed class CircuitOptions /// public CircuitRootComponentOptions RootComponents { get; } = new CircuitRootComponentOptions(); - /// - /// Gets the list of JavaScript initializers used by Blazor server. By default this list gets populated by - /// the .modules.json manifest file in the web root if present. - /// - public IList JavaScriptInitializers { get; } = new List(); + internal IList JavaScriptInitializers { get; } = new List(); } } diff --git a/src/Components/Server/src/PublicAPI.Unshipped.txt b/src/Components/Server/src/PublicAPI.Unshipped.txt index d1622d7741be..172a7b628066 100644 --- a/src/Components/Server/src/PublicAPI.Unshipped.txt +++ b/src/Components/Server/src/PublicAPI.Unshipped.txt @@ -1,5 +1,4 @@ #nullable enable -Microsoft.AspNetCore.Components.Server.CircuitOptions.JavaScriptInitializers.get -> System.Collections.Generic.IList! Microsoft.AspNetCore.Components.Server.CircuitOptions.RootComponents.get -> Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions! Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions.CircuitRootComponentOptions() -> void From 6db97d33c7eebd3757fe11a290a0efe738d286e7 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 03:36:38 -0700 Subject: [PATCH 23/27] Add additional E2E test for file modules --- .../TestContentPackage/ComponentFromPackage.razor | 14 ++++---------- .../ComponentFromPackage.razor.js | 6 ++++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor index 3fd8b11d4671..553de9db7006 100644 --- a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor +++ b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor @@ -1,17 +1,15 @@ @using Microsoft.JSInterop @inject IJSRuntime JS -
- The behavior for this button was imported from a JS module shipping with the component. - -
-
This component, including the CSS and image required to produce its elegant styling, is in an external NuGet package.
+
+
+ @code { string buttonLabel = "Click me"; private IJSObjectReference _module = null; @@ -19,11 +17,7 @@ protected async override Task OnInitializedAsync() { _module = await JS.InvokeAsync("import", "./_content/TestContentPackage/ComponentFromPackage.razor.js"); - } - - async Task TriggerPrompt() - { - await _module.InvokeVoidAsync("showPrompt", "Hello from module"); + await _module.InvokeVoidAsync("displayMessage", "Hello from module"); } void ChangeLabel() diff --git a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js index f984193fa449..965a355da109 100644 --- a/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js +++ b/src/Components/test/testassets/TestContentPackage/ComponentFromPackage.razor.js @@ -1,3 +1,5 @@ -export function showPrompt(message) { - window.TestContentPackage.showPrompt(message); +export function displayMessage(message) { + const element = document.createElement("p"); + element.innerText = message; + document.querySelector('.js-module-message').appendChild(element); } From 218f0fe484ed2bb7a004e2515d56cb42e7320841 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 05:13:12 -0700 Subject: [PATCH 24/27] Temporarily supress a bunch of warnings --- src/Components/Authorization/src/AuthorizeRouteView.cs | 5 +++++ src/Components/Web/src/JSComponents/JSComponentInterop.cs | 3 +++ src/Components/Web/src/WebEventData/WebEventData.cs | 2 ++ .../WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs | 3 +++ 4 files changed, 13 insertions(+) diff --git a/src/Components/Authorization/src/AuthorizeRouteView.cs b/src/Components/Authorization/src/AuthorizeRouteView.cs index ef1fb45dfd9c..291da9bf12d8 100644 --- a/src/Components/Authorization/src/AuthorizeRouteView.cs +++ b/src/Components/Authorization/src/AuthorizeRouteView.cs @@ -1,6 +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.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components.Rendering; @@ -95,6 +96,10 @@ private void RenderAuthorizeRouteViewCore(RenderTreeBuilder builder) builder.CloseComponent(); } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2111:RequiresUnreferencedCode", + Justification = "OpenComponent already has the right set of attributes")] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2110:RequiresUnreferencedCode", + Justification = "OpenComponent already has the right set of attributes")] private void RenderContentInDefaultLayout(RenderTreeBuilder builder, RenderFragment content) { builder.OpenComponent(0); diff --git a/src/Components/Web/src/JSComponents/JSComponentInterop.cs b/src/Components/Web/src/JSComponents/JSComponentInterop.cs index c37466ceac28..1418ea5ab431 100644 --- a/src/Components/Web/src/JSComponents/JSComponentInterop.cs +++ b/src/Components/Web/src/JSComponents/JSComponentInterop.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Metadata; using System.Text.Json; @@ -76,6 +77,8 @@ protected internal virtual int AddRootComponent(string identifier, string domEle /// /// For framework use only. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "OpenComponent already has the right set of attributes")] protected internal void SetRootComponentParameters(int componentId, int parameterCount, JsonElement parametersJson, JsonSerializerOptions jsonOptions) { // In case the client misreports the number of parameters, impose bounds so we know the amount diff --git a/src/Components/Web/src/WebEventData/WebEventData.cs b/src/Components/Web/src/WebEventData/WebEventData.cs index c8fc38f0add3..01db2752e5c2 100644 --- a/src/Components/Web/src/WebEventData/WebEventData.cs +++ b/src/Components/Web/src/WebEventData/WebEventData.cs @@ -59,6 +59,8 @@ private WebEventData(ulong eventHandlerId, EventFieldInfo? eventFieldInfo, Event public EventArgs EventArgs { get; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "We are already using the appropriate overload")] private static EventArgs ParseEventArgsJson( Renderer renderer, JsonSerializerOptions jsonSerializerOptions, diff --git a/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs b/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs index db2817a95423..fcf1c19a2f95 100644 --- a/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs +++ b/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Reflection.Metadata; @@ -217,6 +218,8 @@ public void ApplyDeltas(IReadOnlyList deltas) } } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "OpenComponent already has the right set of attributes")] private Type[] GetMetadataUpdateTypes(IReadOnlyList deltas) { List? types = null; From 63f6ed316e88fdeaee5d2574f18680eb03d6f44a Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 12 Aug 2021 06:20:14 -0700 Subject: [PATCH 25/27] Add additional test --- src/Components/test/E2ETest/Tests/JsInitializersTest.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Components/test/E2ETest/Tests/JsInitializersTest.cs b/src/Components/test/E2ETest/Tests/JsInitializersTest.cs index 1c40c968dd0b..e8fc13715967 100644 --- a/src/Components/test/E2ETest/Tests/JsInitializersTest.cs +++ b/src/Components/test/E2ETest/Tests/JsInitializersTest.cs @@ -32,5 +32,12 @@ public void InitializersWork() Browser.Exists(By.Id("initializer-start")); Browser.Exists(By.Id("initializer-end")); } + + [Fact] + public void CanLoadJsModulePackagesFromLibrary() + { + Browser.MountTestComponent(); + Browser.Equal("Hello from module", () => Browser.Exists(By.CssSelector(".js-module-message > p")).Text); + } } } From a474909d2e79e007aee2e7d152c0a5f1341fabdc Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 13 Aug 2021 09:19:51 -0700 Subject: [PATCH 26/27] Update JS files --- src/Components/Web.JS/dist/Release/blazor.server.js | 2 +- src/Components/Web.JS/dist/Release/blazor.webview.js | 2 +- .../src/Infrastructure/ConfigureCompatibilityOptions.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Web.JS/dist/Release/blazor.server.js b/src/Components/Web.JS/dist/Release/blazor.server.js index c09fced56bd9..c591e6ab9a26 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;!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"}(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);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 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,s=new Map,i={createEventArgs:()=>({})},a=[];function c(e){return o.get(e)}function l(e){const t=o.get(e);return(null==t?void 0:t.browserEventName)||e}function h(e,t){e.forEach((e=>o.set(e,t)))}function u(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}}}),h(["copy","cut","paste"],i),h(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...d(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}}),h(["focus","blur","focusin","focusout"],i),h(["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}}),h(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>d(e)}),h(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),h(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),h(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:u(t.touches),targetTouches:u(t.targetTouches),changedTouches:u(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),h(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...d(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}}),h(["wheel","mousewheel"],{createEventArgs:e=>{return{...d(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),h(["toggle"],i);const p=["date","datetime-local","month","time","week"],f=new Map;let g,m,y=0;const w={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++y).toString();f.set(r,e);const o=await _().invokeMethodAsync("AddRootComponent",t,r),s=new b(o,m[t]);return await s.setParameters(n),s}};class v{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 b{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 v)}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 _().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await _().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function _(){if(!g)throw new Error("Dynamic root components have not been enabled in this application.");return g}const E=new Map;function S(e,t,n){return I(e,t.eventHandlerId,(()=>C(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function C(e){const t=E.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let I=(e,t,n)=>n();const k=U(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),T={submit:!0},D=U(["click","dblclick","mousedown","mousemove","mouseup"]);class x{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++x.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new R(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,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 o=n.shift(),s=null,i=!1;const a=k.hasOwnProperty(e);let l=!1;for(;o;){const d=o,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)&&D.hasOwnProperty(u)&&h.disabled))){if(!i){const n=c(e);s=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},i=!0}T.hasOwnProperty(t.type)&&t.preventDefault(),S(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:r.fromEvent(n.renderingComponentId,t)},s)}p.stopPropagation(e)&&(l=!0),p.preventDefault(e)&&t.preventDefault()}o=a||l?void 0:n.shift()}var h,u}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new P:null}}x.nextEventDelegatorId=0;class R{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},a.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=k.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 P{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 U(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const A=X("_blazorLogicalChildren"),N=X("_blazorLogicalParent"),B=X("_blazorLogicalEnd");function $(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return A in e||(e[A]=[]),e}function L(e,t){const n=document.createComment("!");return M(n,e,t),n}function M(e,t,n){const r=e;if(e instanceof Comment&&W(r)&&W(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(F(r))throw new Error("Not implemented: moving existing logical children");const o=W(t);if(n0;)O(n,0)}const r=n;r.parentNode.removeChild(r)}function F(e){return e[N]||null}function H(e,t){return W(e)[t]}function j(e){var t=J(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function W(e){return e[A]}function z(e,t){const n=W(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=K(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):V(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 J(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 q(e){const t=W(F(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function V(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=q(t);n?n.parentNode.insertBefore(e,n):V(e,F(t))}}}function K(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=q(e);if(t)return t.previousSibling;{const t=F(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:K(t)}}function X(e){return"function"==typeof Symbol?Symbol():e}function Y(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${Y(e)}]`;return document.querySelector(t)}(t.__internalId):t));const G="_blazorDeferredValue",Q=document.createElement("template"),Z=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 x(e),this.eventDelegator.notifyAfterClick((e=>{if(!de)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;ewe(!1))))},enableNavigationInterception:function(){de=!0},navigateTo:me,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function me(e,t,n=!1){const r=be(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Ee(r)?ye(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 ye(e,t,n){ue=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),we(t)}async function we(e){fe&&await fe(location.href,e)}let ve;function be(e){return ve=ve||document.createElement("a"),ve.href=e,ve.href}function _e(e,t){return e?e.tagName===t?e:_e(e.parentElement,t):null}function Ee(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=ke(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}Ie[e._id]={intersectionObserver:s,mutationObserverBefore:i,mutationObserverAfter:a}},dispose:function(e){const t=Ie[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete Ie[e._id])}},Ie={};function ke(e){return e?"visible"!==getComputedStyle(e).overflowY?e:ke(e.parentElement):null}const Te={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!==F(s)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},De={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=xe(e,t),i=await new Promise((function(e){const t=new Image;t.onload=function(){e(t)},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 xe(e,t).blob}};function xe(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 Re(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 Pe=new Map,Ue={navigateTo:me,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=s.get(t.browserEventName);n?n.push(e):s.set(t.browserEventName,[e]),a.forEach((n=>n(e,t.browserEventName)))}o.set(e,t)},rootComponents:w,_internal:{navigationManager:ge,domWrapper:Se,Virtualize:Ce,PageTitle:Te,InputFile:De,getJSDataStreamChunk:Re,receiveDotNetDataStream:function(t,n,r,o){let s=Pe.get(t);if(!s){const n=new ReadableStream({start(e){Pe.set(t,e),s=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(s.error(o),Pe.delete(t)):0===r?(s.close(),Pe.delete(t)):s.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(E.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);E.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(g)throw new Error("Dynamic root components have already been enabled.");g=t,m=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=Ue;const Ae=[0,2e3,1e4,3e4,null];class Ne{constructor(e){this._retryDelays=void 0!==e?[...e,null]:Ae}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 $e extends Error{constructor(e="A timeout occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Le extends Error{constructor(e="An abort occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Me extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="UnsupportedTransportError",this.__proto__=n}}class Oe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="DisabledTransportError",this.__proto__=n}}class Fe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="FailedToStartTransportError",this.__proto__=n}}class He extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.innerErrors=t,this.__proto__=n}}class je{constructor(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}class We{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 ze,Je,qe,Ve,Ke;!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"}(ze||(ze={}));class Xe extends We{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),this._abortControllerType=e("abort-controller")}else this._fetchType=fetch.bind(self),this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new Le;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 Le});let r,o=null;if(e.timeout){const r=e.timeout;o=setTimeout((()=>{t.abort(),this._logger.log(ze.Warning,"Timeout from HTTP request."),n=new $e}),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(ze.Warning,`Error from HTTP request. ${e}.`),e}finally{o&&clearTimeout(o),e.abortSignal&&(e.abortSignal.onabort=null)}if(!r.ok){const e=await Ye(r,"text");throw new Be(e||r.statusText,r.status)}const s=Ye(r,e.responseType),i=await s;return new je(r.status,r.statusText,i)}getCookieString(e){return""}}function Ye(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 Ge extends We{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Le):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 Le)}),e.timeout&&(r.timeout=e.timeout),r.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),r.status>=200&&r.status<300?t(new je(r.status,r.statusText,r.response||r.responseText)):n(new Be(r.response||r.responseText||r.statusText,r.status))},r.onerror=()=>{this._logger.log(ze.Warning,`Error from HTTP request. ${r.status}: ${r.statusText}.`),n(new Be(r.statusText,r.status))},r.ontimeout=()=>{this._logger.log(ze.Warning,"Timeout from HTTP request."),n(new $e)},r.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}}class Qe extends We{constructor(e){if(super(),"undefined"!=typeof fetch)this._httpClient=new Xe(e);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");this._httpClient=new Ge(e)}}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Le):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 Ze{}Ze.Authorization="Authorization",Ze.Cookie="Cookie",function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(Je||(Je={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(qe||(qe={}));class et{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 tt{constructor(){}log(e,t){}}tt.instance=new tt;class nt{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 rt{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 ot(e,t){let n="";return st(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 st(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}async function it(e,t,n,r,o,s,i){let a={};if(o){const e=await o();e&&(a={Authorization:`Bearer ${e}`})}const[c,l]=lt();a[c]=l,e.log(ze.Trace,`(${t} transport) sending data. ${ot(s,i.logMessageContent)}.`);const h=st(s)?"arraybuffer":"text",u=await n.post(r,{content:s,headers:{...a,...i.headers},responseType:h,timeout:i.timeout,withCredentials:i.withCredentials});e.log(ze.Trace,`(${t} transport) request complete. Response status: ${u.statusCode}.`)}class at{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 ct{constructor(e){this._minLevel=e,this.out=console}log(e,t){if(e>=this._minLevel){const n=`[${(new Date).toISOString()}] ${ze[e]}: ${t}`;switch(e){case ze.Critical:case ze.Error:this.out.error(n);break;case ze.Warning:this.out.warn(n);break;case ze.Information:this.out.info(n);break;default:this.out.log(n)}}}}function lt(){let e="X-SignalR-User-Agent";return rt.isNode&&(e="User-Agent"),[e,ht("0.0.0-DEV_BUILD",ut(),rt.isNode?"NodeJS":"Browser",dt())]}function ht(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 ut(){if(!rt.isNode)return"";switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}function dt(){if(rt.isNode)return process.versions.node}function pt(e){return e.stack?e.stack:e.message?e.message:`${e}`}class ft{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._pollAbort=new et,this._options=r,this._running=!1,this.onreceive=null,this.onclose=null}get pollAborted(){return this._pollAbort.aborted}async connect(e,t){if(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._url=e,this._logger.log(ze.Trace,"(LongPolling transport) Connecting."),t===qe.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]=lt(),o={[n]:r,...this._options.headers},s={abortSignal:this._pollAbort.signal,headers:o,timeout:1e5,withCredentials:this._options.withCredentials};t===qe.Binary&&(s.responseType="arraybuffer");const i=await this._getAccessToken();this._updateHeaderToken(s,i);const a=`${e}&_=${Date.now()}`;this._logger.log(ze.Trace,`(LongPolling transport) polling: ${a}.`);const c=await this._httpClient.get(a,s);200!==c.statusCode?(this._logger.log(ze.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[Ze.Authorization]=`Bearer ${t}`:e.headers[Ze.Authorization]&&delete e.headers[Ze.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(ze.Trace,`(LongPolling transport) polling: ${n}.`);const r=await this._httpClient.get(n,t);204===r.statusCode?(this._logger.log(ze.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):200!==r.statusCode?(this._logger.log(ze.Error,`(LongPolling transport) Unexpected response code: ${r.statusCode}.`),this._closeError=new Be(r.statusText||"",r.statusCode),this._running=!1):r.content?(this._logger.log(ze.Trace,`(LongPolling transport) data received. ${ot(r.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(r.content)):this._logger.log(ze.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(e){this._running?e instanceof $e?this._logger.log(ze.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=e,this._running=!1):this._logger.log(ze.Trace,`(LongPolling transport) Poll errored after shutdown: ${e.message}`)}}}finally{this._logger.log(ze.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?it(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(ze.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(ze.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);const e={},[t,n]=lt();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(ze.Trace,"(LongPolling transport) DELETE request sent.")}finally{this._logger.log(ze.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(ze.Trace,e),this.onclose(this._closeError)}}}class gt{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(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._logger.log(ze.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===qe.Text){if(rt.isBrowser||rt.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]=lt();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(ze.Trace,`(SSE transport) data received. ${ot(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(ze.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?it(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 mt{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(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._logger.log(ze.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===qe.Binary&&(o.binaryType="arraybuffer"),o.onopen=t=>{this._logger.log(ze.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(ze.Information,`(WebSockets transport) ${t}.`)},o.onmessage=e=>{if(this._logger.log(ze.Trace,`(WebSockets transport) data received. ${ot(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(ze.Trace,`(WebSockets transport) sending data. ${ot(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(ze.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 yt{constructor(e,t={}){var n;if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,nt.isRequired(e,"url"),this._logger=void 0===(n=t.logger)?new ct(ze.Information):null===n?tt.instance:void 0!==n.log?n:new ct(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 Qe(this._logger),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=t,this.onreceive=null,this.onclose=null}async start(e){if(e=e||qe.Binary,nt.isIn(e,qe,"transferFormat"),this._logger.log(ze.Debug,`Starting connection with transfer format '${qe[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(ze.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(ze.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 wt(this.transport)),this._sendQueue.send(e))}async stop(e){return"Disconnected"===this._connectionState?(this._logger.log(ze.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve()):"Disconnecting"===this._connectionState?(this._logger.log(ze.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(ze.Error,`HttpConnection.transport.stop() threw error '${e}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(ze.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!==Je.WebSockets)throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");this.transport=this._constructTransport(Je.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 ft&&(this.features.inherentKeepAlive=!0),"Connecting"===this._connectionState&&(this._logger.log(ze.Debug,"The HttpConnection connected successfully."),this._connectionState="Connected")}catch(e){return this._logger.log(ze.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[Ze.Authorization]=`Bearer ${e}`)}const[n,r]=lt();t[n]=r;const o=this._resolveNegotiateUrl(e);this._logger.log(ze.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(ze.Error,t),Promise.reject(new Error(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(ze.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(ze.Error,`Failed to start the transport '${n.transport}': ${e}`),a=void 0,s.push(new Fe(`${n.transport} failed: ${e}`,Je[n.transport])),"Connecting"!==this._connectionState){const e="Failed to select transport before stop() was called.";return this._logger.log(ze.Debug,e),Promise.reject(new Error(e))}}}}return s.length>0?Promise.reject(new He(`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 Je.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new mt(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case Je.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new gt(this._httpClient,this._accessTokenFactory,this._logger,this._options);case Je.LongPolling:return new ft(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=Je[e.transport];if(null==r)return this._logger.log(ze.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(ze.Debug,`Skipping transport '${Je[r]}' because it was disabled by the client.`),new Oe(`'${Je[r]}' is disabled by the client.`,r);if(!(e.transferFormats.map((e=>qe[e])).indexOf(n)>=0))return this._logger.log(ze.Debug,`Skipping transport '${Je[r]}' because it does not support the requested transfer format '${qe[n]}'.`),new Error(`'${Je[r]}' does not support ${qe[n]}.`);if(r===Je.WebSockets&&!this._options.WebSocket||r===Je.ServerSentEvents&&!this._options.EventSource)return this._logger.log(ze.Debug,`Skipping transport '${Je[r]}' because it is not supported in your environment.'`),new Me(`'${Je[r]}' is not supported in your environment.`,r);this._logger.log(ze.Debug,`Selecting transport '${Je[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(ze.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(ze.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(ze.Error,`Connection disconnected with error '${e}'.`):this._logger.log(ze.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch((e=>{this._logger.log(ze.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(ze.Error,`HttpConnection.onclose(${e}) threw error '${t}'.`)}}}else this._logger.log(ze.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(!rt.isBrowser||!window.document)throw new Error(`Cannot resolve '${e}'.`);const t=window.document.createElement("a");return t.href=e,this._logger.log(ze.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 wt{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new vt,this._transportResult=new vt,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new vt),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 vt;const e=this._transportResult;this._transportResult=void 0;const t="string"==typeof this._buffer[0]?this._buffer.join(""):wt._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 vt{constructor(){this.promise=new Promise(((e,t)=>[this._resolver,this._rejecter]=[e,t]))}resolve(){this._resolver()}reject(e){this._rejecter(e)}}class bt{static write(e){return`${e}${bt.RecordSeparator}`}static parse(e){if(e[e.length-1]!==bt.RecordSeparator)throw new Error("Message is incomplete.");const t=e.split(bt.RecordSeparator);return t.pop(),t}}bt.RecordSeparatorCode=30,bt.RecordSeparator=String.fromCharCode(bt.RecordSeparatorCode);class _t{writeHandshakeRequest(e){return bt.write(JSON.stringify(e))}parseHandshakeResponse(e){let t,n;if(st(e)){const r=new Uint8Array(e),o=r.indexOf(bt.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(bt.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=bt.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"}(Ve||(Ve={}));class Et{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 at(this,e)}}!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(Ke||(Ke={}));class St{constructor(e,t,n,r){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(ze.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")},nt.isRequired(e,"connection"),nt.isRequired(t,"logger"),nt.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=3e4,this.keepAliveIntervalInMilliseconds=15e3,this._logger=t,this._protocol=n,this.connection=e,this._reconnectPolicy=r,this._handshakeProtocol=new _t,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=Ke.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:Ve.Ping})}static create(e,t,n,r){return new St(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!==Ke.Disconnected&&this._connectionState!==Ke.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!==Ke.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=Ke.Connecting,this._logger.log(ze.Debug,"Starting HubConnection.");try{await this._startInternal(),rt.isBrowser&&document&&document.addEventListener("freeze",this._freezeEventListener),this._connectionState=Ke.Connected,this._connectionStarted=!0,this._logger.log(ze.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=Ke.Disconnected,this._logger.log(ze.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(ze.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(t)),this._logger.log(ze.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(ze.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===Ke.Disconnected?(this._logger.log(ze.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve()):this._connectionState===Ke.Disconnecting?(this._logger.log(ze.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState=Ke.Disconnecting,this._logger.log(ze.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(ze.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 Et;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===Ve.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===Ve.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 Ve.Invocation:this._invokeClientMethod(e);break;case Ve.StreamItem:case Ve.Completion:{const t=this._callbacks[e.invocationId];if(t){e.type===Ve.Completion&&delete this._callbacks[e.invocationId];try{t(e)}catch(e){this._logger.log(ze.Error,`Stream callback threw error: ${pt(e)}`)}}break}case Ve.Ping:break;case Ve.Close:{this._logger.log(ze.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(ze.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(ze.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(ze.Error,e);const n=new Error(e);throw this._handshakeRejecter(n),n}return this._logger.log(ze.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===Ke.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(ze.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(ze.Error,e),this._stopPromise=this._stopInternal(new Error(e))}}else this._logger.log(ze.Warning,`No client method with the name '${e.target}' found.`)}_connectionClosed(e){this._logger.log(ze.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===Ke.Disconnecting?this._completeClose(e):this._connectionState===Ke.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===Ke.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=Ke.Disconnected,this._connectionStarted=!1,rt.isBrowser&&document&&document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(ze.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(ze.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),void this._completeClose(e);if(this._connectionState=Ke.Reconnecting,e?this._logger.log(ze.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(ze.Information,"Connection reconnecting."),0!==this._reconnectingCallbacks.length){try{this._reconnectingCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(ze.Error,`An onreconnecting callback called with error '${e}' threw error '${t}'.`)}if(this._connectionState!==Ke.Reconnecting)return void this._logger.log(ze.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.")}for(;null!==o;){if(this._logger.log(ze.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!==Ke.Reconnecting)return void this._logger.log(ze.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");try{if(await this._startInternal(),this._connectionState=Ke.Connected,this._logger.log(ze.Information,"HubConnection reconnected successfully."),0!==this._reconnectedCallbacks.length)try{this._reconnectedCallbacks.forEach((e=>e.apply(this,[this.connection.connectionId])))}catch(e){this._logger.log(ze.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${e}'.`)}return}catch(e){if(this._logger.log(ze.Information,`Reconnect attempt failed because of error '${e}'.`),this._connectionState!==Ke.Reconnecting)return this._logger.log(ze.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),void(this._connectionState===Ke.Disconnecting&&this._completeClose());r=e instanceof Error?e:new Error(e.toString()),o=this._getNextRetryDelay(n++,Date.now()-t,r)}}this._logger.log(ze.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(ze.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(ze.Error,`Stream 'error' callback called with '${e}' threw error: ${pt(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:Ve.Invocation}:{arguments:t,target:e,type:Ve.Invocation};{const n=this._invocationId;return this._invocationId++,0!==r.length?{arguments:t,invocationId:n.toString(),streamIds:r,target:e,type:Ve.Invocation}:{arguments:t,invocationId:n.toString(),target:e,type:Ve.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 $t,Lt=Rt?new TextDecoder:null,Mt=Rt?"undefined"!=typeof process&&"force"!==process.env.TEXT_DECODER?200:0:Tt,Ot=function(e,t){this.type=e,this.data=t},Ft=($t=function(e,t){return($t=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}$t(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Ht=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 Ft(t,e),t}(Error),jt={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),Dt(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:xt(t,4),nsec:t.getUint32(0)};default:throw new Ht("Unrecognized data size for timestamp (expected 4, 8, or 12): "+e.length)}}(e);return new Date(1e3*t.sec+t.nsec/1e6)}},Wt=function(){function e(){this.builtInEncoders=[],this.builtInDecoders=[],this.encoders=[],this.decoders=[],this.register(jt)}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>At){var t=Pt(e);this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),Nt(e,this.bytes,this.pos),this.pos+=t}else t=Pt(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=zt(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=Bt(e,t,n),s=Uint8Array.prototype.slice.call(e,t,t+n);return this.store(s,o),o},e}(),Kt=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 Yt?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])}},Qt=new DataView(new ArrayBuffer(0)),Zt=new Uint8Array(Qt.buffer),en=function(){try{Qt.getInt8(0)}catch(e){return e.constructor}throw new Error("never reached")}(),tn=new en("Insufficient data"),nn=new Vt,rn=function(){function e(e,t,n,r,o,s,i,a){void 0===e&&(e=Wt.defaultCodec),void 0===t&&(t=void 0),void 0===n&&(n=Tt),void 0===r&&(r=Tt),void 0===o&&(o=Tt),void 0===s&&(s=Tt),void 0===i&&(i=Tt),void 0===a&&(a=nn),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=Qt,this.bytes=Zt,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=zt(e),this.view=function(e){if(e instanceof ArrayBuffer)return new DataView(e);var t=zt(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=zt(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 Kt(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 Kt(this,(function(p){switch(p.label){case 0:s=!1,p.label=1;case 1:p.trys.push([1,6,7,12]),t=Xt(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 en))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 "+qt(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 Gt(this,arguments,(function(){var n,r,o,s,i,a,c,l,h;return Kt(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=Xt(e),u.label=2;case 2:return[4,Yt(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,Yt(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 en))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,Yt(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 Ht("Unrecognized type byte: "+qt(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 Ht("The type of key must be string or number but "+typeof t);if("__proto__"===t)throw new Ht("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 Ht("Unrecognized array type byte: "+qt(e))}},e.prototype.pushMapState=function(e){if(e>this.maxMapLength)throw new Ht("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 Ht("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 Ht("Max length exceeded: UTF-8 byte length ("+e+") > maxStrLength ("+this.maxStrLength+")");if(this.bytes.byteLengthMt?function(e,t,n){var r=e.subarray(t,t+n);return Lt.decode(r)}(this.bytes,o,e):Bt(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 Ht("Max length exceeded: bin length ("+e+") > maxBinLength ("+this.maxBinLength+")");if(!this.hasRemaining(e+t))throw tn;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 Ht("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=xt(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 on{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 sn=new Uint8Array([145,Ve.Ping]);class an{constructor(e){this.name="messagepack",this.version=1,this.transferFormat=qe.Binary,this._errorResult=1,this._voidResult=2,this._nonVoidResult=3,e=e||{},this._encoder=new Jt(e.extensionCodec,e.context,e.maxDepth,e.initialBufferSize,e.sortKeys,e.forceFloat32,e.ignoreUndefined,e.forceIntegerToFloat),this._decoder=new rn(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=tt.instance);const r=on.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 Ve.Invocation:return this._writeInvocation(e);case Ve.StreamInvocation:return this._writeStreamInvocation(e);case Ve.StreamItem:return this._writeStreamItem(e);case Ve.Completion:return this._writeCompletion(e);case Ve.Ping:return on.write(sn);case Ve.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 Ve.Invocation:return this._createInvocationMessage(this._readHeaders(n),n);case Ve.StreamItem:return this._createStreamItemMessage(this._readHeaders(n),n);case Ve.Completion:return this._createCompletionMessage(this._readHeaders(n),n);case Ve.Ping:return this._createPingMessage(n);case Ve.Close:return this._createCloseMessage(n);default:return t.log(ze.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:Ve.Close}}_createPingMessage(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:Ve.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:Ve.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:Ve.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:Ve.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:Ve.Completion}}_writeInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Ve.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]):this._encoder.encode([Ve.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments]),on.write(t.slice())}_writeStreamInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Ve.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]):this._encoder.encode([Ve.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments]),on.write(t.slice())}_writeStreamItem(e){const t=this._encoder.encode([Ve.StreamItem,e.headers||{},e.invocationId,e.item]);return on.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([Ve.Completion,e.headers||{},e.invocationId,t,e.error]);break;case this._voidResult:n=this._encoder.encode([Ve.Completion,e.headers||{},e.invocationId,t]);break;case this._nonVoidResult:n=this._encoder.encode([Ve.Completion,e.headers||{},e.invocationId,t,e.result])}return on.write(n.slice())}_writeCancelInvocation(e){const t=this._encoder.encode([Ve.CancelInvocation,e.headers||{},e.invocationId]);return on.write(t.slice())}_readHeaders(e){const t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t}}let cn=!1;async function ln(e=""){let t=document.querySelector("#blazor-error-ui");t&&(t.style.display="block",e&&t.firstChild&&(t.firstChild.textContent=`\n\t${e}\t\n`)),cn||(cn=!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 hn="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,un=hn?hn.decode.bind(hn):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("")},dn=Math.pow(2,32),pn=Math.pow(2,21)-1;function fn(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function gn(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function mn(e,t){const n=gn(e,t+4);if(n>pn)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*dn+gn(e,t)}class yn{constructor(e){this.batchData=e;const t=new _n(e);this.arrayRangeReader=new En(e),this.arrayBuilderSegmentReader=new Sn(e),this.diffReader=new wn(e),this.editReader=new vn(e,t),this.frameReader=new bn(e,t)}updatedComponents(){return fn(this.batchData,this.batchData.length-20)}referenceFrames(){return fn(this.batchData,this.batchData.length-16)}disposedComponentIds(){return fn(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return fn(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return fn(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return fn(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return mn(this.batchData,n)}}class wn{constructor(e){this.batchDataUint8=e}componentId(e){return fn(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class vn{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return fn(this.batchDataUint8,e)}siblingIndex(e){return fn(this.batchDataUint8,e+4)}newTreeIndex(e){return fn(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return fn(this.batchDataUint8,e+8)}removedAttributeName(e){const t=fn(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class bn{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return fn(this.batchDataUint8,e)}subtreeLength(e){return fn(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return fn(this.batchDataUint8,e+8)}elementName(e){const t=fn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=fn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return mn(this.batchDataUint8,e+12)}}class _n{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=fn(e,e.length-4)}readString(e){if(-1===e)return null;{const n=fn(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(Cn.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(Cn.Debug,`Waiting for batch ${this.nextBatchId}. Batch ${e} not processed.`);try{this.nextBatchId++,this.logger.log(Cn.Debug,`Applying batch ${e}.`),function(e,t){const n=he[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()}] ${Cn[e]}: ${t}`;switch(e){case Cn.Critical:case Cn.Error:console.error(n);break;case Cn.Warning:console.warn(n);break;case Cn.Information:console.info(n);break;default:console.log(n)}}}}class Dn{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!==Ke.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!==Ke.Connected)return!1;const t=await e.invoke("StartCircuit",ge.getBaseURI(),ge.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=f.get(e);if(t)return f.delete(e),t}(e);if(t)return $(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=$(n,!0),o=W(r);return Array.from(n.childNodes).forEach((e=>o.push(e))),e[N]=r,t&&(e[B]=t,$(t)),$(e)}(this.components[n].start,this.components[n].end);throw new Error(`Invalid sequence number or identifier '${e}'.`)}}const xn={configureSignalR:e=>{},logLevel:Cn.Warning,reconnectionOptions:{maxRetries:8,retryIntervalMilliseconds:2e4,dialogId:"components-reconnect-modal"}};class Rn{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(null==Ue?void 0:Ue.reconnect)()||this.rejected()}catch(e){this.logger.log(Cn.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 Pn{constructor(e,t,n){this.dialog=e,this.maxRetries=t,this.document=n,this.document=n;const r=this.document.getElementById(Pn.MaxRetriesId);r&&(r.innerText=this.maxRetries.toString())}show(){this.removeClasses(),this.dialog.classList.add(Pn.ShowClassName)}update(e){const t=this.document.getElementById(Pn.CurrentAttemptId);t&&(t.innerText=e.toString())}hide(){this.removeClasses(),this.dialog.classList.add(Pn.HideClassName)}failed(){this.removeClasses(),this.dialog.classList.add(Pn.FailedClassName)}rejected(){this.removeClasses(),this.dialog.classList.add(Pn.RejectedClassName)}removeClasses(){this.dialog.classList.remove(Pn.ShowClassName,Pn.HideClassName,Pn.FailedClassName,Pn.RejectedClassName)}}Pn.ShowClassName="components-reconnect-show",Pn.HideClassName="components-reconnect-hide",Pn.FailedClassName="components-reconnect-failed",Pn.RejectedClassName="components-reconnect-rejected",Pn.MaxRetriesId="components-reconnect-max-retries",Pn.CurrentAttemptId="components-reconnect-current-attempt";class Un{constructor(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||(()=>Ue.reconnect())}onConnectionDown(e,t){if(!this._reconnectionDisplay){const t=document.getElementById(e.dialogId);this._reconnectionDisplay=t?new Pn(t,e.maxRetries,document):new Rn(e.dialogId,e.maxRetries,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new An(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))}onConnectionUp(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)}}class An{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;tAn.MaximumFirstRetryInterval?An.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(Cn.Error,e)}}this.reconnectDisplay.failed()}delay(e){return new Promise((t=>setTimeout(t,e)))}}An.MaximumFirstRetryInterval=3e3;const Nn=/^\s*Blazor-Component-State:(?[a-zA-Z0-9\+\/=]+)$/;function Bn(e){var t;if(e.nodeType===Node.COMMENT_NODE){const n=e.textContent||"",r=Nn.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 Mn(e,t){const n=e.currentElement;if(n&&n.nodeType===Node.COMMENT_NODE&&n.textContent){const r=Ln.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=On(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=On(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 On(e,t){for(;t.next()&&t.currentElement;){const n=t.currentElement;if(n.nodeType!==Node.COMMENT_NODE)continue;if(!n.textContent)continue;const r=Ln.exec(n.textContent),o=r&&r[1];if(o)return Fn(o,e),n}}function Fn(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 Hn{constructor(e){this.childNodes=e,this.currentIndex=-1,this.length=e.length}next(){return this.currentIndex++,this.currentIndexe.sequence-t.sequence))}(e)}(document),o=Bn(document),s=new Dn(r,o||""),i=await Vn(t,n,s);if(!await s.startCircuit(i))return void n.log(Cn.Error,"Failed to start the circuit.");let a=!1;const c=()=>{if(!a){const e=new FormData,t=s.circuitId;e.append("circuitId",t),a=navigator.sendBeacon("_blazor/disconnect",e)}};Ue.disconnect=c,window.addEventListener("unload",c,{capture:!1,once:!0}),Ue.reconnect=async e=>{if(zn)return!1;const r=e||await Vn(t,n,s);return await s.reconnect(r)?(t.reconnectionHandler.onConnectionUp(),!0):(n.log(Cn.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)},n.log(Cn.Information,"Blazor server-side application started.")}async function Vn(t,n,r){const o=new an;o.name="blazorpack";const s=(new kt).withUrl("_blazor",Je.WebSockets).withHubProtocol(o);t.configureSignalR(s);const i=s.build();Ue._internal.navigationManager.listenForNavigationEvents(((e,t)=>i.send("OnLocationChanged",e,t))),i.on("JS.AttachComponent",((e,t)=>function(e,t,n,r){let o=he[0];o||(o=he[0]=new oe(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=In.getOrCreate(n);i.on("JS.RenderBatch",((e,t)=>{n.log(Cn.Debug,`Received render batch with id ${e} and ${t.byteLength} bytes.`),a.processBatch(e,t,i)})),i.onclose((e=>!zn&&t.reconnectionHandler.onConnectionDown(t.reconnectionOptions,e))),i.on("JS.Error",(e=>{zn=!0,Kn(i,e,n),ln()})),Ue._internal.forceCloseConnection=()=>i.stop(),Ue._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){Kn(i,e,n),e.innerErrors&&e.innerErrors.some((e=>"UnsupportedTransportError"===e.errorType&&e.transport===Je.WebSockets))?ln("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===Je.WebSockets))?ln("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===Je.LongPolling))?(n.log(Cn.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."),ln()):ln()}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 Kn(e,t,n){n.log(Cn.Error,t),e&&e.stop()}Ue.start=qn,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&qn()})(); \ 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",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"}(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);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 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,s=new Map,i={createEventArgs:()=>({})},a=[];function c(e){return o.get(e)}function l(e){const t=o.get(e);return(null==t?void 0:t.browserEventName)||e}function h(e,t){e.forEach((e=>o.set(e,t)))}function u(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}}}),h(["copy","cut","paste"],i),h(["drag","dragend","dragenter","dragleave","dragover","dragstart","drop"],{createEventArgs:e=>{return{...d(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}}),h(["focus","blur","focusin","focusout"],i),h(["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}}),h(["contextmenu","click","mouseover","mouseout","mousemove","mousedown","mouseup","dblclick"],{createEventArgs:e=>d(e)}),h(["error"],{createEventArgs:e=>{return{message:(t=e).message,filename:t.filename,lineno:t.lineno,colno:t.colno};var t}}),h(["loadstart","timeout","abort","load","loadend","progress"],{createEventArgs:e=>{return{lengthComputable:(t=e).lengthComputable,loaded:t.loaded,total:t.total};var t}}),h(["touchcancel","touchend","touchmove","touchenter","touchleave","touchstart"],{createEventArgs:e=>{return{detail:(t=e).detail,touches:u(t.touches),targetTouches:u(t.targetTouches),changedTouches:u(t.changedTouches),ctrlKey:t.ctrlKey,shiftKey:t.shiftKey,altKey:t.altKey,metaKey:t.metaKey,type:t.type};var t}}),h(["gotpointercapture","lostpointercapture","pointercancel","pointerdown","pointerenter","pointerleave","pointermove","pointerout","pointerover","pointerup"],{createEventArgs:e=>{return{...d(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}}),h(["wheel","mousewheel"],{createEventArgs:e=>{return{...d(t=e),deltaX:t.deltaX,deltaY:t.deltaY,deltaZ:t.deltaZ,deltaMode:t.deltaMode};var t}}),h(["toggle"],i);const p=["date","datetime-local","month","time","week"],f=new Map;let g,m,y=0;const w={async add(e,t,n){if(!n)throw new Error("initialParameters must be an object, even if empty.");const r="__bl-dynamic-root:"+(++y).toString();f.set(r,e);const o=await _().invokeMethodAsync("AddRootComponent",t,r),s=new b(o,m[t]);return await s.setParameters(n),s}};class v{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 b{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 v)}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 _().invokeMethodAsync("SetRootComponentParameters",this._componentId,r,t)}async dispose(){if(null!==this._componentId){await _().invokeMethodAsync("RemoveRootComponent",this._componentId),this._componentId=null;for(const e of this._jsEventCallbackWrappers.values())e.dispose()}}}function _(){if(!g)throw new Error("Dynamic root components have not been enabled in this application.");return g}const E=new Map;function S(e,t,n){return I(e,t.eventHandlerId,(()=>C(e).invokeMethodAsync("DispatchEventAsync",t,n)))}function C(e){const t=E.get(e);if(!t)throw new Error(`No interop methods are registered for renderer ${e}`);return t}let I=(e,t,n)=>n();const k=U(["abort","blur","change","error","focus","load","loadend","loadstart","mouseenter","mouseleave","progress","reset","scroll","submit","unload","toggle","DOMNodeInsertedIntoDocument","DOMNodeRemovedFromDocument"]),T={submit:!0},D=U(["click","dblclick","mousedown","mousemove","mouseup"]);class x{constructor(e){this.browserRendererId=e,this.afterClickCallbacks=[];const t=++x.nextEventDelegatorId;this.eventsCollectionKey=`_blazorEvents_${t}`,this.eventInfoStore=new R(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,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 o=n.shift(),s=null,i=!1;const a=k.hasOwnProperty(e);let l=!1;for(;o;){const d=o,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)&&D.hasOwnProperty(u)&&h.disabled))){if(!i){const n=c(e);s=(null==n?void 0:n.createEventArgs)?n.createEventArgs(t):{},i=!0}T.hasOwnProperty(t.type)&&t.preventDefault(),S(this.browserRendererId,{eventHandlerId:n.eventHandlerId,eventName:e,eventFieldInfo:r.fromEvent(n.renderingComponentId,t)},s)}p.stopPropagation(e)&&(l=!0),p.preventDefault(e)&&t.preventDefault()}o=a||l?void 0:n.shift()}var h,u}getEventHandlerInfosForElement(e,t){return e.hasOwnProperty(this.eventsCollectionKey)?e[this.eventsCollectionKey]:t?e[this.eventsCollectionKey]=new P:null}}x.nextEventDelegatorId=0;class R{constructor(e){this.globalListener=e,this.infosByEventHandlerId={},this.countByEventName={},a.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=k.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 P{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 U(e){const t={};return e.forEach((e=>{t[e]=!0})),t}const A=X("_blazorLogicalChildren"),N=X("_blazorLogicalParent"),$=X("_blazorLogicalEnd");function B(e,t){if(e.childNodes.length>0&&!t)throw new Error("New logical elements must start empty, or allowExistingContents must be true");return A in e||(e[A]=[]),e}function L(e,t){const n=document.createComment("!");return M(n,e,t),n}function M(e,t,n){const r=e;if(e instanceof Comment&&W(r)&&W(r).length>0)throw new Error("Not implemented: inserting non-empty logical container");if(F(r))throw new Error("Not implemented: moving existing logical children");const o=W(t);if(n0;)O(n,0)}const r=n;r.parentNode.removeChild(r)}function F(e){return e[N]||null}function H(e,t){return W(e)[t]}function j(e){var t=J(e);return"http://www.w3.org/2000/svg"===t.namespaceURI&&"foreignObject"!==t.tagName}function W(e){return e[A]}function z(e,t){const n=W(e);t.forEach((e=>{e.moveRangeStart=n[e.fromSiblingIndex],e.moveRangeEnd=K(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):V(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 J(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 q(e){const t=W(F(e));return t[Array.prototype.indexOf.call(t,e)+1]||null}function V(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=q(t);n?n.parentNode.insertBefore(e,n):V(e,F(t))}}}function K(e){if(e instanceof Element||e instanceof DocumentFragment)return e;const t=q(e);if(t)return t.previousSibling;{const t=F(e);return t instanceof Element||t instanceof DocumentFragment?t.lastChild:K(t)}}function X(e){return"function"==typeof Symbol?Symbol():e}function Y(e){return`_bl_${e}`}e.attachReviver(((e,t)=>t&&"object"==typeof t&&t.hasOwnProperty("__internalId")&&"string"==typeof t.__internalId?function(e){const t=`[${Y(e)}]`;return document.querySelector(t)}(t.__internalId):t));const G="_blazorDeferredValue",Q=document.createElement("template"),Z=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 x(e),this.eventDelegator.notifyAfterClick((e=>{if(!de)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;ewe(!1))))},enableNavigationInterception:function(){de=!0},navigateTo:me,getBaseURI:()=>document.baseURI,getLocationHref:()=>location.href};function me(e,t,n=!1){const r=be(e),o=t instanceof Object?t:{forceLoad:t,replaceHistoryEntry:n};!o.forceLoad&&Ee(r)?ye(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 ye(e,t,n){ue=!0,n?history.replaceState(null,"",e):history.pushState(null,"",e),we(t)}async function we(e){fe&&await fe(location.href,e)}let ve;function be(e){return ve=ve||document.createElement("a"),ve.href=e,ve.href}function _e(e,t){return e?e.tagName===t?e:_e(e.parentElement,t):null}function Ee(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=ke(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}Ie[e._id]={intersectionObserver:s,mutationObserverBefore:i,mutationObserverAfter:a}},dispose:function(e){const t=Ie[e._id];t&&(t.intersectionObserver.disconnect(),t.mutationObserverBefore.disconnect(),t.mutationObserverAfter.disconnect(),e.dispose(),delete Ie[e._id])}},Ie={};function ke(e){return e?"visible"!==getComputedStyle(e).overflowY?e:ke(e.parentElement):null}const Te={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!==F(s)||(null===n&&(n=o.textContent),null===(e=o.parentNode)||void 0===e||e.removeChild(o))}return n}},De={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=xe(e,t),i=await new Promise((function(e){const t=new Image;t.onload=function(){e(t)},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 xe(e,t).blob}};function xe(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 Re(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 Pe=new Map,Ue={navigateTo:me,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=s.get(t.browserEventName);n?n.push(e):s.set(t.browserEventName,[e]),a.forEach((n=>n(e,t.browserEventName)))}o.set(e,t)},rootComponents:w,_internal:{navigationManager:ge,domWrapper:Se,Virtualize:Ce,PageTitle:Te,InputFile:De,getJSDataStreamChunk:Re,receiveDotNetDataStream:function(t,n,r,o){let s=Pe.get(t);if(!s){const n=new ReadableStream({start(e){Pe.set(t,e),s=e}});e.jsCallDispatcher.supplyDotNetStream(t,n)}o?(s.error(o),Pe.delete(t)):0===r?(s.close(),Pe.delete(t)):s.enqueue(n.length===r?n:n.subarray(0,r))},attachWebRendererInterop:function(t,n,r,o){if(E.has(t))throw new Error(`Interop methods are already registered for renderer ${t}`);E.set(t,n),Object.keys(r).length>0&&function(t,n,r){if(g)throw new Error("Dynamic root components have already been enabled.");g=t,m=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=Ue;const Ae=[0,2e3,1e4,3e4,null];class Ne{constructor(e){this._retryDelays=void 0!==e?[...e,null]:Ae}nextRetryDelayInMilliseconds(e){return this._retryDelays[e.previousRetryCount]}}class $e extends Error{constructor(e,t){const n=new.target.prototype;super(`${e}: Status code '${t}'`),this.statusCode=t,this.__proto__=n}}class Be extends Error{constructor(e="A timeout occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Le extends Error{constructor(e="An abort occurred."){const t=new.target.prototype;super(e),this.__proto__=t}}class Me extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="UnsupportedTransportError",this.__proto__=n}}class Oe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="DisabledTransportError",this.__proto__=n}}class Fe extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.transport=t,this.errorType="FailedToStartTransportError",this.__proto__=n}}class He extends Error{constructor(e,t){const n=new.target.prototype;super(e),this.innerErrors=t,this.__proto__=n}}class je{constructor(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}}class We{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 ze,Je,qe,Ve,Ke;!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"}(ze||(ze={}));class Xe extends We{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),this._abortControllerType=e("abort-controller")}else this._fetchType=fetch.bind(self),this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new Le;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 Le});let r,o=null;if(e.timeout){const r=e.timeout;o=setTimeout((()=>{t.abort(),this._logger.log(ze.Warning,"Timeout from HTTP request."),n=new Be}),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(ze.Warning,`Error from HTTP request. ${e}.`),e}finally{o&&clearTimeout(o),e.abortSignal&&(e.abortSignal.onabort=null)}if(!r.ok){const e=await Ye(r,"text");throw new $e(e||r.statusText,r.status)}const s=Ye(r,e.responseType),i=await s;return new je(r.status,r.statusText,i)}getCookieString(e){return""}}function Ye(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 Ge extends We{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Le):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 Le)}),e.timeout&&(r.timeout=e.timeout),r.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),r.status>=200&&r.status<300?t(new je(r.status,r.statusText,r.response||r.responseText)):n(new $e(r.response||r.responseText||r.statusText,r.status))},r.onerror=()=>{this._logger.log(ze.Warning,`Error from HTTP request. ${r.status}: ${r.statusText}.`),n(new $e(r.statusText,r.status))},r.ontimeout=()=>{this._logger.log(ze.Warning,"Timeout from HTTP request."),n(new Be)},r.send(e.content||"")})):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}}class Qe extends We{constructor(e){if(super(),"undefined"!=typeof fetch)this._httpClient=new Xe(e);else{if("undefined"==typeof XMLHttpRequest)throw new Error("No usable HttpClient found.");this._httpClient=new Ge(e)}}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Le):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 Ze{}Ze.Authorization="Authorization",Ze.Cookie="Cookie",function(e){e[e.None=0]="None",e[e.WebSockets=1]="WebSockets",e[e.ServerSentEvents=2]="ServerSentEvents",e[e.LongPolling=4]="LongPolling"}(Je||(Je={})),function(e){e[e.Text=1]="Text",e[e.Binary=2]="Binary"}(qe||(qe={}));class et{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 tt{constructor(){}log(e,t){}}tt.instance=new tt;class nt{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 rt{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 ot(e,t){let n="";return st(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 st(e){return e&&"undefined"!=typeof ArrayBuffer&&(e instanceof ArrayBuffer||e.constructor&&"ArrayBuffer"===e.constructor.name)}async function it(e,t,n,r,o,s,i){let a={};if(o){const e=await o();e&&(a={Authorization:`Bearer ${e}`})}const[c,l]=lt();a[c]=l,e.log(ze.Trace,`(${t} transport) sending data. ${ot(s,i.logMessageContent)}.`);const h=st(s)?"arraybuffer":"text",u=await n.post(r,{content:s,headers:{...a,...i.headers},responseType:h,timeout:i.timeout,withCredentials:i.withCredentials});e.log(ze.Trace,`(${t} transport) request complete. Response status: ${u.statusCode}.`)}class at{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 ct{constructor(e){this._minLevel=e,this.out=console}log(e,t){if(e>=this._minLevel){const n=`[${(new Date).toISOString()}] ${ze[e]}: ${t}`;switch(e){case ze.Critical:case ze.Error:this.out.error(n);break;case ze.Warning:this.out.warn(n);break;case ze.Information:this.out.info(n);break;default:this.out.log(n)}}}}function lt(){let e="X-SignalR-User-Agent";return rt.isNode&&(e="User-Agent"),[e,ht("0.0.0-DEV_BUILD",ut(),rt.isNode?"NodeJS":"Browser",dt())]}function ht(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 ut(){if(!rt.isNode)return"";switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}function dt(){if(rt.isNode)return process.versions.node}function pt(e){return e.stack?e.stack:e.message?e.message:`${e}`}class ft{constructor(e,t,n,r){this._httpClient=e,this._accessTokenFactory=t,this._logger=n,this._pollAbort=new et,this._options=r,this._running=!1,this.onreceive=null,this.onclose=null}get pollAborted(){return this._pollAbort.aborted}async connect(e,t){if(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._url=e,this._logger.log(ze.Trace,"(LongPolling transport) Connecting."),t===qe.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]=lt(),o={[n]:r,...this._options.headers},s={abortSignal:this._pollAbort.signal,headers:o,timeout:1e5,withCredentials:this._options.withCredentials};t===qe.Binary&&(s.responseType="arraybuffer");const i=await this._getAccessToken();this._updateHeaderToken(s,i);const a=`${e}&_=${Date.now()}`;this._logger.log(ze.Trace,`(LongPolling transport) polling: ${a}.`);const c=await this._httpClient.get(a,s);200!==c.statusCode?(this._logger.log(ze.Error,`(LongPolling transport) Unexpected response code: ${c.statusCode}.`),this._closeError=new $e(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[Ze.Authorization]=`Bearer ${t}`:e.headers[Ze.Authorization]&&delete e.headers[Ze.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(ze.Trace,`(LongPolling transport) polling: ${n}.`);const r=await this._httpClient.get(n,t);204===r.statusCode?(this._logger.log(ze.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):200!==r.statusCode?(this._logger.log(ze.Error,`(LongPolling transport) Unexpected response code: ${r.statusCode}.`),this._closeError=new $e(r.statusText||"",r.statusCode),this._running=!1):r.content?(this._logger.log(ze.Trace,`(LongPolling transport) data received. ${ot(r.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(r.content)):this._logger.log(ze.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(e){this._running?e instanceof Be?this._logger.log(ze.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=e,this._running=!1):this._logger.log(ze.Trace,`(LongPolling transport) Poll errored after shutdown: ${e.message}`)}}}finally{this._logger.log(ze.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?it(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(ze.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(ze.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);const e={},[t,n]=lt();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(ze.Trace,"(LongPolling transport) DELETE request sent.")}finally{this._logger.log(ze.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(ze.Trace,e),this.onclose(this._closeError)}}}class gt{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(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._logger.log(ze.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===qe.Text){if(rt.isBrowser||rt.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]=lt();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(ze.Trace,`(SSE transport) data received. ${ot(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(ze.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?it(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 mt{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(nt.isRequired(e,"url"),nt.isRequired(t,"transferFormat"),nt.isIn(t,qe,"transferFormat"),this._logger.log(ze.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===qe.Binary&&(o.binaryType="arraybuffer"),o.onopen=t=>{this._logger.log(ze.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(ze.Information,`(WebSockets transport) ${t}.`)},o.onmessage=e=>{if(this._logger.log(ze.Trace,`(WebSockets transport) data received. ${ot(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(ze.Trace,`(WebSockets transport) sending data. ${ot(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(ze.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 yt{constructor(e,t={}){var n;if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,nt.isRequired(e,"url"),this._logger=void 0===(n=t.logger)?new ct(ze.Information):null===n?tt.instance:void 0!==n.log?n:new ct(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 Qe(this._logger),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=t,this.onreceive=null,this.onclose=null}async start(e){if(e=e||qe.Binary,nt.isIn(e,qe,"transferFormat"),this._logger.log(ze.Debug,`Starting connection with transfer format '${qe[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(ze.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(ze.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 wt(this.transport)),this._sendQueue.send(e))}async stop(e){return"Disconnected"===this._connectionState?(this._logger.log(ze.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve()):"Disconnecting"===this._connectionState?(this._logger.log(ze.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(ze.Error,`HttpConnection.transport.stop() threw error '${e}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(ze.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!==Je.WebSockets)throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");this.transport=this._constructTransport(Je.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 ft&&(this.features.inherentKeepAlive=!0),"Connecting"===this._connectionState&&(this._logger.log(ze.Debug,"The HttpConnection connected successfully."),this._connectionState="Connected")}catch(e){return this._logger.log(ze.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[Ze.Authorization]=`Bearer ${e}`)}const[n,r]=lt();t[n]=r;const o=this._resolveNegotiateUrl(e);this._logger.log(ze.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 $e&&404===e.statusCode&&(t+=" Either this is not a SignalR endpoint or there is a proxy blocking the connection."),this._logger.log(ze.Error,t),Promise.reject(new Error(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(ze.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(ze.Error,`Failed to start the transport '${n.transport}': ${e}`),a=void 0,s.push(new Fe(`${n.transport} failed: ${e}`,Je[n.transport])),"Connecting"!==this._connectionState){const e="Failed to select transport before stop() was called.";return this._logger.log(ze.Debug,e),Promise.reject(new Error(e))}}}}return s.length>0?Promise.reject(new He(`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 Je.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new mt(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case Je.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new gt(this._httpClient,this._accessTokenFactory,this._logger,this._options);case Je.LongPolling:return new ft(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=Je[e.transport];if(null==r)return this._logger.log(ze.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(ze.Debug,`Skipping transport '${Je[r]}' because it was disabled by the client.`),new Oe(`'${Je[r]}' is disabled by the client.`,r);if(!(e.transferFormats.map((e=>qe[e])).indexOf(n)>=0))return this._logger.log(ze.Debug,`Skipping transport '${Je[r]}' because it does not support the requested transfer format '${qe[n]}'.`),new Error(`'${Je[r]}' does not support ${qe[n]}.`);if(r===Je.WebSockets&&!this._options.WebSocket||r===Je.ServerSentEvents&&!this._options.EventSource)return this._logger.log(ze.Debug,`Skipping transport '${Je[r]}' because it is not supported in your environment.'`),new Me(`'${Je[r]}' is not supported in your environment.`,r);this._logger.log(ze.Debug,`Selecting transport '${Je[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(ze.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(ze.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(ze.Error,`Connection disconnected with error '${e}'.`):this._logger.log(ze.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch((e=>{this._logger.log(ze.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(ze.Error,`HttpConnection.onclose(${e}) threw error '${t}'.`)}}}else this._logger.log(ze.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(!rt.isBrowser||!window.document)throw new Error(`Cannot resolve '${e}'.`);const t=window.document.createElement("a");return t.href=e,this._logger.log(ze.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 wt{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new vt,this._transportResult=new vt,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new vt),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 vt;const e=this._transportResult;this._transportResult=void 0;const t="string"==typeof this._buffer[0]?this._buffer.join(""):wt._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 vt{constructor(){this.promise=new Promise(((e,t)=>[this._resolver,this._rejecter]=[e,t]))}resolve(){this._resolver()}reject(e){this._rejecter(e)}}class bt{static write(e){return`${e}${bt.RecordSeparator}`}static parse(e){if(e[e.length-1]!==bt.RecordSeparator)throw new Error("Message is incomplete.");const t=e.split(bt.RecordSeparator);return t.pop(),t}}bt.RecordSeparatorCode=30,bt.RecordSeparator=String.fromCharCode(bt.RecordSeparatorCode);class _t{writeHandshakeRequest(e){return bt.write(JSON.stringify(e))}parseHandshakeResponse(e){let t,n;if(st(e)){const r=new Uint8Array(e),o=r.indexOf(bt.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(bt.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=bt.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"}(Ve||(Ve={}));class Et{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 at(this,e)}}!function(e){e.Disconnected="Disconnected",e.Connecting="Connecting",e.Connected="Connected",e.Disconnecting="Disconnecting",e.Reconnecting="Reconnecting"}(Ke||(Ke={}));class St{constructor(e,t,n,r){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(ze.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")},nt.isRequired(e,"connection"),nt.isRequired(t,"logger"),nt.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=3e4,this.keepAliveIntervalInMilliseconds=15e3,this._logger=t,this._protocol=n,this.connection=e,this._reconnectPolicy=r,this._handshakeProtocol=new _t,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=Ke.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:Ve.Ping})}static create(e,t,n,r){return new St(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!==Ke.Disconnected&&this._connectionState!==Ke.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!==Ke.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=Ke.Connecting,this._logger.log(ze.Debug,"Starting HubConnection.");try{await this._startInternal(),rt.isBrowser&&document&&document.addEventListener("freeze",this._freezeEventListener),this._connectionState=Ke.Connected,this._connectionStarted=!0,this._logger.log(ze.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=Ke.Disconnected,this._logger.log(ze.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(ze.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(t)),this._logger.log(ze.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(ze.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===Ke.Disconnected?(this._logger.log(ze.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve()):this._connectionState===Ke.Disconnecting?(this._logger.log(ze.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise):(this._connectionState=Ke.Disconnecting,this._logger.log(ze.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(ze.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 Et;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===Ve.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===Ve.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 Ve.Invocation:this._invokeClientMethod(e);break;case Ve.StreamItem:case Ve.Completion:{const t=this._callbacks[e.invocationId];if(t){e.type===Ve.Completion&&delete this._callbacks[e.invocationId];try{t(e)}catch(e){this._logger.log(ze.Error,`Stream callback threw error: ${pt(e)}`)}}break}case Ve.Ping:break;case Ve.Close:{this._logger.log(ze.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(ze.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(ze.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(ze.Error,e);const n=new Error(e);throw this._handshakeRejecter(n),n}return this._logger.log(ze.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===Ke.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(ze.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(ze.Error,e),this._stopPromise=this._stopInternal(new Error(e))}}else this._logger.log(ze.Warning,`No client method with the name '${e.target}' found.`)}_connectionClosed(e){this._logger.log(ze.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===Ke.Disconnecting?this._completeClose(e):this._connectionState===Ke.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===Ke.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=Ke.Disconnected,this._connectionStarted=!1,rt.isBrowser&&document&&document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(ze.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(ze.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),void this._completeClose(e);if(this._connectionState=Ke.Reconnecting,e?this._logger.log(ze.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(ze.Information,"Connection reconnecting."),0!==this._reconnectingCallbacks.length){try{this._reconnectingCallbacks.forEach((t=>t.apply(this,[e])))}catch(t){this._logger.log(ze.Error,`An onreconnecting callback called with error '${e}' threw error '${t}'.`)}if(this._connectionState!==Ke.Reconnecting)return void this._logger.log(ze.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.")}for(;null!==o;){if(this._logger.log(ze.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!==Ke.Reconnecting)return void this._logger.log(ze.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");try{if(await this._startInternal(),this._connectionState=Ke.Connected,this._logger.log(ze.Information,"HubConnection reconnected successfully."),0!==this._reconnectedCallbacks.length)try{this._reconnectedCallbacks.forEach((e=>e.apply(this,[this.connection.connectionId])))}catch(e){this._logger.log(ze.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${e}'.`)}return}catch(e){if(this._logger.log(ze.Information,`Reconnect attempt failed because of error '${e}'.`),this._connectionState!==Ke.Reconnecting)return this._logger.log(ze.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),void(this._connectionState===Ke.Disconnecting&&this._completeClose());r=e instanceof Error?e:new Error(e.toString()),o=this._getNextRetryDelay(n++,Date.now()-t,r)}}this._logger.log(ze.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(ze.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(ze.Error,`Stream 'error' callback called with '${e}' threw error: ${pt(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:Ve.Invocation}:{arguments:t,target:e,type:Ve.Invocation};{const n=this._invocationId;return this._invocationId++,0!==r.length?{arguments:t,invocationId:n.toString(),streamIds:r,target:e,type:Ve.Invocation}:{arguments:t,invocationId:n.toString(),target:e,type:Ve.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 Bt,Lt=Rt?new TextDecoder:null,Mt=Rt?"undefined"!=typeof process&&"force"!==process.env.TEXT_DECODER?200:0:Tt,Ot=function(e,t){this.type=e,this.data=t},Ft=(Bt=function(e,t){return(Bt=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}Bt(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Ht=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 Ft(t,e),t}(Error),jt={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),Dt(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:xt(t,4),nsec:t.getUint32(0)};default:throw new Ht("Unrecognized data size for timestamp (expected 4, 8, or 12): "+e.length)}}(e);return new Date(1e3*t.sec+t.nsec/1e6)}},Wt=function(){function e(){this.builtInEncoders=[],this.builtInDecoders=[],this.encoders=[],this.decoders=[],this.register(jt)}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>At){var t=Pt(e);this.ensureBufferSizeToWrite(5+t),this.writeStringHeader(t),Nt(e,this.bytes,this.pos),this.pos+=t}else t=Pt(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=zt(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=$t(e,t,n),s=Uint8Array.prototype.slice.call(e,t,t+n);return this.store(s,o),o},e}(),Kt=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 Yt?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])}},Qt=new DataView(new ArrayBuffer(0)),Zt=new Uint8Array(Qt.buffer),en=function(){try{Qt.getInt8(0)}catch(e){return e.constructor}throw new Error("never reached")}(),tn=new en("Insufficient data"),nn=new Vt,rn=function(){function e(e,t,n,r,o,s,i,a){void 0===e&&(e=Wt.defaultCodec),void 0===t&&(t=void 0),void 0===n&&(n=Tt),void 0===r&&(r=Tt),void 0===o&&(o=Tt),void 0===s&&(s=Tt),void 0===i&&(i=Tt),void 0===a&&(a=nn),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=Qt,this.bytes=Zt,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=zt(e),this.view=function(e){if(e instanceof ArrayBuffer)return new DataView(e);var t=zt(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=zt(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 Kt(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 Kt(this,(function(p){switch(p.label){case 0:s=!1,p.label=1;case 1:p.trys.push([1,6,7,12]),t=Xt(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 en))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 "+qt(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 Gt(this,arguments,(function(){var n,r,o,s,i,a,c,l,h;return Kt(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=Xt(e),u.label=2;case 2:return[4,Yt(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,Yt(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 en))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,Yt(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 Ht("Unrecognized type byte: "+qt(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 Ht("The type of key must be string or number but "+typeof t);if("__proto__"===t)throw new Ht("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 Ht("Unrecognized array type byte: "+qt(e))}},e.prototype.pushMapState=function(e){if(e>this.maxMapLength)throw new Ht("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 Ht("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 Ht("Max length exceeded: UTF-8 byte length ("+e+") > maxStrLength ("+this.maxStrLength+")");if(this.bytes.byteLengthMt?function(e,t,n){var r=e.subarray(t,t+n);return Lt.decode(r)}(this.bytes,o,e):$t(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 Ht("Max length exceeded: bin length ("+e+") > maxBinLength ("+this.maxBinLength+")");if(!this.hasRemaining(e+t))throw tn;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 Ht("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=xt(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 on{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 sn=new Uint8Array([145,Ve.Ping]);class an{constructor(e){this.name="messagepack",this.version=1,this.transferFormat=qe.Binary,this._errorResult=1,this._voidResult=2,this._nonVoidResult=3,e=e||{},this._encoder=new Jt(e.extensionCodec,e.context,e.maxDepth,e.initialBufferSize,e.sortKeys,e.forceFloat32,e.ignoreUndefined,e.forceIntegerToFloat),this._decoder=new rn(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=tt.instance);const r=on.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 Ve.Invocation:return this._writeInvocation(e);case Ve.StreamInvocation:return this._writeStreamInvocation(e);case Ve.StreamItem:return this._writeStreamItem(e);case Ve.Completion:return this._writeCompletion(e);case Ve.Ping:return on.write(sn);case Ve.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 Ve.Invocation:return this._createInvocationMessage(this._readHeaders(n),n);case Ve.StreamItem:return this._createStreamItemMessage(this._readHeaders(n),n);case Ve.Completion:return this._createCompletionMessage(this._readHeaders(n),n);case Ve.Ping:return this._createPingMessage(n);case Ve.Close:return this._createCloseMessage(n);default:return t.log(ze.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:Ve.Close}}_createPingMessage(e){if(e.length<1)throw new Error("Invalid payload for Ping message.");return{type:Ve.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:Ve.Invocation}:{arguments:t[4],headers:e,streamIds:[],target:t[3],type:Ve.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:Ve.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:Ve.Completion}}_writeInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Ve.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments,e.streamIds]):this._encoder.encode([Ve.Invocation,e.headers||{},e.invocationId||null,e.target,e.arguments]),on.write(t.slice())}_writeStreamInvocation(e){let t;return t=e.streamIds?this._encoder.encode([Ve.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments,e.streamIds]):this._encoder.encode([Ve.StreamInvocation,e.headers||{},e.invocationId,e.target,e.arguments]),on.write(t.slice())}_writeStreamItem(e){const t=this._encoder.encode([Ve.StreamItem,e.headers||{},e.invocationId,e.item]);return on.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([Ve.Completion,e.headers||{},e.invocationId,t,e.error]);break;case this._voidResult:n=this._encoder.encode([Ve.Completion,e.headers||{},e.invocationId,t]);break;case this._nonVoidResult:n=this._encoder.encode([Ve.Completion,e.headers||{},e.invocationId,t,e.result])}return on.write(n.slice())}_writeCancelInvocation(e){const t=this._encoder.encode([Ve.CancelInvocation,e.headers||{},e.invocationId]);return on.write(t.slice())}_readHeaders(e){const t=e[1];if("object"!=typeof t)throw new Error("Invalid headers.");return t}}let cn=!1;async function ln(e=""){let t=document.querySelector("#blazor-error-ui");t&&(t.style.display="block",e&&t.firstChild&&(t.firstChild.textContent=`\n\t${e}\t\n`)),cn||(cn=!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 hn="function"==typeof TextDecoder?new TextDecoder("utf-8"):null,un=hn?hn.decode.bind(hn):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("")},dn=Math.pow(2,32),pn=Math.pow(2,21)-1;function fn(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function gn(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function mn(e,t){const n=gn(e,t+4);if(n>pn)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*dn+gn(e,t)}class yn{constructor(e){this.batchData=e;const t=new _n(e);this.arrayRangeReader=new En(e),this.arrayBuilderSegmentReader=new Sn(e),this.diffReader=new wn(e),this.editReader=new vn(e,t),this.frameReader=new bn(e,t)}updatedComponents(){return fn(this.batchData,this.batchData.length-20)}referenceFrames(){return fn(this.batchData,this.batchData.length-16)}disposedComponentIds(){return fn(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return fn(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return fn(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return fn(this.batchData,n)}disposedEventHandlerIdsEntry(e,t){const n=e+8*t;return mn(this.batchData,n)}}class wn{constructor(e){this.batchDataUint8=e}componentId(e){return fn(this.batchDataUint8,e)}edits(e){return e+4}editsEntry(e,t){return e+16*t}}class vn{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}editType(e){return fn(this.batchDataUint8,e)}siblingIndex(e){return fn(this.batchDataUint8,e+4)}newTreeIndex(e){return fn(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return fn(this.batchDataUint8,e+8)}removedAttributeName(e){const t=fn(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class bn{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return fn(this.batchDataUint8,e)}subtreeLength(e){return fn(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return fn(this.batchDataUint8,e+8)}elementName(e){const t=fn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=fn(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=fn(this.batchDataUint8,e+8);return this.stringReader.readString(t)}attributeEventHandlerId(e){return mn(this.batchDataUint8,e+12)}}class _n{constructor(e){this.batchDataUint8=e,this.stringTableStartIndex=fn(e,e.length-4)}readString(e){if(-1===e)return null;{const n=fn(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(Cn.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(Cn.Debug,`Waiting for batch ${this.nextBatchId}. Batch ${e} not processed.`);try{this.nextBatchId++,this.logger.log(Cn.Debug,`Applying batch ${e}.`),function(e,t){const n=he[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()}] ${Cn[e]}: ${t}`;switch(e){case Cn.Critical:case Cn.Error:console.error(n);break;case Cn.Warning:console.warn(n);break;case Cn.Information:console.info(n);break;default:console.log(n)}}}}class Dn{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!==Ke.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!==Ke.Connected)return!1;const t=await e.invoke("StartCircuit",ge.getBaseURI(),ge.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=f.get(e);if(t)return f.delete(e),t}(e);if(t)return B(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=B(n,!0),o=W(r);return Array.from(n.childNodes).forEach((e=>o.push(e))),e[N]=r,t&&(e[$]=t,B(t)),B(e)}(this.components[n].start,this.components[n].end);throw new Error(`Invalid sequence number or identifier '${e}'.`)}}const xn={configureSignalR:e=>{},logLevel:Cn.Warning,reconnectionOptions:{maxRetries:8,retryIntervalMilliseconds:2e4,dialogId:"components-reconnect-modal"}};class Rn{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(null==Ue?void 0:Ue.reconnect)()||this.rejected()}catch(e){this.logger.log(Cn.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 Pn{constructor(e,t,n){this.dialog=e,this.maxRetries=t,this.document=n,this.document=n;const r=this.document.getElementById(Pn.MaxRetriesId);r&&(r.innerText=this.maxRetries.toString())}show(){this.removeClasses(),this.dialog.classList.add(Pn.ShowClassName)}update(e){const t=this.document.getElementById(Pn.CurrentAttemptId);t&&(t.innerText=e.toString())}hide(){this.removeClasses(),this.dialog.classList.add(Pn.HideClassName)}failed(){this.removeClasses(),this.dialog.classList.add(Pn.FailedClassName)}rejected(){this.removeClasses(),this.dialog.classList.add(Pn.RejectedClassName)}removeClasses(){this.dialog.classList.remove(Pn.ShowClassName,Pn.HideClassName,Pn.FailedClassName,Pn.RejectedClassName)}}Pn.ShowClassName="components-reconnect-show",Pn.HideClassName="components-reconnect-hide",Pn.FailedClassName="components-reconnect-failed",Pn.RejectedClassName="components-reconnect-rejected",Pn.MaxRetriesId="components-reconnect-max-retries",Pn.CurrentAttemptId="components-reconnect-current-attempt";class Un{constructor(e,t,n){this._currentReconnectionProcess=null,this._logger=e,this._reconnectionDisplay=t,this._reconnectCallback=n||(()=>Ue.reconnect())}onConnectionDown(e,t){if(!this._reconnectionDisplay){const t=document.getElementById(e.dialogId);this._reconnectionDisplay=t?new Pn(t,e.maxRetries,document):new Rn(e.dialogId,e.maxRetries,document,this._logger)}this._currentReconnectionProcess||(this._currentReconnectionProcess=new An(e,this._logger,this._reconnectCallback,this._reconnectionDisplay))}onConnectionUp(){this._currentReconnectionProcess&&(this._currentReconnectionProcess.dispose(),this._currentReconnectionProcess=null)}}class An{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;tAn.MaximumFirstRetryInterval?An.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(Cn.Error,e)}}this.reconnectDisplay.failed()}delay(e){return new Promise((t=>setTimeout(t,e)))}}An.MaximumFirstRetryInterval=3e3;const Nn=/^\s*Blazor-Component-State:(?[a-zA-Z0-9\+\/=]+)$/;function $n(e){var t;if(e.nodeType===Node.COMMENT_NODE){const n=e.textContent||"",r=Nn.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 Mn(e,t){const n=e.currentElement;if(n&&n.nodeType===Node.COMMENT_NODE&&n.textContent){const r=Ln.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=On(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=On(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 On(e,t){for(;t.next()&&t.currentElement;){const n=t.currentElement;if(n.nodeType!==Node.COMMENT_NODE)continue;if(!n.textContent)continue;const r=Ln.exec(n.textContent),o=r&&r[1];if(o)return Fn(o,e),n}}function Fn(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 Hn{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 Jn=!1,qn=!1;async function Vn(e){if(qn)throw new Error("Blazor has already started.");qn=!0;const t=function(e){const t={...xn,...e};return e&&e.reconnectionOptions&&(t.reconnectionOptions={...xn.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 zn;return await r.importInitializersAsync(n,[e]),r}(t),r=new Tn(t.logLevel);Ue.defaultReconnectionHandler=new Un(r),t.reconnectionHandler=t.reconnectionHandler||Ue.defaultReconnectionHandler,r.log(Cn.Information,"Starting up Blazor server-side application.");const o=function(e,t){return function(e){const t=Bn(e,"server"),n=[];for(let e=0;ee.sequence-t.sequence))}(e)}(document),s=$n(document),i=new Dn(o,s||""),a=await Kn(t,r,i);if(!await i.startCircuit(a))return void r.log(Cn.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)}};Ue.disconnect=l,window.addEventListener("unload",l,{capture:!1,once:!0}),Ue.reconnect=async e=>{if(Jn)return!1;const n=e||await Kn(t,r,i);return await i.reconnect(n)?(t.reconnectionHandler.onConnectionUp(),!0):(r.log(Cn.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)},r.log(Cn.Information,"Blazor server-side application started."),n.invokeAfterStartedCallbacks(Ue)}async function Kn(t,n,r){const o=new an;o.name="blazorpack";const s=(new kt).withUrl("_blazor",Je.WebSockets).withHubProtocol(o);t.configureSignalR(s);const i=s.build();Ue._internal.navigationManager.listenForNavigationEvents(((e,t)=>i.send("OnLocationChanged",e,t))),i.on("JS.AttachComponent",((e,t)=>function(e,t,n,r){let o=he[0];o||(o=he[0]=new oe(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=In.getOrCreate(n);i.on("JS.RenderBatch",((e,t)=>{n.log(Cn.Debug,`Received render batch with id ${e} and ${t.byteLength} bytes.`),a.processBatch(e,t,i)})),i.onclose((e=>!Jn&&t.reconnectionHandler.onConnectionDown(t.reconnectionOptions,e))),i.on("JS.Error",(e=>{Jn=!0,Xn(i,e,n),ln()})),Ue._internal.forceCloseConnection=()=>i.stop(),Ue._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){Xn(i,e,n),e.innerErrors&&e.innerErrors.some((e=>"UnsupportedTransportError"===e.errorType&&e.transport===Je.WebSockets))?ln("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===Je.WebSockets))?ln("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===Je.LongPolling))?(n.log(Cn.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."),ln()):ln()}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 Xn(e,t,n){n.log(Cn.Error,t),e&&e.stop()}Ue.start=Vn,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&Vn()})(); \ 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 0b09560ad7a2..ab6e66d75bc9 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"}(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);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=W("_blazorLogicalChildren"),x=W("_blazorLogicalParent"),P=W("_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 F in e||(e[F]=[]),e}function M(e,t){const n=document.createComment("!");return j(n,e,t),n}function j(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=Y(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):X(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 X(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):X(e,H(t))}}}function Y(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:Y(t)}}function W(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(){e(t)},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("")},Pe=Math.pow(2,32),Le=Math.pow(2,21)-1;function Me(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function je(e,t){return e[t]+(e[t+1]<<8)+(e[t+2]<<16)+(e[t+3]<<24>>>0)}function Be(e,t){const n=je(e,t+4);if(n>Le)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*Pe+je(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 Me(this.batchData,this.batchData.length-20)}referenceFrames(){return Me(this.batchData,this.batchData.length-16)}disposedComponentIds(){return Me(this.batchData,this.batchData.length-12)}disposedEventHandlerIds(){return Me(this.batchData,this.batchData.length-8)}updatedComponentsEntry(e,t){const n=e+4*t;return Me(this.batchData,n)}referenceFramesEntry(e,t){return e+20*t}disposedComponentIdsEntry(e,t){const n=e+4*t;return Me(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 Me(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 Me(this.batchDataUint8,e)}siblingIndex(e){return Me(this.batchDataUint8,e+4)}newTreeIndex(e){return Me(this.batchDataUint8,e+8)}moveToSiblingIndex(e){return Me(this.batchDataUint8,e+8)}removedAttributeName(e){const t=Me(this.batchDataUint8,e+12);return this.stringReader.readString(t)}}class $e{constructor(e,t){this.batchDataUint8=e,this.stringReader=t}frameType(e){return Me(this.batchDataUint8,e)}subtreeLength(e){return Me(this.batchDataUint8,e+4)}elementReferenceCaptureId(e){const t=Me(this.batchDataUint8,e+4);return this.stringReader.readString(t)}componentId(e){return Me(this.batchDataUint8,e+8)}elementName(e){const t=Me(this.batchDataUint8,e+8);return this.stringReader.readString(t)}textContent(e){const t=Me(this.batchDataUint8,e+4);return this.stringReader.readString(t)}markupContent(e){const t=Me(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeName(e){const t=Me(this.batchDataUint8,e+4);return this.stringReader.readString(t)}attributeValue(e){const t=Me(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=Me(e,e.length-4)}readString(e){if(-1===e)return null;{const n=Me(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)<{!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,L(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{Ye=!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(Ye||!e||!e.startsWith(Xe))return null;const t=e.substring(Xe.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())}_e.start=ot,document&&document.currentScript&&"false"!==document.currentScript.getAttribute("autostart")&&ot()})(); \ 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"}(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);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=W("_blazorLogicalChildren"),x=W("_blazorLogicalParent"),P=W("_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 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=Y(e.moveRangeStart)})),t.forEach((t=>{const r=t.moveToBeforeMarker=document.createComment("marker"),o=n[t.toSiblingIndex+1];o?o.parentNode.insertBefore(r,o):X(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 X(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):X(e,H(t))}}}function Y(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:Y(t)}}function W(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(){e(t)},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("")},Pe=Math.pow(2,32),Le=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>Le)throw new Error(`Cannot read uint64 with high order part ${n}, because the result would exceed Number.MAX_SAFE_INTEGER.`);return n*Pe+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,L(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{Ye=!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(Ye||!e||!e.startsWith(Xe))return null;const t=e.substring(Xe.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/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs b/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs index 893bc9208f10..ce0ea19de6ed 100644 --- a/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs +++ b/src/Mvc/Mvc.Core/src/Infrastructure/ConfigureCompatibilityOptions.cs @@ -88,7 +88,7 @@ private void ConfigureSwitch(ICompatibilitySwitch @switch, IReadOnlyDictionary Date: Mon, 16 Aug 2021 13:35:50 -0700 Subject: [PATCH 27/27] Update identity tests --- .../Infrastructure/ServerFactory.cs | 59 ------------------- 1 file changed, 59 deletions(-) diff --git a/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs b/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs index 912e817dca9d..de41e17e4ad3 100644 --- a/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs +++ b/src/Identity/test/Identity.FunctionalTests/Infrastructure/ServerFactory.cs @@ -57,71 +57,12 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) .AddCookieTempDataProvider(o => o.Cookie.IsEssential = true); }); - UpdateStaticAssets(builder); UpdateApplicationParts(builder); } private void UpdateApplicationParts(IWebHostBuilder builder) => builder.ConfigureServices(services => AddRelatedParts(services, BootstrapFrameworkVersion)); - private void UpdateStaticAssets(IWebHostBuilder builder) - { - var manifestPath = Path.GetDirectoryName(typeof(ServerFactory<,>).Assembly.Location); - builder.ConfigureAppConfiguration((ctx, cb) => - { - if (ctx.HostingEnvironment.WebRootFileProvider is CompositeFileProvider composite) - { - var originalWebRoot = composite.FileProviders.First(); - ctx.HostingEnvironment.WebRootFileProvider = originalWebRoot; - } - }); - - string versionedPath = Path.Combine(manifestPath, $"Testing.DefaultWebSite.StaticWebAssets.{BootstrapFrameworkVersion}.xml"); - UpdateManifest(versionedPath); - - builder.ConfigureAppConfiguration((context, configBuilder) => - { - using (var manifest = File.OpenRead(versionedPath)) - { - typeof(StaticWebAssetsLoader) - .GetMethod("UseStaticWebAssetsCore", BindingFlags.NonPublic | BindingFlags.Static) - .Invoke(null, new object[] { context.HostingEnvironment, manifest, false }); - } - }); - } - - private void UpdateManifest(string versionedPath) - { - var content = File.ReadAllText(versionedPath); - var path = typeof(ServerFactory<,>).Assembly.GetCustomAttributes() - .Single(a => a.Key == "Microsoft.AspNetCore.Testing.IdentityUIProjectPath").Value; - - path = Directory.Exists(path) ? Path.Combine(path, "wwwroot") : Path.Combine(FindHelixSlnFileDirectory(), "UI", "wwwroot"); - - var updatedContent = content.Replace("{TEST_PLACEHOLDER}", path); - - File.WriteAllText(versionedPath, updatedContent); - } - - private string FindHelixSlnFileDirectory() - { - var applicationPath = Path.GetDirectoryName(typeof(ServerFactory<,>).Assembly.Location); - var directoryInfo = new DirectoryInfo(applicationPath); - do - { - var solutionPath = Directory.EnumerateFiles(directoryInfo.FullName, "*.sln").FirstOrDefault(); - if (solutionPath != null) - { - return directoryInfo.FullName; - } - - directoryInfo = directoryInfo.Parent; - } - while (directoryInfo.Parent != null); - - throw new InvalidOperationException($"Solution root could not be located using application root {applicationPath}."); - } - protected override IHost CreateHost(IHostBuilder builder) { var result = base.CreateHost(builder);