diff --git a/.filenesting.json b/.filenesting.json new file mode 100644 index 000000000..0b7196627 --- /dev/null +++ b/.filenesting.json @@ -0,0 +1,3 @@ +{ + "help":"https://go.microsoft.com/fwlink/?linkid=866610" +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..452158309 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/src/Tools/CmdLine/bin/Debug/net6.0/fusee.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Tools/CmdLine", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..5e4865a45 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Tools/CmdLine/Fusee.Tools.CmdLine.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/src/Tools/CmdLine/Fusee.Tools.CmdLine.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/src/Tools/CmdLine/Fusee.Tools.CmdLine.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/App.razor b/Examples/Complete/Animation/Blazor/App.razor new file mode 100644 index 000000000..6f67a6ea6 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/App.razor @@ -0,0 +1,10 @@ + + + + + + +

Sorry, there's nothing at this address.

+
+
+
diff --git a/Examples/Complete/Animation/Blazor/Fusee.Examples.Animation.Blazor.csproj b/Examples/Complete/Animation/Blazor/Fusee.Examples.Animation.Blazor.csproj new file mode 100644 index 000000000..dd9dc51db --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Fusee.Examples.Animation.Blazor.csproj @@ -0,0 +1,41 @@ + + + net6.0 + service-worker-assets.js + false + false + false + disable + AnyCPU + + + + $(BaseOutputPath)\Examples\Animation\Blazor\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Complete/Animation/Blazor/Main.cs b/Examples/Complete/Animation/Blazor/Main.cs new file mode 100644 index 000000000..5b90b9c4e --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Main.cs @@ -0,0 +1,231 @@ +using Fusee.Base.Common; +using Fusee.Base.Core; +using Fusee.Base.Imp.Blazor; +using Fusee.Engine.Core; +using Fusee.Engine.Core.Scene; +using Fusee.Engine.Imp.Graphics.Blazor; +using Fusee.Serialization; +using Microsoft.JSInterop; +using ProtoBuf; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Path = System.IO.Path; +using Stream = System.IO.Stream; + +namespace Fusee.Examples.Simple.Blazor +{ + public class Main : BlazorBase + { + private RenderCanvasImp _canvasImp; + private Core.Animation _app; + + public override void Run() + { + Console.WriteLine("Starting Blazor program"); + + // Disable colored console ouput, not supported + Diagnostics.UseConsoleColor(false); + Diagnostics.SetMinDebugOutputLoggingSeverityLevel(Diagnostics.SeverityLevel.Verbose); + + base.Run(); + + // Inject Fusee.Engine.Base InjectMe dependencies + Base.Core.IO.IOImp = new Fusee.Base.Imp.Blazor.IO(); + + #region FAP + + var fap = new Fusee.Base.Imp.Blazor.AssetProvider(Runtime); + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(Base.Core.Font), + Decoder = (_, __) => throw new System.NotImplementedException("Non-async decoder isn't supported in Blazor builds"), + DecoderAsync = async (string id, object storage) => + { + if (Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase)) + { + var font = new Base.Core.Font + { + _fontImp = new FontImp((Stream)storage) + }; + + return await Task.FromResult(font); + } + + return null; + }, + Checker = (string id) => + { + return Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase); + } + }); + + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(SceneContainer), + Decoder = (_, __) => throw new System.NotImplementedException("Non-async decoder isn't supported in Blazor builds"), + DecoderAsync = async (string id, object storage) => + { + if (Path.GetExtension(id).IndexOf("fus", System.StringComparison.OrdinalIgnoreCase) >= 0) + { + return await FusSceneConverter.ConvertFromAsync(Serializer.Deserialize((System.IO.Stream)storage)); + } + return null; + }, + Checker = (string id) => + { + return Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase); + } + }); + + // Image handler + fap.RegisterTypeHandler(new AssetHandler + { + ReturnedType = typeof(Base.Core.ImageData), + Decoder = (_, __) => throw new NotImplementedException("Non-async decoder isn't supported in Blazor builds"), + DecoderAsync = async (string id, object storage) => + { + var ext = Path.GetExtension(id).ToLower(); + + try + { + //using var ms = new MemoryStream(); + //((Stream)storage).CopyTo(ms); + using var image = await Image.LoadAsync((Stream)storage); + + image.Mutate(x => x.AutoOrient()); + image.Mutate(x => x.RotateFlip(RotateMode.None, FlipMode.Vertical)); + var ret = ReadPixels(image); + + return ret; + + // inner method to prevent Span inside async method error + static ImageData ReadPixels(Image image) + { + var bpp = image.PixelType.BitsPerPixel; + + switch (image.PixelType.BitsPerPixel) + { + case 16: + { + (image as Image).TryGetSinglePixelSpan(out var res); + var resBytes = MemoryMarshal.AsBytes(res.ToArray()); + return new ImageData(resBytes.ToArray(), image.Width, image.Height, + new ImagePixelFormat(ColorFormat.Depth16)); + } + case 24: + { + var rgb = image as Image; + + rgb.TryGetSinglePixelSpan(out var res); + var resBytes = MemoryMarshal.AsBytes(res.ToArray()); + return new ImageData(resBytes.ToArray(), image.Width, image.Height, + new ImagePixelFormat(ColorFormat.RGB)); + } + case 32: + { + var rgba = image as Image; + + rgba.TryGetSinglePixelSpan(out var res); + var resBytes = MemoryMarshal.AsBytes(res.ToArray()); + return new ImageData(resBytes.ToArray(), image.Width, image.Height, + new ImagePixelFormat(ColorFormat.RGBA)); + } + case 48: + { + var rgba = image as Image; + + rgba.TryGetSinglePixelSpan(out var res); + var resBytes = MemoryMarshal.AsBytes(res.ToArray()); + return new ImageData(resBytes.ToArray(), image.Width, image.Height, + new ImagePixelFormat(ColorFormat.fRGB32)); + } + case 64: + { + (image as Image).TryGetSinglePixelSpan(out var res); + var resBytes = MemoryMarshal.AsBytes(res.ToArray()); + return new ImageData(resBytes.ToArray(), image.Width, image.Height, + new ImagePixelFormat(ColorFormat.fRGBA32)); + } + default: + { + Console.WriteLine($"Error converting! {bpp}"); + + throw new ArgumentException($"{bpp} Bits per pixel not supported!"); + + } + } + }; + } + catch (Exception ex) + { + Console.WriteLine($"Error loading/converting image {id} {ex}"); + Diagnostics.Error($"Error loading/converting image {id}", ex); + + // return empty 1x1 image + return new ImageData(new byte[] { 0, 0, 0, 1, 0, 0, 0, 1 }, 1, 1, + new ImagePixelFormat(ColorFormat.RGBA)); + + } + + }, + Checker = (string id) => + { + var ext = Path.GetExtension(id).ToLower(); + return true; + } + }); + + AssetStorage.RegisterProvider(fap); + + #endregion + + _app = new Core.Simple(); + + // Inject Fusee.Engine InjectMe dependencies (hard coded) + _canvasImp = new RenderCanvasImp(canvas, Runtime, gl, canvasWidth, canvasHeight); + _app.CanvasImplementor = _canvasImp; + _app.ContextImplementor = new RenderContextImp(_app.CanvasImplementor); + Input.AddDriverImp(new RenderCanvasInputDriverImp(_app.CanvasImplementor, Runtime)); + + _app.LoadingCompleted += (s, e) => + { + Console.WriteLine("Loading finished"); + ((IJSInProcessRuntime)Runtime).InvokeVoid("LoadingFinished"); + }; + + _app.InitApp(); + + // Start the app + _app.Run(); + } + + public override void Update(double elapsedMilliseconds) + { + if (_canvasImp != null) + _canvasImp.DeltaTimeUpdate = (float)(elapsedMilliseconds / 1000.0); + + _canvasImp?.DoUpdate(); + } + + public override void Draw(double elapsedMilliseconds) + { + if (_canvasImp != null) + _canvasImp.DeltaTime = (float)(elapsedMilliseconds / 1000.0); + + _canvasImp?.DoRender(); + } + + public override void Resize(int width, int height) + { + base.Resize(width, height); + _canvasImp?.DoResize(width, height); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/Pages/Index.razor b/Examples/Complete/Animation/Blazor/Pages/Index.razor new file mode 100644 index 000000000..d77426ddb --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Pages/Index.razor @@ -0,0 +1,23 @@ +@page "/" +@using System.Runtime.CompilerServices +@using System.Diagnostics.CodeAnalysis +@inject IJSRuntime JS + + +@code +{ + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + var program = new Fusee.Base.Imp.Blazor.BlazorProgramm(); + var main = new Main(); + program.Start(main, (IJSInProcessRuntime)JS); + } + + + + await base.OnAfterRenderAsync(firstRender); + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/Program.cs b/Examples/Complete/Animation/Blazor/Program.cs new file mode 100644 index 000000000..27cce6ddb --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Program.cs @@ -0,0 +1,27 @@ +using Fusee.Base.Core; +using Fusee.Base.Imp.Blazor; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Fusee.Examples.Simple.Blazor +{ + public class Program + { + public static async Task Main(string[] args) + { + var builder = WebAssemblyHostBuilder.CreateDefault(args); + builder.RootComponents.Add("#app"); + + builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); + + await builder.Build().RunAsync(); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/Properties/launchSettings.json b/Examples/Complete/Animation/Blazor/Properties/launchSettings.json new file mode 100644 index 000000000..a8e32d2de --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Properties/launchSettings.json @@ -0,0 +1,20 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49678", + "sslPort": 44374 + } + }, + "profiles": { + "Fusee.Examples.Simple.Blazor": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor b/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor new file mode 100644 index 000000000..3b9976749 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor @@ -0,0 +1,5 @@ +@inherits LayoutComponentBase + +
+ @Body +
diff --git a/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor.css b/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor.css new file mode 100644 index 000000000..43c355a47 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/Shared/MainLayout.razor.css @@ -0,0 +1,70 @@ +.page { + position: relative; + display: flex; + flex-direction: column; +} + +.main { + flex: 1; +} + +.sidebar { + background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); +} + +.top-row { + background-color: #f7f7f7; + border-bottom: 1px solid #d6d5d5; + justify-content: flex-end; + height: 3.5rem; + display: flex; + align-items: center; +} + + .top-row ::deep a, .top-row .btn-link { + white-space: nowrap; + margin-left: 1.5rem; + } + + .top-row a:first-child { + overflow: hidden; + text-overflow: ellipsis; + } + +@media (max-width: 640.98px) { + .top-row:not(.auth) { + display: none; + } + + .top-row.auth { + justify-content: space-between; + } + + .top-row a, .top-row .btn-link { + margin-left: 0; + } +} + +@media (min-width: 641px) { + .page { + flex-direction: row; + } + + .sidebar { + width: 250px; + height: 100vh; + position: sticky; + top: 0; + } + + .top-row { + position: sticky; + top: 0; + z-index: 1; + } + + .main > div { + padding-left: 2rem !important; + padding-right: 1.5rem !important; + } +} diff --git a/Examples/Complete/Animation/Blazor/_Imports.razor b/Examples/Complete/Animation/Blazor/_Imports.razor new file mode 100644 index 000000000..ab2685ce4 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/_Imports.razor @@ -0,0 +1,13 @@ +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.AspNetCore.Components.WebAssembly.Http +@using Microsoft.JSInterop +@using Fusee.Examples.Simple.Blazor +@using Fusee.Examples.Simple.Blazor.Shared +@using Fusee.Base.Imp.Blazor +@using Fusee.Engine.Imp.Graphics.Blazor +@using Fusee.Engine.Imp.Blazor \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/FuseeText.png b/Examples/Complete/Animation/Blazor/wwwroot/Assets/FuseeText.png new file mode 100644 index 000000000..af5ffb051 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/Assets/FuseeText.png differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/Lato-Black.ttf b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Lato-Black.ttf new file mode 100644 index 000000000..6848db0d1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Lato-Black.ttf differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/RocketFus.fus b/Examples/Complete/Animation/Blazor/wwwroot/Assets/RocketFus.fus new file mode 100644 index 000000000..cb993b664 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/Assets/RocketFus.fus differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/PixelShader.frag b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/PixelShader.frag new file mode 100644 index 000000000..8b0610e53 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/PixelShader.frag @@ -0,0 +1,8 @@ +#include "Blinn/Blinn_CalculatePixelColor.frag" + +out vec4 oColor; + +void main(void) +{ + oColor = CalculatePixelColor(); +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/VertexShader.vert b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/VertexShader.vert new file mode 100644 index 000000000..d9e524c78 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/Shader/VertexShader.vert @@ -0,0 +1,6 @@ +#include "Blinn/Blinn_CalculateVertexPosition.vert" + +void main(void) +{ + gl_Position = CalculateVertexPosition(); +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSlice.vert b/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSlice.vert new file mode 100644 index 000000000..6c637213a --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSlice.vert @@ -0,0 +1,183 @@ +#version 300 es + +in vec3 fuVertex; +in vec3 fuNormal; +in vec2 fuUV; + +out vec2 vUv; +out vec3 vMVNormal; +out vec4 fragBorders; + +uniform mat4 FUSEE_MVP; +uniform mat4 FUSEE_ITMV; +uniform mat4 FUSEE_IMV; +uniform mat4 FUSEE_M; +uniform mat4 FUSEE_V; +uniform mat4 FUSEE_P; +uniform vec4 borders; +uniform vec4 borderThickness; + +bool isFloatEqual(float a, float b) +{ + return (a + 0.000001 >= b) && (a - 0.000001 <= b); +} + +vec4 calculateTranslationVector(vec2 scale, vec2 borderThicknessXY, float borderX, bool isXnegative, float borderY, bool isYnegative, vec3 coordinateSysVecX, vec3 coordinateSysVecY) +{ + vec4 translateXVec = vec4(0.0,0.0,0.0,0.0); + vec4 translateYVec = vec4(0.0,0.0,0.0,0.0); + float translateX = 0.0; + float translateY = 0.0; + + if( borderX > 0.00001) + { + float isX = abs(fuVertex.x * (scale.x)); + float translateToX = (((scale.x/2.0) - (borderThicknessXY.x * borderX)) - isX); + translateXVec = (isXnegative) ? vec4(normalize(coordinateSysVecX) * -translateToX,0.0) : vec4(coordinateSysVecX * translateToX,0.0); + } + + if( borderY > 0.00001 ) + { + float isY = abs(fuVertex.y * (scale.y)); + float translateToY = (((scale.y/2.0) - (borderThicknessXY.y * borderY)) - isY); + + translateYVec = (isYnegative) ? vec4(normalize(coordinateSysVecY) * -translateToY,0.0) : vec4(coordinateSysVecY * translateToY,0.0); + } + return (translateXVec + translateYVec); +} + +vec4 calculateGlPosAccordingToUvs() +{ + vec2 scale = vec2(length(FUSEE_M[0]),length(FUSEE_M[1])); + + mat4 origPlaneCoord = mat4(1.0); + origPlaneCoord[2][2] = -1.0; + + mat4 planeCoord = FUSEE_M * origPlaneCoord; + + vec3 xVec = normalize(planeCoord[0].xyz); + vec3 yVec = normalize(planeCoord[1].xyz); + + float offsetL = borders.x; + float offsetR = borders.y; + float offsetT = borders.z; + float offsetB = borders.w; + + //left bottom corner + if(isFloatEqual(vUv.x, 1.0/3.0) && isFloatEqual(vUv.y, 1.0/3.0)) + { + //Set Vertex and UV in unit plane, according to given border. + gl_Position = vec4(-(0.5-offsetL), -(0.5-offsetB), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + //Translate the Vertex according to the scaling of the plane. + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.w), offsetL, true, offsetB, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.x, 1.0/3.0) && isFloatEqual(vUv.y, 0.0)) + { + gl_Position = vec4(-(0.5-offsetL), -0.5, 0.0, 1.0); + vUv = vec2(gl_Position.x,gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.w), offsetL, true, 0.0, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.y, 1.0/3.0) && isFloatEqual(vUv.x, 0.0)) + { + gl_Position = vec4(-0.5, -(0.5-offsetB), 0.0, 1.0); + vUv = vec2(gl_Position.x,gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.w), 0.0, true, offsetB, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + //left top corner + if(isFloatEqual(vUv.x, 1.0/3.0) && isFloatEqual(vUv.y, 2.0/3.0)) + { + gl_Position = vec4(-(0.5-offsetL), (0.5-offsetT), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.z), offsetL, true, offsetT, false, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.x, 1.0/3.0) && isFloatEqual(vUv.y, 1.0)) + { + gl_Position = vec4(-(0.5-offsetL), 0.5, 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.z), offsetL, true, 0.0, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.y, 2.0/3.0) && isFloatEqual(vUv.x, 0.0)) + { + gl_Position = vec4(-0.5, (0.5-offsetT), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.x,borderThickness.z), 0.0, true, offsetT, false, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + //right bottom corner + if(isFloatEqual(vUv.x, 2.0/3.0) && isFloatEqual(vUv.y, 1.0/3.0)) + { + gl_Position = vec4((0.5-offsetR), -(0.5-offsetB), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.w), offsetR, false, offsetB, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.x, 2.0/3.0) && isFloatEqual(vUv.y, 0.0)) + { + gl_Position = vec4((0.5-offsetR), -0.5, 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.w), offsetR, false, 0.0, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.y, 1.0/3.0) && isFloatEqual(vUv.x, 1.0)) + { + gl_Position = vec4(0.5, -(0.5-offsetB), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.w), 0.0, true, offsetB, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + //right top corner + if(isFloatEqual(vUv.x, 2.0/3.0) && isFloatEqual(vUv.y, 2.0/3.0)) + { + gl_Position = vec4((0.5-offsetR), (0.5-offsetT), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.z), offsetR, false, offsetT, false, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.x, 2.0/3.0) && isFloatEqual(vUv.y, 1.0)) + { + gl_Position = vec4((0.5-offsetR), 0.5, 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.z), offsetR, false, 0.0, true, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + if(isFloatEqual(vUv.y, 2.0/3.0) && isFloatEqual(vUv.x, 1.0)) + { + gl_Position = vec4(0.5, (0.5-offsetT), 0.0, 1.0); + vUv = vec2(gl_Position.x, gl_Position.y) + vec2(0.5,0.5); + + vec4 translateVec = calculateTranslationVector(scale,vec2(borderThickness.y,borderThickness.z), 0.0, false, offsetT, false, xVec, yVec); + return(FUSEE_P * FUSEE_V * ((FUSEE_M * vec4(fuVertex, 1.0)) + translateVec)); + } + //corner vertices + if((isFloatEqual(vUv.x, 1.0) && isFloatEqual(vUv.y, 0.0)) || (isFloatEqual(vUv.x, 1.0) && isFloatEqual(vUv.y, 1.0)) || (isFloatEqual(vUv.x,0.0) && isFloatEqual(vUv.y, 1.0)) || (isFloatEqual(vUv.x, 0.0) && isFloatEqual(vUv.y, 0.0))) + { + return(FUSEE_P * FUSEE_V * FUSEE_M * vec4(fuVertex, 1.0)); + } +} + +void main() +{ + vUv = fuUV; + fragBorders = borders; + + vMVNormal = normalize(mat3(FUSEE_ITMV) * fuNormal); + //gl_Position = FUSEE_P * FUSEE_V * FUSEE_M * vec4(fuVertex, 1.0); + gl_Position = calculateGlPosAccordingToUvs(); +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSliceTile.frag b/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSliceTile.frag new file mode 100644 index 000000000..d64ec0896 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/nineSliceTile.frag @@ -0,0 +1,97 @@ +#version 300 es + +#ifdef GL_ES +precision highp float; +#endif + +in vec3 vMVNormal; +in vec2 vUv; +in vec4 fragBorders; + +uniform sampler2D AlbedoTexture; +uniform vec4 Albedo; +uniform float AlbedoMix; +uniform vec2 Tile; + +out vec4 outColor; + +//Scales value from range [fromMin, fromMax] to range [toMin, toMax] +float bringInRange(float fromMin, float fromMax, float toMin, float toMax, float value) +{ + float nominator = (toMax - toMin) * (value - fromMin); + float denominator = fromMax - fromMin; + return (nominator/denominator) + toMin; +} + +float calculateUvY(float currentTileY, vec2 p1, vec2 p4, vec2 Tile, float height) +{ + float uvY = vUv.y; + + //First tile + if(currentTileY == 0.0) + return bringInRange(p1.y , p1.y + height / Tile.y, p1.y, p4.y , vUv.y); + //Last tile + else if(currentTileY == Tile.y) + return bringInRange(p1.y + (height * (currentTileY / Tile.y)), p1.y + height, p1.y, p4.y , vUv.y); + //Every tile inbetween + else + return bringInRange( p1.y + (height * (currentTileY / Tile.y)), p1.y + (height * ((currentTileY + 1.0) / Tile.y)), p1.y, p4.y , vUv.y); + +} + +void main() +{ + vec3 N = normalize(vMVNormal); + vec3 L = vec3(0.0,0.0,-1.0); + + //LRTB + vec2 p1 = vec2(fragBorders.x, fragBorders.w); //lower left + vec2 p2 = vec2(fragBorders.x, 1.0-fragBorders.z); //upper left + vec2 p3 = vec2(1.0-fragBorders.y, 1.0-fragBorders.w); //lower right + vec2 p4 = vec2(1.0-fragBorders.y, 1.0-fragBorders.z); //upper right + + if((vUv.x >= p1.x && vUv.y >= p1.y) && (vUv.x <= p4.x && vUv.y <= p4.y)) + { + float currentTileX = floor(Tile.x * bringInRange(p1.x, p4.x, 0.0 ,1.0 , vUv.x)); + float currentTileY = floor(Tile.y * bringInRange(p1.y, p4.y, 0.0 ,1.0 , vUv.y)); + + float width = p4.x - p1.x; + float height = p4.y - p1.y; + + //Fist tile + if(currentTileX == 0.0) + { + float uvX = bringInRange(p1.x , p1.x + width / Tile.x, p1.x, p4.x , vUv.x); + float uvY = calculateUvY(currentTileY,p1, p4, Tile, height); + + vec4 baseColor = texture(AlbedoTexture, vec2(uvX, uvY)) * AlbedoMix * Albedo; + vec3 diff = baseColor.rgb * max(dot(N, L), 0.0); + outColor = vec4(diff, baseColor.a); + } + //Last tile + else if(currentTileX == Tile.x) + { + float uvX = bringInRange(p1.x + (width * (currentTileX / Tile.x)), p1.x + width, p1.x, p4.x , vUv.x); + float uvY = calculateUvY(currentTileY,p1, p4, Tile, height); + + vec4 baseColor = texture(AlbedoTexture, vec2(uvX, uvY)) * AlbedoMix * Albedo; + vec3 diff = baseColor.rgb * max(dot(N, L), 0.0); + outColor = vec4(diff, baseColor.a); + } + //Every tile inbetween + else + { + float uvX = bringInRange( p1.x + (width * (currentTileX / Tile.x)), p1.x + (width * ((currentTileX + 1.0) / Tile.x)), p1.x, p4.x , vUv.x); + float uvY = calculateUvY(currentTileY,p1, p4, Tile, height); + + vec4 baseColor = texture(AlbedoTexture, vec2(uvX , uvY)) * AlbedoMix * Albedo; + vec3 diff = baseColor.rgb * max(dot(N, L), 0.0); + outColor = vec4(diff, baseColor.a); + } + } + else{ + vec4 baseColor = texture(AlbedoTexture, vUv) * AlbedoMix* Albedo; + vec3 diff = baseColor.rgb * max(dot(N, L), 0.0); + outColor = vec4(diff, baseColor.a); + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/text.frag b/Examples/Complete/Animation/Blazor/wwwroot/Assets/text.frag new file mode 100644 index 000000000..4b3f0f68c --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/text.frag @@ -0,0 +1,50 @@ +#version 300 es + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 vUv; +in vec3 vMVNormal; + +uniform sampler2D AlbedoTexture; +uniform vec2 AlbedoTextureTiles; +uniform vec4 Albedo; +uniform float AlbedoMix; +uniform int FUSEE_PLATFORM_ID; + +out vec4 outColor; + +vec3 EncodeSRgb(vec3 linearRGB) +{ + vec3 a = 12.92 * linearRGB; + vec3 b = 1.055 * pow(linearRGB, vec3(1.0 / 2.4)) - 0.055; + vec3 c = step(vec3(0.0031308), linearRGB); + return mix(a, b, c); +} + +void main() +{ + vec3 N = normalize(vMVNormal); + vec3 L = vec3(0.0, 0.0, -1.0); + + vec3 lightColor = vec3(1.0, 1.0, 1.0); + vec4 objCol = vec4(0.0, 0.0, 0.0, 1.0); + vec4 texCol = texture(AlbedoTexture, vUv * AlbedoTextureTiles); + vec3 mixCol = mix(Albedo.xyz, texCol.xyz, AlbedoMix); + + if (FUSEE_PLATFORM_ID == 1 || FUSEE_PLATFORM_ID == 3) + { + objCol = vec4(mixCol.rgb, texCol.r); + } + else + { + objCol = vec4(mixCol, texCol.a); + } + + vec4 Idif = vec4(max(dot(N, L), 0.0) * lightColor, 1.0); + + vec4 linearOutCol = Idif * objCol; + + outColor = vec4(EncodeSRgb(linearOutCol.rgb), linearOutCol.a); +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.frag b/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.frag new file mode 100644 index 000000000..a45394bcd --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.frag @@ -0,0 +1,47 @@ +#version 300 es + +#ifdef GL_ES +precision highp float; +#endif + +in vec2 vUv; +in vec3 vMVNormal; + +uniform sampler2D AlbedoTexture; +uniform vec2 AlbedoTextureTiles; +uniform vec4 Albedo; +uniform float AlbedoMix; + +out vec4 outColor; + +vec3 EncodeSRgb(vec3 linearRGB) +{ + vec3 a = 12.92 * linearRGB; + vec3 b = 1.055 * pow(linearRGB, vec3(1.0 / 2.4)) - 0.055; + vec3 c = step(vec3(0.0031308), linearRGB); + return mix(a, b, c); +} + +vec3 DecodeSRgb(vec3 sRgb) +{ + vec3 a = sRgb / 12.92; + vec3 b = pow((sRgb + 0.055) / 1.055, vec3(2.4)); + vec3 c = step(vec3(0.04045), sRgb); + return mix(a, b, c); +} + +void main() +{ + vec3 N = normalize(vMVNormal); + vec3 L = vec3(0.0, 0.0, -1.0); + + vec3 lightColor = vec3(1.0, 1.0, 1.0); + vec4 texCol = texture(AlbedoTexture, vUv * AlbedoTextureTiles); + + texCol = vec4(DecodeSRgb(texCol.rgb), texCol.a); + float linearLuminance = (0.2126 * texCol.r) + (0.7152 * texCol.g) + (0.0722 * texCol.b); + + vec3 Idif = vec3(max(dot(N, L), 0.0) * lightColor); + vec3 linearOutCol = Idif * mix(Albedo.rgb * linearLuminance, texCol.rgb, AlbedoMix); + outColor = vec4(EncodeSRgb(linearOutCol.rgb), texCol.a); +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.vert b/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.vert new file mode 100644 index 000000000..06ddf5a0b --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/Assets/texture.vert @@ -0,0 +1,22 @@ +#version 300 es + +in vec3 fuVertex; +in vec3 fuNormal; +in vec2 fuUV; + +out vec2 vUv; +out vec3 vMVNormal; + +uniform mat4 FUSEE_MVP; +uniform mat4 FUSEE_ITMV; +uniform mat4 FUSEE_IMV; + + +void main() +{ + vUv = fuUV; + + vMVNormal = normalize(mat3(FUSEE_ITMV) * fuNormal); + gl_Position = FUSEE_MVP * vec4(fuVertex, 1.0); + +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Authorization.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Authorization.dll new file mode 100644 index 000000000..0fcca6f3b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Authorization.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Forms.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Forms.dll new file mode 100644 index 000000000..98c83415e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Forms.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Web.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Web.dll new file mode 100644 index 000000000..49240666a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.Web.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.WebAssembly.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.WebAssembly.dll new file mode 100644 index 000000000..03a467d8c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.WebAssembly.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.dll new file mode 100644 index 000000000..8bc8bc186 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Components.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Metadata.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Metadata.dll new file mode 100644 index 000000000..83d35fa45 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.AspNetCore.Metadata.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.CSharp.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.CSharp.dll new file mode 100644 index 000000000..60da2d01d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.CSharp.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Abstractions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Abstractions.dll new file mode 100644 index 000000000..c9da0ee14 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Abstractions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Binder.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Binder.dll new file mode 100644 index 000000000..547f622a8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Binder.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.FileExtensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.FileExtensions.dll new file mode 100644 index 000000000..dc17b548a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.FileExtensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Json.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Json.dll new file mode 100644 index 000000000..ee8f6cd46 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.Json.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.dll new file mode 100644 index 000000000..856e7c2e2 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Configuration.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.Abstractions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.Abstractions.dll new file mode 100644 index 000000000..0eb728cc8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.Abstractions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.dll new file mode 100644 index 000000000..86ab7d2de Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.DependencyInjection.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Abstractions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Abstractions.dll new file mode 100644 index 000000000..4c8b346f0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Abstractions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Physical.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Physical.dll new file mode 100644 index 000000000..92c3d654c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileProviders.Physical.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileSystemGlobbing.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileSystemGlobbing.dll new file mode 100644 index 000000000..3c01af84f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.FileSystemGlobbing.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.Abstractions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.Abstractions.dll new file mode 100644 index 000000000..a9a16f431 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.Abstractions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.dll new file mode 100644 index 000000000..d132872c7 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Logging.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Options.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Options.dll new file mode 100644 index 000000000..89de3610c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Options.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Primitives.dll new file mode 100644 index 000000000..befa607e6 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Extensions.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.WebAssembly.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.WebAssembly.dll new file mode 100644 index 000000000..431affdee Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.WebAssembly.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.dll new file mode 100644 index 000000000..8783527a3 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.JSInterop.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.Core.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.Core.dll new file mode 100644 index 000000000..5d99f81f8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.Core.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.dll new file mode 100644 index 000000000..583b36123 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.VisualBasic.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Primitives.dll new file mode 100644 index 000000000..1fdb49955 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Registry.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Registry.dll new file mode 100644 index 000000000..70e23abe5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Microsoft.Win32.Registry.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/Mono.WebAssembly.Interop.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Mono.WebAssembly.Interop.dll new file mode 100644 index 000000000..a761f091d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/Mono.WebAssembly.Interop.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/SharpFontManaged.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/SharpFontManaged.dll new file mode 100644 index 000000000..de3b06c4d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/SharpFontManaged.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.AppContext.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.AppContext.dll new file mode 100644 index 000000000..77c26430b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.AppContext.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Buffers.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Buffers.dll new file mode 100644 index 000000000..4b75e71f5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Buffers.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Concurrent.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Concurrent.dll new file mode 100644 index 000000000..a5eebae0b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Concurrent.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Immutable.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Immutable.dll new file mode 100644 index 000000000..87f365c2c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Immutable.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.NonGeneric.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.NonGeneric.dll new file mode 100644 index 000000000..8a6290c6b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.NonGeneric.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Specialized.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Specialized.dll new file mode 100644 index 000000000..ef7ef57d0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.Specialized.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.dll new file mode 100644 index 000000000..569db2ec5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Collections.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Annotations.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Annotations.dll new file mode 100644 index 000000000..e1552e963 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Annotations.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.DataAnnotations.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.DataAnnotations.dll new file mode 100644 index 000000000..77955e792 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.DataAnnotations.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.EventBasedAsync.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.EventBasedAsync.dll new file mode 100644 index 000000000..a17a6dab4 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.EventBasedAsync.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Primitives.dll new file mode 100644 index 000000000..7488ee6b8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.TypeConverter.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.TypeConverter.dll new file mode 100644 index 000000000..e8ccde816 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.TypeConverter.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.dll new file mode 100644 index 000000000..01e21562a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ComponentModel.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Configuration.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Configuration.dll new file mode 100644 index 000000000..61eb6a9c8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Configuration.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Console.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Console.dll new file mode 100644 index 000000000..f46b862a0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Console.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Core.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Core.dll new file mode 100644 index 000000000..6d3e198ce Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Core.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.Common.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.Common.dll new file mode 100644 index 000000000..9efd9cc9b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.Common.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.DataSetExtensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.DataSetExtensions.dll new file mode 100644 index 000000000..959dbee6d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.DataSetExtensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.dll new file mode 100644 index 000000000..c141a7b79 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Data.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Contracts.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Contracts.dll new file mode 100644 index 000000000..371abd373 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Contracts.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Debug.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Debug.dll new file mode 100644 index 000000000..468608936 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Debug.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.DiagnosticSource.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.DiagnosticSource.dll new file mode 100644 index 000000000..e09840443 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.DiagnosticSource.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.FileVersionInfo.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.FileVersionInfo.dll new file mode 100644 index 000000000..0556d5f5d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.FileVersionInfo.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Process.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Process.dll new file mode 100644 index 000000000..f34eb73af Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Process.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.StackTrace.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.StackTrace.dll new file mode 100644 index 000000000..caf7d4809 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.StackTrace.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TextWriterTraceListener.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TextWriterTraceListener.dll new file mode 100644 index 000000000..5c62c4652 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TextWriterTraceListener.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tools.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tools.dll new file mode 100644 index 000000000..79e997a3c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tools.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TraceSource.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TraceSource.dll new file mode 100644 index 000000000..ae22edc71 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.TraceSource.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tracing.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tracing.dll new file mode 100644 index 000000000..157f98334 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Diagnostics.Tracing.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.Primitives.dll new file mode 100644 index 000000000..caa84df2c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.dll new file mode 100644 index 000000000..bae4a9f6c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Drawing.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Dynamic.Runtime.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Dynamic.Runtime.dll new file mode 100644 index 000000000..042fd6600 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Dynamic.Runtime.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Formats.Asn1.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Formats.Asn1.dll new file mode 100644 index 000000000..ed8bb6ec1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Formats.Asn1.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Calendars.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Calendars.dll new file mode 100644 index 000000000..30804991c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Calendars.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Extensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Extensions.dll new file mode 100644 index 000000000..88678bf76 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.Extensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.dll new file mode 100644 index 000000000..21d4cccca Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Globalization.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.Brotli.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.Brotli.dll new file mode 100644 index 000000000..5d2f6eaec Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.Brotli.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.FileSystem.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.FileSystem.dll new file mode 100644 index 000000000..e4b641ae0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.FileSystem.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.ZipFile.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.ZipFile.dll new file mode 100644 index 000000000..2aba28e75 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.ZipFile.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.dll new file mode 100644 index 000000000..3502cc211 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Compression.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.AccessControl.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.AccessControl.dll new file mode 100644 index 000000000..d91a177e9 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.AccessControl.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.DriveInfo.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.DriveInfo.dll new file mode 100644 index 000000000..bd70932a1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.DriveInfo.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Primitives.dll new file mode 100644 index 000000000..fdd2c7b44 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Watcher.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Watcher.dll new file mode 100644 index 000000000..b3f0cb071 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.Watcher.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.dll new file mode 100644 index 000000000..f8a545ca1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.FileSystem.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.IsolatedStorage.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.IsolatedStorage.dll new file mode 100644 index 000000000..913095d3f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.IsolatedStorage.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.MemoryMappedFiles.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.MemoryMappedFiles.dll new file mode 100644 index 000000000..9bc7f8456 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.MemoryMappedFiles.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipelines.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipelines.dll new file mode 100644 index 000000000..74811b712 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipelines.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.AccessControl.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.AccessControl.dll new file mode 100644 index 000000000..d147cf243 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.AccessControl.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.dll new file mode 100644 index 000000000..a290d31e0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.Pipes.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.UnmanagedMemoryStream.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.UnmanagedMemoryStream.dll new file mode 100644 index 000000000..1d2340161 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.UnmanagedMemoryStream.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.dll new file mode 100644 index 000000000..c0fec502e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.IO.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Expressions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Expressions.dll new file mode 100644 index 000000000..c01313755 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Expressions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Parallel.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Parallel.dll new file mode 100644 index 000000000..b6f196476 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Parallel.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Queryable.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Queryable.dll new file mode 100644 index 000000000..7502256c4 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.Queryable.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.dll new file mode 100644 index 000000000..4443f7a1d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Linq.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Memory.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Memory.dll new file mode 100644 index 000000000..d80c59f58 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Memory.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.Json.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.Json.dll new file mode 100644 index 000000000..fedabfa04 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.Json.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.dll new file mode 100644 index 000000000..85a9a549c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Http.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.HttpListener.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.HttpListener.dll new file mode 100644 index 000000000..59a432f3b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.HttpListener.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Mail.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Mail.dll new file mode 100644 index 000000000..146d3ae5e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Mail.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NameResolution.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NameResolution.dll new file mode 100644 index 000000000..56a379d3e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NameResolution.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NetworkInformation.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NetworkInformation.dll new file mode 100644 index 000000000..309afe171 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.NetworkInformation.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Ping.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Ping.dll new file mode 100644 index 000000000..20999f0c2 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Ping.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Primitives.dll new file mode 100644 index 000000000..9855bd251 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Quic.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Quic.dll new file mode 100644 index 000000000..d91360c63 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Quic.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Requests.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Requests.dll new file mode 100644 index 000000000..d932f2934 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Requests.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Security.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Security.dll new file mode 100644 index 000000000..b122cd5b8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Security.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.ServicePoint.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.ServicePoint.dll new file mode 100644 index 000000000..a5f1b121d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.ServicePoint.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Sockets.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Sockets.dll new file mode 100644 index 000000000..543f85310 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.Sockets.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebClient.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebClient.dll new file mode 100644 index 000000000..2ad44437a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebClient.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebHeaderCollection.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebHeaderCollection.dll new file mode 100644 index 000000000..c7b5034d5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebHeaderCollection.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebProxy.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebProxy.dll new file mode 100644 index 000000000..b913d924b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebProxy.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.Client.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.Client.dll new file mode 100644 index 000000000..66fa472a7 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.Client.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.dll new file mode 100644 index 000000000..100130e07 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.WebSockets.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.dll new file mode 100644 index 000000000..197c44a5e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Net.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.Vectors.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.Vectors.dll new file mode 100644 index 000000000..042cde451 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.Vectors.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.dll new file mode 100644 index 000000000..21ded7acb Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Numerics.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ObjectModel.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ObjectModel.dll new file mode 100644 index 000000000..5ea2468be Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ObjectModel.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.CoreLib.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.CoreLib.dll new file mode 100644 index 000000000..ba0004e2b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.CoreLib.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.DataContractSerialization.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.DataContractSerialization.dll new file mode 100644 index 000000000..94c1267a7 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.DataContractSerialization.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Runtime.InteropServices.JavaScript.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Runtime.InteropServices.JavaScript.dll new file mode 100644 index 000000000..91f700354 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Runtime.InteropServices.JavaScript.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Uri.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Uri.dll new file mode 100644 index 000000000..81f35cf33 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Uri.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.Linq.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.Linq.dll new file mode 100644 index 000000000..233bb6762 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.Linq.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.dll new file mode 100644 index 000000000..df5614a79 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Private.Xml.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.DispatchProxy.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.DispatchProxy.dll new file mode 100644 index 000000000..7b2889292 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.DispatchProxy.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.ILGeneration.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.ILGeneration.dll new file mode 100644 index 000000000..7dadba587 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.ILGeneration.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.Lightweight.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.Lightweight.dll new file mode 100644 index 000000000..e525bcc57 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.Lightweight.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.dll new file mode 100644 index 000000000..ea8aa432b Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Emit.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Extensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Extensions.dll new file mode 100644 index 000000000..d7eb56e5e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Extensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Metadata.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Metadata.dll new file mode 100644 index 000000000..9e2ffa563 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Metadata.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Primitives.dll new file mode 100644 index 000000000..b7a7072e8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.TypeExtensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.TypeExtensions.dll new file mode 100644 index 000000000..a39ee9533 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.TypeExtensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.dll new file mode 100644 index 000000000..43364c0d3 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Reflection.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Reader.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Reader.dll new file mode 100644 index 000000000..030b64568 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Reader.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.ResourceManager.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.ResourceManager.dll new file mode 100644 index 000000000..b68a8dbe5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.ResourceManager.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Writer.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Writer.dll new file mode 100644 index 000000000..7e059fb30 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Resources.Writer.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.Unsafe.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.Unsafe.dll new file mode 100644 index 000000000..57d2b4560 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.Unsafe.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.VisualC.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.VisualC.dll new file mode 100644 index 000000000..1520f9f50 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.CompilerServices.VisualC.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Extensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Extensions.dll new file mode 100644 index 000000000..1feb16a05 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Extensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Handles.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Handles.dll new file mode 100644 index 000000000..af82d8aab Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Handles.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.RuntimeInformation.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.RuntimeInformation.dll new file mode 100644 index 000000000..62553ed91 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.RuntimeInformation.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.dll new file mode 100644 index 000000000..fd49ab4fa Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.InteropServices.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Intrinsics.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Intrinsics.dll new file mode 100644 index 000000000..1a08cf68d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Intrinsics.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Loader.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Loader.dll new file mode 100644 index 000000000..f861d3a0f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Loader.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Numerics.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Numerics.dll new file mode 100644 index 000000000..93fa6f662 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Numerics.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Formatters.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Formatters.dll new file mode 100644 index 000000000..21f8c171c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Formatters.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Json.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Json.dll new file mode 100644 index 000000000..c00aedc17 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Json.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Primitives.dll new file mode 100644 index 000000000..267db7937 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Xml.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Xml.dll new file mode 100644 index 000000000..548e85e2a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.Xml.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.dll new file mode 100644 index 000000000..7487f75fa Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.Serialization.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.dll new file mode 100644 index 000000000..fcc59106a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Runtime.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.AccessControl.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.AccessControl.dll new file mode 100644 index 000000000..78bd16e1c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.AccessControl.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Claims.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Claims.dll new file mode 100644 index 000000000..7d607e0da Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Claims.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Algorithms.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Algorithms.dll new file mode 100644 index 000000000..8bf434adc Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Algorithms.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Cng.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Cng.dll new file mode 100644 index 000000000..5bc606949 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Cng.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Csp.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Csp.dll new file mode 100644 index 000000000..4cf3830eb Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Csp.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Encoding.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Encoding.dll new file mode 100644 index 000000000..e0000aff6 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Encoding.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.OpenSsl.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.OpenSsl.dll new file mode 100644 index 000000000..5d5645e8c Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.OpenSsl.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Primitives.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Primitives.dll new file mode 100644 index 000000000..1d591ae82 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.Primitives.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.X509Certificates.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.X509Certificates.dll new file mode 100644 index 000000000..a351884fc Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Cryptography.X509Certificates.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.Windows.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.Windows.dll new file mode 100644 index 000000000..107637b01 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.Windows.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.dll new file mode 100644 index 000000000..ec72940be Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.Principal.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.SecureString.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.SecureString.dll new file mode 100644 index 000000000..6cb21adf2 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.SecureString.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.dll new file mode 100644 index 000000000..14a91aeb1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Security.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceModel.Web.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceModel.Web.dll new file mode 100644 index 000000000..d80d3e0b0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceModel.Web.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceProcess.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceProcess.dll new file mode 100644 index 000000000..2adf58202 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ServiceProcess.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.CodePages.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.CodePages.dll new file mode 100644 index 000000000..5a5837a81 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.CodePages.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.Extensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.Extensions.dll new file mode 100644 index 000000000..cc4e8b098 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.Extensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.dll new file mode 100644 index 000000000..0ee288c4f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encoding.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encodings.Web.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encodings.Web.dll new file mode 100644 index 000000000..3c52c7c0f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Encodings.Web.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Json.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Json.dll new file mode 100644 index 000000000..ee9f9e28d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.Json.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.RegularExpressions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.RegularExpressions.dll new file mode 100644 index 000000000..a0d0c3df5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Text.RegularExpressions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Channels.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Channels.dll new file mode 100644 index 000000000..0e8139e54 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Channels.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Overlapped.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Overlapped.dll new file mode 100644 index 000000000..9ed5b6eb8 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Overlapped.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Dataflow.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Dataflow.dll new file mode 100644 index 000000000..7f628bc8a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Dataflow.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Extensions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Extensions.dll new file mode 100644 index 000000000..b5ec56f6a Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Extensions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Parallel.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Parallel.dll new file mode 100644 index 000000000..c94615309 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.Parallel.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.dll new file mode 100644 index 000000000..050b33f80 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Tasks.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Thread.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Thread.dll new file mode 100644 index 000000000..88102cfb9 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Thread.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.ThreadPool.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.ThreadPool.dll new file mode 100644 index 000000000..2b4892942 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.ThreadPool.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Timer.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Timer.dll new file mode 100644 index 000000000..62a2b53fb Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.Timer.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.dll new file mode 100644 index 000000000..86a749c85 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Threading.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.Local.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.Local.dll new file mode 100644 index 000000000..99dd4ba08 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.Local.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.dll new file mode 100644 index 000000000..3c6d1d1b5 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Transactions.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ValueTuple.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ValueTuple.dll new file mode 100644 index 000000000..828967438 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.ValueTuple.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.HttpUtility.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.HttpUtility.dll new file mode 100644 index 000000000..031a9705f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.HttpUtility.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.dll new file mode 100644 index 000000000..d48482da3 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Web.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Windows.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Windows.dll new file mode 100644 index 000000000..6a0805e68 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Windows.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Linq.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Linq.dll new file mode 100644 index 000000000..73ad661f6 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Linq.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.ReaderWriter.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.ReaderWriter.dll new file mode 100644 index 000000000..4d4bdd68d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.ReaderWriter.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Serialization.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Serialization.dll new file mode 100644 index 000000000..180437bb4 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.Serialization.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XDocument.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XDocument.dll new file mode 100644 index 000000000..1aa86f9f2 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XDocument.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.XDocument.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.XDocument.dll new file mode 100644 index 000000000..dc7c3e79d Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.XDocument.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.dll new file mode 100644 index 000000000..5b2dc9743 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XPath.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlDocument.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlDocument.dll new file mode 100644 index 000000000..ecc556ff2 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlDocument.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlSerializer.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlSerializer.dll new file mode 100644 index 000000000..99c76de19 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.XmlSerializer.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.dll new file mode 100644 index 000000000..d67460a9f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.Xml.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.dll new file mode 100644 index 000000000..4c4524bb0 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/System.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/WebAssembly.Bindings.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/WebAssembly.Bindings.dll new file mode 100644 index 000000000..fd882dd24 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/WebAssembly.Bindings.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/WindowsBase.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/WindowsBase.dll new file mode 100644 index 000000000..453a23b63 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/WindowsBase.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/binding_support.js b/Examples/Complete/Animation/Blazor/wwwroot/_framework/binding_support.js new file mode 100644 index 000000000..74a7e994e --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/binding_support.js @@ -0,0 +1,2277 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var BindingSupportLib = { + $BINDING__postset: 'BINDING.export_functions (Module);', + $BINDING: { + BINDING_ASM: "[System.Private.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.Runtime", + mono_wasm_object_registry: [], + mono_wasm_ref_counter: 0, + mono_wasm_free_list: [], + mono_wasm_owned_objects_frames: [], + mono_wasm_owned_objects_LMF: [], + mono_wasm_marshal_enum_as_int: true, + mono_bindings_init: function (binding_asm) { + this.BINDING_ASM = binding_asm; + }, + + export_functions: function (module) { + module ["mono_bindings_init"] = BINDING.mono_bindings_init.bind(BINDING); + module ["mono_bind_method"] = BINDING.bind_method.bind(BINDING); + module ["mono_method_invoke"] = BINDING.call_method.bind(BINDING); + module ["mono_method_get_call_signature"] = BINDING.mono_method_get_call_signature.bind(BINDING); + module ["mono_method_resolve"] = BINDING.resolve_method_fqn.bind(BINDING); + module ["mono_bind_static_method"] = BINDING.bind_static_method.bind(BINDING); + module ["mono_call_static_method"] = BINDING.call_static_method.bind(BINDING); + module ["mono_bind_assembly_entry_point"] = BINDING.bind_assembly_entry_point.bind(BINDING); + module ["mono_call_assembly_entry_point"] = BINDING.call_assembly_entry_point.bind(BINDING); + module ["mono_intern_string"] = BINDING.mono_intern_string.bind(BINDING); + }, + + bindings_lazy_init: function () { + if (this.init) + return; + + // avoid infinite recursion + this.init = true; + + Array.prototype[Symbol.for("wasm type")] = 1; + ArrayBuffer.prototype[Symbol.for("wasm type")] = 2; + DataView.prototype[Symbol.for("wasm type")] = 3; + Function.prototype[Symbol.for("wasm type")] = 4; + Map.prototype[Symbol.for("wasm type")] = 5; + if (typeof SharedArrayBuffer !== 'undefined') + SharedArrayBuffer.prototype[Symbol.for("wasm type")] = 6; + Int8Array.prototype[Symbol.for("wasm type")] = 10; + Uint8Array.prototype[Symbol.for("wasm type")] = 11; + Uint8ClampedArray.prototype[Symbol.for("wasm type")] = 12; + Int16Array.prototype[Symbol.for("wasm type")] = 13; + Uint16Array.prototype[Symbol.for("wasm type")] = 14; + Int32Array.prototype[Symbol.for("wasm type")] = 15; + Uint32Array.prototype[Symbol.for("wasm type")] = 16; + Float32Array.prototype[Symbol.for("wasm type")] = 17; + Float64Array.prototype[Symbol.for("wasm type")] = 18; + + this.assembly_load = Module.cwrap ('mono_wasm_assembly_load', 'number', ['string']); + this.find_corlib_class = Module.cwrap ('mono_wasm_find_corlib_class', 'number', ['string', 'string']); + this.find_class = Module.cwrap ('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']); + this._find_method = Module.cwrap ('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']); + this.invoke_method = Module.cwrap ('mono_wasm_invoke_method', 'number', ['number', 'number', 'number', 'number']); + this.mono_string_get_utf8 = Module.cwrap ('mono_wasm_string_get_utf8', 'number', ['number']); + this.mono_wasm_string_from_utf16 = Module.cwrap ('mono_wasm_string_from_utf16', 'number', ['number', 'number']); + this.mono_get_obj_type = Module.cwrap ('mono_wasm_get_obj_type', 'number', ['number']); + this.mono_array_length = Module.cwrap ('mono_wasm_array_length', 'number', ['number']); + this.mono_array_get = Module.cwrap ('mono_wasm_array_get', 'number', ['number', 'number']); + this.mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']); + this.mono_obj_array_set = Module.cwrap ('mono_wasm_obj_array_set', 'void', ['number', 'number', 'number']); + this.mono_wasm_register_bundled_satellite_assemblies = Module.cwrap ('mono_wasm_register_bundled_satellite_assemblies', 'void', [ ]); + this.mono_wasm_try_unbox_primitive_and_get_type = Module.cwrap ('mono_wasm_try_unbox_primitive_and_get_type', 'number', ['number', 'number']); + this.mono_wasm_box_primitive = Module.cwrap ('mono_wasm_box_primitive', 'number', ['number', 'number', 'number']); + this.mono_wasm_intern_string = Module.cwrap ('mono_wasm_intern_string', 'number', ['number']); + this.assembly_get_entry_point = Module.cwrap ('mono_wasm_assembly_get_entry_point', 'number', ['number']); + this.mono_wasm_get_delegate_invoke = Module.cwrap ('mono_wasm_get_delegate_invoke', 'number', ['number']); + this.mono_wasm_string_array_new = Module.cwrap ('mono_wasm_string_array_new', 'number', ['number']); + + this._box_buffer = Module._malloc(16); + this._unbox_buffer = Module._malloc(16); + this._class_int32 = this.find_corlib_class ("System", "Int32"); + this._class_uint32 = this.find_corlib_class ("System", "UInt32"); + this._class_double = this.find_corlib_class ("System", "Double"); + this._class_boolean = this.find_corlib_class ("System", "Boolean"); + + // receives a byteoffset into allocated Heap with a size. + this.mono_typed_array_new = Module.cwrap ('mono_wasm_typed_array_new', 'number', ['number','number','number','number']); + + var binding_fqn_asm = this.BINDING_ASM.substring(this.BINDING_ASM.indexOf ("[") + 1, this.BINDING_ASM.indexOf ("]")).trim(); + var binding_fqn_class = this.BINDING_ASM.substring (this.BINDING_ASM.indexOf ("]") + 1).trim(); + + this.binding_module = this.assembly_load (binding_fqn_asm); + if (!this.binding_module) + throw "Can't find bindings module assembly: " + binding_fqn_asm; + + var namespace = null, classname = null; + if (binding_fqn_class !== null && typeof binding_fqn_class !== "undefined") + { + namespace = "System.Runtime.InteropServices.JavaScript"; + classname = binding_fqn_class.length > 0 ? binding_fqn_class : "Runtime"; + if (binding_fqn_class.indexOf(".") != -1) { + var idx = binding_fqn_class.lastIndexOf("."); + namespace = binding_fqn_class.substring (0, idx); + classname = binding_fqn_class.substring (idx + 1); + } + } + + var wasm_runtime_class = this.find_class (this.binding_module, namespace, classname); + if (!wasm_runtime_class) + throw "Can't find " + binding_fqn_class + " class"; + + var get_method = function(method_name) { + var res = BINDING.find_method (wasm_runtime_class, method_name, -1); + if (!res) + throw "Can't find method " + namespace + "." + classname + ":" + method_name; + return res; + }; + + var bind_runtime_method = function (method_name, signature) { + var method = get_method (method_name); + return BINDING.bind_method (method, 0, signature, "BINDINGS_" + method_name); + }; + + // NOTE: The bound methods have a _ prefix on their names to ensure + // that any code relying on the old get_method/call_method pattern will + // break in a more understandable way. + + this._bind_js_obj = bind_runtime_method ("BindIJSObjectReference", "iii"); + this._bind_core_clr_obj = bind_runtime_method ("BindCoreCLRObject", "ii"); + this._bind_existing_obj = bind_runtime_method ("BindExistingObject", "mi"); + this._unbind_raw_obj_and_free = bind_runtime_method ("UnBindRawIJSObjectReferenceAndFree", "ii"); + this._get_js_id = bind_runtime_method ("GetIJSObjectReferenceId", "m"); + this._get_raw_mono_obj = bind_runtime_method ("GetDotNetObject", "i!"); + + this._is_simple_array = bind_runtime_method ("IsSimpleArray", "m"); + this.setup_js_cont = get_method ("SetupJSContinuation"); + + this.create_tcs = get_method ("CreateTaskSource"); + this.set_tcs_result = get_method ("SetTaskSourceResult"); + this.set_tcs_failure = get_method ("SetTaskSourceFailure"); + this.tcs_get_task_and_bind = get_method ("GetTaskAndBind"); + this.get_call_sig = get_method ("GetCallSignature"); + + this._object_to_string = bind_runtime_method ("ObjectToString", "m"); + this.get_date_value = get_method ("GetDateValue"); + this.create_date_time = get_method ("CreateDateTime"); + this.create_uri = get_method ("CreateUri"); + + this.safehandle_addref = get_method ("SafeHandleAddRef"); + this.safehandle_release = get_method ("SafeHandleRelease"); + this.safehandle_get_handle = get_method ("SafeHandleGetHandle"); + this.safehandle_release_by_handle = get_method ("SafeHandleReleaseByHandle"); + + this._are_promises_supported = ((typeof Promise === "object") || (typeof Promise === "function")) && (typeof Promise.resolve === "function"); + + this._empty_string = ""; + this._empty_string_ptr = 0; + this._interned_string_full_root_buffers = []; + this._interned_string_current_root_buffer = null; + this._interned_string_current_root_buffer_count = 0; + this._interned_string_table = new Map (); + this._managed_pointer_to_interned_string_table = new Map (); + }, + + // Ensures the string is already interned on both the managed and JavaScript sides, + // then returns the interned string value (to provide fast reference comparisons like C#) + mono_intern_string: function (string) { + if (string.length === 0) + return this._empty_string; + + var ptr = this.js_string_to_mono_string_interned (string); + var result = this._managed_pointer_to_interned_string_table.get (ptr); + return result; + }, + + _store_string_in_intern_table: function (string, ptr, internIt) { + if (!ptr) + throw new Error ("null pointer passed to _store_string_in_intern_table"); + else if (typeof (ptr) !== "number") + throw new Error (`non-pointer passed to _store_string_in_intern_table: ${typeof(ptr)}`); + + const internBufferSize = 8192; + + if (this._interned_string_current_root_buffer_count >= internBufferSize) { + this._interned_string_full_root_buffers.push (this._interned_string_current_root_buffer); + this._interned_string_current_root_buffer = null; + } + if (!this._interned_string_current_root_buffer) { + this._interned_string_current_root_buffer = MONO.mono_wasm_new_root_buffer (internBufferSize, "interned strings"); + this._interned_string_current_root_buffer_count = 0; + } + + var rootBuffer = this._interned_string_current_root_buffer; + var index = this._interned_string_current_root_buffer_count++; + rootBuffer.set (index, ptr); + + // Store the managed string into the managed intern table. This can theoretically + // provide a different managed object than the one we passed in, so update our + // pointer (stored in the root) with the result. + if (internIt) + rootBuffer.set (index, ptr = this.mono_wasm_intern_string (ptr)); + + if (!ptr) + throw new Error ("mono_wasm_intern_string produced a null pointer"); + + this._interned_string_table.set (string, ptr); + this._managed_pointer_to_interned_string_table.set (ptr, string); + + if ((string.length === 0) && !this._empty_string_ptr) + this._empty_string_ptr = ptr; + + return ptr; + }, + + js_string_to_mono_string_interned: function (string) { + var text = (typeof (string) === "symbol") + ? (string.description || Symbol.keyFor(string) || "") + : string; + + if ((text.length === 0) && this._empty_string_ptr) + return this._empty_string_ptr; + + var ptr = this._interned_string_table.get (string); + if (ptr) + return ptr; + + ptr = this.js_string_to_mono_string_new (text); + ptr = this._store_string_in_intern_table (string, ptr, true); + + return ptr; + }, + + js_string_to_mono_string: function (string) { + if (string === null) + return null; + else if (typeof (string) === "symbol") + return this.js_string_to_mono_string_interned (string); + else if (typeof (string) !== "string") + throw new Error ("Expected string argument"); + + // Always use an interned pointer for empty strings + if (string.length === 0) + return this.js_string_to_mono_string_interned (string); + + // Looking up large strings in the intern table will require the JS runtime to + // potentially hash them and then do full byte-by-byte comparisons, which is + // very expensive. Because we can not guarantee it won't happen, try to minimize + // the cost of this and prevent performance issues for large strings + if (string.length <= 256) { + var interned = this._interned_string_table.get (string); + if (interned) + return interned; + } + + return this.js_string_to_mono_string_new (string); + }, + + js_string_to_mono_string_new: function (string) { + var buffer = Module._malloc ((string.length + 1) * 2); + var buffer16 = (buffer / 2) | 0; + for (var i = 0; i < string.length; i++) + Module.HEAP16[buffer16 + i] = string.charCodeAt (i); + Module.HEAP16[buffer16 + string.length] = 0; + var result = this.mono_wasm_string_from_utf16 (buffer, string.length); + Module._free (buffer); + return result; + }, + + find_method: function (klass, name, n) { + var result = this._find_method(klass, name, n); + if (result) { + if (!this._method_descriptions) + this._method_descriptions = new Map(); + this._method_descriptions.set(result, name); + } + return result; + }, + + get_js_obj: function (js_handle) { + if (js_handle > 0) + return this.mono_wasm_require_handle(js_handle); + return null; + }, + + conv_string: function (mono_obj, interned) { + var interned_instance = this._managed_pointer_to_interned_string_table.get (mono_obj); + if (interned_instance !== undefined) + return interned_instance; + + var result = MONO.string_decoder.copy (mono_obj); + if (interned) { + // This string is interned on the managed side but we didn't have it in our cache. + this._store_string_in_intern_table (result, mono_obj, false); + } + return result; + }, + + is_nested_array: function (ele) { + return this._is_simple_array(ele); + }, + + mono_array_to_js_array: function (mono_array) { + if (mono_array === 0) + return null; + + var arrayRoot = MONO.mono_wasm_new_root (mono_array); + try { + return this._mono_array_root_to_js_array (arrayRoot); + } finally { + arrayRoot.release(); + } + }, + + _mono_array_root_to_js_array: function (arrayRoot) { + if (arrayRoot.value === 0) + return null; + + let elemRoot = MONO.mono_wasm_new_root (); + + try { + var len = this.mono_array_length (arrayRoot.value); + var res = new Array (len); + for (var i = 0; i < len; ++i) + { + elemRoot.value = this.mono_array_get (arrayRoot.value, i); + + if (this.is_nested_array (elemRoot.value)) + res[i] = this._mono_array_root_to_js_array (elemRoot); + else + res[i] = this._unbox_mono_obj_root (elemRoot); + } + } finally { + elemRoot.release (); + } + + return res; + }, + + js_array_to_mono_array: function (js_array, asString = false) { + var mono_array = asString ? this.mono_wasm_string_array_new (js_array.length) : this.mono_obj_array_new (js_array.length); + let [arrayRoot, elemRoot] = MONO.mono_wasm_new_roots ([mono_array, 0]); + + try { + for (var i = 0; i < js_array.length; ++i) { + var obj = js_array[i]; + if (asString) + obj = obj.toString (); + + elemRoot.value = this.js_to_mono_obj (obj); + this.mono_obj_array_set (arrayRoot.value, i, elemRoot.value); + } + + return mono_array; + } finally { + MONO.mono_wasm_release_roots (arrayRoot, elemRoot); + } + }, + + unbox_mono_obj: function (mono_obj) { + if (mono_obj === 0) + return undefined; + + var root = MONO.mono_wasm_new_root (mono_obj); + try { + return this._unbox_mono_obj_root (root); + } finally { + root.release(); + } + }, + + _unbox_delegate_rooted: function (mono_obj) { + var obj = this.extract_js_obj (mono_obj); + obj.__mono_delegate_alive__ = true; + // FIXME: Should we root the object as long as this function has not been GCd? + return function () { + // TODO: Just use Function.bind + return BINDING.invoke_delegate (obj, arguments); + }; + }, + + _unbox_task_rooted: function (mono_obj) { + if (!this._are_promises_supported) + throw new Error ("Promises are not supported thus 'System.Threading.Tasks.Task' can not work in this context."); + + var obj = this.extract_js_obj (mono_obj); + var cont_obj = null; + var promise = new Promise (function (resolve, reject) { + cont_obj = { + resolve: resolve, + reject: reject + }; + }); + + this.call_method (this.setup_js_cont, null, "mo", [ mono_obj, cont_obj ]); + obj.__mono_js_cont__ = cont_obj.__mono_gchandle__; + cont_obj.__mono_js_task__ = obj.__mono_gchandle__; + return promise; + }, + + _unbox_safehandle_rooted: function (mono_obj) { + var addRef = true; + var js_handle = this.call_method(this.safehandle_get_handle, null, "mi", [ mono_obj, addRef ]); + var requiredObject = BINDING.mono_wasm_require_handle (js_handle); + if (addRef) + { + if (typeof this.mono_wasm_owned_objects_LMF === "undefined") + this.mono_wasm_owned_objects_LMF = []; + + this.mono_wasm_owned_objects_LMF.push(js_handle); + } + return requiredObject; + }, + + _unbox_mono_obj_rooted_with_known_nonprimitive_type: function (mono_obj, type) { + //See MARSHAL_TYPE_ defines in driver.c + switch (type) { + case 26: // int64 + case 27: // uint64 + // TODO: Fix this once emscripten offers HEAPI64/HEAPU64 or can return them + throw new Error ("int64 not available"); + case 3: // string + return this.conv_string (mono_obj, false); + case 29: // interned string + return this.conv_string (mono_obj, true); + case 4: //vts + throw new Error ("no idea on how to unbox value types"); + case 5: // delegate + return this._unbox_delegate_rooted (mono_obj); + case 6: // Task + return this._unbox_task_rooted (mono_obj); + case 7: // ref type + return this.extract_js_obj (mono_obj); + case 10: // arrays + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + throw new Error ("Marshalling of primitive arrays are not supported. Use the corresponding TypedArray instead."); + case 20: // clr .NET DateTime + var dateValue = this.call_method(this.get_date_value, null, "md", [ mono_obj ]); + return new Date(dateValue); + case 21: // clr .NET DateTimeOffset + var dateoffsetValue = this._object_to_string (mono_obj); + return dateoffsetValue; + case 22: // clr .NET Uri + var uriValue = this._object_to_string (mono_obj); + return uriValue; + case 23: // clr .NET SafeHandle + return this._unbox_safehandle_rooted (mono_obj); + case 30: + return undefined; + default: + throw new Error ("no idea on how to unbox object kind " + type + " at offset " + mono_obj); + } + }, + + _unbox_mono_obj_root: function (root) { + var mono_obj = root.value; + if (mono_obj === 0) + return undefined; + + var type = this.mono_wasm_try_unbox_primitive_and_get_type (mono_obj, this._unbox_buffer); + switch (type) { + case 1: // int + return Module.HEAP32[this._unbox_buffer / 4]; + case 25: // uint32 + return Module.HEAPU32[this._unbox_buffer / 4]; + case 24: // float32 + return Module.HEAPF32[this._unbox_buffer / 4]; + case 2: // float64 + return Module.HEAPF64[this._unbox_buffer / 8]; + case 8: // boolean + return (Module.HEAP32[this._unbox_buffer / 4]) !== 0; + case 28: // char + return String.fromCharCode(Module.HEAP32[this._unbox_buffer / 4]); + default: + return this._unbox_mono_obj_rooted_with_known_nonprimitive_type (mono_obj, type); + } + }, + + create_task_completion_source: function () { + return this.call_method (this.create_tcs, null, "i", [ -1 ]); + }, + + set_task_result: function (tcs, result) { + tcs.is_mono_tcs_result_set = true; + this.call_method (this.set_tcs_result, null, "oo", [ tcs, result ]); + if (tcs.is_mono_tcs_task_bound) + this.free_task_completion_source(tcs); + }, + + set_task_failure: function (tcs, reason) { + tcs.is_mono_tcs_result_set = true; + this.call_method (this.set_tcs_failure, null, "os", [ tcs, reason.toString () ]); + if (tcs.is_mono_tcs_task_bound) + this.free_task_completion_source(tcs); + }, + + // https://github.com/Planeshifter/emscripten-examples/blob/master/01_PassingArrays/sum_post.js + js_typedarray_to_heap: function(typedArray){ + var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT; + var ptr = Module._malloc(numBytes); + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes); + heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, numBytes)); + return heapBytes; + }, + + _box_js_int: function (js_obj) { + Module.HEAP32[this._box_buffer / 4] = js_obj; + return this.mono_wasm_box_primitive (this._class_int32, this._box_buffer, 4); + }, + + _box_js_uint: function (js_obj) { + Module.HEAPU32[this._box_buffer / 4] = js_obj; + return this.mono_wasm_box_primitive (this._class_uint32, this._box_buffer, 4); + }, + + _box_js_double: function (js_obj) { + Module.HEAPF64[this._box_buffer / 8] = js_obj; + return this.mono_wasm_box_primitive (this._class_double, this._box_buffer, 8); + }, + + _box_js_bool: function (js_obj) { + Module.HEAP32[this._box_buffer / 4] = js_obj ? 1 : 0; + return this.mono_wasm_box_primitive (this._class_boolean, this._box_buffer, 4); + }, + + js_to_mono_obj: function (js_obj) { + this.bindings_lazy_init (); + + // determines if the javascript object is a Promise or Promise like which can happen + // when using an external Promise library. The javascript object should be marshalled + // as managed Task objects. + // + // Example is when Bluebird is included in a web page using a script tag, it overwrites the + // global Promise object by default with its own version of Promise. + function isThenable() { + // When using an external Promise library the Promise.resolve may not be sufficient + // to identify the object as a Promise. + return Promise.resolve(js_obj) === js_obj || + ((typeof js_obj === "object" || typeof js_obj === "function") && typeof js_obj.then === "function") + } + + switch (true) { + case js_obj === null: + case typeof js_obj === "undefined": + return 0; + case typeof js_obj === "number": { + if ((js_obj | 0) === js_obj) + result = this._box_js_int (js_obj); + else if ((js_obj >>> 0) === js_obj) + result = this._box_js_uint (js_obj); + else + result = this._box_js_double (js_obj); + + if (!result) + throw new Error (`Boxing failed for ${js_obj}`); + + return result; + } case typeof js_obj === "string": + return this.js_string_to_mono_string (js_obj); + case typeof js_obj === "symbol": + return this.js_string_to_mono_string_interned (js_obj); + case typeof js_obj === "boolean": + return this._box_js_bool (js_obj); + case isThenable() === true: + var the_task = this.try_extract_mono_obj (js_obj); + if (the_task) + return the_task; + // FIXME: We need to root tcs for an appropriate timespan, at least until the Task + // is resolved + var tcs = this.create_task_completion_source (); + js_obj.then (function (result) { + BINDING.set_task_result (tcs, result); + }, function (reason) { + BINDING.set_task_failure (tcs, reason); + }) + return this.get_task_and_bind (tcs, js_obj); + case js_obj.constructor.name === "Date": + // We may need to take into account the TimeZone Offset + return this.call_method(this.create_date_time, null, "d!", [ js_obj.getTime() ]); + default: + return this.extract_mono_obj (js_obj); + } + }, + js_to_mono_uri: function (js_obj) { + this.bindings_lazy_init (); + + switch (true) { + case js_obj === null: + case typeof js_obj === "undefined": + return 0; + case typeof js_obj === "symbol": + case typeof js_obj === "string": + return this.call_method(this.create_uri, null, "s!", [ js_obj ]) + default: + return this.extract_mono_obj (js_obj); + } + }, + has_backing_array_buffer: function (js_obj) { + return typeof SharedArrayBuffer !== 'undefined' + ? js_obj.buffer instanceof ArrayBuffer || js_obj.buffer instanceof SharedArrayBuffer + : js_obj.buffer instanceof ArrayBuffer; + }, + + js_typed_array_to_array : function (js_obj) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(this.has_backing_array_buffer(js_obj) && js_obj.BYTES_PER_ELEMENT)) + { + var arrayType = js_obj[Symbol.for("wasm type")]; + var heapBytes = this.js_typedarray_to_heap(js_obj); + var bufferArray = this.mono_typed_array_new(heapBytes.byteOffset, js_obj.length, js_obj.BYTES_PER_ELEMENT, arrayType); + Module._free(heapBytes.byteOffset); + return bufferArray; + } + else { + throw new Error("Object '" + js_obj + "' is not a typed array"); + } + + + }, + // Copy the existing typed array to the heap pointed to by the pinned array address + // typed array memory -> copy to heap -> address of managed pinned array + typedarray_copy_to : function (typed_array, pinned_array, begin, end, bytes_per_element) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(this.has_backing_array_buffer(typed_array) && typed_array.BYTES_PER_ELEMENT)) + { + // Some sanity checks of what is being asked of us + // lets play it safe and throw an error here instead of assuming to much. + // Better safe than sorry later + if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT) + throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'"); + + // how much space we have to work with + var num_of_bytes = (end - begin) * bytes_per_element; + // how much typed buffer space are we talking about + var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT; + // only use what is needed. + if (num_of_bytes > view_bytes) + num_of_bytes = view_bytes; + + // offset index into the view + var offset = begin * bytes_per_element; + + // Create a view over the heap pointed to by the pinned array address + var heapBytes = new Uint8Array(Module.HEAPU8.buffer, pinned_array + offset, num_of_bytes); + // Copy the bytes of the typed array to the heap. + heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes)); + + return num_of_bytes; + } + else { + throw new Error("Object '" + typed_array + "' is not a typed array"); + } + + }, + // Copy the pinned array address from pinned_array allocated on the heap to the typed array. + // adress of managed pinned array -> copy from heap -> typed array memory + typedarray_copy_from : function (typed_array, pinned_array, begin, end, bytes_per_element) { + + // JavaScript typed arrays are array-like objects and provide a mechanism for accessing + // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays + // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object) + // is an object representing a chunk of data; it has no format to speak of, and offers no + // mechanism for accessing its contents. In order to access the memory contained in a buffer, + // you need to use a view. A view provides a context — that is, a data type, starting offset, + // and number of elements — that turns the data into an actual typed array. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays + if (!!(this.has_backing_array_buffer(typed_array) && typed_array.BYTES_PER_ELEMENT)) + { + // Some sanity checks of what is being asked of us + // lets play it safe and throw an error here instead of assuming to much. + // Better safe than sorry later + if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT) + throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'"); + + // how much space we have to work with + var num_of_bytes = (end - begin) * bytes_per_element; + // how much typed buffer space are we talking about + var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT; + // only use what is needed. + if (num_of_bytes > view_bytes) + num_of_bytes = view_bytes; + + // Create a new view for mapping + var typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes); + // offset index into the view + var offset = begin * bytes_per_element; + // Set view bytes to value from HEAPU8 + typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array + offset, pinned_array + offset + num_of_bytes)); + return num_of_bytes; + } + else { + throw new Error("Object '" + typed_array + "' is not a typed array"); + } + + }, + // Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array. + // adress of managed pinned array -> copy from heap -> typed array memory + typed_array_from : function (pinned_array, begin, end, bytes_per_element, type) { + + // typed array + var newTypedArray = 0; + + switch (type) + { + case 5: + newTypedArray = new Int8Array(end - begin); + break; + case 6: + newTypedArray = new Uint8Array(end - begin); + break; + case 7: + newTypedArray = new Int16Array(end - begin); + break; + case 8: + newTypedArray = new Uint16Array(end - begin); + break; + case 9: + newTypedArray = new Int32Array(end - begin); + break; + case 10: + newTypedArray = new Uint32Array(end - begin); + break; + case 13: + newTypedArray = new Float32Array(end - begin); + break; + case 14: + newTypedArray = new Float64Array(end - begin); + break; + case 15: // This is a special case because the typed array is also byte[] + newTypedArray = new Uint8ClampedArray(end - begin); + break; + } + + this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element); + return newTypedArray; + }, + js_to_mono_enum: function (js_obj, method, parmIdx) { + this.bindings_lazy_init (); + + if (typeof (js_obj) !== "number") + throw new Error (`Expected numeric value for enum argument, got '${js_obj}'`); + + return js_obj | 0; + }, + wasm_binding_obj_new: function (js_obj_id, ownsHandle, type) + { + return this._bind_js_obj (js_obj_id, ownsHandle, type); + }, + wasm_bind_existing: function (mono_obj, js_id) + { + return this._bind_existing_obj (mono_obj, js_id); + }, + + wasm_bind_core_clr_obj: function (js_id, gc_handle) + { + return this._bind_core_clr_obj (js_id, gc_handle); + }, + + wasm_get_js_id: function (mono_obj) + { + return this._get_js_id (mono_obj); + }, + + wasm_get_raw_obj: function (gchandle) + { + return this._get_raw_mono_obj (gchandle); + }, + + try_extract_mono_obj:function (js_obj) { + if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined") + return 0; + return this.wasm_get_raw_obj (js_obj.__mono_gchandle__); + }, + + mono_method_get_call_signature: function(method, mono_obj) { + this.bindings_lazy_init (); + + return this.call_method (this.get_call_sig, null, "im", [ method, mono_obj ]); + }, + + get_task_and_bind: function (tcs, js_obj) { + var gc_handle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + var task_gchandle = this.call_method (this.tcs_get_task_and_bind, null, "oi", [ tcs, gc_handle + 1 ]); + js_obj.__mono_gchandle__ = task_gchandle; + this.mono_wasm_object_registry[gc_handle] = js_obj; + this.free_task_completion_source(tcs); + tcs.is_mono_tcs_task_bound = true; + js_obj.__mono_bound_tcs__ = tcs.__mono_gchandle__; + tcs.__mono_bound_task__ = js_obj.__mono_gchandle__; + return this.wasm_get_raw_obj (js_obj.__mono_gchandle__); + }, + + free_task_completion_source: function (tcs) { + if (tcs.is_mono_tcs_result_set) + { + this._unbind_raw_obj_and_free (tcs.__mono_gchandle__); + } + if (tcs.__mono_bound_task__) + { + this._unbind_raw_obj_and_free (tcs.__mono_bound_task__); + } + }, + + extract_mono_obj: function (js_obj) { + if (js_obj === null || typeof js_obj === "undefined") + return 0; + + var result = null; + var gc_handle = js_obj.__mono_gchandle__; + if (gc_handle) { + result = this.wasm_get_raw_obj (gc_handle); + + // It's possible the managed object corresponding to this JS object was collected, + // in which case we need to make a new one. + if (!result) { + delete js_obj.__mono_gchandle__; + delete js_obj.is_mono_bridged_obj; + } + } + + if (!result) { + gc_handle = this.mono_wasm_register_obj(js_obj); + result = this.wasm_get_raw_obj (gc_handle); + } + + return result; + }, + + extract_js_obj: function (mono_obj) { + if (mono_obj == 0) + return null; + + var js_id = this.wasm_get_js_id (mono_obj); + if (js_id > 0) + return this.mono_wasm_require_handle(js_id); + + var gcHandle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + var js_obj = { + __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1), + is_mono_bridged_obj: true + }; + + this.mono_wasm_object_registry[gcHandle] = js_obj; + return js_obj; + }, + + _create_named_function: function (name, argumentNames, body, closure) { + var result = null, keys = null, closureArgumentList = null, closureArgumentNames = null; + + if (closure) { + closureArgumentNames = Object.keys (closure); + closureArgumentList = new Array (closureArgumentNames.length); + for (var i = 0, l = closureArgumentNames.length; i < l; i++) + closureArgumentList[i] = closure[closureArgumentNames[i]]; + } + + var constructor = this._create_rebindable_named_function (name, argumentNames, body, closureArgumentNames); + result = constructor.apply (null, closureArgumentList); + + return result; + }, + + _create_rebindable_named_function: function (name, argumentNames, body, closureArgNames) { + var strictPrefix = "\"use strict\";\r\n"; + var uriPrefix = "", escapedFunctionIdentifier = ""; + + if (name) { + uriPrefix = "//# sourceURL=https://mono-wasm.invalid/" + name + "\r\n"; + escapedFunctionIdentifier = name; + } else { + escapedFunctionIdentifier = "unnamed"; + } + + var rawFunctionText = "function " + escapedFunctionIdentifier + "(" + + argumentNames.join(", ") + + ") {\r\n" + + body + + "\r\n};\r\n"; + + var lineBreakRE = /\r(\n?)/g; + + rawFunctionText = + uriPrefix + strictPrefix + + rawFunctionText.replace(lineBreakRE, "\r\n ") + + ` return ${escapedFunctionIdentifier};\r\n`; + + var result = null, keys = null; + + if (closureArgNames) { + keys = closureArgNames.concat ([rawFunctionText]); + } else { + keys = [rawFunctionText]; + } + + result = Function.apply (Function, keys); + return result; + }, + + _create_primitive_converters: function () { + var result = new Map (); + result.set ('m', { steps: [{ }], size: 0}); + result.set ('s', { steps: [{ convert: this.js_string_to_mono_string.bind (this) }], size: 0, needs_root: true }); + result.set ('S', { steps: [{ convert: this.js_string_to_mono_string_interned.bind (this) }], size: 0, needs_root: true }); + result.set ('o', { steps: [{ convert: this.js_to_mono_obj.bind (this) }], size: 0, needs_root: true }); + result.set ('u', { steps: [{ convert: this.js_to_mono_uri.bind (this) }], size: 0, needs_root: true }); + + // result.set ('k', { steps: [{ convert: this.js_to_mono_enum.bind (this), indirect: 'i64'}], size: 8}); + result.set ('j', { steps: [{ convert: this.js_to_mono_enum.bind (this), indirect: 'i32'}], size: 8}); + + result.set ('i', { steps: [{ indirect: 'i32'}], size: 8}); + result.set ('l', { steps: [{ indirect: 'i64'}], size: 8}); + result.set ('f', { steps: [{ indirect: 'float'}], size: 8}); + result.set ('d', { steps: [{ indirect: 'double'}], size: 8}); + + this._primitive_converters = result; + return result; + }, + + _create_converter_for_marshal_string: function (args_marshal) { + var primitiveConverters = this._primitive_converters; + if (!primitiveConverters) + primitiveConverters = this._create_primitive_converters (); + + var steps = []; + var size = 0; + var is_result_definitely_unmarshaled = false, + is_result_possibly_unmarshaled = false, + result_unmarshaled_if_argc = -1, + needs_root_buffer = false; + + for (var i = 0; i < args_marshal.length; ++i) { + var key = args_marshal[i]; + + if (i === args_marshal.length - 1) { + if (key === "!") { + is_result_definitely_unmarshaled = true; + continue; + } else if (key === "m") { + is_result_possibly_unmarshaled = true; + result_unmarshaled_if_argc = args_marshal.length - 1; + } + } else if (key === "!") + throw new Error ("! must be at the end of the signature"); + + var conv = primitiveConverters.get (key); + if (!conv) + throw new Error ("Unknown parameter type " + type); + + var localStep = Object.create (conv.steps[0]); + localStep.size = conv.size; + if (conv.needs_root) + needs_root_buffer = true; + localStep.needs_root = conv.needs_root; + localStep.key = args_marshal[i]; + steps.push (localStep); + size += conv.size; + } + + return { + steps: steps, size: size, args_marshal: args_marshal, + is_result_definitely_unmarshaled: is_result_definitely_unmarshaled, + is_result_possibly_unmarshaled: is_result_possibly_unmarshaled, + result_unmarshaled_if_argc: result_unmarshaled_if_argc, + needs_root_buffer: needs_root_buffer + }; + }, + + _get_converter_for_marshal_string: function (args_marshal) { + if (!this._signature_converters) + this._signature_converters = new Map(); + + var converter = this._signature_converters.get (args_marshal); + if (!converter) { + converter = this._create_converter_for_marshal_string (args_marshal); + this._signature_converters.set (args_marshal, converter); + } + + return converter; + }, + + _compile_converter_for_marshal_string: function (args_marshal) { + var converter = this._get_converter_for_marshal_string (args_marshal); + if (typeof (converter.args_marshal) !== "string") + throw new Error ("Corrupt converter for '" + args_marshal + "'"); + + if (converter.compiled_function && converter.compiled_variadic_function) + return converter; + + var converterName = args_marshal.replace("!", "_result_unmarshaled"); + converter.name = converterName; + + var body = []; + var argumentNames = ["buffer", "rootBuffer", "method"]; + + // worst-case allocation size instead of allocating dynamically, plus padding + var bufferSizeBytes = converter.size + (args_marshal.length * 4) + 16; + var rootBufferSize = args_marshal.length; + // ensure the indirect values are 8-byte aligned so that aligned loads and stores will work + var indirectBaseOffset = ((((args_marshal.length * 4) + 7) / 8) | 0) * 8; + + var closure = {}; + var indirectLocalOffset = 0; + + body.push ( + `if (!buffer) buffer = Module._malloc (${bufferSizeBytes});`, + `var indirectStart = buffer + ${indirectBaseOffset};`, + "var indirect32 = (indirectStart / 4) | 0, indirect64 = (indirectStart / 8) | 0;", + "var buffer32 = (buffer / 4) | 0;", + "" + ); + + for (let i = 0; i < converter.steps.length; i++) { + var step = converter.steps[i]; + var closureKey = "step" + i; + var valueKey = "value" + i; + + var argKey = "arg" + i; + argumentNames.push (argKey); + + if (step.convert) { + closure[closureKey] = step.convert; + body.push (`var ${valueKey} = ${closureKey}(${argKey}, method, ${i});`); + } else { + body.push (`var ${valueKey} = ${argKey};`); + } + + if (step.needs_root) + body.push (`rootBuffer.set (${i}, ${valueKey});`); + + if (step.indirect) { + var heapArrayName = null; + + switch (step.indirect) { + case "u32": + heapArrayName = "HEAPU32"; + break; + case "i32": + heapArrayName = "HEAP32"; + break; + case "float": + heapArrayName = "HEAPF32"; + break; + case "double": + body.push (`Module.HEAPF64[indirect64 + ${(indirectLocalOffset / 8)}] = ${valueKey};`); + break; + case "i64": + body.push (`Module.setValue (indirectStart + ${indirectLocalOffset}, ${valueKey}, 'i64');`); + break; + default: + throw new Error ("Unimplemented indirect type: " + step.indirect); + } + + if (heapArrayName) + body.push (`Module.${heapArrayName}[indirect32 + ${(indirectLocalOffset / 4)}] = ${valueKey};`); + + body.push (`Module.HEAP32[buffer32 + ${i}] = indirectStart + ${indirectLocalOffset};`, ""); + indirectLocalOffset += step.size; + } else { + body.push (`Module.HEAP32[buffer32 + ${i}] = ${valueKey};`, ""); + indirectLocalOffset += 4; + } + } + + body.push ("return buffer;"); + + var bodyJs = body.join ("\r\n"), compiledFunction = null, compiledVariadicFunction = null; + try { + compiledFunction = this._create_named_function("converter_" + converterName, argumentNames, bodyJs, closure); + converter.compiled_function = compiledFunction; + } catch (exc) { + converter.compiled_function = null; + console.warn("compiling converter failed for", bodyJs, "with error", exc); + throw exc; + } + + argumentNames = ["existingBuffer", "rootBuffer", "method", "args"]; + closure = { + converter: compiledFunction + }; + body = [ + "return converter(", + " existingBuffer, rootBuffer, method," + ]; + + for (let i = 0; i < converter.steps.length; i++) { + body.push( + " args[" + i + + ( + (i == converter.steps.length - 1) + ? "]" + : "], " + ) + ); + } + + body.push(");"); + + bodyJs = body.join ("\r\n"); + try { + compiledVariadicFunction = this._create_named_function("variadic_converter_" + converterName, argumentNames, bodyJs, closure); + converter.compiled_variadic_function = compiledVariadicFunction; + } catch (exc) { + converter.compiled_variadic_function = null; + console.warn("compiling converter failed for", bodyJs, "with error", exc); + throw exc; + } + + converter.scratchRootBuffer = null; + converter.scratchBuffer = 0 | 0; + + return converter; + }, + + _verify_args_for_method_call: function (args_marshal, args) { + var has_args = args && (typeof args === "object") && args.length > 0; + var has_args_marshal = typeof args_marshal === "string"; + + if (has_args) { + if (!has_args_marshal) + throw new Error ("No signature provided for method call."); + else if (args.length > args_marshal.length) + throw new Error ("Too many parameter values. Expected at most " + args_marshal.length + " value(s) for signature " + args_marshal); + } + + return has_args_marshal && has_args; + }, + + _get_buffer_for_method_call: function (converter) { + if (!converter) + return 0; + + var result = converter.scratchBuffer; + converter.scratchBuffer = 0; + return result; + }, + + _get_args_root_buffer_for_method_call: function (converter) { + if (!converter) + return null; + + if (!converter.needs_root_buffer) + return null; + + var result; + if (converter.scratchRootBuffer) { + result = converter.scratchRootBuffer; + converter.scratchRootBuffer = null; + } else { + // TODO: Expand the converter's heap allocation and then use + // mono_wasm_new_root_buffer_from_pointer instead. Not that important + // at present because the scratch buffer will be reused unless we are + // recursing through a re-entrant call + result = MONO.mono_wasm_new_root_buffer (converter.steps.length); + result.converter = converter; + } + return result; + }, + + _release_args_root_buffer_from_method_call: function (converter, argsRootBuffer) { + if (!argsRootBuffer || !converter) + return; + + // Store the arguments root buffer for re-use in later calls + if (!converter.scratchRootBuffer) { + argsRootBuffer.clear (); + converter.scratchRootBuffer = argsRootBuffer; + } else { + argsRootBuffer.release (); + } + }, + + _release_buffer_from_method_call: function (converter, buffer) { + if (!converter || !buffer) + return; + + if (!converter.scratchBuffer) + converter.scratchBuffer = buffer | 0; + else + Module._free (buffer | 0); + }, + + _convert_exception_for_method_call: function (result, exception) { + if (exception === 0) + return null; + + var msg = this.conv_string (result, false); + var err = new Error (msg); //the convention is that invoke_method ToString () any outgoing exception + // console.warn ("error", msg, "at location", err.stack); + return err; + }, + + _maybe_produce_signature_warning: function (converter) { + if (converter.has_warned_about_signature) + return; + + console.warn ("MONO_WASM: Deprecated raw return value signature: '" + converter.args_marshal + "'. End the signature with '!' instead of 'm'."); + converter.has_warned_about_signature = true; + }, + + _decide_if_result_is_marshaled: function (converter, argc) { + if (!converter) + return true; + + if ( + converter.is_result_possibly_unmarshaled && + (argc === converter.result_unmarshaled_if_argc) + ) { + if (argc < converter.result_unmarshaled_if_argc) + throw new Error(["Expected >= ", converter.result_unmarshaled_if_argc, "argument(s) but got", argc, "for signature " + converter.args_marshal].join(" ")); + + this._maybe_produce_signature_warning (converter); + return false; + } else { + if (argc < converter.steps.length) + throw new Error(["Expected", converter.steps.length, "argument(s) but got", argc, "for signature " + converter.args_marshal].join(" ")); + + return !converter.is_result_definitely_unmarshaled; + } + }, + + /* + args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values: + + i: int32 + j: int32 - Enum with underlying type of int32 + l: int64 + k: int64 - Enum with underlying type of int64 + f: float + d: double + s: string + S: interned string + o: js object will be converted to a C# object (this will box numbers/bool/promises) + m: raw mono object. Don't use it unless you know what you're doing + + to suppress marshaling of the return value, place '!' at the end of args_marshal, i.e. 'ii!' instead of 'ii' + */ + call_method: function (method, this_arg, args_marshal, args) { + this.bindings_lazy_init (); + + // HACK: Sometimes callers pass null or undefined, coerce it to 0 since that's what wasm expects + this_arg = this_arg | 0; + + // Detect someone accidentally passing the wrong type of value to method + if ((method | 0) !== method) + throw new Error (`method must be an address in the native heap, but was '${method}'`); + if (!method) + throw new Error ("no method specified"); + + var needs_converter = this._verify_args_for_method_call (args_marshal, args); + + var buffer = 0, converter = null, argsRootBuffer = null; + var is_result_marshaled = true; + + // check if the method signature needs argument mashalling + if (needs_converter) { + converter = this._compile_converter_for_marshal_string (args_marshal); + + is_result_marshaled = this._decide_if_result_is_marshaled (converter, args.length); + + argsRootBuffer = this._get_args_root_buffer_for_method_call (converter); + + var scratchBuffer = this._get_buffer_for_method_call (converter); + + buffer = converter.compiled_variadic_function (scratchBuffer, argsRootBuffer, method, args); + } + + return this._call_method_with_converted_args (method, this_arg, converter, buffer, is_result_marshaled, argsRootBuffer); + }, + + _handle_exception_for_call: function ( + converter, buffer, resultRoot, exceptionRoot, argsRootBuffer + ) { + var exc = this._convert_exception_for_method_call (resultRoot.value, exceptionRoot.value); + if (!exc) + return; + + this._teardown_after_call (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer); + throw exc; + }, + + _handle_exception_and_produce_result_for_call: function ( + converter, buffer, resultRoot, exceptionRoot, argsRootBuffer, is_result_marshaled + ) { + this._handle_exception_for_call (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer); + + if (is_result_marshaled) + result = this._unbox_mono_obj_root (resultRoot); + else + result = resultRoot.value; + + this._teardown_after_call (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer); + return result; + }, + + _teardown_after_call: function (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer) { + this._release_args_root_buffer_from_method_call (converter, argsRootBuffer); + this._release_buffer_from_method_call (converter, buffer | 0); + + if (resultRoot) + resultRoot.release (); + if (exceptionRoot) + exceptionRoot.release (); + }, + + _get_method_description: function (method) { + if (!this._method_descriptions) + this._method_descriptions = new Map(); + + var result = this._method_descriptions.get (method); + if (!result) + result = "method#" + method; + return result; + }, + + _call_method_with_converted_args: function (method, this_arg, converter, buffer, is_result_marshaled, argsRootBuffer) { + var resultRoot = MONO.mono_wasm_new_root (), exceptionRoot = MONO.mono_wasm_new_root (); + resultRoot.value = this.invoke_method (method, this_arg, buffer, exceptionRoot.get_address ()); + return this._handle_exception_and_produce_result_for_call (converter, buffer, resultRoot, exceptionRoot, argsRootBuffer, is_result_marshaled); + }, + + bind_method: function (method, this_arg, args_marshal, friendly_name) { + this.bindings_lazy_init (); + + this_arg = this_arg | 0; + + var converter = null; + if (typeof (args_marshal) === "string") + converter = this._compile_converter_for_marshal_string (args_marshal); + + var closure = { + library_mono: MONO, + binding_support: this, + method: method, + this_arg: this_arg + }; + + var converterKey = "converter_" + converter.name; + + if (converter) + closure[converterKey] = converter; + + var argumentNames = []; + var body = [ + "var resultRoot = library_mono.mono_wasm_new_root (), exceptionRoot = library_mono.mono_wasm_new_root ();", + "" + ]; + + if (converter) { + body.push( + `var argsRootBuffer = binding_support._get_args_root_buffer_for_method_call (${converterKey});`, + `var scratchBuffer = binding_support._get_buffer_for_method_call (${converterKey});`, + `var buffer = ${converterKey}.compiled_function (`, + " scratchBuffer, argsRootBuffer, method," + ); + + for (var i = 0; i < converter.steps.length; i++) { + var argName = "arg" + i; + argumentNames.push(argName); + body.push( + " " + argName + + ( + (i == converter.steps.length - 1) + ? "" + : ", " + ) + ); + } + + body.push(");"); + + } else { + body.push("var argsRootBuffer = null, buffer = 0;"); + } + + if (converter.is_result_definitely_unmarshaled) { + body.push ("var is_result_marshaled = false;"); + } else if (converter.is_result_possibly_unmarshaled) { + body.push (`var is_result_marshaled = arguments.length !== ${converter.result_unmarshaled_if_argc};`); + } else { + body.push ("var is_result_marshaled = true;"); + } + + // We inline a bunch of the invoke and marshaling logic here in order to eliminate the GC pressure normally + // created by the unboxing part of the call process. Because unbox_mono_obj(_rooted) can return non-numeric + // types, v8 and spidermonkey allocate and store its result on the heap (in the nursery, to be fair). + // For a bound method however, we know the result will always be the same type because C# methods have known + // return types. Inlining the invoke and marshaling logic means that even though the bound method has logic + // for handling various types, only one path through the method (for its appropriate return type) will ever + // be taken, and the JIT will see that the 'result' local and thus the return value of this function are + // always of the exact same type. All of the branches related to this end up being predicted and low-cost. + // The end result is that bound method invocations don't always allocate, so no more nursery GCs. Yay! -kg + body.push( + "", + "resultRoot.value = binding_support.invoke_method (method, this_arg, buffer, exceptionRoot.get_address ());", + `binding_support._handle_exception_for_call (${converterKey}, buffer, resultRoot, exceptionRoot, argsRootBuffer);`, + "", + "var resultPtr = resultRoot.value, result = undefined;", + "if (!is_result_marshaled) ", + " result = resultPtr;", + "else if (resultPtr !== 0) {", + // For the common scenario where the return type is a primitive, we want to try and unbox it directly + // into our existing heap allocation and then read it out of the heap. Doing this all in one operation + // means that we only need to enter a gc safe region twice (instead of 3+ times with the normal, + // slower check-type-and-then-unbox flow which has extra checks since unbox verifies the type). + " var resultType = binding_support.mono_wasm_try_unbox_primitive_and_get_type (resultPtr, buffer);", + " switch (resultType) {", + " case 1:", // int + " result = Module.HEAP32[buffer / 4]; break;", + " case 25:", // uint32 + " result = Module.HEAPU32[buffer / 4]; break;", + " case 24:", // float32 + " result = Module.HEAPF32[buffer / 4]; break;", + " case 2:", // float64 + " result = Module.HEAPF64[buffer / 8]; break;", + " case 8:", // boolean + " result = (Module.HEAP32[buffer / 4]) !== 0; break;", + " case 28:", // char + " result = String.fromCharCode(Module.HEAP32[buffer / 4]); break;", + " default:", + " result = binding_support._unbox_mono_obj_rooted_with_known_nonprimitive_type (resultPtr, resultType); break;", + " }", + "}", + "", + `binding_support._teardown_after_call (${converterKey}, buffer, resultRoot, exceptionRoot, argsRootBuffer);`, + "return result;" + ); + + bodyJs = body.join ("\r\n"); + + if (friendly_name) { + var escapeRE = /[^A-Za-z0-9_]/g; + friendly_name = friendly_name.replace(escapeRE, "_"); + } + + var displayName = "managed_" + (friendly_name || method); + + if (this_arg) + displayName += "_with_this_" + this_arg; + + return this._create_named_function(displayName, argumentNames, bodyJs, closure); + }, + + invoke_delegate: function (delegate_obj, js_args) { + this.bindings_lazy_init (); + + // Check to make sure the delegate is still alive on the CLR side of things. + if (typeof delegate_obj.__mono_delegate_alive__ !== "undefined") { + if (!delegate_obj.__mono_delegate_alive__) + throw new Error("The delegate target that is being invoked is no longer available. Please check if it has been prematurely GC'd."); + } + + var [delegateRoot] = MONO.mono_wasm_new_roots ([this.extract_mono_obj (delegate_obj)]); + try { + if (typeof delegate_obj.__mono_delegate_invoke__ === "undefined") + delegate_obj.__mono_delegate_invoke__ = this.mono_wasm_get_delegate_invoke(delegateRoot.value); + if (!delegate_obj.__mono_delegate_invoke__) + throw new Error("System.Delegate Invoke method can not be resolved."); + + if (typeof delegate_obj.__mono_delegate_invoke_sig__ === "undefined") + delegate_obj.__mono_delegate_invoke_sig__ = Module.mono_method_get_call_signature (delegate_obj.__mono_delegate_invoke__, delegateRoot.value); + + return this.call_method (delegate_obj.__mono_delegate_invoke__, delegateRoot.value, delegate_obj.__mono_delegate_invoke_sig__, js_args); + } finally { + MONO.mono_wasm_release_roots (delegateRoot); + } + }, + + resolve_method_fqn: function (fqn) { + this.bindings_lazy_init (); + + var assembly = fqn.substring(fqn.indexOf ("[") + 1, fqn.indexOf ("]")).trim(); + fqn = fqn.substring (fqn.indexOf ("]") + 1).trim(); + + var methodname = fqn.substring(fqn.indexOf (":") + 1); + fqn = fqn.substring (0, fqn.indexOf (":")).trim (); + + var namespace = ""; + var classname = fqn; + if (fqn.indexOf(".") != -1) { + var idx = fqn.lastIndexOf("."); + namespace = fqn.substring (0, idx); + classname = fqn.substring (idx + 1); + } + + if (!assembly.trim()) + throw new Error("No assembly name specified"); + if (!classname.trim()) + throw new Error("No class name specified"); + if (!methodname.trim()) + throw new Error("No method name specified"); + + var asm = this.assembly_load (assembly); + if (!asm) + throw new Error ("Could not find assembly: " + assembly); + + var klass = this.find_class(asm, namespace, classname); + if (!klass) + throw new Error ("Could not find class: " + namespace + ":" + classname + " in assembly " + assembly); + + var method = this.find_method (klass, methodname, -1); + if (!method) + throw new Error ("Could not find method: " + methodname); + return method; + }, + + call_static_method: function (fqn, args, signature) { + this.bindings_lazy_init (); + + var method = this.resolve_method_fqn (fqn); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return this.call_method (method, null, signature, args); + }, + + bind_static_method: function (fqn, signature) { + this.bindings_lazy_init (); + + var method = this.resolve_method_fqn (fqn); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return BINDING.bind_method (method, null, signature, fqn); + }, + + bind_assembly_entry_point: function (assembly, signature) { + this.bindings_lazy_init (); + + var asm = this.assembly_load (assembly); + if (!asm) + throw new Error ("Could not find assembly: " + assembly); + + var method = this.assembly_get_entry_point(asm); + if (!method) + throw new Error ("Could not find entry point for assembly: " + assembly); + + if (typeof signature === "undefined") + signature = Module.mono_method_get_call_signature (method); + + return function() { + try { + var args = [...arguments]; + if (args.length > 0 && Array.isArray (args[0])) + args[0] = BINDING.js_array_to_mono_array (args[0], true); + + let result = BINDING.call_method (method, null, signature, args); + return Promise.resolve (result); + } catch (error) { + return Promise.reject (error); + } + }; + }, + call_assembly_entry_point: function (assembly, args, signature) { + return this.bind_assembly_entry_point (assembly, signature) (...args) + }, + // Object wrapping helper functions to handle reference handles that will + // be used in managed code. + mono_wasm_register_obj: function(obj) { + + var gc_handle = undefined; + if (obj !== null && typeof obj !== "undefined") + { + gc_handle = obj.__mono_gchandle__; + + if (typeof gc_handle === "undefined") { + var handle = this.mono_wasm_free_list.length ? + this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++; + obj.__mono_jshandle__ = handle; + // Obtain the JS -> C# type mapping. + var wasm_type = obj[Symbol.for("wasm type")]; + obj.__owns_handle__ = true; + gc_handle = obj.__mono_gchandle__ = this.wasm_binding_obj_new(handle + 1, obj.__owns_handle__, typeof wasm_type === "undefined" ? -1 : wasm_type); + this.mono_wasm_object_registry[handle] = obj; + + } + } + return gc_handle; + }, + mono_wasm_require_handle: function(handle) { + if (handle > 0) + return this.mono_wasm_object_registry[handle - 1]; + return null; + }, + mono_wasm_unregister_obj: function(js_id) { + var obj = this.mono_wasm_object_registry[js_id - 1]; + if (typeof obj !== "undefined" && obj !== null) { + // if this is the global object then do not + // unregister it. + if (globalThis === obj) + return obj; + + var gc_handle = obj.__mono_gchandle__; + if (typeof gc_handle !== "undefined") { + + obj.__mono_gchandle__ = undefined; + obj.__mono_jshandle__ = undefined; + + // If we are unregistering a delegate then mark it as not being alive + // this will be checked in the delegate invoke and throw an appropriate + // error. + if (typeof obj.__mono_delegate_alive__ !== "undefined") + obj.__mono_delegate_alive__ = false; + + this.mono_wasm_object_registry[js_id - 1] = undefined; + this.mono_wasm_free_list.push(js_id - 1); + } + } + return obj; + }, + mono_wasm_free_handle: function(handle) { + this.mono_wasm_unregister_obj(handle); + }, + mono_wasm_free_raw_object: function(js_id) { + var obj = this.mono_wasm_object_registry[js_id - 1]; + if (typeof obj !== "undefined" && obj !== null) { + // if this is the global object then do not + // unregister it. + if (globalThis === obj) + return obj; + + var gc_handle = obj.__mono_gchandle__; + if (typeof gc_handle !== "undefined") { + + obj.__mono_gchandle__ = undefined; + obj.__mono_jshandle__ = undefined; + + this.mono_wasm_object_registry[js_id - 1] = undefined; + this.mono_wasm_free_list.push(js_id - 1); + } + } + return obj; + }, + mono_wasm_parse_args : function (args) { + var js_args = this.mono_array_to_js_array(args); + this.mono_wasm_save_LMF(); + return js_args; + }, + mono_wasm_save_LMF : function () { + //console.log("save LMF: " + BINDING.mono_wasm_owned_objects_frames.length) + BINDING.mono_wasm_owned_objects_frames.push(BINDING.mono_wasm_owned_objects_LMF); + BINDING.mono_wasm_owned_objects_LMF = undefined; + }, + mono_wasm_unwind_LMF : function () { + var __owned_objects__ = this.mono_wasm_owned_objects_frames.pop(); + // Release all managed objects that are loaded into the LMF + if (typeof __owned_objects__ !== "undefined") + { + // Look into passing the array of owned object handles in one pass. + var refidx; + for (refidx = 0; refidx < __owned_objects__.length; refidx++) + { + var ownerRelease = __owned_objects__[refidx]; + this.call_method(this.safehandle_release_by_handle, null, "i", [ ownerRelease ]); + } + } + //console.log("restore LMF: " + BINDING.mono_wasm_owned_objects_frames.length) + + }, + mono_wasm_convert_return_value: function (ret) { + this.mono_wasm_unwind_LMF(); + return this.js_to_mono_obj (ret); + }, + }, + + mono_wasm_invoke_js_with_args: function(js_handle, method_name, args, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.get_js_obj (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_name = BINDING.conv_string (method_name, false); + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'"); + } + + var js_args = BINDING.mono_wasm_parse_args(args); + + var res; + try { + var m = obj [js_name]; + if (typeof m === "undefined") + throw new Error("Method: '" + js_name + "' not found for: '" + Object.prototype.toString.call(obj) + "'"); + var res = m.apply (obj, js_args); + return BINDING.mono_wasm_convert_return_value(res); + } catch (e) { + // make sure we release object reference counts on errors. + BINDING.mono_wasm_unwind_LMF(); + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_get_object_property: function(js_handle, property_name, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_name = BINDING.conv_string (property_name, false); + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'"); + } + + var res; + try { + var m = obj [js_name]; + if (m === Object(m) && obj.__is_mono_proxied__) + m.__is_mono_proxied__ = true; + + return BINDING.js_to_mono_obj (m); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_set_object_property: function (js_handle, property_name, value, createIfNotExist, hasOwnProperty, is_exception) { + + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var property = BINDING.conv_string (property_name, false); + if (!property) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'"); + } + + var result = false; + + var js_value = BINDING.unbox_mono_obj(value); + BINDING.mono_wasm_save_LMF(); + + if (createIfNotExist) { + requireObject[property] = js_value; + result = true; + } + else { + result = false; + if (!createIfNotExist) + { + if (!requireObject.hasOwnProperty(property)) + return false; + } + if (hasOwnProperty === true) { + if (requireObject.hasOwnProperty(property)) { + requireObject[property] = js_value; + result = true; + } + } + else { + requireObject[property] = js_value; + result = true; + } + + } + BINDING.mono_wasm_unwind_LMF(); + return BINDING._box_js_bool (result); + }, + mono_wasm_get_by_index: function(js_handle, property_index, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + try { + var m = obj [property_index]; + return BINDING.js_to_mono_obj (m); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_set_by_index: function(js_handle, property_index, value, is_exception) { + BINDING.bindings_lazy_init (); + + var obj = BINDING.mono_wasm_require_handle (js_handle); + if (!obj) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var js_value = BINDING.unbox_mono_obj(value); + BINDING.mono_wasm_save_LMF(); + + try { + obj [property_index] = js_value; + BINDING.mono_wasm_unwind_LMF(); + return true; + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || typeof res === "undefined") + res = "unknown exception"; + return BINDING.js_string_to_mono_string (res); + } + }, + mono_wasm_get_global_object: function(global_name, is_exception) { + BINDING.bindings_lazy_init (); + + var js_name = BINDING.conv_string (global_name, false); + + var globalObj; + + if (!js_name) { + globalObj = globalThis; + } + else { + globalObj = globalThis[js_name]; + } + + if (globalObj === null || typeof globalObj === undefined) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found."); + } + + return BINDING.js_to_mono_obj (globalObj); + }, + mono_wasm_release_handle: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + BINDING.mono_wasm_free_handle(js_handle); + }, + mono_wasm_release_object: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + BINDING.mono_wasm_free_raw_object(js_handle); + }, + mono_wasm_bind_core_object: function(js_handle, gc_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle ); + requireObject.__mono_gchandle__ = gc_handle; + requireObject.__js_handle__ = js_handle; + return gc_handle; + }, + mono_wasm_bind_host_object: function(js_handle, gc_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle ); + requireObject.__mono_gchandle__ = gc_handle; + return gc_handle; + }, + mono_wasm_new: function (core_name, args, is_exception) { + BINDING.bindings_lazy_init (); + + var js_name = BINDING.conv_string (core_name, false); + + if (!js_name) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found."); + } + + var coreObj = globalThis[js_name]; + + if (coreObj === null || typeof coreObj === "undefined") { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("JavaScript host object '" + js_name + "' not found."); + } + + var js_args = BINDING.mono_wasm_parse_args(args); + + try { + + // This is all experimental !!!!!! + var allocator = function(constructor, js_args) { + // Not sure if we should be checking for anything here + var argsList = new Array(); + argsList[0] = constructor; + if (js_args) + argsList = argsList.concat (js_args); + var tempCtor = constructor.bind.apply (constructor, argsList); + var obj = new tempCtor (); + return obj; + }; + + var res = allocator(coreObj, js_args); + var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++; + BINDING.mono_wasm_object_registry[gc_handle] = res; + return BINDING.mono_wasm_convert_return_value(gc_handle + 1); + } catch (e) { + var res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "Error allocating object."; + return BINDING.js_string_to_mono_string (res); + } + + }, + + mono_wasm_typed_array_to_array: function(js_handle, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + return BINDING.js_typed_array_to_array(requireObject); + }, + mono_wasm_typed_array_copy_to: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element); + return BINDING.js_to_mono_obj (res) + }, + mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) { + BINDING.bindings_lazy_init (); + var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type); + return BINDING.js_to_mono_obj (res) + }, + mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) { + BINDING.bindings_lazy_init (); + + var requireObject = BINDING.mono_wasm_require_handle (js_handle); + if (!requireObject) { + setValue (is_exception, 1, "i32"); + return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'"); + } + + var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element); + return BINDING.js_to_mono_obj (res) + }, + + +}; + +autoAddDeps(BindingSupportLib, '$BINDING') +mergeInto(LibraryManager.library, BindingSupportLib) + +// SIG // Begin signature block +// SIG // MIIkjAYJKoZIhvcNAQcCoIIkfTCCJHkCAQExDzANBglg +// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor +// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC +// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg +// SIG // nxTMCwiUNcOBRhhNQT5WVPUesv0mhdRMmZ4ME03Cqb+g +// SIG // gg3wMIIGbjCCBFagAwIBAgITMwAAAhOMDBwxNbzSXwAA +// SIG // AAACEzANBgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJV +// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT +// SIG // aWduaW5nIFBDQSAyMDExMB4XDTIxMDIxMTIwMDk1MVoX +// SIG // DTIyMDIxMDIwMDk1MVowYzELMAkGA1UEBhMCVVMxEzAR +// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v +// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +// SIG // bjENMAsGA1UEAxMELk5FVDCCAaIwDQYJKoZIhvcNAQEB +// SIG // BQADggGPADCCAYoCggGBAJtZcELdrGHlHCF6nz4bH8vW +// SIG // l5M3GfXIf7JY7OovRwgweTptJQGby0YHZ+iCrWIE7fTc +// SIG // /c9eGKGm+EsuWHnanAm9Ro7MSjdPsYBRaif1Y6dyhBcb +// SIG // b44guUNKlplq7L1k3ldXFFzyAt+u8UzCL5QFwibg2nWi +// SIG // QmCkoJWhiA6RxEPgEZ/ss2ICppgLHm1o6vy1P4ci6aMk +// SIG // Tj2s1uct/oFflYwE0DsK1OrFH7QvoIqWCAuXUXjZOKnF +// SIG // oRia22+ci2oxs/LVkgqcMwC35KHvUBzCW3LME/dSBWCO +// SIG // TV7gieG+gUtxBgPpzomak4thtrQLMRAWl7AOtI7QvsXa +// SIG // FEyQpAlDVz12Sa89KJOLBPksBRDw4woRZLlHnUrtxFRp +// SIG // MZsr+9cf2zfZPG4ia2iDSBFfXu2BeXrifkT4c/UV5Iy3 +// SIG // qEHCzh1jLmN701jUOhF1QN1LEPn+TCth2b239/34+Bym +// SIG // cIAcDP1EWk8JodsUDedKhK+lAefNL0mzUrIQc6Dxb5cq +// SIG // may/QQIDAQABo4IBfjCCAXowHwYDVR0lBBgwFgYKKwYB +// SIG // BAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFO9NaSC3 +// SIG // 3IwsQ0OKpWHnclste605MFAGA1UdEQRJMEekRTBDMSkw +// SIG // JwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy +// SIG // dG8gUmljbzEWMBQGA1UEBRMNNDY0MjIzKzQ2NDI5MzAf +// SIG // BgNVHSMEGDAWgBRIbmTlUAXTgqoXNzcitW2oynUClTBU +// SIG // BgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jv +// SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUw +// SIG // UzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3Nv +// SIG // ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAw +// SIG // DQYJKoZIhvcNAQEMBQADggIBAFiD+cR0K6evMUeUrBMA +// SIG // pLljV65GDDTzlD4jqr6Mu1NTeZv5L9IJlR6DLAEKaJnB +// SIG // a7fZZ/ME/FZasmc40+WijhDmth/OOc7IpfJ3Ra1auKIA +// SIG // g687mo/eWiPs0nC42oCdchy9Q5AS7K0+MUk7R/p9eCTP +// SIG // NYFjSMItiL+YFYCxaZXqHizwdXcvCIrESq4DXwN+ZdUe +// SIG // GBEO9F2SkMVC61/y2xwSwRWmfO/l4YutKT+dSKjlelYi +// SIG // zFAQaJrGzO5ac56S+K/NMndPL7Od3ohqxMu7gsFUynxY +// SIG // l+eyB9T9I9HrUWoHj6ce4nzOxHC+yDRD6Mi2AaT+IbMO +// SIG // cGvWeJC5iX3tzpMqdz0BOMl6jbff+t+BLS7VtU6JAFCM +// SIG // fk5h+wqIPWjon3tpTuFtCkMOSzIoso3U6kdX0fgrgXnN +// SIG // KJspBXkfKG9lMPOPOKwzua1qjghvgzPMftj1yZqFljJm +// SIG // cjBxs/HKA8J8st1MKcgiBGDX5zkcsHYGuAkIb2fXQuYW +// SIG // y0G78JzzSv1u0LAFj8/Qtx9Hm2wfc20+ww+MYEQ9tu1F +// SIG // uJZK2O7+p7iVziwZvo+XVzuIU7sVjcmJH5Gn/ttfkLQ3 +// SIG // 0jvM9QyV/lYwurg4Gn5Li/IZSN56WGIPilRkXUVurpaV +// SIG // WeYCjeUJzMY2n2tVMFl6pgnGmaA2a0uiG3z0GpMPdbS1 +// SIG // R/oEMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +// SIG // hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV +// SIG // BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +// SIG // HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +// SIG // MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +// SIG // dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5 +// SIG // WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJVUzET +// SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +// SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +// SIG // aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWdu +// SIG // aW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOC +// SIG // Ag8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGf +// SIG // Qhsqa+laUKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDI +// SIG // OdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv +// SIG // 2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13Y +// SIG // xC4Ddato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT +// SIG // +OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +// SIG // 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk +// SIG // kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXD +// SIG // OW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf +// SIG // GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +// SIG // JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bys +// SIG // AoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J64HLn +// SIG // JN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeB +// SIG // e+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx +// SIG // 7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu+HggWCwT +// SIG // XWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEA +// SIG // AaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1Ud +// SIG // DgQWBBRIbmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEE +// SIG // AYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw +// SIG // DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToC +// SIG // MZBDuRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBL +// SIG // hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +// SIG // bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf +// SIG // MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEF +// SIG // BQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br +// SIG // aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +// SIG // MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcu +// SIG // AzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy +// SIG // b3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMu +// SIG // aHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABf +// SIG // AHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0AZQBuAHQA +// SIG // LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou +// SIG // 09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+ +// SIG // vj/oCso7v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzS +// SIG // Gksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlE +// SIG // PXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6V +// SIG // oCo/KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu +// SIG // 5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +// SIG // STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp +// SIG // mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38c +// SIG // bxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN +// SIG // pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +// SIG // QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AA +// SIG // KcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74v2u3 +// SIG // S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8 +// SIG // MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7 +// SIG // qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJ +// SIG // UnMTDXpQzTGCFfQwghXwAgEBMIGVMH4xCzAJBgNVBAYT +// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH +// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +// SIG // cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2Rl +// SIG // IFNpZ25pbmcgUENBIDIwMTECEzMAAAITjAwcMTW80l8A +// SIG // AAAAAhMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN +// SIG // AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +// SIG // MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIH3V +// SIG // rVuHS6jhW1b2UUHL4nnR4dtJ5uT9jxWIJ1zW6lbkMEIG +// SIG // CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv +// SIG // AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w +// SIG // DQYJKoZIhvcNAQEBBQAEggGAluW+auGYLdzMAxqZXnjE +// SIG // AL0vFOlkbqS3YpYbb/93sk5LpYTyyv9AvLiwWOkwP/it +// SIG // RG6yVuwYmaLjRiXdisc6AVn3GoC1SW8CLlO6Yx4Xad+i +// SIG // xbD+KopbBdLcnCy80oJSmKh8peST4SMVsxnMHc6RkYCc +// SIG // wShpd845K6Zr+D/83uLq2wnMJh6kEJHDTPXHOObC5fm4 +// SIG // eAJF8vps7FbW+n8ZgM4zVfiVELaKK+x/uUpaVIIgD99J +// SIG // twXA+0qOhPGlI2KJdh9ptnpLn4wcdTHRq/Vg7GFtC4Un +// SIG // 2aMgDkcer2DrrkUdjtnMoVPo+oWSkLl8hIJDWQUP4apC +// SIG // 7mRCpxNVj9HbxNuV8mXVVacwq590peVGLKEn4US0GBwo +// SIG // d5fXG7T4RJEhBJ2OdQN924/B8asWWxeDm4f3pEIGpnu+ +// SIG // NxnsbDCegbPVuVm97bq51snFul6sQ1NUUNoFOyN+WyAf +// SIG // VLNIDeT9s9X+TrxFqPqA8uYY0pnz83FzlmE/f03Ru08c +// SIG // W1cENGteoYIS/jCCEvoGCisGAQQBgjcDAwExghLqMIIS +// SIG // 5gYJKoZIhvcNAQcCoIIS1zCCEtMCAQMxDzANBglghkgB +// SIG // ZQMEAgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQw +// SIG // ggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB +// SIG // BQAEII2c2aXB+/wtEhB0SYNUVf6+akfrAb8q2mkOPozv +// SIG // Bn+tAgZgsPYTykMYEzIwMjEwNjAzMTAyNzI2LjYzMVow +// SIG // BIACAfSggdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046MTc5RS00QkIwLTgyNDYxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wggg5NMIIE +// SIG // +TCCA+GgAwIBAgITMwAAATyL/bmzP0eX/QAAAAABPDAN +// SIG // BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG +// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +// SIG // MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ +// SIG // Q0EgMjAxMDAeFw0yMDEwMTUxNzI4MjNaFw0yMjAxMTIx +// SIG // NzI4MjNaMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +// SIG // V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +// SIG // A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYD +// SIG // VQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25z +// SIG // IExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO +// SIG // OjE3OUUtNEJCMC04MjQ2MSUwIwYDVQQDExxNaWNyb3Nv +// SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG +// SIG // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAq6WkDqvY5DgaQ +// SIG // t+OX0NCLzqUaivJxHvo6KSXP+VzTas2p6uYa3fcIm+EX +// SIG // b6bj4+vJ+Q5v12btrwqp1qMYct4sa24Ev64Nwkt26qfA +// SIG // INVEIP8QM99k7nnkzmNXDnpXF0WoaLCHI5a65L9dwGnB +// SIG // V5uAG2DAoGDOgc3WSgEXm3OsxL/uEAsuPtQFfER0BxDn +// SIG // aI+NjiaWxVpR72Cs17jNQB+L5o0/aP3wqtplg+yINvwq +// SIG // WiHdoByukfkvdPYitu7lZI1Wqdv0m+AEziyW2lUPl9Po +// SIG // WGxHAnrH/d4PrQEF7rwPHR+t3aCuSOc3WQheVP9w4m35 +// SIG // e2QhbFOpLPqYeIya2wIDAQABo4IBGzCCARcwHQYDVR0O +// SIG // BBYEFOGhZ+LKEvo2s2E/JRjqGL8mZzxGMB8GA1UdIwQY +// SIG // MBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRP +// SIG // ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y +// SIG // MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYI +// SIG // KwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDct +// SIG // MDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI +// SIG // KwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBADL3EIyU +// SIG // 3Zd5bkjMxakZMUZJSfilkVFJQdyNiiVVm+Bp+nlnSU4l +// SIG // nQtbsXoxdqD19G/l/UCIYvLtQGle/dnhIrdpUM6lYD4n +// SIG // 8k2Ri48ytjqLuD4/xefD6dpuh7qRn7jQHoZZ/oUr7yBO +// SIG // YIBJwor/ZVZACTjJSxxd/A2z7+6clrNC879rI2cDx73Y +// SIG // bVfJQbTmLBPDcc55W7MnPNL0Z0XqpvCUCumfMQA+EnmP +// SIG // HbhRV4XIhExthNG4fvzd5sBp81yczG0igCpMyMOmMan/ +// SIG // sx81jxYpvQxmcJnIavuiQSrW+BBk9BBbX6hgqzjw+Tu7 +// SIG // j8EnY9WqYF6qOx3Lce4XLOao6cIwggZxMIIEWaADAgEC +// SIG // AgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQsw +// SIG // CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ +// SIG // MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z +// SIG // b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +// SIG // ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx +// SIG // MDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVa +// SIG // MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN +// SIG // BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR +// SIG // ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vh +// SIG // wna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg +// SIG // iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg +// SIG // MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG +// SIG // GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBX +// SIG // day9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajy +// SIG // eioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHB +// SIG // IAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIw +// SIG // EAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyK +// SIG // MZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoA +// SIG // UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E +// SIG // BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ +// SIG // W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j +// SIG // cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz +// SIG // L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr +// SIG // BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 +// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v +// SIG // Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E +// SIG // gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC +// SIG // ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k +// SIG // b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0 +// SIG // HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMA +// SIG // dABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsF +// SIG // AAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7P +// SIG // BeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcI +// SIG // K1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZL +// SIG // dO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZ +// SIG // qbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8y +// SIG // Sif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoL +// SIG // kSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38 +// SIG // ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ +// SIG // Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ +// SIG // 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdl +// SIG // R3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30 +// SIG // uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp +// SIG // 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR +// SIG // ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXj +// SIG // ad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA1 +// SIG // 2u8JJxzVs341Hgi62jbb01+P3nSISRKhggLXMIICQAIB +// SIG // ATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046MTc5RS00QkIwLTgyNDYxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAH +// SIG // BgUrDgMCGgMVAB1LdHpZ3mjy22teinut0UdweuTmoIGD +// SIG // MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE +// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw +// SIG // DQYJKoZIhvcNAQEFBQACBQDkYrSTMCIYDzIwMjEwNjAz +// SIG // MDk1MzIzWhgPMjAyMTA2MDQwOTUzMjNaMHcwPQYKKwYB +// SIG // BAGEWQoEATEvMC0wCgIFAORitJMCAQAwCgIBAAICHHsC +// SIG // Af8wBwIBAAICEmcwCgIFAORkBhMCAQAwNgYKKwYBBAGE +// SIG // WQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAweh +// SIG // IKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCY +// SIG // ousN436K7aadq4lBgT0F3tetvOpvcoc5L/B0EHZeb+rx +// SIG // I6wYloEMcVPOaLiSMMf0VDjzUIG3/Q31iN/Cn40W86ZS +// SIG // 86kC3qcwFL+McvgJrNZHpU0a9DUI0lHxJi36t0Z/GC7T +// SIG // XkZpJzeAvJ1M+tpdnSRqvDvn9+wzi3HqdNzQEjGCAw0w +// SIG // ggMJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +// SIG // EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w +// SIG // HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk +// SIG // BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy +// SIG // MDEwAhMzAAABPIv9ubM/R5f9AAAAAAE8MA0GCWCGSAFl +// SIG // AwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcN +// SIG // AQkQAQQwLwYJKoZIhvcNAQkEMSIEIGcjizRAV34zL9eJ +// SIG // b2RFHY1/tZslsyH/7JVBDzcmxfxYMIH6BgsqhkiG9w0B +// SIG // CRACLzGB6jCB5zCB5DCBvQQgoEkCuk0kv8DnOqm31HwR +// SIG // r+2IbD3xmIW4FSGK4SboWkYwgZgwgYCkfjB8MQswCQYD +// SIG // VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G +// SIG // A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +// SIG // IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg +// SIG // VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAATyL/bmzP0eX +// SIG // /QAAAAABPDAiBCALHqq7hdXl2pLRNhwHbHSPjkcaMyvv +// SIG // QZpBGWeSTRYazzANBgkqhkiG9w0BAQsFAASCAQBkJ1KB +// SIG // vdXdE1TIb5f+SIDE5GixmmZqtTSyAZ8eeHco27axheRx +// SIG // g3T8HtjDx0nfyKBsA6ukiu+IUXt/jQek6fjxPJLSCI4I +// SIG // Gozyb6SXL2AI1f0Do0kKqTxiSgc3JiCJBiuI9y1jUBcX +// SIG // Tuw06nrSkMzDhcAXg0OiPoSN/K7ZWSfMPCJrc+t+eT79 +// SIG // 9DpbzCXpGvVH/sLrp+hl+Wb9R3AlTQoh0aehcm3CiGBo +// SIG // hIodIiPZsKm4ne/1Otr8HVUnXa52+SqNRbCuVClEvqVL +// SIG // o8GQB7tdfTbLOrEzrdm9omSaXNYSNMsEDHNC04E6j1Ys +// SIG // Oko6bU9skHp/7vp0NRkY5W6Fj4uu +// SIG // End signature block diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/corebindings.c b/Examples/Complete/Animation/Blazor/wwwroot/_framework/corebindings.c new file mode 100644 index 000000000..a0263c2a8 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/corebindings.c @@ -0,0 +1,177 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +#include +#include +#include +#include +#include +#include + +#include + +//JS funcs +extern MonoObject* mono_wasm_invoke_js_with_args (int js_handle, MonoString *method, MonoArray *args, int *is_exception); +extern MonoObject* mono_wasm_get_object_property (int js_handle, MonoString *propertyName, int *is_exception); +extern MonoObject* mono_wasm_get_by_index (int js_handle, int property_index, int *is_exception); +extern MonoObject* mono_wasm_set_object_property (int js_handle, MonoString *propertyName, MonoObject *value, int createIfNotExist, int hasOwnProperty, int *is_exception); +extern MonoObject* mono_wasm_set_by_index (int js_handle, int property_index, MonoObject *value, int *is_exception); +extern MonoObject* mono_wasm_get_global_object (MonoString *global_name, int *is_exception); +extern void* mono_wasm_release_handle (int js_handle, int *is_exception); +extern void* mono_wasm_release_object (int js_handle, int *is_exception); +extern MonoObject* mono_wasm_new (MonoString *core_name, MonoArray *args, int *is_exception); +extern int mono_wasm_bind_core_object (int js_handle, int gc_handle, int *is_exception); +extern int mono_wasm_bind_host_object (int js_handle, int gc_handle, int *is_exception); +extern MonoObject* mono_wasm_typed_array_to_array (int js_handle, int *is_exception); +extern MonoObject* mono_wasm_typed_array_copy_to (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception); +extern MonoObject* mono_wasm_typed_array_from (int ptr, int begin, int end, int bytes_per_element, int type, int *is_exception); +extern MonoObject* mono_wasm_typed_array_copy_from (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception); + +// Compiles a JavaScript function from the function data passed. +// Note: code snippet is not a function definition. Instead it must create and return a function instance. +EM_JS(MonoObject*, compile_function, (int snippet_ptr, int len, int *is_exception), { + try { + var data = MONO.string_decoder.decode (snippet_ptr, snippet_ptr + len); + var wrapper = '(function () { ' + data + ' })'; + var funcFactory = eval(wrapper); + var func = funcFactory(); + if (typeof func !== 'function') { + throw new Error('Code must return an instance of a JavaScript function. ' + + 'Please use `return` statement to return a function.'); + } + setValue (is_exception, 0, "i32"); + return BINDING.js_to_mono_obj (func); + } + catch (e) + { + res = e.toString (); + setValue (is_exception, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + return BINDING.js_to_mono_obj (res); + } +}); + +static MonoObject* +mono_wasm_compile_function (MonoString *str, int *is_exception) +{ + if (str == NULL) + return NULL; + //char *native_val = mono_string_to_utf8 (str); + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + + MonoObject* native_res = compile_function((int)native_val, native_len, is_exception); + mono_free (native_val); + if (native_res == NULL) + return NULL; + return native_res; +} + +void core_initialize_internals () +{ + mono_add_internal_call ("Interop/Runtime::InvokeJSWithArgs", mono_wasm_invoke_js_with_args); + mono_add_internal_call ("Interop/Runtime::GetObjectProperty", mono_wasm_get_object_property); + mono_add_internal_call ("Interop/Runtime::GetByIndex", mono_wasm_get_by_index); + mono_add_internal_call ("Interop/Runtime::SetObjectProperty", mono_wasm_set_object_property); + mono_add_internal_call ("Interop/Runtime::SetByIndex", mono_wasm_set_by_index); + mono_add_internal_call ("Interop/Runtime::GetGlobalObject", mono_wasm_get_global_object); + mono_add_internal_call ("Interop/Runtime::ReleaseHandle", mono_wasm_release_handle); + mono_add_internal_call ("Interop/Runtime::ReleaseObject", mono_wasm_release_object); + mono_add_internal_call ("Interop/Runtime::BindCoreObject", mono_wasm_bind_core_object); + mono_add_internal_call ("Interop/Runtime::BindHostObject", mono_wasm_bind_host_object); + mono_add_internal_call ("Interop/Runtime::New", mono_wasm_new); + mono_add_internal_call ("Interop/Runtime::TypedArrayToArray", mono_wasm_typed_array_to_array); + mono_add_internal_call ("Interop/Runtime::TypedArrayCopyTo", mono_wasm_typed_array_copy_to); + mono_add_internal_call ("Interop/Runtime::TypedArrayFrom", mono_wasm_typed_array_from); + mono_add_internal_call ("Interop/Runtime::TypedArrayCopyFrom", mono_wasm_typed_array_copy_from); + mono_add_internal_call ("Interop/Runtime::CompileFunction", mono_wasm_compile_function); + +} + +// Int8Array | int8_t | byte or SByte (signed byte) +// Uint8Array | uint8_t | byte or Byte (unsigned byte) +// Uint8ClampedArray| uint8_t | byte or Byte (unsigned byte) +// Int16Array | int16_t | short (signed short) +// Uint16Array | uint16_t | ushort (unsigned short) +// Int32Array | int32_t | int (signed integer) +// Uint32Array | uint32_t | uint (unsigned integer) +// Float32Array | float | float +// Float64Array | double | double +// typed array marshalling +#define MARSHAL_ARRAY_BYTE 10 +#define MARSHAL_ARRAY_UBYTE 11 +#define MARSHAL_ARRAY_UBYTE_C 12 // alias of MARSHAL_ARRAY_UBYTE +#define MARSHAL_ARRAY_SHORT 13 +#define MARSHAL_ARRAY_USHORT 14 +#define MARSHAL_ARRAY_INT 15 +#define MARSHAL_ARRAY_UINT 16 +#define MARSHAL_ARRAY_FLOAT 17 +#define MARSHAL_ARRAY_DOUBLE 18 + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_typed_array_new (char *arr, int length, int size, int type) +{ + MonoClass *typeClass = mono_get_byte_class(); // default is Byte + switch (type) { + case MARSHAL_ARRAY_BYTE: + typeClass = mono_get_sbyte_class(); + break; + case MARSHAL_ARRAY_SHORT: + typeClass = mono_get_int16_class(); + break; + case MARSHAL_ARRAY_USHORT: + typeClass = mono_get_uint16_class(); + break; + case MARSHAL_ARRAY_INT: + typeClass = mono_get_int32_class(); + break; + case MARSHAL_ARRAY_UINT: + typeClass = mono_get_uint32_class(); + break; + case MARSHAL_ARRAY_FLOAT: + typeClass = mono_get_single_class(); + break; + case MARSHAL_ARRAY_DOUBLE: + typeClass = mono_get_double_class(); + break; + } + + MonoArray *buffer; + + buffer = mono_array_new (mono_get_root_domain(), typeClass, length); + memcpy(mono_array_addr_with_size(buffer, sizeof(char), 0), arr, length * size); + + return buffer; +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_unbox_enum (MonoObject *obj) +{ + if (!obj) + return 0; + + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type(mono_type_get_underlying_type (type))) { + case MONO_TYPE_I1: + case MONO_TYPE_U1: + return *(unsigned char*)ptr; + case MONO_TYPE_I2: + return *(short*)ptr; + case MONO_TYPE_U2: + return *(unsigned short*)ptr; + case MONO_TYPE_I4: + return *(int*)ptr; + case MONO_TYPE_U4: + return *(unsigned int*)ptr; + // WASM doesn't support returning longs to JS + // case MONO_TYPE_I8: + // case MONO_TYPE_U8: + default: + printf ("Invalid type %d to mono_unbox_enum\n", mono_type_get_type(mono_type_get_underlying_type (type))); + return 0; + } +} + + diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.6.0.0-preview.5.21301.5.js b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.6.0.0-preview.5.21301.5.js new file mode 100644 index 000000000..5d37b0217 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.6.0.0-preview.5.21301.5.js @@ -0,0 +1,288 @@ +var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;return Math.ceil(size/factor)*factor}function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Function==="function"){var typeNames={"i":"i32","j":"i64","f":"f32","d":"f64"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for getValue: "+type)}return null}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;__ATINIT__.push({func:function(){___wasm_call_ctors()}});function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();SOCKFS.root=FS.mount(SOCKFS,{},null);callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="dotnet.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["Sa"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["Ta"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}var tempDouble;var tempI64;var ASM_CONSTS={100232:function($0,$1){var level=$0;var message=Module.UTF8ToString($1);var namespace="Debugger.Debug";if(MONO["logging"]&&MONO.logging["debugger"]){MONO.logging.debugger(level,message);return}console.debug("%s: %s",namespace,message)},102604:function($0,$1,$2){MONO.mono_wasm_add_typed_value("pointer",$0,{ptr_addr:$1,klass_addr:$2})},102719:function($0,$1,$2){MONO.mono_wasm_add_typed_value("array",$0,{objectId:$1,length:$2})},102831:function($0,$1,$2,$3,$4,$5){MONO.mono_wasm_add_typed_value($0,$1,{toString:$2,value_addr:$3,value_size:$4,klass:$5})},102953:function($0,$1,$2){MONO.mono_wasm_add_typed_value($0,$1,{toString:$2})},103391:function($0,$1,$2,$3,$4){MONO.mono_wasm_add_properties_var($0,{field_offset:$1,is_own:$2,attr:$3,owner_class:$4})},541329:function($0,$1){MONO.string_decoder.decode($0,$0+$1,true)},541702:function($0,$1,$2,$3){var str=MONO.string_decoder.decode($0,$0+$1);try{var res=eval(str);if(res===null||res==undefined)return 0;res=res.toString();setValue($2,0,"i32")}catch(e){res=e.toString();setValue($2,1,"i32");if(res===null||res===undefined)res="unknown exception";var stack=e.stack;if(stack){if(stack.startsWith(res))res=stack;else res+="\n"+stack}}var buff=Module._malloc((res.length+1)*2);stringToUTF16(res,buff,(res.length+1)*2);setValue($3,res.length,"i32");return buff},542256:function($0,$1,$2,$3,$4){var log_level=$0;var message=Module.UTF8ToString($1);var isFatal=$2;var domain=Module.UTF8ToString($3);var dataPtr=$4;if(MONO["logging"]&&MONO.logging["trace"]){MONO.logging.trace(domain,log_level,message,isFatal,dataPtr);return}if(isFatal)console.trace(message);switch(Module.UTF8ToString($0)){case"critical":case"error":console.error(message);break;case"warning":console.warn(message);break;case"message":console.log(message);break;case"info":console.info(message);break;case"debug":console.debug(message);break;default:console.log(message);break}}};function compile_function(snippet_ptr,len,is_exception){try{var data=MONO.string_decoder.decode(snippet_ptr,snippet_ptr+len);var wrapper="(function () { "+data+" })";var funcFactory=eval(wrapper);var func=funcFactory();if(typeof func!=="function"){throw new Error("Code must return an instance of a JavaScript function. "+"Please use `return` statement to return a function.")}setValue(is_exception,0,"i32");return BINDING.js_to_mono_obj(func)}catch(e){res=e.toString();setValue(is_exception,1,"i32");if(res===null||res===undefined)res="unknown exception";return BINDING.js_to_mono_obj(res)}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else _emscripten_get_now=function(){return performance.now()};var _emscripten_get_now_is_monotonic=true;function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if((clk_id===1||clk_id===4)&&_emscripten_get_now_is_monotonic){now=_emscripten_get_now()}else{setErrNo(28);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function ___clock_gettime(a0,a1){return _clock_gettime(a0,a1)}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0};this.set_base_ptr=function(basePtr){HEAP32[this.ptr>>2]=basePtr};this.get_base_ptr=function(){return HEAP32[this.ptr>>2]};this.set_adjusted_ptr=function(adjustedPtr){var ptrSize=4;HEAP32[this.ptr+ptrSize>>2]=adjustedPtr};this.get_adjusted_ptr=function(){var ptrSize=4;return HEAP32[this.ptr+ptrSize>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_exception_info().get_type());if(isPointer){return HEAP32[this.get_base_ptr()>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.get_base_ptr()};this.get_exception_info=function(){return new ExceptionInfo(this.get_base_ptr())};if(ptr===undefined){this.ptr=_malloc(8);this.set_adjusted_ptr(0)}else{this.ptr=ptr}}var exceptionCaught=[];function exception_addRef(info){info.add_ref()}var uncaughtExceptionCount=0;function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var info=catchInfo.get_exception_info();if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(catchInfo);exception_addRef(info);return catchInfo.get_exception_ptr()}var exceptionLast=0;function ___cxa_free_exception(ptr){return _free(new ExceptionInfo(ptr).ptr)}function exception_decRef(info){if(info.release_ref()&&!info.get_rethrown()){var destructor=info.get_destructor();if(destructor){wasmTable.get(destructor)(info.excPtr)}___cxa_free_exception(info.excPtr)}}function ___cxa_end_catch(){_setThrew(0);var catchInfo=exceptionCaught.pop();exception_decRef(catchInfo.get_exception_info());catchInfo.free();exceptionLast=0}function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(catchInfoPtr);var ptr=catchInfo.get_base_ptr();if(!exceptionLast){exceptionLast=ptr}catchInfo.free();throw ptr}function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thrown){setTempRet0(0|0);return 0|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){setTempRet0(0|0);return catchInfo.ptr|0}var typeArray=Array.prototype.slice.call(arguments);var stackTop=stackSave();var exceptionThrowBuf=stackAlloc(4);HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}setTempRet0(caughtType|0);return catchInfo.ptr|0}}stackRestore(stackTop);setTempRet0(thrownType|0);return catchInfo.ptr|0}function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["getRandomValues"]==="function"){var randomBuffer=new Uint8Array(1);return function(){crypto.getRandomValues(randomBuffer);return randomBuffer[0]}}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");return function(){return crypto_module["randomBytes"](1)[0]}}catch(e){}}return function(){abort("randomDevice")}}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function mmapAlloc(size){var alignedSize=alignMemory(size,16384);var ptr=_malloc(alignedSize);while(size=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length8){throw new FS.ErrnoError(32)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"r+":2,"w":577,"w+":578,"a":1089,"a+":1090},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 2}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 2}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 2}return 0},mayLookup:function(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:function(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}}}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(70)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){FS.forceLoadFile(node);var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-28}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream},get64:function(low,high){return low}};function ___sys_access(path,amode){try{path=SYSCALLS.getStr(path);return SYSCALLS.doAccess(path,amode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_chdir(path){try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fadvise64_64(fd,offset,len,advice){return 0}function ___sys_fallocate(fd,mode,off_low,off_high,len_low,len_high){try{var stream=SYSCALLS.getStreamFromFD(fd);var offset=SYSCALLS.get64(off_low,off_high);var len=SYSCALLS.get64(len_low,len_high);FS.allocate(stream,offset,len);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_ftruncate64(fd,zero,low,high){try{var length=SYSCALLS.get64(low,high);FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd);if(size>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_getpid(){return 42}function ___sys_getrusage(who,usage){try{_memset(usage,0,136);HEAP32[usage>>2]=1;HEAP32[usage+4>>2]=2;HEAP32[usage+8>>2]=3;HEAP32[usage+12>>2]=4;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_link(oldpath,newpath){return-34}function ___sys_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_madvise1(addr,length,advice){return 0}function ___sys_mkdir(path,mode){try{path=SYSCALLS.getStr(path);return SYSCALLS.doMkdir(path,mode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function syscallMmap2(addr,len,prot,flags,fd,off){off<<=12;var ptr;var allocated=false;if((flags&16)!==0&&addr%16384!==0){return-28}if((flags&32)!==0){ptr=_memalign(16384,len);if(!ptr)return-48;_memset(ptr,0,len);allocated=true}else{var info=FS.getStream(fd);if(!info)return-8;var res=FS.mmap(info,addr,len,off,prot,flags);ptr=res.ptr;allocated=res.allocated}SYSCALLS.mappings[ptr]={malloc:ptr,len:len,allocated:allocated,fd:fd,prot:prot,flags:flags,offset:off};return ptr}function ___sys_mmap2(addr,len,prot,flags,fd,off){try{return syscallMmap2(addr,len,prot,flags,fd,off)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_msync(addr,len,flags){try{var info=SYSCALLS.mappings[addr];if(!info)return 0;SYSCALLS.doMsync(addr,FS.getStream(info.fd),len,info.flags,0);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function syscallMunmap(addr,len){if((addr|0)===-1||len===0){return-28}var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);if(stream){if(info.prot&2){SYSCALLS.doMsync(addr,stream,len,info.flags,info.offset)}FS.munmap(stream)}SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}function ___sys_munmap(addr,len){try{return syscallMunmap(addr,len)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(path);var mode=varargs?SYSCALLS.get():0;var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_readlink(path,buf,bufsize){try{path=SYSCALLS.getStr(path);return SYSCALLS.doReadlink(path,buf,bufsize)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rename(old_path,new_path){try{old_path=SYSCALLS.getStr(old_path);new_path=SYSCALLS.getStr(new_path);FS.rename(old_path,new_path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var SOCKFS={mount:function(mount){Module["websocket"]=Module["websocket"]&&"object"===typeof Module["websocket"]?Module["websocket"]:{};Module["websocket"]._callbacks={};Module["websocket"]["on"]=function(event,callback){if("function"===typeof callback){this._callbacks[event]=callback}return this};Module["websocket"].emit=function(event,param){if("function"===typeof this._callbacks[event]){this._callbacks[event].call(this,param)}};return FS.createNode(null,"/",16384|511,0)},createSocket:function(family,type,protocol){type&=~526336;var streaming=type==1;if(protocol){assert(streaming==(protocol==6))}var sock={family:family,type:type,protocol:protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node:node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket:function(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll:function(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl:function(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read:function(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write:function(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close:function(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname:function(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return"socket["+SOCKFS.nextname.current+++"]"},websocket_sock_ops:{createPeer:function(sock,addr,port){var ws;if(typeof addr==="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var runtimeConfig=Module["websocket"]&&"object"===typeof Module["websocket"];var url="ws:#".replace("#","//");if(runtimeConfig){if("string"===typeof Module["websocket"]["url"]){url=Module["websocket"]["url"]}}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}var subProtocols="binary";if(runtimeConfig){if("string"===typeof Module["websocket"]["subprotocol"]){subProtocols=Module["websocket"]["subprotocol"]}}var opts=undefined;if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=ENVIRONMENT_IS_NODE?{"protocol":subProtocols.toString()}:subProtocols}if(runtimeConfig&&null===Module["websocket"]["subprotocol"]){subProtocols="null";opts=undefined}var WebSocketConstructor;if(ENVIRONMENT_IS_NODE){WebSocketConstructor=require("ws")}else{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH)}}var peer={addr:addr,port:port,socket:ws,dgram_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!=="undefined"){peer.dgram_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer:function(sock,addr,port){return sock.peers[addr+":"+port]},addPeer:function(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer:function(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents:function(sock,peer){var first=true;var handleOpen=function(){Module["websocket"].emit("open",sock.stream.fd);try{var queued=peer.dgram_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.dgram_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data==="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{assert(data.byteLength!==undefined);if(data.byteLength==0){return}else{data=new Uint8Array(data)}}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data:data});Module["websocket"].emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",function(data,flags){if(!flags.binary){return}handleMessage(new Uint8Array(data).buffer)});peer.socket.on("close",function(){Module["websocket"].emit("close",sock.stream.fd)});peer.socket.on("error",function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])})}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){Module["websocket"].emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll:function(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=16}return mask},ioctl:function(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;default:return ERRNO_CODES.EINVAL}},close:function(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i>>0}function jstoi_q(str){return parseInt(str)}function __inet_pton6_raw(str){var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.indexOf("::")===0){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=jstoi_q(words[words.length-4])+jstoi_q(words[words.length-3])*256;words[words.length-3]=jstoi_q(words[words.length-2])+jstoi_q(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255)}function __inet_ntop6_raw(ints){var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=__inet_ntop4_raw(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=__inet_ntop4_raw(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=__inet_ntop6_raw(addr);break;default:return{errno:5}}return{family:family,addr:addr,port:port}}function __write_sockaddr(sa,family,addr,port,addrlen){switch(family){case 2:addr=__inet_pton4_raw(addr);if(addrlen){HEAP32[addrlen>>2]=16}HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=__inet_pton6_raw(addr);if(addrlen){HEAP32[addrlen>>2]=28}HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);HEAP32[sa+4>>2]=0;HEAP32[sa+24>>2]=0;break;default:return 5}return 0}function ___sys_socketcall(call,socketvararg){try{SYSCALLS.varargs=socketvararg;var getSocketFromFD=function(){var socket=SOCKFS.getSocket(SYSCALLS.get());if(!socket)throw new FS.ErrnoError(8);return socket};var getSocketAddress=function(allowNull){var addrp=SYSCALLS.get(),addrlen=SYSCALLS.get();if(allowNull&&addrp===0)return null;var info=__read_sockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info};switch(call){case 1:{var domain=SYSCALLS.get(),type=SYSCALLS.get(),protocol=SYSCALLS.get();var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}case 2:{var sock=getSocketFromFD(),info=getSocketAddress();sock.sock_ops.bind(sock,info.addr,info.port);return 0}case 3:{var sock=getSocketFromFD(),info=getSocketAddress();sock.sock_ops.connect(sock,info.addr,info.port);return 0}case 4:{var sock=getSocketFromFD(),backlog=SYSCALLS.get();sock.sock_ops.listen(sock,backlog);return 0}case 5:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var newsock=sock.sock_ops.accept(sock);if(addr){var errno=__write_sockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport,addrlen)}return newsock.stream.fd}case 6:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var errno=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport,addrlen);return 0}case 7:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();if(!sock.daddr){return-53}var errno=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport,addrlen);return 0}case 11:{var sock=getSocketFromFD(),message=SYSCALLS.get(),length=SYSCALLS.get(),flags=SYSCALLS.get(),dest=getSocketAddress(true);if(!dest){return FS.write(sock.stream,HEAP8,message,length)}else{return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}}case 12:{var sock=getSocketFromFD(),buf=SYSCALLS.get(),len=SYSCALLS.get(),flags=SYSCALLS.get(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var errno=__write_sockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port,addrlen)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}case 14:{return-50}case 15:{var sock=getSocketFromFD(),level=SYSCALLS.get(),optname=SYSCALLS.get(),optval=SYSCALLS.get(),optlen=SYSCALLS.get();if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}case 16:{var sock=getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var addr,port;var name=HEAP32[message>>2];var namelen=HEAP32[message+4>>2];if(name){var info=__read_sockaddr(name,namelen);if(info.errno)return-info.errno;port=info.port;addr=DNS.lookup_addr(info.addr)||info.addr}var total=0;for(var i=0;i>2]}var view=new Uint8Array(total);var offset=0;for(var i=0;i>2];var iovlen=HEAP32[iov+(8*i+4)>>2];for(var j=0;j>0]}}return sock.sock_ops.sendmsg(sock,view,0,total,addr,port)}case 17:{var sock=getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var total=0;for(var i=0;i>2]}var msg=sock.sock_ops.recvmsg(sock,total);if(!msg)return 0;var name=HEAP32[message>>2];if(name){var errno=__write_sockaddr(name,sock.family,DNS.lookup_name(msg.addr),msg.port)}var bytesRead=0;var bytesRemaining=msg.buffer.byteLength;for(var i=0;bytesRemaining>0&&i>2];var iovlen=HEAP32[iov+(8*i+4)>>2];if(!iovlen){continue}var length=Math.min(iovlen,bytesRemaining);var buf=msg.buffer.subarray(bytesRead,bytesRead+length);HEAPU8.set(buf,iovbase+bytesRead);bytesRead+=length;bytesRemaining-=length}return bytesRead}default:{return-52}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_unlink(path){try{path=SYSCALLS.getStr(path);FS.unlink(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var seconds=HEAP32[times>>2];var nanoseconds=HEAP32[times+4>>2];var atime=seconds*1e3+nanoseconds/(1e3*1e3);times+=8;seconds=HEAP32[times>>2];nanoseconds=HEAP32[times+4>>2];var mtime=seconds*1e3+nanoseconds/(1e3*1e3);FS.utime(path,atime,mtime);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _abort(){abort()}function _emscripten_get_now_res(){if(ENVIRONMENT_IS_NODE){return 1}else if(typeof dateNow!=="undefined"){return 1e3}else return 1e3}function _clock_getres(clk_id,res){var nsec;if(clk_id===0){nsec=1e3*1e3}else if(clk_id===1&&_emscripten_get_now_is_monotonic){nsec=_emscripten_get_now_res()}else{setErrNo(28);return-1}HEAP32[res>>2]=nsec/1e9|0;HEAP32[res+4>>2]=nsec;return 0}var DOTNETENTROPY={batchedQuotaMax:65536,getBatchedRandomValues:function(buffer,bufferLength){for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}function _emscripten_thread_sleep(msecs){var start=_emscripten_get_now();while(_emscripten_get_now()-start>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAP32[penviron_buf_size>>2]=bufSize;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _exit(status){exit(status)}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4;HEAP8[pbuf>>0]=type;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doReadv(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var stream=SYSCALLS.getStreamFromFD(fd);var HIGH_OFFSET=4294967296;var offset=offset_high*HIGH_OFFSET+(offset_low>>>0);var DOUBLE_LIMIT=9007199254740992;if(offset<=-DOUBLE_LIMIT||offset>=DOUBLE_LIMIT){return-61}FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_sync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);if(stream.stream_ops&&stream.stream_ops.fsync){return-stream.stream_ops.fsync(stream)}return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doWritev(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _flock(fd,operation){return 0}var GAI_ERRNO_MESSAGES={};function _gai_strerror(val){var buflen=256;if(!_gai_strerror.buffer){_gai_strerror.buffer=_malloc(buflen);GAI_ERRNO_MESSAGES["0"]="Success";GAI_ERRNO_MESSAGES[""+-1]="Invalid value for 'ai_flags' field";GAI_ERRNO_MESSAGES[""+-2]="NAME or SERVICE is unknown";GAI_ERRNO_MESSAGES[""+-3]="Temporary failure in name resolution";GAI_ERRNO_MESSAGES[""+-4]="Non-recoverable failure in name res";GAI_ERRNO_MESSAGES[""+-6]="'ai_family' not supported";GAI_ERRNO_MESSAGES[""+-7]="'ai_socktype' not supported";GAI_ERRNO_MESSAGES[""+-8]="SERVICE not supported for 'ai_socktype'";GAI_ERRNO_MESSAGES[""+-10]="Memory allocation failure";GAI_ERRNO_MESSAGES[""+-11]="System error returned in 'errno'";GAI_ERRNO_MESSAGES[""+-12]="Argument buffer overflow"}var msg="Unknown error";if(val in GAI_ERRNO_MESSAGES){if(GAI_ERRNO_MESSAGES[val].length>buflen-1){msg="Message too long"}else{msg=GAI_ERRNO_MESSAGES[val]}}writeAsciiToMemory(msg,_gai_strerror.buffer);return _gai_strerror.buffer}function _getTempRet0(){return getTempRet0()|0}function _gettimeofday(ptr){var now=Date.now();HEAP32[ptr>>2]=now/1e3|0;HEAP32[ptr+4>>2]=now%1e3*1e3|0;return 0}function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();HEAP32[tmPtr+36>>2]=0;HEAP32[tmPtr+32>>2]=0;var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;if(!_gmtime_r.GMTString)_gmtime_r.GMTString=allocateUTF8("GMT");HEAP32[tmPtr+40>>2]=_gmtime_r.GMTString;return tmPtr}function _llvm_eh_typeid_for(type){return type}function _tzset(){if(_tzset.called)return;_tzset.called=true;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAP32[__get_timezone()>>2]=stdTimezoneOffset*60;HEAP32[__get_daylight()>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}var MONO={pump_count:0,timeout_queue:[],_vt_stack:[],mono_wasm_runtime_is_ready:false,mono_wasm_ignore_pdb_load_errors:true,_id_table:{},pump_message:function(){if(!this.mono_background_exec)this.mono_background_exec=Module.cwrap("mono_background_exec",null);while(MONO.timeout_queue.length>0){--MONO.pump_count;MONO.timeout_queue.shift()()}while(MONO.pump_count>0){--MONO.pump_count;this.mono_background_exec()}},export_functions:function(module){module["pump_message"]=MONO.pump_message.bind(MONO);module["mono_load_runtime_and_bcl"]=MONO.mono_load_runtime_and_bcl.bind(MONO);module["mono_load_runtime_and_bcl_args"]=MONO.mono_load_runtime_and_bcl_args.bind(MONO);module["mono_wasm_load_bytes_into_heap"]=MONO.mono_wasm_load_bytes_into_heap.bind(MONO);module["mono_wasm_load_icu_data"]=MONO.mono_wasm_load_icu_data.bind(MONO);module["mono_wasm_get_icudt_name"]=MONO.mono_wasm_get_icudt_name.bind(MONO);module["mono_wasm_globalization_init"]=MONO.mono_wasm_globalization_init.bind(MONO);module["mono_wasm_get_loaded_files"]=MONO.mono_wasm_get_loaded_files.bind(MONO);module["mono_wasm_new_root_buffer"]=MONO.mono_wasm_new_root_buffer.bind(MONO);module["mono_wasm_new_root_buffer_from_pointer"]=MONO.mono_wasm_new_root_buffer_from_pointer.bind(MONO);module["mono_wasm_new_root"]=MONO.mono_wasm_new_root.bind(MONO);module["mono_wasm_new_roots"]=MONO.mono_wasm_new_roots.bind(MONO);module["mono_wasm_release_roots"]=MONO.mono_wasm_release_roots.bind(MONO)},_base64Converter:{_base64Table:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"],_makeByteReader:function(bytes,index,count){var position=typeof index==="number"?index:0;var endpoint;if(typeof count==="number")endpoint=position+count;else endpoint=bytes.length-position;var result={read:function(){if(position>=endpoint)return false;var nextByte=bytes[position];position+=1;return nextByte}};Object.defineProperty(result,"eof",{get:function(){return position>=endpoint},configurable:true,enumerable:true});return result},toBase64StringImpl:function(inArray,offset,length){var reader=this._makeByteReader(inArray,offset,length);var result="";var ch1=0,ch2=0,ch3=0,bits=0,equalsCount=0,sum=0;var mask1=(1<<24)-1,mask2=(1<<18)-1,mask3=(1<<12)-1,mask4=(1<<6)-1;var shift1=18,shift2=12,shift3=6,shift4=0;while(true){ch1=reader.read();ch2=reader.read();ch3=reader.read();if(ch1===false)break;if(ch2===false){ch2=0;equalsCount+=1}if(ch3===false){ch3=0;equalsCount+=1}sum=ch1<<16|ch2<<8|ch3<<0;bits=(sum&mask1)>>shift1;result+=this._base64Table[bits];bits=(sum&mask2)>>shift2;result+=this._base64Table[bits];if(equalsCount<2){bits=(sum&mask3)>>shift3;result+=this._base64Table[bits]}if(equalsCount===2){result+="=="}else if(equalsCount===1){result+="="}else{bits=(sum&mask4)>>shift4;result+=this._base64Table[bits]}}return result}},_mono_wasm_root_buffer_prototype:{_throw_index_out_of_range:function(){throw new Error("index out of range")},_check_in_range:function(index){if(index>=this.__count||index<0)this._throw_index_out_of_range()},get_address:function(index){this._check_in_range(index);return this.__offset+index*4},get_address_32:function(index){this._check_in_range(index);return this.__offset32+index},get:function(index){this._check_in_range(index);return Module.HEAP32[this.get_address_32(index)]},set:function(index,value){Module.HEAP32[this.get_address_32(index)]=value;return value},_unsafe_get:function(index){return Module.HEAP32[this.__offset32+index]},_unsafe_set:function(index,value){Module.HEAP32[this.__offset32+index]=value},clear:function(){if(this.__offset)MONO._zero_region(this.__offset,this.__count*4)},release:function(){if(this.__offset&&this.__ownsAllocation){MONO.mono_wasm_deregister_root(this.__offset);MONO._zero_region(this.__offset,this.__count*4);Module._free(this.__offset)}this.__handle=this.__offset=this.__count=this.__offset32=0},toString:function(){return"[root buffer @"+this.get_address(0)+", size "+this.__count+"]"}},_scratch_root_buffer:null,_scratch_root_free_indices:null,_scratch_root_free_indices_count:0,_scratch_root_free_instances:[],_mono_wasm_root_prototype:{get_address:function(){return this.__buffer.get_address(this.__index)},get_address_32:function(){return this.__buffer.get_address_32(this.__index)},get:function(){var result=this.__buffer._unsafe_get(this.__index);return result},set:function(value){this.__buffer._unsafe_set(this.__index,value);return value},valueOf:function(){return this.get()},clear:function(){this.set(0)},release:function(){const maxPooledInstances=128;if(MONO._scratch_root_free_instances.length>maxPooledInstances){MONO._mono_wasm_release_scratch_index(this.__index);this.__buffer=0;this.__index=0}else{this.set(0);MONO._scratch_root_free_instances.push(this)}},toString:function(){return"[root @"+this.get_address()+"]"}},_mono_wasm_release_scratch_index:function(index){if(index===undefined)return;this._scratch_root_buffer.set(index,0);this._scratch_root_free_indices[this._scratch_root_free_indices_count]=index;this._scratch_root_free_indices_count++},_mono_wasm_claim_scratch_index:function(){if(!this._scratch_root_buffer){const maxScratchRoots=8192;this._scratch_root_buffer=this.mono_wasm_new_root_buffer(maxScratchRoots,"js roots");this._scratch_root_free_indices=new Int32Array(maxScratchRoots);this._scratch_root_free_indices_count=maxScratchRoots;for(var i=0;i= 1");capacity=capacity|0;var capacityBytes=capacity*4;var offset=Module._malloc(capacityBytes);if(offset%4!==0)throw new Error("Malloc returned an unaligned offset");this._zero_region(offset,capacityBytes);var result=Object.create(this._mono_wasm_root_buffer_prototype);result.__offset=offset;result.__offset32=offset/4|0;result.__count=capacity;result.length=capacity;result.__handle=this.mono_wasm_register_root(offset,capacityBytes,msg||0);result.__ownsAllocation=true;return result},mono_wasm_new_root_buffer_from_pointer:function(offset,capacity,msg){if(!this.mono_wasm_register_root||!this.mono_wasm_deregister_root){this.mono_wasm_register_root=Module.cwrap("mono_wasm_register_root","number",["number","number","string"]);this.mono_wasm_deregister_root=Module.cwrap("mono_wasm_deregister_root",null,["number"])}if(capacity<=0)throw new Error("capacity >= 1");capacity=capacity|0;var capacityBytes=capacity*4;if(offset%4!==0)throw new Error("Unaligned offset");this._zero_region(offset,capacityBytes);var result=Object.create(this._mono_wasm_root_buffer_prototype);result.__offset=offset;result.__offset32=offset/4|0;result.__count=capacity;result.length=capacity;result.__handle=this.mono_wasm_register_root(offset,capacityBytes,msg||0);result.__ownsAllocation=false;return result},mono_wasm_new_root:function(value){var result;if(this._scratch_root_free_instances.length>0){result=this._scratch_root_free_instances.pop()}else{var index=this._mono_wasm_claim_scratch_index();var buffer=this._scratch_root_buffer;result=Object.create(this._mono_wasm_root_prototype);result.__buffer=buffer;result.__index=index}if(value!==undefined){if(typeof value!=="number")throw new Error("value must be an address in the managed heap");result.set(value)}else{result.set(0)}return result},mono_wasm_new_roots:function(count_or_values){var result;if(Array.isArray(count_or_values)){result=new Array(count_or_values.length);for(var i=0;i0){result=new Array(count_or_values);for(var i=0;i",description:""};i++}out_list.push(o)}return out_list},_filter_automatic_properties:function(props,accessors_only=false){let getters={};let all_fields_except_backing_fields={};let backing_fields={};props.forEach(p=>{if(p.name===undefined){console.debug(`Bug: Found a member with no name. Skipping it. p: ${JSON.stringify(p)}`);return}if(p.name.endsWith("k__BackingField")){const auto_prop_name=p.name.replace("k__BackingField","").replace("<","").replace(">","");if(!(auto_prop_name in backing_fields))backing_fields[auto_prop_name]=Object.assign(p,{name:auto_prop_name})}else if(p.get!==undefined){if(!(p.name in getters)&&!(p.name in all_fields_except_backing_fields))getters[p.name]=p}else if(!(p.name in all_fields_except_backing_fields)){all_fields_except_backing_fields[p.name]=p}});Object.values(backing_fields).forEach(backing_field=>{const auto_prop_name=backing_field.name;const getter=getters[auto_prop_name];if(getter===undefined){return}if(auto_prop_name in all_fields_except_backing_fields){delete getters[auto_prop_name]}else if(getter.__args.owner_class===backing_field.__args.owner_class){all_fields_except_backing_fields[auto_prop_name]=backing_field;delete getters[auto_prop_name]}});if(accessors_only)return Object.values(getters);return Object.values(all_fields_except_backing_fields).concat(Object.values(getters))},_parse_object_id:function(idStr,throwOnError=false){if(idStr===undefined||idStr==""||!idStr.startsWith("dotnet:")){if(throwOnError)throw new Error(`Invalid id: ${idStr}`);return undefined}const[,scheme,...rest]=idStr.split(":");let res={scheme:scheme,value:rest.join(":"),idStr:idStr,o:{}};try{res.o=JSON.parse(res.value)}catch(e){}return res},_resolve_member_by_name:function(base_object,base_name,expr_parts){if(base_object===undefined||base_object.value===undefined)throw new Error(`Bug: base_object is undefined`);if(base_object.value.type==="object"&&base_object.value.subtype==="null")throw new ReferenceError(`Null reference: ${base_name} is null`);if(base_object.value.type!=="object")throw new ReferenceError(`'.' is only supported on non-primitive types. Failed on '${base_name}'`);if(expr_parts.length==0)throw new Error(`Invalid member access expression`);const root=expr_parts[0];const props=this.mono_wasm_get_details(base_object.value.objectId,{});let resObject=props.find(l=>l.name==root);if(resObject!==undefined){if(resObject.value===undefined&&resObject.get!==undefined)resObject=this._invoke_getter(base_object.value.objectId,root)}if(resObject===undefined||expr_parts.length==1)return resObject;else{expr_parts.shift();return this._resolve_member_by_name(resObject,root,expr_parts)}},mono_wasm_eval_member_access:function(scope,var_list,rootObjectId,expr){if(expr===undefined||expr.length==0)throw new Error(`expression argument required`);let parts=expr.split(".");if(parts.length==0)throw new Error(`Invalid member access expression: ${expr}`);const root=parts[0];const locals=this.mono_wasm_get_variables(scope,var_list);let rootObject=locals.find(l=>l.name===root);if(rootObject===undefined){const thisObject=locals.find(l=>l.name=="this");if(thisObject===undefined)throw new ReferenceError(`Could not find ${root} in locals, and no 'this' found.`);const thisProps=this.mono_wasm_get_details(thisObject.value.objectId,{});rootObject=thisProps.find(tp=>tp.name==root);if(rootObject===undefined)throw new ReferenceError(`Could not find ${root} in locals, or in 'this'`);if(rootObject.value===undefined&&rootObject.get!==undefined)rootObject=this._invoke_getter(thisObject.value.objectId,root)}parts.shift();if(parts.length==0)return rootObject;if(rootObject===undefined||rootObject.value===undefined)throw new Error(`Could not get a value for ${root}`);return this._resolve_member_by_name(rootObject,root,parts)},mono_wasm_set_variable_value:function(scope,index,name,newValue){console.debug(">> mono_wasm_set_variable_value "+name+" - "+newValue);var ret=this._c_fn_table.mono_wasm_set_variable_on_frame_wrapper(scope,index,name,newValue);if(ret==false)throw new Error(`Could not get a value for ${name}`);return ret},_get_vt_properties:function(id,args={}){let entry=this._get_id_props(id.idStr);if(entry===undefined||entry.members===undefined){if(!isNaN(id.o.containerId)){this._get_object_properties(id.o.containerId,{expandValueTypes:true})}else if(!isNaN(id.o.arrayId))this._get_array_values(id,Number(id.o.arrayIdx),1,true);else throw new Error(`Invalid valuetype id (${id.idStr}). Can't get properties for it.`)}entry=this._get_id_props(id.idStr);if(entry!==undefined&&entry.members!==undefined){if(args.accessorPropertiesOnly===true)return entry.accessors;return entry.members}throw new Error(`Unknown valuetype id: ${id.idStr}. Failed to get properties for it.`)},_assign_vt_ids:function(vars,getIdArgs){vars.forEach((v,i)=>{const value=v.value;if(value===undefined||!value.isValueType)return;if(value.objectId!==undefined)throw new Error(`Bug: Trying to assign valuetype id, but the var already has one: ${v}`);value.objectId=this._new_or_add_id_props({scheme:"valuetype",idArgs:getIdArgs(v,i),props:value._props});delete value._props});return vars},mono_wasm_get_variables:function(scope,var_list){const numBytes=var_list.length*Int32Array.BYTES_PER_ELEMENT;const ptr=Module._malloc(numBytes);let heapBytes=new Int32Array(Module.HEAP32.buffer,ptr,numBytes);for(let i=0;i({containerId:this._async_method_objectId,fieldOffset:v.fieldOffset}));for(let i in res){const res_name=res[i].name;if(this._async_method_objectId!=0){if(res_name!==undefined&&res_name.indexOf(">")>0){res[i].name=res_name.substring(1,res_name.indexOf(">"))}}else if(res_name===undefined&&var_list[i]!==undefined){res[i].name=var_list[i].name}}this._post_process_details(res);return res},_get_properties_args_to_gpflags:function(args){let gpflags=0;if(args.expandValueTypes)gpflags|=4;return gpflags},_get_object_properties:function(idNum,args={}){let gpflags=this._get_properties_args_to_gpflags(args);let{res_ok:res_ok,res:res}=this.mono_wasm_get_object_properties_info(idNum,gpflags);if(!res_ok)throw new Error(`Failed to get properties for ${idNum}`);res=MONO._filter_automatic_properties(res,args.accessorPropertiesOnly===true);res=this._assign_vt_ids(res,v=>({containerId:idNum,fieldOffset:v.fieldOffset}));res=this._post_process_details(res);return res},_get_array_values:function(id,startIdx=0,count=-1,expandValueTypes=false){if(isNaN(id.o.arrayId)||isNaN(startIdx))throw new Error(`Invalid array id: ${id.idStr}`);let gpflags=this._get_properties_args_to_gpflags({expandValueTypes:expandValueTypes});let{res_ok:res_ok,res:res}=this.mono_wasm_get_array_values_info(id.o.arrayId,startIdx,count,gpflags);if(!res_ok)throw new Error(`Failed to get properties for array id ${id.idStr}`);res=this._assign_vt_ids(res,(_,i)=>({arrayId:id.o.arrayId,arrayIdx:Number(startIdx)+i}));for(let i=0;i0)this._extract_and_cache_value_types(details);details.forEach(d=>delete d.__args);return details},_next_id:function(){return++this._next_id_var},_extract_and_cache_value_types:function(var_list){if(var_list==undefined||!Array.isArray(var_list)||var_list.length==0)return var_list;for(let i in var_list){let value=var_list[i].value;if(value===undefined)continue;if(value.objectId!==undefined&&value.objectId.startsWith("dotnet:pointer:")){let ptr_args=this._get_id_props(value.objectId);if(ptr_args===undefined)throw new Error(`Bug: Expected to find an entry for pointer id: ${value.objectId}`);ptr_args.varName=ptr_args.varName||var_list[i].name}if(value.type!="object"||value.isValueType!=true||value.expanded!=true)continue;if(value.members===undefined){continue}value.objectId=value.objectId||this._new_or_add_id_props({scheme:"valuetype"});this._extract_and_cache_value_types(value.members);const accessors=value.members.filter(m=>m.get!==undefined);const new_props=Object.assign({members:value.members,accessors:accessors},value.__extra_vt_props);this._new_or_add_id_props({objectId:value.objectId,props:new_props});delete value.members;delete value.__extra_vt_props}return var_list},_get_cfo_res_details:function(objectId,args){if(!(objectId in this._call_function_res_cache))throw new Error(`Could not find any object with id ${objectId}`);const real_obj=this._call_function_res_cache[objectId];const descriptors=Object.getOwnPropertyDescriptors(real_obj);if(args.accessorPropertiesOnly){Object.keys(descriptors).forEach(k=>{if(descriptors[k].get===undefined)Reflect.deleteProperty(descriptors,k)})}let res_details=[];Object.keys(descriptors).forEach(k=>{let new_obj;let prop_desc=descriptors[k];if(typeof prop_desc.value=="object"){new_obj=Object.assign({name:k},prop_desc)}else if(prop_desc.value!==undefined){new_obj={name:k,value:Object.assign({type:typeof prop_desc.value,description:""+prop_desc.value},prop_desc)}}else if(prop_desc.get!==undefined){new_obj={name:k,get:{className:"Function",description:`get ${k} () {}`,type:"function"}}}else{new_obj={name:k,value:{type:"symbol",value:"",description:""}}}res_details.push(new_obj)});return{__value_as_json_string__:JSON.stringify(res_details)}},_new_or_add_id_props:function({scheme:scheme=undefined,objectId:objectId=undefined,idArgs:idArgs={},props:props={}}){if(scheme===undefined&&objectId===undefined)throw new Error(`Either scheme or objectId must be given`);if(scheme!==undefined&&objectId!==undefined)throw new Error(`Both scheme, and objectId cannot be given`);if(objectId!==undefined&&Object.entries(idArgs).length>0)throw new Error(`Both objectId, and idArgs cannot be given`);if(Object.entries(idArgs).length==0){idArgs.num=this._next_id()}let idStr;if(objectId!==undefined){idStr=objectId;const old_props=this._id_table[idStr];if(old_props===undefined)throw new Error(`ObjectId not found in the id table: ${idStr}`);this._id_table[idStr]=Object.assign(old_props,props)}else{idStr=`dotnet:${scheme}:${JSON.stringify(idArgs)}`;this._id_table[idStr]=props}return idStr},_get_id_props:function(objectId){return this._id_table[objectId]},_get_deref_ptr_value:function(objectId){const ptr_args=this._get_id_props(objectId);if(ptr_args===undefined)throw new Error(`Unknown pointer id: ${objectId}`);if(ptr_args.ptr_addr==0||ptr_args.klass_addr==0)throw new Error(`Both ptr_addr and klass_addr need to be non-zero, to dereference a pointer. objectId: ${objectId}`);const value_addr=new DataView(Module.HEAPU8.buffer).getUint32(ptr_args.ptr_addr,true);let{res_ok:res_ok,res:res}=this.mono_wasm_get_deref_ptr_value_info(value_addr,ptr_args.klass_addr);if(!res_ok)throw new Error(`Failed to dereference pointer ${objectId}`);if(res.length>0){if(ptr_args.varName===undefined)throw new Error(`Bug: no varName found for the pointer. objectId: ${objectId}`);res[0].name=`*${ptr_args.varName}`}res=this._post_process_details(res);return res},mono_wasm_get_details:function(objectId,args={}){let id=this._parse_object_id(objectId,true);switch(id.scheme){case"object":{if(isNaN(id.value))throw new Error(`Invalid objectId: ${objectId}. Expected a numeric id.`);args.expandValueTypes=false;return this._get_object_properties(id.value,args)}case"array":return this._get_array_values(id);case"valuetype":return this._get_vt_properties(id,args);case"cfo_res":return this._get_cfo_res_details(objectId,args);case"pointer":{return this._get_deref_ptr_value(objectId)}default:throw new Error(`Unknown object id format: ${objectId}`)}},_cache_call_function_res:function(obj){const id=`dotnet:cfo_res:${this._next_call_function_res_id++}`;this._call_function_res_cache[id]=obj;return id},mono_wasm_release_object:function(objectId){if(objectId in this._cache_call_function_res)delete this._cache_call_function_res[objectId]},_invoke_getter:function(objectIdStr,name){const id=this._parse_object_id(objectIdStr);if(id===undefined)throw new Error(`Invalid object id: ${objectIdStr}`);let getter_res;if(id.scheme=="object"){if(isNaN(id.o)||id.o<0)throw new Error(`Invalid object id: ${objectIdStr}`);let{res_ok:res_ok,res:res}=this.mono_wasm_invoke_getter_on_object_info(id.o,name);if(!res_ok)throw new Error(`Invoking getter on ${objectIdStr} failed`);getter_res=res}else if(id.scheme=="valuetype"){const id_props=this._get_id_props(objectIdStr);if(id_props===undefined)throw new Error(`Unknown valuetype id: ${objectIdStr}`);if(typeof id_props.value64!=="string"||isNaN(id_props.klass))throw new Error(`Bug: Cannot invoke getter on ${objectIdStr}, because of missing or invalid klass/value64 fields. idProps: ${JSON.stringify(id_props)}`);const dataPtr=Module._malloc(id_props.value64.length);const dataHeap=new Uint8Array(Module.HEAPU8.buffer,dataPtr,id_props.value64.length);dataHeap.set(new Uint8Array(this._base64_to_uint8(id_props.value64)));let{res_ok:res_ok,res:res}=this.mono_wasm_invoke_getter_on_value_info(dataHeap.byteOffset,id_props.klass,name);Module._free(dataHeap.byteOffset);if(!res_ok){console.debug(`Invoking getter on valuetype ${objectIdStr}, with props: ${JSON.stringify(id_props)} failed`);throw new Error(`Invoking getter on valuetype ${objectIdStr} failed`)}getter_res=res}else{throw new Error(`Only object, and valuetypes supported for getters, id: ${objectIdStr}`)}getter_res=MONO._post_process_details(getter_res);return getter_res.length>0?getter_res[0]:{}},_set_value_on_object:function(objectIdStr,name,newvalue){const id=this._parse_object_id(objectIdStr);if(id===undefined)throw new Error(`Invalid object id: ${objectIdStr}`);let setter_res;if(id.scheme=="object"){if(isNaN(id.o)||id.o<0)throw new Error(`Invalid object id: ${objectIdStr}`);var ret=this._c_fn_table.mono_wasm_set_value_on_object_wrapper(id.o,name,newvalue);if(!ret)throw new Error(`Invoking setter on ${objectIdStr} failed`);setter_res=ret}else throw new Error(`Only object is supported for setters, id: ${objectIdStr}`);return setter_res},_create_proxy_from_object_id:function(objectId){const details=this.mono_wasm_get_details(objectId);if(objectId.startsWith("dotnet:array:"))return details.map(p=>p.value);let proxy={};Object.keys(details).forEach(p=>{var prop=details[p];if(prop.get!==undefined){Object.defineProperty(proxy,prop.name,{get(){return MONO._invoke_getter(objectId,prop.name)}})}else{proxy[prop.name]=prop.value}});const handler1={set(obj,prop,newValue){return MONO._set_value_on_object(objectId,prop,newValue.toString())}};return new Proxy(proxy,handler1)},mono_wasm_call_function_on:function(request){if(request.arguments!=undefined&&!Array.isArray(request.arguments))throw new Error(`"arguments" should be an array, but was ${request.arguments}`);const objId=request.objectId;let proxy;if(objId.startsWith("dotnet:cfo_res:")){if(objId in this._call_function_res_cache)proxy=this._call_function_res_cache[objId];else throw new Error(`Unknown object id ${objId}`)}else{proxy=this._create_proxy_from_object_id(objId)}const fn_args=request.arguments!=undefined?request.arguments.map(a=>JSON.stringify(a.value)):[];const fn_eval_str=`var fn = ${request.functionDeclaration}; fn.call (proxy, ...[${fn_args}]);`;const fn_res=eval(fn_eval_str);if(fn_res===undefined)return{type:"undefined"};if(fn_res===null||fn_res.subtype==="null"&&fn_res.value===undefined)return fn_res;if(Object(fn_res)!==fn_res)return fn_res;if(fn_res.value!==undefined&&Object(fn_res.value.value)!==fn_res.value.value)return fn_res.value;if(request.returnByValue)return{type:"object",value:fn_res};const fn_res_id=this._cache_call_function_res(fn_res);if(Object.getPrototypeOf(fn_res)==Array.prototype){return{type:"object",subtype:"array",className:"Array",description:`Array(${fn_res.length})`,objectId:fn_res_id}}else{return{type:"object",className:"Object",description:"Object",objectId:fn_res_id}}},_clear_per_step_state:function(){this._next_id_var=0;this._id_table={}},mono_wasm_debugger_resume:function(){this._clear_per_step_state()},mono_wasm_start_single_stepping:function(kind){console.debug(">> mono_wasm_start_single_stepping "+kind);if(!this.mono_wasm_setup_single_step)this.mono_wasm_setup_single_step=Module.cwrap("mono_wasm_setup_single_step","number",["number"]);this._clear_per_step_state();return this.mono_wasm_setup_single_step(kind)},mono_wasm_set_pause_on_exceptions:function(state){if(!this.mono_wasm_pause_on_exceptions)this.mono_wasm_pause_on_exceptions=Module.cwrap("mono_wasm_pause_on_exceptions","number",["number"]);var state_enum=0;switch(state){case"uncaught":state_enum=1;break;case"all":state_enum=2;break}return this.mono_wasm_pause_on_exceptions(state_enum)},mono_wasm_detach_debugger:function(){if(!this.mono_wasm_set_is_debugger_attached)this.mono_wasm_set_is_debugger_attached=Module.cwrap("mono_wasm_set_is_debugger_attached","void",["bool"]);this.mono_wasm_set_is_debugger_attached(false)},_register_c_fn:function(name,...args){Object.defineProperty(this._c_fn_table,name+"_wrapper",{value:Module.cwrap(name,...args)})},_register_c_var_fn:function(name,ret_type,params){if(ret_type!=="bool")throw new Error(`Bug: Expected a C function signature that returns bool`);this._register_c_fn(name,ret_type,params);Object.defineProperty(this,name+"_info",{value:function(...args){MONO.var_info=[];const res_ok=MONO._c_fn_table[name+"_wrapper"](...args);let res=MONO.var_info;MONO.var_info=[];if(res_ok){res=this._fixup_name_value_objects(res);return{res_ok:res_ok,res:res}}return{res_ok:res_ok,res:undefined}}})},mono_wasm_runtime_ready:function(){this.mono_wasm_runtime_is_ready=true;this._clear_per_step_state();this._next_call_function_res_id=0;this._call_function_res_cache={};this._c_fn_table={};this._register_c_var_fn("mono_wasm_get_object_properties","bool",["number","number"]);this._register_c_var_fn("mono_wasm_get_array_values","bool",["number","number","number","number"]);this._register_c_var_fn("mono_wasm_invoke_getter_on_object","bool",["number","string"]);this._register_c_var_fn("mono_wasm_invoke_getter_on_value","bool",["number","number","string"]);this._register_c_var_fn("mono_wasm_get_local_vars","bool",["number","number","number"]);this._register_c_var_fn("mono_wasm_get_deref_ptr_value","bool",["number","number"]);this._register_c_fn("mono_wasm_set_value_on_object","bool",["number","string","string"]);this._register_c_fn("mono_wasm_set_variable_on_frame","bool",["number","number","string","string"]);if(globalThis.dotnetDebugger)debugger;else console.debug("mono_wasm_runtime_ready","fe00e07a-5519-4dfe-b35a-f867dbaf2e28")},mono_wasm_set_breakpoint:function(assembly,method_token,il_offset){if(!this.mono_wasm_set_bp)this.mono_wasm_set_bp=Module.cwrap("mono_wasm_set_breakpoint","number",["string","number","number"]);return this.mono_wasm_set_bp(assembly,method_token,il_offset)},mono_wasm_remove_breakpoint:function(breakpoint_id){if(!this.mono_wasm_del_bp)this.mono_wasm_del_bp=Module.cwrap("mono_wasm_remove_breakpoint","number",["number"]);return this.mono_wasm_del_bp(breakpoint_id)},mono_wasm_setenv:function(name,value){if(!this.wasm_setenv)this.wasm_setenv=Module.cwrap("mono_wasm_setenv",null,["string","string"]);this.wasm_setenv(name,value)},mono_wasm_set_runtime_options:function(options){if(!this.wasm_parse_runtime_options)this.wasm_parse_runtime_options=Module.cwrap("mono_wasm_parse_runtime_options",null,["number","number"]);var argv=Module._malloc(options.length*4);var wasm_strdup=Module.cwrap("mono_wasm_strdup","number",["string"]);let aindex=0;for(var i=0;i0?virtualName.substr(0,lastSlash):null;var fileName=lastSlash>0?virtualName.substr(lastSlash+1):virtualName;if(fileName.startsWith("/"))fileName=fileName.substr(1);if(parentDirectory){if(ctx.tracing)console.log("MONO_WASM: Creating directory '"+parentDirectory+"'");var pathRet=ctx.createPath("/",parentDirectory,true,true)}else{parentDirectory="/"}if(ctx.tracing)console.log("MONO_WASM: Creating file '"+fileName+"' in directory '"+parentDirectory+"'");if(!this.mono_wasm_load_data_archive(bytes,parentDirectory)){var fileRet=ctx.createDataFile(parentDirectory,fileName,bytes,true,true,true)}break;default:throw new Error("Unrecognized asset behavior:",asset.behavior,"for asset",asset.name)}if(asset.behavior==="assembly"){var hasPpdb=ctx.mono_wasm_add_assembly(virtualName,offset,bytes.length);if(!hasPpdb){var index=ctx.loaded_files.findIndex(element=>element.file==virtualName);ctx.loaded_files.splice(index,1)}}else if(asset.behavior==="icu"){if(this.mono_wasm_load_icu_data(offset))ctx.num_icu_assets_loaded_successfully+=1;else console.error("Error loading ICU asset",asset.name)}else if(asset.behavior==="resource"){ctx.mono_wasm_add_satellite_assembly(virtualName,asset.culture,offset,bytes.length)}},mono_load_runtime_and_bcl:function(unused_vfs_prefix,deploy_prefix,debug_level,file_list,loaded_cb,fetch_file_cb){var args={fetch_file_cb:fetch_file_cb,loaded_cb:loaded_cb,debug_level:debug_level,assembly_root:deploy_prefix,assets:[]};for(var i=0;iloaded_files_with_debug_info.push(value.url));MONO.loaded_files=loaded_files_with_debug_info;if(ctx.tracing){console.log("MONO_WASM: loaded_assets: "+JSON.stringify(ctx.loaded_assets));console.log("MONO_WASM: loaded_files: "+JSON.stringify(ctx.loaded_files))}var load_runtime=Module.cwrap("mono_wasm_load_runtime",null,["string","number"]);console.debug("MONO_WASM: Initializing mono runtime");this.mono_wasm_globalization_init(args.globalization_mode);if(ENVIRONMENT_IS_SHELL||ENVIRONMENT_IS_NODE){try{load_runtime("unused",args.debug_level)}catch(ex){print("MONO_WASM: load_runtime () failed: "+ex);print("MONO_WASM: Stacktrace: \n");print(ex.stack);var wasm_exit=Module.cwrap("mono_wasm_exit",null,["number"]);wasm_exit(1)}}else{load_runtime("unused",args.debug_level)}let tz;try{tz=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}MONO.mono_wasm_setenv("TZ",tz||"UTC");MONO.mono_wasm_runtime_ready();args.loaded_cb()},_load_assets_and_runtime:function(args){if(args.enable_debugging)args.debug_level=args.enable_debugging;if(args.assembly_list)throw new Error("Invalid args (assembly_list was replaced by assets)");if(args.runtime_assets)throw new Error("Invalid args (runtime_assets was replaced by assets)");if(args.runtime_asset_sources)throw new Error("Invalid args (runtime_asset_sources was replaced by remote_sources)");if(!args.loaded_cb)throw new Error("loaded_cb not provided");var ctx={tracing:args.diagnostic_tracing||false,pending_count:args.assets.length,mono_wasm_add_assembly:Module.cwrap("mono_wasm_add_assembly","number",["string","number","number"]),mono_wasm_add_satellite_assembly:Module.cwrap("mono_wasm_add_satellite_assembly","void",["string","string","number","number"]),loaded_assets:Object.create(null),loaded_files:[],createPath:Module["FS_createPath"],createDataFile:Module["FS_createDataFile"]};if(ctx.tracing)console.log("mono_wasm_load_runtime_with_args",JSON.stringify(args));this._apply_configuration_from_args(args);var fetch_file_cb=this._get_fetch_file_cb_from_args(args);var onPendingRequestComplete=function(){--ctx.pending_count;if(ctx.pending_count===0){try{MONO._finalize_startup(args,ctx)}catch(exc){console.error("Unhandled exception in _finalize_startup",exc);throw exc}}};var processFetchResponseBuffer=function(asset,url,blob){try{MONO._handle_loaded_asset(ctx,asset,url,blob)}catch(exc){console.error("Unhandled exception in processFetchResponseBuffer",exc);throw exc}finally{onPendingRequestComplete()}};args.assets.forEach(function(asset){var attemptNextSource;var sourceIndex=0;var sourcesList=asset.load_remote?args.remote_sources:[""];var handleFetchResponse=function(response){if(!response.ok){try{attemptNextSource();return}catch(exc){console.error("MONO_WASM: Unhandled exception in handleFetchResponse attemptNextSource for asset",asset.name,exc);throw exc}}try{var bufferPromise=response["arrayBuffer"]();bufferPromise.then(processFetchResponseBuffer.bind(this,asset,response.url))}catch(exc){console.error("MONO_WASM: Unhandled exception in handleFetchResponse for asset",asset.name,exc);attemptNextSource()}};attemptNextSource=function(){if(sourceIndex>=sourcesList.length){var msg="MONO_WASM: Failed to load "+asset.name;try{var isOk=asset.is_optional||asset.name.match(/\.pdb$/)&&MONO.mono_wasm_ignore_pdb_load_errors;if(isOk)console.debug(msg);else{console.error(msg);throw new Error(msg)}}finally{onPendingRequestComplete()}}var sourcePrefix=sourcesList[sourceIndex];sourceIndex++;if(sourcePrefix==="./")sourcePrefix="";var attemptUrl;if(sourcePrefix.trim()===""){if(asset.behavior==="assembly")attemptUrl=locateFile(args.assembly_root+"/"+asset.name);else if(asset.behavior==="resource"){var path=asset.culture!==""?`${asset.culture}/${asset.name}`:asset.name;attemptUrl=locateFile(args.assembly_root+"/"+path)}else attemptUrl=asset.name}else{attemptUrl=sourcePrefix+asset.name}try{if(asset.name===attemptUrl){if(ctx.tracing)console.log("Attempting to fetch '"+attemptUrl+"'")}else{if(ctx.tracing)console.log("Attempting to fetch '"+attemptUrl+"' for",asset.name)}var fetch_promise=fetch_file_cb(attemptUrl);fetch_promise.then(handleFetchResponse)}catch(exc){console.error("MONO_WASM: Error fetching "+attemptUrl,exc);attemptNextSource()}};attemptNextSource()})},mono_wasm_globalization_init:function(globalization_mode){var invariantMode=false;if(globalization_mode==="invariant")invariantMode=true;if(!invariantMode){if(this.num_icu_assets_loaded_successfully>0){console.debug("MONO_WASM: ICU data archive(s) loaded, disabling invariant mode")}else if(globalization_mode!=="icu"){console.debug("MONO_WASM: ICU data archive(s) not loaded, using invariant globalization mode");invariantMode=true}else{var msg="invariant globalization mode is inactive and no ICU data archives were loaded";console.error("MONO_WASM: ERROR: "+msg);throw new Error(msg)}}if(invariantMode)this.mono_wasm_setenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT","1");this.mono_wasm_setenv("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY","1")},mono_wasm_get_loaded_files:function(){if(!this.mono_wasm_set_is_debugger_attached)this.mono_wasm_set_is_debugger_attached=Module.cwrap("mono_wasm_set_is_debugger_attached","void",["bool"]);this.mono_wasm_set_is_debugger_attached(true);return MONO.loaded_files},mono_wasm_get_loaded_asset_table:function(){return MONO.loaded_assets},mono_wasm_clear_all_breakpoints:function(){if(!this.mono_clear_bps)this.mono_clear_bps=Module.cwrap("mono_wasm_clear_all_breakpoints",null);this.mono_clear_bps()},mono_wasm_add_null_var:function(className){let fixed_class_name=MONO._mono_csharp_fixup_class_name(Module.UTF8ToString(className));if(!fixed_class_name){fixed_class_name=className}MONO.var_info.push({value:{type:"object",className:fixed_class_name,description:fixed_class_name,subtype:"null"}})},_mono_wasm_add_string_var:function(var_value){if(var_value===0){MONO.mono_wasm_add_null_var("string");return}MONO.var_info.push({value:{type:"string",value:var_value,description:var_value}})},_mono_wasm_add_getter_var:function(className){const fixed_class_name=MONO._mono_csharp_fixup_class_name(className);var name;if(MONO.var_info.length>0)name=MONO.var_info[MONO.var_info.length-1].name;name=name===undefined?"":name;MONO.var_info.push({get:{className:"Function",description:`get ${name} () {}`,type:"function"}})},_mono_wasm_add_array_var:function(className,objectId,length){const fixed_class_name=MONO._mono_csharp_fixup_class_name(className);if(objectId==0){MONO.mono_wasm_add_null_var(fixed_class_name);return}MONO.var_info.push({value:{type:"object",subtype:"array",className:fixed_class_name,description:`${fixed_class_name}(${length})`,objectId:this._new_or_add_id_props({scheme:"array",idArgs:{arrayId:objectId}})}})},_base64_to_uint8:function(base64String){const byteCharacters=atob(base64String);const byteNumbers=new Array(byteCharacters.length);for(let i=0;i{var file=m[0];var last=file.lastIndexOf("/");var directory=file.slice(0,last+1);folders.add(directory)});folders.forEach(folder=>{Module["FS_createPath"](prefix,folder,true,true)});for(row of manifest){var name=row[0];var length=row[1];var bytes=data.slice(0,length);Module["FS_createDataFile"](prefix,name,bytes,true,true);data=data.slice(length)}return true},mono_wasm_raise_debug_event:function(event,args={}){if(typeof event!=="object")throw new Error(`event must be an object, but got ${JSON.stringify(event)}`);if(event.eventName===undefined)throw new Error(`event.eventName is a required parameter, in event: ${JSON.stringify(event)}`);if(typeof args!=="object")throw new Error(`args must be an object, but got ${JSON.stringify(args)}`);console.debug("mono_wasm_debug_event_raised:aef14bca-5519-4dfe-b35a-f867abc123ae",JSON.stringify(event),JSON.stringify(args))}};function _mono_set_timeout(timeout,id){if(!this.mono_set_timeout_exec)this.mono_set_timeout_exec=Module.cwrap("mono_set_timeout_exec",null,["number"]);if(typeof globalThis.setTimeout==="function"){globalThis.setTimeout(function(){this.mono_set_timeout_exec(id)},timeout)}else{++MONO.pump_count;MONO.timeout_queue.push(function(){this.mono_set_timeout_exec(id)})}}function _mono_wasm_add_array_item(position){MONO.var_info.push({name:`${position}`})}function _mono_wasm_add_enum_var(className,members,value){const re=new RegExp(`[,]?([^,:]+):(${value}(?=,)|${value}$)`,"g");const members_str=Module.UTF8ToString(members);const match=re.exec(members_str);const member_name=match==null?""+value:match[1];const fixed_class_name=MONO._mono_csharp_fixup_class_name(Module.UTF8ToString(className));MONO.var_info.push({value:{type:"object",className:fixed_class_name,description:member_name,isEnum:true}})}function _mono_wasm_add_frame(il,method,frame_id,assembly_name,method_full_name){var parts=Module.UTF8ToString(method_full_name).split(":",2);MONO.active_frames.push({il_pos:il,method_token:method,assembly_name:Module.UTF8ToString(assembly_name),method_name:parts[parts.length-1],frame_id:frame_id})}function _mono_wasm_add_func_var(className,targetName,objectId){if(objectId==0){MONO.mono_wasm_add_null_var(MONO._mono_csharp_fixup_class_name(Module.UTF8ToString(className)));return}function args_to_sig(args_str){var parts=args_str.split(":");parts=parts.map(a=>MONO._mono_csharp_fixup_class_name(a));var method_name=parts.pop();var ret_sig=parts[0];var args_sig=parts.splice(1).join(", ");return`${ret_sig} ${method_name} (${args_sig})`}let tgt_sig;if(targetName!=0)tgt_sig=args_to_sig(Module.UTF8ToString(targetName));const type_name=MONO._mono_csharp_fixup_class_name(Module.UTF8ToString(className));if(tgt_sig===undefined)tgt_sig=type_name;if(objectId==-1||targetName===0){MONO.var_info.push({value:{type:"symbol",value:tgt_sig,description:tgt_sig}})}else{MONO.var_info.push({value:{type:"object",className:type_name,description:tgt_sig,objectId:"dotnet:object:"+objectId}})}}function _mono_wasm_add_obj_var(className,toString,objectId){if(objectId==0){MONO.mono_wasm_add_null_var(className);return}const fixed_class_name=MONO._mono_csharp_fixup_class_name(Module.UTF8ToString(className));MONO.var_info.push({value:{type:"object",className:fixed_class_name,description:toString===0?fixed_class_name:Module.UTF8ToString(toString),objectId:"dotnet:object:"+objectId}})}function _mono_wasm_add_properties_var(name,args){MONO.mono_wasm_add_properties_var(name,args)}function _mono_wasm_add_typed_value(type,str_value,value){MONO.mono_wasm_add_typed_value(type,str_value,value)}function _mono_wasm_asm_loaded(assembly_name,assembly_ptr,assembly_len,pdb_ptr,pdb_len){if(MONO.mono_wasm_runtime_is_ready!==true)return;const assembly_name_str=assembly_name!==0?Module.UTF8ToString(assembly_name).concat(".dll"):"";const assembly_data=new Uint8Array(Module.HEAPU8.buffer,assembly_ptr,assembly_len);const assembly_b64=MONO._base64Converter.toBase64StringImpl(assembly_data);let pdb_b64;if(pdb_ptr){const pdb_data=new Uint8Array(Module.HEAPU8.buffer,pdb_ptr,pdb_len);pdb_b64=MONO._base64Converter.toBase64StringImpl(pdb_data)}MONO.mono_wasm_raise_debug_event({eventName:"AssemblyLoaded",assembly_name:assembly_name_str,assembly_b64:assembly_b64,pdb_b64:pdb_b64})}var BINDING={BINDING_ASM:"[System.Private.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.Runtime",mono_wasm_object_registry:[],mono_wasm_ref_counter:0,mono_wasm_free_list:[],mono_wasm_owned_objects_frames:[],mono_wasm_owned_objects_LMF:[],mono_wasm_marshal_enum_as_int:true,mono_bindings_init:function(binding_asm){this.BINDING_ASM=binding_asm},export_functions:function(module){module["mono_bindings_init"]=BINDING.mono_bindings_init.bind(BINDING);module["mono_bind_method"]=BINDING.bind_method.bind(BINDING);module["mono_method_invoke"]=BINDING.call_method.bind(BINDING);module["mono_method_get_call_signature"]=BINDING.mono_method_get_call_signature.bind(BINDING);module["mono_method_resolve"]=BINDING.resolve_method_fqn.bind(BINDING);module["mono_bind_static_method"]=BINDING.bind_static_method.bind(BINDING);module["mono_call_static_method"]=BINDING.call_static_method.bind(BINDING);module["mono_bind_assembly_entry_point"]=BINDING.bind_assembly_entry_point.bind(BINDING);module["mono_call_assembly_entry_point"]=BINDING.call_assembly_entry_point.bind(BINDING);module["mono_intern_string"]=BINDING.mono_intern_string.bind(BINDING)},bindings_lazy_init:function(){if(this.init)return;this.init=true;Array.prototype[Symbol.for("wasm type")]=1;ArrayBuffer.prototype[Symbol.for("wasm type")]=2;DataView.prototype[Symbol.for("wasm type")]=3;Function.prototype[Symbol.for("wasm type")]=4;Map.prototype[Symbol.for("wasm type")]=5;if(typeof SharedArrayBuffer!=="undefined")SharedArrayBuffer.prototype[Symbol.for("wasm type")]=6;Int8Array.prototype[Symbol.for("wasm type")]=10;Uint8Array.prototype[Symbol.for("wasm type")]=11;Uint8ClampedArray.prototype[Symbol.for("wasm type")]=12;Int16Array.prototype[Symbol.for("wasm type")]=13;Uint16Array.prototype[Symbol.for("wasm type")]=14;Int32Array.prototype[Symbol.for("wasm type")]=15;Uint32Array.prototype[Symbol.for("wasm type")]=16;Float32Array.prototype[Symbol.for("wasm type")]=17;Float64Array.prototype[Symbol.for("wasm type")]=18;this.assembly_load=Module.cwrap("mono_wasm_assembly_load","number",["string"]);this.find_corlib_class=Module.cwrap("mono_wasm_find_corlib_class","number",["string","string"]);this.find_class=Module.cwrap("mono_wasm_assembly_find_class","number",["number","string","string"]);this._find_method=Module.cwrap("mono_wasm_assembly_find_method","number",["number","string","number"]);this.invoke_method=Module.cwrap("mono_wasm_invoke_method","number",["number","number","number","number"]);this.mono_string_get_utf8=Module.cwrap("mono_wasm_string_get_utf8","number",["number"]);this.mono_wasm_string_from_utf16=Module.cwrap("mono_wasm_string_from_utf16","number",["number","number"]);this.mono_get_obj_type=Module.cwrap("mono_wasm_get_obj_type","number",["number"]);this.mono_array_length=Module.cwrap("mono_wasm_array_length","number",["number"]);this.mono_array_get=Module.cwrap("mono_wasm_array_get","number",["number","number"]);this.mono_obj_array_new=Module.cwrap("mono_wasm_obj_array_new","number",["number"]);this.mono_obj_array_set=Module.cwrap("mono_wasm_obj_array_set","void",["number","number","number"]);this.mono_wasm_register_bundled_satellite_assemblies=Module.cwrap("mono_wasm_register_bundled_satellite_assemblies","void",[]);this.mono_wasm_try_unbox_primitive_and_get_type=Module.cwrap("mono_wasm_try_unbox_primitive_and_get_type","number",["number","number"]);this.mono_wasm_box_primitive=Module.cwrap("mono_wasm_box_primitive","number",["number","number","number"]);this.mono_wasm_intern_string=Module.cwrap("mono_wasm_intern_string","number",["number"]);this.assembly_get_entry_point=Module.cwrap("mono_wasm_assembly_get_entry_point","number",["number"]);this.mono_wasm_get_delegate_invoke=Module.cwrap("mono_wasm_get_delegate_invoke","number",["number"]);this.mono_wasm_string_array_new=Module.cwrap("mono_wasm_string_array_new","number",["number"]);this._box_buffer=Module._malloc(16);this._unbox_buffer=Module._malloc(16);this._class_int32=this.find_corlib_class("System","Int32");this._class_uint32=this.find_corlib_class("System","UInt32");this._class_double=this.find_corlib_class("System","Double");this._class_boolean=this.find_corlib_class("System","Boolean");this.mono_typed_array_new=Module.cwrap("mono_wasm_typed_array_new","number",["number","number","number","number"]);var binding_fqn_asm=this.BINDING_ASM.substring(this.BINDING_ASM.indexOf("[")+1,this.BINDING_ASM.indexOf("]")).trim();var binding_fqn_class=this.BINDING_ASM.substring(this.BINDING_ASM.indexOf("]")+1).trim();this.binding_module=this.assembly_load(binding_fqn_asm);if(!this.binding_module)throw"Can't find bindings module assembly: "+binding_fqn_asm;var namespace=null,classname=null;if(binding_fqn_class!==null&&typeof binding_fqn_class!=="undefined"){namespace="System.Runtime.InteropServices.JavaScript";classname=binding_fqn_class.length>0?binding_fqn_class:"Runtime";if(binding_fqn_class.indexOf(".")!=-1){var idx=binding_fqn_class.lastIndexOf(".");namespace=binding_fqn_class.substring(0,idx);classname=binding_fqn_class.substring(idx+1)}}var wasm_runtime_class=this.find_class(this.binding_module,namespace,classname);if(!wasm_runtime_class)throw"Can't find "+binding_fqn_class+" class";var get_method=function(method_name){var res=BINDING.find_method(wasm_runtime_class,method_name,-1);if(!res)throw"Can't find method "+namespace+"."+classname+":"+method_name;return res};var bind_runtime_method=function(method_name,signature){var method=get_method(method_name);return BINDING.bind_method(method,0,signature,"BINDINGS_"+method_name)};this._bind_js_obj=bind_runtime_method("BindJSObject","iii");this._bind_core_clr_obj=bind_runtime_method("BindCoreCLRObject","ii");this._bind_existing_obj=bind_runtime_method("BindExistingObject","mi");this._unbind_raw_obj_and_free=bind_runtime_method("UnBindRawJSObjectAndFree","ii");this._get_js_id=bind_runtime_method("GetJSObjectId","m");this._get_raw_mono_obj=bind_runtime_method("GetDotNetObject","i!");this._is_simple_array=bind_runtime_method("IsSimpleArray","m");this.setup_js_cont=get_method("SetupJSContinuation");this.create_tcs=get_method("CreateTaskSource");this.set_tcs_result=get_method("SetTaskSourceResult");this.set_tcs_failure=get_method("SetTaskSourceFailure");this.tcs_get_task_and_bind=get_method("GetTaskAndBind");this.get_call_sig=get_method("GetCallSignature");this._object_to_string=bind_runtime_method("ObjectToString","m");this.get_date_value=get_method("GetDateValue");this.create_date_time=get_method("CreateDateTime");this.create_uri=get_method("CreateUri");this.safehandle_addref=get_method("SafeHandleAddRef");this.safehandle_release=get_method("SafeHandleRelease");this.safehandle_get_handle=get_method("SafeHandleGetHandle");this.safehandle_release_by_handle=get_method("SafeHandleReleaseByHandle");this._are_promises_supported=(typeof Promise==="object"||typeof Promise==="function")&&typeof Promise.resolve==="function";this._empty_string="";this._empty_string_ptr=0;this._interned_string_full_root_buffers=[];this._interned_string_current_root_buffer=null;this._interned_string_current_root_buffer_count=0;this._interned_string_table=new Map;this._managed_pointer_to_interned_string_table=new Map},mono_intern_string:function(string){if(string.length===0)return this._empty_string;var ptr=this.js_string_to_mono_string_interned(string);var result=this._managed_pointer_to_interned_string_table.get(ptr);return result},_store_string_in_intern_table:function(string,ptr,internIt){if(!ptr)throw new Error("null pointer passed to _store_string_in_intern_table");else if(typeof ptr!=="number")throw new Error(`non-pointer passed to _store_string_in_intern_table: ${typeof ptr}`);const internBufferSize=8192;if(this._interned_string_current_root_buffer_count>=internBufferSize){this._interned_string_full_root_buffers.push(this._interned_string_current_root_buffer);this._interned_string_current_root_buffer=null}if(!this._interned_string_current_root_buffer){this._interned_string_current_root_buffer=MONO.mono_wasm_new_root_buffer(internBufferSize,"interned strings");this._interned_string_current_root_buffer_count=0}var rootBuffer=this._interned_string_current_root_buffer;var index=this._interned_string_current_root_buffer_count++;rootBuffer.set(index,ptr);if(internIt)rootBuffer.set(index,ptr=this.mono_wasm_intern_string(ptr));if(!ptr)throw new Error("mono_wasm_intern_string produced a null pointer");this._interned_string_table.set(string,ptr);this._managed_pointer_to_interned_string_table.set(ptr,string);if(string.length===0&&!this._empty_string_ptr)this._empty_string_ptr=ptr;return ptr},js_string_to_mono_string_interned:function(string){var text=typeof string==="symbol"?string.description||Symbol.keyFor(string)||"":string;if(text.length===0&&this._empty_string_ptr)return this._empty_string_ptr;var ptr=this._interned_string_table.get(string);if(ptr)return ptr;ptr=this.js_string_to_mono_string_new(text);ptr=this._store_string_in_intern_table(string,ptr,true);return ptr},js_string_to_mono_string:function(string){if(string===null)return null;else if(typeof string==="symbol")return this.js_string_to_mono_string_interned(string);else if(typeof string!=="string")throw new Error("Expected string argument");if(string.length===0)return this.js_string_to_mono_string_interned(string);if(string.length<=256){var interned=this._interned_string_table.get(string);if(interned)return interned}return this.js_string_to_mono_string_new(string)},js_string_to_mono_string_new:function(string){var buffer=Module._malloc((string.length+1)*2);var buffer16=buffer/2|0;for(var i=0;i0)return this.mono_wasm_require_handle(js_handle);return null},conv_string:function(mono_obj,interned){var interned_instance=this._managed_pointer_to_interned_string_table.get(mono_obj);if(interned_instance!==undefined)return interned_instance;var result=MONO.string_decoder.copy(mono_obj);if(interned){this._store_string_in_intern_table(result,mono_obj,false)}return result},is_nested_array:function(ele){return this._is_simple_array(ele)},mono_array_to_js_array:function(mono_array){if(mono_array===0)return null;var arrayRoot=MONO.mono_wasm_new_root(mono_array);try{return this._mono_array_root_to_js_array(arrayRoot)}finally{arrayRoot.release()}},_mono_array_root_to_js_array:function(arrayRoot){if(arrayRoot.value===0)return null;let elemRoot=MONO.mono_wasm_new_root();try{var len=this.mono_array_length(arrayRoot.value);var res=new Array(len);for(var i=0;i>>0===js_obj)result=this._box_js_uint(js_obj);else result=this._box_js_double(js_obj);if(!result)throw new Error(`Boxing failed for ${js_obj}`);return result}case typeof js_obj==="string":return this.js_string_to_mono_string(js_obj);case typeof js_obj==="symbol":return this.js_string_to_mono_string_interned(js_obj);case typeof js_obj==="boolean":return this._box_js_bool(js_obj);case isThenable()===true:var the_task=this.try_extract_mono_obj(js_obj);if(the_task)return the_task;var tcs=this.create_task_completion_source();js_obj.then(function(result){BINDING.set_task_result(tcs,result)},function(reason){BINDING.set_task_failure(tcs,reason)});return this.get_task_and_bind(tcs,js_obj);case js_obj.constructor.name==="Date":return this.call_method(this.create_date_time,null,"d!",[js_obj.getTime()]);default:return this.extract_mono_obj(js_obj)}},js_to_mono_uri:function(js_obj){this.bindings_lazy_init();switch(true){case js_obj===null:case typeof js_obj==="undefined":return 0;case typeof js_obj==="symbol":case typeof js_obj==="string":return this.call_method(this.create_uri,null,"s!",[js_obj]);default:return this.extract_mono_obj(js_obj)}},has_backing_array_buffer:function(js_obj){return typeof SharedArrayBuffer!=="undefined"?js_obj.buffer instanceof ArrayBuffer||js_obj.buffer instanceof SharedArrayBuffer:js_obj.buffer instanceof ArrayBuffer},js_typed_array_to_array:function(js_obj){if(!!(this.has_backing_array_buffer(js_obj)&&js_obj.BYTES_PER_ELEMENT)){var arrayType=js_obj[Symbol.for("wasm type")];var heapBytes=this.js_typedarray_to_heap(js_obj);var bufferArray=this.mono_typed_array_new(heapBytes.byteOffset,js_obj.length,js_obj.BYTES_PER_ELEMENT,arrayType);Module._free(heapBytes.byteOffset);return bufferArray}else{throw new Error("Object '"+js_obj+"' is not a typed array")}},typedarray_copy_to:function(typed_array,pinned_array,begin,end,bytes_per_element){if(!!(this.has_backing_array_buffer(typed_array)&&typed_array.BYTES_PER_ELEMENT)){if(bytes_per_element!==typed_array.BYTES_PER_ELEMENT)throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '"+typed_array.BYTES_PER_ELEMENT+"' sizeof managed element: '"+bytes_per_element+"'");var num_of_bytes=(end-begin)*bytes_per_element;var view_bytes=typed_array.length*typed_array.BYTES_PER_ELEMENT;if(num_of_bytes>view_bytes)num_of_bytes=view_bytes;var offset=begin*bytes_per_element;var heapBytes=new Uint8Array(Module.HEAPU8.buffer,pinned_array+offset,num_of_bytes);heapBytes.set(new Uint8Array(typed_array.buffer,typed_array.byteOffset,num_of_bytes));return num_of_bytes}else{throw new Error("Object '"+typed_array+"' is not a typed array")}},typedarray_copy_from:function(typed_array,pinned_array,begin,end,bytes_per_element){if(!!(this.has_backing_array_buffer(typed_array)&&typed_array.BYTES_PER_ELEMENT)){if(bytes_per_element!==typed_array.BYTES_PER_ELEMENT)throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '"+typed_array.BYTES_PER_ELEMENT+"' sizeof managed element: '"+bytes_per_element+"'");var num_of_bytes=(end-begin)*bytes_per_element;var view_bytes=typed_array.length*typed_array.BYTES_PER_ELEMENT;if(num_of_bytes>view_bytes)num_of_bytes=view_bytes;var typedarrayBytes=new Uint8Array(typed_array.buffer,0,num_of_bytes);var offset=begin*bytes_per_element;typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array+offset,pinned_array+offset+num_of_bytes));return num_of_bytes}else{throw new Error("Object '"+typed_array+"' is not a typed array")}},typed_array_from:function(pinned_array,begin,end,bytes_per_element,type){var newTypedArray=0;switch(type){case 5:newTypedArray=new Int8Array(end-begin);break;case 6:newTypedArray=new Uint8Array(end-begin);break;case 7:newTypedArray=new Int16Array(end-begin);break;case 8:newTypedArray=new Uint16Array(end-begin);break;case 9:newTypedArray=new Int32Array(end-begin);break;case 10:newTypedArray=new Uint32Array(end-begin);break;case 13:newTypedArray=new Float32Array(end-begin);break;case 14:newTypedArray=new Float64Array(end-begin);break;case 15:newTypedArray=new Uint8ClampedArray(end-begin);break}this.typedarray_copy_from(newTypedArray,pinned_array,begin,end,bytes_per_element);return newTypedArray},js_to_mono_enum:function(js_obj,method,parmIdx){this.bindings_lazy_init();if(typeof js_obj!=="number")throw new Error(`Expected numeric value for enum argument, got '${js_obj}'`);return js_obj|0},wasm_binding_obj_new:function(js_obj_id,ownsHandle,type){return this._bind_js_obj(js_obj_id,ownsHandle,type)},wasm_bind_existing:function(mono_obj,js_id){return this._bind_existing_obj(mono_obj,js_id)},wasm_bind_core_clr_obj:function(js_id,gc_handle){return this._bind_core_clr_obj(js_id,gc_handle)},wasm_get_js_id:function(mono_obj){return this._get_js_id(mono_obj)},wasm_get_raw_obj:function(gchandle){return this._get_raw_mono_obj(gchandle)},try_extract_mono_obj:function(js_obj){if(js_obj===null||typeof js_obj==="undefined"||typeof js_obj.__mono_gchandle__==="undefined")return 0;return this.wasm_get_raw_obj(js_obj.__mono_gchandle__)},mono_method_get_call_signature:function(method,mono_obj){this.bindings_lazy_init();return this.call_method(this.get_call_sig,null,"im",[method,mono_obj])},get_task_and_bind:function(tcs,js_obj){var gc_handle=this.mono_wasm_free_list.length?this.mono_wasm_free_list.pop():this.mono_wasm_ref_counter++;var task_gchandle=this.call_method(this.tcs_get_task_and_bind,null,"oi",[tcs,gc_handle+1]);js_obj.__mono_gchandle__=task_gchandle;this.mono_wasm_object_registry[gc_handle]=js_obj;this.free_task_completion_source(tcs);tcs.is_mono_tcs_task_bound=true;js_obj.__mono_bound_tcs__=tcs.__mono_gchandle__;tcs.__mono_bound_task__=js_obj.__mono_gchandle__;return this.wasm_get_raw_obj(js_obj.__mono_gchandle__)},free_task_completion_source:function(tcs){if(tcs.is_mono_tcs_result_set){this._unbind_raw_obj_and_free(tcs.__mono_gchandle__)}if(tcs.__mono_bound_task__){this._unbind_raw_obj_and_free(tcs.__mono_bound_task__)}},extract_mono_obj:function(js_obj){if(js_obj===null||typeof js_obj==="undefined")return 0;var result=null;var gc_handle=js_obj.__mono_gchandle__;if(gc_handle){result=this.wasm_get_raw_obj(gc_handle);if(!result){delete js_obj.__mono_gchandle__;delete js_obj.is_mono_bridged_obj}}if(!result){gc_handle=this.mono_wasm_register_obj(js_obj);result=this.wasm_get_raw_obj(gc_handle)}return result},extract_js_obj:function(mono_obj){if(mono_obj==0)return null;var js_id=this.wasm_get_js_id(mono_obj);if(js_id>0)return this.mono_wasm_require_handle(js_id);var gcHandle=this.mono_wasm_free_list.length?this.mono_wasm_free_list.pop():this.mono_wasm_ref_counter++;var js_obj={__mono_gchandle__:this.wasm_bind_existing(mono_obj,gcHandle+1),is_mono_bridged_obj:true};this.mono_wasm_object_registry[gcHandle]=js_obj;return js_obj},_create_named_function:function(name,argumentNames,body,closure){var result=null,closureArgumentList=null,closureArgumentNames=null;if(closure){closureArgumentNames=Object.keys(closure);closureArgumentList=new Array(closureArgumentNames.length);for(var i=0,l=closureArgumentNames.length;i0;var has_args_marshal=typeof args_marshal==="string";if(has_args){if(!has_args_marshal)throw new Error("No signature provided for method call.");else if(args.length>args_marshal.length)throw new Error("Too many parameter values. Expected at most "+args_marshal.length+" value(s) for signature "+args_marshal)}return has_args_marshal&&has_args},_get_buffer_for_method_call:function(converter){if(!converter)return 0;var result=converter.scratchBuffer;converter.scratchBuffer=0;return result},_get_args_root_buffer_for_method_call:function(converter){if(!converter)return null;if(!converter.needs_root_buffer)return null;var result;if(converter.scratchRootBuffer){result=converter.scratchRootBuffer;converter.scratchRootBuffer=null}else{result=MONO.mono_wasm_new_root_buffer(converter.steps.length);result.converter=converter}return result},_release_args_root_buffer_from_method_call:function(converter,argsRootBuffer){if(!argsRootBuffer||!converter)return;if(!converter.scratchRootBuffer){argsRootBuffer.clear();converter.scratchRootBuffer=argsRootBuffer}else{argsRootBuffer.release()}},_release_buffer_from_method_call:function(converter,buffer){if(!converter||!buffer)return;if(!converter.scratchBuffer)converter.scratchBuffer=buffer|0;else Module._free(buffer|0)},_convert_exception_for_method_call:function(result,exception){if(exception===0)return null;var msg=this.conv_string(result,false);var err=new Error(msg);return err},_maybe_produce_signature_warning:function(converter){if(converter.has_warned_about_signature)return;console.warn("MONO_WASM: Deprecated raw return value signature: '"+converter.args_marshal+"'. End the signature with '!' instead of 'm'.");converter.has_warned_about_signature=true},_decide_if_result_is_marshaled:function(converter,argc){if(!converter)return true;if(converter.is_result_possibly_unmarshaled&&argc===converter.result_unmarshaled_if_argc){if(argc= ",converter.result_unmarshaled_if_argc,"argument(s) but got",argc,"for signature "+converter.args_marshal].join(" "));this._maybe_produce_signature_warning(converter);return false}else{if(argc0&&Array.isArray(args[0]))args[0]=BINDING.js_array_to_mono_array(args[0],true);let result=BINDING.call_method(method,null,signature,args);return Promise.resolve(result)}catch(error){return Promise.reject(error)}}},call_assembly_entry_point:function(assembly,args,signature){return this.bind_assembly_entry_point(assembly,signature)(...args)},mono_wasm_register_obj:function(obj){var gc_handle=undefined;if(obj!==null&&typeof obj!=="undefined"){gc_handle=obj.__mono_gchandle__;if(typeof gc_handle==="undefined"){var handle=this.mono_wasm_free_list.length?this.mono_wasm_free_list.pop():this.mono_wasm_ref_counter++;obj.__mono_jshandle__=handle;var wasm_type=obj[Symbol.for("wasm type")];obj.__owns_handle__=true;gc_handle=obj.__mono_gchandle__=this.wasm_binding_obj_new(handle+1,obj.__owns_handle__,typeof wasm_type==="undefined"?-1:wasm_type);this.mono_wasm_object_registry[handle]=obj}}return gc_handle},mono_wasm_require_handle:function(handle){if(handle>0)return this.mono_wasm_object_registry[handle-1];return null},mono_wasm_unregister_obj:function(js_id){var obj=this.mono_wasm_object_registry[js_id-1];if(typeof obj!=="undefined"&&obj!==null){if(globalThis===obj)return obj;var gc_handle=obj.__mono_gchandle__;if(typeof gc_handle!=="undefined"){obj.__mono_gchandle__=undefined;obj.__mono_jshandle__=undefined;if(typeof obj.__mono_delegate_alive__!=="undefined")obj.__mono_delegate_alive__=false;this.mono_wasm_object_registry[js_id-1]=undefined;this.mono_wasm_free_list.push(js_id-1)}}return obj},mono_wasm_free_handle:function(handle){this.mono_wasm_unregister_obj(handle)},mono_wasm_free_raw_object:function(js_id){var obj=this.mono_wasm_object_registry[js_id-1];if(typeof obj!=="undefined"&&obj!==null){if(globalThis===obj)return obj;var gc_handle=obj.__mono_gchandle__;if(typeof gc_handle!=="undefined"){obj.__mono_gchandle__=undefined;obj.__mono_jshandle__=undefined;this.mono_wasm_object_registry[js_id-1]=undefined;this.mono_wasm_free_list.push(js_id-1)}}return obj},mono_wasm_parse_args:function(args){var js_args=this.mono_array_to_js_array(args);this.mono_wasm_save_LMF();return js_args},mono_wasm_save_LMF:function(){BINDING.mono_wasm_owned_objects_frames.push(BINDING.mono_wasm_owned_objects_LMF);BINDING.mono_wasm_owned_objects_LMF=undefined},mono_wasm_unwind_LMF:function(){var __owned_objects__=this.mono_wasm_owned_objects_frames.pop();if(typeof __owned_objects__!=="undefined"){var refidx;for(refidx=0;refidx<__owned_objects__.length;refidx++){var ownerRelease=__owned_objects__[refidx];this.call_method(this.safehandle_release_by_handle,null,"i",[ownerRelease])}}},mono_wasm_convert_return_value:function(ret){this.mono_wasm_unwind_LMF();return this.js_to_mono_obj(ret)}};function _mono_wasm_bind_core_object(js_handle,gc_handle,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}BINDING.wasm_bind_core_clr_obj(js_handle,gc_handle);requireObject.__mono_gchandle__=gc_handle;requireObject.__js_handle__=js_handle;return gc_handle}function _mono_wasm_bind_host_object(js_handle,gc_handle,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}BINDING.wasm_bind_core_clr_obj(js_handle,gc_handle);requireObject.__mono_gchandle__=gc_handle;return gc_handle}function _mono_wasm_fire_bp(){debugger}function _mono_wasm_fire_exception(exception_id,message,class_name,uncaught){MONO.active_exception={exception_id:exception_id,message:Module.UTF8ToString(message),class_name:Module.UTF8ToString(class_name),uncaught:uncaught};debugger}function _mono_wasm_get_by_index(js_handle,property_index,is_exception){BINDING.bindings_lazy_init();var obj=BINDING.mono_wasm_require_handle(js_handle);if(!obj){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}try{var m=obj[property_index];return BINDING.js_to_mono_obj(m)}catch(e){var res=e.toString();setValue(is_exception,1,"i32");if(res===null||typeof res==="undefined")res="unknown exception";return BINDING.js_string_to_mono_string(res)}}function _mono_wasm_get_global_object(global_name,is_exception){BINDING.bindings_lazy_init();var js_name=BINDING.conv_string(global_name,false);var globalObj;if(!js_name){globalObj=globalThis}else{globalObj=globalThis[js_name]}if(globalObj===null||typeof globalObj===undefined){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Global object '"+js_name+"' not found.")}return BINDING.js_to_mono_obj(globalObj)}function _mono_wasm_get_object_property(js_handle,property_name,is_exception){BINDING.bindings_lazy_init();var obj=BINDING.mono_wasm_require_handle(js_handle);if(!obj){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var js_name=BINDING.conv_string(property_name,false);if(!js_name){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid property name object '"+js_name+"'")}var res;try{var m=obj[js_name];if(m===Object(m)&&obj.__is_mono_proxied__)m.__is_mono_proxied__=true;return BINDING.js_to_mono_obj(m)}catch(e){var res=e.toString();setValue(is_exception,1,"i32");if(res===null||typeof res==="undefined")res="unknown exception";return BINDING.js_string_to_mono_string(res)}}var DOTNET={conv_string:function(mono_obj){return MONO.string_decoder.copy(mono_obj)}};function _mono_wasm_invoke_js_blazor(exceptionMessage,callInfo,arg0,arg1,arg2){var mono_string=globalThis._mono_string_cached||(globalThis._mono_string_cached=Module.cwrap("mono_wasm_string_from_js","number",["string"]));try{var blazorExports=globalThis.Blazor;if(!blazorExports){throw new Error("The blazor.webassembly.js library is not loaded.")}return blazorExports._internal.invokeJSFromDotNet(callInfo,arg0,arg1,arg2)}catch(ex){var exceptionJsString=ex.message+"\n"+ex.stack;var exceptionSystemString=mono_string(exceptionJsString);setValue(exceptionMessage,exceptionSystemString,"i32");return 0}}function _mono_wasm_invoke_js_marshalled(exceptionMessage,asyncHandleLongPtr,functionName,argsJson,treatResultAsVoid){var mono_string=globalThis._mono_string_cached||(globalThis._mono_string_cached=Module.cwrap("mono_wasm_string_from_js","number",["string"]));try{var u32Index=asyncHandleLongPtr>>2;var asyncHandleJsNumber=Module.HEAPU32[u32Index+1]*4294967296+Module.HEAPU32[u32Index];var funcNameJsString=DOTNET.conv_string(functionName);var argsJsonJsString=argsJson&&DOTNET.conv_string(argsJson);var dotNetExports=globaThis.DotNet;if(!dotNetExports){throw new Error("The Microsoft.JSInterop.js library is not loaded.")}if(asyncHandleJsNumber){dotNetExports.jsCallDispatcher.beginInvokeJSFromDotNet(asyncHandleJsNumber,funcNameJsString,argsJsonJsString,treatResultAsVoid);return 0}else{var resultJson=dotNetExports.jsCallDispatcher.invokeJSFromDotNet(funcNameJsString,argsJsonJsString,treatResultAsVoid);return resultJson===null?0:mono_string(resultJson)}}catch(ex){var exceptionJsString=ex.message+"\n"+ex.stack;var exceptionSystemString=mono_string(exceptionJsString);setValue(exceptionMessage,exceptionSystemString,"i32");return 0}}function _mono_wasm_invoke_js_unmarshalled(exceptionMessage,funcName,arg0,arg1,arg2){try{var funcNameJsString=DOTNET.conv_string(funcName);var dotNetExports=globalThis.DotNet;if(!dotNetExports){throw new Error("The Microsoft.JSInterop.js library is not loaded.")}var funcInstance=dotNetExports.jsCallDispatcher.findJSFunction(funcNameJsString);return funcInstance.call(null,arg0,arg1,arg2)}catch(ex){var exceptionJsString=ex.message+"\n"+ex.stack;var mono_string=Module.cwrap("mono_wasm_string_from_js","number",["string"]);var exceptionSystemString=mono_string(exceptionJsString);setValue(exceptionMessage,exceptionSystemString,"i32");return 0}}function _mono_wasm_invoke_js_with_args(js_handle,method_name,args,is_exception){BINDING.bindings_lazy_init();var obj=BINDING.get_js_obj(js_handle);if(!obj){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var js_name=BINDING.conv_string(method_name,false);if(!js_name){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid method name object '"+method_name+"'")}var js_args=BINDING.mono_wasm_parse_args(args);var res;try{var m=obj[js_name];if(typeof m==="undefined")throw new Error("Method: '"+js_name+"' not found for: '"+Object.prototype.toString.call(obj)+"'");var res=m.apply(obj,js_args);return BINDING.mono_wasm_convert_return_value(res)}catch(e){BINDING.mono_wasm_unwind_LMF();var res=e.toString();setValue(is_exception,1,"i32");if(res===null||res===undefined)res="unknown exception";return BINDING.js_string_to_mono_string(res)}}function _mono_wasm_new(core_name,args,is_exception){BINDING.bindings_lazy_init();var js_name=BINDING.conv_string(core_name,false);if(!js_name){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Core object '"+js_name+"' not found.")}var coreObj=globalThis[js_name];if(coreObj===null||typeof coreObj==="undefined"){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("JavaScript host object '"+js_name+"' not found.")}var js_args=BINDING.mono_wasm_parse_args(args);try{var allocator=function(constructor,js_args){var argsList=new Array;argsList[0]=constructor;if(js_args)argsList=argsList.concat(js_args);var tempCtor=constructor.bind.apply(constructor,argsList);var obj=new tempCtor;return obj};var res=allocator(coreObj,js_args);var gc_handle=BINDING.mono_wasm_free_list.length?BINDING.mono_wasm_free_list.pop():BINDING.mono_wasm_ref_counter++;BINDING.mono_wasm_object_registry[gc_handle]=res;return BINDING.mono_wasm_convert_return_value(gc_handle+1)}catch(e){var res=e.toString();setValue(is_exception,1,"i32");if(res===null||res===undefined)res="Error allocating object.";return BINDING.js_string_to_mono_string(res)}}function _mono_wasm_release_handle(js_handle,is_exception){BINDING.bindings_lazy_init();BINDING.mono_wasm_free_handle(js_handle)}function _mono_wasm_release_object(js_handle,is_exception){BINDING.bindings_lazy_init();BINDING.mono_wasm_free_raw_object(js_handle)}function _mono_wasm_set_by_index(js_handle,property_index,value,is_exception){BINDING.bindings_lazy_init();var obj=BINDING.mono_wasm_require_handle(js_handle);if(!obj){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var js_value=BINDING.unbox_mono_obj(value);BINDING.mono_wasm_save_LMF();try{obj[property_index]=js_value;BINDING.mono_wasm_unwind_LMF();return true}catch(e){var res=e.toString();setValue(is_exception,1,"i32");if(res===null||typeof res==="undefined")res="unknown exception";return BINDING.js_string_to_mono_string(res)}}function _mono_wasm_set_is_async_method(objectId){MONO._async_method_objectId=objectId}function _mono_wasm_set_object_property(js_handle,property_name,value,createIfNotExist,hasOwnProperty,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var property=BINDING.conv_string(property_name,false);if(!property){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid property name object '"+property_name+"'")}var result=false;var js_value=BINDING.unbox_mono_obj(value);BINDING.mono_wasm_save_LMF();if(createIfNotExist){requireObject[property]=js_value;result=true}else{result=false;if(!createIfNotExist){if(!requireObject.hasOwnProperty(property))return false}if(hasOwnProperty===true){if(requireObject.hasOwnProperty(property)){requireObject[property]=js_value;result=true}}else{requireObject[property]=js_value;result=true}}BINDING.mono_wasm_unwind_LMF();return BINDING._box_js_bool(result)}function _mono_wasm_typed_array_copy_from(js_handle,pinned_array,begin,end,bytes_per_element,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var res=BINDING.typedarray_copy_from(requireObject,pinned_array,begin,end,bytes_per_element);return BINDING.js_to_mono_obj(res)}function _mono_wasm_typed_array_copy_to(js_handle,pinned_array,begin,end,bytes_per_element,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}var res=BINDING.typedarray_copy_to(requireObject,pinned_array,begin,end,bytes_per_element);return BINDING.js_to_mono_obj(res)}function _mono_wasm_typed_array_from(pinned_array,begin,end,bytes_per_element,type,is_exception){BINDING.bindings_lazy_init();var res=BINDING.typed_array_from(pinned_array,begin,end,bytes_per_element,type);return BINDING.js_to_mono_obj(res)}function _mono_wasm_typed_array_to_array(js_handle,is_exception){BINDING.bindings_lazy_init();var requireObject=BINDING.mono_wasm_require_handle(js_handle);if(!requireObject){setValue(is_exception,1,"i32");return BINDING.js_string_to_mono_string("Invalid JS object handle '"+js_handle+"'")}return BINDING.js_typed_array_to_array(requireObject)}function _schedule_background_exec(){++MONO.pump_count;if(typeof globalThis.setTimeout==="function"){globalThis.setTimeout(MONO.pump_message,0)}}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"},"%V":function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _sysconf(name){switch(name){case 30:return 16384;case 85:var maxHeapSize=2147483648;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:case 80:case 81:case 79:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return-1}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var double=ch<105;if(double&&buf&1)buf++;readAsmConstArgsArray.push(double?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;MONO.export_functions(Module);BINDING.export_functions(Module);function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var asmLibraryArg={"q":___assert_fail,"Ra":___clock_gettime,"Qa":___cxa_allocate_exception,"Pa":___cxa_begin_catch,"Oa":___cxa_end_catch,"Na":___cxa_find_matching_catch_3,"Ma":___cxa_throw,"La":___resumeException,"xa":___sys_access,"Ja":___sys_chdir,"x":___sys_chmod,"Aa":___sys_fadvise64_64,"ya":___sys_fallocate,"oa":___sys_fchmod,"d":___sys_fcntl64,"Da":___sys_fstat64,"Fa":___sys_ftruncate64,"Ha":___sys_getcwd,"Ba":___sys_getdents64,"j":___sys_getpid,"sa":___sys_getrusage,"ta":___sys_ioctl,"qa":___sys_link,"Ea":___sys_lstat64,"Ca":___sys_madvise1,"va":___sys_mkdir,"Ga":___sys_mmap2,"Ia":___sys_msync,"pa":___sys_munmap,"v":___sys_open,"ra":___sys_readlink,"wa":___sys_rename,"ua":___sys_rmdir,"m":___sys_socketcall,"w":___sys_stat64,"Ka":___sys_unlink,"za":___sys_utimensat,"a":_abort,"ja":_clock_getres,"h":_clock_gettime,"ia":compile_function,"t":_dotnet_browser_entropy,"f":_emscripten_asm_const_int,"ha":_emscripten_memcpy_big,"ga":_emscripten_resize_heap,"fa":_emscripten_thread_sleep,"na":_environ_get,"ma":_environ_sizes_get,"c":_exit,"i":_fd_close,"la":_fd_fdstat_get,"u":_fd_read,"$":_fd_seek,"ka":_fd_sync,"p":_fd_write,"ea":_flock,"da":_gai_strerror,"ca":_getTempRet0,"e":_gettimeofday,"ba":_gmtime_r,"aa":invoke_vi,"W":_llvm_eh_typeid_for,"l":_localtime_r,"V":_mono_set_timeout,"U":_mono_wasm_add_array_item,"_":_mono_wasm_add_enum_var,"T":_mono_wasm_add_frame,"Z":_mono_wasm_add_func_var,"Y":_mono_wasm_add_obj_var,"k":_mono_wasm_add_properties_var,"b":_mono_wasm_add_typed_value,"s":_mono_wasm_asm_loaded,"S":_mono_wasm_bind_core_object,"R":_mono_wasm_bind_host_object,"r":_mono_wasm_fire_bp,"Q":_mono_wasm_fire_exception,"P":_mono_wasm_get_by_index,"O":_mono_wasm_get_global_object,"N":_mono_wasm_get_object_property,"M":_mono_wasm_invoke_js_blazor,"L":_mono_wasm_invoke_js_marshalled,"K":_mono_wasm_invoke_js_unmarshalled,"J":_mono_wasm_invoke_js_with_args,"I":_mono_wasm_new,"H":_mono_wasm_release_handle,"G":_mono_wasm_release_object,"F":_mono_wasm_set_by_index,"X":_mono_wasm_set_is_async_method,"E":_mono_wasm_set_object_property,"D":_mono_wasm_typed_array_copy_from,"C":_mono_wasm_typed_array_copy_to,"B":_mono_wasm_typed_array_from,"A":_mono_wasm_typed_array_to_array,"z":_schedule_background_exec,"o":_strftime,"g":_sysconf,"n":_time,"y":_tzset};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["Ua"]).apply(null,arguments)};var _mono_wasm_register_root=Module["_mono_wasm_register_root"]=function(){return(_mono_wasm_register_root=Module["_mono_wasm_register_root"]=Module["asm"]["Va"]).apply(null,arguments)};var _mono_wasm_deregister_root=Module["_mono_wasm_deregister_root"]=function(){return(_mono_wasm_deregister_root=Module["_mono_wasm_deregister_root"]=Module["asm"]["Wa"]).apply(null,arguments)};var _mono_wasm_add_assembly=Module["_mono_wasm_add_assembly"]=function(){return(_mono_wasm_add_assembly=Module["_mono_wasm_add_assembly"]=Module["asm"]["Xa"]).apply(null,arguments)};var _mono_wasm_add_satellite_assembly=Module["_mono_wasm_add_satellite_assembly"]=function(){return(_mono_wasm_add_satellite_assembly=Module["_mono_wasm_add_satellite_assembly"]=Module["asm"]["Ya"]).apply(null,arguments)};var _mono_wasm_setenv=Module["_mono_wasm_setenv"]=function(){return(_mono_wasm_setenv=Module["_mono_wasm_setenv"]=Module["asm"]["Za"]).apply(null,arguments)};var _mono_wasm_register_bundled_satellite_assemblies=Module["_mono_wasm_register_bundled_satellite_assemblies"]=function(){return(_mono_wasm_register_bundled_satellite_assemblies=Module["_mono_wasm_register_bundled_satellite_assemblies"]=Module["asm"]["_a"]).apply(null,arguments)};var _mono_wasm_load_runtime=Module["_mono_wasm_load_runtime"]=function(){return(_mono_wasm_load_runtime=Module["_mono_wasm_load_runtime"]=Module["asm"]["$a"]).apply(null,arguments)};var _mono_wasm_assembly_load=Module["_mono_wasm_assembly_load"]=function(){return(_mono_wasm_assembly_load=Module["_mono_wasm_assembly_load"]=Module["asm"]["ab"]).apply(null,arguments)};var _mono_wasm_find_corlib_class=Module["_mono_wasm_find_corlib_class"]=function(){return(_mono_wasm_find_corlib_class=Module["_mono_wasm_find_corlib_class"]=Module["asm"]["bb"]).apply(null,arguments)};var _mono_wasm_assembly_find_class=Module["_mono_wasm_assembly_find_class"]=function(){return(_mono_wasm_assembly_find_class=Module["_mono_wasm_assembly_find_class"]=Module["asm"]["cb"]).apply(null,arguments)};var _mono_wasm_assembly_find_method=Module["_mono_wasm_assembly_find_method"]=function(){return(_mono_wasm_assembly_find_method=Module["_mono_wasm_assembly_find_method"]=Module["asm"]["db"]).apply(null,arguments)};var _mono_wasm_get_delegate_invoke=Module["_mono_wasm_get_delegate_invoke"]=function(){return(_mono_wasm_get_delegate_invoke=Module["_mono_wasm_get_delegate_invoke"]=Module["asm"]["eb"]).apply(null,arguments)};var _mono_wasm_box_primitive=Module["_mono_wasm_box_primitive"]=function(){return(_mono_wasm_box_primitive=Module["_mono_wasm_box_primitive"]=Module["asm"]["fb"]).apply(null,arguments)};var _mono_wasm_invoke_method=Module["_mono_wasm_invoke_method"]=function(){return(_mono_wasm_invoke_method=Module["_mono_wasm_invoke_method"]=Module["asm"]["gb"]).apply(null,arguments)};var _mono_wasm_assembly_get_entry_point=Module["_mono_wasm_assembly_get_entry_point"]=function(){return(_mono_wasm_assembly_get_entry_point=Module["_mono_wasm_assembly_get_entry_point"]=Module["asm"]["hb"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["ib"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["jb"]).apply(null,arguments)};var _mono_wasm_string_get_utf8=Module["_mono_wasm_string_get_utf8"]=function(){return(_mono_wasm_string_get_utf8=Module["_mono_wasm_string_get_utf8"]=Module["asm"]["kb"]).apply(null,arguments)};var _mono_wasm_string_convert=Module["_mono_wasm_string_convert"]=function(){return(_mono_wasm_string_convert=Module["_mono_wasm_string_convert"]=Module["asm"]["lb"]).apply(null,arguments)};var _mono_wasm_string_from_js=Module["_mono_wasm_string_from_js"]=function(){return(_mono_wasm_string_from_js=Module["_mono_wasm_string_from_js"]=Module["asm"]["mb"]).apply(null,arguments)};var _mono_wasm_string_from_utf16=Module["_mono_wasm_string_from_utf16"]=function(){return(_mono_wasm_string_from_utf16=Module["_mono_wasm_string_from_utf16"]=Module["asm"]["nb"]).apply(null,arguments)};var _mono_wasm_get_obj_type=Module["_mono_wasm_get_obj_type"]=function(){return(_mono_wasm_get_obj_type=Module["_mono_wasm_get_obj_type"]=Module["asm"]["ob"]).apply(null,arguments)};var _mono_wasm_try_unbox_primitive_and_get_type=Module["_mono_wasm_try_unbox_primitive_and_get_type"]=function(){return(_mono_wasm_try_unbox_primitive_and_get_type=Module["_mono_wasm_try_unbox_primitive_and_get_type"]=Module["asm"]["pb"]).apply(null,arguments)};var _mono_unbox_int=Module["_mono_unbox_int"]=function(){return(_mono_unbox_int=Module["_mono_unbox_int"]=Module["asm"]["qb"]).apply(null,arguments)};var _mono_wasm_array_length=Module["_mono_wasm_array_length"]=function(){return(_mono_wasm_array_length=Module["_mono_wasm_array_length"]=Module["asm"]["rb"]).apply(null,arguments)};var _mono_wasm_array_get=Module["_mono_wasm_array_get"]=function(){return(_mono_wasm_array_get=Module["_mono_wasm_array_get"]=Module["asm"]["sb"]).apply(null,arguments)};var _mono_wasm_obj_array_new=Module["_mono_wasm_obj_array_new"]=function(){return(_mono_wasm_obj_array_new=Module["_mono_wasm_obj_array_new"]=Module["asm"]["tb"]).apply(null,arguments)};var _mono_wasm_obj_array_set=Module["_mono_wasm_obj_array_set"]=function(){return(_mono_wasm_obj_array_set=Module["_mono_wasm_obj_array_set"]=Module["asm"]["ub"]).apply(null,arguments)};var _mono_wasm_string_array_new=Module["_mono_wasm_string_array_new"]=function(){return(_mono_wasm_string_array_new=Module["_mono_wasm_string_array_new"]=Module["asm"]["vb"]).apply(null,arguments)};var _mono_wasm_exec_regression=Module["_mono_wasm_exec_regression"]=function(){return(_mono_wasm_exec_regression=Module["_mono_wasm_exec_regression"]=Module["asm"]["wb"]).apply(null,arguments)};var _mono_wasm_exit=Module["_mono_wasm_exit"]=function(){return(_mono_wasm_exit=Module["_mono_wasm_exit"]=Module["asm"]["xb"]).apply(null,arguments)};var _mono_wasm_set_main_args=Module["_mono_wasm_set_main_args"]=function(){return(_mono_wasm_set_main_args=Module["_mono_wasm_set_main_args"]=Module["asm"]["yb"]).apply(null,arguments)};var _mono_wasm_strdup=Module["_mono_wasm_strdup"]=function(){return(_mono_wasm_strdup=Module["_mono_wasm_strdup"]=Module["asm"]["zb"]).apply(null,arguments)};var _mono_wasm_parse_runtime_options=Module["_mono_wasm_parse_runtime_options"]=function(){return(_mono_wasm_parse_runtime_options=Module["_mono_wasm_parse_runtime_options"]=Module["asm"]["Ab"]).apply(null,arguments)};var _mono_wasm_enable_on_demand_gc=Module["_mono_wasm_enable_on_demand_gc"]=function(){return(_mono_wasm_enable_on_demand_gc=Module["_mono_wasm_enable_on_demand_gc"]=Module["asm"]["Bb"]).apply(null,arguments)};var _mono_wasm_intern_string=Module["_mono_wasm_intern_string"]=function(){return(_mono_wasm_intern_string=Module["_mono_wasm_intern_string"]=Module["asm"]["Cb"]).apply(null,arguments)};var _mono_wasm_typed_array_new=Module["_mono_wasm_typed_array_new"]=function(){return(_mono_wasm_typed_array_new=Module["_mono_wasm_typed_array_new"]=Module["asm"]["Db"]).apply(null,arguments)};var _mono_wasm_unbox_enum=Module["_mono_wasm_unbox_enum"]=function(){return(_mono_wasm_unbox_enum=Module["_mono_wasm_unbox_enum"]=Module["asm"]["Eb"]).apply(null,arguments)};var _memset=Module["_memset"]=function(){return(_memset=Module["_memset"]=Module["asm"]["Fb"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["Gb"]).apply(null,arguments)};var _putchar=Module["_putchar"]=function(){return(_putchar=Module["_putchar"]=Module["asm"]["Hb"]).apply(null,arguments)};var _mono_background_exec=Module["_mono_background_exec"]=function(){return(_mono_background_exec=Module["_mono_background_exec"]=Module["asm"]["Ib"]).apply(null,arguments)};var _mono_wasm_get_icudt_name=Module["_mono_wasm_get_icudt_name"]=function(){return(_mono_wasm_get_icudt_name=Module["_mono_wasm_get_icudt_name"]=Module["asm"]["Jb"]).apply(null,arguments)};var _mono_wasm_load_icu_data=Module["_mono_wasm_load_icu_data"]=function(){return(_mono_wasm_load_icu_data=Module["_mono_wasm_load_icu_data"]=Module["asm"]["Kb"]).apply(null,arguments)};var _mono_print_method_from_ip=Module["_mono_print_method_from_ip"]=function(){return(_mono_print_method_from_ip=Module["_mono_print_method_from_ip"]=Module["asm"]["Lb"]).apply(null,arguments)};var _mono_set_timeout_exec=Module["_mono_set_timeout_exec"]=function(){return(_mono_set_timeout_exec=Module["_mono_set_timeout_exec"]=Module["asm"]["Mb"]).apply(null,arguments)};var _mono_wasm_pause_on_exceptions=Module["_mono_wasm_pause_on_exceptions"]=function(){return(_mono_wasm_pause_on_exceptions=Module["_mono_wasm_pause_on_exceptions"]=Module["asm"]["Nb"]).apply(null,arguments)};var _mono_wasm_setup_single_step=Module["_mono_wasm_setup_single_step"]=function(){return(_mono_wasm_setup_single_step=Module["_mono_wasm_setup_single_step"]=Module["asm"]["Ob"]).apply(null,arguments)};var _mono_wasm_clear_all_breakpoints=Module["_mono_wasm_clear_all_breakpoints"]=function(){return(_mono_wasm_clear_all_breakpoints=Module["_mono_wasm_clear_all_breakpoints"]=Module["asm"]["Pb"]).apply(null,arguments)};var _mono_wasm_set_breakpoint=Module["_mono_wasm_set_breakpoint"]=function(){return(_mono_wasm_set_breakpoint=Module["_mono_wasm_set_breakpoint"]=Module["asm"]["Qb"]).apply(null,arguments)};var _mono_wasm_remove_breakpoint=Module["_mono_wasm_remove_breakpoint"]=function(){return(_mono_wasm_remove_breakpoint=Module["_mono_wasm_remove_breakpoint"]=Module["asm"]["Rb"]).apply(null,arguments)};var _mono_wasm_current_bp_id=Module["_mono_wasm_current_bp_id"]=function(){return(_mono_wasm_current_bp_id=Module["_mono_wasm_current_bp_id"]=Module["asm"]["Sb"]).apply(null,arguments)};var _mono_wasm_enum_frames=Module["_mono_wasm_enum_frames"]=function(){return(_mono_wasm_enum_frames=Module["_mono_wasm_enum_frames"]=Module["asm"]["Tb"]).apply(null,arguments)};var _mono_wasm_set_variable_on_frame=Module["_mono_wasm_set_variable_on_frame"]=function(){return(_mono_wasm_set_variable_on_frame=Module["_mono_wasm_set_variable_on_frame"]=Module["asm"]["Ub"]).apply(null,arguments)};var _mono_wasm_get_deref_ptr_value=Module["_mono_wasm_get_deref_ptr_value"]=function(){return(_mono_wasm_get_deref_ptr_value=Module["_mono_wasm_get_deref_ptr_value"]=Module["asm"]["Vb"]).apply(null,arguments)};var _mono_wasm_get_local_vars=Module["_mono_wasm_get_local_vars"]=function(){return(_mono_wasm_get_local_vars=Module["_mono_wasm_get_local_vars"]=Module["asm"]["Wb"]).apply(null,arguments)};var _mono_wasm_get_object_properties=Module["_mono_wasm_get_object_properties"]=function(){return(_mono_wasm_get_object_properties=Module["_mono_wasm_get_object_properties"]=Module["asm"]["Xb"]).apply(null,arguments)};var _mono_wasm_get_array_values=Module["_mono_wasm_get_array_values"]=function(){return(_mono_wasm_get_array_values=Module["_mono_wasm_get_array_values"]=Module["asm"]["Yb"]).apply(null,arguments)};var _mono_wasm_invoke_getter_on_object=Module["_mono_wasm_invoke_getter_on_object"]=function(){return(_mono_wasm_invoke_getter_on_object=Module["_mono_wasm_invoke_getter_on_object"]=Module["asm"]["Zb"]).apply(null,arguments)};var _mono_wasm_set_value_on_object=Module["_mono_wasm_set_value_on_object"]=function(){return(_mono_wasm_set_value_on_object=Module["_mono_wasm_set_value_on_object"]=Module["asm"]["_b"]).apply(null,arguments)};var _mono_wasm_invoke_getter_on_value=Module["_mono_wasm_invoke_getter_on_value"]=function(){return(_mono_wasm_invoke_getter_on_value=Module["_mono_wasm_invoke_getter_on_value"]=Module["asm"]["$b"]).apply(null,arguments)};var _mono_wasm_set_is_debugger_attached=Module["_mono_wasm_set_is_debugger_attached"]=function(){return(_mono_wasm_set_is_debugger_attached=Module["_mono_wasm_set_is_debugger_attached"]=Module["asm"]["ac"]).apply(null,arguments)};var _ntohs=Module["_ntohs"]=function(){return(_ntohs=Module["_ntohs"]=Module["asm"]["bc"]).apply(null,arguments)};var _htons=Module["_htons"]=function(){return(_htons=Module["_htons"]=Module["asm"]["cc"]).apply(null,arguments)};var __get_tzname=Module["__get_tzname"]=function(){return(__get_tzname=Module["__get_tzname"]=Module["asm"]["dc"]).apply(null,arguments)};var __get_daylight=Module["__get_daylight"]=function(){return(__get_daylight=Module["__get_daylight"]=Module["asm"]["ec"]).apply(null,arguments)};var __get_timezone=Module["__get_timezone"]=function(){return(__get_timezone=Module["__get_timezone"]=Module["asm"]["fc"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["gc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["hc"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["ic"]).apply(null,arguments)};var _setThrew=Module["_setThrew"]=function(){return(_setThrew=Module["_setThrew"]=Module["asm"]["jc"]).apply(null,arguments)};var _memalign=Module["_memalign"]=function(){return(_memalign=Module["_memalign"]=Module["asm"]["kc"]).apply(null,arguments)};function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["UTF8ArrayToString"]=UTF8ArrayToString;Module["UTF8ToString"]=UTF8ToString;Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;Module["addFunction"]=addFunction;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime){}else{EXITSTATUS=status;exitRuntime();if(Module["onExit"])Module["onExit"](status);ABORT=true}quit_(status,new ExitStatus(status))}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); + +// SIG // Begin signature block +// SIG // MIIkiQYJKoZIhvcNAQcCoIIkejCCJHYCAQExDzANBglg +// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor +// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC +// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg +// SIG // PLeKwAgCwe2CPN782zkeEf0KfzZbJmCrLpS8iENFFtWg +// SIG // gg3wMIIGbjCCBFagAwIBAgITMwAAAhOMDBwxNbzSXwAA +// SIG // AAACEzANBgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJV +// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT +// SIG // aWduaW5nIFBDQSAyMDExMB4XDTIxMDIxMTIwMDk1MVoX +// SIG // DTIyMDIxMDIwMDk1MVowYzELMAkGA1UEBhMCVVMxEzAR +// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v +// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +// SIG // bjENMAsGA1UEAxMELk5FVDCCAaIwDQYJKoZIhvcNAQEB +// SIG // BQADggGPADCCAYoCggGBAJtZcELdrGHlHCF6nz4bH8vW +// SIG // l5M3GfXIf7JY7OovRwgweTptJQGby0YHZ+iCrWIE7fTc +// SIG // /c9eGKGm+EsuWHnanAm9Ro7MSjdPsYBRaif1Y6dyhBcb +// SIG // b44guUNKlplq7L1k3ldXFFzyAt+u8UzCL5QFwibg2nWi +// SIG // QmCkoJWhiA6RxEPgEZ/ss2ICppgLHm1o6vy1P4ci6aMk +// SIG // Tj2s1uct/oFflYwE0DsK1OrFH7QvoIqWCAuXUXjZOKnF +// SIG // oRia22+ci2oxs/LVkgqcMwC35KHvUBzCW3LME/dSBWCO +// SIG // TV7gieG+gUtxBgPpzomak4thtrQLMRAWl7AOtI7QvsXa +// SIG // FEyQpAlDVz12Sa89KJOLBPksBRDw4woRZLlHnUrtxFRp +// SIG // MZsr+9cf2zfZPG4ia2iDSBFfXu2BeXrifkT4c/UV5Iy3 +// SIG // qEHCzh1jLmN701jUOhF1QN1LEPn+TCth2b239/34+Bym +// SIG // cIAcDP1EWk8JodsUDedKhK+lAefNL0mzUrIQc6Dxb5cq +// SIG // may/QQIDAQABo4IBfjCCAXowHwYDVR0lBBgwFgYKKwYB +// SIG // BAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFO9NaSC3 +// SIG // 3IwsQ0OKpWHnclste605MFAGA1UdEQRJMEekRTBDMSkw +// SIG // JwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy +// SIG // dG8gUmljbzEWMBQGA1UEBRMNNDY0MjIzKzQ2NDI5MzAf +// SIG // BgNVHSMEGDAWgBRIbmTlUAXTgqoXNzcitW2oynUClTBU +// SIG // BgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jv +// SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUw +// SIG // UzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3Nv +// SIG // ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAw +// SIG // DQYJKoZIhvcNAQEMBQADggIBAFiD+cR0K6evMUeUrBMA +// SIG // pLljV65GDDTzlD4jqr6Mu1NTeZv5L9IJlR6DLAEKaJnB +// SIG // a7fZZ/ME/FZasmc40+WijhDmth/OOc7IpfJ3Ra1auKIA +// SIG // g687mo/eWiPs0nC42oCdchy9Q5AS7K0+MUk7R/p9eCTP +// SIG // NYFjSMItiL+YFYCxaZXqHizwdXcvCIrESq4DXwN+ZdUe +// SIG // GBEO9F2SkMVC61/y2xwSwRWmfO/l4YutKT+dSKjlelYi +// SIG // zFAQaJrGzO5ac56S+K/NMndPL7Od3ohqxMu7gsFUynxY +// SIG // l+eyB9T9I9HrUWoHj6ce4nzOxHC+yDRD6Mi2AaT+IbMO +// SIG // cGvWeJC5iX3tzpMqdz0BOMl6jbff+t+BLS7VtU6JAFCM +// SIG // fk5h+wqIPWjon3tpTuFtCkMOSzIoso3U6kdX0fgrgXnN +// SIG // KJspBXkfKG9lMPOPOKwzua1qjghvgzPMftj1yZqFljJm +// SIG // cjBxs/HKA8J8st1MKcgiBGDX5zkcsHYGuAkIb2fXQuYW +// SIG // y0G78JzzSv1u0LAFj8/Qtx9Hm2wfc20+ww+MYEQ9tu1F +// SIG // uJZK2O7+p7iVziwZvo+XVzuIU7sVjcmJH5Gn/ttfkLQ3 +// SIG // 0jvM9QyV/lYwurg4Gn5Li/IZSN56WGIPilRkXUVurpaV +// SIG // WeYCjeUJzMY2n2tVMFl6pgnGmaA2a0uiG3z0GpMPdbS1 +// SIG // R/oEMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +// SIG // hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV +// SIG // BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +// SIG // HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +// SIG // MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +// SIG // dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5 +// SIG // WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJVUzET +// SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +// SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +// SIG // aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWdu +// SIG // aW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOC +// SIG // Ag8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGf +// SIG // Qhsqa+laUKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDI +// SIG // OdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv +// SIG // 2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13Y +// SIG // xC4Ddato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT +// SIG // +OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +// SIG // 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk +// SIG // kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXD +// SIG // OW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf +// SIG // GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +// SIG // JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bys +// SIG // AoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J64HLn +// SIG // JN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeB +// SIG // e+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx +// SIG // 7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu+HggWCwT +// SIG // XWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEA +// SIG // AaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1Ud +// SIG // DgQWBBRIbmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEE +// SIG // AYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw +// SIG // DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToC +// SIG // MZBDuRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBL +// SIG // hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +// SIG // bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf +// SIG // MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEF +// SIG // BQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br +// SIG // aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +// SIG // MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcu +// SIG // AzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy +// SIG // b3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMu +// SIG // aHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABf +// SIG // AHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0AZQBuAHQA +// SIG // LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou +// SIG // 09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+ +// SIG // vj/oCso7v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzS +// SIG // Gksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlE +// SIG // PXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6V +// SIG // oCo/KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu +// SIG // 5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +// SIG // STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp +// SIG // mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38c +// SIG // bxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN +// SIG // pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +// SIG // QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AA +// SIG // KcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74v2u3 +// SIG // S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8 +// SIG // MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7 +// SIG // qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJ +// SIG // UnMTDXpQzTGCFfEwghXtAgEBMIGVMH4xCzAJBgNVBAYT +// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH +// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +// SIG // cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2Rl +// SIG // IFNpZ25pbmcgUENBIDIwMTECEzMAAAITjAwcMTW80l8A +// SIG // AAAAAhMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN +// SIG // AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +// SIG // MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIO+j +// SIG // /BZlk1fhkXEi+WULmsUiSkNrwq1x/0ZWBzjJYz6KMEIG +// SIG // CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv +// SIG // AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w +// SIG // DQYJKoZIhvcNAQEBBQAEggGAFA2yiPcmjO5fRqia9Wia +// SIG // uE4PtJ1/ht2JzVjgxuO5qR65vahC3mqQYtuP4Rob01W+ +// SIG // jMrXoGElLlAmcDnjer7uVhNdojFma3G8HmuxLZdXMq1f +// SIG // +aJI3O+nM5vZKHaBY9pYxU1pa3TkUvtZZ/YJFBdhbKZD +// SIG // Ls1MYVhTkSwDeneYZoTMnUuGRHh+PaId1aHZKpYlVtdV +// SIG // j7fe4MA69cxp/L1/kImlYrXyEOCKsjMoYP2+2oPVsCSd +// SIG // EqGO7WjkMCeL+pVy0jJhp33rc/zQcmlPckMUNfj7PCxH +// SIG // u8uiphWyyKqYnsw+GSFMNwmREcQBSn7eN6/Vba07M74M +// SIG // O3izrFGoobjArchg5sSefgDBSURVDhZgb/0c+MOXH3o1 +// SIG // LvJratAGmsYH6l7UYF03diOLAUENmv+xODrOs7zkH7hJ +// SIG // A9wGcELhUZjHA9YiGpc/ArBooRskd+F+uo7PCndVOSVq +// SIG // LNCIqeZcl20g/lskSIAh6ww5+ELR+TiC+P+N/du+FBHY +// SIG // doBM1fBaoYIS+zCCEvcGCisGAQQBgjcDAwExghLnMIIS +// SIG // 4wYJKoZIhvcNAQcCoIIS1DCCEtACAQMxDzANBglghkgB +// SIG // ZQMEAgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQw +// SIG // ggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB +// SIG // BQAEIF9W/UlnlTLeyoCPkSO+Vze4KnVZVhXQet9xGpGD +// SIG // VDUBAgZgsBDDb7UYEzIwMjEwNjAzMTAyNzI0LjIxMlow +// SIG // BIACAfSggdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046RDA4Mi00QkZELUVFQkExJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wggg5KMIIE +// SIG // +TCCA+GgAwIBAgITMwAAAUGvf1KXXPLcRQAAAAABQTAN +// SIG // BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG +// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +// SIG // MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ +// SIG // Q0EgMjAxMDAeFw0yMDEwMTUxNzI4MjdaFw0yMjAxMTIx +// SIG // NzI4MjdaMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +// SIG // V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +// SIG // A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYD +// SIG // VQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25z +// SIG // IExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO +// SIG // OkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3Nv +// SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG +// SIG // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8irLqL28dal+PJUm +// SIG // UJOwvYn/sOCEzQzZyj94XbFPtRhDhPjagvvKOv1GgMoO +// SIG // uXvkpM3uM5E67vyOCPxqhTAzq7Ak3zkEXXBv7JoM8Xm0 +// SIG // x5UcnAkpUiEo0eycRl6bnYIB3KlZW3uz4Jc2v2FV0KCG +// SIG // kLrvqfKP8V/i2hVyN854OejWpx8wGUazM4CYUVowcgED +// SIG // c76OY+Xa4W27DCZJm2f9ol4BjSL+b2L/T8n/LEGknaUx +// SIG // wSQTN1LQCt+uBDCASd6VQR5CLLJVt6MBL0W1NlaWxEAJ +// SIG // wlIdyBnS1ihLvRg1jc/KUZe0sRFdD3fhKrjPac3hoy00 +// SIG // 7Fvr6Go0WJ4pr2rJdQIDAQABo4IBGzCCARcwHQYDVR0O +// SIG // BBYEFC0oPyxuLpD9RXBr9c8NO0EFEsbEMB8GA1UdIwQY +// SIG // MBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRP +// SIG // ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y +// SIG // MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYI +// SIG // KwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDct +// SIG // MDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI +// SIG // KwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBAFJ63yJ9 +// SIG // 2ChqCgpexD48okviGuC4ikNsvmwlCSet1sFpvJEzLJB8 +// SIG // cTF4z4qQTz8AsQtcew6mAVmQCYDu9f5ee11xXj1LwHYs +// SIG // ZGnSs/OfRul1VKmY51OQpqvK5O/Ct4fs0Iblzo8eyOLJ +// SIG // ygTk97aXVA4Uzq8GblL7LQ5XiwAY446MOALnNXFo/Kq9 +// SIG // tvzipwY1YcRn/nlMQ+b92OiLLmHVMi2wAUORiKFvaAfY +// SIG // WjhQd+2qHLMsdpNluwBbWe7FF5ABsDo0HROMWyCgxdLQ +// SIG // 3vqr3DMSH3ZWKiirFsvWJmchfZPGRObwqszvSXPFmPBZ +// SIG // 9o+er+4UoLV+50GWnnQky7HVgLkwggZxMIIEWaADAgEC +// SIG // AgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQsw +// SIG // CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ +// SIG // MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z +// SIG // b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +// SIG // ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx +// SIG // MDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVa +// SIG // MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN +// SIG // BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR +// SIG // ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vh +// SIG // wna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg +// SIG // iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg +// SIG // MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG +// SIG // GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBX +// SIG // day9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajy +// SIG // eioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHB +// SIG // IAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIw +// SIG // EAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyK +// SIG // MZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoA +// SIG // UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E +// SIG // BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ +// SIG // W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j +// SIG // cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz +// SIG // L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr +// SIG // BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 +// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v +// SIG // Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E +// SIG // gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC +// SIG // ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k +// SIG // b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0 +// SIG // HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMA +// SIG // dABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsF +// SIG // AAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7P +// SIG // BeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcI +// SIG // K1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZL +// SIG // dO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZ +// SIG // qbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8y +// SIG // Sif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoL +// SIG // kSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38 +// SIG // ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ +// SIG // Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ +// SIG // 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdl +// SIG // R3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30 +// SIG // uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp +// SIG // 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR +// SIG // ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXj +// SIG // ad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA1 +// SIG // 2u8JJxzVs341Hgi62jbb01+P3nSISRKhggLUMIICPQIB +// SIG // ATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046RDA4Mi00QkZELUVFQkExJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAH +// SIG // BgUrDgMCGgMVAKrlvym1CquIoQcrzncLvkD1WpUDoIGD +// SIG // MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE +// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw +// SIG // DQYJKoZIhvcNAQEFBQACBQDkYyCxMCIYDzIwMjEwNjAz +// SIG // MTczNDQxWhgPMjAyMTA2MDQxNzM0NDFaMHQwOgYKKwYB +// SIG // BAGEWQoEATEsMCowCgIFAORjILECAQAwBwIBAAICEcww +// SIG // BwIBAAICEgswCgIFAORkcjECAQAwNgYKKwYBBAGEWQoE +// SIG // AjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEK +// SIG // MAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQBtyFzG +// SIG // N2gJJZ3T6Dzxrw0RoLe9MAvzpz7H2wn8BMAuUs68+9Sz +// SIG // 0qPPgY06wPmE9dqyNzKBjwQrPnJ/qIegjqxgIAazKKN2 +// SIG // hxkAF/kZg0zTK4jDKKUAzIlSwaXbpD19RKHHRdyXGu/0 +// SIG // xlUHCFogRUpH8CZQsXulgvS7H0jiYUkTLTGCAw0wggMJ +// SIG // AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX +// SIG // YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD +// SIG // VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV +// SIG // BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw +// SIG // AhMzAAABQa9/Updc8txFAAAAAAFBMA0GCWCGSAFlAwQC +// SIG // AQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ +// SIG // AQQwLwYJKoZIhvcNAQkEMSIEIDpRwFQTDOc8xcJlaU+j +// SIG // NiTtrqf2gu9E6sxjCfitRM3RMIH6BgsqhkiG9w0BCRAC +// SIG // LzGB6jCB5zCB5DCBvQQgUT8BPIzqc3SecHRPLKBtW0vO +// SIG // OnT+78haWo+XcxVerd4wgZgwgYCkfjB8MQswCQYDVQQG +// SIG // EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +// SIG // BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv +// SIG // cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt +// SIG // ZS1TdGFtcCBQQ0EgMjAxMAITMwAAAUGvf1KXXPLcRQAA +// SIG // AAABQTAiBCDEmllKq6p2dSDRT7WXEfJzMnBQlv3YcYTQ +// SIG // /uWbkawwhzANBgkqhkiG9w0BAQsFAASCAQAhfBpb75wo +// SIG // So2gcoQJiDZ9lV0kGglSZX1BDF8J62A6IVx2Pmn7D4IY +// SIG // IKXiWQe19jI1zYw8TuiFUPzFNQbkdJHvt3P8A4FoowN3 +// SIG // tMwdX6Vh5pisICKU05HguvtJ8sc6iVBPTk7LFHG/+n3p +// SIG // Wf/9ou6BZkxdYddKcn9Aw1udIEc+mXLrji6BrJmE8Fr4 +// SIG // rXOutJkFBTBOyDfxeBqqb3EzcH620EQL9CEShF4Ozs14 +// SIG // QAdOnIGLdDYe0QCqZh13uT1o4d6vp374oi78tV8ledom +// SIG // 9JJe0S6eeUr8/Pvl4p5qkPNIlZKDVKdj9DNUHIGj/Gac +// SIG // OJi52Nnfjra0FMb1/kMTkRZa +// SIG // End signature block diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.timezones.blat b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.timezones.blat new file mode 100644 index 000000000..2b8309168 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.timezones.blat differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.wasm b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.wasm new file mode 100644 index 000000000..8c6ce0285 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet.wasm differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet_support.js b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet_support.js new file mode 100644 index 000000000..d4b54ff86 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/dotnet_support.js @@ -0,0 +1,382 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var DotNetSupportLib = { + $DOTNET: { + conv_string: function (mono_obj) { + return MONO.string_decoder.copy (mono_obj); + } + }, + mono_wasm_invoke_js_blazor: function(exceptionMessage, callInfo, arg0, arg1, arg2) { + var mono_string = globalThis._mono_string_cached + || (globalThis._mono_string_cached = Module.cwrap('mono_wasm_string_from_js', 'number', ['string'])); + + try { + var blazorExports = globalThis.Blazor; + if (!blazorExports) { + throw new Error('The blazor.webassembly.js library is not loaded.'); + } + + return blazorExports._internal.invokeJSFromDotNet(callInfo, arg0, arg1, arg2); + } catch (ex) { + var exceptionJsString = ex.message + '\n' + ex.stack; + var exceptionSystemString = mono_string(exceptionJsString); + setValue (exceptionMessage, exceptionSystemString, 'i32'); // *exceptionMessage = exceptionSystemString; + return 0; + } + }, + + // This is for back-compat only and will eventually be removed + mono_wasm_invoke_js_marshalled: function(exceptionMessage, asyncHandleLongPtr, functionName, argsJson, treatResultAsVoid) { + + var mono_string = globalThis._mono_string_cached + || (globalThis._mono_string_cached = Module.cwrap('mono_wasm_string_from_js', 'number', ['string'])); + + try { + // Passing a .NET long into JS via Emscripten is tricky. The method here is to pass + // as pointer to the long, then combine two reads from the HEAPU32 array. + // Even though JS numbers can't represent the full range of a .NET long, it's OK + // because we'll never exceed Number.MAX_SAFE_INTEGER (2^53 - 1) in this case. + //var u32Index = $1 >> 2; + var u32Index = asyncHandleLongPtr >> 2; + var asyncHandleJsNumber = Module.HEAPU32[u32Index + 1]*4294967296 + Module.HEAPU32[u32Index]; + + // var funcNameJsString = UTF8ToString (functionName); + // var argsJsonJsString = argsJson && UTF8ToString (argsJson); + var funcNameJsString = DOTNET.conv_string(functionName); + var argsJsonJsString = argsJson && DOTNET.conv_string (argsJson); + + var dotNetExports = globaThis.DotNet; + if (!dotNetExports) { + throw new Error('The Microsoft.JSInterop.js library is not loaded.'); + } + + if (asyncHandleJsNumber) { + dotNetExports.jsCallDispatcher.beginInvokeJSFromDotNet(asyncHandleJsNumber, funcNameJsString, argsJsonJsString, treatResultAsVoid); + return 0; + } else { + var resultJson = dotNetExports.jsCallDispatcher.invokeJSFromDotNet(funcNameJsString, argsJsonJsString, treatResultAsVoid); + return resultJson === null ? 0 : mono_string(resultJson); + } + } catch (ex) { + var exceptionJsString = ex.message + '\n' + ex.stack; + var exceptionSystemString = mono_string(exceptionJsString); + setValue (exceptionMessage, exceptionSystemString, 'i32'); // *exceptionMessage = exceptionSystemString; + return 0; + } + }, + + // This is for back-compat only and will eventually be removed + mono_wasm_invoke_js_unmarshalled: function(exceptionMessage, funcName, arg0, arg1, arg2) { + try { + // Get the function you're trying to invoke + var funcNameJsString = DOTNET.conv_string(funcName); + var dotNetExports = globalThis.DotNet; + if (!dotNetExports) { + throw new Error('The Microsoft.JSInterop.js library is not loaded.'); + } + var funcInstance = dotNetExports.jsCallDispatcher.findJSFunction(funcNameJsString); + + return funcInstance.call(null, arg0, arg1, arg2); + } catch (ex) { + var exceptionJsString = ex.message + '\n' + ex.stack; + var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']); // TODO: Cache + var exceptionSystemString = mono_string(exceptionJsString); + setValue (exceptionMessage, exceptionSystemString, 'i32'); // *exceptionMessage = exceptionSystemString; + return 0; + } + } + + +}; + +autoAddDeps(DotNetSupportLib, '$DOTNET') +mergeInto(LibraryManager.library, DotNetSupportLib) + + +// SIG // Begin signature block +// SIG // MIIkiQYJKoZIhvcNAQcCoIIkejCCJHYCAQExDzANBglg +// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor +// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC +// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg +// SIG // DQxM5aUosMIFmI353dLRcro0jWTAvinWkY5FLkoNZqCg +// SIG // gg3wMIIGbjCCBFagAwIBAgITMwAAAhOMDBwxNbzSXwAA +// SIG // AAACEzANBgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJV +// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT +// SIG // aWduaW5nIFBDQSAyMDExMB4XDTIxMDIxMTIwMDk1MVoX +// SIG // DTIyMDIxMDIwMDk1MVowYzELMAkGA1UEBhMCVVMxEzAR +// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v +// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +// SIG // bjENMAsGA1UEAxMELk5FVDCCAaIwDQYJKoZIhvcNAQEB +// SIG // BQADggGPADCCAYoCggGBAJtZcELdrGHlHCF6nz4bH8vW +// SIG // l5M3GfXIf7JY7OovRwgweTptJQGby0YHZ+iCrWIE7fTc +// SIG // /c9eGKGm+EsuWHnanAm9Ro7MSjdPsYBRaif1Y6dyhBcb +// SIG // b44guUNKlplq7L1k3ldXFFzyAt+u8UzCL5QFwibg2nWi +// SIG // QmCkoJWhiA6RxEPgEZ/ss2ICppgLHm1o6vy1P4ci6aMk +// SIG // Tj2s1uct/oFflYwE0DsK1OrFH7QvoIqWCAuXUXjZOKnF +// SIG // oRia22+ci2oxs/LVkgqcMwC35KHvUBzCW3LME/dSBWCO +// SIG // TV7gieG+gUtxBgPpzomak4thtrQLMRAWl7AOtI7QvsXa +// SIG // FEyQpAlDVz12Sa89KJOLBPksBRDw4woRZLlHnUrtxFRp +// SIG // MZsr+9cf2zfZPG4ia2iDSBFfXu2BeXrifkT4c/UV5Iy3 +// SIG // qEHCzh1jLmN701jUOhF1QN1LEPn+TCth2b239/34+Bym +// SIG // cIAcDP1EWk8JodsUDedKhK+lAefNL0mzUrIQc6Dxb5cq +// SIG // may/QQIDAQABo4IBfjCCAXowHwYDVR0lBBgwFgYKKwYB +// SIG // BAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFO9NaSC3 +// SIG // 3IwsQ0OKpWHnclste605MFAGA1UdEQRJMEekRTBDMSkw +// SIG // JwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy +// SIG // dG8gUmljbzEWMBQGA1UEBRMNNDY0MjIzKzQ2NDI5MzAf +// SIG // BgNVHSMEGDAWgBRIbmTlUAXTgqoXNzcitW2oynUClTBU +// SIG // BgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jv +// SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUw +// SIG // UzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3Nv +// SIG // ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAw +// SIG // DQYJKoZIhvcNAQEMBQADggIBAFiD+cR0K6evMUeUrBMA +// SIG // pLljV65GDDTzlD4jqr6Mu1NTeZv5L9IJlR6DLAEKaJnB +// SIG // a7fZZ/ME/FZasmc40+WijhDmth/OOc7IpfJ3Ra1auKIA +// SIG // g687mo/eWiPs0nC42oCdchy9Q5AS7K0+MUk7R/p9eCTP +// SIG // NYFjSMItiL+YFYCxaZXqHizwdXcvCIrESq4DXwN+ZdUe +// SIG // GBEO9F2SkMVC61/y2xwSwRWmfO/l4YutKT+dSKjlelYi +// SIG // zFAQaJrGzO5ac56S+K/NMndPL7Od3ohqxMu7gsFUynxY +// SIG // l+eyB9T9I9HrUWoHj6ce4nzOxHC+yDRD6Mi2AaT+IbMO +// SIG // cGvWeJC5iX3tzpMqdz0BOMl6jbff+t+BLS7VtU6JAFCM +// SIG // fk5h+wqIPWjon3tpTuFtCkMOSzIoso3U6kdX0fgrgXnN +// SIG // KJspBXkfKG9lMPOPOKwzua1qjghvgzPMftj1yZqFljJm +// SIG // cjBxs/HKA8J8st1MKcgiBGDX5zkcsHYGuAkIb2fXQuYW +// SIG // y0G78JzzSv1u0LAFj8/Qtx9Hm2wfc20+ww+MYEQ9tu1F +// SIG // uJZK2O7+p7iVziwZvo+XVzuIU7sVjcmJH5Gn/ttfkLQ3 +// SIG // 0jvM9QyV/lYwurg4Gn5Li/IZSN56WGIPilRkXUVurpaV +// SIG // WeYCjeUJzMY2n2tVMFl6pgnGmaA2a0uiG3z0GpMPdbS1 +// SIG // R/oEMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +// SIG // hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV +// SIG // BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +// SIG // HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +// SIG // MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +// SIG // dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5 +// SIG // WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJVUzET +// SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +// SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +// SIG // aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWdu +// SIG // aW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOC +// SIG // Ag8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGf +// SIG // Qhsqa+laUKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDI +// SIG // OdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv +// SIG // 2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13Y +// SIG // xC4Ddato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT +// SIG // +OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +// SIG // 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk +// SIG // kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXD +// SIG // OW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf +// SIG // GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +// SIG // JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bys +// SIG // AoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J64HLn +// SIG // JN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeB +// SIG // e+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx +// SIG // 7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu+HggWCwT +// SIG // XWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEA +// SIG // AaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1Ud +// SIG // DgQWBBRIbmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEE +// SIG // AYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw +// SIG // DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToC +// SIG // MZBDuRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBL +// SIG // hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +// SIG // bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf +// SIG // MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEF +// SIG // BQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br +// SIG // aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +// SIG // MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcu +// SIG // AzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy +// SIG // b3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMu +// SIG // aHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABf +// SIG // AHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0AZQBuAHQA +// SIG // LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou +// SIG // 09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+ +// SIG // vj/oCso7v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzS +// SIG // Gksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlE +// SIG // PXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6V +// SIG // oCo/KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu +// SIG // 5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +// SIG // STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp +// SIG // mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38c +// SIG // bxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN +// SIG // pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +// SIG // QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AA +// SIG // KcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74v2u3 +// SIG // S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8 +// SIG // MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7 +// SIG // qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJ +// SIG // UnMTDXpQzTGCFfEwghXtAgEBMIGVMH4xCzAJBgNVBAYT +// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH +// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +// SIG // cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2Rl +// SIG // IFNpZ25pbmcgUENBIDIwMTECEzMAAAITjAwcMTW80l8A +// SIG // AAAAAhMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN +// SIG // AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +// SIG // MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIPei +// SIG // aMpT7aW0G0eaO4V7u+OYsUIWBD2V6EuD1ajffj24MEIG +// SIG // CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv +// SIG // AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w +// SIG // DQYJKoZIhvcNAQEBBQAEggGASEblTgnTmkn+iGPTMgPr +// SIG // +5uptto3kTMfvkelPQ3w/xHmtXcAdH24QMN1aSgRgQkH +// SIG // oHsEzQgzSVBwR5jRH/yeM8rA3JqNHY7Gqo1Mhjz6KSxh +// SIG // 4n1YHmD+QYcpt1jSkqWvV6APQhsYyFv+0SsiAErlDRrv +// SIG // vuIHM5xjmVi5yjW2GGOLDtKN0UOtWS3Fagjdv4L02kXi +// SIG // a4XX9rRjzh8ykJawJrd/OgFKbBZlk/O/5ClWVMQ0ijoQ +// SIG // 5Gb2olho4CZ3M0cqsCigz8GMtQDEKb2y4MYYUrKHlkmo +// SIG // tW+q5Jqhw+ocM7sOIz/EIWfjw/D+Lz44N2oQag0MwW0o +// SIG // 0JBk4TcqIHkiYZ1At70J118HmWllMsh35TDgZTD6Ds7W +// SIG // NEG9Y7e+0GwRiva/wLQq/L6vGDtMfBXBJCwpNuwlniok +// SIG // bY4LFW45OtTkCBleFPyuTyNzz7DkG0+XJhE5fw3H6Tsy +// SIG // VgHbV3fAUM76vS/rVrihi6M+M7HejkC7il15R8lqm2La +// SIG // NUG0IugSoYIS+zCCEvcGCisGAQQBgjcDAwExghLnMIIS +// SIG // 4wYJKoZIhvcNAQcCoIIS1DCCEtACAQMxDzANBglghkgB +// SIG // ZQMEAgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQw +// SIG // ggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB +// SIG // BQAEILs+o5Vp2Uu3D+piTqZS72r4qxA46uSkXA4muDH6 +// SIG // FxXaAgZgsATplaQYEzIwMjEwNjAzMTAyNzI0LjIxN1ow +// SIG // BIACAfSggdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046ODZERi00QkJDLTkzMzUxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wggg5KMIIE +// SIG // +TCCA+GgAwIBAgITMwAAAT7OyndSxfc0KwAAAAABPjAN +// SIG // BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG +// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +// SIG // MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ +// SIG // Q0EgMjAxMDAeFw0yMDEwMTUxNzI4MjVaFw0yMjAxMTIx +// SIG // NzI4MjVaMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +// SIG // V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +// SIG // A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYD +// SIG // VQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25z +// SIG // IExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO +// SIG // Ojg2REYtNEJCQy05MzM1MSUwIwYDVQQDExxNaWNyb3Nv +// SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG +// SIG // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFTEyDzZfpws404g +// SIG // SC0kt4VSyX/vaxwOfri89gQdxvfQNvvQARebKR3plqHz +// SIG // 0ZHZW+bmFxyGtTh9zw20LSdpMcWYDFc1rzPuJvTNAnDk +// SIG // KyQP+TqrW7j/lDlCLbqi8ubo4EqSpkHra0Zt15j2r/IJ +// SIG // GZbu3QaRY6qYMZxxkkw4Y5ubAwV3E1p+TNzFg8nzgJ9k +// SIG // wEM4xvZAf9NhHhM2K/jx092xmKxyFfp0X0tboY9d1Oyh +// SIG // dCXl8spOigE32g8zH12Y2NXTfI4141LQU+9dKOKQ7YFF +// SIG // 1kwofuGGwxMU0CsDimODWgr6VFVcNDd2tQbGubgdfLBG +// SIG // EBfje0PyoOOXEO1m4QIDAQABo4IBGzCCARcwHQYDVR0O +// SIG // BBYEFJNa8534u9BiLWvwtbZUDraGiP17MB8GA1UdIwQY +// SIG // MBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRP +// SIG // ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y +// SIG // MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYI +// SIG // KwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDct +// SIG // MDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI +// SIG // KwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBAKaz+RF9 +// SIG // Wp+GkrkVj6cY5djCdVepJFyufABJ1qKlCWXhOoYAcB7w +// SIG // 7ZxzRC4Z2iY4bc9QU93sa2YDwhQwFPeqfKZfWSkmrcus +// SIG // 49QB9EGPc9FwIgfBQK2AJthaYEysTawS40f6yc6w/ybo +// SIG // tAclqFAr+BPDt0zGZoExvGc8ZpVAZpvSyXbzGLuKtm8K +// SIG // +R73VC4DUp4sRFck1Cx8ILvYdYSNYqORyh0Gwi3v4HWm +// SIG // w6HutafFOdFjaKQEcSsn0SNLfY25qOqnu6DL+NAo7z3q +// SIG // D0eBDISilWob5dllDcONfsu99UEtOnrbdl292yGNIyxi +// SIG // lpI8XGNgGcZxKN6VqLBxAuKlWOYwggZxMIIEWaADAgEC +// SIG // AgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQsw +// SIG // CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ +// SIG // MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z +// SIG // b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +// SIG // ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx +// SIG // MDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVa +// SIG // MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN +// SIG // BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR +// SIG // ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vh +// SIG // wna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg +// SIG // iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg +// SIG // MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG +// SIG // GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBX +// SIG // day9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajy +// SIG // eioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHB +// SIG // IAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIw +// SIG // EAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyK +// SIG // MZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoA +// SIG // UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E +// SIG // BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ +// SIG // W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j +// SIG // cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz +// SIG // L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr +// SIG // BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 +// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v +// SIG // Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E +// SIG // gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC +// SIG // ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k +// SIG // b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0 +// SIG // HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMA +// SIG // dABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsF +// SIG // AAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7P +// SIG // BeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcI +// SIG // K1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZL +// SIG // dO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZ +// SIG // qbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8y +// SIG // Sif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoL +// SIG // kSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38 +// SIG // ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ +// SIG // Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ +// SIG // 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdl +// SIG // R3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30 +// SIG // uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp +// SIG // 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR +// SIG // ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXj +// SIG // ad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA1 +// SIG // 2u8JJxzVs341Hgi62jbb01+P3nSISRKhggLUMIICPQIB +// SIG // ATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046ODZERi00QkJDLTkzMzUxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAH +// SIG // BgUrDgMCGgMVAKBMFej0xjCTjCk1sTdTKa+TzJDUoIGD +// SIG // MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE +// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw +// SIG // DQYJKoZIhvcNAQEFBQACBQDkYxTdMCIYDzIwMjEwNjAz +// SIG // MTY0NDEzWhgPMjAyMTA2MDQxNjQ0MTNaMHQwOgYKKwYB +// SIG // BAGEWQoEATEsMCowCgIFAORjFN0CAQAwBwIBAAICClww +// SIG // BwIBAAICEWswCgIFAORkZl0CAQAwNgYKKwYBBAGEWQoE +// SIG // AjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEK +// SIG // MAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCC1rRg +// SIG // Um9T0Ah6EhW50sEN59pkZRy0IgWsJcHlLQpvuQsViBPR +// SIG // T31t6DW2LGocHjECh7d4qMeTTFZkyQPxXQygdUlJ07FD +// SIG // o4myvnoM60HYf8+Ol1NxBOFmmLbLhAGN7VQDFbpMHBQI +// SIG // 4NMiG1Ac/PEu4PU/wsjlpVv69kzg2mek5DGCAw0wggMJ +// SIG // AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX +// SIG // YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD +// SIG // VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV +// SIG // BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw +// SIG // AhMzAAABPs7Kd1LF9zQrAAAAAAE+MA0GCWCGSAFlAwQC +// SIG // AQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ +// SIG // AQQwLwYJKoZIhvcNAQkEMSIEICub1JDAL/AsiPiNlCbL +// SIG // 6bT/2mCQpgIN5GH9eCiLaYMJMIH6BgsqhkiG9w0BCRAC +// SIG // LzGB6jCB5zCB5DCBvQQgi+vOjaqNTvKOZGut49HXrqtw +// SIG // Uj2ZCnVOurBwfgQxmxMwgZgwgYCkfjB8MQswCQYDVQQG +// SIG // EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +// SIG // BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv +// SIG // cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt +// SIG // ZS1TdGFtcCBQQ0EgMjAxMAITMwAAAT7OyndSxfc0KwAA +// SIG // AAABPjAiBCDDg1tbQNT5a0tUZMwkkm3mp0UsTWCruFb9 +// SIG // MCaPExqjRDANBgkqhkiG9w0BAQsFAASCAQBH2iVHVOlH +// SIG // VmptqEcBLS3eNS8ycIqxph4ALRJ1GnEZDaGCyvSiL/y0 +// SIG // 5Vx7GFvWSaRfZ8Kq0BgfWZEYCpq8uZ9gZYy1paDGU6Ps +// SIG // YAZtQZak32SzipkHZsswC7W9ePKfMT4FV4tZtupRBgE6 +// SIG // 9J0PRnpXNRXwtZgAYyiKU8TVQsfUryRXYAKQily9GzwY +// SIG // UG67G7umMk9LnycPNUlEgIbn58qhJ59lMDdbrWigHJLF +// SIG // VXzfvWNXLIsMQKPZPgA1sCaUhLrBu+T3nFUX0R57ve7m +// SIG // Xl2HoGZLdkA4V0pXYO5J7yCAvbGjEzm5lltyyQnYrqfx +// SIG // 0RV0o3+4XN4MV2Blp63JcnTX +// SIG // End signature block diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/driver.c b/Examples/Complete/Animation/Blazor/wwwroot/_framework/driver.c new file mode 100644 index 000000000..515391815 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/driver.c @@ -0,0 +1,1118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +// FIXME: unavailable in emscripten +// #include + +#include + +#include +#include +#include +#include + +#include "pinvoke.h" + +#ifdef CORE_BINDINGS +void core_initialize_internals (); +#endif + +// Blazor specific custom routines - see dotnet_support.js for backing code +extern void* mono_wasm_invoke_js_blazor (MonoString **exceptionMessage, void *callInfo, void* arg0, void* arg1, void* arg2); +// The following two are for back-compat and will eventually be removed +extern void* mono_wasm_invoke_js_marshalled (MonoString **exceptionMessage, void *asyncHandleLongPtr, MonoString *funcName, MonoString *argsJson); +extern void* mono_wasm_invoke_js_unmarshalled (MonoString **exceptionMessage, MonoString *funcName, void* arg0, void* arg1, void* arg2); + +void mono_wasm_enable_debugging (int); + +int mono_wasm_register_root (char *start, size_t size, const char *name); +void mono_wasm_deregister_root (char *addr); + +void mono_ee_interp_init (const char *opts); +void mono_marshal_ilgen_init (void); +void mono_method_builder_ilgen_init (void); +void mono_sgen_mono_ilgen_init (void); +void mono_icall_table_init (void); +void mono_aot_register_module (void **aot_info); +char *monoeg_g_getenv(const char *variable); +int monoeg_g_setenv(const char *variable, const char *value, int overwrite); +int32_t monoeg_g_hasenv(const char *variable); +void mono_free (void*); +int32_t mini_parse_debug_option (const char *option); +char *mono_method_get_full_name (MonoMethod *method); + +static MonoClass* datetime_class; +static MonoClass* datetimeoffset_class; +static MonoClass* uri_class; +static MonoClass* task_class; +static MonoClass* safehandle_class; +static MonoClass* voidtaskresult_class; + +static int resolved_datetime_class = 0, + resolved_datetimeoffset_class = 0, + resolved_uri_class = 0, + resolved_task_class = 0, + resolved_safehandle_class = 0, + resolved_voidtaskresult_class = 0; + +int mono_wasm_enable_gc = 1; + +/* Not part of public headers */ +#define MONO_ICALL_TABLE_CALLBACKS_VERSION 2 + +typedef struct { + int version; + void* (*lookup) (MonoMethod *method, char *classname, char *methodname, char *sigstart, int32_t *uses_handles); + const char* (*lookup_icall_symbol) (void* func); +} MonoIcallTableCallbacks; + +void +mono_install_icall_table_callbacks (const MonoIcallTableCallbacks *cb); + +int mono_regression_test_step (int verbose_level, char *image, char *method_name); +void mono_trace_init (void); + +#define g_new(type, size) ((type *) malloc (sizeof (type) * (size))) +#define g_new0(type, size) ((type *) calloc (sizeof (type), (size))) + +static MonoDomain *root_domain; + +static MonoString* +mono_wasm_invoke_js (MonoString *str, int *is_exception) +{ + if (str == NULL) + return NULL; + + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + int native_res_len; + int *p_native_res_len = &native_res_len; + + mono_unichar2 *native_res = (mono_unichar2*)EM_ASM_INT ({ + var str = MONO.string_decoder.decode ($0, $0 + $1); + try { + var res = eval (str); + if (res === null || res == undefined) + return 0; + res = res.toString (); + setValue ($2, 0, "i32"); + } catch (e) { + res = e.toString(); + setValue ($2, 1, "i32"); + if (res === null || res === undefined) + res = "unknown exception"; + + var stack = e.stack; + if (stack) { + // Some JS runtimes insert the error message at the top of the stack, some don't, + // so normalize it by using the stack as the result if it already contains the error + if (stack.startsWith(res)) + res = stack; + else + res += "\n" + stack; + } + } + var buff = Module._malloc((res.length + 1) * 2); + stringToUTF16 (res, buff, (res.length + 1) * 2); + setValue ($3, res.length, "i32"); + return buff; + }, (int)native_val, native_len, is_exception, p_native_res_len); + + if (native_res == NULL) + return NULL; + + MonoString *res = mono_string_new_utf16 (mono_domain_get (), native_res, native_res_len); + free (native_res); + return res; +} + +static void +wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) +{ + EM_ASM({ + var log_level = $0; + var message = Module.UTF8ToString ($1); + var isFatal = $2; + var domain = Module.UTF8ToString ($3); // is this always Mono? + var dataPtr = $4; + + if (MONO["logging"] && MONO.logging["trace"]) { + MONO.logging.trace(domain, log_level, message, isFatal, dataPtr); + return; + } + + if (isFatal) + console.trace (message); + + switch (Module.UTF8ToString ($0)) { + case "critical": + case "error": + console.error (message); + break; + case "warning": + console.warn (message); + break; + case "message": + console.log (message); + break; + case "info": + console.info (message); + break; + case "debug": + console.debug (message); + break; + default: + console.log (message); + break; + } + }, log_level, message, fatal, log_domain, user_data); +} + +typedef uint32_t target_mword; +typedef target_mword SgenDescriptor; +typedef SgenDescriptor MonoGCDescriptor; +MONO_API int mono_gc_register_root (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg); +void mono_gc_deregister_root (char* addr); + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_register_root (char *start, size_t size, const char *name) +{ + return mono_gc_register_root (start, size, (MonoGCDescriptor)NULL, MONO_ROOT_SOURCE_EXTERNAL, NULL, name ? name : "mono_wasm_register_root"); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_deregister_root (char *addr) +{ + mono_gc_deregister_root (addr); +} + +#ifdef DRIVER_GEN +#include "driver-gen.c" +#endif + +typedef struct WasmAssembly_ WasmAssembly; + +struct WasmAssembly_ { + MonoBundledAssembly assembly; + WasmAssembly *next; +}; + +static WasmAssembly *assemblies; +static int assembly_count; + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_add_assembly (const char *name, const unsigned char *data, unsigned int size) +{ + int len = strlen (name); + if (!strcasecmp (".pdb", &name [len - 4])) { + char *new_name = strdup (name); + //FIXME handle debugging assemblies with .exe extension + strcpy (&new_name [len - 3], "dll"); + mono_register_symfile_for_assembly (new_name, data, size); + return 1; + } + WasmAssembly *entry = g_new0 (WasmAssembly, 1); + entry->assembly.name = strdup (name); + entry->assembly.data = data; + entry->assembly.size = size; + entry->next = assemblies; + assemblies = entry; + ++assembly_count; + return mono_has_pdb_checksum ((char*)data, size); +} + +int +mono_wasm_assembly_already_added (const char *assembly_name) +{ + if (assembly_count == 0) + return 0; + + WasmAssembly *entry = assemblies; + while (entry != NULL) { + int entry_name_minus_extn_len = strlen(entry->assembly.name) - 4; + if (entry_name_minus_extn_len == strlen(assembly_name) && strncmp (entry->assembly.name, assembly_name, entry_name_minus_extn_len) == 0) + return 1; + entry = entry->next; + } + + return 0; +} + +typedef struct WasmSatelliteAssembly_ WasmSatelliteAssembly; + +struct WasmSatelliteAssembly_ { + MonoBundledSatelliteAssembly *assembly; + WasmSatelliteAssembly *next; +}; + +static WasmSatelliteAssembly *satellite_assemblies; +static int satellite_assembly_count; + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_add_satellite_assembly (const char *name, const char *culture, const unsigned char *data, unsigned int size) +{ + WasmSatelliteAssembly *entry = g_new0 (WasmSatelliteAssembly, 1); + entry->assembly = mono_create_new_bundled_satellite_assembly (name, culture, data, size); + entry->next = satellite_assemblies; + satellite_assemblies = entry; + ++satellite_assembly_count; +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_setenv (const char *name, const char *value) +{ + monoeg_g_setenv (strdup (name), strdup (value), 1); +} + +static void *sysglobal_native_handle; + +static void* +wasm_dl_load (const char *name, int flags, char **err, void *user_data) +{ + void* handle = wasm_dl_lookup_pinvoke_table (name); + if (handle) + return handle; + + if (!strcmp (name, "System.Globalization.Native")) + return sysglobal_native_handle; + +#if WASM_SUPPORTS_DLOPEN + return dlopen(name, flags); +#endif + + return NULL; +} + +static void* +wasm_dl_symbol (void *handle, const char *name, char **err, void *user_data) +{ + if (handle == sysglobal_native_handle) + assert (0); + +#if WASM_SUPPORTS_DLOPEN + if (!wasm_dl_is_pinvoke_tables (handle)) { + return dlsym (handle, name); + } +#endif + + PinvokeImport *table = (PinvokeImport*)handle; + for (int i = 0; table [i].name; ++i) { + if (!strcmp (table [i].name, name)) + return table [i].func; + } + return NULL; +} + +#if !defined(ENABLE_AOT) || defined(EE_MODE_LLVMONLY_INTERP) +#define NEED_INTERP 1 +#ifndef LINK_ICALLS +// FIXME: llvm+interp mode needs this to call icalls +#define NEED_NORMAL_ICALL_TABLES 1 +#endif +#endif + +#ifdef LINK_ICALLS + +#include "icall-table.h" + +static int +compare_int (const void *k1, const void *k2) +{ + return *(int*)k1 - *(int*)k2; +} + +static void* +icall_table_lookup (MonoMethod *method, char *classname, char *methodname, char *sigstart, int32_t *uses_handles) +{ + uint32_t token = mono_method_get_token (method); + assert (token); + assert ((token & MONO_TOKEN_METHOD_DEF) == MONO_TOKEN_METHOD_DEF); + uint32_t token_idx = token - MONO_TOKEN_METHOD_DEF; + + int *indexes = NULL; + int indexes_size = 0; + uint8_t *handles = NULL; + void **funcs = NULL; + + *uses_handles = 0; + + const char *image_name = mono_image_get_name (mono_class_get_image (mono_method_get_class (method))); + +#if defined(ICALL_TABLE_mscorlib) + if (!strcmp (image_name, "mscorlib")) { + indexes = mscorlib_icall_indexes; + indexes_size = sizeof (mscorlib_icall_indexes) / 4; + handles = mscorlib_icall_handles; + funcs = mscorlib_icall_funcs; + assert (sizeof (mscorlib_icall_indexes [0]) == 4); + } +#endif +#if defined(ICALL_TABLE_corlib) + if (!strcmp (image_name, "System.Private.CoreLib")) { + indexes = corlib_icall_indexes; + indexes_size = sizeof (corlib_icall_indexes) / 4; + handles = corlib_icall_handles; + funcs = corlib_icall_funcs; + assert (sizeof (corlib_icall_indexes [0]) == 4); + } +#endif +#ifdef ICALL_TABLE_System + if (!strcmp (image_name, "System")) { + indexes = System_icall_indexes; + indexes_size = sizeof (System_icall_indexes) / 4; + handles = System_icall_handles; + funcs = System_icall_funcs; + } +#endif + assert (indexes); + + void *p = bsearch (&token_idx, indexes, indexes_size, 4, compare_int); + if (!p) { + return NULL; + printf ("wasm: Unable to lookup icall: %s\n", mono_method_get_name (method)); + exit (1); + } + + uint32_t idx = (int*)p - indexes; + *uses_handles = handles [idx]; + + //printf ("ICALL: %s %x %d %d\n", methodname, token, idx, (int)(funcs [idx])); + + return funcs [idx]; +} + +static const char* +icall_table_lookup_symbol (void *func) +{ + assert (0); + return NULL; +} + +#endif + +/* + * get_native_to_interp: + * + * Return a pointer to a wasm function which can be used to enter the interpreter to + * execute METHOD from native code. + * EXTRA_ARG is the argument passed to the interp entry functions in the runtime. + */ +void* +get_native_to_interp (MonoMethod *method, void *extra_arg) +{ + MonoClass *klass = mono_method_get_class (method); + MonoImage *image = mono_class_get_image (klass); + MonoAssembly *assembly = mono_image_get_assembly (image); + MonoAssemblyName *aname = mono_assembly_get_name (assembly); + const char *name = mono_assembly_name_get_name (aname); + const char *class_name = mono_class_get_name (klass); + const char *method_name = mono_method_get_name (method); + char key [128]; + int len; + + assert (strlen (name) < 100); + snprintf (key, sizeof(key), "%s_%s_%s", name, class_name, method_name); + len = strlen (key); + for (int i = 0; i < len; ++i) { + if (key [i] == '.') + key [i] = '_'; + } + + void *addr = wasm_dl_get_native_to_interp (key, extra_arg); + return addr; +} + +void mono_initialize_internals () +{ + mono_add_internal_call ("Interop/Runtime::InvokeJS", mono_wasm_invoke_js); + // TODO: what happens when two types in different assemblies have the same FQN? + + // Blazor specific custom routines - see dotnet_support.js for backing code + mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJS", mono_wasm_invoke_js_blazor); + // The following two are for back-compat and will eventually be removed + mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSMarshalled", mono_wasm_invoke_js_marshalled); + mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSUnmarshalled", mono_wasm_invoke_js_unmarshalled); + +#ifdef CORE_BINDINGS + core_initialize_internals(); +#endif + +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_register_bundled_satellite_assemblies () +{ + /* In legacy satellite_assembly_count is always false */ + if (satellite_assembly_count) { + MonoBundledSatelliteAssembly **satellite_bundle_array = g_new0 (MonoBundledSatelliteAssembly *, satellite_assembly_count + 1); + WasmSatelliteAssembly *cur = satellite_assemblies; + int i = 0; + while (cur) { + satellite_bundle_array [i] = cur->assembly; + cur = cur->next; + ++i; + } + mono_register_bundled_satellite_assemblies ((const MonoBundledSatelliteAssembly **)satellite_bundle_array); + } +} + +void mono_wasm_link_icu_shim (void); + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_load_runtime (const char *unused, int debug_level) +{ + const char *interp_opts = ""; + +#ifndef INVARIANT_GLOBALIZATION + mono_wasm_link_icu_shim (); +#endif + +#ifdef DEBUG + monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 0); + monoeg_g_setenv ("MONO_LOG_MASK", "gc", 0); + // Setting this env var allows Diagnostic.Debug to write to stderr. In a browser environment this + // output will be sent to the console. Right now this is the only way to emit debug logging from + // corlib assemblies. + monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0); +#endif + + const char *appctx_keys[2]; + appctx_keys [0] = "APP_CONTEXT_BASE_DIRECTORY"; + appctx_keys [1] = "RUNTIME_IDENTIFIER"; + + const char *appctx_values[2]; + appctx_values [0] = "/"; + appctx_values [1] = "browser-wasm"; + + monovm_initialize (2, appctx_keys, appctx_values); + + mini_parse_debug_option ("top-runtime-invoke-unhandled"); + + mono_dl_fallback_register (wasm_dl_load, wasm_dl_symbol, NULL, NULL); + mono_wasm_install_get_native_to_interp_tramp (get_native_to_interp); + +#ifdef ENABLE_AOT + monoeg_g_setenv ("MONO_AOT_MODE", "aot", 1); + + // Defined in driver-gen.c + register_aot_modules (); +#ifdef EE_MODE_LLVMONLY_INTERP + mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY_INTERP); +#else + mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY); +#endif +#else + mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_ONLY); + + /* + * debug_level > 0 enables debugging and sets the debug log level to debug_level + * debug_level == 0 disables debugging and enables interpreter optimizations + * debug_level < 0 enabled debugging and disables debug logging. + * + * Note: when debugging is enabled interpreter optimizations are disabled. + */ + if (debug_level) { + // Disable optimizations which interfere with debugging + interp_opts = "-all"; + mono_wasm_enable_debugging (debug_level); + } + +#endif + +#ifdef LINK_ICALLS + /* Link in our own linked icall table */ + static const MonoIcallTableCallbacks mono_icall_table_callbacks = + { + MONO_ICALL_TABLE_CALLBACKS_VERSION, + icall_table_lookup, + icall_table_lookup_symbol + }; + mono_install_icall_table_callbacks (&mono_icall_table_callbacks); +#endif + +#ifdef NEED_NORMAL_ICALL_TABLES + mono_icall_table_init (); +#endif +#ifdef NEED_INTERP + mono_ee_interp_init (interp_opts); + mono_marshal_ilgen_init (); + mono_method_builder_ilgen_init (); + mono_sgen_mono_ilgen_init (); +#endif + + if (assembly_count) { + MonoBundledAssembly **bundle_array = g_new0 (MonoBundledAssembly*, assembly_count + 1); + WasmAssembly *cur = assemblies; + int i = 0; + while (cur) { + bundle_array [i] = &cur->assembly; + cur = cur->next; + ++i; + } + mono_register_bundled_assemblies ((const MonoBundledAssembly **)bundle_array); + } + + mono_wasm_register_bundled_satellite_assemblies (); + mono_trace_init (); + mono_trace_set_log_handler (wasm_trace_logger, NULL); + root_domain = mono_jit_init_version ("mono", "v4.0.30319"); + + mono_initialize_internals(); + + mono_thread_set_main (mono_thread_current ()); +} + +EMSCRIPTEN_KEEPALIVE MonoAssembly* +mono_wasm_assembly_load (const char *name) +{ + MonoImageOpenStatus status; + MonoAssemblyName* aname = mono_assembly_name_new (name); + if (!name) + return NULL; + + MonoAssembly *res = mono_assembly_load (aname, NULL, &status); + mono_assembly_name_free (aname); + + return res; +} + +EMSCRIPTEN_KEEPALIVE MonoClass* +mono_wasm_find_corlib_class (const char *namespace, const char *name) +{ + return mono_class_from_name (mono_get_corlib (), namespace, name); +} + +EMSCRIPTEN_KEEPALIVE MonoClass* +mono_wasm_assembly_find_class (MonoAssembly *assembly, const char *namespace, const char *name) +{ + return mono_class_from_name (mono_assembly_get_image (assembly), namespace, name); +} + +EMSCRIPTEN_KEEPALIVE MonoMethod* +mono_wasm_assembly_find_method (MonoClass *klass, const char *name, int arguments) +{ + return mono_class_get_method_from_name (klass, name, arguments); +} + +EMSCRIPTEN_KEEPALIVE MonoMethod* +mono_wasm_get_delegate_invoke (MonoObject *delegate) +{ + return mono_get_delegate_invoke(mono_object_get_class (delegate)); +} + +EMSCRIPTEN_KEEPALIVE MonoObject* +mono_wasm_box_primitive (MonoClass *klass, void *value, int value_size) +{ + if (!klass) + return NULL; + + MonoType *type = mono_class_get_type (klass); + int alignment; + if (mono_type_size (type, &alignment) > value_size) + return NULL; + + // TODO: use mono_value_box_checked and propagate error out + return mono_value_box (root_domain, klass, value); +} + +EMSCRIPTEN_KEEPALIVE MonoObject* +mono_wasm_invoke_method (MonoMethod *method, MonoObject *this_arg, void *params[], MonoObject **out_exc) +{ + MonoObject *exc = NULL; + MonoObject *res; + + if (out_exc) + *out_exc = NULL; + res = mono_runtime_invoke (method, this_arg, params, &exc); + if (exc) { + if (out_exc) + *out_exc = exc; + + MonoObject *exc2 = NULL; + res = (MonoObject*)mono_object_to_string (exc, &exc2); + if (exc2) + res = (MonoObject*) mono_string_new (root_domain, "Exception Double Fault"); + return res; + } + + MonoMethodSignature *sig = mono_method_signature (method); + MonoType *type = mono_signature_get_return_type (sig); + // If the method return type is void return null + // This gets around a memory access crash when the result return a value when + // a void method is invoked. + if (mono_type_get_type (type) == MONO_TYPE_VOID) + return NULL; + + return res; +} + +EMSCRIPTEN_KEEPALIVE MonoMethod* +mono_wasm_assembly_get_entry_point (MonoAssembly *assembly) +{ + MonoImage *image; + MonoMethod *method; + + image = mono_assembly_get_image (assembly); + uint32_t entry = mono_image_get_entry_point (image); + if (!entry) + return NULL; + + mono_domain_ensure_entry_assembly (root_domain, assembly); + method = mono_get_method (image, entry, NULL); + + /* + * If the entry point looks like a compiler generated wrapper around + * an async method in the form "" then try to look up the async methods + * "$" and "Name" it could be wrapping. We do this because the generated + * sync wrapper will call task.GetAwaiter().GetResult() when we actually want + * to yield to the host runtime. + */ + if (mono_method_get_flags (method, NULL) & 0x0800 /* METHOD_ATTRIBUTE_SPECIAL_NAME */) { + const char *name = mono_method_get_name (method); + int name_length = strlen (name); + + if ((*name != '<') || (name [name_length - 1] != '>')) + return method; + + MonoClass *klass = mono_method_get_class (method); + char *async_name = malloc (name_length + 2); + snprintf (async_name, name_length + 2, "%s$", name); + + // look for "$" + MonoMethodSignature *sig = mono_method_get_signature (method, image, mono_method_get_token (method)); + MonoMethod *async_method = mono_class_get_method_from_name (klass, async_name, mono_signature_get_param_count (sig)); + if (async_method != NULL) { + free (async_name); + return async_method; + } + + // look for "Name" by trimming the first and last character of "" + async_name [name_length - 1] = '\0'; + async_method = mono_class_get_method_from_name (klass, async_name + 1, mono_signature_get_param_count (sig)); + + free (async_name); + if (async_method != NULL) + return async_method; + } + return method; +} + +EMSCRIPTEN_KEEPALIVE char * +mono_wasm_string_get_utf8 (MonoString *str) +{ + return mono_string_to_utf8 (str); //XXX JS is responsible for freeing this +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_string_convert (MonoString *str) +{ + if (str == NULL) + return; + + mono_unichar2 *native_val = mono_string_chars (str); + int native_len = mono_string_length (str) * 2; + + EM_ASM ({ + MONO.string_decoder.decode($0, $0 + $1, true); + }, (int)native_val, native_len); +} + +EMSCRIPTEN_KEEPALIVE MonoString * +mono_wasm_string_from_js (const char *str) +{ + if (str) + return mono_string_new (root_domain, str); + else + return NULL; +} + +EMSCRIPTEN_KEEPALIVE MonoString * +mono_wasm_string_from_utf16 (const mono_unichar2 * chars, int length) +{ + assert (length >= 0); + + if (chars) + return mono_string_new_utf16 (root_domain, chars, length); + else + return NULL; +} + +static int +class_is_task (MonoClass *klass) +{ + if (!task_class && !resolved_task_class) { + task_class = mono_class_from_name (mono_get_corlib(), "System.Threading.Tasks", "Task"); + resolved_task_class = 1; + } + + if (task_class && (klass == task_class || mono_class_is_subclass_of(klass, task_class, 0))) + return 1; + + return 0; +} + +MonoClass* mono_get_uri_class(MonoException** exc) +{ + MonoAssembly* assembly = mono_wasm_assembly_load ("System"); + if (!assembly) + return NULL; + MonoClass* klass = mono_wasm_assembly_find_class(assembly, "System", "Uri"); + return klass; +} + +#define MARSHAL_TYPE_INT 1 +#define MARSHAL_TYPE_FP64 2 +#define MARSHAL_TYPE_STRING 3 +#define MARSHAL_TYPE_VT 4 +#define MARSHAL_TYPE_DELEGATE 5 +#define MARSHAL_TYPE_TASK 6 +#define MARSHAL_TYPE_OBJECT 7 +#define MARSHAL_TYPE_BOOL 8 +#define MARSHAL_TYPE_ENUM 9 +#define MARSHAL_TYPE_DATE 20 +#define MARSHAL_TYPE_DATEOFFSET 21 +#define MARSHAL_TYPE_URI 22 +#define MARSHAL_TYPE_SAFEHANDLE 23 + +// typed array marshalling +#define MARSHAL_ARRAY_BYTE 10 +#define MARSHAL_ARRAY_UBYTE 11 +#define MARSHAL_ARRAY_UBYTE_C 12 +#define MARSHAL_ARRAY_SHORT 13 +#define MARSHAL_ARRAY_USHORT 14 +#define MARSHAL_ARRAY_INT 15 +#define MARSHAL_ARRAY_UINT 16 +#define MARSHAL_ARRAY_FLOAT 17 +#define MARSHAL_ARRAY_DOUBLE 18 + +#define MARSHAL_TYPE_FP32 24 +#define MARSHAL_TYPE_UINT32 25 +#define MARSHAL_TYPE_INT64 26 +#define MARSHAL_TYPE_UINT64 27 +#define MARSHAL_TYPE_CHAR 28 +#define MARSHAL_TYPE_STRING_INTERNED 29 +#define MARSHAL_TYPE_VOID 30 + +void mono_wasm_ensure_classes_resolved () +{ + if (!datetime_class && !resolved_datetime_class) { + datetime_class = mono_class_from_name (mono_get_corlib(), "System", "DateTime"); + resolved_datetime_class = 1; + } + if (!datetimeoffset_class && !resolved_datetimeoffset_class) { + datetimeoffset_class = mono_class_from_name (mono_get_corlib(), "System", "DateTimeOffset"); + resolved_datetimeoffset_class = 1; + } + if (!uri_class && !resolved_uri_class) { + MonoException** exc = NULL; + uri_class = mono_get_uri_class(exc); + resolved_uri_class = 1; + } + if (!safehandle_class && !resolved_safehandle_class) { + safehandle_class = mono_class_from_name (mono_get_corlib(), "System.Runtime.InteropServices", "SafeHandle"); + resolved_safehandle_class = 1; + } + if (!voidtaskresult_class && !resolved_voidtaskresult_class) { + voidtaskresult_class = mono_class_from_name (mono_get_corlib(), "System.Threading.Tasks", "VoidTaskResult"); + resolved_voidtaskresult_class = 1; + } +} + +int +mono_wasm_marshal_type_from_mono_type (int mono_type, MonoClass *klass, MonoType *type) +{ + switch (mono_type) { + // case MONO_TYPE_CHAR: prob should be done not as a number? + case MONO_TYPE_BOOLEAN: + return MARSHAL_TYPE_BOOL; + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_I: // IntPtr + return MARSHAL_TYPE_INT; + case MONO_TYPE_CHAR: + return MARSHAL_TYPE_CHAR; + case MONO_TYPE_U4: // The distinction between this and signed int is + // important due to how numbers work in JavaScript + return MARSHAL_TYPE_UINT32; + case MONO_TYPE_I8: + return MARSHAL_TYPE_INT64; + case MONO_TYPE_U8: + return MARSHAL_TYPE_UINT64; + case MONO_TYPE_R4: + return MARSHAL_TYPE_FP32; + case MONO_TYPE_R8: + return MARSHAL_TYPE_FP64; + case MONO_TYPE_STRING: + return MARSHAL_TYPE_STRING; + case MONO_TYPE_SZARRAY: { // simple zero based one-dim-array + MonoClass *eklass = mono_class_get_element_class (klass); + MonoType *etype = mono_class_get_type (eklass); + + switch (mono_type_get_type (etype)) { + case MONO_TYPE_U1: + return MARSHAL_ARRAY_UBYTE; + case MONO_TYPE_I1: + return MARSHAL_ARRAY_BYTE; + case MONO_TYPE_U2: + return MARSHAL_ARRAY_USHORT; + case MONO_TYPE_I2: + return MARSHAL_ARRAY_SHORT; + case MONO_TYPE_U4: + return MARSHAL_ARRAY_UINT; + case MONO_TYPE_I4: + return MARSHAL_ARRAY_INT; + case MONO_TYPE_R4: + return MARSHAL_ARRAY_FLOAT; + case MONO_TYPE_R8: + return MARSHAL_ARRAY_DOUBLE; + default: + return MARSHAL_TYPE_OBJECT; + } + } + default: + mono_wasm_ensure_classes_resolved (); + + if (klass == datetime_class) + return MARSHAL_TYPE_DATE; + if (klass == datetimeoffset_class) + return MARSHAL_TYPE_DATEOFFSET; + if (uri_class && mono_class_is_assignable_from(uri_class, klass)) + return MARSHAL_TYPE_URI; + if (klass == voidtaskresult_class) + return MARSHAL_TYPE_VOID; + if (mono_class_is_enum (klass)) + return MARSHAL_TYPE_ENUM; + if (!mono_type_is_reference (type)) //vt + return MARSHAL_TYPE_VT; + if (mono_class_is_delegate (klass)) + return MARSHAL_TYPE_DELEGATE; + if (class_is_task(klass)) + return MARSHAL_TYPE_TASK; + if (safehandle_class && (klass == safehandle_class || mono_class_is_subclass_of(klass, safehandle_class, 0))) { + return MARSHAL_TYPE_SAFEHANDLE; + } + + return MARSHAL_TYPE_OBJECT; + } +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_get_obj_type (MonoObject *obj) +{ + if (!obj) + return 0; + + /* Process obj before calling into the runtime, class_from_name () can invoke managed code */ + MonoClass *klass = mono_object_get_class (obj); + if ((klass == mono_get_string_class ()) && + (mono_string_is_interned ((MonoString *)obj) == (MonoString *)obj)) + return MARSHAL_TYPE_STRING_INTERNED; + + MonoType *type = mono_class_get_type (klass); + obj = NULL; + + int mono_type = mono_type_get_type (type); + + return mono_wasm_marshal_type_from_mono_type (mono_type, klass, type); +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_try_unbox_primitive_and_get_type (MonoObject *obj, void *result) +{ + int *resultI = result; + int64_t *resultL = result; + float *resultF = result; + double *resultD = result; + + if (!obj) { + *resultL = 0; + return 0; + } + + /* Process obj before calling into the runtime, class_from_name () can invoke managed code */ + MonoClass *klass = mono_object_get_class (obj); + if ((klass == mono_get_string_class ()) && + (mono_string_is_interned ((MonoString *)obj) == (MonoString *)obj)) { + *resultL = 0; + return MARSHAL_TYPE_STRING_INTERNED; + } + + MonoType *type = mono_class_get_type (klass), *original_type = type; + + if (mono_class_is_enum (klass)) + type = mono_type_get_underlying_type (type); + + int mono_type = mono_type_get_type (type); + + // FIXME: We would prefer to unbox once here but it will fail if the value isn't unboxable + + switch (mono_type) { + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + *resultI = *(signed char*)mono_object_unbox (obj); + break; + case MONO_TYPE_U1: + *resultI = *(unsigned char*)mono_object_unbox (obj); + break; + case MONO_TYPE_I2: + case MONO_TYPE_CHAR: + *resultI = *(short*)mono_object_unbox (obj); + break; + case MONO_TYPE_U2: + *resultI = *(unsigned short*)mono_object_unbox (obj); + break; + case MONO_TYPE_I4: + case MONO_TYPE_I: + *resultI = *(int*)mono_object_unbox (obj); + break; + case MONO_TYPE_U4: + // FIXME: Will this behave the way we want for large unsigned values? + *resultI = *(int*)mono_object_unbox (obj); + break; + case MONO_TYPE_R4: + *resultF = *(float*)mono_object_unbox (obj); + break; + case MONO_TYPE_R8: + *resultD = *(double*)mono_object_unbox (obj); + break; + case MONO_TYPE_I8: + case MONO_TYPE_U8: + // FIXME: At present the javascript side of things can't handle this, + // but there's no reason not to future-proof this API + *resultL = *(int64_t*)mono_object_unbox (obj); + break; + default: + // If we failed to do a fast unboxing, return the original type information so + // that the caller can do a proper, slow unboxing later + *resultL = 0; + obj = NULL; + return mono_wasm_marshal_type_from_mono_type (mono_type, klass, original_type); + } + + // We successfully performed a fast unboxing here so use the type information + // matching what we unboxed (i.e. an enum's underlying type instead of its type) + obj = NULL; + return mono_wasm_marshal_type_from_mono_type (mono_type, klass, type); +} + +// FIXME: This function is retained specifically because runtime-test.js uses it +EMSCRIPTEN_KEEPALIVE int +mono_unbox_int (MonoObject *obj) +{ + if (!obj) + return 0; + MonoType *type = mono_class_get_type (mono_object_get_class(obj)); + + void *ptr = mono_object_unbox (obj); + switch (mono_type_get_type (type)) { + case MONO_TYPE_I1: + case MONO_TYPE_BOOLEAN: + return *(signed char*)ptr; + case MONO_TYPE_U1: + return *(unsigned char*)ptr; + case MONO_TYPE_I2: + return *(short*)ptr; + case MONO_TYPE_U2: + return *(unsigned short*)ptr; + case MONO_TYPE_I4: + case MONO_TYPE_I: + return *(int*)ptr; + case MONO_TYPE_U4: + return *(unsigned int*)ptr; + case MONO_TYPE_CHAR: + return *(short*)ptr; + // WASM doesn't support returning longs to JS + // case MONO_TYPE_I8: + // case MONO_TYPE_U8: + default: + printf ("Invalid type %d to mono_unbox_int\n", mono_type_get_type (type)); + return 0; + } +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_array_length (MonoArray *array) +{ + return mono_array_length (array); +} + +EMSCRIPTEN_KEEPALIVE MonoObject* +mono_wasm_array_get (MonoArray *array, int idx) +{ + return mono_array_get (array, MonoObject*, idx); +} + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_obj_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_object_class (), size); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_obj_array_set (MonoArray *array, int idx, MonoObject *obj) +{ + mono_array_setref (array, idx, obj); +} + +EMSCRIPTEN_KEEPALIVE MonoArray* +mono_wasm_string_array_new (int size) +{ + return mono_array_new (root_domain, mono_get_string_class (), size); +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_exec_regression (int verbose_level, char *image) +{ + return mono_regression_test_step (verbose_level, image, NULL) ? 0 : 1; +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_exit (int exit_code) +{ + exit (exit_code); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_set_main_args (int argc, char* argv[]) +{ + mono_runtime_set_main_args (argc, argv); +} + +EMSCRIPTEN_KEEPALIVE int +mono_wasm_strdup (const char *s) +{ + return (int)strdup (s); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_parse_runtime_options (int argc, char* argv[]) +{ + mono_jit_parse_options (argc, argv); +} + +EMSCRIPTEN_KEEPALIVE void +mono_wasm_enable_on_demand_gc (int enable) +{ + mono_wasm_enable_gc = enable ? 1 : 0; +} + +EMSCRIPTEN_KEEPALIVE MonoString * +mono_wasm_intern_string (MonoString *string) +{ + return mono_string_intern (string); +} diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-flags.txt b/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-flags.txt new file mode 100644 index 000000000..bfcdcb7cd --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-flags.txt @@ -0,0 +1 @@ +--profiling-funcs -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=1 -s FORCE_FILESYSTEM=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString', 'UTF8ArrayToString', 'addFunction']" -s "EXPORTED_FUNCTIONS=['_putchar']" --source-map-base http://example.com -emit-llvm -DENABLE_METADATA_UPDATE=1 -Oz --llvm-opts 2 diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-version.txt b/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-version.txt new file mode 100644 index 000000000..8fd4e7025 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/emcc-version.txt @@ -0,0 +1 @@ +emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.12 (d0e647bf266caad50943e78c9841e05e9c499a5d) diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt.dat b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt.dat new file mode 100644 index 000000000..c527c4d8e Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt.dat differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_CJK.dat b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_CJK.dat new file mode 100644 index 000000000..39a71c553 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_CJK.dat differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_EFIGS.dat b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_EFIGS.dat new file mode 100644 index 000000000..924353157 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_EFIGS.dat differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_no_CJK.dat b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_no_CJK.dat new file mode 100644 index 000000000..2e696e256 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/icudt_no_CJK.dat differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/library_mono.js b/Examples/Complete/Animation/Blazor/wwwroot/_framework/library_mono.js new file mode 100644 index 000000000..096cd00cc --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/library_mono.js @@ -0,0 +1,2804 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/** + * @typedef WasmId + * @type {object} + * @property {string} idStr - full object id string + * @property {string} scheme - eg, object, valuetype, array .. + * @property {string} value - string part after `dotnet:scheme:` of the id string + * @property {object} o - value parsed as JSON + */ + +/** + * @typedef WasmRoot - a single address in the managed heap, visible to the GC + * @type {object} + * @property {ManagedPointer} value - pointer into the managed heap, stored in the root + * @property {function} get_address - retrieves address of the root in wasm memory + * @property {function} get - retrieves pointer value + * @property {function} set - updates the pointer + * @property {function} release - releases the root storage for future use + */ + +/** + * @typedef WasmRootBuffer - a collection of addresses in the managed heap, visible to the GC + * @type {object} + * @property {number} length - number of elements the root buffer can hold + * @property {function} get_address - retrieves address of an element in wasm memory, by index + * @property {function} get - retrieves an element by index + * @property {function} set - sets an element's value by index + * @property {function} release - releases the root storage for future use + */ + +/** + * @typedef ManagedPointer + * @type {number} - address in the managed heap + */ + +/** + * @typedef NativePointer + * @type {number} - address in wasm memory + */ + +/** + * @typedef Event + * @type {object} + * @property {string} eventName - name of the event being raised + * @property {object} eventArgs - arguments for the event itself + */ + +var MonoSupportLib = { + $MONO__postset: 'MONO.export_functions (Module);', + $MONO: { + pump_count: 0, + timeout_queue: [], + _vt_stack: [], + mono_wasm_runtime_is_ready : false, + mono_wasm_ignore_pdb_load_errors: true, + + /** @type {object.} */ + _id_table: {}, + + pump_message: function () { + if (!this.mono_background_exec) + this.mono_background_exec = Module.cwrap ("mono_background_exec", null); + while (MONO.timeout_queue.length > 0) { + --MONO.pump_count; + MONO.timeout_queue.shift()(); + } + while (MONO.pump_count > 0) { + --MONO.pump_count; + this.mono_background_exec (); + } + }, + + export_functions: function (module) { + module ["pump_message"] = MONO.pump_message.bind(MONO); + module ["mono_load_runtime_and_bcl"] = MONO.mono_load_runtime_and_bcl.bind(MONO); + module ["mono_load_runtime_and_bcl_args"] = MONO.mono_load_runtime_and_bcl_args.bind(MONO); + module ["mono_wasm_load_bytes_into_heap"] = MONO.mono_wasm_load_bytes_into_heap.bind(MONO); + module ["mono_wasm_load_icu_data"] = MONO.mono_wasm_load_icu_data.bind(MONO); + module ["mono_wasm_get_icudt_name"] = MONO.mono_wasm_get_icudt_name.bind(MONO); + module ["mono_wasm_globalization_init"] = MONO.mono_wasm_globalization_init.bind(MONO); + module ["mono_wasm_get_loaded_files"] = MONO.mono_wasm_get_loaded_files.bind(MONO); + module ["mono_wasm_new_root_buffer"] = MONO.mono_wasm_new_root_buffer.bind(MONO); + module ["mono_wasm_new_root_buffer_from_pointer"] = MONO.mono_wasm_new_root_buffer_from_pointer.bind(MONO); + module ["mono_wasm_new_root"] = MONO.mono_wasm_new_root.bind(MONO); + module ["mono_wasm_new_roots"] = MONO.mono_wasm_new_roots.bind(MONO); + module ["mono_wasm_release_roots"] = MONO.mono_wasm_release_roots.bind(MONO); + }, + + _base64Converter: { + // Code from JSIL: + // https://github.com/sq/JSIL/blob/1d57d5427c87ab92ffa3ca4b82429cd7509796ba/JSIL.Libraries/Includes/Bootstrap/Core/Classes/System.Convert.js#L149 + // Thanks to Katelyn Gadd @kg + + _base64Table: [ + 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', + 'Y', 'Z', + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', + 'y', 'z', + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', + '+', '/' + ], + + _makeByteReader: function (bytes, index, count) { + var position = (typeof (index) === "number") ? index : 0; + var endpoint; + + if (typeof (count) === "number") + endpoint = (position + count); + else + endpoint = (bytes.length - position); + + var result = { + read: function () { + if (position >= endpoint) + return false; + + var nextByte = bytes[position]; + position += 1; + return nextByte; + } + }; + + Object.defineProperty(result, "eof", { + get: function () { + return (position >= endpoint); + }, + configurable: true, + enumerable: true + }); + + return result; + }, + + toBase64StringImpl: function (inArray, offset, length) { + var reader = this._makeByteReader(inArray, offset, length); + var result = ""; + var ch1 = 0, ch2 = 0, ch3 = 0, bits = 0, equalsCount = 0, sum = 0; + var mask1 = (1 << 24) - 1, mask2 = (1 << 18) - 1, mask3 = (1 << 12) - 1, mask4 = (1 << 6) - 1; + var shift1 = 18, shift2 = 12, shift3 = 6, shift4 = 0; + + while (true) { + ch1 = reader.read(); + ch2 = reader.read(); + ch3 = reader.read(); + + if (ch1 === false) + break; + if (ch2 === false) { + ch2 = 0; + equalsCount += 1; + } + if (ch3 === false) { + ch3 = 0; + equalsCount += 1; + } + + // Seems backwards, but is right! + sum = (ch1 << 16) | (ch2 << 8) | (ch3 << 0); + + bits = (sum & mask1) >> shift1; + result += this._base64Table[bits]; + bits = (sum & mask2) >> shift2; + result += this._base64Table[bits]; + + if (equalsCount < 2) { + bits = (sum & mask3) >> shift3; + result += this._base64Table[bits]; + } + + if (equalsCount === 2) { + result += "=="; + } else if (equalsCount === 1) { + result += "="; + } else { + bits = (sum & mask4) >> shift4; + result += this._base64Table[bits]; + } + } + + return result; + }, + }, + + _mono_wasm_root_buffer_prototype: { + _throw_index_out_of_range: function () { + throw new Error ("index out of range"); + }, + _check_in_range: function (index) { + if ((index >= this.__count) || (index < 0)) + this._throw_index_out_of_range(); + }, + /** @returns {NativePointer} */ + get_address: function (index) { + this._check_in_range (index); + return this.__offset + (index * 4); + }, + /** @returns {number} */ + get_address_32: function (index) { + this._check_in_range (index); + return this.__offset32 + index; + }, + /** @returns {ManagedPointer} */ + get: function (index) { + this._check_in_range (index); + return Module.HEAP32[this.get_address_32 (index)]; + }, + set: function (index, value) { + Module.HEAP32[this.get_address_32 (index)] = value; + return value; + }, + _unsafe_get: function (index) { + return Module.HEAP32[this.__offset32 + index]; + }, + _unsafe_set: function (index, value) { + Module.HEAP32[this.__offset32 + index] = value; + }, + clear: function () { + if (this.__offset) + MONO._zero_region (this.__offset, this.__count * 4); + }, + release: function () { + if (this.__offset && this.__ownsAllocation) { + MONO.mono_wasm_deregister_root (this.__offset); + MONO._zero_region (this.__offset, this.__count * 4); + Module._free (this.__offset); + } + + this.__handle = this.__offset = this.__count = this.__offset32 = 0; + }, + toString: function () { + return "[root buffer @" + this.get_address (0) + ", size " + this.__count + "]"; + } + }, + + _scratch_root_buffer: null, + _scratch_root_free_indices: null, + _scratch_root_free_indices_count: 0, + _scratch_root_free_instances: [], + + _mono_wasm_root_prototype: { + /** @returns {NativePointer} */ + get_address: function () { + return this.__buffer.get_address (this.__index); + }, + /** @returns {number} */ + get_address_32: function () { + return this.__buffer.get_address_32 (this.__index); + }, + /** @returns {ManagedPointer} */ + get: function () { + var result = this.__buffer._unsafe_get (this.__index); + return result; + }, + set: function (value) { + this.__buffer._unsafe_set (this.__index, value); + return value; + }, + /** @returns {ManagedPointer} */ + valueOf: function () { + return this.get (); + }, + clear: function () { + this.set (0); + }, + release: function () { + const maxPooledInstances = 128; + if (MONO._scratch_root_free_instances.length > maxPooledInstances) { + MONO._mono_wasm_release_scratch_index (this.__index); + this.__buffer = 0; + this.__index = 0; + } else { + this.set (0); + MONO._scratch_root_free_instances.push (this); + } + }, + toString: function () { + return "[root @" + this.get_address () + "]"; + } + }, + + _mono_wasm_release_scratch_index: function (index) { + if (index === undefined) + return; + + this._scratch_root_buffer.set (index, 0); + this._scratch_root_free_indices[this._scratch_root_free_indices_count] = index; + this._scratch_root_free_indices_count++; + }, + + _mono_wasm_claim_scratch_index: function () { + if (!this._scratch_root_buffer) { + const maxScratchRoots = 8192; + this._scratch_root_buffer = this.mono_wasm_new_root_buffer (maxScratchRoots, "js roots"); + + this._scratch_root_free_indices = new Int32Array (maxScratchRoots); + this._scratch_root_free_indices_count = maxScratchRoots; + for (var i = 0; i < maxScratchRoots; i++) + this._scratch_root_free_indices[i] = maxScratchRoots - i - 1; + + Object.defineProperty (this._mono_wasm_root_prototype, "value", { + get: this._mono_wasm_root_prototype.get, + set: this._mono_wasm_root_prototype.set, + configurable: false + }); + } + + if (this._scratch_root_free_indices_count < 1) + throw new Error ("Out of scratch root space"); + + var result = this._scratch_root_free_indices[this._scratch_root_free_indices_count - 1]; + this._scratch_root_free_indices_count--; + return result; + }, + + _zero_region: function (byteOffset, sizeBytes) { + if (((byteOffset % 4) === 0) && ((sizeBytes % 4) === 0)) + Module.HEAP32.fill(0, byteOffset / 4, sizeBytes / 4); + else + Module.HEAP8.fill(0, byteOffset, sizeBytes); + }, + + /** + * Allocates a block of memory that can safely contain pointers into the managed heap. + * The result object has get(index) and set(index, value) methods that can be used to retrieve and store managed pointers. + * Once you are done using the root buffer, you must call its release() method. + * For small numbers of roots, it is preferable to use the mono_wasm_new_root and mono_wasm_new_roots APIs instead. + * @param {number} capacity - the maximum number of elements the buffer can hold. + * @param {string} [msg] - a description of the root buffer (for debugging) + * @returns {WasmRootBuffer} + */ + mono_wasm_new_root_buffer: function (capacity, msg) { + if (!this.mono_wasm_register_root || !this.mono_wasm_deregister_root) { + this.mono_wasm_register_root = Module.cwrap ("mono_wasm_register_root", "number", ["number", "number", "string"]); + this.mono_wasm_deregister_root = Module.cwrap ("mono_wasm_deregister_root", null, ["number"]); + } + + if (capacity <= 0) + throw new Error ("capacity >= 1"); + + capacity = capacity | 0; + + var capacityBytes = capacity * 4; + var offset = Module._malloc (capacityBytes); + if ((offset % 4) !== 0) + throw new Error ("Malloc returned an unaligned offset"); + + this._zero_region (offset, capacityBytes); + + var result = Object.create (this._mono_wasm_root_buffer_prototype); + result.__offset = offset; + result.__offset32 = (offset / 4) | 0; + result.__count = capacity; + result.length = capacity; + result.__handle = this.mono_wasm_register_root (offset, capacityBytes, msg || 0); + result.__ownsAllocation = true; + + return result; + }, + + /** + * Creates a root buffer object representing an existing allocation in the native heap and registers + * the allocation with the GC. The caller is responsible for managing the lifetime of the allocation. + * @param {NativePointer} offset - the offset of the root buffer in the native heap. + * @param {number} capacity - the maximum number of elements the buffer can hold. + * @param {string} [msg] - a description of the root buffer (for debugging) + * @returns {WasmRootBuffer} + */ + mono_wasm_new_root_buffer_from_pointer: function (offset, capacity, msg) { + if (!this.mono_wasm_register_root || !this.mono_wasm_deregister_root) { + this.mono_wasm_register_root = Module.cwrap ("mono_wasm_register_root", "number", ["number", "number", "string"]); + this.mono_wasm_deregister_root = Module.cwrap ("mono_wasm_deregister_root", null, ["number"]); + } + + if (capacity <= 0) + throw new Error ("capacity >= 1"); + + capacity = capacity | 0; + + var capacityBytes = capacity * 4; + if ((offset % 4) !== 0) + throw new Error ("Unaligned offset"); + + this._zero_region (offset, capacityBytes); + + var result = Object.create (this._mono_wasm_root_buffer_prototype); + result.__offset = offset; + result.__offset32 = (offset / 4) | 0; + result.__count = capacity; + result.length = capacity; + result.__handle = this.mono_wasm_register_root (offset, capacityBytes, msg || 0); + result.__ownsAllocation = false; + + return result; + }, + + /** + * Allocates temporary storage for a pointer into the managed heap. + * Pointers stored here will be visible to the GC, ensuring that the object they point to aren't moved or collected. + * If you already have a managed pointer you can pass it as an argument to initialize the temporary storage. + * The result object has get() and set(value) methods, along with a .value property. + * When you are done using the root you must call its .release() method. + * @param {ManagedPointer} [value] - an address in the managed heap to initialize the root with (or 0) + * @returns {WasmRoot} + */ + mono_wasm_new_root: function (value) { + var result; + + if (this._scratch_root_free_instances.length > 0) { + result = this._scratch_root_free_instances.pop (); + } else { + var index = this._mono_wasm_claim_scratch_index (); + var buffer = this._scratch_root_buffer; + + result = Object.create (this._mono_wasm_root_prototype); + result.__buffer = buffer; + result.__index = index; + } + + if (value !== undefined) { + if (typeof (value) !== "number") + throw new Error ("value must be an address in the managed heap"); + + result.set (value); + } else { + result.set (0); + } + + return result; + }, + + /** + * Allocates 1 or more temporary roots, accepting either a number of roots or an array of pointers. + * mono_wasm_new_roots(n): returns an array of N zero-initialized roots. + * mono_wasm_new_roots([a, b, ...]) returns an array of new roots initialized with each element. + * Each root must be released with its release method, or using the mono_wasm_release_roots API. + * @param {(number | ManagedPointer[])} count_or_values - either a number of roots or an array of pointers + * @returns {WasmRoot[]} + */ + mono_wasm_new_roots: function (count_or_values) { + var result; + + if (Array.isArray (count_or_values)) { + result = new Array (count_or_values.length); + for (var i = 0; i < result.length; i++) + result[i] = this.mono_wasm_new_root (count_or_values[i]); + } else if ((count_or_values | 0) > 0) { + result = new Array (count_or_values); + for (var i = 0; i < result.length; i++) + result[i] = this.mono_wasm_new_root (); + } else { + throw new Error ("count_or_values must be either an array or a number greater than 0"); + } + + return result; + }, + + /** + * Releases 1 or more root or root buffer objects. + * Multiple objects may be passed on the argument list. + * 'undefined' may be passed as an argument so it is safe to call this method from finally blocks + * even if you are not sure all of your roots have been created yet. + * @param {... WasmRoot} roots + */ + mono_wasm_release_roots: function () { + for (var i = 0; i < arguments.length; i++) { + if (!arguments[i]) + continue; + + arguments[i].release (); + } + }, + + mono_text_decoder: undefined, + string_decoder: { + copy: function (mono_string) { + if (mono_string == 0) + return null; + + if (!this.mono_wasm_string_convert) + this.mono_wasm_string_convert = Module.cwrap ("mono_wasm_string_convert", null, ['number']); + + this.mono_wasm_string_convert (mono_string); + var result = this.result; + this.result = undefined; + return result; + }, + decode: function (start, end, save) { + if (!MONO.mono_text_decoder) { + MONO.mono_text_decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; + } + + var str = ""; + if (MONO.mono_text_decoder) { + // When threading is enabled, TextDecoder does not accept a view of a + // SharedArrayBuffer, we must make a copy of the array first. + var subArray = typeof SharedArrayBuffer !== 'undefined' && Module.HEAPU8.buffer instanceof SharedArrayBuffer + ? Module.HEAPU8.slice(start, end) + : Module.HEAPU8.subarray(start, end); + + str = MONO.mono_text_decoder.decode(subArray); + } else { + for (var i = 0; i < end - start; i+=2) { + var char = Module.getValue (start + i, 'i16'); + str += String.fromCharCode (char); + } + } + if (save) + this.result = str; + + return str; + }, + }, + + mono_wasm_get_exception_object: function() { + var exception_obj = MONO.active_exception; + MONO.active_exception = null; + return exception_obj ; + }, + + mono_wasm_get_call_stack: function() { + if (!this.mono_wasm_current_bp_id) + this.mono_wasm_current_bp_id = Module.cwrap ("mono_wasm_current_bp_id", 'number'); + if (!this.mono_wasm_enum_frames) + this.mono_wasm_enum_frames = Module.cwrap ("mono_wasm_enum_frames", null); + + var bp_id = this.mono_wasm_current_bp_id (); + this.active_frames = []; + this.mono_wasm_enum_frames (); + + var the_frames = this.active_frames; + this.active_frames = []; + return { + "breakpoint_id": bp_id, + "frames": the_frames, + }; + }, + + _fixup_name_value_objects: function (var_list) { + let out_list = []; + + var i = 0; + while (i < var_list.length) { + let o = var_list [i]; + const this_has_name = o.name !== undefined; + let next_has_value_or_get_set = false; + + if (i + 1 < var_list.length) { + const next = var_list [i+1]; + next_has_value_or_get_set = next.value !== undefined || next.get !== undefined || next.set !== undefined; + } + + if (!this_has_name) { + // insert the object as-is + // Eg. in case of locals, the names are added + // later + i ++; + } else if (next_has_value_or_get_set) { + // found a {name} followed by a {value/get} + o = Object.assign (o, var_list [i + 1]); + i += 2; + } else { + // missing value/get, so add a placeholder one + o.value = { + type: "symbol", + value: "", + description: "" + }; + i ++; + } + + out_list.push (o); + } + + return out_list; + }, + + _filter_automatic_properties: function (props, accessors_only=false) { + // Note: members in @props, have derived class members, followed by + // those from parent classes + + // Note: Auto-properties have backing fields, named with a special suffix. + // @props here will have the backing field, *and* the getter. + // + // But we want to return only one name/value pair: + // [name of the auto-property] = value of the backing field + + let getters = {}; + let all_fields_except_backing_fields = {}; + let backing_fields = {}; + + // Split props into the 3 groups - backing_fields, getters, and all_fields_except_backing_fields + props.forEach(p => { + if (p.name === undefined) { + console.debug(`Bug: Found a member with no name. Skipping it. p: ${JSON.stringify(p)}`); + return; + } + + if (p.name.endsWith('k__BackingField')) { + const auto_prop_name = p.name.replace ('k__BackingField', '') + .replace ('<', '') + .replace ('>', ''); + + // Only take the first one, as that is overriding others + if (!(auto_prop_name in backing_fields)) + backing_fields[auto_prop_name] = Object.assign(p, { name: auto_prop_name }); + + } else if (p.get !== undefined) { + // if p wasn't overridden by a getter or a field, + // from a more derived class + if (!(p.name in getters) && !(p.name in all_fields_except_backing_fields)) + getters[p.name] = p; + + } else if (!(p.name in all_fields_except_backing_fields)) { + all_fields_except_backing_fields[p.name] = p; + } + }); + + // Filter/merge backing fields, and getters + Object.values(backing_fields).forEach(backing_field => { + const auto_prop_name = backing_field.name; + const getter = getters[auto_prop_name]; + + if (getter === undefined) { + // backing field with no getter + // eg. when a field overrides/`new string foo=..` + // an autoproperty + return; + } + + if (auto_prop_name in all_fields_except_backing_fields) { + delete getters[auto_prop_name]; + } else if (getter.__args.owner_class === backing_field.__args.owner_class) { + // getter+backing_field are from the same class. + // Add the backing_field value as a field + all_fields_except_backing_fields[auto_prop_name] = backing_field; + + // .. and drop the auto-prop getter + delete getters[auto_prop_name]; + } + }); + + if (accessors_only) + return Object.values(getters); + + return Object.values(all_fields_except_backing_fields).concat(Object.values(getters)); + }, + + /** Given `dotnet:object:foo:bar`, + * returns { scheme:'object', value: 'foo:bar' } + * + * Given `dotnet:pointer:{ b: 3 }` + * returns { scheme:'object', value: '{b:3}`, o: {b:3} + * + * @param {string} idStr + * @param {boolean} [throwOnError=false] + * + * @returns {WasmId} + */ + _parse_object_id: function (idStr, throwOnError = false) { + if (idStr === undefined || idStr == "" || !idStr.startsWith ('dotnet:')) { + if (throwOnError) + throw new Error (`Invalid id: ${idStr}`); + + return undefined; + } + + const [, scheme, ...rest] = idStr.split(':'); + let res = { + scheme, + value: rest.join (':'), + idStr, + o: {} + }; + + try { + res.o = JSON.parse(res.value); + // eslint-disable-next-line no-empty + } catch (e) {} + + return res; + }, + + _resolve_member_by_name: function (base_object, base_name, expr_parts) { + if (base_object === undefined || base_object.value === undefined) + throw new Error(`Bug: base_object is undefined`); + + if (base_object.value.type === 'object' && base_object.value.subtype === 'null') + throw new ReferenceError(`Null reference: ${base_name} is null`); + + if (base_object.value.type !== 'object') + throw new ReferenceError(`'.' is only supported on non-primitive types. Failed on '${base_name}'`); + + if (expr_parts.length == 0) + throw new Error(`Invalid member access expression`);//FIXME: need the full expression here + + const root = expr_parts[0]; + const props = this.mono_wasm_get_details(base_object.value.objectId, {}); + let resObject = props.find(l => l.name == root); + if (resObject !== undefined) { + if (resObject.value === undefined && resObject.get !== undefined) + resObject = this._invoke_getter(base_object.value.objectId, root); + } + + if (resObject === undefined || expr_parts.length == 1) + return resObject; + else { + expr_parts.shift(); + return this._resolve_member_by_name(resObject, root, expr_parts); + } + }, + + mono_wasm_eval_member_access: function (scope, var_list, rootObjectId, expr) { + if (expr === undefined || expr.length == 0) + throw new Error(`expression argument required`); + + let parts = expr.split('.'); + if (parts.length == 0) + throw new Error(`Invalid member access expression: ${expr}`); + + const root = parts[0]; + + const locals = this.mono_wasm_get_variables(scope, var_list); + let rootObject = locals.find(l => l.name === root); + if (rootObject === undefined) { + // check `this` + const thisObject = locals.find(l => l.name == "this"); + if (thisObject === undefined) + throw new ReferenceError(`Could not find ${root} in locals, and no 'this' found.`); + + const thisProps = this.mono_wasm_get_details(thisObject.value.objectId, {}); + rootObject = thisProps.find(tp => tp.name == root); + if (rootObject === undefined) + throw new ReferenceError(`Could not find ${root} in locals, or in 'this'`); + + if (rootObject.value === undefined && rootObject.get !== undefined) + rootObject = this._invoke_getter(thisObject.value.objectId, root); + } + + parts.shift(); + + if (parts.length == 0) + return rootObject; + + if (rootObject === undefined || rootObject.value === undefined) + throw new Error(`Could not get a value for ${root}`); + + return this._resolve_member_by_name(rootObject, root, parts); + }, + + mono_wasm_set_variable_value: function (scope, index, name, newValue) { + console.debug (">> mono_wasm_set_variable_value " + name + " - " + newValue); + var ret = this._c_fn_table.mono_wasm_set_variable_on_frame_wrapper(scope, index, name, newValue); + if (ret == false) + throw new Error(`Could not get a value for ${name}`); + return ret; + }, + + /** + * @param {WasmId} id + * @returns {object[]} + */ + _get_vt_properties: function (id, args={}) { + let entry = this._get_id_props (id.idStr); + + if (entry === undefined || entry.members === undefined) { + if (!isNaN (id.o.containerId)) { + // We are expanding, so get *all* the members. + // Which ones to return based on @args, can be determined + // at the time of return + this._get_object_properties (id.o.containerId, { expandValueTypes: true }); + } else if (!isNaN (id.o.arrayId)) + this._get_array_values (id, Number (id.o.arrayIdx), 1, true); + else + throw new Error (`Invalid valuetype id (${id.idStr}). Can't get properties for it.`); + } + + // Let's try again + entry = this._get_id_props (id.idStr); + + if (entry !== undefined && entry.members !== undefined) { + if (args.accessorPropertiesOnly === true) + return entry.accessors; + + return entry.members; + } + + throw new Error (`Unknown valuetype id: ${id.idStr}. Failed to get properties for it.`); + }, + + /** + * + * @callback GetIdArgsCallback + * @param {object} var + * @param {number} idx + * @returns {object} + */ + + /** + * @param {object[]} vars + * @param {GetIdArgsCallback} getIdArgs + * @returns {object} + */ + _assign_vt_ids: function (vars, getIdArgs) + { + vars.forEach ((v, i) => { + // we might not have a `.value`, like in case of getters which have a `.get` instead + const value = v.value; + if (value === undefined || !value.isValueType) + return; + + if (value.objectId !== undefined) + throw new Error (`Bug: Trying to assign valuetype id, but the var already has one: ${v}`); + + value.objectId = this._new_or_add_id_props ({ scheme: 'valuetype', idArgs: getIdArgs (v, i), props: value._props }); + delete value._props; + }); + + return vars; + }, + + // + // @var_list: [ { index: , name: }, .. ] + mono_wasm_get_variables: function(scope, var_list) { + const numBytes = var_list.length * Int32Array.BYTES_PER_ELEMENT; + const ptr = Module._malloc(numBytes); + let heapBytes = new Int32Array(Module.HEAP32.buffer, ptr, numBytes); + for (let i=0; i ({ containerId: this._async_method_objectId, fieldOffset: v.fieldOffset })); + + for (let i in res) { + const res_name = res [i].name; + if (this._async_method_objectId != 0) { + //Async methods are special in the way that local variables can be lifted to generated class fields + //value of "this" comes here either + if (res_name !== undefined && res_name.indexOf ('>') > 0) { + // For async methods, we get the names too, so use that + // ALTHOUGH, the name wouldn't have `<>` for method args + res [i].name = res_name.substring (1, res_name.indexOf ('>')); + } + } else if (res_name === undefined && var_list [i] !== undefined) { + // For non-async methods, we just have the var id, but we have the name + // from the caller + res [i].name = var_list [i].name; + } + } + + this._post_process_details(res); + return res; + }, + + // Keep in sync with the flags in mini-wasm-debugger.c + _get_properties_args_to_gpflags: function (args) { + let gpflags =0; + /* + Disabled for now. Instead, we ask debugger.c to return + ~all~ the members, and then handle the filtering in mono.js . + + if (args.ownProperties) + gpflags |= 1; + if (args.accessorPropertiesOnly) + gpflags |= 2; + */ + if (args.expandValueTypes) + gpflags |= 4; + + return gpflags; + }, + + /** + * @param {number} idNum + * @param {boolean} expandValueTypes + * @returns {object} + */ + _get_object_properties: function(idNum, args={}) { + let gpflags = this._get_properties_args_to_gpflags (args); + + let { res_ok, res } = this.mono_wasm_get_object_properties_info (idNum, gpflags); + if (!res_ok) + throw new Error (`Failed to get properties for ${idNum}`); + + res = MONO._filter_automatic_properties (res, args.accessorPropertiesOnly === true); + res = this._assign_vt_ids (res, v => ({ containerId: idNum, fieldOffset: v.fieldOffset })); + res = this._post_process_details (res); + + return res; + }, + + /** + * @param {WasmId} id + * @param {number} [startIdx=0] + * @param {number} [count=-1] + * @param {boolean} [expandValueTypes=false] + * @returns {object[]} + */ + _get_array_values: function (id, startIdx = 0, count = -1, expandValueTypes = false) { + if (isNaN (id.o.arrayId) || isNaN (startIdx)) + throw new Error (`Invalid array id: ${id.idStr}`); + + let gpflags = this._get_properties_args_to_gpflags({ expandValueTypes }); + let { res_ok, res } = this.mono_wasm_get_array_values_info (id.o.arrayId, startIdx, count, gpflags); + if (!res_ok) + throw new Error (`Failed to get properties for array id ${id.idStr}`); + + res = this._assign_vt_ids (res, (_, i) => ({ arrayId: id.o.arrayId, arrayIdx: Number (startIdx) + i})); + + for (let i = 0; i < res.length; i ++) { + let value = res [i].value; + if (value.objectId !== undefined && value.objectId.startsWith("dotnet:pointer")) + this._new_or_add_id_props ({ objectId: value.objectId, props: { varName: `[${i}]` } }); + } + res = this._post_process_details (res); + return res; + }, + + _post_process_details: function (details) { + if (details == undefined) + return {}; + + if (details.length > 0) + this._extract_and_cache_value_types(details); + + // remove __args added by add_properties_var + details.forEach(d => delete d.__args); + return details; + }, + + /** + * Gets the next id number to use for generating ids + * + * @returns {number} + */ + _next_id: function () { + return ++this._next_id_var; + }, + + _extract_and_cache_value_types: function (var_list) { + if (var_list == undefined || !Array.isArray (var_list) || var_list.length == 0) + return var_list; + + for (let i in var_list) { + let value = var_list [i].value; + if (value === undefined) + continue; + + if (value.objectId !== undefined && value.objectId.startsWith ("dotnet:pointer:")) { + let ptr_args = this._get_id_props (value.objectId); + if (ptr_args === undefined) + throw new Error (`Bug: Expected to find an entry for pointer id: ${value.objectId}`); + + // It might have been already set in some cases, like arrays + // where the name would be `0`, but we want `[0]` for pointers, + // so the deref would look like `*[0]` + ptr_args.varName = ptr_args.varName || var_list [i].name; + } + + if (value.type != "object" || value.isValueType != true || value.expanded != true) // undefined would also give us false + continue; + + if (value.members === undefined) { + // this could happen for valuetypes that maybe + // we were not able to describe, like `ref` parameters + // So, skip that + continue; + } + + // Generate objectId for expanded valuetypes + value.objectId = value.objectId || this._new_or_add_id_props ({ scheme: 'valuetype' }); + + this._extract_and_cache_value_types (value.members); + + const accessors = value.members.filter(m => m.get !== undefined); + const new_props = Object.assign ({ members: value.members, accessors }, value.__extra_vt_props); + + this._new_or_add_id_props ({ objectId: value.objectId, props: new_props }); + delete value.members; + delete value.__extra_vt_props; + } + + return var_list; + }, + + _get_cfo_res_details: function (objectId, args) { + if (!(objectId in this._call_function_res_cache)) + throw new Error(`Could not find any object with id ${objectId}`); + + const real_obj = this._call_function_res_cache [objectId]; + + const descriptors = Object.getOwnPropertyDescriptors (real_obj); + if (args.accessorPropertiesOnly) { + Object.keys (descriptors).forEach (k => { + if (descriptors [k].get === undefined) + Reflect.deleteProperty (descriptors, k); + }); + } + + let res_details = []; + Object.keys (descriptors).forEach (k => { + let new_obj; + let prop_desc = descriptors [k]; + if (typeof prop_desc.value == "object") { + // convert `{value: { type='object', ... }}` + // to `{ name: 'foo', value: { type='object', ... }} + new_obj = Object.assign ({ name: k }, prop_desc); + } else if (prop_desc.value !== undefined) { + // This is needed for values that were not added by us, + // thus are like { value: 5 } + // instead of { value: { type = 'number', value: 5 }} + // + // This can happen, for eg., when `length` gets added for arrays + // or `__proto__`. + new_obj = { + name: k, + // merge/add `type` and `description` to `d.value` + value: Object.assign ({ type: (typeof prop_desc.value), description: '' + prop_desc.value }, + prop_desc) + }; + } else if (prop_desc.get !== undefined) { + // The real_obj has the actual getter. We are just returning a placeholder + // If the caller tries to run function on the cfo_res object, + // that accesses this property, then it would be run on `real_obj`, + // which *has* the original getter + new_obj = { + name: k, + get: { + className: "Function", + description: `get ${k} () {}`, + type: "function" + } + }; + } else { + new_obj = { name: k, value: { type: "symbol", value: "", description: ""} }; + } + + res_details.push (new_obj); + }); + + return { __value_as_json_string__: JSON.stringify (res_details) }; + }, + + /** + * Generates a new id, and a corresponding entry for associated properties + * like `dotnet:pointer:{ a: 4 }` + * The third segment of that `{a:4}` is the idArgs parameter + * + * Only `scheme` or `objectId` can be set. + * if `scheme`, then a new id is generated, and it's properties set + * if `objectId`, then it's properties are updated + * + * @param {object} args + * @param {string} [args.scheme=undefined] scheme second part of `dotnet:pointer:..` + * @param {string} [args.objectId=undefined] objectId + * @param {object} [args.idArgs={}] The third segment of the objectId + * @param {object} [args.props={}] Properties for the generated id + * + * @returns {string} generated/updated id string + */ + _new_or_add_id_props: function ({ scheme = undefined, objectId = undefined, idArgs = {}, props = {} }) { + if (scheme === undefined && objectId === undefined) + throw new Error (`Either scheme or objectId must be given`); + + if (scheme !== undefined && objectId !== undefined) + throw new Error (`Both scheme, and objectId cannot be given`); + + if (objectId !== undefined && Object.entries (idArgs).length > 0) + throw new Error (`Both objectId, and idArgs cannot be given`); + + if (Object.entries (idArgs).length == 0) { + // We want to generate a new id, only if it doesn't have other + // attributes that it can use to uniquely identify. + // Eg, we don't do this for `dotnet:valuetype:{containerId:4, fieldOffset: 24}` + idArgs.num = this._next_id (); + } + + let idStr; + if (objectId !== undefined) { + idStr = objectId; + const old_props = this._id_table [idStr]; + if (old_props === undefined) + throw new Error (`ObjectId not found in the id table: ${idStr}`); + + this._id_table [idStr] = Object.assign (old_props, props); + } else { + idStr = `dotnet:${scheme}:${JSON.stringify (idArgs)}`; + this._id_table [idStr] = props; + } + + return idStr; + }, + + /** + * @param {string} objectId + * @returns {object} + */ + _get_id_props: function (objectId) { + return this._id_table [objectId]; + }, + + _get_deref_ptr_value: function (objectId) { + const ptr_args = this._get_id_props (objectId); + if (ptr_args === undefined) + throw new Error (`Unknown pointer id: ${objectId}`); + + if (ptr_args.ptr_addr == 0 || ptr_args.klass_addr == 0) + throw new Error (`Both ptr_addr and klass_addr need to be non-zero, to dereference a pointer. objectId: ${objectId}`); + + const value_addr = new DataView (Module.HEAPU8.buffer).getUint32 (ptr_args.ptr_addr, /* littleEndian */ true); + let { res_ok, res } = this.mono_wasm_get_deref_ptr_value_info (value_addr, ptr_args.klass_addr); + if (!res_ok) + throw new Error (`Failed to dereference pointer ${objectId}`); + + if (res.length > 0) { + if (ptr_args.varName === undefined) + throw new Error (`Bug: no varName found for the pointer. objectId: ${objectId}`); + + res [0].name = `*${ptr_args.varName}`; + } + + res = this._post_process_details (res); + return res; + }, + + mono_wasm_get_details: function (objectId, args={}) { + let id = this._parse_object_id (objectId, true); + + switch (id.scheme) { + case "object": { + if (isNaN (id.value)) + throw new Error (`Invalid objectId: ${objectId}. Expected a numeric id.`); + + args.expandValueTypes = false; + return this._get_object_properties(id.value, args); + } + + case "array": + return this._get_array_values (id); + + case "valuetype": + return this._get_vt_properties(id, args); + + case "cfo_res": + return this._get_cfo_res_details (objectId, args); + + case "pointer": { + return this._get_deref_ptr_value (objectId); + } + + default: + throw new Error(`Unknown object id format: ${objectId}`); + } + }, + + _cache_call_function_res: function (obj) { + const id = `dotnet:cfo_res:${this._next_call_function_res_id++}`; + this._call_function_res_cache[id] = obj; + return id; + }, + + mono_wasm_release_object: function (objectId) { + if (objectId in this._cache_call_function_res) + delete this._cache_call_function_res[objectId]; + }, + + /** + * @param {string} objectIdStr objectId + * @param {string} name property name + * @returns {object} return value + */ + _invoke_getter: function (objectIdStr, name) { + const id = this._parse_object_id (objectIdStr); + if (id === undefined) + throw new Error (`Invalid object id: ${objectIdStr}`); + + let getter_res; + if (id.scheme == 'object') { + if (isNaN (id.o) || id.o < 0) + throw new Error (`Invalid object id: ${objectIdStr}`); + + let { res_ok, res } = this.mono_wasm_invoke_getter_on_object_info (id.o, name); + if (!res_ok) + throw new Error (`Invoking getter on ${objectIdStr} failed`); + + getter_res = res; + } else if (id.scheme == 'valuetype') { + const id_props = this._get_id_props (objectIdStr); + if (id_props === undefined) + throw new Error (`Unknown valuetype id: ${objectIdStr}`); + + if (typeof id_props.value64 !== 'string' || isNaN (id_props.klass)) + throw new Error (`Bug: Cannot invoke getter on ${objectIdStr}, because of missing or invalid klass/value64 fields. idProps: ${JSON.stringify (id_props)}`); + + const dataPtr = Module._malloc (id_props.value64.length); + const dataHeap = new Uint8Array (Module.HEAPU8.buffer, dataPtr, id_props.value64.length); + dataHeap.set (new Uint8Array (this._base64_to_uint8 (id_props.value64))); + + let { res_ok, res } = this.mono_wasm_invoke_getter_on_value_info (dataHeap.byteOffset, id_props.klass, name); + Module._free (dataHeap.byteOffset); + + if (!res_ok) { + console.debug (`Invoking getter on valuetype ${objectIdStr}, with props: ${JSON.stringify (id_props)} failed`); + throw new Error (`Invoking getter on valuetype ${objectIdStr} failed`); + } + getter_res = res; + } else { + throw new Error (`Only object, and valuetypes supported for getters, id: ${objectIdStr}`); + } + + getter_res = MONO._post_process_details (getter_res); + return getter_res.length > 0 ? getter_res [0] : {}; + }, + + /** + * @param {string} objectIdStr objectId + * @param {string} name property name + * @returns {object} return true if it works and false if it doesn't + */ + _set_value_on_object: function (objectIdStr, name, newvalue) { + const id = this._parse_object_id (objectIdStr); + if (id === undefined) + throw new Error (`Invalid object id: ${objectIdStr}`); + + let setter_res; + if (id.scheme == 'object') { + if (isNaN (id.o) || id.o < 0) + throw new Error (`Invalid object id: ${objectIdStr}`); + + var ret = this._c_fn_table.mono_wasm_set_value_on_object_wrapper (id.o, name, newvalue); + if (!ret) + throw new Error (`Invoking setter on ${objectIdStr} failed`); + + setter_res = ret; + } + else + throw new Error (`Only object is supported for setters, id: ${objectIdStr}`); + return setter_res; + }, + + _create_proxy_from_object_id: function (objectId) { + const details = this.mono_wasm_get_details(objectId); + + if (objectId.startsWith ('dotnet:array:')) + return details.map (p => p.value); + + let proxy = {}; + Object.keys (details).forEach (p => { + var prop = details [p]; + if (prop.get !== undefined) { + // TODO: `set` + + Object.defineProperty (proxy, + prop.name, + { get () { return MONO._invoke_getter (objectId, prop.name); } } + ); + } else { + proxy [prop.name] = prop.value; + } + }); + + const handler1 = { + set (obj, prop, newValue) {return MONO._set_value_on_object (objectId, prop, newValue.toString());}, + }; + return new Proxy(proxy, handler1); + }, + + mono_wasm_call_function_on: function (request) { + if (request.arguments != undefined && !Array.isArray (request.arguments)) + throw new Error (`"arguments" should be an array, but was ${request.arguments}`); + + const objId = request.objectId; + let proxy; + + if (objId.startsWith ('dotnet:cfo_res:')) { + if (objId in this._call_function_res_cache) + proxy = this._call_function_res_cache [objId]; + else + throw new Error (`Unknown object id ${objId}`); + } else { + proxy = this._create_proxy_from_object_id (objId); + } + + const fn_args = request.arguments != undefined ? request.arguments.map(a => JSON.stringify(a.value)) : []; + const fn_eval_str = `var fn = ${request.functionDeclaration}; fn.call (proxy, ...[${fn_args}]);`; + + const fn_res = eval (fn_eval_str); + if (fn_res === undefined) + return { type: "undefined" }; + + if (fn_res === null || (fn_res.subtype === 'null' && fn_res.value === undefined)) + return fn_res; + + // primitive type + if (Object (fn_res) !== fn_res) + return fn_res; + + // return .value, if it is a primitive type + if (fn_res.value !== undefined && Object (fn_res.value.value) !== fn_res.value.value) + return fn_res.value; + + if (request.returnByValue) + return {type: "object", value: fn_res}; + + const fn_res_id = this._cache_call_function_res (fn_res); + if (Object.getPrototypeOf (fn_res) == Array.prototype) { + return { + type: "object", + subtype: "array", + className: "Array", + description: `Array(${fn_res.length})`, + objectId: fn_res_id + }; + } else { + return { type: "object", className: "Object", description: "Object", objectId: fn_res_id }; + } + }, + + _clear_per_step_state: function () { + this._next_id_var = 0; + this._id_table = {}; + }, + + mono_wasm_debugger_resume: function () { + this._clear_per_step_state (); + }, + + mono_wasm_start_single_stepping: function (kind) { + console.debug (">> mono_wasm_start_single_stepping " + kind); + if (!this.mono_wasm_setup_single_step) + this.mono_wasm_setup_single_step = Module.cwrap ("mono_wasm_setup_single_step", 'number', [ 'number']); + + this._clear_per_step_state (); + + return this.mono_wasm_setup_single_step (kind); + }, + + mono_wasm_set_pause_on_exceptions: function (state) { + if (!this.mono_wasm_pause_on_exceptions) + this.mono_wasm_pause_on_exceptions = Module.cwrap ("mono_wasm_pause_on_exceptions", 'number', [ 'number']); + var state_enum = 0; + switch (state) { + case 'uncaught': + state_enum = 1; //EXCEPTION_MODE_UNCAUGHT + break; + case 'all': + state_enum = 2; //EXCEPTION_MODE_ALL + break; + } + return this.mono_wasm_pause_on_exceptions (state_enum); + }, + + mono_wasm_detach_debugger: function () { + if (!this.mono_wasm_set_is_debugger_attached) + this.mono_wasm_set_is_debugger_attached = Module.cwrap ('mono_wasm_set_is_debugger_attached', 'void', ['bool']); + this.mono_wasm_set_is_debugger_attached(false); + }, + + _register_c_fn: function (name, ...args) { + Object.defineProperty (this._c_fn_table, name + '_wrapper', { value: Module.cwrap (name, ...args) }); + }, + + /** + * Calls `Module.cwrap` for the function name, + * and creates a wrapper around it that returns + * `{ bool result, object var_info } + * + * @param {string} name C function name + * @param {string} ret_type + * @param {string[]} params + * + * @returns {void} + */ + _register_c_var_fn: function (name, ret_type, params) { + if (ret_type !== 'bool') + throw new Error (`Bug: Expected a C function signature that returns bool`); + + this._register_c_fn (name, ret_type, params); + Object.defineProperty (this, name + '_info', { + value: function (...args) { + MONO.var_info = []; + const res_ok = MONO._c_fn_table [name + '_wrapper'] (...args); + let res = MONO.var_info; + MONO.var_info = []; + if (res_ok) { + res = this._fixup_name_value_objects (res); + return { res_ok, res }; + } + + return { res_ok, res: undefined }; + } + }); + }, + + mono_wasm_runtime_ready: function () { + this.mono_wasm_runtime_is_ready = true; + this._clear_per_step_state (); + + // FIXME: where should this go? + this._next_call_function_res_id = 0; + this._call_function_res_cache = {}; + + this._c_fn_table = {}; + this._register_c_var_fn ('mono_wasm_get_object_properties', 'bool', [ 'number', 'number' ]); + this._register_c_var_fn ('mono_wasm_get_array_values', 'bool', [ 'number', 'number', 'number', 'number' ]); + this._register_c_var_fn ('mono_wasm_invoke_getter_on_object', 'bool', [ 'number', 'string' ]); + this._register_c_var_fn ('mono_wasm_invoke_getter_on_value', 'bool', [ 'number', 'number', 'string' ]); + this._register_c_var_fn ('mono_wasm_get_local_vars', 'bool', [ 'number', 'number', 'number']); + this._register_c_var_fn ('mono_wasm_get_deref_ptr_value', 'bool', [ 'number', 'number']); + this._register_c_fn ('mono_wasm_set_value_on_object', 'bool', [ 'number', 'string', 'string' ]); + this._register_c_fn ('mono_wasm_set_variable_on_frame', 'bool', [ 'number', 'number', 'string', 'string']); + // DO NOT REMOVE - magic debugger init function + if (globalThis.dotnetDebugger) + debugger; + else + console.debug ("mono_wasm_runtime_ready", "fe00e07a-5519-4dfe-b35a-f867dbaf2e28"); + }, + + mono_wasm_set_breakpoint: function (assembly, method_token, il_offset) { + if (!this.mono_wasm_set_bp) + this.mono_wasm_set_bp = Module.cwrap ('mono_wasm_set_breakpoint', 'number', ['string', 'number', 'number']); + + return this.mono_wasm_set_bp (assembly, method_token, il_offset) + }, + + mono_wasm_remove_breakpoint: function (breakpoint_id) { + if (!this.mono_wasm_del_bp) + this.mono_wasm_del_bp = Module.cwrap ('mono_wasm_remove_breakpoint', 'number', ['number']); + + return this.mono_wasm_del_bp (breakpoint_id); + }, + + // Set environment variable NAME to VALUE + // Should be called before mono_load_runtime_and_bcl () in most cases + mono_wasm_setenv: function (name, value) { + if (!this.wasm_setenv) + this.wasm_setenv = Module.cwrap ('mono_wasm_setenv', null, ['string', 'string']); + this.wasm_setenv (name, value); + }, + + mono_wasm_set_runtime_options: function (options) { + if (!this.wasm_parse_runtime_options) + this.wasm_parse_runtime_options = Module.cwrap ('mono_wasm_parse_runtime_options', null, ['number', 'number']); + var argv = Module._malloc (options.length * 4); + var wasm_strdup = Module.cwrap ('mono_wasm_strdup', 'number', ['string']); + let aindex = 0; + for (var i = 0; i < options.length; ++i) { + Module.setValue (argv + (aindex * 4), wasm_strdup (options [i]), "i32"); + aindex += 1; + } + this.wasm_parse_runtime_options (options.length, argv); + }, + + // + // Initialize the AOT profiler with OPTIONS. + // Requires the AOT profiler to be linked into the app. + // options = { write_at: "", send_to: "" } + // should be in the format ::. + // write_at defaults to 'WebAssembly.Runtime::StopProfile'. + // send_to defaults to 'WebAssembly.Runtime::DumpAotProfileData'. + // DumpAotProfileData stores the data into Module.aot_profile_data. + // + mono_wasm_init_aot_profiler: function (options) { + if (options == null) + options = {} + if (!('write_at' in options)) + options.write_at = 'Interop/Runtime::StopProfile'; + if (!('send_to' in options)) + options.send_to = 'Interop/Runtime::DumpAotProfileData'; + var arg = "aot:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + Module.ccall ('mono_wasm_load_profiler_aot', null, ['string'], [arg]); + }, + + // options = { write_at: "", send_to: "" } + // should be in the format ::. + // write_at defaults to 'WebAssembly.Runtime::StopProfile'. + // send_to defaults to 'WebAssembly.Runtime::DumpCoverageProfileData'. + // DumpCoverageProfileData stores the data into Module.coverage_profile_data. + mono_wasm_init_coverage_profiler: function (options) { + if (options == null) + options = {} + if (!('write_at' in options)) + options.write_at = 'WebAssembly.Runtime::StopProfile'; + if (!('send_to' in options)) + options.send_to = 'WebAssembly.Runtime::DumpCoverageProfileData'; + var arg = "coverage:write-at-method=" + options.write_at + ",send-to-method=" + options.send_to; + Module.ccall ('mono_wasm_load_profiler_coverage', null, ['string'], [arg]); + }, + + _apply_configuration_from_args: function (args) { + for (var k in (args.environment_variables || {})) + MONO.mono_wasm_setenv (k, args.environment_variables[k]); + + if (args.runtime_options) + MONO.mono_wasm_set_runtime_options (args.runtime_options); + + if (args.aot_profiler_options) + MONO.mono_wasm_init_aot_profiler (args.aot_profiler_options); + + if (args.coverage_profiler_options) + MONO.mono_wasm_init_coverage_profiler (args.coverage_profiler_options); + }, + + _get_fetch_file_cb_from_args: function (args) { + if (typeof (args.fetch_file_cb) === "function") + return args.fetch_file_cb; + + if (ENVIRONMENT_IS_NODE) { + var fs = require('fs'); + return function (asset) { + console.debug ("MONO_WASM: Loading... " + asset); + var binary = fs.readFileSync (asset); + var resolve_func2 = function (resolve, reject) { + resolve (new Uint8Array (binary)); + }; + + var resolve_func1 = function (resolve, reject) { + var response = { + ok: true, + url: asset, + arrayBuffer: function () { + return new Promise (resolve_func2); + } + }; + resolve (response); + }; + + return new Promise (resolve_func1); + }; + } else if (typeof (fetch) === "function") { + return function (asset) { + return fetch (asset, { credentials: 'same-origin' }); + }; + } else { + throw new Error ("No fetch_file_cb was provided and this environment does not expose 'fetch'."); + } + }, + + _handle_loaded_asset: function (ctx, asset, url, blob) { + var bytes = new Uint8Array (blob); + if (ctx.tracing) + console.log ("MONO_WASM: Loaded:", asset.name, "size", bytes.length, "from", url); + + var virtualName = asset.virtual_path || asset.name; + var offset = null; + + switch (asset.behavior) { + case "resource": + case "assembly": + ctx.loaded_files.push ({ url: url, file: virtualName}); + case "heap": + case "icu": + offset = this.mono_wasm_load_bytes_into_heap (bytes); + ctx.loaded_assets[virtualName] = [offset, bytes.length]; + break; + + case "vfs": + // FIXME + var lastSlash = virtualName.lastIndexOf("/"); + var parentDirectory = (lastSlash > 0) + ? virtualName.substr(0, lastSlash) + : null; + var fileName = (lastSlash > 0) + ? virtualName.substr(lastSlash + 1) + : virtualName; + if (fileName.startsWith("/")) + fileName = fileName.substr(1); + if (parentDirectory) { + if (ctx.tracing) + console.log ("MONO_WASM: Creating directory '" + parentDirectory + "'"); + + var pathRet = ctx.createPath( + "/", parentDirectory, true, true // fixme: should canWrite be false? + ); + } else { + parentDirectory = "/"; + } + + if (ctx.tracing) + console.log ("MONO_WASM: Creating file '" + fileName + "' in directory '" + parentDirectory + "'"); + + if (!this.mono_wasm_load_data_archive (bytes, parentDirectory)) { + var fileRet = ctx.createDataFile ( + parentDirectory, fileName, + bytes, true /* canRead */, true /* canWrite */, true /* canOwn */ + ); + } + break; + + default: + throw new Error ("Unrecognized asset behavior:", asset.behavior, "for asset", asset.name); + } + + if (asset.behavior === "assembly") { + var hasPpdb = ctx.mono_wasm_add_assembly (virtualName, offset, bytes.length); + + if (!hasPpdb) { + var index = ctx.loaded_files.findIndex(element => element.file == virtualName); + ctx.loaded_files.splice(index, 1); + } + } + else if (asset.behavior === "icu") { + if (this.mono_wasm_load_icu_data (offset)) + ctx.num_icu_assets_loaded_successfully += 1; + else + console.error ("Error loading ICU asset", asset.name); + } + else if (asset.behavior === "resource") { + ctx.mono_wasm_add_satellite_assembly (virtualName, asset.culture, offset, bytes.length); + } + }, + + // deprecated + mono_load_runtime_and_bcl: function ( + unused_vfs_prefix, deploy_prefix, debug_level, file_list, loaded_cb, fetch_file_cb + ) { + var args = { + fetch_file_cb: fetch_file_cb, + loaded_cb: loaded_cb, + debug_level: debug_level, + assembly_root: deploy_prefix, + assets: [] + }; + + for (var i = 0; i < file_list.length; i++) { + var file_name = file_list[i]; + var behavior; + if (file_name.startsWith ("icudt") && file_name.endsWith (".dat")) { + // ICU data files are expected to be "icudt%FilterName%.dat" + behavior = "icu"; + } else { // if (file_name.endsWith (".pdb") || file_name.endsWith (".dll")) + behavior = "assembly"; + } + + args.assets.push ({ + name: file_name, + behavior: behavior + }); + } + + return this.mono_load_runtime_and_bcl_args (args); + }, + + // Initializes the runtime and loads assemblies, debug information, and other files. + // @args is a dictionary-style Object with the following properties: + // assembly_root: (required) the subfolder containing managed assemblies and pdbs + // debug_level or enable_debugging: (required) + // assets: (required) a list of assets to load along with the runtime. each asset + // is a dictionary-style Object with the following properties: + // name: (required) the name of the asset, including extension. + // behavior: (required) determines how the asset will be handled once loaded: + // "heap": store asset into the native heap + // "assembly": load asset as a managed assembly (or debugging information) + // "resource": load asset as a managed resource assembly + // "icu": load asset as an ICU data archive + // "vfs": load asset into the virtual filesystem (for fopen, File.Open, etc) + // load_remote: (optional) if true, an attempt will be made to load the asset + // from each location in @args.remote_sources. + // virtual_path: (optional) if specified, overrides the path of the asset in + // the virtual filesystem and similar data structures once loaded. + // is_optional: (optional) if true, any failure to load this asset will be ignored. + // loaded_cb: (required) a function () invoked when loading has completed. + // fetch_file_cb: (optional) a function (string) invoked to fetch a given file. + // If no callback is provided a default implementation appropriate for the current + // environment will be selected (readFileSync in node, fetch elsewhere). + // If no default implementation is available this call will fail. + // remote_sources: (optional) additional search locations for assets. + // sources will be checked in sequential order until the asset is found. + // the string "./" indicates to load from the application directory (as with the + // files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates + // that asset loads can be attempted from a remote server. Sources must end with a "/". + // environment_variables: (optional) dictionary-style Object containing environment variables + // runtime_options: (optional) array of runtime options as strings + // aot_profiler_options: (optional) dictionary-style Object. see the comments for + // mono_wasm_init_aot_profiler. If omitted, aot profiler will not be initialized. + // coverage_profiler_options: (optional) dictionary-style Object. see the comments for + // mono_wasm_init_coverage_profiler. If omitted, coverage profiler will not be initialized. + // globalization_mode: (optional) configures the runtime's globalization mode: + // "icu": load ICU globalization data from any runtime assets with behavior "icu". + // "invariant": operate in invariant globalization mode. + // "auto" (default): if "icu" behavior assets are present, use ICU, otherwise invariant. + // diagnostic_tracing: (optional) enables diagnostic log messages during startup + mono_load_runtime_and_bcl_args: function (args) { + try { + return this._load_assets_and_runtime (args); + } catch (exc) { + console.error ("error in mono_load_runtime_and_bcl_args:", exc); + throw exc; + } + }, + + // @bytes must be a typed array. space is allocated for it in the native heap + // and it is copied to that location. returns the address of the allocation. + mono_wasm_load_bytes_into_heap: function (bytes) { + var memoryOffset = Module._malloc (bytes.length); + var heapBytes = new Uint8Array (Module.HEAPU8.buffer, memoryOffset, bytes.length); + heapBytes.set (bytes); + return memoryOffset; + }, + + num_icu_assets_loaded_successfully: 0, + + // @offset must be the address of an ICU data archive in the native heap. + // returns true on success. + mono_wasm_load_icu_data: function (offset) { + var fn = Module.cwrap ('mono_wasm_load_icu_data', 'number', ['number']); + var ok = (fn (offset)) === 1; + if (ok) + this.num_icu_assets_loaded_successfully++; + return ok; + }, + + // Get icudt.dat exact filename that matches given culture, examples: + // "ja" -> "icudt_CJK.dat" + // "en_US" (or "en-US" or just "en") -> "icudt_EFIGS.dat" + // etc, see "mono_wasm_get_icudt_name" implementation in pal_icushim_static.c + mono_wasm_get_icudt_name: function (culture) { + return Module.ccall ('mono_wasm_get_icudt_name', 'string', ['string'], [culture]); + }, + + _finalize_startup: function (args, ctx) { + var loaded_files_with_debug_info = []; + + MONO.loaded_assets = ctx.loaded_assets; + ctx.loaded_files.forEach(value => loaded_files_with_debug_info.push(value.url)); + MONO.loaded_files = loaded_files_with_debug_info; + if (ctx.tracing) { + console.log ("MONO_WASM: loaded_assets: " + JSON.stringify(ctx.loaded_assets)); + console.log ("MONO_WASM: loaded_files: " + JSON.stringify(ctx.loaded_files)); + } + + var load_runtime = Module.cwrap ('mono_wasm_load_runtime', null, ['string', 'number']); + + console.debug ("MONO_WASM: Initializing mono runtime"); + + this.mono_wasm_globalization_init (args.globalization_mode); + + if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) { + try { + load_runtime ("unused", args.debug_level); + } catch (ex) { + print ("MONO_WASM: load_runtime () failed: " + ex); + print ("MONO_WASM: Stacktrace: \n"); + print (ex.stack); + + var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']); + wasm_exit (1); + } + } else { + load_runtime ("unused", args.debug_level); + } + + let tz; + try { + tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch {} + MONO.mono_wasm_setenv ("TZ", tz || "UTC"); + MONO.mono_wasm_runtime_ready (); + args.loaded_cb (); + }, + + _load_assets_and_runtime: function (args) { + if (args.enable_debugging) + args.debug_level = args.enable_debugging; + if (args.assembly_list) + throw new Error ("Invalid args (assembly_list was replaced by assets)"); + if (args.runtime_assets) + throw new Error ("Invalid args (runtime_assets was replaced by assets)"); + if (args.runtime_asset_sources) + throw new Error ("Invalid args (runtime_asset_sources was replaced by remote_sources)"); + if (!args.loaded_cb) + throw new Error ("loaded_cb not provided"); + + var ctx = { + tracing: args.diagnostic_tracing || false, + pending_count: args.assets.length, + mono_wasm_add_assembly: Module.cwrap ('mono_wasm_add_assembly', 'number', ['string', 'number', 'number']), + mono_wasm_add_satellite_assembly: Module.cwrap ('mono_wasm_add_satellite_assembly', 'void', ['string', 'string', 'number', 'number']), + loaded_assets: Object.create (null), + // dlls and pdbs, used by blazor and the debugger + loaded_files: [], + createPath: Module['FS_createPath'], + createDataFile: Module['FS_createDataFile'] + }; + + if (ctx.tracing) + console.log ("mono_wasm_load_runtime_with_args", JSON.stringify(args)); + + this._apply_configuration_from_args (args); + + var fetch_file_cb = this._get_fetch_file_cb_from_args (args); + + var onPendingRequestComplete = function () { + --ctx.pending_count; + + if (ctx.pending_count === 0) { + try { + MONO._finalize_startup (args, ctx); + } catch (exc) { + console.error ("Unhandled exception in _finalize_startup", exc); + throw exc; + } + } + }; + + var processFetchResponseBuffer = function (asset, url, blob) { + try { + MONO._handle_loaded_asset (ctx, asset, url, blob); + } catch (exc) { + console.error ("Unhandled exception in processFetchResponseBuffer", exc); + throw exc; + } finally { + onPendingRequestComplete (); + } + }; + + args.assets.forEach (function (asset) { + var attemptNextSource; + var sourceIndex = 0; + var sourcesList = asset.load_remote ? args.remote_sources : [""]; + + var handleFetchResponse = function (response) { + if (!response.ok) { + try { + attemptNextSource (); + return; + } catch (exc) { + console.error ("MONO_WASM: Unhandled exception in handleFetchResponse attemptNextSource for asset", asset.name, exc); + throw exc; + } + } + + try { + var bufferPromise = response ['arrayBuffer'] (); + bufferPromise.then (processFetchResponseBuffer.bind (this, asset, response.url)); + } catch (exc) { + console.error ("MONO_WASM: Unhandled exception in handleFetchResponse for asset", asset.name, exc); + attemptNextSource (); + } + }; + + attemptNextSource = function () { + if (sourceIndex >= sourcesList.length) { + var msg = "MONO_WASM: Failed to load " + asset.name; + try { + var isOk = asset.is_optional || + (asset.name.match (/\.pdb$/) && MONO.mono_wasm_ignore_pdb_load_errors); + + if (isOk) + console.debug (msg); + else { + console.error (msg); + throw new Error (msg); + } + } finally { + onPendingRequestComplete (); + } + } + + var sourcePrefix = sourcesList[sourceIndex]; + sourceIndex++; + + // HACK: Special-case because MSBuild doesn't allow "" as an attribute + if (sourcePrefix === "./") + sourcePrefix = ""; + + var attemptUrl; + if (sourcePrefix.trim() === "") { + if (asset.behavior === "assembly") + attemptUrl = locateFile (args.assembly_root + "/" + asset.name); + else if (asset.behavior === "resource") { + var path = asset.culture !== '' ? `${asset.culture}/${asset.name}` : asset.name; + attemptUrl = locateFile (args.assembly_root + "/" + path); + } + else + attemptUrl = asset.name; + } else { + attemptUrl = sourcePrefix + asset.name; + } + + try { + if (asset.name === attemptUrl) { + if (ctx.tracing) + console.log ("Attempting to fetch '" + attemptUrl + "'"); + } else { + if (ctx.tracing) + console.log ("Attempting to fetch '" + attemptUrl + "' for", asset.name); + } + var fetch_promise = fetch_file_cb (attemptUrl); + fetch_promise.then (handleFetchResponse); + } catch (exc) { + console.error ("MONO_WASM: Error fetching " + attemptUrl, exc); + attemptNextSource (); + } + }; + + attemptNextSource (); + }); + }, + + // Performs setup for globalization. + // @globalization_mode is one of "icu", "invariant", or "auto". + // "auto" will use "icu" if any ICU data archives have been loaded, + // otherwise "invariant". + mono_wasm_globalization_init: function (globalization_mode) { + var invariantMode = false; + + if (globalization_mode === "invariant") + invariantMode = true; + + if (!invariantMode) { + if (this.num_icu_assets_loaded_successfully > 0) { + console.debug ("MONO_WASM: ICU data archive(s) loaded, disabling invariant mode"); + } else if (globalization_mode !== "icu") { + console.debug ("MONO_WASM: ICU data archive(s) not loaded, using invariant globalization mode"); + invariantMode = true; + } else { + var msg = "invariant globalization mode is inactive and no ICU data archives were loaded"; + console.error ("MONO_WASM: ERROR: " + msg); + throw new Error (msg); + } + } + + if (invariantMode) + this.mono_wasm_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1"); + + // Set globalization mode to PredefinedCulturesOnly + this.mono_wasm_setenv ("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", "1"); + }, + + // Used by the debugger to enumerate loaded dlls and pdbs + mono_wasm_get_loaded_files: function() { + if (!this.mono_wasm_set_is_debugger_attached) + this.mono_wasm_set_is_debugger_attached = Module.cwrap ('mono_wasm_set_is_debugger_attached', 'void', ['bool']); + this.mono_wasm_set_is_debugger_attached (true); + return MONO.loaded_files; + }, + + mono_wasm_get_loaded_asset_table: function() { + return MONO.loaded_assets; + }, + + mono_wasm_clear_all_breakpoints: function() { + if (!this.mono_clear_bps) + this.mono_clear_bps = Module.cwrap ('mono_wasm_clear_all_breakpoints', null); + + this.mono_clear_bps (); + }, + + mono_wasm_add_null_var: function(className) + { + let fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + if (!fixed_class_name) { + // Eg, when a @className is passed from js itself, like + // mono_wasm_add_null_var ("string") + fixed_class_name = className; + } + MONO.var_info.push ({value: { + type: "object", + className: fixed_class_name, + description: fixed_class_name, + subtype: "null" + }}); + }, + + _mono_wasm_add_string_var: function(var_value) { + if (var_value === 0) { + MONO.mono_wasm_add_null_var ("string"); + return; + } + + MONO.var_info.push({ + value: { + type: "string", + value: var_value, + description: var_value + } + }); + }, + + _mono_wasm_add_getter_var: function(className) { + const fixed_class_name = MONO._mono_csharp_fixup_class_name (className); + var name; + if (MONO.var_info.length > 0) + name = MONO.var_info [MONO.var_info.length - 1].name; + name = (name === undefined) ? "" : name; + + MONO.var_info.push({ + get: { + className: "Function", + description: `get ${name} () {}`, + type: "function", + } + }); + }, + + _mono_wasm_add_array_var: function(className, objectId, length) { + const fixed_class_name = MONO._mono_csharp_fixup_class_name(className); + if (objectId == 0) { + MONO.mono_wasm_add_null_var (fixed_class_name); + return; + } + + MONO.var_info.push({ + value: { + type: "object", + subtype: "array", + className: fixed_class_name, + description: `${fixed_class_name}(${length})`, + objectId: this._new_or_add_id_props ({ scheme: 'array', idArgs: { arrayId: objectId } }) + } + }); + }, + + // FIXME: improve + _base64_to_uint8: function (base64String) { + const byteCharacters = atob (base64String); + const byteNumbers = new Array(byteCharacters.length); + for (let i = 0; i < byteCharacters.length; i++) { + byteNumbers[i] = byteCharacters.charCodeAt(i); + } + + return new Uint8Array (byteNumbers); + }, + + _begin_value_type_var: function(className, args) { + if (args === undefined || (typeof args !== 'object')) { + console.debug (`_begin_value_type_var: Expected an args object`); + return; + } + + const fixed_class_name = MONO._mono_csharp_fixup_class_name(className); + const toString = args.toString; + const base64String = btoa (String.fromCharCode (...new Uint8Array (Module.HEAPU8.buffer, args.value_addr, args.value_size))); + const vt_obj = { + value: { + type : "object", + className : fixed_class_name, + description : (toString === 0 ? fixed_class_name: Module.UTF8ToString (toString)), + expanded : true, + isValueType : true, + __extra_vt_props: { klass: args.klass, value64: base64String }, + members : [] + } + }; + if (MONO._vt_stack.length == 0) + MONO._old_var_info = MONO.var_info; + + MONO.var_info = vt_obj.value.members; + MONO._vt_stack.push (vt_obj); + }, + + _end_value_type_var: function() { + let top_vt_obj_popped = MONO._vt_stack.pop (); + top_vt_obj_popped.value.members = MONO._filter_automatic_properties ( + MONO._fixup_name_value_objects (top_vt_obj_popped.value.members)); + + if (MONO._vt_stack.length == 0) { + MONO.var_info = MONO._old_var_info; + MONO.var_info.push(top_vt_obj_popped); + } else { + var top_obj = MONO._vt_stack [MONO._vt_stack.length - 1]; + top_obj.value.members.push (top_vt_obj_popped); + MONO.var_info = top_obj.value.members; + } + }, + + _add_valuetype_unexpanded_var: function(className, args) { + if (args === undefined || (typeof args !== 'object')) { + console.debug (`_add_valuetype_unexpanded_var: Expected an args object`); + return; + } + + const fixed_class_name = MONO._mono_csharp_fixup_class_name (className); + const toString = args.toString; + + MONO.var_info.push ({ + value: { + type: "object", + className: fixed_class_name, + description: (toString === 0 ? fixed_class_name : Module.UTF8ToString (toString)), + isValueType: true + } + }); + }, + + mono_wasm_add_properties_var: function (name, args) { + if (typeof args !== 'object') + args = { field_offset: args }; + + if (args.owner_class !== undefined && args.owner_class !== 0) + args.owner_class = Module.UTF8ToString(args.owner_class); + + let name_obj = { + name: Module.UTF8ToString (name), + fieldOffset: args.field_offset, + __args: args + }; + if (args.is_own) + name_obj.isOwn = true; + + MONO.var_info.push(name_obj); + }, + + mono_wasm_add_typed_value: function (type, str_value, value) { + let type_str = type; + if (typeof type != 'string') + type_str = Module.UTF8ToString (type); + + if (str_value !== 0) + str_value = Module.UTF8ToString (str_value); + + switch (type_str) { + case "bool": { + const v = value != 0; + MONO.var_info.push ({ + value: { + type: "boolean", + value: v, + description: v.toString () + }, + writable:true + }); + break; + } + + case "char": { + const v = `${value} '${String.fromCharCode (value)}'`; + MONO.var_info.push ({ + value: { + type: "symbol", + value: v, + description: v + }, + writable:true + }); + break; + } + + case "number": + MONO.var_info.push ({ + value: { + type: "number", + value: value, + description: '' + value + }, + writable:true + }); + break; + + case "string": + MONO._mono_wasm_add_string_var (str_value); + break; + + case "getter": + MONO._mono_wasm_add_getter_var (str_value); + break; + + case "array": + MONO._mono_wasm_add_array_var (str_value, value.objectId, value.length); + break; + + case "begin_vt": + MONO._begin_value_type_var (str_value, value); + break; + + case "end_vt": + MONO._end_value_type_var (); + break; + + case "unexpanded_vt": + MONO._add_valuetype_unexpanded_var (str_value, value); + break; + + case "pointer": { + const fixed_value_str = MONO._mono_csharp_fixup_class_name (str_value); + if (value.klass_addr == 0 || value.ptr_addr == 0 || fixed_value_str.startsWith ('(void*')) { + // null or void*, which we can't deref + MONO.var_info.push({ + value: { + type: "symbol", + value: fixed_value_str, + description: fixed_value_str + } + }); + } else { + MONO.var_info.push({ + value: { + type: "object", + className: fixed_value_str, + description: fixed_value_str, + objectId: this._new_or_add_id_props ({ scheme: 'pointer', props: value }) + } + }); + } + } + break; + + case "symbol": { + if (typeof value === 'object' && value.isClassName) + str_value = MONO._mono_csharp_fixup_class_name (str_value); + + MONO.var_info.push ({ + value: { + type: "symbol", + value: str_value, + description: str_value + } + }); + } + break; + + default: { + const msg = `'${str_value}' ${value}`; + + MONO.var_info.push ({ + value: { + type: "symbol", + value: msg, + description: msg + } + }); + break; + } + } + }, + + _mono_csharp_fixup_class_name: function(className) + { + // Fix up generic names like Foo`2 to Foo + // and nested class names like Foo/Bar to Foo.Bar + return className.replace(/\//g, '.').replace(/`\d+/g, ''); + }, + + mono_wasm_load_data_archive: function (data, prefix) { + if (data.length < 8) + return false; + + var dataview = new DataView(data.buffer); + var magic = dataview.getUint32(0, true); + // get magic number + if (magic != 0x626c6174) { + return false; + } + var manifestSize = dataview.getUint32(4, true); + if (manifestSize == 0 || data.length < manifestSize + 8) + return false; + + var manifest; + try { + manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize); + manifest = JSON.parse(manifestContent); + if (!(manifest instanceof Array)) + return false; + } catch (exc) { + return false; + } + + data = data.slice(manifestSize+8); + + // Create the folder structure + // /usr/share/zoneinfo + // /usr/share/zoneinfo/Africa + // /usr/share/zoneinfo/Asia + // .. + + var folders = new Set() + manifest.filter(m => { + var file = m[0]; + var last = file.lastIndexOf ("/"); + var directory = file.slice (0, last+1); + folders.add(directory); + }); + folders.forEach(folder => { + Module['FS_createPath'](prefix, folder, true, true); + }); + + for (row of manifest) { + var name = row[0]; + var length = row[1]; + var bytes = data.slice(0, length); + Module['FS_createDataFile'](prefix, name, bytes, true, true); + data = data.slice(length); + } + return true; + }, + + /** + * Raises an event for the debug proxy + * + * @param {Event} event - event to be raised + * @param {object} args - arguments for raising this event, eg. `{trace: true}` + */ + mono_wasm_raise_debug_event: function(event, args={}) { + if (typeof event !== 'object') + throw new Error(`event must be an object, but got ${JSON.stringify(event)}`); + + if (event.eventName === undefined) + throw new Error(`event.eventName is a required parameter, in event: ${JSON.stringify(event)}`); + + if (typeof args !== 'object') + throw new Error(`args must be an object, but got ${JSON.stringify(args)}`); + + console.debug('mono_wasm_debug_event_raised:aef14bca-5519-4dfe-b35a-f867abc123ae', JSON.stringify(event), JSON.stringify(args)); + }, + }, + + mono_wasm_add_typed_value: function (type, str_value, value) { + MONO.mono_wasm_add_typed_value (type, str_value, value); + }, + + mono_wasm_add_properties_var: function(name, args) { + MONO.mono_wasm_add_properties_var (name, args); + }, + + mono_wasm_set_is_async_method: function(objectId) { + MONO._async_method_objectId = objectId; + }, + + mono_wasm_add_enum_var: function(className, members, value) { + // FIXME: flags + // + + // group0: Monday:0 + // group1: Monday + // group2: 0 + const re = new RegExp (`[,]?([^,:]+):(${value}(?=,)|${value}$)`, 'g') + const members_str = Module.UTF8ToString (members); + + const match = re.exec(members_str); + const member_name = match == null ? ('' + value) : match [1]; + + const fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + MONO.var_info.push({ + value: { + type: "object", + className: fixed_class_name, + description: member_name, + isEnum: true + } + }); + }, + + mono_wasm_add_array_item: function(position) { + MONO.var_info.push({ + name: `${position}` + }); + }, + + mono_wasm_add_obj_var: function(className, toString, objectId) { + if (objectId == 0) { + MONO.mono_wasm_add_null_var (className); + return; + } + + const fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className)); + MONO.var_info.push({ + value: { + type: "object", + className: fixed_class_name, + description: (toString === 0 ? fixed_class_name : Module.UTF8ToString (toString)), + objectId: "dotnet:object:"+ objectId, + } + }); + }, + + /* + * @className, and @targetName are in the following format: + * + * :[]: + */ + mono_wasm_add_func_var: function (className, targetName, objectId) { + if (objectId == 0) { + MONO.mono_wasm_add_null_var ( + MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className))); + return; + } + + function args_to_sig (args_str) { + var parts = args_str.split (":"); + // TODO: min length = 3? + parts = parts.map (a => MONO._mono_csharp_fixup_class_name (a)); + + // method name at the end + var method_name = parts.pop (); + + // ret type at the beginning + var ret_sig = parts [0]; + var args_sig = parts.splice (1).join (', '); + return `${ret_sig} ${method_name} (${args_sig})`; + } + let tgt_sig; + if (targetName != 0) + tgt_sig = args_to_sig (Module.UTF8ToString (targetName)); + + const type_name = MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className)); + if (tgt_sig === undefined) + tgt_sig = type_name; + + if (objectId == -1 || targetName === 0) { + // Target property + MONO.var_info.push ({ + value: { + type: "symbol", + value: tgt_sig, + description: tgt_sig, + } + }); + } else { + MONO.var_info.push ({ + value: { + type: "object", + className: type_name, + description: tgt_sig, + objectId: "dotnet:object:" + objectId, + } + }); + } + }, + + mono_wasm_add_frame: function(il, method, frame_id, assembly_name, method_full_name) { + var parts = Module.UTF8ToString (method_full_name).split (":", 2); + MONO.active_frames.push( { + il_pos: il, + method_token: method, + assembly_name: Module.UTF8ToString (assembly_name), + // Extract just the method name from `{class_name}:{method_name}` + method_name: parts [parts.length - 1], + frame_id + }); + }, + + schedule_background_exec: function () { + ++MONO.pump_count; + if (typeof globalThis.setTimeout === 'function') { + globalThis.setTimeout (MONO.pump_message, 0); + } + }, + + mono_set_timeout: function (timeout, id) { + if (!this.mono_set_timeout_exec) + this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); + + if (typeof globalThis.setTimeout === 'function') { + globalThis.setTimeout (function () { + this.mono_set_timeout_exec (id); + }, timeout); + } else { + ++MONO.pump_count; + MONO.timeout_queue.push(function() { + this.mono_set_timeout_exec (id); + }) + } + }, + + mono_wasm_fire_bp: function () { + // eslint-disable-next-line no-debugger + debugger; + }, + + mono_wasm_fire_exception: function (exception_id, message, class_name, uncaught) { + MONO.active_exception = { + exception_id: exception_id, + message : Module.UTF8ToString (message), + class_name : Module.UTF8ToString (class_name), + uncaught : uncaught + }; + debugger; + }, + + mono_wasm_asm_loaded: function (assembly_name, assembly_ptr, assembly_len, pdb_ptr, pdb_len) { + // Only trigger this codepath for assemblies loaded after app is ready + if (MONO.mono_wasm_runtime_is_ready !== true) + return; + + const assembly_name_str = assembly_name !== 0 ? Module.UTF8ToString(assembly_name).concat('.dll') : ''; + + const assembly_data = new Uint8Array(Module.HEAPU8.buffer, assembly_ptr, assembly_len); + const assembly_b64 = MONO._base64Converter.toBase64StringImpl(assembly_data); + + let pdb_b64; + if (pdb_ptr) { + const pdb_data = new Uint8Array(Module.HEAPU8.buffer, pdb_ptr, pdb_len); + pdb_b64 = MONO._base64Converter.toBase64StringImpl(pdb_data); + } + + MONO.mono_wasm_raise_debug_event({ + eventName: 'AssemblyLoaded', + assembly_name: assembly_name_str, + assembly_b64, + pdb_b64 + }); + }, +}; + +autoAddDeps(MonoSupportLib, '$MONO') +mergeInto(LibraryManager.library, MonoSupportLib) + +// SIG // Begin signature block +// SIG // MIIkiQYJKoZIhvcNAQcCoIIkejCCJHYCAQExDzANBglg +// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor +// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC +// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg +// SIG // Tvvy87p47DiUVUWnMbIR1/KRbWHFmD0b1Ot+3ZtV2Eig +// SIG // gg3wMIIGbjCCBFagAwIBAgITMwAAAhOMDBwxNbzSXwAA +// SIG // AAACEzANBgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJV +// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT +// SIG // aWduaW5nIFBDQSAyMDExMB4XDTIxMDIxMTIwMDk1MVoX +// SIG // DTIyMDIxMDIwMDk1MVowYzELMAkGA1UEBhMCVVMxEzAR +// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v +// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +// SIG // bjENMAsGA1UEAxMELk5FVDCCAaIwDQYJKoZIhvcNAQEB +// SIG // BQADggGPADCCAYoCggGBAJtZcELdrGHlHCF6nz4bH8vW +// SIG // l5M3GfXIf7JY7OovRwgweTptJQGby0YHZ+iCrWIE7fTc +// SIG // /c9eGKGm+EsuWHnanAm9Ro7MSjdPsYBRaif1Y6dyhBcb +// SIG // b44guUNKlplq7L1k3ldXFFzyAt+u8UzCL5QFwibg2nWi +// SIG // QmCkoJWhiA6RxEPgEZ/ss2ICppgLHm1o6vy1P4ci6aMk +// SIG // Tj2s1uct/oFflYwE0DsK1OrFH7QvoIqWCAuXUXjZOKnF +// SIG // oRia22+ci2oxs/LVkgqcMwC35KHvUBzCW3LME/dSBWCO +// SIG // TV7gieG+gUtxBgPpzomak4thtrQLMRAWl7AOtI7QvsXa +// SIG // FEyQpAlDVz12Sa89KJOLBPksBRDw4woRZLlHnUrtxFRp +// SIG // MZsr+9cf2zfZPG4ia2iDSBFfXu2BeXrifkT4c/UV5Iy3 +// SIG // qEHCzh1jLmN701jUOhF1QN1LEPn+TCth2b239/34+Bym +// SIG // cIAcDP1EWk8JodsUDedKhK+lAefNL0mzUrIQc6Dxb5cq +// SIG // may/QQIDAQABo4IBfjCCAXowHwYDVR0lBBgwFgYKKwYB +// SIG // BAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFO9NaSC3 +// SIG // 3IwsQ0OKpWHnclste605MFAGA1UdEQRJMEekRTBDMSkw +// SIG // JwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy +// SIG // dG8gUmljbzEWMBQGA1UEBRMNNDY0MjIzKzQ2NDI5MzAf +// SIG // BgNVHSMEGDAWgBRIbmTlUAXTgqoXNzcitW2oynUClTBU +// SIG // BgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jv +// SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUw +// SIG // UzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3Nv +// SIG // ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAw +// SIG // DQYJKoZIhvcNAQEMBQADggIBAFiD+cR0K6evMUeUrBMA +// SIG // pLljV65GDDTzlD4jqr6Mu1NTeZv5L9IJlR6DLAEKaJnB +// SIG // a7fZZ/ME/FZasmc40+WijhDmth/OOc7IpfJ3Ra1auKIA +// SIG // g687mo/eWiPs0nC42oCdchy9Q5AS7K0+MUk7R/p9eCTP +// SIG // NYFjSMItiL+YFYCxaZXqHizwdXcvCIrESq4DXwN+ZdUe +// SIG // GBEO9F2SkMVC61/y2xwSwRWmfO/l4YutKT+dSKjlelYi +// SIG // zFAQaJrGzO5ac56S+K/NMndPL7Od3ohqxMu7gsFUynxY +// SIG // l+eyB9T9I9HrUWoHj6ce4nzOxHC+yDRD6Mi2AaT+IbMO +// SIG // cGvWeJC5iX3tzpMqdz0BOMl6jbff+t+BLS7VtU6JAFCM +// SIG // fk5h+wqIPWjon3tpTuFtCkMOSzIoso3U6kdX0fgrgXnN +// SIG // KJspBXkfKG9lMPOPOKwzua1qjghvgzPMftj1yZqFljJm +// SIG // cjBxs/HKA8J8st1MKcgiBGDX5zkcsHYGuAkIb2fXQuYW +// SIG // y0G78JzzSv1u0LAFj8/Qtx9Hm2wfc20+ww+MYEQ9tu1F +// SIG // uJZK2O7+p7iVziwZvo+XVzuIU7sVjcmJH5Gn/ttfkLQ3 +// SIG // 0jvM9QyV/lYwurg4Gn5Li/IZSN56WGIPilRkXUVurpaV +// SIG // WeYCjeUJzMY2n2tVMFl6pgnGmaA2a0uiG3z0GpMPdbS1 +// SIG // R/oEMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +// SIG // hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV +// SIG // BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +// SIG // HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +// SIG // MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +// SIG // dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5 +// SIG // WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJVUzET +// SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +// SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +// SIG // aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWdu +// SIG // aW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOC +// SIG // Ag8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGf +// SIG // Qhsqa+laUKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDI +// SIG // OdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv +// SIG // 2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13Y +// SIG // xC4Ddato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT +// SIG // +OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +// SIG // 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk +// SIG // kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXD +// SIG // OW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf +// SIG // GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +// SIG // JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bys +// SIG // AoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J64HLn +// SIG // JN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeB +// SIG // e+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx +// SIG // 7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu+HggWCwT +// SIG // XWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEA +// SIG // AaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1Ud +// SIG // DgQWBBRIbmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEE +// SIG // AYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw +// SIG // DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToC +// SIG // MZBDuRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBL +// SIG // hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +// SIG // bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf +// SIG // MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEF +// SIG // BQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br +// SIG // aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +// SIG // MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcu +// SIG // AzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy +// SIG // b3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMu +// SIG // aHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABf +// SIG // AHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0AZQBuAHQA +// SIG // LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou +// SIG // 09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+ +// SIG // vj/oCso7v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzS +// SIG // Gksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlE +// SIG // PXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6V +// SIG // oCo/KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu +// SIG // 5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +// SIG // STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp +// SIG // mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38c +// SIG // bxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN +// SIG // pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +// SIG // QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AA +// SIG // KcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74v2u3 +// SIG // S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8 +// SIG // MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7 +// SIG // qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJ +// SIG // UnMTDXpQzTGCFfEwghXtAgEBMIGVMH4xCzAJBgNVBAYT +// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH +// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +// SIG // cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2Rl +// SIG // IFNpZ25pbmcgUENBIDIwMTECEzMAAAITjAwcMTW80l8A +// SIG // AAAAAhMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN +// SIG // AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +// SIG // MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIIc0 +// SIG // GX5eNl4PgrfOFgISutINWxZYGN5xQPt82b94AyqYMEIG +// SIG // CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv +// SIG // AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w +// SIG // DQYJKoZIhvcNAQEBBQAEggGAJ0DQ80PWaiFWypAKfKBM +// SIG // wmQpNy8l63FMfu0ctMvHYVXFgsYGKtMDutRNKr3UmlGw +// SIG // 5GBnDaSURINl0TpKtzM5l+lm3xRxId8V4g4plnJYOVdR +// SIG // 0SUpUpUld4wGuZcvJJKJgrUC57B06jBCbI/Giohe3XDI +// SIG // 7DrpvR4xI6bvYZEkWreCHz6yOTIiTYDPT30Ekzja1mv4 +// SIG // DGI2U3Zw9SgcnmSmUeLILvtVfYnV5fVkfMeisKj8TyIM +// SIG // lkUJ0NgWpVWk1ev7eLQkw5Oh609F8NiSA4PkRMIpvua4 +// SIG // 0E4bM7n05HlITtfgB/h4k2K26J8c+ea1eDKF624r7RY9 +// SIG // +/3WjJHZdGbIiojEii/aLdZjGhNs2YheJ7L64IlvS56u +// SIG // dYIXMATb3ZZcCbjVqB3aiVD9xxMyzpmf//S6e4LsPCJV +// SIG // FUS17f7yQak+5/ZVJssBG4ldCN6c9Rr61Miq5pvC44Gv +// SIG // eos0fBbT3aJXlWtt8sg6IKd+HT2U6OTIbpVYTs4dybRa +// SIG // Bqz6kf/XoYIS+zCCEvcGCisGAQQBgjcDAwExghLnMIIS +// SIG // 4wYJKoZIhvcNAQcCoIIS1DCCEtACAQMxDzANBglghkgB +// SIG // ZQMEAgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQw +// SIG // ggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB +// SIG // BQAEIMY0V2/ZQvpl02KAa9TY35X/CnTrfPplccdRWprr +// SIG // /hvBAgZgsBDDb54YEzIwMjEwNjAzMTAyNzIzLjg1OFow +// SIG // BIACAfSggdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046RDA4Mi00QkZELUVFQkExJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wggg5KMIIE +// SIG // +TCCA+GgAwIBAgITMwAAAUGvf1KXXPLcRQAAAAABQTAN +// SIG // BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG +// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +// SIG // MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ +// SIG // Q0EgMjAxMDAeFw0yMDEwMTUxNzI4MjdaFw0yMjAxMTIx +// SIG // NzI4MjdaMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +// SIG // V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +// SIG // A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYD +// SIG // VQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25z +// SIG // IExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO +// SIG // OkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3Nv +// SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG +// SIG // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8irLqL28dal+PJUm +// SIG // UJOwvYn/sOCEzQzZyj94XbFPtRhDhPjagvvKOv1GgMoO +// SIG // uXvkpM3uM5E67vyOCPxqhTAzq7Ak3zkEXXBv7JoM8Xm0 +// SIG // x5UcnAkpUiEo0eycRl6bnYIB3KlZW3uz4Jc2v2FV0KCG +// SIG // kLrvqfKP8V/i2hVyN854OejWpx8wGUazM4CYUVowcgED +// SIG // c76OY+Xa4W27DCZJm2f9ol4BjSL+b2L/T8n/LEGknaUx +// SIG // wSQTN1LQCt+uBDCASd6VQR5CLLJVt6MBL0W1NlaWxEAJ +// SIG // wlIdyBnS1ihLvRg1jc/KUZe0sRFdD3fhKrjPac3hoy00 +// SIG // 7Fvr6Go0WJ4pr2rJdQIDAQABo4IBGzCCARcwHQYDVR0O +// SIG // BBYEFC0oPyxuLpD9RXBr9c8NO0EFEsbEMB8GA1UdIwQY +// SIG // MBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRP +// SIG // ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y +// SIG // MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYI +// SIG // KwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDct +// SIG // MDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI +// SIG // KwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBAFJ63yJ9 +// SIG // 2ChqCgpexD48okviGuC4ikNsvmwlCSet1sFpvJEzLJB8 +// SIG // cTF4z4qQTz8AsQtcew6mAVmQCYDu9f5ee11xXj1LwHYs +// SIG // ZGnSs/OfRul1VKmY51OQpqvK5O/Ct4fs0Iblzo8eyOLJ +// SIG // ygTk97aXVA4Uzq8GblL7LQ5XiwAY446MOALnNXFo/Kq9 +// SIG // tvzipwY1YcRn/nlMQ+b92OiLLmHVMi2wAUORiKFvaAfY +// SIG // WjhQd+2qHLMsdpNluwBbWe7FF5ABsDo0HROMWyCgxdLQ +// SIG // 3vqr3DMSH3ZWKiirFsvWJmchfZPGRObwqszvSXPFmPBZ +// SIG // 9o+er+4UoLV+50GWnnQky7HVgLkwggZxMIIEWaADAgEC +// SIG // AgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQsw +// SIG // CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ +// SIG // MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z +// SIG // b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +// SIG // ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx +// SIG // MDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVa +// SIG // MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN +// SIG // BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR +// SIG // ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vh +// SIG // wna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg +// SIG // iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg +// SIG // MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG +// SIG // GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBX +// SIG // day9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajy +// SIG // eioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHB +// SIG // IAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIw +// SIG // EAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyK +// SIG // MZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoA +// SIG // UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E +// SIG // BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ +// SIG // W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j +// SIG // cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz +// SIG // L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr +// SIG // BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 +// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v +// SIG // Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E +// SIG // gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC +// SIG // ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k +// SIG // b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0 +// SIG // HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMA +// SIG // dABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsF +// SIG // AAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7P +// SIG // BeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcI +// SIG // K1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZL +// SIG // dO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZ +// SIG // qbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8y +// SIG // Sif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoL +// SIG // kSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38 +// SIG // ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ +// SIG // Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ +// SIG // 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdl +// SIG // R3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30 +// SIG // uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp +// SIG // 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR +// SIG // ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXj +// SIG // ad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA1 +// SIG // 2u8JJxzVs341Hgi62jbb01+P3nSISRKhggLUMIICPQIB +// SIG // ATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046RDA4Mi00QkZELUVFQkExJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAH +// SIG // BgUrDgMCGgMVAKrlvym1CquIoQcrzncLvkD1WpUDoIGD +// SIG // MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE +// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw +// SIG // DQYJKoZIhvcNAQEFBQACBQDkYyCxMCIYDzIwMjEwNjAz +// SIG // MTczNDQxWhgPMjAyMTA2MDQxNzM0NDFaMHQwOgYKKwYB +// SIG // BAGEWQoEATEsMCowCgIFAORjILECAQAwBwIBAAICEcww +// SIG // BwIBAAICEgswCgIFAORkcjECAQAwNgYKKwYBBAGEWQoE +// SIG // AjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEK +// SIG // MAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQBtyFzG +// SIG // N2gJJZ3T6Dzxrw0RoLe9MAvzpz7H2wn8BMAuUs68+9Sz +// SIG // 0qPPgY06wPmE9dqyNzKBjwQrPnJ/qIegjqxgIAazKKN2 +// SIG // hxkAF/kZg0zTK4jDKKUAzIlSwaXbpD19RKHHRdyXGu/0 +// SIG // xlUHCFogRUpH8CZQsXulgvS7H0jiYUkTLTGCAw0wggMJ +// SIG // AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX +// SIG // YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD +// SIG // VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV +// SIG // BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw +// SIG // AhMzAAABQa9/Updc8txFAAAAAAFBMA0GCWCGSAFlAwQC +// SIG // AQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ +// SIG // AQQwLwYJKoZIhvcNAQkEMSIEII8NUwagPkRHGAJ8Oo/i +// SIG // OW4YAgx20yCGVo52QoQGwCM7MIH6BgsqhkiG9w0BCRAC +// SIG // LzGB6jCB5zCB5DCBvQQgUT8BPIzqc3SecHRPLKBtW0vO +// SIG // OnT+78haWo+XcxVerd4wgZgwgYCkfjB8MQswCQYDVQQG +// SIG // EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +// SIG // BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv +// SIG // cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt +// SIG // ZS1TdGFtcCBQQ0EgMjAxMAITMwAAAUGvf1KXXPLcRQAA +// SIG // AAABQTAiBCDEmllKq6p2dSDRT7WXEfJzMnBQlv3YcYTQ +// SIG // /uWbkawwhzANBgkqhkiG9w0BAQsFAASCAQDKMix79B07 +// SIG // +fbk3bFY4G6Rl6OG/BDKvIWVa6A0nJcM0lAcngEJm/j0 +// SIG // V0ooT1kDINkma8NxBS5EnY1oPpHyMG9U9vgL4uz4VwuB +// SIG // eS+cD+fgnbaSWzksiIKwyrSByhq5D2anX+fI5uHMK2a9 +// SIG // +S8zFRwhLjdyu6IIh614P9cRTubsyOjLhD1VxG4ZQ0Sz +// SIG // SIOtHMNPYoZgpHNeiS+rf39jIqlgAB8e3t/tqhtOIUUW +// SIG // VJCrYx9Ri5g5WYrsPnXV2H2GY7rCMn0iSeLEkDhw5Ck1 +// SIG // ZJgRlRavAqoScb2Z3AyMQmBDfLq0aG/+Z58eWPOvG3aZ +// SIG // H89A+KL1p3E1Lr8/Seby8NXt +// SIG // End signature block diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/mscorlib.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/mscorlib.dll new file mode 100644 index 000000000..1fd5a54bf Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/mscorlib.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/netstandard.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/netstandard.dll new file mode 100644 index 000000000..1430b8791 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/netstandard.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/pal_random.js b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pal_random.js new file mode 100644 index 000000000..63e5bdac6 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pal_random.js @@ -0,0 +1,320 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var DotNetEntropyLib = { + $DOTNETENTROPY: { + // batchedQuotaMax is the max number of bytes as specified by the api spec. + // If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm. + // https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues + batchedQuotaMax: 65536, + getBatchedRandomValues: function (buffer, bufferLength) { + // for modern web browsers + // map the work array to the memory buffer passed with the length + for (var i = 0; i < bufferLength; i += this.batchedQuotaMax) { + var view = new Uint8Array(Module.HEAPU8.buffer, buffer + i, Math.min(bufferLength - i, this.batchedQuotaMax)); + crypto.getRandomValues(view) + } + } + }, + dotnet_browser_entropy : function (buffer, bufferLength) { + // check that we have crypto available + if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') { + DOTNETENTROPY.getBatchedRandomValues(buffer, bufferLength) + return 0; + } else { + // we couldn't find a proper implementation, as Math.random() is not suitable + // instead of aborting here we will return and let managed code handle the message + return -1; + } + }, +}; + +autoAddDeps(DotNetEntropyLib, '$DOTNETENTROPY') +mergeInto(LibraryManager.library, DotNetEntropyLib) + +// SIG // Begin signature block +// SIG // MIIkjAYJKoZIhvcNAQcCoIIkfTCCJHkCAQExDzANBglg +// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor +// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC +// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg +// SIG // He0Yy7K+G59QXMN5sHHtOtGJyoFg0Ie3YpqLi1MNoKeg +// SIG // gg3wMIIGbjCCBFagAwIBAgITMwAAAhOMDBwxNbzSXwAA +// SIG // AAACEzANBgkqhkiG9w0BAQwFADB+MQswCQYDVQQGEwJV +// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT +// SIG // aWduaW5nIFBDQSAyMDExMB4XDTIxMDIxMTIwMDk1MVoX +// SIG // DTIyMDIxMDIwMDk1MVowYzELMAkGA1UEBhMCVVMxEzAR +// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v +// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv +// SIG // bjENMAsGA1UEAxMELk5FVDCCAaIwDQYJKoZIhvcNAQEB +// SIG // BQADggGPADCCAYoCggGBAJtZcELdrGHlHCF6nz4bH8vW +// SIG // l5M3GfXIf7JY7OovRwgweTptJQGby0YHZ+iCrWIE7fTc +// SIG // /c9eGKGm+EsuWHnanAm9Ro7MSjdPsYBRaif1Y6dyhBcb +// SIG // b44guUNKlplq7L1k3ldXFFzyAt+u8UzCL5QFwibg2nWi +// SIG // QmCkoJWhiA6RxEPgEZ/ss2ICppgLHm1o6vy1P4ci6aMk +// SIG // Tj2s1uct/oFflYwE0DsK1OrFH7QvoIqWCAuXUXjZOKnF +// SIG // oRia22+ci2oxs/LVkgqcMwC35KHvUBzCW3LME/dSBWCO +// SIG // TV7gieG+gUtxBgPpzomak4thtrQLMRAWl7AOtI7QvsXa +// SIG // FEyQpAlDVz12Sa89KJOLBPksBRDw4woRZLlHnUrtxFRp +// SIG // MZsr+9cf2zfZPG4ia2iDSBFfXu2BeXrifkT4c/UV5Iy3 +// SIG // qEHCzh1jLmN701jUOhF1QN1LEPn+TCth2b239/34+Bym +// SIG // cIAcDP1EWk8JodsUDedKhK+lAefNL0mzUrIQc6Dxb5cq +// SIG // may/QQIDAQABo4IBfjCCAXowHwYDVR0lBBgwFgYKKwYB +// SIG // BAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFO9NaSC3 +// SIG // 3IwsQ0OKpWHnclste605MFAGA1UdEQRJMEekRTBDMSkw +// SIG // JwYDVQQLEyBNaWNyb3NvZnQgT3BlcmF0aW9ucyBQdWVy +// SIG // dG8gUmljbzEWMBQGA1UEBRMNNDY0MjIzKzQ2NDI5MzAf +// SIG // BgNVHSMEGDAWgBRIbmTlUAXTgqoXNzcitW2oynUClTBU +// SIG // BgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jv +// SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUw +// SIG // UzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3Nv +// SIG // ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0Ey +// SIG // MDExXzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAw +// SIG // DQYJKoZIhvcNAQEMBQADggIBAFiD+cR0K6evMUeUrBMA +// SIG // pLljV65GDDTzlD4jqr6Mu1NTeZv5L9IJlR6DLAEKaJnB +// SIG // a7fZZ/ME/FZasmc40+WijhDmth/OOc7IpfJ3Ra1auKIA +// SIG // g687mo/eWiPs0nC42oCdchy9Q5AS7K0+MUk7R/p9eCTP +// SIG // NYFjSMItiL+YFYCxaZXqHizwdXcvCIrESq4DXwN+ZdUe +// SIG // GBEO9F2SkMVC61/y2xwSwRWmfO/l4YutKT+dSKjlelYi +// SIG // zFAQaJrGzO5ac56S+K/NMndPL7Od3ohqxMu7gsFUynxY +// SIG // l+eyB9T9I9HrUWoHj6ce4nzOxHC+yDRD6Mi2AaT+IbMO +// SIG // cGvWeJC5iX3tzpMqdz0BOMl6jbff+t+BLS7VtU6JAFCM +// SIG // fk5h+wqIPWjon3tpTuFtCkMOSzIoso3U6kdX0fgrgXnN +// SIG // KJspBXkfKG9lMPOPOKwzua1qjghvgzPMftj1yZqFljJm +// SIG // cjBxs/HKA8J8st1MKcgiBGDX5zkcsHYGuAkIb2fXQuYW +// SIG // y0G78JzzSv1u0LAFj8/Qtx9Hm2wfc20+ww+MYEQ9tu1F +// SIG // uJZK2O7+p7iVziwZvo+XVzuIU7sVjcmJH5Gn/ttfkLQ3 +// SIG // 0jvM9QyV/lYwurg4Gn5Li/IZSN56WGIPilRkXUVurpaV +// SIG // WeYCjeUJzMY2n2tVMFl6pgnGmaA2a0uiG3z0GpMPdbS1 +// SIG // R/oEMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq +// SIG // hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV +// SIG // BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx +// SIG // HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +// SIG // MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +// SIG // dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5 +// SIG // WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJVUzET +// SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk +// SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 +// SIG // aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWdu +// SIG // aW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOC +// SIG // Ag8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGf +// SIG // Qhsqa+laUKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDI +// SIG // OdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv +// SIG // 2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13Y +// SIG // xC4Ddato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT +// SIG // +OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy +// SIG // 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk +// SIG // kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXD +// SIG // OW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf +// SIG // GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +// SIG // JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bys +// SIG // AoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J64HLn +// SIG // JN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeB +// SIG // e+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx +// SIG // 7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu+HggWCwT +// SIG // XWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEA +// SIG // AaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1Ud +// SIG // DgQWBBRIbmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEE +// SIG // AYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw +// SIG // DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToC +// SIG // MZBDuRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBL +// SIG // hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny +// SIG // bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf +// SIG // MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEF +// SIG // BQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br +// SIG // aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +// SIG // MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcu +// SIG // AzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy +// SIG // b3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMu +// SIG // aHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABf +// SIG // AHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0AZQBuAHQA +// SIG // LiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou +// SIG // 09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+ +// SIG // vj/oCso7v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzS +// SIG // Gksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlE +// SIG // PXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6V +// SIG // oCo/KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu +// SIG // 5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 +// SIG // STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp +// SIG // mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38c +// SIG // bxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN +// SIG // pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +// SIG // QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AA +// SIG // KcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74v2u3 +// SIG // S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8 +// SIG // MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7 +// SIG // qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJ +// SIG // UnMTDXpQzTGCFfQwghXwAgEBMIGVMH4xCzAJBgNVBAYT +// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH +// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +// SIG // cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2Rl +// SIG // IFNpZ25pbmcgUENBIDIwMTECEzMAAAITjAwcMTW80l8A +// SIG // AAAAAhMwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcN +// SIG // AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO +// SIG // MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIKTQ +// SIG // ts56jQmXdTOrJhxHePDRP6IYHMqtdIFdJu6K2KWDMEIG +// SIG // CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv +// SIG // AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w +// SIG // DQYJKoZIhvcNAQEBBQAEggGAOhQBtM8dGqO4xsak/oHn +// SIG // LgxQeUK0erh74L+U88RqkAd9KtULNj1RqjYSeAxsoXxZ +// SIG // /6F/wiQaHzYr41yGXNTiUtT2+VQ3fJRffXZA59U19pve +// SIG // uonmwz2ZAD+NJl6uzQQsuc+aiyDmENCBI8Q95d8zfopn +// SIG // lEpKICbrb3sAIfvOzJxod/JJEfVWm/P0r1XXMdcgbC9O +// SIG // LmxaVgyH+L4Zwb6K3OYIQrnEKxXKAydWUCyqtynPyEsH +// SIG // UFnSL9SogbunqXCug7xv9hUC1qqR08796dn4+Arxa4LT +// SIG // /5yfn9pQ2QVIQPZghqKN5xYsQBFyn8Xh4fSYt9aSGrh7 +// SIG // 3k1WYPumXp901gILj4TxSZtxtOyOHxZzy/AzdAtUAFit +// SIG // ePp5G12J7XduTJIb7SIPbvMNoOeRPEWTIRYk7orpRsqP +// SIG // t2ChkxkKzljyAjPNpZjYM+J2+l+uYUTuUlQBSwouHw4h +// SIG // hDGVC4mOn7/friAsLo7MOB2Als0kuXGP4uY2nC0hvAyM +// SIG // 5/gxULEGoYIS/jCCEvoGCisGAQQBgjcDAwExghLqMIIS +// SIG // 5gYJKoZIhvcNAQcCoIIS1zCCEtMCAQMxDzANBglghkgB +// SIG // ZQMEAgEFADCCAVkGCyqGSIb3DQEJEAEEoIIBSASCAUQw +// SIG // ggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB +// SIG // BQAEIG06YaXst+QK7V0RqeXNgH8uVNIHvnuRRBwqG+UM +// SIG // g7LQAgZgsPYTylQYEzIwMjEwNjAzMTAyNzI2LjgwNlow +// SIG // BIACAfSggdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046MTc5RS00QkIwLTgyNDYxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wggg5NMIIE +// SIG // +TCCA+GgAwIBAgITMwAAATyL/bmzP0eX/QAAAAABPDAN +// SIG // BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEG +// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +// SIG // MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ +// SIG // Q0EgMjAxMDAeFw0yMDEwMTUxNzI4MjNaFw0yMjAxMTIx +// SIG // NzI4MjNaMIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMK +// SIG // V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +// SIG // A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYD +// SIG // VQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25z +// SIG // IExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNO +// SIG // OjE3OUUtNEJCMC04MjQ2MSUwIwYDVQQDExxNaWNyb3Nv +// SIG // ZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG +// SIG // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBAq6WkDqvY5DgaQ +// SIG // t+OX0NCLzqUaivJxHvo6KSXP+VzTas2p6uYa3fcIm+EX +// SIG // b6bj4+vJ+Q5v12btrwqp1qMYct4sa24Ev64Nwkt26qfA +// SIG // INVEIP8QM99k7nnkzmNXDnpXF0WoaLCHI5a65L9dwGnB +// SIG // V5uAG2DAoGDOgc3WSgEXm3OsxL/uEAsuPtQFfER0BxDn +// SIG // aI+NjiaWxVpR72Cs17jNQB+L5o0/aP3wqtplg+yINvwq +// SIG // WiHdoByukfkvdPYitu7lZI1Wqdv0m+AEziyW2lUPl9Po +// SIG // WGxHAnrH/d4PrQEF7rwPHR+t3aCuSOc3WQheVP9w4m35 +// SIG // e2QhbFOpLPqYeIya2wIDAQABo4IBGzCCARcwHQYDVR0O +// SIG // BBYEFOGhZ+LKEvo2s2E/JRjqGL8mZzxGMB8GA1UdIwQY +// SIG // MBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRP +// SIG // ME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y +// SIG // MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYI +// SIG // KwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv +// SIG // bS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDct +// SIG // MDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI +// SIG // KwYBBQUHAwgwDQYJKoZIhvcNAQELBQADggEBADL3EIyU +// SIG // 3Zd5bkjMxakZMUZJSfilkVFJQdyNiiVVm+Bp+nlnSU4l +// SIG // nQtbsXoxdqD19G/l/UCIYvLtQGle/dnhIrdpUM6lYD4n +// SIG // 8k2Ri48ytjqLuD4/xefD6dpuh7qRn7jQHoZZ/oUr7yBO +// SIG // YIBJwor/ZVZACTjJSxxd/A2z7+6clrNC879rI2cDx73Y +// SIG // bVfJQbTmLBPDcc55W7MnPNL0Z0XqpvCUCumfMQA+EnmP +// SIG // HbhRV4XIhExthNG4fvzd5sBp81yczG0igCpMyMOmMan/ +// SIG // sx81jxYpvQxmcJnIavuiQSrW+BBk9BBbX6hgqzjw+Tu7 +// SIG // j8EnY9WqYF6qOx3Lce4XLOao6cIwggZxMIIEWaADAgEC +// SIG // AgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQsw +// SIG // CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ +// SIG // MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z +// SIG // b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +// SIG // ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx +// SIG // MDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3MDEyMTQ2NTVa +// SIG // MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n +// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN +// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN +// SIG // BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcR +// SIG // ijog7PwTl/X6f2mUa3RUENWlCgCChfvtfGhLLF/Fw+Vh +// SIG // wna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg +// SIG // iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRg +// SIG // MlhgRvJYR4YyhB50YWeRX4FUsc+TTJLBxKZd0WETbijG +// SIG // GvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/XcfPfBX +// SIG // day9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajy +// SIG // eioKMfDaTgaRtogINeh4HLDpmc085y9Euqf03GS9pAHB +// SIG // IAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB5jCCAeIw +// SIG // EAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyK +// SIG // MZDzQ3t8RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoA +// SIG // UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E +// SIG // BTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ +// SIG // W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j +// SIG // cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz +// SIG // L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr +// SIG // BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93 +// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v +// SIG // Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E +// SIG // gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcC +// SIG // ARYxaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL1BLSS9k +// SIG // b2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcCAjA0 +// SIG // HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMA +// SIG // dABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsF +// SIG // AAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Prpsz1Mb7P +// SIG // BeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcI +// SIG // K1GCRBL7uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZL +// SIG // dO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCvOA8X9S95gWXZ +// SIG // qbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8y +// SIG // Sif9Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoL +// SIG // kSbiOewZSnFjnXshbcOco6I8+n99lmqQeKZt0uGc+R38 +// SIG // ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+ +// SIG // Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ +// SIG // 732D8OE7cQnfXXSYIghh2rBQHm+98eEA3+cxB6STOvdl +// SIG // R3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30 +// SIG // uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp +// SIG // 9cAvVCch98isTtoouLGp25ayp0Kiyc8ZQU3ghvkqmqMR +// SIG // ZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HSxVXj +// SIG // ad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA1 +// SIG // 2u8JJxzVs341Hgi62jbb01+P3nSISRKhggLXMIICQAIB +// SIG // ATCCAQChgdikgdUwgdIxCzAJBgNVBAYTAlVTMRMwEQYD +// SIG // VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +// SIG // MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x +// SIG // LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh +// SIG // dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRT +// SIG // UyBFU046MTc5RS00QkIwLTgyNDYxJTAjBgNVBAMTHE1p +// SIG // Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAH +// SIG // BgUrDgMCGgMVAB1LdHpZ3mjy22teinut0UdweuTmoIGD +// SIG // MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh +// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV +// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE +// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw +// SIG // DQYJKoZIhvcNAQEFBQACBQDkYrSTMCIYDzIwMjEwNjAz +// SIG // MDk1MzIzWhgPMjAyMTA2MDQwOTUzMjNaMHcwPQYKKwYB +// SIG // BAGEWQoEATEvMC0wCgIFAORitJMCAQAwCgIBAAICHHsC +// SIG // Af8wBwIBAAICEmcwCgIFAORkBhMCAQAwNgYKKwYBBAGE +// SIG // WQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAweh +// SIG // IKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCY +// SIG // ousN436K7aadq4lBgT0F3tetvOpvcoc5L/B0EHZeb+rx +// SIG // I6wYloEMcVPOaLiSMMf0VDjzUIG3/Q31iN/Cn40W86ZS +// SIG // 86kC3qcwFL+McvgJrNZHpU0a9DUI0lHxJi36t0Z/GC7T +// SIG // XkZpJzeAvJ1M+tpdnSRqvDvn9+wzi3HqdNzQEjGCAw0w +// SIG // ggMJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +// SIG // EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w +// SIG // HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk +// SIG // BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy +// SIG // MDEwAhMzAAABPIv9ubM/R5f9AAAAAAE8MA0GCWCGSAFl +// SIG // AwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcN +// SIG // AQkQAQQwLwYJKoZIhvcNAQkEMSIEIEDP9TS9t0tVhYYh +// SIG // aVWNhKGSloUqLAb0iMBgj6/F5ZD7MIH6BgsqhkiG9w0B +// SIG // CRACLzGB6jCB5zCB5DCBvQQgoEkCuk0kv8DnOqm31HwR +// SIG // r+2IbD3xmIW4FSGK4SboWkYwgZgwgYCkfjB8MQswCQYD +// SIG // VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G +// SIG // A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 +// SIG // IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg +// SIG // VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAATyL/bmzP0eX +// SIG // /QAAAAABPDAiBCALHqq7hdXl2pLRNhwHbHSPjkcaMyvv +// SIG // QZpBGWeSTRYazzANBgkqhkiG9w0BAQsFAASCAQA/tNOS +// SIG // ROAW5YXTbJIsKtU+QCCg2z5gPErQeDJUj/F5VP3vAdSc +// SIG // 2htKXzRXPBa2ogS+bgULMjfrf8WXkjtLfhC7EGdKyJqV +// SIG // RbCt+hOfPMyARE97EaiTukNbqVVLRM68CnknsBdi5HOg +// SIG // K2qd7C3CZfTv2qF8rhmsWXdR9rRG9LBOIwIoABna0gIU +// SIG // dPWrqLwRKNVNQznSFwKlI8WyLsFExx64d13AspZxjcKv +// SIG // dedPCLNvqqw8n4RZGXy2T8snU2somQLPRpyv11U3B8El +// SIG // MVok0S3YqvHSYGWslEKeDiavLaY38JkbFZSa6WVBxxqP +// SIG // vjdCNxwuZMlTu3cZPdUo7iY31BTQ +// SIG // End signature block diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.c b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.c new file mode 100644 index 000000000..3804005cb --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.c @@ -0,0 +1,61 @@ +#include "pinvoke.h" + +#include + +/* + * The table header contain autogenerated function declarations, so avoid including standard headers + * to avoid incompatible declarations. + */ +#define NULL ((void*)0) +int strcmp (const char *s1, const char *s2); +void mono_wasm_printerr (const char *s); + +#ifdef GEN_PINVOKE +#include "pinvoke-table.h" +#else +#include "pinvoke-tables-default.h" +#endif + +void +mono_wasm_pinvoke_vararg_stub (void) +{ + /* This is just a stub used to mark vararg pinvokes */ +} + +void* +wasm_dl_lookup_pinvoke_table (const char *name) +{ + for (int i = 0; i < sizeof (pinvoke_tables) / sizeof (void*); ++i) { + if (!strcmp (name, pinvoke_names [i])) + return pinvoke_tables [i]; + } + return NULL; +} + +int +wasm_dl_is_pinvoke_table (void *handle) +{ + for (int i = 0; i < sizeof (pinvoke_tables) / sizeof (void*); ++i) { + if (pinvoke_tables [i] == handle) { + return 1; + } + } + return 0; +} + +void* +wasm_dl_get_native_to_interp (const char *key, void *extra_arg) +{ +#ifdef GEN_PINVOKE + for (int i = 0; i < sizeof (wasm_native_to_interp_map) / sizeof (void*); ++i) { + if (!strcmp (wasm_native_to_interp_map [i], key)) { + void *addr = wasm_native_to_interp_funcs [i]; + wasm_native_to_interp_ftndescs [i] = *(InterpFtnDesc*)extra_arg; + return addr; + } + } + return NULL; +#else + return NULL; +#endif +} diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.h b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.h new file mode 100644 index 000000000..03c5ce4ed --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/_framework/pinvoke.h @@ -0,0 +1,26 @@ +#ifndef __PINVOKE_H__ +#define __PINVOKE_H__ + +typedef struct { + const char *name; + void *func; +} PinvokeImport; + +typedef struct { + void *func; + void *arg; +} InterpFtnDesc; + +void* +wasm_dl_lookup_pinvoke_table (const char *name); + +int +wasm_dl_is_pinvoke_table (void *handle); + +void* +wasm_dl_get_native_to_interp (const char *key, void *extra_arg); + +void +mono_wasm_pinvoke_vararg_stub (void); + +#endif diff --git a/Examples/Complete/Animation/Blazor/wwwroot/_framework/protobuf-net.Core.dll b/Examples/Complete/Animation/Blazor/wwwroot/_framework/protobuf-net.Core.dll new file mode 100644 index 000000000..602fa0f6f Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/_framework/protobuf-net.Core.dll differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/index.html b/Examples/Complete/Animation/Blazor/wwwroot/index.html new file mode 100644 index 000000000..4d7367fd7 --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/index.html @@ -0,0 +1,45 @@ + + + + + + Fusee.Examples.Simple.Blazor + + + + + + + + + + + + +
+
+

+ Loading Animation +

+

Loading

+
+
+ +
+
+

+ Startup animation +

+

Made with Fusee

+
+
+ +
+
+ + + + + + + diff --git a/Examples/Complete/Animation/Blazor/wwwroot/manifest.json b/Examples/Complete/Animation/Blazor/wwwroot/manifest.json new file mode 100644 index 000000000..81682c63e --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/manifest.json @@ -0,0 +1,15 @@ +{ + "name": "Fusee.Examples.Picking.Blazor", + "short_name": "Fusee.Examples.Picking.Blazor", + "start_url": "./", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#03173d", + "icons": [ + { + "src": "icon-512.png", + "type": "image/png", + "sizes": "512x512" + } + ] +} diff --git a/Examples/Complete/Animation/Blazor/wwwroot/service-worker.js b/Examples/Complete/Animation/Blazor/wwwroot/service-worker.js new file mode 100644 index 000000000..fe614daee --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/service-worker.js @@ -0,0 +1,4 @@ +// In development, always fetch from the network and do not enable offline support. +// This is because caching would make development more difficult (changes would not +// be reflected on the first load after each change). +self.addEventListener('fetch', () => { }); diff --git a/Examples/Complete/Animation/Blazor/wwwroot/service-worker.published.js b/Examples/Complete/Animation/Blazor/wwwroot/service-worker.published.js new file mode 100644 index 000000000..0d9986fce --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/service-worker.published.js @@ -0,0 +1,48 @@ +// Caution! Be sure you understand the caveats before publishing an application with +// offline support. See https://aka.ms/blazor-offline-considerations + +self.importScripts('./service-worker-assets.js'); +self.addEventListener('install', event => event.waitUntil(onInstall(event))); +self.addEventListener('activate', event => event.waitUntil(onActivate(event))); +self.addEventListener('fetch', event => event.respondWith(onFetch(event))); + +const cacheNamePrefix = 'offline-cache-'; +const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; +const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ]; +const offlineAssetsExclude = [ /^service-worker\.js$/ ]; + +async function onInstall(event) { + console.info('Service worker: Install'); + + // Fetch and cache all matching items from the assets manifest + const assetsRequests = self.assetsManifest.assets + .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) + .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) + .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' })); + await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); +} + +async function onActivate(event) { + console.info('Service worker: Activate'); + + // Delete unused caches + const cacheKeys = await caches.keys(); + await Promise.all(cacheKeys + .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName) + .map(key => caches.delete(key))); +} + +async function onFetch(event) { + let cachedResponse = null; + if (event.request.method === 'GET') { + // For all navigation requests, try to serve index.html from cache + // If you need some URLs to be server-rendered, edit the following check to exclude those URLs + const shouldServeIndexHtml = event.request.mode === 'navigate'; + + const request = shouldServeIndexHtml ? 'index.html' : event.request; + const cache = await caches.open(cacheName); + cachedResponse = await cache.match(request); + } + + return cachedResponse || fetch(event.request); +} diff --git a/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeAnim.gif b/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeAnim.gif new file mode 100644 index 000000000..3d2803861 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeAnim.gif differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeSpinning.gif b/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeSpinning.gif new file mode 100644 index 000000000..0347065b1 Binary files /dev/null and b/Examples/Complete/Animation/Blazor/wwwroot/style/FuseeSpinning.gif differ diff --git a/Examples/Complete/Animation/Blazor/wwwroot/style/style.css b/Examples/Complete/Animation/Blazor/wwwroot/style/style.css new file mode 100644 index 000000000..7ca2b4f8c --- /dev/null +++ b/Examples/Complete/Animation/Blazor/wwwroot/style/style.css @@ -0,0 +1,39 @@ +body { + padding: 0; + margin: 0; + overflow: hidden; + font-family: 'Lato', sans-serif; + font-weight: 700; + color: #8cb34f; +} + +#LoadingFinishedOverlay +{ + visibility: hidden; +} + +#LoadingOverlay, +#LoadingFinishedOverlay { + position: absolute; + width: 100%; + height: 100%; + z-index: 999; + padding: 0; + margin: auto 0; + background-color: white; +} + +#center p { + font-weight: 700; + text-transform: uppercase; + font-size: 1.25em; +} + +#center { + margin: 0; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; +} diff --git a/Examples/Complete/Animation/Core/Animation.cs b/Examples/Complete/Animation/Core/Animation.cs new file mode 100644 index 000000000..688090a47 --- /dev/null +++ b/Examples/Complete/Animation/Core/Animation.cs @@ -0,0 +1,143 @@ +using Fusee.Base.Core; +using Fusee.Engine.Common; +using Fusee.Engine.Core; +using Fusee.Engine.Core.Scene; +using Fusee.Engine.Gui; +using Fusee.Math.Core; +using System; +using System.Threading.Tasks; +using static Fusee.Engine.Core.Input; +using static Fusee.Engine.Core.Time; + +namespace Fusee.Examples.Animation.Core +{ + public class Animation : RenderCanvas + { + // angle variables + private static float _angleHorz = M.PiOver3, _angleVert = -M.PiOver6 * 0.5f, _angleVelHorz, _angleVelVert; + + private const float RotationSpeed = 7; + private const float Damping = 0.8f; + + private SceneContainer _rocketScene; + private SceneRendererForward _sceneRenderer; + + private const float ZNear = 1f; + private const float ZFar = 1000; + private readonly float _fovy = M.PiOver4; + + private SceneRendererForward _guiRenderer; + private SceneContainer _gui; + private SceneInteractionHandler _sih; + + private bool _keys; + + private async Task Load() + { + Console.WriteLine("Loading scene ..."); + + _gui = await FuseeGuiHelper.CreateDefaultGuiAsync(this, CanvasRenderMode.Screen, "FUSEE Simple Example"); + + // Create the interaction handler + _sih = new SceneInteractionHandler(_gui); + + // Load the rocket model + _rocketScene = await AssetStorage.GetAsync("testing.fus"); + + // Wrap a SceneRenderer around the model. + _sceneRenderer = new SceneRendererForward(_rocketScene); + _guiRenderer = new SceneRendererForward(_gui); + } + + public override async Task InitAsync() + { + await Load(); + await base.InitAsync(); + } + + // Init is called on startup. + public override void Init() + { + // Set the clear color for the backbuffer to white (100% intensity in all color channels R, G, B, A). + RC.ClearColor = new float4(1, 1, 1, 1); + } + + public override void Update() + { + // Mouse and keyboard movement + if (Keyboard.LeftRightAxis != 0 || Keyboard.UpDownAxis != 0) + { + _keys = true; + } + + if (Mouse.LeftButton) + { + _keys = false; + _angleVelHorz = -RotationSpeed * Mouse.XVel * DeltaTimeUpdate * 0.0005f; + _angleVelVert = -RotationSpeed * Mouse.YVel * DeltaTimeUpdate * 0.0005f; + } + else if (Touch != null && Touch.GetTouchActive(TouchPoints.Touchpoint_0)) + { + _keys = false; + var touchVel = Touch.GetVelocity(TouchPoints.Touchpoint_0); + _angleVelHorz = -RotationSpeed * touchVel.x * DeltaTimeUpdate * 0.0005f; + _angleVelVert = -RotationSpeed * touchVel.y * DeltaTimeUpdate * 0.0005f; + } + else + { + if (_keys) + { + _angleVelHorz = -RotationSpeed * Keyboard.LeftRightAxis * DeltaTimeUpdate; + _angleVelVert = -RotationSpeed * Keyboard.UpDownAxis * DeltaTimeUpdate; + } + else + { + var curDamp = (float)System.Math.Exp(-Damping * DeltaTimeUpdate); + _angleVelHorz *= curDamp; + _angleVelVert *= curDamp; + } + } + + _angleHorz += _angleVelHorz; + _angleVert += _angleVelVert; + } + + + // RenderAFrame is called once a frame + public override void RenderAFrame() + { + // Clear the backbuffer + RC.Clear(ClearFlags.Color | ClearFlags.Depth); + + RC.Viewport(0, 0, Width, Height); + + // Create the camera matrix and set it as the current ModelView transformation + var mtxRot = float4x4.CreateRotationX(_angleVert) * float4x4.CreateRotationY(_angleHorz); + var mtxCam = float4x4.LookAt(0, 2, -10, 0, 2, 0, 0, 1, 0); + + var view = mtxCam * mtxRot; + var perspective = float4x4.CreatePerspectiveFieldOfView(_fovy, (float)Width / Height, ZNear, ZFar); + var orthographic = float4x4.CreateOrthographic(Width, Height, ZNear, ZFar); + + // Render the scene loaded in Init() + RC.View = view; + RC.Projection = perspective; + _sceneRenderer.Render(RC); + + //Constantly check for interactive objects. + RC.View = float4x4.LookAt(0, 0, 1, 0, 0, 0, 0, 1, 0); + RC.Projection = orthographic; + if (!Mouse.Desc.Contains("Android")) + _sih.CheckForInteractiveObjects(RC, Mouse.Position, Width, Height); + if (Touch != null && Touch.GetTouchActive(TouchPoints.Touchpoint_0) && !Touch.TwoPoint) + { + _sih.CheckForInteractiveObjects(RC, Touch.GetPosition(TouchPoints.Touchpoint_0), Width, Height); + } + + _guiRenderer.Render(RC); + + // Swap buffers: Show the contents of the backbuffer (containing the currently rendered frame) on the front buffer. + Present(); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/Animation/Core/Assets/FuseeText.png b/Examples/Complete/Animation/Core/Assets/FuseeText.png new file mode 100644 index 000000000..af5ffb051 Binary files /dev/null and b/Examples/Complete/Animation/Core/Assets/FuseeText.png differ diff --git a/Examples/Complete/Animation/Core/Assets/Lato-Black.ttf b/Examples/Complete/Animation/Core/Assets/Lato-Black.ttf new file mode 100644 index 000000000..6848db0d1 Binary files /dev/null and b/Examples/Complete/Animation/Core/Assets/Lato-Black.ttf differ diff --git a/Examples/Complete/Animation/Core/Assets/RocketFus.fus b/Examples/Complete/Animation/Core/Assets/RocketFus.fus new file mode 100644 index 000000000..cb993b664 Binary files /dev/null and b/Examples/Complete/Animation/Core/Assets/RocketFus.fus differ diff --git a/Examples/Complete/Animation/Core/Assets/testing.fus b/Examples/Complete/Animation/Core/Assets/testing.fus new file mode 100644 index 000000000..eb1da9dea Binary files /dev/null and b/Examples/Complete/Animation/Core/Assets/testing.fus differ diff --git a/Examples/Complete/Animation/Core/Fusee.Examples.Animation.Core.csproj b/Examples/Complete/Animation/Core/Fusee.Examples.Animation.Core.csproj new file mode 100644 index 000000000..5c2c5e3dd --- /dev/null +++ b/Examples/Complete/Animation/Core/Fusee.Examples.Animation.Core.csproj @@ -0,0 +1,29 @@ + + + + net6.0 + $(BaseOutputPath)\Examples\Animation\Core\ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Complete/Animation/Desktop/Fusee.Examples.Animation.Desktop.csproj b/Examples/Complete/Animation/Desktop/Fusee.Examples.Animation.Desktop.csproj new file mode 100644 index 000000000..0b4dcfd49 --- /dev/null +++ b/Examples/Complete/Animation/Desktop/Fusee.Examples.Animation.Desktop.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + $(BaseOutputPath)\Examples\Animation\Desktop\ + + Exe + + + + + + + + + + + \ No newline at end of file diff --git a/Examples/Complete/Animation/Desktop/FuseeLogo.ico b/Examples/Complete/Animation/Desktop/FuseeLogo.ico new file mode 100644 index 000000000..dbdc5bc33 Binary files /dev/null and b/Examples/Complete/Animation/Desktop/FuseeLogo.ico differ diff --git a/Examples/Complete/Animation/Desktop/Main.cs b/Examples/Complete/Animation/Desktop/Main.cs new file mode 100644 index 000000000..1ddb55c6d --- /dev/null +++ b/Examples/Complete/Animation/Desktop/Main.cs @@ -0,0 +1,74 @@ +using Fusee.Base.Common; +using Fusee.Base.Core; +using Fusee.Base.Imp.Desktop; +using Fusee.Engine.Core; +using Fusee.Engine.Core.Scene; +using Fusee.Serialization; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; + +namespace Fusee.Examples.Animation.Desktop +{ + public class Animation + { + public static void Main() + { + // Inject Fusee.Engine.Base InjectMe dependencies + IO.IOImp = new Fusee.Base.Imp.Desktop.IOImp(); + + var fap = new Fusee.Base.Imp.Desktop.FileAssetProvider("Assets"); + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(Font), + DecoderAsync = async (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase)) return null; + return await Task.FromResult(new Font { _fontImp = new FontImp((Stream)storage) }); + }, + Decoder = (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase)) return null; + return new Font { _fontImp = new FontImp((Stream)storage) }; + }, + Checker = id => Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase) + }); + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(SceneContainer), + DecoderAsync = async (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase)) return null; + return await FusSceneConverter.ConvertFromAsync(ProtoBuf.Serializer.Deserialize((Stream)storage), id); + }, + Decoder = (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase)) return null; + return FusSceneConverter.ConvertFrom(ProtoBuf.Serializer.Deserialize((Stream)storage), id); + }, + Checker = id => Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase) + }); + + AssetStorage.RegisterProvider(fap); + + var app = new Core.Animation(); + + // Inject Fusee.Engine InjectMe dependencies (hard coded) + System.Drawing.Icon appIcon = System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); + app.CanvasImplementor = new Fusee.Engine.Imp.Graphics.Desktop.RenderCanvasImp(appIcon); + app.ContextImplementor = new Fusee.Engine.Imp.Graphics.Desktop.RenderContextImp(app.CanvasImplementor); + Input.AddDriverImp(new Fusee.Engine.Imp.Graphics.Desktop.RenderCanvasInputDriverImp(app.CanvasImplementor)); + Input.AddDriverImp(new Fusee.Engine.Imp.Graphics.Desktop.WindowsTouchInputDriverImp(app.CanvasImplementor)); + // app.InputImplementor = new Fusee.Engine.Imp.Graphics.Desktop.InputImp(app.CanvasImplementor); + // app.InputDriverImplementor = new Fusee.Engine.Imp.Input.Desktop.InputDriverImp(); + // app.VideoManagerImplementor = ImpFactory.CreateIVideoManagerImp(); + + app.InitApp(); + + // Start the app + app.Run(); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/BoneAnimation/Core/Assets/BoneFragment.frag b/Examples/Complete/BoneAnimation/Core/Assets/BoneFragment.frag new file mode 100644 index 000000000..ecbc130bc --- /dev/null +++ b/Examples/Complete/BoneAnimation/Core/Assets/BoneFragment.frag @@ -0,0 +1,16 @@ +#version 330 core +out vec4 FragColor; + +in vec4 oColor; // the input variable from the vertex shader (same name and same type) +in vec3 oNormal; +in vec4 oPos; + +void main() +{ + vec3 norm = normalize(oNormal); + vec3 lightDir = normalize(-oPos.xyz); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * vec3(1,1,1); + vec3 result = (0.1 + diffuse) * oColor.xyz; + FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/Examples/Complete/BoneAnimation/Core/Assets/BoneVertex.vert b/Examples/Complete/BoneAnimation/Core/Assets/BoneVertex.vert new file mode 100644 index 000000000..afc06aafe --- /dev/null +++ b/Examples/Complete/BoneAnimation/Core/Assets/BoneVertex.vert @@ -0,0 +1,49 @@ +#version 330 core + +in vec3 fuVertex; +in vec3 fuNormal; +in vec2 tex; +in vec4 fuBoneIndex; +in vec4 fuBoneWeight; +uniform mat4 FUSEE_MVP; +uniform mat4 FUSEE_MV; +uniform mat4 FUSEE_ITMV; + + +const int MAX_BONES = 100; +const int MAX_BONE_INFLUENCE = 4; +//const ivec4 fuBoneIndex = ivec4(0,0,0,0); +//const vec4 fuBoneWeight= vec4(0,1,0,0); +uniform mat4 finalBonesMatrices[MAX_BONES]; +uniform mat4 boneMatrices[MAX_BONES]; + +out vec4 oColor; +out vec3 oNormal; +out vec4 oPos; + +void main() +{ + vec4 totalPosition = vec4(0.0f); + for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++) + { + int idx = int(fuBoneIndex[i]); + vec4 localPosition = (boneMatrices[idx] * finalBonesMatrices[idx]) * vec4(fuVertex,1.0f); + totalPosition += localPosition * fuBoneWeight[i]; + //vec3 localNormal = mat3(finalBonesMatrices[fuBoneIndex[i]]) * fuNormal; + } + gl_Position = FUSEE_MVP * totalPosition; + oNormal = (FUSEE_ITMV * vec4(fuNormal,1)).xyz; + oPos = FUSEE_MV * totalPosition; + oColor = vec4(0,0, 1, 1); +} +//in vec3 aPos; // the position variable has attribute position 0 +// +//out vec4 vertexColor; // specify a color output to the fragment shader +// +//uniform vec3 bPos; +//uniform mat4 FUSEE_MVP; +//void main() +//{ +// gl_Position = FUSEE_MVP * vec4(aPos, 1.0); // see how we directly give a vec3 to vec4's constructor +// vertexColor = vec4(bPos, 1.0); // set the output variable to a dark-red color +//} \ No newline at end of file diff --git a/Examples/Complete/BoneAnimation/Core/Assets/FuseeIconTop32.png b/Examples/Complete/BoneAnimation/Core/Assets/FuseeIconTop32.png new file mode 100644 index 000000000..61f50dd9f Binary files /dev/null and b/Examples/Complete/BoneAnimation/Core/Assets/FuseeIconTop32.png differ diff --git a/Examples/Complete/BoneAnimation/Core/Assets/FuseeText.png b/Examples/Complete/BoneAnimation/Core/Assets/FuseeText.png new file mode 100644 index 000000000..af5ffb051 Binary files /dev/null and b/Examples/Complete/BoneAnimation/Core/Assets/FuseeText.png differ diff --git a/Examples/Complete/BoneAnimation/Core/Assets/Lato-Black.ttf b/Examples/Complete/BoneAnimation/Core/Assets/Lato-Black.ttf new file mode 100644 index 000000000..6848db0d1 Binary files /dev/null and b/Examples/Complete/BoneAnimation/Core/Assets/Lato-Black.ttf differ diff --git a/Examples/Complete/BoneAnimation/Core/Assets/Walk.fus b/Examples/Complete/BoneAnimation/Core/Assets/Walk.fus new file mode 100644 index 000000000..16297cf20 Binary files /dev/null and b/Examples/Complete/BoneAnimation/Core/Assets/Walk.fus differ diff --git a/Examples/Complete/BoneAnimation/Core/Bone.cs b/Examples/Complete/BoneAnimation/Core/Bone.cs new file mode 100644 index 000000000..f01a8462e --- /dev/null +++ b/Examples/Complete/BoneAnimation/Core/Bone.cs @@ -0,0 +1,212 @@ +using Fusee.Base.Core; +using Fusee.Engine.Common; +using Fusee.Engine.Core; +using Fusee.Engine.Core.Effects; +using Fusee.Engine.Core.Scene; +using Fusee.Engine.Gui; +using Fusee.Math.Core; +using Fusee.Xene; +using ProtoBuf.WellKnownTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static Fusee.Engine.Core.Input; +using static Fusee.Engine.Core.Time; + +namespace Fusee.Examples.BoneAnimation.Core +{ + [FuseeApplication(Name = "FUSEE Bone Animation Example", Description = "Quick bone animation example")] + public class Bone : RenderCanvas + { + // angle variables + private static float _angleHorz = M.PiOver3, _angleVert = -M.PiOver6 * 0.5f, _angleVelHorz, _angleVelVert; + + private const float RotationSpeed = 7; + private const float Damping = 0.8f; + private SceneRendererForward _sceneRenderer; + List bone = new List(); + Weight weight; + + private readonly Camera _mainCam = new(ProjectionMethod.Perspective, 0.1f, 100, M.PiOver4); + private ShaderEffect _renderEffect; + private Transform _mainCamTransform; + private SceneRendererForward _guiRenderer; + private SceneContainer _gui; + private SceneInteractionHandler _sih; + private SceneContainer _scene; + private bool _keys; + + //Shader + + private async Task Load() + { + Console.WriteLine("Loading scene ..."); + _scene = AssetStorage.Get("Walk.fus"); + SceneNode _armature = _scene.Children.FindNodes(node => node.Name == "Armature")?.FirstOrDefault(); + SceneNode _mesh = _scene.Children.FindNodes(node => node.Name == "A51_Alien2")?.FirstOrDefault(); + + weight = _mesh.GetComponent(); + List bi = new List(); + + foreach (SceneNode b in weight.Bones) + { + bone.Add(b.GetComponent().Matrix); + } + SceneNode cam = new() + { + Name = "MainCam", + Components = new List() + { + _mainCamTransform, + _mainCam + + } + }; + _scene.Children.Add(cam); + + string vs = await AssetStorage.GetAsync("BoneVertex.vert"); + string ps = await AssetStorage.GetAsync("BoneFragment.frag"); + _gui = await FuseeGuiHelper.CreateDefaultGuiAsync(this, CanvasRenderMode.Screen, "FUSEE Simple Example"); + + // Create the interaction handler + _sih = new SceneInteractionHandler(_gui); + //Load the rocket model + _renderEffect = new ShaderEffect( + new IFxParamDeclaration[] + { + new FxParamDeclaration + { + Name = UniformNameDeclarations.ModelViewProjection, Value = float4x4.Identity + }, + new FxParamDeclaration + { + Name = UniformNameDeclarations.ModelView, Value = float4x4.Identity + }, + new FxParamDeclaration + { + Name = UniformNameDeclarations.ITModelView, Value = float4x4.Identity + }, + new FxParamDeclaration + { + Name = "finalBonesMatrices[0]", Value = weight.BindingMatrices.ToArray() + }, + new FxParamDeclaration + { + Name = "boneMatrices[0]", Value = bone.ToArray() + }, + }, + new RenderStateSet + { + AlphaBlendEnable = false, + ZEnable = true + }, + vs, + ps); + _mesh.RemoveComponent(typeof(SurfaceEffect)); + _mesh.Components.Insert(1, _renderEffect); + //// Wrap a SceneRenderer around the model. + _sceneRenderer = new SceneRendererForward(_scene); + _guiRenderer = new SceneRendererForward(_gui); + } + + public override async Task InitAsync() + { + await Load(); + await base.InitAsync(); + } + + // Init is called on startup. + public override void Init() + { + // Set the clear color for the backbuffer to white (100% intensity in all color channels R, G, B, A). + + _mainCam.Viewport = new float4(0, 0, 100, 100); + _mainCam.BackgroundColor = new float4(1f, 1f, 1f, 1); + _mainCam.Layer = -1; + + _mainCamTransform = new Transform() + { + Rotation = float3.Zero, + Translation = new float3(0, 1, 10), + Scale = new float3(1, 1, 1) + }; + _angleHorz = -135; + } + + public override void Update() + { + // Mouse and keyboard movement + if (Keyboard.LeftRightAxis != 0 || Keyboard.UpDownAxis != 0) + { + _keys = true; + } + + if (Mouse.LeftButton) + { + _keys = false; + _angleVelHorz = -RotationSpeed * Mouse.XVel * DeltaTimeUpdate * 0.0005f; + _angleVelVert = -RotationSpeed * Mouse.YVel * DeltaTimeUpdate * 0.0005f; + } + else + { + if (_keys) + { + _angleVelHorz = -RotationSpeed * Keyboard.LeftRightAxis * DeltaTimeUpdate; + _angleVelVert = -RotationSpeed * Keyboard.UpDownAxis * DeltaTimeUpdate; + } + else + { + var curDamp = (float)System.Math.Exp(-Damping * DeltaTimeUpdate); + _angleVelHorz *= curDamp; + _angleVelVert *= curDamp; + } + } + if (!Mouse.Desc.Contains("Android")) + _sih.CheckForInteractiveObjects(RC, Mouse.Position, Width, Height); + if (Touch != null && Touch.GetTouchActive(TouchPoints.Touchpoint_0) && !Touch.TwoPoint) + { + _sih.CheckForInteractiveObjects(RC, Touch.GetPosition(TouchPoints.Touchpoint_0), Width, Height); + } + + _angleHorz += _angleVelHorz; + _angleVert += _angleVelVert; + } + + // RenderAFrame is called once a frame + + public override void RenderAFrame() + { + Dictionary x = new Dictionary(); + for (int i = 0; i < weight.Bones.Count; i++) + { + if (weight.Bones[i].Parent.GetComponent() == null) + { + bone[i] = weight.Bones[i].Parent.GetTransform().Matrix * weight.Bones[i].GetTransform().Matrix; + x[weight.Bones[i].Name] = weight.Bones[i].Parent.GetTransform().Matrix * weight.Bones[i].GetTransform().Matrix; + } + else + { + float4x4 parent = x[weight.Bones[i].Parent.Name]; + bone[i] = parent * weight.Bones[i].GetTransform().Matrix; + x[weight.Bones[i].Name] = parent * weight.Bones[i].GetTransform().Matrix; + } + } + _renderEffect.SetFxParam("boneMatrices[0]", bone.ToArray()); + // Clear the backbuffer + //bPos = new float3(1, 1, 0); + //_renderEffect.SetFxParam("bPos", bPos); + // Create the camera matrix and set it as the current ModelView transformation + _mainCamTransform.FpsView(_angleHorz, _angleVert, Keyboard.WSAxis, Keyboard.ADAxis, DeltaTime * 10); + + // Render the scene loaded in Init() + _sceneRenderer.Render(RC); + + //Constantly check for interactive objects. + _guiRenderer.Render(RC); + + // Swap buffers: Show the contents of the backbuffer (containing the currently rendered frame) on the front buffer. + Present(); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/BoneAnimation/Core/Fusee.Examples.BoneAnimation.Core.csproj b/Examples/Complete/BoneAnimation/Core/Fusee.Examples.BoneAnimation.Core.csproj new file mode 100644 index 000000000..4f744ea12 --- /dev/null +++ b/Examples/Complete/BoneAnimation/Core/Fusee.Examples.BoneAnimation.Core.csproj @@ -0,0 +1,31 @@ + + + + netstandard2.1;net6.0 + $(BaseOutputPath)\Examples\BoneAnimation\Core\ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Complete/BoneAnimation/Desktop/Fusee.Examples.BoneAnimation.Desktop.csproj b/Examples/Complete/BoneAnimation/Desktop/Fusee.Examples.BoneAnimation.Desktop.csproj new file mode 100644 index 000000000..4db5bd6c2 --- /dev/null +++ b/Examples/Complete/BoneAnimation/Desktop/Fusee.Examples.BoneAnimation.Desktop.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + $(BaseOutputPath)\Examples\BoneAnimation\Desktop\ + + Exe + + + + + + + + + diff --git a/Examples/Complete/BoneAnimation/Desktop/FuseeLogo.ico b/Examples/Complete/BoneAnimation/Desktop/FuseeLogo.ico new file mode 100644 index 000000000..dbdc5bc33 Binary files /dev/null and b/Examples/Complete/BoneAnimation/Desktop/FuseeLogo.ico differ diff --git a/Examples/Complete/BoneAnimation/Desktop/Main.cs b/Examples/Complete/BoneAnimation/Desktop/Main.cs new file mode 100644 index 000000000..e2041eab9 --- /dev/null +++ b/Examples/Complete/BoneAnimation/Desktop/Main.cs @@ -0,0 +1,75 @@ +using Fusee.Base.Common; +using Fusee.Base.Core; +using Fusee.Base.Imp.Desktop; +using Fusee.Engine.Common; +using Fusee.Engine.Core; +using Fusee.Engine.Core.Scene; +using Fusee.Serialization; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; + +namespace Fusee.Examples.BoneAnimation.Desktop +{ + public class Bone + { + public static void Main() + { + // Inject Fusee.Engine.Base InjectMe dependencies + IO.IOImp = new Fusee.Base.Imp.Desktop.IOImp(); + + var fap = new Fusee.Base.Imp.Desktop.FileAssetProvider("Assets"); + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(Font), + DecoderAsync = async (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase)) return null; + return await Task.FromResult(new Font { _fontImp = new FontImp((Stream)storage) }); + }, + Decoder = (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase)) return null; + return new Font { _fontImp = new FontImp((Stream)storage) }; + }, + Checker = id => Path.GetExtension(id).Contains("ttf", System.StringComparison.OrdinalIgnoreCase) + }); + fap.RegisterTypeHandler( + new AssetHandler + { + ReturnedType = typeof(SceneContainer), + DecoderAsync = async (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase)) return null; + return await FusSceneConverter.ConvertFromAsync(ProtoBuf.Serializer.Deserialize((Stream)storage), id); + }, + Decoder = (string id, object storage) => + { + if (!Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase)) return null; + return FusSceneConverter.ConvertFrom(ProtoBuf.Serializer.Deserialize((Stream)storage), id); + }, + Checker = id => Path.GetExtension(id).Contains("fus", System.StringComparison.OrdinalIgnoreCase) + }); + + AssetStorage.RegisterProvider(fap); + + var app = new Fusee.Examples.BoneAnimation.Core.Bone(); + + // Inject Fusee.Engine InjectMe dependencies (hard coded) + var icon = AssetStorage.Get("FuseeIconTop32.png"); + app.CanvasImplementor = new Fusee.Engine.Imp.Graphics.Desktop.RenderCanvasImp(icon); + app.ContextImplementor = new Fusee.Engine.Imp.Graphics.Desktop.RenderContextImp(app.CanvasImplementor); + Input.AddDriverImp(new Fusee.Engine.Imp.Graphics.Desktop.RenderCanvasInputDriverImp(app.CanvasImplementor)); + Input.AddDriverImp(new Fusee.Engine.Imp.Graphics.Desktop.WindowsTouchInputDriverImp(app.CanvasImplementor)); + // app.InputImplementor = new Fusee.Engine.Imp.Graphics.Desktop.InputImp(app.CanvasImplementor); + // app.InputDriverImplementor = new Fusee.Engine.Imp.Input.Desktop.InputDriverImp(); + // app.VideoManagerImplementor = ImpFactory.CreateIVideoManagerImp(); + + app.InitApp(); + + // Start the app + app.Run(); + } + } +} \ No newline at end of file diff --git a/Examples/Complete/Simple/Core/Fusee.Examples.Simple.Core.csproj b/Examples/Complete/Simple/Core/Fusee.Examples.Simple.Core.csproj index dd177d864..a0b1465eb 100644 --- a/Examples/Complete/Simple/Core/Fusee.Examples.Simple.Core.csproj +++ b/Examples/Complete/Simple/Core/Fusee.Examples.Simple.Core.csproj @@ -5,6 +5,9 @@ $(BaseOutputPath)\Examples\Simple\Core\ + + + diff --git a/Fusee.sln b/Fusee.sln index c64ba2dc1..f31873751 100644 --- a/Fusee.sln +++ b/Fusee.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.0.31612.314 +VisualStudioVersion = 17.2.32602.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Base", "Base", "{BF6B8C64-C111-450A-A8CA-297B75CDFEF8}" EndProject @@ -61,6 +61,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F98C2B41-CE68-465A-B091-9FDA9F74164D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + .filenesting.json = .filenesting.json .gitattributes = .gitattributes .gitignore = .gitignore BuildNuget.cmd = BuildNuget.cmd @@ -268,6 +269,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.PointCloudPo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.Deferred.Blazor", "Examples\Complete\Deferred\Blazor\Fusee.Examples.Deferred.Blazor.csproj", "{84C77C62-0721-4C6F-9789-88D5F9C98974}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Animation", "Animation", "{18FB22AC-37D4-40FF-94DB-F2B5F388B37B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.Animation.Desktop", "Examples\Complete\Animation\Desktop\Fusee.Examples.Animation.Desktop.csproj", "{2D1593FD-EEFA-4664-A3BC-016A140968A2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.Animation.Core", "Examples\Complete\Animation\Core\Fusee.Examples.Animation.Core.csproj", "{51364D5B-1C58-403D-93E6-ED4D168D0C95}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.Animation.Blazor", "Examples\Complete\Animation\Blazor\Fusee.Examples.Animation.Blazor.csproj", "{8751E127-907E-4DA5-8CCC-64D397BBF3D4}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.PointCloudPotree2.Wpf", "Examples\Complete\PointCloudPotree2\Wpf\Fusee.Examples.PointCloudPotree2.Wpf.csproj", "{35839EA8-889B-4C26-94CB-9DB309E9C9F3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Desktop", "Desktop", "{FA703895-434C-4ECF-8E0D-3145280DA2C6}" @@ -302,6 +311,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ImGui", "ImGui", "{D1853E25 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.PointCloudPotree2.ImGui", "Examples\Complete\PointCloudPotree2\ImGui\Fusee.Examples.PointCloudPotree2.ImGui.csproj", "{DF33EBD9-9CD9-409C-A10F-AC6FA8FA851D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BoneAnimation", "BoneAnimation", "{E18A18D5-D720-4E65-96FC-F3A5D9EBABA4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.BoneAnimation.Desktop", "Examples\Complete\BoneAnimation\Desktop\Fusee.Examples.BoneAnimation.Desktop.csproj", "{A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fusee.Examples.BoneAnimation.Core", "Examples\Complete\BoneAnimation\Core\Fusee.Examples.BoneAnimation.Core.csproj", "{97E64A42-1866-4191-B6A2-0D7075A39304}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1583,6 +1598,60 @@ Global {84C77C62-0721-4C6F-9789-88D5F9C98974}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU {84C77C62-0721-4C6F-9789-88D5F9C98974}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU {84C77C62-0721-4C6F-9789-88D5F9C98974}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Android|Any CPU.Build.0 = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Blazor|Any CPU.ActiveCfg = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Blazor|Any CPU.Build.0 = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Desktop|Any CPU.ActiveCfg = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Debug-Desktop|Any CPU.Build.0 = Debug|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release|Any CPU.Build.0 = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Android|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Android|Any CPU.Build.0 = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Blazor|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {2D1593FD-EEFA-4664-A3BC-016A140968A2}.Release-NuGet|Any CPU.Build.0 = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Android|Any CPU.Build.0 = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Blazor|Any CPU.ActiveCfg = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Blazor|Any CPU.Build.0 = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Desktop|Any CPU.ActiveCfg = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Debug-Desktop|Any CPU.Build.0 = Debug|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release|Any CPU.Build.0 = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Android|Any CPU.ActiveCfg = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Android|Any CPU.Build.0 = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Blazor|Any CPU.ActiveCfg = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {51364D5B-1C58-403D-93E6-ED4D168D0C95}.Release-NuGet|Any CPU.Build.0 = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Android|Any CPU.Build.0 = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Blazor|Any CPU.ActiveCfg = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Blazor|Any CPU.Build.0 = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Desktop|Any CPU.ActiveCfg = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Debug-Desktop|Any CPU.Build.0 = Debug|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release|Any CPU.Build.0 = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Android|Any CPU.ActiveCfg = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Android|Any CPU.Build.0 = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Blazor|Any CPU.ActiveCfg = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {8751E127-907E-4DA5-8CCC-64D397BBF3D4}.Release-NuGet|Any CPU.Build.0 = Release|Any CPU {35839EA8-889B-4C26-94CB-9DB309E9C9F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {35839EA8-889B-4C26-94CB-9DB309E9C9F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {35839EA8-889B-4C26-94CB-9DB309E9C9F3}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU @@ -1742,6 +1811,42 @@ Global {DF33EBD9-9CD9-409C-A10F-AC6FA8FA851D}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU {DF33EBD9-9CD9-409C-A10F-AC6FA8FA851D}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU {DF33EBD9-9CD9-409C-A10F-AC6FA8FA851D}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Android|Any CPU.Build.0 = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Blazor|Any CPU.ActiveCfg = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Blazor|Any CPU.Build.0 = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Desktop|Any CPU.ActiveCfg = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Debug-Desktop|Any CPU.Build.0 = Debug|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release|Any CPU.Build.0 = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Android|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Android|Any CPU.Build.0 = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Blazor|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99}.Release-NuGet|Any CPU.Build.0 = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Android|Any CPU.ActiveCfg = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Android|Any CPU.Build.0 = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Blazor|Any CPU.ActiveCfg = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Blazor|Any CPU.Build.0 = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Desktop|Any CPU.ActiveCfg = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Debug-Desktop|Any CPU.Build.0 = Debug|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release|Any CPU.Build.0 = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Android|Any CPU.ActiveCfg = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Android|Any CPU.Build.0 = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Blazor|Any CPU.ActiveCfg = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Blazor|Any CPU.Build.0 = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Desktop|Any CPU.ActiveCfg = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-Desktop|Any CPU.Build.0 = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-NuGet|Any CPU.ActiveCfg = Release|Any CPU + {97E64A42-1866-4191-B6A2-0D7075A39304}.Release-NuGet|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1859,6 +1964,10 @@ Global {72974011-C264-4D3D-979A-A4E750C5787A} = {B2C0746D-E5CC-45F1-BD88-3E0D5A2A7191} {76FE409A-DCA8-4714-8E95-4FE189751EE7} = {B2C0746D-E5CC-45F1-BD88-3E0D5A2A7191} {84C77C62-0721-4C6F-9789-88D5F9C98974} = {E7E4600F-D815-49F6-B79C-C456C87F01DC} + {18FB22AC-37D4-40FF-94DB-F2B5F388B37B} = {E68628DA-312F-4171-A5ED-08072B5CCA3C} + {2D1593FD-EEFA-4664-A3BC-016A140968A2} = {18FB22AC-37D4-40FF-94DB-F2B5F388B37B} + {51364D5B-1C58-403D-93E6-ED4D168D0C95} = {18FB22AC-37D4-40FF-94DB-F2B5F388B37B} + {8751E127-907E-4DA5-8CCC-64D397BBF3D4} = {18FB22AC-37D4-40FF-94DB-F2B5F388B37B} {35839EA8-889B-4C26-94CB-9DB309E9C9F3} = {B2C0746D-E5CC-45F1-BD88-3E0D5A2A7191} {FA703895-434C-4ECF-8E0D-3145280DA2C6} = {E364F712-2400-4D9F-8F40-8B5870086262} {6F281DDE-0376-40C4-9693-51C7CD2F49D4} = {E364F712-2400-4D9F-8F40-8B5870086262} @@ -1875,6 +1984,9 @@ Global {A1E5AC7E-97B2-4BED-AB75-780416E422A5} = {D1853E25-C274-44E7-8AB6-9BE3A4E61928} {D1853E25-C274-44E7-8AB6-9BE3A4E61928} = {E68628DA-312F-4171-A5ED-08072B5CCA3C} {DF33EBD9-9CD9-409C-A10F-AC6FA8FA851D} = {B2C0746D-E5CC-45F1-BD88-3E0D5A2A7191} + {E18A18D5-D720-4E65-96FC-F3A5D9EBABA4} = {E68628DA-312F-4171-A5ED-08072B5CCA3C} + {A9DE0D58-6A9B-44D2-B997-F5DDF967FE99} = {E18A18D5-D720-4E65-96FC-F3A5D9EBABA4} + {97E64A42-1866-4191-B6A2-0D7075A39304} = {E18A18D5-D720-4E65-96FC-F3A5D9EBABA4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC1775C2-579F-4897-8770-592966D00E3D} diff --git a/src/Engine/Common/AttributeLocations.cs b/src/Engine/Common/AttributeLocations.cs index 756fa8b2a..ac0b633b0 100644 --- a/src/Engine/Common/AttributeLocations.cs +++ b/src/Engine/Common/AttributeLocations.cs @@ -104,7 +104,7 @@ public static class AttributeLocations /// /// The binding index for the Bone Index buffer. /// - public static readonly int BoneIndexAttribAttribBindingIndex = BoneIndexAttribLocation; + public static readonly int BoneIndexAttribBindingIndex = BoneIndexAttribLocation; /// /// First attribute location for the instanced model matrix. diff --git a/src/Engine/Core/FusSceneConverter.cs b/src/Engine/Core/FusSceneConverter.cs index 8fb411317..5c5f1b979 100644 --- a/src/Engine/Core/FusSceneConverter.cs +++ b/src/Engine/Core/FusSceneConverter.cs @@ -7,6 +7,7 @@ using Fusee.Serialization; using Fusee.Serialization.V1; using Fusee.Xene; +using Fusee.Xirkit; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -145,12 +146,12 @@ internal class FusFileToSceneConvertV1 : Visitor private readonly SceneContainer _convertedScene; private readonly Stack _predecessors; private SceneNode _currentNode; - + protected AnimTimeline _animation; private readonly Dictionary _matMap; private readonly Dictionary _meshMap; private readonly ConcurrentDictionary _texMap; - private readonly Stack _boneContainers; - + private readonly Queue _boneContainers; + private readonly Dictionary _componentMap; private readonly Dictionary> _allEffects; /// @@ -169,14 +170,15 @@ internal FusFileToSceneConvertV1() _matMap = new Dictionary(); _meshMap = new Dictionary(); _texMap = new ConcurrentDictionary(); - _boneContainers = new Stack(); - + _boneContainers = new Queue(); + _componentMap = new Dictionary(); _allEffects = new Dictionary>(); } internal async Task Convert(FusScene sc) { _fusScene = sc; + //TODO: Convert all raw Components in _fusScene.Components upfront and store them in _componentMap Traverse(sc.Children); // During scene traversal we collect all effects but do not create them, yet @@ -272,7 +274,7 @@ public void ConvFusNode(FusNode snc) } /// - /// Converts the animation component. + /// Converts the animation component and adds the Xirkit Animation to it. /// [VisitMethod] public void ConvAnimation(FusAnimation a) @@ -281,10 +283,174 @@ public void ConvAnimation(FusAnimation a) { _currentNode.Components = new List(); } + Animation anim = new Animation(); + anim.animation.Animation(0); + int i = 0; + foreach (var animChnannelContainer in a.AnimationChannel) + { + // Type t = animTrackContainer.TypeId; + switch (animChnannelContainer.TypeId) + { + // if (typeof(int).IsAssignableFrom(t)) + case Serialization.V1.TypeId.Int: + { + var channel = new Channel(Lerp.IntLerp); + var test = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusTransform; + var testBone = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusBoneTransform; + var sceneComponent = new Transform(); + if (test != null) + { + sceneComponent = LookupTransform(test); + } + else if (testBone != null) + { + sceneComponent = LookupTransform(testBone); + } + else + { + sceneComponent = null; + } + foreach (Serialization.V1.FusAnimationKeyInt key in animChnannelContainer.KeyFrames) + { + channel.AddKeyframe(new Keyframe(key.Time, key.Value)); + } + anim.animation.AddAnimation(channel, sceneComponent, + animChnannelContainer.Property); + } + break; + //else if (typeof(float).IsAssignableFrom(t)) + case Serialization.V1.TypeId.Float: + { + var channel = new Channel(Lerp.FloatLerp); + var test = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusTransform; + var testBone = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusBoneTransform; + var sceneComponent = new Transform(); + if (test != null) + { + sceneComponent = LookupTransform(test); + } + else if (testBone != null) + { + sceneComponent = LookupTransform(testBone); + } + else + { + sceneComponent = null; + } + foreach (Serialization.V1.FusAnimationKeyFloat key in animChnannelContainer.KeyFrames) + { + channel.AddKeyframe(new Keyframe(key.Time, key.Value)); + } + anim.animation.AddAnimation(channel, sceneComponent, + animChnannelContainer.Property); + } + break; - // TODO: Test animation and refactor animation method from scene renderer to this converter + // else if (typeof(float2).IsAssignableFrom(t)) + case Serialization.V1.TypeId.Float2: + { + var channel = new Channel(Lerp.Float2Lerp); + var test = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusTransform; + var testBone = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusBoneTransform; + var sceneComponent = new Transform(); + if (test != null) + { + sceneComponent = LookupTransform(test); + } + else if (testBone != null) + { + sceneComponent = LookupTransform(testBone); + } + else + { + sceneComponent = null; + } + foreach (Serialization.V1.FusAnimationKeyFloat2 key in animChnannelContainer.KeyFrames) + { + channel.AddKeyframe(new Keyframe(key.Time, key.Value)); + } + anim.animation.AddAnimation(channel, sceneComponent, + animChnannelContainer.Property); + } + break; + // else if (typeof(float3).IsAssignableFrom(t)) + case Serialization.V1.TypeId.Float3: + { + Channel.LerpFunc lerpFunc = animChnannelContainer.LerpType switch + { + Serialization.V1.LerpType.Lerp => Lerp.Float3Lerp, + Serialization.V1.LerpType.Slerp => Lerp.Float3QuaternionSlerp, + _ => throw new System.InvalidOperationException( + "Unknown lerp type: animTrackContainer.LerpType: " + + (int)animChnannelContainer.LerpType),// C# 6throw new InvalidEnumArgumentException(nameof(animTrackContainer.LerpType), (int)animTrackContainer.LerpType, typeof(LerpType)); + // throw new InvalidEnumArgumentException("animTrackContainer.LerpType", (int)animTrackContainer.LerpType, typeof(LerpType)); + }; + var channel = new Channel(lerpFunc); + var test = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusTransform; + var testBone = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusBoneTransform; + var sceneComponent = new Transform(); + if (test != null) + { + sceneComponent = LookupTransform(test); + } + else if (testBone != null) + { + sceneComponent = LookupTransform(testBone); + } + else + { + sceneComponent = null; + } + foreach (Serialization.V1.FusAnimationKeyFloat3 key in animChnannelContainer.KeyFrames) + { + channel.AddKeyframe(new Keyframe(key.Time, key.Value)); + } + anim.animation.AddAnimation(channel, sceneComponent, + animChnannelContainer.Property); + } + break; + // else if (typeof(float4).IsAssignableFrom(t)) + case Serialization.V1.TypeId.Float4: + { + Channel.LerpFunc lerpFunc = animChnannelContainer.LerpType switch + { + Serialization.V1.LerpType.Lerp => Lerp.Float4Lerp, + Serialization.V1.LerpType.Slerp => Lerp.Float4QuaternionSlerp, + _ => throw new System.InvalidOperationException( + "Unknown lerp type: animTrackContainer.LerpType: " + + (int)animChnannelContainer.LerpType),// C# 6throw new InvalidEnumArgumentException(nameof(animTrackContainer.LerpType), (int)animTrackContainer.LerpType, typeof(LerpType)); + // throw new InvalidEnumArgumentException("animTrackContainer.LerpType", (int)animTrackContainer.LerpType, typeof(LerpType)); + }; + var channel = new Channel(lerpFunc); + var test = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusTransform; + var testBone = _fusScene.ComponentList[a.AnimationChannel[i].SceneComponent] as FusBoneTransform; + var sceneComponent = new Transform(); + if (test != null) + { + sceneComponent = LookupTransform(test); + } + else if (testBone != null) + { + sceneComponent = LookupTransform(testBone); + } + else + { + sceneComponent = null; + } + foreach (Serialization.V1.FusAnimationKeyFloat4 key in animChnannelContainer.KeyFrames) + { + channel.AddKeyframe(new Keyframe(key.Time, key.Value)); + } + anim.animation.AddAnimation(channel, sceneComponent, + animChnannelContainer.Property); + } + break; + //TODO : Add cases for each type + } + i++; + } + _currentNode.AddComponent(anim); } - /// /// Converts the XForm component. /// @@ -388,14 +554,55 @@ public void ConvTransform(FusTransform t) _currentNode.Components = new List(); } - _currentNode.Components.Add(new Transform + _currentNode.Components.Add(LookupTransform(t)); + } + [VisitMethod] + public void ConvBoneTransform(FusBoneTransform t) + { + if (_currentNode.Components == null) + { + _currentNode.Components = new List(); + } + + _currentNode.Components.Add(LookupTransform(t)); + } + + + + private Transform LookupTransform(FusTransform t) + { + SceneComponent sc; + if (_componentMap.TryGetValue(t, out sc)) + return (Transform)sc; + + Transform nt = new Transform { Translation = t.Translation, Name = t.Name, Active = t.Active, Rotation = t.Rotation, - Scale = t.Scale - }); + Scale = t.Scale, + }; + _componentMap[t] = nt; + return nt; + + } + private Transform LookupTransform(FusBoneTransform t) + { + SceneComponent sc; + if (_componentMap.TryGetValue(t, out sc)) + return (Transform)sc; + QuaternionF q = new QuaternionF(t.RotationQuaternion.xyz, t.RotationQuaternion.w); + Transform nt = new Transform + { + Translation = t.Translation, + Name = t.Name, + Active = t.Active, + RotationQuaternion = q + }; + _componentMap[t] = nt; + return nt; + } /// @@ -572,7 +779,6 @@ public void ConvMesh(FusMesh m) { _currentNode.Components = new List(); } - _currentNode.Components.Add(mesh); _meshMap.Add(m, mesh); @@ -624,7 +830,7 @@ public void ConvBone(FusBone bone) }); // Collect all bones, later, when a WeightComponent is found, we can set all Joints - _boneContainers.Push(_currentNode); + _boneContainers.Enqueue(_currentNode); } /// @@ -649,14 +855,14 @@ public void ConVWeight(FusWeight w) VertexWeights = new List() }; - var currentVertexWeights = wm.VertexWeights.Select(ww => new Scene.VertexWeight { JointIndex = ww.JointIndex, Weight = ww.Weight }).ToList(); + var currentVertexWeights = wm.VertexWeights.Select(ww => new Scene.VertexWeight { BoneIndex = ww.BoneIndex, Weight = ww.Weight }).ToList(); currentWeightList.VertexWeights.AddRange(currentVertexWeights); return currentWeightList; }).ToList(), BindingMatrices = w.BindingMatrices, - Joints = new List(), + Bones = new List(), Name = w.Name, Active = w.Active }; @@ -664,23 +870,72 @@ public void ConVWeight(FusWeight w) // check if we have bones if (_boneContainers.Count >= 1) { - if (weight.Joints == null) // initialize joint container + if (weight.Bones == null) // initialize joint container { - weight.Joints = new List(); + weight.Bones = new List(); } // set all bones found until this WeightComponent while (_boneContainers.Count != 0) { - weight.Joints.Add(_boneContainers.Pop()); + weight.Bones.Add(_boneContainers.Dequeue()); } - } + + } + if (weight.BindingMatrices.Count == 0) + { + Dictionary x = new Dictionary(); + foreach (SceneNode bone in weight.Bones) + { + if (bone.Parent.GetComponent() == null) + { + weight.BindingMatrices.Add((bone.Parent.GetTransform().Matrix * bone.GetTransform().Matrix).Invert()); + x[bone.Name] = bone.Parent.GetTransform().Matrix * bone.GetTransform().Matrix; + } + else + { + float4x4 parent = x[bone.Parent.Name]; + weight.BindingMatrices.Add((parent * bone.GetTransform().Matrix).Invert()); + x[bone.Name] = parent * bone.GetTransform().Matrix; + } + } + } _currentNode.Components.Add(weight); + AddWeightToMesh(_currentNode.GetMesh(), _currentNode.GetWeights()); } #endregion + /// + /// Adds bone indices and bone weights from a to a mesh. + /// + /// + /// + protected void AddWeightToMesh(Mesh mesh, Weight wc) + { + mesh.BoneIndices = new float4[wc.WeightMap.Count]; + mesh.BoneWeights = new float4[wc.WeightMap.Count]; + for (int i = 0; i < wc.WeightMap.Count; i++) + { + var weightList = wc.WeightMap[i]; + if (weightList.VertexWeights.Count > 4) + { + throw new ArgumentException("Invalid number of vertex weights."); + } + var boneIndex = float4.Zero; + var boneWeight = float4.Zero; + for (int j = 0; j < weightList.VertexWeights.Count; j++) + { + boneIndex[j] = weightList.VertexWeights[j].BoneIndex; + boneWeight[j] = weightList.VertexWeights[j].Weight; + } + + mesh.BoneIndices[i] = boneIndex; + mesh.BoneWeights[i] = boneWeight; + } + + } #region Make Effect private async Task LookupMaterial(FusMaterialStandard m) @@ -1026,7 +1281,7 @@ public void ConvSceneNode(SceneNode snc) /// Converts the animation component. /// [VisitMethod] - public void ConvAnimation(Animation a) + public void ConvAnimation(AnimTimeline a) { // TODO: Test animation and refactor animation method from scene renderer to this converter } @@ -1352,14 +1607,14 @@ public void ConVWeight(Weight w) VertexWeights = new List() }; - var currentVertexWeights = wm.VertexWeights.Select(ww => new Serialization.V1.VertexWeight { JointIndex = ww.JointIndex, Weight = ww.Weight }).ToList(); + var currentVertexWeights = wm.VertexWeights.Select(ww => new Serialization.V1.VertexWeight { BoneIndex = ww.BoneIndex, Weight = ww.Weight }).ToList(); currentWeightList.VertexWeights.AddRange(currentVertexWeights); return currentWeightList; }).ToList(), BindingMatrices = w.BindingMatrices, - Joints = new List(), + Bones = new List(), Name = w.Name, Active = w.Active }; @@ -1367,15 +1622,15 @@ public void ConVWeight(Weight w) // check if we have bones if (_boneContainers.Count >= 1) { - if (weight.Joints == null) // initialize joint container + if (weight.Bones == null) // initialize joint container { - weight.Joints = new List(); + weight.Bones = new List(); } // set all bones found until this WeightComponent while (_boneContainers.Count != 0) { - weight.Joints.Add(_boneContainers.Pop()); + weight.Bones.Add(_boneContainers.Pop()); } } diff --git a/src/Engine/Core/Scene/Animation.cs b/src/Engine/Core/Scene/Animation.cs index 2dc9e3e91..cd6327dad 100644 --- a/src/Engine/Core/Scene/Animation.cs +++ b/src/Engine/Core/Scene/Animation.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Fusee.Xirkit; +using System.Collections.Generic; namespace Fusee.Engine.Core.Scene { @@ -8,10 +9,9 @@ namespace Fusee.Engine.Core.Scene public class Animation : SceneComponent { /// - /// The animation tracks making up this animation data. - /// Each animation track controls a single value. + /// The Xirkit Animation thats going to be filled in the FusSceneConverter class /// - public List AnimationTracks = new(); + public AnimTimeline animation = new AnimTimeline(); } } \ No newline at end of file diff --git a/src/Engine/Core/Scene/AnimationTrack.cs b/src/Engine/Core/Scene/AnimationChannel.cs similarity index 98% rename from src/Engine/Core/Scene/AnimationTrack.cs rename to src/Engine/Core/Scene/AnimationChannel.cs index 89db8d899..649b35fbf 100644 --- a/src/Engine/Core/Scene/AnimationTrack.cs +++ b/src/Engine/Core/Scene/AnimationChannel.cs @@ -97,7 +97,7 @@ public enum LerpType /// Lerp, /// - /// Spherical interpolation. float3 are interpreted as Euler angles and interpolated in a shortest-path way using s. + /// Spherical interpolation. float3 are interpreted as Euler angles and interpolated in a shortest-path way using s. /// Slerp, } @@ -126,7 +126,7 @@ public enum TypeId /// /// Stores data about a single animation track (mainly a list of keyframes). /// - public class AnimationTrack + public class AnimationChannel { /// /// The scene component to be controlled by this animation track. diff --git a/src/Engine/Core/Scene/Transform.cs b/src/Engine/Core/Scene/Transform.cs index afcb5ce81..6dc77bcf2 100644 --- a/src/Engine/Core/Scene/Transform.cs +++ b/src/Engine/Core/Scene/Transform.cs @@ -232,6 +232,7 @@ public float3 Rotation } } + /// /// The scale (size) of the node. /// diff --git a/src/Engine/Core/Scene/Weight.cs b/src/Engine/Core/Scene/Weight.cs index 7a0eb5a5d..6562041bc 100644 --- a/src/Engine/Core/Scene/Weight.cs +++ b/src/Engine/Core/Scene/Weight.cs @@ -15,9 +15,9 @@ public class Weight : SceneComponent public List WeightMap = new(); /// - /// The joint objects controlling the geometry. + /// The bone objects controlling the geometry. /// - public List Joints = new(); + public List Bones = new(); /// /// The binding matrices defining the object's untransformed state. @@ -45,7 +45,7 @@ public struct VertexWeight /// /// The joint index controlling the vertex. /// - public int JointIndex; + public int BoneIndex; /// /// The weight (the influence) of the bone on the vertex's transformation. @@ -57,12 +57,12 @@ public struct VertexWeight /// /// /// - public override bool Equals(object obj) => obj is VertexWeight w && w.JointIndex.Equals(JointIndex) && w.Weight.Equals(Weight); + public override bool Equals(object obj) => obj is VertexWeight w && w.BoneIndex.Equals(BoneIndex) && w.Weight.Equals(Weight); /// /// Returns the hash code of one vertex weight /// - public override int GetHashCode() => (7 * JointIndex.GetHashCode()) + 5 * Weight.GetHashCode(); + public override int GetHashCode() => (7 * BoneIndex.GetHashCode()) + 5 * Weight.GetHashCode(); /// /// Check if two vertex weights are the same diff --git a/src/Engine/Core/SceneRendererForward.cs b/src/Engine/Core/SceneRendererForward.cs index 4ece30f9e..d4d79cc70 100644 --- a/src/Engine/Core/SceneRendererForward.cs +++ b/src/Engine/Core/SceneRendererForward.cs @@ -9,7 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Animation = Fusee.Xirkit.Animation; +using AnimTimeline = Fusee.Xirkit.AnimTimeline; namespace Fusee.Engine.Core { @@ -152,114 +152,6 @@ public SceneRendererForward(SceneContainer sc, RenderLayers renderLayer = Render PrePassVisitor = new PrePassVisitor(); IgnoreInactiveComponents = true; _state = new RendererState(); - InitAnimations(_sc); - } - - /// - /// Initializes animations, given as . - /// - /// The Scene, containing the Animations. - public void InitAnimations(SceneContainer sc) - { - _animation = new Animation(); - - foreach (var a in sc.Children.FindComponents(t => t.GetType() == typeof(Scene.Animation))) - { - var ac = (Scene.Animation)a; - if (ac.AnimationTracks != null) - { - foreach (var animTrackContainer in ac.AnimationTracks) - { - // Type t = animTrackContainer.TypeId; - switch (animTrackContainer.TypeId) - { - // if (typeof(int).IsAssignableFrom(t)) - case TypeId.Int: - { - var channel = new Channel(Lerp.IntLerp); - foreach (AnimationKeyInt key in animTrackContainer.KeyFrames) - { - channel.AddKeyframe(new Keyframe(key.Time, key.Value)); - } - _animation.AddAnimation(channel, animTrackContainer.SceneComponent, - animTrackContainer.Property); - } - break; - //else if (typeof(float).IsAssignableFrom(t)) - case TypeId.Float: - { - var channel = new Channel(Lerp.FloatLerp); - foreach (AnimationKeyFloat key in animTrackContainer.KeyFrames) - { - channel.AddKeyframe(new Keyframe(key.Time, key.Value)); - } - _animation.AddAnimation(channel, animTrackContainer.SceneComponent, - animTrackContainer.Property); - } - break; - - // else if (typeof(float2).IsAssignableFrom(t)) - case TypeId.Float2: - { - var channel = new Channel(Lerp.Float2Lerp); - foreach (AnimationKeyFloat2 key in animTrackContainer.KeyFrames) - { - channel.AddKeyframe(new Keyframe(key.Time, key.Value)); - } - _animation.AddAnimation(channel, animTrackContainer.SceneComponent, - animTrackContainer.Property); - } - break; - // else if (typeof(float3).IsAssignableFrom(t)) - case TypeId.Float3: - { - Channel.LerpFunc lerpFunc = animTrackContainer.LerpType switch - { - LerpType.Lerp => Lerp.Float3Lerp, - LerpType.Slerp => Lerp.Float3QuaternionSlerp, - _ => throw new InvalidOperationException( - "Unknown lerp type: animTrackContainer.LerpType: " + - (int)animTrackContainer.LerpType),// C# 6throw new InvalidEnumArgumentException(nameOf(animTrackContainer.LerpType), (int)animTrackContainer.LerpType, typeof(LerpType)); - // throw new InvalidEnumArgumentException("animTrackContainer.LerpType", (int)animTrackContainer.LerpType, typeof(LerpType)); - }; - var channel = new Channel(lerpFunc); - foreach (AnimationKeyFloat3 key in animTrackContainer.KeyFrames) - { - channel.AddKeyframe(new Keyframe(key.Time, key.Value)); - } - _animation.AddAnimation(channel, animTrackContainer.SceneComponent, - animTrackContainer.Property); - } - break; - // else if (typeof(float4).IsAssignableFrom(t)) - case TypeId.Float4: - { - var channel = new Channel(Lerp.Float4Lerp); - foreach (AnimationKeyFloat4 key in animTrackContainer.KeyFrames) - { - channel.AddKeyframe(new Keyframe(key.Time, key.Value)); - } - _animation.AddAnimation(channel, animTrackContainer.SceneComponent, - animTrackContainer.Property); - } - break; - //TODO : Add cases for each type - } - } - } - } - } - - /// - /// Handles animations. - /// - public void Animate() - { - if (_animation.ChannelBaseList.Count != 0) - { - // Set the animation time here! - _animation.Animate(Time.DeltaTime); - } } /// @@ -437,11 +329,11 @@ public void RenderBone(Bone bone) [VisitMethod] public void RenderWeight(Weight weight) { - var boneArray = new float4x4[weight.Joints.Count]; - for (var i = 0; i < weight.Joints.Count; i++) + var boneArray = new float4x4[weight.Bones.Count]; + for (var i = 0; i < weight.Bones.Count; i++) { var tmp = weight.BindingMatrices[i]; - boneArray[i] = _boneMap[weight.Joints[i]] * tmp; + boneArray[i] = _boneMap[weight.Bones[i]] * tmp; } //TODO: find a way to NOT push the bones into the RC because they are not "global" } @@ -746,64 +638,14 @@ public void RenderMesh(GpuMesh mesh) _rc.Render(mesh, true); } - /// - /// Adds bone indices and bone weights from a to a mesh. + /// If the Scene has an , it will be played. /// - /// - /// - protected void AddWeightToMesh(Mesh mesh, Weight wc) + /// The Animation. + [VisitMethod] + public void RenderAnimation(Scene.Animation anim) { - var boneWeights = new float4[wc.WeightMap.Count]; - var boneIndices = new float4[wc.WeightMap.Count]; - - // Iterate over the vertices - for (var iVert = 0; iVert < wc.WeightMap.Count; iVert++) - { - var vwl = wc.WeightMap[iVert]; - - // Security guard. Sometimes a vertex has no weight. This should be fixed in the model. But - // let's just not crash here. Instead of having a completely unweighted vertex, bind it to - // the root bone (index 0). - if (vwl == null) - vwl = new VertexWeightList(); - if (vwl.VertexWeights == null) - { - vwl.VertexWeights = - new List(new[] { new VertexWeight { JointIndex = 0, Weight = 1.0f } }); - } - - var nJoints = System.Math.Min(4, vwl.VertexWeights.Count); - for (var iJoint = 0; iJoint < nJoints; iJoint++) - { - // boneWeights[iVert][iJoint] = vwl.VertexWeights[iJoint].Weight; - // boneIndices[iVert][iJoint] = vwl.VertexWeights[iJoint].JointIndex; - // JSIL cannot handle float4 indexer. Map [0..3] to [x..z] by hand - switch (iJoint) - { - case 0: - boneWeights[iVert].x = vwl.VertexWeights[iJoint].Weight; - boneIndices[iVert].x = vwl.VertexWeights[iJoint].JointIndex; - break; - case 1: - boneWeights[iVert].y = vwl.VertexWeights[iJoint].Weight; - boneIndices[iVert].y = vwl.VertexWeights[iJoint].JointIndex; - break; - case 2: - boneWeights[iVert].z = vwl.VertexWeights[iJoint].Weight; - boneIndices[iVert].z = vwl.VertexWeights[iJoint].JointIndex; - break; - case 3: - boneWeights[iVert].w = vwl.VertexWeights[iJoint].Weight; - boneIndices[iVert].w = vwl.VertexWeights[iJoint].JointIndex; - break; - } - } - boneWeights[iVert].Normalize1(); - } - - mesh.BoneIndices = boneIndices; - mesh.BoneWeights = boneWeights; + anim.animation.Animate(Time.DeltaTime); } #endregion diff --git a/src/Engine/Core/ShaderShards/Header.cs b/src/Engine/Core/ShaderShards/Header.cs index 1c777f4be..bcf372689 100644 --- a/src/Engine/Core/ShaderShards/Header.cs +++ b/src/Engine/Core/ShaderShards/Header.cs @@ -42,7 +42,7 @@ public static class Header /// public static string DefineBones(Weight wc) { - return $"#define {BoneDefineVar} {wc.Joints.Count}"; + return $"#define {BoneDefineVar} {wc.Bones.Count}"; } } } \ No newline at end of file diff --git a/src/Engine/Imp/Graphics/Desktop/RenderContextImp.cs b/src/Engine/Imp/Graphics/Desktop/RenderContextImp.cs index 3591d21a3..3a28846a5 100644 --- a/src/Engine/Imp/Graphics/Desktop/RenderContextImp.cs +++ b/src/Engine/Imp/Graphics/Desktop/RenderContextImp.cs @@ -1587,10 +1587,10 @@ public void SetBoneIndices(IMeshImp mr, float4[] boneIndices) throw new ApplicationException("Create the VAO first!"); } GL.NamedBufferStorage(biBo, indicesBytes, boneIndices, BufferStorageFlags.DynamicStorageBit); - GL.VertexArrayVertexBuffer(vao, AttributeLocations.BoneIndexAttribAttribBindingIndex, biBo, IntPtr.Zero, sizeOfboneIndex); + GL.VertexArrayVertexBuffer(vao, AttributeLocations.BoneIndexAttribBindingIndex, biBo, IntPtr.Zero, sizeOfboneIndex); GL.VertexArrayAttribFormat(vao, AttributeLocations.BoneIndexAttribLocation, 4, VertexAttribType.Float, false, 0); - GL.VertexArrayAttribBinding(vao, AttributeLocations.BoneIndexAttribLocation, AttributeLocations.BoneIndexAttribAttribBindingIndex); + GL.VertexArrayAttribBinding(vao, AttributeLocations.BoneIndexAttribLocation, AttributeLocations.BoneIndexAttribBindingIndex); } else { @@ -1634,10 +1634,10 @@ public void SetBoneWeights(IMeshImp mr, float4[] boneWeights) int sizeOfBoneWeight = 4 * sizeof(float); int weightsBytes = boneWeights.Length * sizeOfBoneWeight; int wBo; - if (((MeshImp)mr).BoneIndexBufferObject == 0) + if (((MeshImp)mr).BoneWeightBufferObject == 0) { GL.CreateBuffers(1, out wBo); - ((MeshImp)mr).BoneIndexBufferObject = wBo; + ((MeshImp)mr).BoneWeightBufferObject = wBo; var vao = ((MeshImp)mr).VertexArrayObject; if (vao == 0) @@ -1645,14 +1645,14 @@ public void SetBoneWeights(IMeshImp mr, float4[] boneWeights) throw new ApplicationException("Create the VAO first!"); } GL.NamedBufferStorage(wBo, weightsBytes, boneWeights, BufferStorageFlags.DynamicStorageBit); - GL.VertexArrayVertexBuffer(vao, AttributeLocations.BoneIndexAttribAttribBindingIndex, wBo, IntPtr.Zero, sizeOfBoneWeight); + GL.VertexArrayVertexBuffer(vao, AttributeLocations.BoneWeightAttribBindingIndex, wBo, IntPtr.Zero, sizeOfBoneWeight); - GL.VertexArrayAttribFormat(vao, AttributeLocations.BoneIndexAttribLocation, 4, VertexAttribType.Float, false, 0); - GL.VertexArrayAttribBinding(vao, AttributeLocations.BoneIndexAttribLocation, AttributeLocations.BoneIndexAttribAttribBindingIndex); + GL.VertexArrayAttribFormat(vao, AttributeLocations.BoneWeightAttribLocation, 4, VertexAttribType.Float, false, 0); + GL.VertexArrayAttribBinding(vao, AttributeLocations.BoneWeightAttribLocation, AttributeLocations.BoneWeightAttribBindingIndex); } else { - wBo = ((MeshImp)mr).BoneIndexBufferObject; + wBo = ((MeshImp)mr).BoneWeightBufferObject; GL.GetNamedBufferParameter(wBo, BufferParameterName.BufferSize, out int size); if (size < weightsBytes) { @@ -1661,7 +1661,7 @@ public void SetBoneWeights(IMeshImp mr, float4[] boneWeights) var vao = ((MeshImp)mr).VertexArrayObject; GL.NamedBufferStorage(wBo, weightsBytes, boneWeights, BufferStorageFlags.DynamicStorageBit); - GL.VertexArrayVertexBuffer(((MeshImp)mr).VertexArrayObject, AttributeLocations.BoneIndexAttribLocation, wBo, IntPtr.Zero, sizeOfBoneWeight); + GL.VertexArrayVertexBuffer(((MeshImp)mr).VertexArrayObject, AttributeLocations.BoneWeightAttribLocation, wBo, IntPtr.Zero, sizeOfBoneWeight); } else diff --git a/src/Engine/Player/Core/Player.cs b/src/Engine/Player/Core/Player.cs index 8cf827777..565c46b09 100644 --- a/src/Engine/Player/Core/Player.cs +++ b/src/Engine/Player/Core/Player.cs @@ -210,7 +210,7 @@ public override void RenderAFrame() _mainCamPivot.RotationQuaternion = QuaternionF.FromEuler(_angleVert, _angleHorz, 0); - _sceneRenderer.Animate(); + _sceneRenderer.Render(RC); _guiRenderer.Render(RC); diff --git a/src/Math/Core/QuaternionF.cs b/src/Math/Core/QuaternionF.cs index 0d7965b36..136dc3e4d 100644 --- a/src/Math/Core/QuaternionF.cs +++ b/src/Math/Core/QuaternionF.cs @@ -30,6 +30,17 @@ public QuaternionF(float3 v, float w) _w = w; } + /// + /// Construct a new Quaternion from vector and w components + /// + /// The vector part + /// The w part + public QuaternionF(float4 v) + { + _xyz = v.xyz; + _w = v.w; + } + /// /// Construct a new Quaternion /// @@ -156,6 +167,11 @@ public float4 ToAxisAngle() return ToAxisAngle(this); } + public float4 ToFloat4() + { + return new float4(x, y, z, w); + } + /// /// Converts the quaternion into a rotation matrix. /// @@ -172,7 +188,9 @@ public float4x4 ToRotationMatrix() return ToRotationMatrix(this); } - #endregion ToAxisAngle + + + #endregion #region public float Length @@ -507,6 +525,51 @@ public static QuaternionF Slerp(QuaternionF q1, QuaternionF q2, float blend) #endregion Slerp #region Conversion + /// + /// Convert Euler angle to Quaternion rotation. + /// + /// Angle around x. + /// Angle around x. + /// Angle around x. + /// Whether the angles are in degrees or radians. + /// A Quaternion representing the euler angle passed to this method. + /// The euler angle is assumed to be in common aviation order where the y axis is up. Thus x is pitch/attitude, + /// y is yaw/heading, and z is roll/bank. In practice x is never out of [-PI/2, PI/2] while y and z may well be in + /// the range of [-PI, PI]. + /// + /// See also the euclideanspace website. + /// + public static QuaternionD FromEuler(double x, double y, double z, bool inDegrees = false) + { + if (inDegrees) + { + // Converts all degrees angles to radians. + x = M.DegreesToRadiansD(x); + y = M.DegreesToRadiansD(y); + z = M.DegreesToRadiansD(z); + } + + var q = new QuaternionD(); + + double3 s, c; + + s.x = System.Math.Sin(x * 0.5); + c.x = System.Math.Cos(x * 0.5); + + s.y = System.Math.Sin(y * 0.5); + c.y = System.Math.Cos(y * 0.5); + + s.z = System.Math.Sin(z * 0.5); + c.z = System.Math.Cos(z * 0.5); + + q.x = s.x * c.y * c.z + s.y * s.z * c.x; + q.y = s.y * c.x * c.z - s.x * s.z * c.y; + q.z = s.z * c.x * c.y - s.x * s.y * c.z; + q.w = c.x * c.y * c.z + s.y * s.z * s.x; + + return q; + } + /// /// Convert Euler angle to Quaternion rotation. /// diff --git a/src/Serialization/Properties/launchSettings.json b/src/Serialization/Properties/launchSettings.json new file mode 100644 index 000000000..e83f43d52 --- /dev/null +++ b/src/Serialization/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Fusee.Serialization": { + "commandName": "Project", + "commandLineArgs": "fusee help\r\n" + } + } +} \ No newline at end of file diff --git a/src/Serialization/V1/FusAnimation.cs b/src/Serialization/V1/FusAnimation.cs index e16dc3aed..2c5d8d712 100644 --- a/src/Serialization/V1/FusAnimation.cs +++ b/src/Serialization/V1/FusAnimation.cs @@ -14,6 +14,6 @@ public class FusAnimation : FusComponent /// Each animation track controls a single value. /// [ProtoMember(3)] - public List AnimationTracks = new(); + public List AnimationChannel = new(); } } \ No newline at end of file diff --git a/src/Serialization/V1/FusAnimationTrack.cs b/src/Serialization/V1/FusAnimationChannel.cs similarity index 96% rename from src/Serialization/V1/FusAnimationTrack.cs rename to src/Serialization/V1/FusAnimationChannel.cs index fb40dda86..1c6c6be92 100644 --- a/src/Serialization/V1/FusAnimationTrack.cs +++ b/src/Serialization/V1/FusAnimationChannel.cs @@ -118,7 +118,7 @@ public enum LerpType /// Lerp, /// - /// Spherical interpolation. float3 are interpreted as Euler angles and interpolated in a shortest-path way using s. + /// Spherical interpolation. float3 are interpreted as Euler angles and interpolated in a shortest-path way using s. /// Slerp, } @@ -148,13 +148,13 @@ public enum TypeId /// Stores data about a single animation track (mainly a list of keyframes) /// [ProtoContract] - public class FusAnimationTrack + public class FusAnimationChannel { /// - /// The scene component to be controlled by this animation track. + /// The index to the scene component to be controlled by this animation track. /// [ProtoMember(1)] - public FusComponent SceneComponent; + public int SceneComponent; /// /// The name to the property/field to control. May be a dot-separated path to a sub-item (e.g. "Transform.Position.x"). diff --git a/src/Serialization/V1/FusBoneTransform.cs b/src/Serialization/V1/FusBoneTransform.cs new file mode 100644 index 000000000..5ca8793d0 --- /dev/null +++ b/src/Serialization/V1/FusBoneTransform.cs @@ -0,0 +1,27 @@ +using Fusee.Math.Core; +using ProtoBuf; +using System.Collections.Generic; + +namespace Fusee.Serialization.V1 +{ + /// + /// Contains animation data. Generally, a list of animation tracks + /// + [ProtoContract] + public class FusBoneTransform : FusComponent + { + #region Payload + /// + /// The translation (position) of the node. + /// + [ProtoMember(1)] + public float3 Translation; + + /// + /// The rotation (orientation) of the node. + /// + [ProtoMember(2)] + public float4 RotationQuaternion; + #endregion + } +} \ No newline at end of file diff --git a/src/Serialization/V1/FusComponent.cs b/src/Serialization/V1/FusComponent.cs index f8c786b00..20ff672af 100644 --- a/src/Serialization/V1/FusComponent.cs +++ b/src/Serialization/V1/FusComponent.cs @@ -16,6 +16,7 @@ namespace Fusee.Serialization.V1 [ProtoInclude(105, typeof(FusAnimation))] [ProtoInclude(106, typeof(FusBone))] [ProtoInclude(107, typeof(FusCamera))] + [ProtoInclude(108, typeof(FusBoneTransform))] public class FusComponent : IComponent { /// diff --git a/src/Serialization/V1/FusWeight.cs b/src/Serialization/V1/FusWeight.cs index 8844a8fe3..ed47a60bb 100644 --- a/src/Serialization/V1/FusWeight.cs +++ b/src/Serialization/V1/FusWeight.cs @@ -18,10 +18,10 @@ public class FusWeight : FusComponent public List WeightMap = new(); /// - /// The joint objects controlling the geometry. + /// The bone objects controlling the geometry. /// [ProtoMember(2)] - public List Joints = new(); + public List Bones = new(); /// /// The binding matrices defining the object's untransformed state. @@ -38,10 +38,10 @@ public class FusWeight : FusComponent public struct VertexWeight { /// - /// The joint index controlling the vertex. + /// The Bone index controlling the vertex. /// [ProtoMember(1)] - public int JointIndex; + public int BoneIndex; /// /// The weight (the influence) of the bone on the vertex's transformation. diff --git a/src/Tools/BlenderScripts/addons/io_export_fus.zip b/src/Tools/BlenderScripts/addons/io_export_fus.zip new file mode 100644 index 000000000..6c1d775c4 Binary files /dev/null and b/src/Tools/BlenderScripts/addons/io_export_fus.zip differ diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/.vscode/launch.json b/src/Tools/BlenderScripts/addons/io_export_fus/.vscode/launch.json new file mode 100644 index 000000000..865502638 --- /dev/null +++ b/src/Tools/BlenderScripts/addons/io_export_fus/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Aktuelle Datei", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": false + } + ] +} \ No newline at end of file diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/BlenderVisitor.py b/src/Tools/BlenderScripts/addons/io_export_fus/BlenderVisitor.py index 8e2005337..7e6209dae 100644 --- a/src/Tools/BlenderScripts/addons/io_export_fus/BlenderVisitor.py +++ b/src/Tools/BlenderScripts/addons/io_export_fus/BlenderVisitor.py @@ -1,9 +1,11 @@ #from .FusSceneWriter import FusSceneWriter +import math +from threading import local from FusSceneWriter import FusSceneWriter import subprocess,os,sys, time from shutil import copyfile - +import traceback import bpy from bpy.props import ( StringProperty, @@ -12,11 +14,24 @@ ) from bpy_extras.io_utils import ( ExportHelper, + axis_conversion ) import bmesh import mathutils from math import * +try: + # Standard Python import + from proto import FusSerialization_pb2 as FusSer +except Exception: + try: + # The hard (blender) way + dir_path = os.path.dirname(os.path.realpath(__file__)) + dir_path = os.path.join(dir_path, 'proto') + sys.path.append(dir_path) + import FusSerialization_pb2 as FusSer + except Exception as ex: + print('Error importing "FusSerialization_pb2.py" from "' + dir_path + '"' + '\n' + ex) def GetPaths(filepath): @@ -42,16 +57,18 @@ def __init__(self): self.DoApplyScale = True self.DoRecalcOutside = True self.DoApplyModifiers = True - + self.DoBakeNLATracks = False + self.fps = bpy.context.scene.render.fps self.__matrixStack = [mathutils.Matrix.Identity(4)] self.__transformStack = [(mathutils.Vector((0, 0, 0)), mathutils.Quaternion(), mathutils.Vector((0, 0, 0)))] self.__fusWriter = FusSceneWriter() self.__textures = [] + self.__vertsPerMat = [] self.__visitors = { 'MESH': self.VisitMesh, + 'ARMATURE': self.VisitArmature, 'LIGHT': self.VisitLight, 'CAMERA': self.VisitCamera, - 'ARMATURE': self.VisitArmature, } def XFormPush(self, ob): @@ -119,9 +136,162 @@ def __AddTransform(self, isLightOrCamera = False): self.__fusWriter.AddTransform( (location.x, location.z, location.y), (-rot_eul.x, -rot_eul.z, -rot_eul.y), - (scale.x, scale.z, scale.y) + (scale.x, scale.z, scale.y), ) - + # Adds a NLA-Animation if one exists + def __AddAnimationIfPresent(self, ob): + try: + if(ob.animation_data != None): + selected_strips = [strip for strip in ob.animation_data.nla_tracks] + # Variables that store inserted F-Curves and Keyframes to delete them later. + newFC = [] + newKP = [] + + for strip in selected_strips: + for strips in strip.strips: + self.__fusWriter.BeginAnimation() + action = strips.action + # Create placeholder to see which/if axis is missing + loc = [None] * 3 + rotE = [None] * 3 + rotQ = [None] * 4 + scl = [None] * 3 + for af in action.fcurves: + data_path = af.data_path + if(data_path == "location"): + loc[af.array_index] = af + elif(data_path == "rotation_euler"): + rotE[af.array_index] = af + elif(data_path == "scale"): + scl[af.array_index] = af + # If the data_path is still empty because no one used i.e. Scale the list will be deleted + if(loc.count(None) == len(loc)): + loc.clear() + if(rotE.count(None) == len(rotE)): + rotE.clear() + if(scl.count(None) == len(scl)): + scl.clear() + + # Creates new F-Curves that don't exist yet + for idx in range(3): + if(len(loc) > 0): + if(loc[idx] == None): + locf = action.fcurves + loc[idx] = (locf.new(locf[0].data_path, index=idx, action_group=str(locf[0].group.name))) + newFC.append(loc[idx]) + + if(len(rotE) > 0): + if(rotE[idx] == None): + rotEf = action.fcurves + rotE[idx] = (rotEf.new(rotEf[0].data_path, index=idx, action_group=str(rotEf[0].group.name))) + newFC.append(rotE[idx]) + + if(len(scl) > 0): + if(scl[idx] == None): + sclf = action.fcurves + scl[idx] = (sclf.new("scale", index=idx, action_group=str(sclf[0].group.name))) + newFC.append(scl[idx]) + #Starts the AnimationTrack/AddKeyframe creation + if(len(loc) > 0): + newKP = self.createKP(loc, newKP, ob) + self.__fusWriter.BeginAnimationChannel("Translation", FusSer.Float3, FusSer.Lerp) + self.AddKeyframes(loc) + self.__fusWriter.EndAnimationChannel() + if(len(rotE) > 0): + newKP = self.createKP(rotE, newKP, ob) + self.__fusWriter.BeginAnimationChannel("Rotation", FusSer.Float3, FusSer.Lerp) + self.AddKeyframes(rotE) + self.__fusWriter.EndAnimationChannel() + if(not self.DoApplyScale): + if(len(scl) > 0): + newKP = self.createKP(scl, newKP, ob) + self.__fusWriter.BeginAnimationChannel("Scale", FusSer.Float3, FusSer.Lerp) + self.AddKeyframes(scl) + self.__fusWriter.EndAnimationChannel() + + + self.DeleteCreatedKPFC(action, newKP, newFC) + self.__fusWriter.EndAnimation() + except Exception: + print(traceback.format_exc()) + selected_strips = [] + self.__fusWriter.EndAnimation() + + def AddKeyframes(self, _fcurve): + # For the number of Keyframes go through the FCurves and create a tuple from them + if(_fcurve[0].data_path == "rotation_euler"): + for i in range(len(_fcurve[0].keyframe_points)): + keyframe = [] + for fc in _fcurve: + keyframe.append(-(fc.keyframe_points[i].co[1])) + self.__fusWriter.AddKeyframe(_fcurve[0].keyframe_points[i].co[0] / self.fps, (keyframe.x, keyframe.z, keyframe.y)) + else: + for i in range(len(_fcurve[0].keyframe_points)): + keyframe = [] + for fc in _fcurve: + keyframe.append(fc.keyframe_points[i].co[1]) + self.__fusWriter.AddKeyframe(_fcurve[0].keyframe_points[i].co[0] / self.fps, (keyframe.x, keyframe.z, keyframe.y)) + + + def DeleteCreatedKPFC(self, _action, _newKP, _newFC): + # Variable for deletion + kpidx = 0 + preKP = None + preFC = None + # Sort the FCurves by data_path and array_index + _newKP = sorted(_newKP, key=lambda k: (k[0].data_path, k[0].array_index)) + + for idx in range(len(_newKP)): + if(_newKP[idx][0].array_index != preKP or _newKP[idx][0].data_path != preFC): + kpidx = 0 + else: + kpidx += 1 + # Find keyframes on the FCurve and remove them + _newKP[idx][0].keyframe_points.remove(_newKP[idx][0].keyframe_points[(_newKP[idx][1]) - kpidx]) + preKP = _newKP[idx][0].array_index + preFC = _newKP[idx][0].data_path + + for deleteFC in _newFC: + # Remove created FCurves + _action.fcurves.remove(deleteFC) + + def createKP(self, fcs, newKP, ob): + # Find the earliest Keyframe frame + firstFC = None + for fc in fcs: + if(len(fc.keyframe_points)!= 0): + if(firstFC == None): + firstFC = fc.keyframe_points[0].co[0] + elif(firstFC > fc.keyframe_points[0].co[0]): + firstFC = fc.keyframe_points[0].co[0] + + for fc in fcs: + for cfc in fcs: + # Create the first Keyframe if it doesn't exist or the Keyframe frame is later than the firstFC + if(len(cfc.keyframe_points)!= 0): + if(cfc.keyframe_points[0].co[0] != firstFC): + cfc.keyframe_points.insert(frame=firstFC, value=cfc.evaluate(firstFC)) + newKP.append([cfc, 0]) + + else: + + cfc.keyframe_points.insert(frame=firstFC, value=getattr(ob, cfc.data_path)[cfc.array_index]) + newKP.append([cfc, 0]) + + # Create the remaining Keyframes + if(cfc != fc): + for kpi in range(len(fc.keyframe_points)): + if(len(cfc.keyframe_points) > kpi): + if(cfc.keyframe_points[kpi].co[0] != fc.keyframe_points[kpi].co[0]): + cfc.keyframe_points.insert(frame=fc.keyframe_points[kpi].co[0], value=cfc.evaluate(fc.keyframe_points[kpi].co[0])) + newKP.append([cfc, kpi]) + print(str(cfc.array_index) + " " + str(cfc.keyframe_points[kpi].co[0]) + " " + str(fc.array_index) + " " + str(fc.keyframe_points[kpi].co[0])) + else: + cfc.keyframe_points.insert(frame=fc.keyframe_points[kpi].co[0], value=cfc.evaluate(fc.keyframe_points[kpi].co[0])) + newKP.append([cfc, kpi]) + + return newKP + def __GetProcessedBMesh(self, obj): """Create a modifier-applied, normal-flipped, scale-normalized, triangulated BMesh from the Blender mesh object passed. Call result.free() and del result after using the returned bmesh.""" @@ -434,6 +604,7 @@ def __AddDefaultMaterial(self): def VisitMesh(self, mesh): self.__fusWriter.AddChild(mesh.name) self.__AddTransform() + self.__AddAnimationIfPresent(mesh) if self.DoApplyScale: scale = self.XFormGetTOSTransform()[2] @@ -443,11 +614,10 @@ def VisitMesh(self, mesh): materialCount = max(1, len(mesh.material_slots)) - vertsPerMat = [] - + self.__vertsPerMat.clear() # for iMaterial in range(materialCount): - vertsPerMat.append([]) + self.__vertsPerMat.append([]) bm = self.__GetProcessedBMesh(mesh) @@ -462,9 +632,11 @@ def VisitMesh(self, mesh): # print("Triangle with material ", f.material_index) for fl in f.loops: vertex = fl.vert.co + orginalIndex = fl.vert.index normal = fl.vert.normal if f.smooth else f.normal uv = fl[uv_layer].uv if uv_layer is not None else mathutils.Vector((0, 0)) - vertsPerMat[f.material_index].append(( + self.__vertsPerMat[f.material_index].append(( + orginalIndex, (vertex[0], vertex[2], vertex[1]), (normal[0], normal[2], normal[1]), (uv[0], uv[1]))) @@ -476,7 +648,6 @@ def VisitMesh(self, mesh): bm.free() del bm # - # for iMaterial in range(materialCount): @@ -497,10 +668,10 @@ def VisitMesh(self, mesh): else: self.__AddDefaultMaterial() - nVertsTotal = len(vertsPerMat[iMaterial]) + nVertsTotal = len(self.__vertsPerMat[iMaterial]) iVert = 0 iChunk = 0 - + orgiIdx = [None]; while iVert < nVertsTotal: meshName = mesh.data.name + '_mat' + str(iMaterial) + '_chnk' + str(iChunk) + appliedScaleStr if iChunk > 0: @@ -510,25 +681,29 @@ def VisitMesh(self, mesh): if self.__fusWriter.TryReferenceMesh(meshName): iVert = iVert + self.__fusWriter.GetReferencedMeshTriVertCount(meshName) else: - vert = vertsPerMat[iMaterial][iVert] - self.__fusWriter.BeginMesh( - vert[0], # Vertex - vert[1], # Normal - vert[2], # UV + vert = self.__vertsPerMat[iMaterial][iVert] + idx = self.__fusWriter.BeginMesh( + vert[0], + vert[1], # Vertex + vert[2], # Normal + vert[3], # UV name=meshName ) + orgiIdx[0] = idx iVert = iVert + 1 iVertPerChunk = 1 while self.__fusWriter.MeshHasCapacity() and iVert < nVertsTotal: - vert = vertsPerMat[iMaterial][iVert] - self.__fusWriter.AddVertex( - vert[0], # Vertex - vert[1], # Normal - vert[2] # UV + vert = self.__vertsPerMat[iMaterial][iVert] + idx = self.__fusWriter.AddVertex( + vert[0], + vert[1], # Vertex + vert[2], # Normal + vert[3], # UV ) iVert = iVert + 1 iVertPerChunk = iVertPerChunk + 1 - + if(idx > -1): + orgiIdx.append(idx) self.__fusWriter.EndMesh() if iChunk > 0: @@ -539,6 +714,10 @@ def VisitMesh(self, mesh): if materialCount > 1: self.__fusWriter.Pop() # + for modifiers in mesh.modifiers: + if(modifiers.type == "ARMATURE"): + armature = mesh.parent + self.WeightGen(orgiIdx, mesh, armature) def VisitLight(self, light): @@ -602,8 +781,188 @@ def VisitCamera(self, camera): def VisitArmature(self, armature): self.__fusWriter.AddChild(armature.name) - print('Armature: ' + armature.name) + self.__AddTransform() + for bone in armature.pose.bones: + if(bone.parent == None): + self.TraverseBones(bone) + print('Armature: ' + armature.name) + self.__AddBoneAnimationIfPresent(armature) + + def TraverseBones(self, bones): + self.__fusWriter.Push() + self.__fusWriter.AddChild(bones.name) + self.AddBoneTransform(bones, bones.parent) + self.__fusWriter.Bone() + self.__fusWriter.Push() + self.CreateBoneMesh(bones) + self.__fusWriter.Pop() + if(len(bones.children) > 0): + self.TraverseBonesChildren(bones) + self.__fusWriter.Pop() + + def TraverseBonesChildren(self, bones): + for bone in bones.children: + self.__fusWriter.Push() + self.__fusWriter.AddChild(bone.name) + self.AddBoneTransform(bone, bone.parent) + self.__fusWriter.Bone() + self.__fusWriter.Push() + self.CreateBoneMesh(bone) + self.__fusWriter.Pop() + if(len(bone.children) > 0): + self.TraverseBonesChildren(bone) + self.__fusWriter.Pop() + + def AddBoneTransform(self, bone, boneparent): + bone_quaternion = bone.matrix.to_quaternion() + if(boneparent is None): + bone_quaternion = bone_quaternion.inverted() + self.__fusWriter.AddBoneTransform( + (bone.bone.head_local.x, bone.bone.head_local.z, bone.bone.head_local.y), + + ((bone_quaternion.x , + bone_quaternion.z, + bone_quaternion.y, + bone_quaternion.w)), + bone.name + ) + else: + bone_parent_quaternion = boneparent.matrix.to_quaternion() + bone_parent_quaternion_dif = bone_parent_quaternion.rotation_difference(bone_quaternion).inverted() + if(bone.bone.use_connect is False): + boneloc = mathutils.Vector((bone.bone.head.x , + bone.bone.head.z, + boneparent.length + bone.bone.head.y)) + else: + + boneloc = mathutils.Vector((0,0,boneparent.length)) + self.__fusWriter.AddBoneTransform( + + (boneloc.x, boneloc.y, boneloc.z), + + ((bone_parent_quaternion_dif.x , + bone_parent_quaternion_dif.z, + bone_parent_quaternion_dif.y, + bone_parent_quaternion_dif.w)), + bone.name + ) + + def WeightGen(self, originalIndexList, mesh, armature): + self.__fusWriter.Weight() + for v in originalIndexList: + self.__fusWriter.VertexWeightList() + idx = 0 + for grp in mesh.vertex_groups: + if idx < 4: + try: + weight = grp.weight(v) + self.__fusWriter.VertexWeight(grp.index,weight) + idx += 1 + except: + pass def VisitUnknown(self, ob): print('WARNING: Type: ' + ob.type + ' of object ' + ob.name + ' not handled ') + def __AddBoneAnimationIfPresent(self, ob): + try: + nla_tracks = [nla_track for nla_track in ob.animation_data.nla_tracks] + for nla_strips in nla_tracks: + if(not nla_strips.mute): + + for nla_strip in nla_strips.strips: + self.__fusWriter.BeginAnimation() + action = nla_strip.action + frames = self.OrderKeyframes(nla_strip) + bpy.data.scenes['Scene'].frame_set(int(frames[0])) + old_data_path = "" + for af in action.fcurves: + if(old_data_path != af.data_path): + old_data_path = af.data_path + bone_name = af.data_path.rpartition('"')[0].rpartition('"')[2] + data_path = af.data_path.rpartition('.')[2] + if(data_path == "location"): + self.__fusWriter.BeginAnimationChannel(bone_name, "Translation", FusSer.Float3, FusSer.Lerp) + for frame in frames: + frame = int(frame) + bpy.data.scenes['Scene'].frame_set(frame) + bone = bone_name + bone = ob.pose.bones[bone] + if(bone.parent == None): + position = ob.matrix_basis @ bone.location + bone_positon = (bone.bone.head_local.x + + position.x, bone.bone.head_local.z + + position.y , bone.bone.head_local.y + + position.z) + + else: + if(bone.bone.use_connect is False): + bone_positon = mathutils.Vector((0 + bone.bone.head.x, + 0 +bone.bone.head.z, + bone.parent.length + bone.bone.head.y)) + else: + bone_positon = mathutils.Vector((0,0,bone.parent.length)) + self.__fusWriter.AddKeyframe(frame / self.fps, bone_positon) + self.__fusWriter.EndAnimationChannel() + elif("rotation" in data_path): + self.__fusWriter.BeginAnimationChannel(bone_name, "RotationQuaternion", FusSer.Float4, FusSer.Slerp) + for frame in frames: + frame = int(frame) + bpy.data.scenes['Scene'].frame_set(frame) + bone = bone_name + bone = ob.pose.bones[bone] + bone_quaternion = bone.matrix.to_quaternion() + if(bone.parent is not None): + bone_parent_quaternion = bone.parent.matrix.to_quaternion().rotation_difference(bone.matrix.to_quaternion()) + elif(bone.parent is None): + bone_parent_quaternion = bone_quaternion + rot = bone_parent_quaternion.inverted() + self.__fusWriter.AddKeyframe(frame / self.fps, (rot.x, rot.z, rot.y, rot. w)) + self.__fusWriter.EndAnimationChannel() + self.__fusWriter.EndAnimation() + bpy.data.scenes['Scene'].frame_set(int(frames[0])) + except Exception: + print(traceback.format_exc()) + selected_strips = [] + self.__fusWriter.EndAnimation() + if('frames' in locals()): + bpy.data.scenes['Scene'].frame_set(int(frames[0])) + def OrderKeyframes(self, nla_strip): + action = nla_strip.action + kps = [] + for af in action.fcurves: + for kp in af.keyframe_points: + kps.append(kp.co[0]) + kps = list(set(kps)) + kps.sort() + return kps + + def CreateBoneMesh(self, bone): + mat = mathutils.Matrix([(1.0, 0.0, 0.0, 0.0), + (0.0, 0.0, 1.0, bone.length / 2), + (0.0, -1.0, 0, 0), + (0.0, 0.0, 0.0, 1.0)]) + bm = bmesh.new() + bmesh.ops.create_cone( + bm, + cap_ends = True, + cap_tris = False, + segments = 4, + radius1 = 0.05, + radius2 = 0.02, + depth = bone.length, + matrix = mat, + calc_uvs = True + ) + mesh_name="mesh_" + bone.name + mesh_data= bpy.data.meshes.new(mesh_name) + bm.to_mesh(mesh_data) + bm.free + del bm + mesh_obj = bpy.data.objects.new(mesh_data.name, mesh_data) + bpy.context.collection.objects.link(mesh_obj) + mesh = bpy.context.collection.objects[mesh_obj.name] + armature = bone.id_data + mesh.matrix_world = armature.matrix_world + self.TraverseOb(mesh) + bpy.data.objects.remove(mesh) \ No newline at end of file diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/FusSceneWriter.py b/src/Tools/BlenderScripts/addons/io_export_fus/FusSceneWriter.py index 62f8ab3e4..9e5a5c66a 100644 --- a/src/Tools/BlenderScripts/addons/io_export_fus/FusSceneWriter.py +++ b/src/Tools/BlenderScripts/addons/io_export_fus/FusSceneWriter.py @@ -37,6 +37,15 @@ def __init__(self): self.__curComponent = None self.__curMaterial = None self.__curMesh = None + self.__curAnimation = None + self.__curAnimationChannel = None + self.__curWeightMap = None + self.__curVertexWeightList = None + self.__curBone = None + self.__typeId = None + self.__inx = 0 + self.__vertIndex = [None] + self.__boneDict = {} def CurrentNode(self): """Returns the current node (or None if AddChild was not yet called on the current child list).""" @@ -101,7 +110,125 @@ def AddTransform(self, translation, rotation, scale, name = ""): xform.Rotation.z = rotation[2] xform.Scale.x = scale[0] xform.Scale.y = scale[1] - xform.Scale.z = scale[2] + xform.Scale.z = scale[2] + self.__inx = inx + + def AddBoneTransform(self, translation, rotation, boneName, name = ""): + """Adds a transform component to the current child node.""" + comp, inx = self.AddComponent(name) + comp.Name = name + xform = comp.FusBoneTransform + xform.Translation.x = translation[0] + xform.Translation.y = translation[1] + xform.Translation.z = translation[2] + xform.RotationQuaternion.x = rotation[0] + xform.RotationQuaternion.y = rotation[1] + xform.RotationQuaternion.z = rotation[2] + xform.RotationQuaternion.w = rotation[3] + self.__boneDict[boneName] = inx +#### ANIMATION COMPONENT #### + def BeginAnimation(self, name = ""): + if self.__curComponent == None: + self.__curComponent, inx = self.AddComponent(name) + self.__curAnimation = self.__curComponent.FusAnimation + + def BeginAnimationChannel(self, property, typeId, lerpType): + if self.__curAnimation != None: + if self.__curAnimationChannel == None: + self.__curAnimationChannel = self.__curAnimation.AnimationChannel.add() + self.__curAnimationChannel.SceneComponent = self.__inx + self.__curAnimationChannel.Property = property + self.__curAnimationChannel.TypeId = typeId + self.__typeId = typeId + self.__curAnimationChannel.LerpType = lerpType + def BeginAnimationChannel(self, boneName, property, typeId, lerpType): + if self.__curAnimation != None: + if self.__curAnimationChannel == None: + self.__curAnimationChannel = self.__curAnimation.AnimationChannel.add() + self.__curAnimationChannel.SceneComponent = self.__boneDict[boneName] + self.__curAnimationChannel.Property = property + self.__curAnimationChannel.TypeId = typeId + self.__typeId = typeId + self.__curAnimationChannel.LerpType = lerpType + + def AddKeyframe(self, keyTime, keyValue): + if self.__curAnimationChannel != None: + keyFrame = self.__curAnimationChannel.KeyFrames.add() + keyFrame.Time = keyTime + if(self.__typeId == FusSer.Double): + keyFrame.FusAnimationKeyDouble.Value = keyValue + elif(self.__typeId == FusSer.Int): + keyFrame.FusAnimationKeyInt.Value = keyValue + elif(self.__typeId == FusSer.Float): + keyFrame.FusAnimationKeyFloat.Value = keyValue + elif(self.__typeId == FusSer.Float2): + keyFrame.FusAnimationKeyFloat2.Value.x = keyValue[0] + keyFrame.FusAnimationKeyFloat2.Value.y = keyValue[1] + elif(self.__typeId == FusSer.Float3): + keyFrame.FusAnimationKeyFloat3.Value.x = keyValue[0] + keyFrame.FusAnimationKeyFloat3.Value.y = keyValue[1] + keyFrame.FusAnimationKeyFloat3.Value.z = keyValue[2] + elif(self.__typeId == FusSer.Float4): + keyFrame.FusAnimationKeyFloat4.Value.x = keyValue[0] + keyFrame.FusAnimationKeyFloat4.Value.y = keyValue[1] + keyFrame.FusAnimationKeyFloat4.Value.z = keyValue[2] + keyFrame.FusAnimationKeyFloat4.Value.w = keyValue[3] + elif(self.__typeId == FusSer.Bool): + keyFrame.FusAnimationKeyBool.Value = keyValue + else: + print('No fitting TypeId found') + + def EndAnimationChannel(self): + self.__curAnimationChannel = None + + def EndAnimation(self): + self.__curAnimation = None + self.__curComponent = None + + def Bone(self, name = ""): + comp, inx = self.AddComponent(name) + curBone = comp.FusBone + curBone.Name = name + + def Weight(self, name = ""): + if self.__curComponent == None: + self.__curComponent,inx = self.AddComponent(name) + self.__curWeightMap = self.__curComponent.FusWeight + self.__curComponent = None + + def BindingMatrices(self, matrix): + if self.__curWeightMap != None: + bM = self.__curWeightMap.BindingMatrices.add() + bM.Row1.x = matrix[0][0] + bM.Row1.y = matrix[0][1] + bM.Row1.z = matrix[0][2] + bM.Row1.w = matrix[0][3] + + bM.Row2.x = matrix[1][0] + bM.Row2.y = matrix[1][1] + bM.Row2.z = matrix[1][2] + bM.Row2.w = matrix[1][3] + + bM.Row3.x = matrix[2][0] + bM.Row3.y = matrix[2][1] + bM.Row3.z = matrix[2][2] + bM.Row3.w = matrix[2][3] + + bM.Row4.x = matrix[3][0] + bM.Row4.y = matrix[3][1] + bM.Row4.z = matrix[3][2] + bM.Row4.w = matrix[3][3] + + def VertexWeightList(self): + if self.__curWeightMap != None: + self.__curVertexWeightList = self.__curWeightMap.WeightMap.add() + + def VertexWeight(self, boneIndex, weight): + vertexWeight = self.__curVertexWeightList.VertexWeights.add() + vertexWeight.BoneIndex = boneIndex + vertexWeight.Weight = weight + + #### MATERIAL COMPONENT #### def TryReferenceMaterial(self, name): @@ -242,7 +369,7 @@ def EndMaterial(self): # public float3[] BiTangents; # public AABBf BoundingBox; - def AddVertex(self, vertex, normal=None, uv=None, tangent=None, bitangent=None): + def AddVertex(self, originalVertex, vertex, normal=None, uv=None, tangent=None, bitangent=None): self.__checkMeshOpen() vx, vy, vz = vertex nx, ny, nz = normal if normal != None else (1, 1, 1) @@ -280,8 +407,9 @@ def AddVertex(self, vertex, normal=None, uv=None, tangent=None, bitangent=None): else: if not (vertex[0] == self.__curMesh.Vertices[inx].x and vertex[1] == self.__curMesh.Vertices[inx].y and vertex[2] == self.__curMesh.Vertices[inx].z): print('WARNING: New vertex: ' + str(vertex) + ' has same hash as existing: ' + str(self.__curMesh.Vertices[inx])) - + originalVertex = -1 self.__curMesh.Triangles.append(inx) + return originalVertex def __AddVertexToBoundingBox(self, vertex): if vertex[0] < self.__curMesh.BoundingBox.min.x: self.__curMesh.BoundingBox.min.x = vertex[0] @@ -316,7 +444,7 @@ def GetReferencedMeshTriVertCount(self, name): else: return -1 - def BeginMesh(self, vertex, normal=None, uv=None, tangent=None, bitangent=None, name=""): + def BeginMesh(self,originalVertex, vertex, normal=None, uv=None, tangent=None, bitangent=None, name=""): if self.__curComponent == None: self.__curComponent, inx = self.AddComponent(name) self.__curMesh = self.__curComponent.FusMesh @@ -328,8 +456,9 @@ def BeginMesh(self, vertex, normal=None, uv=None, tangent=None, bitangent=None, self.__curMesh.BoundingBox.max.y = vertex[1] self.__curMesh.BoundingBox.max.z = vertex[2] self.__vertCache = {} - self.AddVertex(vertex, normal, uv, tangent, bitangent) - + idx = self.AddVertex(originalVertex, vertex, normal, uv, tangent, bitangent) + if(idx > -1): + return idx else: raise RuntimeError('Cannot begin a mesh component with another component not ended. Call EndXYZ() to close the currently open component.') diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/__init__.py b/src/Tools/BlenderScripts/addons/io_export_fus/__init__.py index 9dac984a3..3b3c05783 100644 --- a/src/Tools/BlenderScripts/addons/io_export_fus/__init__.py +++ b/src/Tools/BlenderScripts/addons/io_export_fus/__init__.py @@ -16,6 +16,8 @@ } #import dependencies +import imp +from .FusSceneWriter import FusSceneWriter import bpy from bpy.props import ( StringProperty, @@ -144,7 +146,7 @@ def execute(self, context): visitor.DoRecalcOutside = self.doRecalcOutside visitor.TraverseList(roots) - # visitor.PrintFus() + visitor.PrintFus() visitor.WriteFus(self.filepath) return {'FINISHED'} diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.pyproj b/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.pyproj deleted file mode 100644 index 80428438e..000000000 --- a/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.pyproj +++ /dev/null @@ -1,66 +0,0 @@ - - - - Debug - 2.0 - {548ba459-616b-4d04-b0a1-2e19388c4b55} - io_export_fus - $(FuseeRoot)\ - ..\..\..\..\.. - - __init__.py - - . - $(FuseeEngineRoot)\bin\$(Configuration)\Tools\BlenderScripts\addons - {888888a0-9f3d-457c-b088-3a5042f75d52} - Standard Python launcher - Global|PythonCore|3.10 - true - True - False - - - - - 10.0 - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.sln b/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.sln deleted file mode 100644 index 5fe28ae79..000000000 --- a/src/Tools/BlenderScripts/addons/io_export_fus/io_export_fus.sln +++ /dev/null @@ -1,23 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2005 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "io_export_fus", "io_export_fus.pyproj", "{548BA459-616B-4D04-B0A1-2E19388C4B55}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {548BA459-616B-4D04-B0A1-2E19388C4B55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {548BA459-616B-4D04-B0A1-2E19388C4B55}.Release|Any CPU.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {428A14B9-B282-445D-90ED-61DFB4F65553} - EndGlobalSection -EndGlobal diff --git a/src/Tools/CmdLine/Properties/launchSettings.json b/src/Tools/CmdLine/Properties/launchSettings.json new file mode 100644 index 000000000..1c90c18d4 --- /dev/null +++ b/src/Tools/CmdLine/Properties/launchSettings.json @@ -0,0 +1,7 @@ +{ + "profiles": { + "Fusee.Tools.CmdLine": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/src/Xirkit/Animation.cs b/src/Xirkit/AnimTimeline.cs similarity index 98% rename from src/Xirkit/Animation.cs rename to src/Xirkit/AnimTimeline.cs index 7e0d8de13..0f4a7cdea 100644 --- a/src/Xirkit/Animation.cs +++ b/src/Xirkit/AnimTimeline.cs @@ -8,7 +8,7 @@ namespace Fusee.Xirkit /// /// The Animation Class is capable of storing and handling different types of Channels. /// - public class Animation + public class AnimTimeline { /// /// The _channels List stores all Animation Channels that are derived from the ChannelBase Class. @@ -52,7 +52,7 @@ public class Animation /// Initializes a new instance of the class. /// /// The parameter sets the AnimationMode - public Animation(int animMode = 0) + public void Animation(int animMode = 0) { _time = 0; _animMode = animMode; diff --git a/src/Xirkit/Lerp.cs b/src/Xirkit/Lerp.cs index 3084bf5e4..2c41af12b 100644 --- a/src/Xirkit/Lerp.cs +++ b/src/Xirkit/Lerp.cs @@ -73,6 +73,19 @@ public static float3 Float3QuaternionSlerp(float3 val1, float3 val2, float time1 return QuaternionF.ToEuler(res); } + /// + /// Slerp Function for Quaternions. Useful if the given float3 values contain euler angles in Pitch(x)/Yaw(y)/Roll(z) order. + /// The euler angle set returned by this method is on the shortest spherical path between the two parameter euler angle sets. + /// Note that using linear interpolation of angle values will NOT yield in a path lying on a great circle between the two parameters. Instead, using + /// linear interpolation, the interpolated values will describe a curve called loxodrome which spirals around the poles (due to gimbal lock). + /// + public static float4 Float4QuaternionSlerp(float4 val1, float4 val2, float time1, float time2) + { + + QuaternionF res = QuaternionF.Slerp(new QuaternionF(val1), new QuaternionF(val2), time2 / time1); + return res.ToFloat4(); + } + /// /// Lerp Function for Float4s. /// diff --git a/src/Xirkit/PinFactory.cs b/src/Xirkit/PinFactory.cs index cb0abee8d..41c14c4d9 100644 --- a/src/Xirkit/PinFactory.cs +++ b/src/Xirkit/PinFactory.cs @@ -359,6 +359,7 @@ static PinFactory() AddConverter(v => new float3(v.x, v.y, v.z)); AddConverter(v => v); AddConverter(v => new float4x4(v.x, v.y, v.z, v.w, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + AddConverter(v => new QuaternionF(v)); // From float4x4 @@ -390,6 +391,9 @@ static PinFactory() AddConverter(v => new float3((float)v.M11, (float)v.M12, (float)v.M13)); AddConverter(v => new float4((float)v.M11, (float)v.M12, (float)v.M13, (float)v.M14)); AddConverter(v => new float4x4((float)v.M11, (float)v.M12, (float)v.M13, (float)v.M14, (float)v.M21, (float)v.M22, (float)v.M23, (float)v.M24, (float)v.M31, (float)v.M32, (float)v.M33, (float)v.M34, (float)v.M41, (float)v.M42, (float)v.M43, (float)v.M44)); + + // From Quaternion + AddConverter(q => q.ToFloat4()); } private static void AddConverter(Math.Core.Converter c)