diff --git a/Avalonia.sln b/Avalonia.sln
index 35b6b2108a..228052c2d5 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -212,7 +212,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.ColorPick
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{EABE2161-989B-42BF-BD8D-1E34B20C21F1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevGenerators", "src\tools\DevGenerators\DevGenerators.csproj", "{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevGenerators", "src\tools\DevGenerators\DevGenerators.csproj", "{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web", "src\Web\Avalonia.Web\Avalonia.Web.csproj", "{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Sample", "src\Web\Avalonia.Web.Sample\Avalonia.Web.Sample.csproj", "{1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -502,6 +506,14 @@ Global
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -545,6 +557,7 @@ Global
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+ {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@@ -559,7 +572,8 @@ Global
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
- {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
+ {76D39FF6-6B4F-46C4-93CD-E6FC4665739E} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
+ {1F61B6F1-B881-4E27-A5B0-09D1F543F7AC} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/global.json b/global.json
index a6792b05c7..44d4e10dbf 100644
--- a/global.json
+++ b/global.json
@@ -1,8 +1,4 @@
{
- "sdk": {
- "version": "6.0.202",
- "rollForward": "latestFeature"
- },
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
"MSBuild.Sdk.Extras": "3.0.22",
diff --git a/src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj b/src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj
new file mode 100644
index 0000000000..8f5912a16f
--- /dev/null
+++ b/src/Web/Avalonia.Web.Sample/Avalonia.Web.Sample.csproj
@@ -0,0 +1,24 @@
+
+
+ net7.0
+ browser-wasm
+ main.js
+ Exe
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Web/Avalonia.Web.Sample/Program.cs b/src/Web/Avalonia.Web.Sample/Program.cs
new file mode 100644
index 0000000000..b880d61ab5
--- /dev/null
+++ b/src/Web/Avalonia.Web.Sample/Program.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Runtime.InteropServices.JavaScript;
+using System.Threading.Tasks;
+using Avalonia.Web;
+//using SkiaSharp;
+
+internal class Program
+{
+ private static void Main(string[] args)
+ {
+ Console.WriteLine("Hello, Browser!");
+
+ AvaloniaRuntime.Init();
+ }
+}
+
+public partial class MyClass
+{
+ [JSExport]
+ internal static async Task TestDynamicModule()
+ {
+ await JSHost.ImportAsync("storage.ts", "./storage.js");
+ var fileApiSupported = AvaloniaRuntime.IsFileApiSupported();
+
+ Console.WriteLine("DynamicModule result: " + fileApiSupported);
+ }
+}
diff --git a/src/Web/Avalonia.Web.Sample/index.html b/src/Web/Avalonia.Web.Sample/index.html
new file mode 100644
index 0000000000..25b92798ad
--- /dev/null
+++ b/src/Web/Avalonia.Web.Sample/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Avalonia.Web.Sample
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Web/Avalonia.Web.Sample/main.js b/src/Web/Avalonia.Web.Sample/main.js
new file mode 100644
index 0000000000..9973b469c7
--- /dev/null
+++ b/src/Web/Avalonia.Web.Sample/main.js
@@ -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.
+
+import { dotnet } from './dotnet.js'
+import { createAvaloniaRuntime } from './avalonia.js'
+
+const is_browser = typeof window != "undefined";
+if (!is_browser) throw new Error(`Expected to be running in a browser`);
+
+const dotnetRuntime = await dotnet
+ .withDiagnosticTracing(false)
+ .withApplicationArgumentsFromQuery()
+ .create();
+
+const avaloniaRuntime = await createAvaloniaRuntime(dotnetRuntime);
+
+const outDiv = document.getElementById("out");
+avaloniaRuntime.createAvaloniaView(outDiv);
+
+const config = dotnetRuntime.getConfig();
+const exports = await dotnetRuntime.getAssemblyExports(config.mainAssemblyName);
+await exports.MyClass.TestDynamicModule();
+
+await dotnetRuntime.runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]);
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web.Sample/runtimeconfig.template.json b/src/Web/Avalonia.Web.Sample/runtimeconfig.template.json
new file mode 100644
index 0000000000..8f0557352c
--- /dev/null
+++ b/src/Web/Avalonia.Web.Sample/runtimeconfig.template.json
@@ -0,0 +1,11 @@
+{
+ "wasmHostProperties": {
+ "perHostConfig": [
+ {
+ "name": "browser",
+ "html-path": "index.html",
+ "Host": "browser"
+ }
+ ]
+ }
+}
diff --git a/src/Web/Avalonia.Web/Avalonia.Web.csproj b/src/Web/Avalonia.Web/Avalonia.Web.csproj
new file mode 100644
index 0000000000..51b1d70173
--- /dev/null
+++ b/src/Web/Avalonia.Web/Avalonia.Web.csproj
@@ -0,0 +1,41 @@
+
+
+ net7.0
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ build\
+
+
+ true
+ build\;buildTransitive\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Web/Avalonia.Web/Avalonia.Web.targets b/src/Web/Avalonia.Web/Avalonia.Web.targets
new file mode 100644
index 0000000000..97c8c29ee4
--- /dev/null
+++ b/src/Web/Avalonia.Web/Avalonia.Web.targets
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/AvaloniaRuntime.cs b/src/Web/Avalonia.Web/AvaloniaRuntime.cs
new file mode 100644
index 0000000000..c8ff75a77f
--- /dev/null
+++ b/src/Web/Avalonia.Web/AvaloniaRuntime.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.JavaScript;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace Avalonia.Web;
+
+public partial class AvaloniaRuntime
+{
+ public record GLInfo(int ContextId, uint FboId, int Stencils, int Samples, int Depth);
+
+ [JSExport]
+ internal static void StartAvaloniaView(JSObject canvas)
+ {
+ Init();
+ // setup, get gl context...
+ var info = InitGL(canvas, "testCanvas");
+
+
+ /* var glInfo = new GLInfo(
+ info.GetPropertyAsInt32("context"),
+ (uint)info.GetPropertyAsInt32("fboId"),
+ info.GetPropertyAsInt32("stencil"),
+ info.GetPropertyAsInt32("sample"),
+ info.GetPropertyAsInt32("depth"));
+
+ Console.WriteLine($"{glInfo.ContextId}, {glInfo.FboId}");*/
+ }
+
+ public static void Init ()
+ {
+ if (false)
+ {
+ SkiaSharp.GRGlInterface.Create();
+ }
+ }
+
+ [JSImport("Canvas.Foo", "avalonia.ts")]
+ internal static partial void Foo(JSObject canvas);
+
+ [JSImport("Canvas.initGL", "avalonia.ts")]
+ internal static partial JSObject InitGL(JSObject canvas, string canvasId);
+
+ [JSImport("StorageProvider.isFileApiSupported", "storage.ts")]
+ public static partial bool IsFileApiSupported();
+
+ //[DllImport("__Internal")]
+ //public
+
+}
+
diff --git a/src/Web/Avalonia.Web/webapp/build.js b/src/Web/Avalonia.Web/webapp/build.js
new file mode 100644
index 0000000000..32f79b0709
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/build.js
@@ -0,0 +1,16 @@
+require("esbuild").build({
+ entryPoints: [
+ "./modules/avalonia.ts",
+ "./modules/storage.ts"
+ ],
+ outdir: "../wwwroot",
+ bundle: true,
+ minify: false,
+ format: "esm",
+ target: "es2016",
+ platform: "browser",
+ sourcemap: "linked",
+ loader: {".ts": "ts"}
+ })
+ .then(() => console.log("⚡ Done"))
+ .catch(() => process.exit(1));
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia.ts
new file mode 100644
index 0000000000..bf9ef48772
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/modules/avalonia.ts
@@ -0,0 +1,7 @@
+import { RuntimeAPI } from "../types/dotnet";
+import { AvaloniaRuntime } from "./avalonia/runtime";
+
+export async function createAvaloniaRuntime(api: RuntimeAPI): Promise {
+ const dotnetAssembly = await api.getAssemblyExports("Avalonia.Web.dll");
+ return new AvaloniaRuntime(dotnetAssembly, api);
+}
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts
new file mode 100644
index 0000000000..c8acf5e428
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts
@@ -0,0 +1,119 @@
+declare let GL: any;
+declare let GLctx: WebGLRenderingContext;
+declare let Module: EmscriptenModule;
+
+type SKGLViewInfo = {
+ context: WebGLRenderingContext | WebGL2RenderingContext | undefined;
+ fboId: number;
+ stencil: number;
+ sample: number;
+ depth: number;
+}
+
+type SKHtmlCanvasElement = {
+ SKHtmlCanvas: Canvas | undefined
+} & HTMLCanvasElement
+
+export class Canvas {
+ static elements: Map;
+
+ //htmlCanvas: HTMLCanvasElement;
+ glInfo?: SKGLViewInfo;
+ //renderFrameCallback: DotNet.DotNetObject;
+ renderLoopEnabled: boolean = false;
+ renderLoopRequest: number = 0;
+ newWidth?: number;
+ newHeight?: number;
+
+ public static initGL(element: HTMLCanvasElement, elementId: string): SKGLViewInfo | null {
+ console.log("inside initGL");
+ var view = Canvas.init(true, element, elementId);
+ if (!view || !view.glInfo)
+ return null;
+
+ return view.glInfo;
+ }
+
+ static init(useGL: boolean, element: HTMLCanvasElement, elementId: string): Canvas | null {
+ var htmlCanvas = element as SKHtmlCanvasElement;
+ if (!htmlCanvas) {
+ console.error(`No canvas element was provided.`);
+ return null;
+ }
+
+ if (!Canvas.elements)
+ Canvas.elements = new Map();
+ Canvas.elements.set(elementId, element);
+
+ const view = new Canvas(useGL, element);
+
+ htmlCanvas.SKHtmlCanvas = view;
+
+ return view;
+ }
+
+
+ public constructor(useGL: boolean, element: HTMLCanvasElement) {
+ //this.htmlCanvas = element;
+ //this.renderFrameCallback = callback;
+
+ if (useGL) {
+ const ctx = Canvas.createWebGLContext(element);
+ if (!ctx) {
+ console.error(`Failed to create WebGL context: err ${ctx}`);
+ return;
+ }
+
+ // make current
+ GL.makeContextCurrent(ctx);
+
+ // read values
+ const fbo = GLctx.getParameter(GLctx.FRAMEBUFFER_BINDING);
+ this.glInfo = {
+ context: ctx,
+ fboId: fbo ? fbo.id : 0,
+ stencil: GLctx.getParameter(GLctx.STENCIL_BITS),
+ sample: 0, // TODO: GLctx.getParameter(GLctx.SAMPLES)
+ depth: GLctx.getParameter(GLctx.DEPTH_BITS),
+ };
+ }
+ }
+
+
+ static Foo(canvas: HTMLCanvasElement) {
+ const ctx = canvas.getContext("2d")!;
+ ctx.fillStyle = "#FF0000";
+ ctx.fillRect(0, 0, 150, 75);
+ }
+
+ static createWebGLContext(htmlCanvas: HTMLCanvasElement): WebGLRenderingContext | WebGL2RenderingContext {
+ const contextAttributes = {
+ alpha: 1,
+ depth: 1,
+ stencil: 8,
+ antialias: 0,
+ premultipliedAlpha: 1,
+ preserveDrawingBuffer: 0,
+ preferLowPowerToHighPerformance: 0,
+ failIfMajorPerformanceCaveat: 0,
+ majorVersion: 2,
+ minorVersion: 0,
+ enableExtensionsByDefault: 1,
+ explicitSwapControl: 0,
+ renderViaOffscreenBackBuffer: 1,
+ };
+
+
+ var context = htmlCanvas.getContext("webgl2", contextAttributes);
+
+ let ctx: WebGLRenderingContext = GL.createContext(htmlCanvas, contextAttributes);
+ if (!ctx && contextAttributes.majorVersion > 1) {
+ console.warn('Falling back to WebGL 1.0');
+ contextAttributes.majorVersion = 1;
+ contextAttributes.minorVersion = 0;
+ ctx = GL.createContext(htmlCanvas, contextAttributes);
+ }
+
+ return ctx;
+ }
+}
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/runtime.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/runtime.ts
new file mode 100644
index 0000000000..bd1989e935
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/runtime.ts
@@ -0,0 +1,23 @@
+import { RuntimeAPI } from "../../types/dotnet";
+
+import { Canvas } from "./canvas";
+
+export class AvaloniaRuntime {
+ constructor(
+ private dotnetAssembly: any,
+ api: RuntimeAPI
+ ) {
+ api.setModuleImports("avalonia.ts", {
+ Canvas
+ });
+ }
+
+ createAvaloniaView(element: HTMLDivElement): void {
+ const canvas = document.createElement("canvas");
+ element.appendChild(canvas);
+
+
+
+ this.dotnetAssembly.Avalonia.Web.AvaloniaRuntime.StartAvaloniaView(canvas);
+ }
+}
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/modules/storage.ts b/src/Web/Avalonia.Web/webapp/modules/storage.ts
new file mode 100644
index 0000000000..7b6cd816de
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/modules/storage.ts
@@ -0,0 +1,5 @@
+export class StorageProvider {
+ static isFileApiSupported(): boolean {
+ return (globalThis as any).showOpenFilePicker !== undefined;
+ }
+}
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/package-lock.json b/src/Web/Avalonia.Web/webapp/package-lock.json
new file mode 100644
index 0000000000..5df9471195
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/package-lock.json
@@ -0,0 +1,634 @@
+{
+ "name": "avalonia.web",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "avalonia.web",
+ "devDependencies": {
+ "@types/emscripten": "^1.39.6",
+ "@types/wicg-file-system-access": "^2020.9.5",
+ "esbuild": "^0.15.7",
+ "typescript": "^4.7.4"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.9.tgz",
+ "integrity": "sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz",
+ "integrity": "sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@types/emscripten": {
+ "version": "1.39.6",
+ "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
+ "integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==",
+ "dev": true
+ },
+ "node_modules/@types/wicg-file-system-access": {
+ "version": "2020.9.5",
+ "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.5.tgz",
+ "integrity": "sha512-UYK244awtmcUYQfs7FR8710MJcefL2WvkyHMjA8yJzxd1mo0Gfn88sRZ1Bls7hiUhA2w7ne1gpJ9T5g3G0wOyA==",
+ "dev": true
+ },
+ "node_modules/esbuild": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.9.tgz",
+ "integrity": "sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.9",
+ "@esbuild/linux-loong64": "0.15.9",
+ "esbuild-android-64": "0.15.9",
+ "esbuild-android-arm64": "0.15.9",
+ "esbuild-darwin-64": "0.15.9",
+ "esbuild-darwin-arm64": "0.15.9",
+ "esbuild-freebsd-64": "0.15.9",
+ "esbuild-freebsd-arm64": "0.15.9",
+ "esbuild-linux-32": "0.15.9",
+ "esbuild-linux-64": "0.15.9",
+ "esbuild-linux-arm": "0.15.9",
+ "esbuild-linux-arm64": "0.15.9",
+ "esbuild-linux-mips64le": "0.15.9",
+ "esbuild-linux-ppc64le": "0.15.9",
+ "esbuild-linux-riscv64": "0.15.9",
+ "esbuild-linux-s390x": "0.15.9",
+ "esbuild-netbsd-64": "0.15.9",
+ "esbuild-openbsd-64": "0.15.9",
+ "esbuild-sunos-64": "0.15.9",
+ "esbuild-windows-32": "0.15.9",
+ "esbuild-windows-64": "0.15.9",
+ "esbuild-windows-arm64": "0.15.9"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz",
+ "integrity": "sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz",
+ "integrity": "sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz",
+ "integrity": "sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz",
+ "integrity": "sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz",
+ "integrity": "sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz",
+ "integrity": "sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz",
+ "integrity": "sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz",
+ "integrity": "sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz",
+ "integrity": "sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz",
+ "integrity": "sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz",
+ "integrity": "sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz",
+ "integrity": "sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz",
+ "integrity": "sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz",
+ "integrity": "sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz",
+ "integrity": "sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz",
+ "integrity": "sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz",
+ "integrity": "sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz",
+ "integrity": "sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz",
+ "integrity": "sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz",
+ "integrity": "sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+ "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ }
+ },
+ "dependencies": {
+ "@esbuild/android-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.9.tgz",
+ "integrity": "sha512-VZPy/ETF3fBG5PiinIkA0W/tlsvlEgJccyN2DzWZEl0DlVKRbu91PvY2D6Lxgluj4w9QtYHjOWjAT44C+oQ+EQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.9.tgz",
+ "integrity": "sha512-O+NfmkfRrb3uSsTa4jE3WApidSe3N5++fyOVGP1SmMZi4A3BZELkhUUvj5hwmMuNdlpzAZ8iAPz2vmcR7DCFQA==",
+ "dev": true,
+ "optional": true
+ },
+ "@types/emscripten": {
+ "version": "1.39.6",
+ "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
+ "integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==",
+ "dev": true
+ },
+ "@types/wicg-file-system-access": {
+ "version": "2020.9.5",
+ "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.5.tgz",
+ "integrity": "sha512-UYK244awtmcUYQfs7FR8710MJcefL2WvkyHMjA8yJzxd1mo0Gfn88sRZ1Bls7hiUhA2w7ne1gpJ9T5g3G0wOyA==",
+ "dev": true
+ },
+ "esbuild": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.9.tgz",
+ "integrity": "sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==",
+ "dev": true,
+ "requires": {
+ "@esbuild/android-arm": "0.15.9",
+ "@esbuild/linux-loong64": "0.15.9",
+ "esbuild-android-64": "0.15.9",
+ "esbuild-android-arm64": "0.15.9",
+ "esbuild-darwin-64": "0.15.9",
+ "esbuild-darwin-arm64": "0.15.9",
+ "esbuild-freebsd-64": "0.15.9",
+ "esbuild-freebsd-arm64": "0.15.9",
+ "esbuild-linux-32": "0.15.9",
+ "esbuild-linux-64": "0.15.9",
+ "esbuild-linux-arm": "0.15.9",
+ "esbuild-linux-arm64": "0.15.9",
+ "esbuild-linux-mips64le": "0.15.9",
+ "esbuild-linux-ppc64le": "0.15.9",
+ "esbuild-linux-riscv64": "0.15.9",
+ "esbuild-linux-s390x": "0.15.9",
+ "esbuild-netbsd-64": "0.15.9",
+ "esbuild-openbsd-64": "0.15.9",
+ "esbuild-sunos-64": "0.15.9",
+ "esbuild-windows-32": "0.15.9",
+ "esbuild-windows-64": "0.15.9",
+ "esbuild-windows-arm64": "0.15.9"
+ }
+ },
+ "esbuild-android-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.9.tgz",
+ "integrity": "sha512-HQCX7FJn9T4kxZQkhPjNZC7tBWZqJvhlLHPU2SFzrQB/7nDXjmTIFpFTjt7Bd1uFpeXmuwf5h5fZm+x/hLnhbw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-android-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.9.tgz",
+ "integrity": "sha512-E6zbLfqbFVCNEKircSHnPiSTsm3fCRxeIMPfrkS33tFjIAoXtwegQfVZqMGR0FlsvVxp2NEDOUz+WW48COCjSg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.9.tgz",
+ "integrity": "sha512-gI7dClcDN/HHVacZhTmGjl0/TWZcGuKJ0I7/xDGJwRQQn7aafZGtvagOFNmuOq+OBFPhlPv1T6JElOXb0unkSQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.9.tgz",
+ "integrity": "sha512-VZIMlcRN29yg/sv7DsDwN+OeufCcoTNaTl3Vnav7dL/nvsApD7uvhVRbgyMzv0zU/PP0xRhhIpTyc7lxEzHGSw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.9.tgz",
+ "integrity": "sha512-uM4z5bTvuAXqPxrI204txhlsPIolQPWRMLenvGuCPZTnnGlCMF2QLs0Plcm26gcskhxewYo9LkkmYSS5Czrb5A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.9.tgz",
+ "integrity": "sha512-HHDjT3O5gWzicGdgJ5yokZVN9K9KG05SnERwl9nBYZaCjcCgj/sX8Ps1jvoFSfNCO04JSsHSOWo4qvxFuj8FoA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.9.tgz",
+ "integrity": "sha512-AQIdE8FugGt1DkcekKi5ycI46QZpGJ/wqcMr7w6YUmOmp2ohQ8eO4sKUsOxNOvYL7hGEVwkndSyszR6HpVHLFg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz",
+ "integrity": "sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.9.tgz",
+ "integrity": "sha512-3Zf2GVGUOI7XwChH3qrnTOSqfV1V4CAc/7zLVm4lO6JT6wbJrTgEYCCiNSzziSju+J9Jhf9YGWk/26quWPC6yQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.9.tgz",
+ "integrity": "sha512-a+bTtxJmYmk9d+s2W4/R1SYKDDAldOKmWjWP0BnrWtDbvUBNOm++du0ysPju4mZVoEFgS1yLNW+VXnG/4FNwdQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-mips64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.9.tgz",
+ "integrity": "sha512-Zn9HSylDp89y+TRREMDoGrc3Z4Hs5u56ozZLQCiZAUx2+HdbbXbWdjmw3FdTJ/i7t5Cew6/Q+6kfO3KCcFGlyw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-ppc64le": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.9.tgz",
+ "integrity": "sha512-OEiOxNAMH9ENFYqRsWUj3CWyN3V8P3ZXyfNAtX5rlCEC/ERXrCEFCJji/1F6POzsXAzxvUJrTSTCy7G6BhA6Fw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-riscv64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.9.tgz",
+ "integrity": "sha512-ukm4KsC3QRausEFjzTsOZ/qqazw0YvJsKmfoZZm9QW27OHjk2XKSQGGvx8gIEswft/Sadp03/VZvAaqv5AIwNA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-s390x": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.9.tgz",
+ "integrity": "sha512-uDOQEH55wQ6ahcIKzQr3VyjGc6Po/xblLGLoUk3fVL1qjlZAibtQr6XRfy5wPJLu/M2o0vQKLq4lyJ2r1tWKcw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-netbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.9.tgz",
+ "integrity": "sha512-yWgxaYTQz+TqX80wXRq6xAtb7GSBAp6gqLKfOdANg9qEmAI1Bxn04IrQr0Mzm4AhxvGKoHzjHjMgXbCCSSDxcw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-openbsd-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.9.tgz",
+ "integrity": "sha512-JmS18acQl4iSAjrEha1MfEmUMN4FcnnrtTaJ7Qg0tDCOcgpPPQRLGsZqhes0vmx8VA6IqRyScqXvaL7+Q0Uf3A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-sunos-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.9.tgz",
+ "integrity": "sha512-UKynGSWpzkPmXW3D2UMOD9BZPIuRaSqphxSCwScfEE05Be3KAmvjsBhht1fLzKpiFVJb0BYMd4jEbWMyJ/z1hQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-32": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.9.tgz",
+ "integrity": "sha512-aqXvu4/W9XyTVqO/hw3rNxKE1TcZiEYHPsXM9LwYmKSX9/hjvfIJzXwQBlPcJ/QOxedfoMVH0YnhhQ9Ffb0RGA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.9.tgz",
+ "integrity": "sha512-zm7h91WUmlS4idMtjvCrEeNhlH7+TNOmqw5dJPJZrgFaxoFyqYG6CKDpdFCQXdyKpD5yvzaQBOMVTCBVKGZDEg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-arm64": {
+ "version": "0.15.9",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.9.tgz",
+ "integrity": "sha512-yQEVIv27oauAtvtuhJVfSNMztJJX47ismRS6Sv2QMVV9RM+6xjbMWuuwM2nxr5A2/gj/mu2z9YlQxiwoFRCfZA==",
+ "dev": true,
+ "optional": true
+ },
+ "typescript": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+ "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
+ "dev": true
+ }
+ }
+}
diff --git a/src/Web/Avalonia.Web/webapp/package.json b/src/Web/Avalonia.Web/webapp/package.json
new file mode 100644
index 0000000000..ca029ce534
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "avalonia.web",
+ "scripts": {
+ "prebuild": "node ./node_modules/typescript/bin/tsc -noEmit",
+ "build": "node build.js"
+ },
+ "devDependencies": {
+ "@types/emscripten": "^1.39.6",
+ "@types/wicg-file-system-access": "^2020.9.5",
+ "typescript": "^4.7.4",
+ "esbuild": "^0.15.7"
+ }
+}
diff --git a/src/Web/Avalonia.Web/webapp/tsconfig.json b/src/Web/Avalonia.Web/webapp/tsconfig.json
new file mode 100644
index 0000000000..ad0e727150
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "es2016",
+ "module": "es2020",
+ "strict": true,
+ "sourceMap": true,
+ "noEmitOnError": true,
+ "isolatedModules": true, // we need it for esbuild
+ "lib": [
+ "dom",
+ "es2016",
+ "esnext.asynciterable"
+ ]
+ },
+ "exclude": [
+ "node_modules"
+ ]
+ }
+
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/webapp/types/dotnet.d.ts b/src/Web/Avalonia.Web/webapp/types/dotnet.d.ts
new file mode 100644
index 0000000000..bc2068cb59
--- /dev/null
+++ b/src/Web/Avalonia.Web/webapp/types/dotnet.d.ts
@@ -0,0 +1,249 @@
+// See https://raw.githubusercontent.com/dotnet/runtime/main/src/mono/wasm/runtime/dotnet.d.ts
+
+//! Licensed to the .NET Foundation under one or more agreements.
+//! The .NET Foundation licenses this file to you under the MIT license.
+//!
+//! This is generated file, see src/mono/wasm/runtime/rollup.config.js
+
+//! This is not considered public API with backward compatibility guarantees.
+
+interface DotnetHostBuilder {
+ withConfig(config: MonoConfig): DotnetHostBuilder;
+ withConfigSrc(configSrc: string): DotnetHostBuilder;
+ withApplicationArguments(...args: string[]): DotnetHostBuilder;
+ withEnvironmentVariable(name: string, value: string): DotnetHostBuilder;
+ withEnvironmentVariables(variables: {
+ [i: string]: string;
+ }): DotnetHostBuilder;
+ withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder;
+ withDiagnosticTracing(enabled: boolean): DotnetHostBuilder;
+ withDebugging(level: number): DotnetHostBuilder;
+ withMainAssembly(mainAssemblyName: string): DotnetHostBuilder;
+ withApplicationArgumentsFromQuery(): DotnetHostBuilder;
+ create(): Promise;
+ run(): Promise;
+}
+
+declare interface NativePointer {
+ __brandNativePointer: "NativePointer";
+}
+declare interface VoidPtr extends NativePointer {
+ __brand: "VoidPtr";
+}
+declare interface CharPtr extends NativePointer {
+ __brand: "CharPtr";
+}
+declare interface Int32Ptr extends NativePointer {
+ __brand: "Int32Ptr";
+}
+declare interface EmscriptenModule {
+ HEAP8: Int8Array;
+ HEAP16: Int16Array;
+ HEAP32: Int32Array;
+ HEAPU8: Uint8Array;
+ HEAPU16: Uint16Array;
+ HEAPU32: Uint32Array;
+ HEAPF32: Float32Array;
+ HEAPF64: Float64Array;
+ _malloc(size: number): VoidPtr;
+ _free(ptr: VoidPtr): void;
+ print(message: string): void;
+ printErr(message: string): void;
+ ccall(ident: string, returnType?: string | null, argTypes?: string[], args?: any[], opts?: any): T;
+ cwrap(ident: string, returnType: string, argTypes?: string[], opts?: any): T;
+ cwrap(ident: string, ...args: any[]): T;
+ setValue(ptr: VoidPtr, value: number, type: string, noSafe?: number | boolean): void;
+ setValue(ptr: Int32Ptr, value: number, type: string, noSafe?: number | boolean): void;
+ getValue(ptr: number, type: string, noSafe?: number | boolean): number;
+ UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string;
+ UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string;
+ FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string;
+ FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string;
+ FS_readFile(filename: string, opts: any): any;
+ removeRunDependency(id: string): void;
+ addRunDependency(id: string): void;
+ stackSave(): VoidPtr;
+ stackRestore(stack: VoidPtr): void;
+ stackAlloc(size: number): VoidPtr;
+ ready: Promise;
+ instantiateWasm?: InstantiateWasmCallBack;
+ preInit?: (() => any)[] | (() => any);
+ preRun?: (() => any)[] | (() => any);
+ onRuntimeInitialized?: () => any;
+ postRun?: (() => any)[] | (() => any);
+ onAbort?: {
+ (error: any): void;
+ };
+}
+declare type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module) => void;
+declare type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any;
+declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
+
+declare type MonoConfig = {
+ /**
+ * The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script.
+ */
+ assemblyRootFolder?: string;
+ /**
+ * A list of assets to load along with the runtime.
+ */
+ assets?: AssetEntry[];
+ /**
+ * Additional search locations for assets.
+ */
+ remoteSources?: string[];
+ /**
+ * It will not fail the startup is .pdb files can't be downloaded
+ */
+ ignorePdbLoadErrors?: boolean;
+ /**
+ * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16.
+ */
+ maxParallelDownloads?: number;
+ /**
+ * Name of the assembly with main entrypoint
+ */
+ mainAssemblyName?: string;
+ /**
+ * Configures the runtime's globalization mode
+ */
+ globalizationMode?: GlobalizationMode;
+ /**
+ * debugLevel > 0 enables debugging and sets the debug log level to debugLevel
+ * debugLevel == 0 disables debugging and enables interpreter optimizations
+ * debugLevel < 0 enabled debugging and disables debug logging.
+ */
+ debugLevel?: number;
+ /**
+ * Enables diagnostic log messages during startup
+ */
+ diagnosticTracing?: boolean;
+ /**
+ * Dictionary-style Object containing environment variables
+ */
+ environmentVariables?: {
+ [i: string]: string;
+ };
+ /**
+ * initial number of workers to add to the emscripten pthread pool
+ */
+ pthreadPoolSize?: number;
+};
+interface ResourceRequest {
+ name: string;
+ behavior: AssetBehaviours;
+ resolvedUrl?: string;
+ hash?: string;
+}
+interface LoadingResource {
+ name: string;
+ url: string;
+ response: Promise;
+}
+interface AssetEntry extends ResourceRequest {
+ /**
+ * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded.
+ */
+ virtualPath?: string;
+ /**
+ * Culture code
+ */
+ culture?: string;
+ /**
+ * If true, an attempt will be made to load the asset from each location in MonoConfig.remoteSources.
+ */
+ loadRemote?: boolean;
+ /**
+ * If true, the runtime startup would not fail if the asset download was not successful.
+ */
+ isOptional?: boolean;
+ /**
+ * If provided, runtime doesn't have to fetch the data.
+ * Runtime would set the buffer to null after instantiation to free the memory.
+ */
+ buffer?: ArrayBuffer;
+ /**
+ * It's metadata + fetch-like Promise
+ * If provided, the runtime doesn't have to initiate the download. It would just await the response.
+ */
+ pendingDownload?: LoadingResource;
+}
+declare type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads";
+declare type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu".
+"invariant" | // operate in invariant globalization mode.
+"auto";
+declare type DotnetModuleConfig = {
+ disableDotnet6Compatibility?: boolean;
+ config?: MonoConfig;
+ configSrc?: string;
+ onConfigLoaded?: (config: MonoConfig) => void | Promise;
+ onDotnetReady?: () => void | Promise;
+ imports?: any;
+ exports?: string[];
+ downloadResource?: (request: ResourceRequest) => LoadingResource | undefined;
+} & Partial;
+declare type APIType = {
+ runMain: (mainAssemblyName: string, args: string[]) => Promise;
+ runMainAndExit: (mainAssemblyName: string, args: string[]) => Promise;
+ setEnvironmentVariable: (name: string, value: string) => void;
+ getAssemblyExports(assemblyName: string): Promise;
+ setModuleImports(moduleName: string, moduleImports: any): void;
+ getConfig: () => MonoConfig;
+ setHeapB32: (offset: NativePointer, value: number | boolean) => void;
+ setHeapU8: (offset: NativePointer, value: number) => void;
+ setHeapU16: (offset: NativePointer, value: number) => void;
+ setHeapU32: (offset: NativePointer, value: NativePointer | number) => void;
+ setHeapI8: (offset: NativePointer, value: number) => void;
+ setHeapI16: (offset: NativePointer, value: number) => void;
+ setHeapI32: (offset: NativePointer, value: number) => void;
+ setHeapI52: (offset: NativePointer, value: number) => void;
+ setHeapU52: (offset: NativePointer, value: number) => void;
+ setHeapI64Big: (offset: NativePointer, value: bigint) => void;
+ setHeapF32: (offset: NativePointer, value: number) => void;
+ setHeapF64: (offset: NativePointer, value: number) => void;
+ getHeapB32: (offset: NativePointer) => boolean;
+ getHeapU8: (offset: NativePointer) => number;
+ getHeapU16: (offset: NativePointer) => number;
+ getHeapU32: (offset: NativePointer) => number;
+ getHeapI8: (offset: NativePointer) => number;
+ getHeapI16: (offset: NativePointer) => number;
+ getHeapI32: (offset: NativePointer) => number;
+ getHeapI52: (offset: NativePointer) => number;
+ getHeapU52: (offset: NativePointer) => number;
+ getHeapI64Big: (offset: NativePointer) => bigint;
+ getHeapF32: (offset: NativePointer) => number;
+ getHeapF64: (offset: NativePointer) => number;
+};
+declare type RuntimeAPI = {
+ /**
+ * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts
+ */
+ MONO: any;
+ /**
+ * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts
+ */
+ BINDING: any;
+ INTERNAL: any;
+ Module: EmscriptenModule;
+ runtimeId: number;
+ runtimeBuildInfo: {
+ productVersion: string;
+ gitHash: string;
+ buildConfiguration: string;
+ };
+} & APIType;
+declare type ModuleAPI = {
+ dotnet: DotnetHostBuilder;
+ exit: (code: number, reason?: any) => void;
+};
+declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise;
+declare type CreateDotnetRuntimeType = typeof createDotnetRuntime;
+
+declare global {
+ function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined;
+}
+
+declare const dotnet: ModuleAPI["dotnet"];
+declare const exit: ModuleAPI["exit"];
+
+export { CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, ModuleAPI, MonoConfig, RuntimeAPI, createDotnetRuntime as default, dotnet, exit };
\ No newline at end of file
diff --git a/src/Web/Avalonia.Web/wwwroot/avalonia.js b/src/Web/Avalonia.Web/wwwroot/avalonia.js
new file mode 100644
index 0000000000..8a44381e52
--- /dev/null
+++ b/src/Web/Avalonia.Web/wwwroot/avalonia.js
@@ -0,0 +1,122 @@
+var __async = (__this, __arguments, generator) => {
+ return new Promise((resolve, reject) => {
+ var fulfilled = (value) => {
+ try {
+ step(generator.next(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var rejected = (value) => {
+ try {
+ step(generator.throw(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+ step((generator = generator.apply(__this, __arguments)).next());
+ });
+};
+
+// modules/avalonia/canvas.ts
+var Canvas = class {
+ constructor(useGL, element) {
+ this.renderLoopEnabled = false;
+ this.renderLoopRequest = 0;
+ if (useGL) {
+ const ctx = Canvas.createWebGLContext(element);
+ if (!ctx) {
+ console.error(`Failed to create WebGL context: err ${ctx}`);
+ return;
+ }
+ GL.makeContextCurrent(ctx);
+ const fbo = GLctx.getParameter(GLctx.FRAMEBUFFER_BINDING);
+ this.glInfo = {
+ context: ctx,
+ fboId: fbo ? fbo.id : 0,
+ stencil: GLctx.getParameter(GLctx.STENCIL_BITS),
+ sample: 0,
+ depth: GLctx.getParameter(GLctx.DEPTH_BITS)
+ };
+ }
+ }
+ static initGL(element, elementId) {
+ console.log("inside initGL");
+ var view = Canvas.init(true, element, elementId);
+ if (!view || !view.glInfo)
+ return null;
+ return view.glInfo;
+ }
+ static init(useGL, element, elementId) {
+ var htmlCanvas = element;
+ if (!htmlCanvas) {
+ console.error(`No canvas element was provided.`);
+ return null;
+ }
+ if (!Canvas.elements)
+ Canvas.elements = /* @__PURE__ */ new Map();
+ Canvas.elements.set(elementId, element);
+ const view = new Canvas(useGL, element);
+ htmlCanvas.SKHtmlCanvas = view;
+ return view;
+ }
+ static Foo(canvas) {
+ const ctx = canvas.getContext("2d");
+ ctx.fillStyle = "#FF0000";
+ ctx.fillRect(0, 0, 150, 75);
+ }
+ static createWebGLContext(htmlCanvas) {
+ const contextAttributes = {
+ alpha: 1,
+ depth: 1,
+ stencil: 8,
+ antialias: 0,
+ premultipliedAlpha: 1,
+ preserveDrawingBuffer: 0,
+ preferLowPowerToHighPerformance: 0,
+ failIfMajorPerformanceCaveat: 0,
+ majorVersion: 2,
+ minorVersion: 0,
+ enableExtensionsByDefault: 1,
+ explicitSwapControl: 0,
+ renderViaOffscreenBackBuffer: 1
+ };
+ var context = htmlCanvas.getContext("webgl2", contextAttributes);
+ let ctx = GL.createContext(htmlCanvas, contextAttributes);
+ if (!ctx && contextAttributes.majorVersion > 1) {
+ console.warn("Falling back to WebGL 1.0");
+ contextAttributes.majorVersion = 1;
+ contextAttributes.minorVersion = 0;
+ ctx = GL.createContext(htmlCanvas, contextAttributes);
+ }
+ return ctx;
+ }
+};
+
+// modules/avalonia/runtime.ts
+var AvaloniaRuntime = class {
+ constructor(dotnetAssembly, api) {
+ this.dotnetAssembly = dotnetAssembly;
+ api.setModuleImports("avalonia.ts", {
+ Canvas
+ });
+ }
+ createAvaloniaView(element) {
+ const canvas = document.createElement("canvas");
+ element.appendChild(canvas);
+ this.dotnetAssembly.Avalonia.Web.AvaloniaRuntime.StartAvaloniaView(canvas);
+ }
+};
+
+// modules/avalonia.ts
+function createAvaloniaRuntime(api) {
+ return __async(this, null, function* () {
+ const dotnetAssembly = yield api.getAssemblyExports("Avalonia.Web.dll");
+ return new AvaloniaRuntime(dotnetAssembly, api);
+ });
+}
+export {
+ createAvaloniaRuntime
+};
+//# sourceMappingURL=avalonia.js.map
diff --git a/src/Web/Avalonia.Web/wwwroot/storage.js b/src/Web/Avalonia.Web/wwwroot/storage.js
new file mode 100644
index 0000000000..a2042aaa11
--- /dev/null
+++ b/src/Web/Avalonia.Web/wwwroot/storage.js
@@ -0,0 +1,10 @@
+// modules/storage.ts
+var StorageProvider = class {
+ static isFileApiSupported() {
+ return globalThis.showOpenFilePicker !== void 0;
+ }
+};
+export {
+ StorageProvider
+};
+//# sourceMappingURL=storage.js.map