diff --git a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
index 45517fe25b..bba793cc09 100644
--- a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
+++ b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
@@ -22,8 +22,7 @@
-
-
+
diff --git a/src/Web/Avalonia.Blazor/AssetLoader.cs b/src/Web/Avalonia.Blazor/AssetLoader.cs
index 40c5a962c0..724b51dfd0 100644
--- a/src/Web/Avalonia.Blazor/AssetLoader.cs
+++ b/src/Web/Avalonia.Blazor/AssetLoader.cs
@@ -395,4 +395,4 @@ namespace Avalonia.Blazor
GenericUriParserOptions.NoFragment), "avares", -1);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Web/Avalonia.Blazor/Avalonia.Blazor.csproj b/src/Web/Avalonia.Blazor/Avalonia.Blazor.csproj
index 402d62d209..dab505087f 100644
--- a/src/Web/Avalonia.Blazor/Avalonia.Blazor.csproj
+++ b/src/Web/Avalonia.Blazor/Avalonia.Blazor.csproj
@@ -12,9 +12,13 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/extras.d.ts b/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/extras.d.ts
new file mode 100644
index 0000000000..4a3d71e034
--- /dev/null
+++ b/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/extras.d.ts
@@ -0,0 +1,7 @@
+
+declare namespace DotNet {
+ interface DotNetObjectReference extends DotNet.DotNetObject {
+ _id: number;
+ dispose();
+ }
+}
diff --git a/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/index.d.ts b/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/index.d.ts
new file mode 100644
index 0000000000..ff6dc4a8f8
--- /dev/null
+++ b/src/Web/Avalonia.Blazor/wwwroot/types/dotnet/index.d.ts
@@ -0,0 +1,56 @@
+// Type definitions for non-npm package @blazor/javascript-interop 3.1
+// Project: https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.1
+// Definitions by: Piotr Błażejewicz (Peter Blazejewicz)
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// Minimum TypeScript Version: 3.0
+
+// Here be dragons!
+// This is community-maintained definition file intended to ease the process of developing
+// high quality JavaScript interop code to be used in Blazor application from your C# .Net code.
+// Could be removed without a notice in case official definition types ships with Blazor itself.
+
+// tslint:disable:no-unnecessary-generics
+
+declare namespace DotNet {
+ /**
+ * Invokes the specified .NET public method synchronously. Not all hosting scenarios support
+ * synchronous invocation, so if possible use invokeMethodAsync instead.
+ *
+ * @param assemblyName The short name (without key/version or .dll extension) of the .NET assembly containing the method.
+ * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
+ * @param args Arguments to pass to the method, each of which must be JSON-serializable.
+ * @returns The result of the operation.
+ */
+ function invokeMethod(assemblyName: string, methodIdentifier: string, ...args: any[]): T;
+ /**
+ * Invokes the specified .NET public method asynchronously.
+ *
+ * @param assemblyName The short name (without key/version or .dll extension) of the .NET assembly containing the method.
+ * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
+ * @param args Arguments to pass to the method, each of which must be JSON-serializable.
+ * @returns A promise representing the result of the operation.
+ */
+ function invokeMethodAsync(assemblyName: string, methodIdentifier: string, ...args: any[]): Promise;
+ /**
+ * Represents the .NET instance passed by reference to JavaScript.
+ */
+ interface DotNetObject {
+ /**
+ * Invokes the specified .NET instance public method synchronously. Not all hosting scenarios support
+ * synchronous invocation, so if possible use invokeMethodAsync instead.
+ *
+ * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
+ * @param args Arguments to pass to the method, each of which must be JSON-serializable.
+ * @returns The result of the operation.
+ */
+ invokeMethod(methodIdentifier: string, ...args: any[]): T;
+ /**
+ * Invokes the specified .NET instance public method asynchronously.
+ *
+ * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
+ * @param args Arguments to pass to the method, each of which must be JSON-serializable.
+ * @returns A promise representing the result of the operation.
+ */
+ invokeMethodAsync(methodIdentifier: string, ...args: any[]): Promise;
+ }
+}
diff --git a/src/Web/Avalonia.Blazor/wwwroot/types/emscripten/index.d.ts b/src/Web/Avalonia.Blazor/wwwroot/types/emscripten/index.d.ts
new file mode 100644
index 0000000000..e3829d4db1
--- /dev/null
+++ b/src/Web/Avalonia.Blazor/wwwroot/types/emscripten/index.d.ts
@@ -0,0 +1,326 @@
+// Type definitions for Emscripten 1.39.16
+// Project: https://emscripten.org
+// Definitions by: Kensuke Matsuzaki
+// Periklis Tsirakidis
+// Bumsik Kim
+// Louis DeScioli
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.2
+
+/** Other WebAssembly declarations, for compatibility with older versions of Typescript */
+declare namespace WebAssembly {
+ interface Module {}
+}
+
+declare namespace Emscripten {
+ interface FileSystemType {}
+ type EnvironmentType = 'WEB' | 'NODE' | 'SHELL' | 'WORKER';
+
+ type JSType = 'number' | 'string' | 'array' | 'boolean';
+ type TypeCompatibleWithC = number | string | any[] | boolean;
+
+ type CIntType = 'i8' | 'i16' | 'i32' | 'i64';
+ type CFloatType = 'float' | 'double';
+ type CPointerType = 'i8*' | 'i16*' | 'i32*' | 'i64*' | 'float*' | 'double*' | '*';
+ type CType = CIntType | CFloatType | CPointerType;
+
+ type WebAssemblyImports = Array<{
+ name: string;
+ kind: string;
+ }>;
+
+ type WebAssemblyExports = Array<{
+ module: string;
+ name: string;
+ kind: string;
+ }>;
+
+ interface CCallOpts {
+ async?: boolean | undefined;
+ }
+}
+
+interface EmscriptenModule {
+ print(str: string): void;
+ printErr(str: string): void;
+ arguments: string[];
+ environment: Emscripten.EnvironmentType;
+ preInit: Array<{ (): void }>;
+ preRun: Array<{ (): void }>;
+ postRun: Array<{ (): void }>;
+ onAbort: { (what: any): void };
+ onRuntimeInitialized: { (): void };
+ preinitializedWebGLContext: WebGLRenderingContext;
+ noInitialRun: boolean;
+ noExitRuntime: boolean;
+ logReadFiles: boolean;
+ filePackagePrefixURL: string;
+ wasmBinary: ArrayBuffer;
+
+ destroy(object: object): void;
+ getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer;
+ instantiateWasm(
+ imports: Emscripten.WebAssemblyImports,
+ successCallback: (module: WebAssembly.Module) => void,
+ ): Emscripten.WebAssemblyExports;
+ locateFile(url: string, scriptDirectory: string): string;
+ onCustomMessage(event: MessageEvent): void;
+
+ // USE_TYPED_ARRAYS == 1
+ HEAP: Int32Array;
+ IHEAP: Int32Array;
+ FHEAP: Float64Array;
+
+ // USE_TYPED_ARRAYS == 2
+ HEAP8: Int8Array;
+ HEAP16: Int16Array;
+ HEAP32: Int32Array;
+ HEAPU8: Uint8Array;
+ HEAPU16: Uint16Array;
+ HEAPU32: Uint32Array;
+ HEAPF32: Float32Array;
+ HEAPF64: Float64Array;
+
+ TOTAL_STACK: number;
+ TOTAL_MEMORY: number;
+ FAST_MEMORY: number;
+
+ addOnPreRun(cb: () => any): void;
+ addOnInit(cb: () => any): void;
+ addOnPreMain(cb: () => any): void;
+ addOnExit(cb: () => any): void;
+ addOnPostRun(cb: () => any): void;
+
+ preloadedImages: any;
+ preloadedAudios: any;
+
+ _malloc(size: number): number;
+ _free(ptr: number): void;
+}
+
+/**
+ * A factory function is generated when setting the `MODULARIZE` build option
+ * to `1` in your Emscripten build. It return a Promise that resolves to an
+ * initialized, ready-to-call `EmscriptenModule` instance.
+ *
+ * By default, the factory function will be named `Module`. It's recommended to
+ * use the `EXPORT_ES6` option, in which the factory function will be the
+ * default export. If used without `EXPORT_ES6`, the factory function will be a
+ * global variable. You can rename the variable using the `EXPORT_NAME` build
+ * option. It's left to you to declare any global variables as needed in your
+ * application's types.
+ * @param moduleOverrides Default properties for the initialized module.
+ */
+type EmscriptenModuleFactory = (
+ moduleOverrides?: Partial,
+) => Promise;
+
+declare namespace FS {
+ interface Lookup {
+ path: string;
+ node: FSNode;
+ }
+
+ interface FSStream {}
+ interface FSNode {}
+ interface ErrnoError {}
+
+ let ignorePermissions: boolean;
+ let trackingDelegate: any;
+ let tracking: any;
+ let genericErrors: any;
+
+ //
+ // paths
+ //
+ function lookupPath(path: string, opts: any): Lookup;
+ function getPath(node: FSNode): string;
+
+ //
+ // nodes
+ //
+ function isFile(mode: number): boolean;
+ function isDir(mode: number): boolean;
+ function isLink(mode: number): boolean;
+ function isChrdev(mode: number): boolean;
+ function isBlkdev(mode: number): boolean;
+ function isFIFO(mode: number): boolean;
+ function isSocket(mode: number): boolean;
+
+ //
+ // devices
+ //
+ function major(dev: number): number;
+ function minor(dev: number): number;
+ function makedev(ma: number, mi: number): number;
+ function registerDevice(dev: number, ops: any): void;
+
+ //
+ // core
+ //
+ function syncfs(populate: boolean, callback: (e: any) => any): void;
+ function syncfs(callback: (e: any) => any, populate?: boolean): void;
+ function mount(type: Emscripten.FileSystemType, opts: any, mountpoint: string): any;
+ function unmount(mountpoint: string): void;
+
+ function mkdir(path: string, mode?: number): any;
+ function mkdev(path: string, mode?: number, dev?: number): any;
+ function symlink(oldpath: string, newpath: string): any;
+ function rename(old_path: string, new_path: string): void;
+ function rmdir(path: string): void;
+ function readdir(path: string): any;
+ function unlink(path: string): void;
+ function readlink(path: string): string;
+ function stat(path: string, dontFollow?: boolean): any;
+ function lstat(path: string): any;
+ function chmod(path: string, mode: number, dontFollow?: boolean): void;
+ function lchmod(path: string, mode: number): void;
+ function fchmod(fd: number, mode: number): void;
+ function chown(path: string, uid: number, gid: number, dontFollow?: boolean): void;
+ function lchown(path: string, uid: number, gid: number): void;
+ function fchown(fd: number, uid: number, gid: number): void;
+ function truncate(path: string, len: number): void;
+ function ftruncate(fd: number, len: number): void;
+ function utime(path: string, atime: number, mtime: number): void;
+ function open(path: string, flags: string, mode?: number, fd_start?: number, fd_end?: number): FSStream;
+ function close(stream: FSStream): void;
+ function llseek(stream: FSStream, offset: number, whence: number): any;
+ function read(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number): number;
+ function write(
+ stream: FSStream,
+ buffer: ArrayBufferView,
+ offset: number,
+ length: number,
+ position?: number,
+ canOwn?: boolean,
+ ): number;
+ function allocate(stream: FSStream, offset: number, length: number): void;
+ function mmap(
+ stream: FSStream,
+ buffer: ArrayBufferView,
+ offset: number,
+ length: number,
+ position: number,
+ prot: number,
+ flags: number,
+ ): any;
+ function ioctl(stream: FSStream, cmd: any, arg: any): any;
+ function readFile(path: string, opts: { encoding: 'binary'; flags?: string | undefined }): Uint8Array;
+ function readFile(path: string, opts: { encoding: 'utf8'; flags?: string | undefined }): string;
+ function readFile(path: string, opts?: { flags?: string | undefined }): Uint8Array;
+ function writeFile(path: string, data: string | ArrayBufferView, opts?: { flags?: string | undefined }): void;
+
+ //
+ // module-level FS code
+ //
+ function cwd(): string;
+ function chdir(path: string): void;
+ function init(
+ input: null | (() => number | null),
+ output: null | ((c: number) => any),
+ error: null | ((c: number) => any),
+ ): void;
+
+ function createLazyFile(
+ parent: string | FSNode,
+ name: string,
+ url: string,
+ canRead: boolean,
+ canWrite: boolean,
+ ): FSNode;
+ function createPreloadedFile(
+ parent: string | FSNode,
+ name: string,
+ url: string,
+ canRead: boolean,
+ canWrite: boolean,
+ onload?: () => void,
+ onerror?: () => void,
+ dontCreateFile?: boolean,
+ canOwn?: boolean,
+ ): void;
+ function createDataFile(
+ parent: string | FSNode,
+ name: string,
+ data: ArrayBufferView,
+ canRead: boolean,
+ canWrite: boolean,
+ canOwn: boolean,
+ ): FSNode;
+}
+
+declare var MEMFS: Emscripten.FileSystemType;
+declare var NODEFS: Emscripten.FileSystemType;
+declare var IDBFS: Emscripten.FileSystemType;
+
+// Below runtime function/variable declarations are exportable by
+// -s EXTRA_EXPORTED_RUNTIME_METHODS. You can extend or merge
+// EmscriptenModule interface to add runtime functions.
+//
+// For example, by using -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']"
+// You can access ccall() via Module["ccall"]. In this case, you should
+// extend EmscriptenModule to pass the compiler check like the following:
+//
+// interface YourOwnEmscriptenModule extends EmscriptenModule {
+// ccall: typeof ccall;
+// }
+//
+// See: https://emscripten.org/docs/getting_started/FAQ.html#why-do-i-get-typeerror-module-something-is-not-a-function
+
+declare function ccall(
+ ident: string,
+ returnType: Emscripten.JSType | null,
+ argTypes: Emscripten.JSType[],
+ args: Emscripten.TypeCompatibleWithC[],
+ opts?: Emscripten.CCallOpts,
+): any;
+declare function cwrap(
+ ident: string,
+ returnType: Emscripten.JSType | null,
+ argTypes: Emscripten.JSType[],
+ opts?: Emscripten.CCallOpts,
+): (...args: any[]) => any;
+
+declare function setValue(ptr: number, value: any, type: Emscripten.CType, noSafe?: boolean): void;
+declare function getValue(ptr: number, type: Emscripten.CType, noSafe?: boolean): number;
+
+declare function allocate(
+ slab: number[] | ArrayBufferView | number,
+ types: Emscripten.CType | Emscripten.CType[],
+ allocator: number,
+ ptr?: number,
+): number;
+
+declare function stackAlloc(size: number): number;
+declare function stackSave(): number;
+declare function stackRestore(ptr: number): void;
+
+declare function UTF8ToString(ptr: number, maxBytesToRead?: number): string;
+declare function stringToUTF8(str: string, outPtr: number, maxBytesToRead?: number): void;
+declare function lengthBytesUTF8(str: string): number;
+declare function allocateUTF8(str: string): number;
+declare function allocateUTF8OnStack(str: string): number;
+declare function UTF16ToString(ptr: number): string;
+declare function stringToUTF16(str: string, outPtr: number, maxBytesToRead?: number): void;
+declare function lengthBytesUTF16(str: string): number;
+declare function UTF32ToString(ptr: number): string;
+declare function stringToUTF32(str: string, outPtr: number, maxBytesToRead?: number): void;
+declare function lengthBytesUTF32(str: string): number;
+
+declare function intArrayFromString(stringy: string, dontAddNull?: boolean, length?: number): number[];
+declare function intArrayToString(array: number[]): string;
+declare function writeStringToMemory(str: string, buffer: number, dontAddNull: boolean): void;
+declare function writeArrayToMemory(array: number[], buffer: number): void;
+declare function writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void;
+
+declare function addRunDependency(id: any): void;
+declare function removeRunDependency(id: any): void;
+
+declare function addFunction(func: (...args: any[]) => any, signature?: string): number;
+declare function removeFunction(funcPtr: number): void;
+
+declare var ALLOC_NORMAL: number;
+declare var ALLOC_STACK: number;
+declare var ALLOC_STATIC: number;
+declare var ALLOC_DYNAMIC: number;
+declare var ALLOC_NONE: number;