diff --git a/eng/Build.props b/eng/Build.props index 1925bc902..8a1804350 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -3,9 +3,7 @@ - - diff --git a/src/BlazorWebAssemblyCustomInitialization/BlazorWebAssemblyCustomInitialization.sln b/src/BlazorWebAssemblyCustomInitialization/BlazorWebAssemblyCustomInitialization.sln deleted file mode 100644 index 6e0b94799..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/BlazorWebAssemblyCustomInitialization.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31713.378 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle", "Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.csproj", "{AB5B3CB1-80C9-4982-80D0-8FA482464917}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks", "Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj", "{853B5E7C-DE46-4D18-B8C9-57DC7E7B15F2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AB5B3CB1-80C9-4982-80D0-8FA482464917}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB5B3CB1-80C9-4982-80D0-8FA482464917}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB5B3CB1-80C9-4982-80D0-8FA482464917}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB5B3CB1-80C9-4982-80D0-8FA482464917}.Release|Any CPU.Build.0 = Release|Any CPU - {853B5E7C-DE46-4D18-B8C9-57DC7E7B15F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {853B5E7C-DE46-4D18-B8C9-57DC7E7B15F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {853B5E7C-DE46-4D18-B8C9-57DC7E7B15F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {853B5E7C-DE46-4D18-B8C9-57DC7E7B15F2}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {1D35211E-BB7A-46AF-8731-751E236B00DB} - EndGlobalSection -EndGlobal diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs deleted file mode 100644 index 6cfcee949..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.IO; -using System.Net.Http; -using System.Net.Http.Headers; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; - -namespace Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks -{ - public class BundleBlazorAssets : Task - { - [Required] - public ITaskItem[] PublishBlazorBootStaticWebAsset { get; set; } - - [Required] - public string BundlePath { get; set; } - - [Output] - public ITaskItem[] Extension { get; set; } - - public override bool Execute() - { - var bundle = new MultipartFormDataContent("--0a7e8441d64b4bf89086b85e59523b7d"); - foreach (var asset in PublishBlazorBootStaticWebAsset) - { - var name = Path.GetFileName(asset.GetMetadata("RelativePath")); - var fileContents = File.OpenRead(asset.ItemSpec); - var content = new StreamContent(fileContents); - var disposition = new ContentDispositionHeaderValue("form-data"); - disposition.Name = name; - disposition.FileName = name; - content.Headers.ContentDisposition = disposition; - var contentType = Path.GetExtension(name) switch - { - ".js" => "text/javascript", - ".wasm" => "application/wasm", - _ => "application/octet-stream" - }; - content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); - bundle.Add(content); - } - - using (var output = File.Open(BundlePath, FileMode.OpenOrCreate)) - { - output.SetLength(0); - bundle.CopyToAsync(output).ConfigureAwait(false).GetAwaiter().GetResult(); - output.Flush(true); - } - - var bundleItem = new TaskItem(BundlePath); - bundleItem.SetMetadata("RelativePath", "app.bundle"); - bundleItem.SetMetadata("ExtensionName", "multipart"); - - Extension = new ITaskItem[] { bundleItem }; - - return true; - } - } -} diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj deleted file mode 100644 index af279923d..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - netstandard2.0 - 8.0 - - - - - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.csproj b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.csproj deleted file mode 100644 index 2d3f512ba..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - - - NU5100 - net6.0 - enable - enable - Sample package demonstrating how to customize the Blazor publish process. Using this package in production is not supported. - true - true - false - - - - - - - - - - - - - - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/_._ b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/_._ deleted file mode 100644 index 5f282702b..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/_._ +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/build/net6.0/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.targets b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/build/net6.0/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.targets deleted file mode 100644 index cc09d2dda..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/build/net6.0/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.targets +++ /dev/null @@ -1,17 +0,0 @@ - - - - - $(ComputeBlazorExtensionsDependsOn);_BundleBlazorDlls - - - - - - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/wwwroot/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js b/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/wwwroot/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js deleted file mode 100644 index 9db292592..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/wwwroot/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js +++ /dev/null @@ -1,27 +0,0 @@ -const resources = new Map(); -export async function beforeStart(wasmOptions, extensions) { - // Simple way of detecting we are in web assembly - if (!extensions || !extensions.multipart) { - return; - } - - try { - const integrity = extensions.multipart['app.bundle']; - const bundleResponse = await fetch('app.bundle', { integrity: integrity, cache: 'no-cache' }); - const bundleFromData = await bundleResponse.formData(); - for (let value of bundleFromData.values()) { - resources.set(value.name, URL.createObjectURL(value)); - } - wasmOptions.loadBootResource = function (type, name, defaultUri, integrity) { - return resources.get(name) ?? null; - } - } catch (error) { - console.log(error); - } -} - -export async function afterStarted(blazor) { - for (const [_, url] of resources) { - URL.revokeObjectURL(url); - } -} diff --git a/src/BlazorWebAssemblyCustomInitialization/README.md b/src/BlazorWebAssemblyCustomInitialization/README.md deleted file mode 100644 index 8f61c8536..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Blazor custom packaging sample - -This sample demonstrates how to transform the publish output of a blazor webassembly application via a package to support scenarios where the default loading process causes issues on a given environment. - -The sample is composed of 1 project that deals with building the custom boot extension, and a sample app that demonstrates how the package is consumed. - -Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle contains MSBuild targets to customize the Blazor publish output as well as a JS initializer for handling the loading of resources for the custom loading process. - -Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks contains an MSBuild task that is consumed by Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle MSBuild targets and that is responsible for generating the contents of the bundle. - -## Building the sample and running the sample app -* Run the run.ps1 script on this folder. -* Open the browser and navigate to https://localhost:5001 - -## Tailoring the publish output for your own environment. -* Copy the code from `src\BlazorWebAssemblyCustomInitialization\Microsoft.AspNetCore.Components.WebAssembly.*` into your own repository. -* Rename projects and namespaces to suit your needs. -* Update the task in Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks to perform whatever transformation you want on the blazor publish assets. -* Update the JS initializer in Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle as well as the MSBuild targets if necessary. -* Update any code on the server you might need to make sure the files are served correctly. diff --git a/src/BlazorWebAssemblyCustomInitialization/run.ps1 b/src/BlazorWebAssemblyCustomInitialization/run.ps1 deleted file mode 100644 index 79efee29f..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/run.ps1 +++ /dev/null @@ -1,10 +0,0 @@ -$repoRoot = Resolve-Path $PSScriptRoot/../..; -Remove-Item -Recurse -Force $repoRoot/artifacts/obj/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/, $repoRoot/bin/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/ -ErrorAction SilentlyContinue; -Push-Location $repoRoot/src/BlazorWebAssemblyCustomInitialization/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle; -dotnet pack; -Remove-Item -Recurse -Force $env:USERPROFILE/.nuget/packages/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle -ErrorAction SilentlyContinue; -Copy-Item $repoRoot/artifacts/packages/Debug/Shipping/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.0.1.0.nupkg -Destination $repoRoot/src/BlazorWebAssemblyCustomInitialization/sample/.local/ -Pop-Location; -Push-Location $repoRoot/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server; -dotnet publish /bl; -Push-Location $repoRoot/artifacts/bin/CustomPackagedApp.Server/Debug/net6.0/publish/; ./CustomPackagedApp.Server.exe diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/.local/.gitignore b/src/BlazorWebAssemblyCustomInitialization/sample/.local/.gitignore deleted file mode 100644 index 1d56b825e..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/.local/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.nupkg diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/.local/README.txt b/src/BlazorWebAssemblyCustomInitialization/sample/.local/README.txt deleted file mode 100644 index 47d2a6890..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/.local/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This folder is used as an additional package source by the sample project. - -Using `run.ps1` at the root of the sample will populate this folder with the generated packages for customizing the publish output. diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/CustomPackagedApp.Client.csproj b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/CustomPackagedApp.Client.csproj deleted file mode 100644 index 30a11b147..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/CustomPackagedApp.Client.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net6.0 - enable - enable - - $(RestoreAdditionalProjectSources); - $(MSBuildThisFileDirectory)../../.local - - - - - - - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Pages/Index.razor b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Pages/Index.razor deleted file mode 100644 index f8ffadce7..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Pages/Index.razor +++ /dev/null @@ -1,14 +0,0 @@ -

Counter

- -

Current count: @currentCount

- - - -@code { - int currentCount = 0; - - void IncrementCount() - { - currentCount++; - } -} diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Program.cs b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Program.cs deleted file mode 100644 index ba6fdf568..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/Program.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using CustomPackagedApp.Client; - -var builder = WebAssemblyHostBuilder.CreateDefault(args); -builder.RootComponents.Add("#app"); - -await builder.Build().RunAsync(); diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/_Imports.razor b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/_Imports.razor deleted file mode 100644 index 4dad09679..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/_Imports.razor +++ /dev/null @@ -1,9 +0,0 @@ -@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 CustomPackagedApp.Client diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/favicon.ico b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/favicon.ico deleted file mode 100644 index 63e859b47..000000000 Binary files a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/favicon.ico and /dev/null differ diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/icon-192.png b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/icon-192.png deleted file mode 100644 index 166f56da7..000000000 Binary files a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/icon-192.png and /dev/null differ diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/index.html b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/index.html deleted file mode 100644 index b51cecd27..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Client/wwwroot/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - CustomPackagedApp - - - - -
Loading...
- - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/CustomPackagedApp.sln b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/CustomPackagedApp.sln deleted file mode 100644 index 2bfa3a42f..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/CustomPackagedApp.sln +++ /dev/null @@ -1,50 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31713.378 -MinimumVisualStudioVersion = 16.0.0.0 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomPackagedApp.Server", "Server\CustomPackagedApp.Server.csproj", "{2BFE414B-090D-4D15-9796-5AF9E4E687D2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomPackagedApp.Client", "Client\CustomPackagedApp.Client.csproj", "{DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|x64.ActiveCfg = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|x64.Build.0 = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|x86.ActiveCfg = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Debug|x86.Build.0 = Debug|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|Any CPU.Build.0 = Release|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|x64.ActiveCfg = Release|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|x64.Build.0 = Release|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|x86.ActiveCfg = Release|Any CPU - {2BFE414B-090D-4D15-9796-5AF9E4E687D2}.Release|x86.Build.0 = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|x64.ActiveCfg = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|x64.Build.0 = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|x86.ActiveCfg = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Debug|x86.Build.0 = Debug|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|Any CPU.Build.0 = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|x64.ActiveCfg = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|x64.Build.0 = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|x86.ActiveCfg = Release|Any CPU - {DDFCBC06-F6C5-4BC8-B202-F0FE0E1BCC2A}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E182336C-CE38-4CFA-BB2F-BC1B18DAA355} - EndGlobalSection -EndGlobal diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/CustomPackagedApp.Server.csproj b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/CustomPackagedApp.Server.csproj deleted file mode 100644 index 20492526b..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/CustomPackagedApp.Server.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - net6.0 - enable - enable - - $(RestoreAdditionalProjectSources); - $(MSBuildThisFileDirectory)../../.local - - - - - - - - - - - - - diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml deleted file mode 100644 index cf9499dda..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml +++ /dev/null @@ -1,42 +0,0 @@ -@page -@model CustomPackagedApp.Server.Pages.ErrorModel - - - - - - - - Error - - - - - -
-
-

Error.

-

An error occurred while processing your request.

- - @if (Model.ShowRequestId) - { -

- Request ID: @Model.RequestId -

- } - -

Development Mode

-

- Swapping to the Development environment displays detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

-
-
- - - diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml.cs b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml.cs deleted file mode 100644 index e83858219..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Pages/Error.cshtml.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Diagnostics; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace CustomPackagedApp.Server.Pages; - -[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] -[IgnoreAntiforgeryToken] -public class ErrorModel : PageModel -{ - public string? RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - private readonly ILogger _logger; - - public ErrorModel(ILogger logger) - { - _logger = logger; - } - - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } -} diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Program.cs b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Program.cs deleted file mode 100644 index 52dfb65d3..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/Program.cs +++ /dev/null @@ -1,64 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. - -builder.Services.AddControllersWithViews(); -builder.Services.AddRazorPages(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseWebAssemblyDebugging(); -} -else -{ - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); -} - -app.UseHttpsRedirection(); - -app.UseBlazorFrameworkFiles(); -app.UseStaticFiles(); - -app.UseRouting(); - -app.MapRazorPages(); -app.MapControllers(); - -app.MapGet("app.bundle", (HttpContext context) => -{ - string? contentEncoding = null; - var contentType = "multipart/form-data; boundary=\"--0a7e8441d64b4bf89086b85e59523b7d\""; - var fileName = "app.bundle"; - - var acceptEncodings = context.Request.Headers.AcceptEncoding; - if (StringWithQualityHeaderValue.TryParseList(acceptEncodings, out var encodings)) - { - if (encodings.Any(e => e.Value == "br")) - { - contentEncoding = "br"; - fileName += ".br"; - } - else if (encodings.Any(e => e.Value == "gzip")) - { - contentEncoding = "gzip"; - fileName += ".gz"; - } - } - - if (contentEncoding != null) - { - context.Response.Headers.ContentEncoding = contentEncoding; - } - return Results.File( - app.Environment.WebRootFileProvider.GetFileInfo(fileName).CreateReadStream(), - contentType); -}); - -app.MapFallbackToFile("index.html"); - -app.Run(); diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.Development.json b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.json b/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/src/BlazorWebAssemblyCustomInitialization/sample/CustomPackagedApp/Server/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/src/Components.Web.Extensions/HeadManagement/HeadManagementJSObjectReference.cs b/src/Components.Web.Extensions/HeadManagement/HeadManagementJSObjectReference.cs deleted file mode 100644 index 526f3a756..000000000 --- a/src/Components.Web.Extensions/HeadManagement/HeadManagementJSObjectReference.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading.Tasks; -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - internal class HeadManagementJSObjectReference - { - private const string ScriptPath = "./_content/Microsoft.AspNetCore.Components.Web.Extensions/headManager.js"; - private readonly IJSRuntime _jsRuntime; - private Task? _headManager; - - public HeadManagementJSObjectReference(IJSRuntime jsRuntime) - { - _jsRuntime = jsRuntime; - } - - public Task HeadManager => - _headManager ??= _jsRuntime.InvokeAsync("import", ScriptPath).AsTask(); - - public async ValueTask SetTitleAsync(string title) - { - var headManager = await HeadManager; - await headManager.InvokeVoidAsync("setTitle", title); - } - - public async ValueTask AddOrUpdateHeadTagAsync(TagElement tag, string id) - { - var headManager = await HeadManager; - await headManager.InvokeVoidAsync("addOrUpdateHeadTag", tag, id); - } - - public async ValueTask RemoveHeadTagAsync(string id) - { - var headManager = await HeadManager; - await headManager.InvokeVoidAsync("removeHeadTag", id); - } - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/HeadTagBase.cs b/src/Components.Web.Extensions/HeadManagement/HeadTagBase.cs deleted file mode 100644 index 79bac9aae..000000000 --- a/src/Components.Web.Extensions/HeadManagement/HeadTagBase.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - /// - /// Serves as a base for components that represent tags in the HTML head. - /// - public abstract class HeadTagBase : ComponentBase, IAsyncDisposable - { - private readonly string _id = Guid.NewGuid().ToString("N"); - - private TagElement _tagElement; - private HeadManagementJSObjectReference _jsObject = default!; - private bool _hasRendered; - - [Inject] - private IJSRuntime JSRuntime { get; set; } = default!; - - /// - /// Gets or sets a collection of additional attributes that will be applied to the meta element. - /// - [Parameter(CaptureUnmatchedValues = true)] - public IReadOnlyDictionary? Attributes { get; set; } - - /// - /// Gets the name of the tag being represented. - /// - protected abstract string TagName { get; } - - /// - protected override void OnParametersSet() - { - _tagElement = new TagElement(TagName, Attributes); - _jsObject = new HeadManagementJSObjectReference(JSRuntime); - } - - /// - protected override async Task OnAfterRenderAsync(bool firstRender) - { - _hasRendered = true; - - await _jsObject.AddOrUpdateHeadTagAsync(_tagElement, _id); - } - - /// - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddMarkupContent(0, $""); - } - - /// - public async ValueTask DisposeAsync() - { - if (_hasRendered) - { - await _jsObject.RemoveHeadTagAsync(_id); - } - } - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/JsonSerializerOptionsProvider.cs b/src/Components.Web.Extensions/HeadManagement/JsonSerializerOptionsProvider.cs deleted file mode 100644 index 72c9cc873..000000000 --- a/src/Components.Web.Extensions/HeadManagement/JsonSerializerOptionsProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Text.Json; - -namespace Microsoft.AspNetCore.Components -{ - internal static class JsonSerializerOptionsProvider - { - public static readonly JsonSerializerOptions Options = new JsonSerializerOptions(JsonSerializerDefaults.Web); - } -} \ No newline at end of file diff --git a/src/Components.Web.Extensions/HeadManagement/Link.cs b/src/Components.Web.Extensions/HeadManagement/Link.cs deleted file mode 100644 index 83cc193b7..000000000 --- a/src/Components.Web.Extensions/HeadManagement/Link.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - /// - /// A component that adds a link tag to the HTML head. - /// - public sealed class Link : HeadTagBase - { - /// - protected override string TagName => "link"; - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/Meta.cs b/src/Components.Web.Extensions/HeadManagement/Meta.cs deleted file mode 100644 index e5100bbd4..000000000 --- a/src/Components.Web.Extensions/HeadManagement/Meta.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - /// - /// A component that adds a meta tag to the HTML head. - /// - public sealed class Meta : HeadTagBase - { - /// - protected override string TagName => "meta"; - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/TagElement.cs b/src/Components.Web.Extensions/HeadManagement/TagElement.cs deleted file mode 100644 index 3488eb1e1..000000000 --- a/src/Components.Web.Extensions/HeadManagement/TagElement.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - internal readonly struct TagElement - { - public string Type => "tag"; - - public string TagName { get; } - - public IReadOnlyDictionary? Attributes { get; } - - public TagElement(string tagName, IReadOnlyDictionary? attributes) - { - TagName = tagName; - Attributes = attributes; - } - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/Title.cs b/src/Components.Web.Extensions/HeadManagement/Title.cs deleted file mode 100644 index 8ceb7b302..000000000 --- a/src/Components.Web.Extensions/HeadManagement/Title.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - /// - /// A component that changes the title of the document. - /// - public sealed class Title : ComponentBase - { - private HeadManagementJSObjectReference _jsObject = default!; - - [Inject] - private IJSRuntime JSRuntime { get; set; } = default!; - - /// - /// Gets or sets the value to use as the document's title. - /// - [Parameter] - public string Value { get; set; } = string.Empty; - - protected override void OnParametersSet() - { - _jsObject = new HeadManagementJSObjectReference(JSRuntime); - } - - /// - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await _jsObject.SetTitleAsync(Value); - } - - /// - protected override void BuildRenderTree(RenderTreeBuilder builder) - { - builder.AddMarkupContent(0, $""); - } - } -} diff --git a/src/Components.Web.Extensions/HeadManagement/TitleElement.cs b/src/Components.Web.Extensions/HeadManagement/TitleElement.cs deleted file mode 100644 index c56d550ac..000000000 --- a/src/Components.Web.Extensions/HeadManagement/TitleElement.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Components.Web.Extensions.Head -{ - internal readonly struct TitleElement - { - public string Type => "title"; - - public string Title { get; } - - public TitleElement(string title) - { - Title = title; - } - } -} diff --git a/src/Components.Web.Extensions/Microsoft.AspNetCore.Components.Web.Extensions.csproj b/src/Components.Web.Extensions/Microsoft.AspNetCore.Components.Web.Extensions.csproj deleted file mode 100644 index 1348bcbd9..000000000 --- a/src/Components.Web.Extensions/Microsoft.AspNetCore.Components.Web.Extensions.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net5.0 - A collection of Blazor components for the web. - true - Microsoft.AspNetCore.Components - enable - true - true - 5 - 0 - preview9 - - - - - - - - diff --git a/src/Components.Web.Extensions/Properties/AssemblyInfo.cs b/src/Components.Web.Extensions/Properties/AssemblyInfo.cs deleted file mode 100644 index 2e06371bc..000000000 --- a/src/Components.Web.Extensions/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Web.Extensions.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Components.Web.Extensions/wwwroot/headManager.js b/src/Components.Web.Extensions/wwwroot/headManager.js deleted file mode 100644 index e6dd7f20f..000000000 --- a/src/Components.Web.Extensions/wwwroot/headManager.js +++ /dev/null @@ -1,96 +0,0 @@ -// Local helpers - -const blazorIdAttributeName = '_blazor_id'; -const headCommentRegularExpression = /\W*Head:[^{]*(.*)$/; -const prerenderedTags = []; - -function createHeadTag({ tagName, attributes }, id) { - const tagElement = document.createElement(tagName); - - // The id is undefined during prerendering - if (id) { - tagElement.setAttribute(blazorIdAttributeName, id); - } - - if (attributes) { - Object.keys(attributes).forEach(key => { - tagElement.setAttribute(key, attributes[key]); - }); - } - - document.head.appendChild(tagElement); - - return tagElement; -} - -function resolvePrerenderedHeadComponents(node) { - node.childNodes.forEach((childNode) => { - const headElement = parseHeadComment(childNode); - - if (headElement) { - applyPrerenderedHeadComponent(headElement); - } else { - resolvePrerenderedHeadComponents(childNode); - } - }); -} - -function applyPrerenderedHeadComponent(headElement) { - switch (headElement.type) { - case 'title': - setTitle(headElement.title); - break; - case 'tag': - const tag = createHeadTag(headElement); - prerenderedTags.push(tag); - break; - default: - throw new Error(`Invalid head element type '${headElement.type}'.`); - } -} - -function parseHeadComment(node) { - if (!node || node.nodeType != Node.COMMENT_NODE) { - return; - } - - const commentText = node.textContent; - - if (!commentText) { - return; - } - - const definition = headCommentRegularExpression.exec(commentText); - const json = definition && definition[1]; - - return json && JSON.parse(json); -} - -function removePrerenderedHeadTags() { - prerenderedTags.forEach((tag) => { - tag.remove(); - }); - - prerenderedTags.length = 0; -} - -// Exported functions - -export function setTitle(title) { - document.title = title; -} - -export function addOrUpdateHeadTag(tag, id) { - removePrerenderedHeadTags(); - removeHeadTag(id); - createHeadTag(tag, id); -} - -export function removeHeadTag(id) { - let tag = document.head.querySelector(`[${blazorIdAttributeName}='${id}']`); - tag && tag.remove(); -} - -(function () { - resolvePrerenderedHeadComponents(document); -})(); diff --git a/src/DynamicJS/DynamicJS.sln b/src/DynamicJS/DynamicJS.sln deleted file mode 100644 index 1d36bd2ad..000000000 --- a/src/DynamicJS/DynamicJS.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30413.136 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicJsApi", "src\Microsoft.AspNetCore.DynamicJS.csproj", "{A200593F-89AA-405B-A80B-2693A5C8E6B8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleWasmApp", "samples\SampleWasmApp\SampleWasmApp.csproj", "{6EC3F227-B997-4DDA-80ED-50D787A19D7E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A200593F-89AA-405B-A80B-2693A5C8E6B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A200593F-89AA-405B-A80B-2693A5C8E6B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A200593F-89AA-405B-A80B-2693A5C8E6B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A200593F-89AA-405B-A80B-2693A5C8E6B8}.Release|Any CPU.Build.0 = Release|Any CPU - {6EC3F227-B997-4DDA-80ED-50D787A19D7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6EC3F227-B997-4DDA-80ED-50D787A19D7E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6EC3F227-B997-4DDA-80ED-50D787A19D7E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6EC3F227-B997-4DDA-80ED-50D787A19D7E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E32AB38B-7A53-4891-B788-10653A0EF224} - EndGlobalSection -EndGlobal diff --git a/src/DynamicJS/README.md b/src/DynamicJS/README.md deleted file mode 100644 index 5a5271ac7..000000000 --- a/src/DynamicJS/README.md +++ /dev/null @@ -1,88 +0,0 @@ -## Blazor Dynamic JS -An package allowing JavaScipt-like interactions with JavaScript objects, all in a .NET context. - -### Example: -```csharp -private async Task OnClick() -{ - // Get scoped access to the browser's 'window' JS object - await using var window = JSRuntime.GetDynamicWindow(); - - // Use JS-like property access and method invocation - window.console.log("Hello, world!"); - - // Create bindings to other JS objects - var element = document.getElementById("some-element-id"); - - // Mutate JS objects with ease - element.innerText = "Not a single line of JS :)"; - - // Even create your own JS objects! - var myObject = JSObject.Create(window, new - { - numValue = 42, - strValue = "37", - objValue = new - { - boolValue = true - } - }); - - // Looks like JS, acts like JS, but isn't JS (this operation is illegal in normal C#!) - var result = myObject.numValue - myObject.strValue; // 42 - "37" = 5 - - // ... -} -``` - -## Why? -One of the greatest aspects of Blazor is that it enables developers to create web apps without using JS. However, there are times where the best solution to a problem is to use JS in your Blazor app, even if it's a few simple lines. Instead of introducing a new JS file, linking it up, and calling its functions via `IJSRuntime`, you can write a few lines of C# using DynamicJS. - -## Setup -1. Add a package reference to `Microsoft.AspNetCore.DynamicJS`. -2. Add `` to your `index.html` when using Blazor WebAssembly, or to your `_Host.cshtml` on Blazor Server. - -## Usage -Before using this package, the crucial thing to understand is that all dynamic JS operations are lazily evaluated. This is done to minimize the number of JS interop calls, maximizing performance. There are only two conditions that trigger a dynamic JS evaluation: -1. A `JSObject` is evaluated as another .NET type. Various ways this can be done are discussed later. -2. The "root" `JSObject` is disposed. The `using` statement is a common pattern to make sure disposal occurs, but you can also dispose the root manually. This will be discussed in more detail later. - -In the example at the top of this document, no JS is executed until the end of `OnClick()`, since a `JSObject` is never converted to another .NET type. This means that it only takes a *single* JS interop calls to execute all that code. Awesome! - -### Evaluating a `JSObject` as another .NET type -Let's say we wanted to get `window.document.title` as a .NET `string`. This can be done via the static method `JSObject.EvaluateAsync()`: - -```csharp -await using var window = JSRuntime.GetDynamicWindow(); -var title = await JSObject.EvaluateAsync(window.document.title); -``` - -Note that if we were to simply say: -```csharp -var title = window.document.title; -``` -then `title` would be another `JSObject`, not a `string`, and no evaluation would occur. - -**IMPORTANT**: Attempting to cast a `JSObject` to another .NET type, **either implicitly or explicitly**, will throw an exception if the root `JSObject` was obtained via `GetDynamicWindow()`, because dynamic JS evaluations must occur asynchronously. If you're on Blazor Server, there's no better alternative, but if you're on Blazor WebAssembly, read the next section. - -### Synchronous lazy evaluation -If you're using Blazor WebAssembly, JS interop calls can be done in-process (i.e. synchronously). For this reason, it's possible to evaluate a `JSObject` by directly casting it to a .NET type (either implicitly or explicitly), as long as you create the root `JSObject` with `IJSInProcessRuntime.GetInProcessWindowDynamic()`. For example: -```csharp -using var window = JSInProcessRuntime.GetInProcessWindowDynamic(); - -// Explicit cast, triggering an evaluation -var title = (string)window.document.title; - -// Implicit cast to a .NET bool, again triggering an evaluation -if (document.getElementById("done-loading")) -{ - // Do something -} -``` - -Compared to manually evaluating asynchronously, this is far less verbose. Again, note that the example above will only run on Blazor WebAssembly. - -### Cleaning up -The root `JSObject` (the one obtained directly from `IJSRuntime`) should be disposed to free up internal memory. There are two ways to do this: -1. Create the root `JSObject` with the `using` statement pattern as shown in the examples in this document. Make sure to use `await using` when using asynchronous evaluation. -2. Call `DisposeAsync()` on the root `JSObject` when using asynchronous evaluation, or `Dispose()` when using synchronous evaluation. diff --git a/src/DynamicJS/samples/SampleWasmApp/App.razor b/src/DynamicJS/samples/SampleWasmApp/App.razor deleted file mode 100644 index 6f67a6ea6..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/App.razor +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Sorry, there's nothing at this address.

-
-
-
diff --git a/src/DynamicJS/samples/SampleWasmApp/AsyncDynamicJSProvider.cs b/src/DynamicJS/samples/SampleWasmApp/AsyncDynamicJSProvider.cs deleted file mode 100644 index 41da856b0..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/AsyncDynamicJSProvider.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.DynamicJS; -using Microsoft.JSInterop; - -namespace SampleWasmApp -{ - public class AsyncDynamicJSProvider : IDynamicJSProvider - { - private readonly IJSRuntime _jsRuntime; - - public AsyncDynamicJSProvider(IJSRuntime jsRuntime) - { - _jsRuntime = jsRuntime; - } - - public async Task Evaluate(dynamic jsObject) - { - var result = await JSObject.EvaluateAsync(jsObject); - return (object)result; - } - - public async Task RunWithWindow(Func> operation) - { - await using var window = _jsRuntime.GetDynamicWindow(); - return await operation(window); - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/IDynamicJSProvider.cs b/src/DynamicJS/samples/SampleWasmApp/IDynamicJSProvider.cs deleted file mode 100644 index 370f2becc..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/IDynamicJSProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.DynamicJS; - -namespace SampleWasmApp -{ - public interface IDynamicJSProvider - { - Task Evaluate(dynamic jsObject); - Task RunWithWindow(Func> operation); - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/InProcessDynamicJSProvider.cs b/src/DynamicJS/samples/SampleWasmApp/InProcessDynamicJSProvider.cs deleted file mode 100644 index b72f56958..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/InProcessDynamicJSProvider.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.DynamicJS; -using Microsoft.JSInterop; - -namespace SampleWasmApp -{ - public class InProcessDynamicJSProvider : IDynamicJSProvider - { - private readonly IJSInProcessRuntime _jsRuntime; - - public InProcessDynamicJSProvider(IJSInProcessRuntime jsRuntime) - { - _jsRuntime = jsRuntime; - } - - public Task Evaluate(dynamic jsObject) - { - return Task.FromResult((object)(TValue)jsObject); - } - - public Task RunWithWindow(Func> operation) - { - using var window = _jsRuntime.GetInProcessDynamicWindow(); - return operation(window); - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/Pages/Asynchronous.razor b/src/DynamicJS/samples/SampleWasmApp/Pages/Asynchronous.razor deleted file mode 100644 index 316285e67..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/Pages/Asynchronous.razor +++ /dev/null @@ -1,65 +0,0 @@ -@page "/async" -@inject IJSRuntime JSRuntime - -

Asynchronous dynamic JS

- - -
-Will be replaced. -
- -
- - -@code { - private readonly string _textId = "some-text"; - - private AsyncDynamicJSProvider _dynamicJSProvider; - - protected override void OnInitialized() - { - _dynamicJSProvider = new AsyncDynamicJSProvider(JSRuntime); - } - - private async Task RunAdvanced() - { - await using (var window = JSRuntime.GetDynamicWindow()) - { - window.console.log("Hello, world!"); - - var document = window.document; - var element = document.getElementById(_textId); - element.style = "background-color: green;"; - - if (await JSObject.EvaluateAsync(element.innerText == "Will be replaced.")) - { - element.innerText = "New text!"; - } - else - { - window.console.log("Nothing to change"); - } - - var jsObject = JSObject.Create(window, new - { - field = "this is a field", - nested = new - { - otherField = 3 - } - }); - - window.console.log(jsObject); - } - - await using (var window = JSRuntime.GetDynamicWindow()) - { - var jsTrue = JSObject.Create(window, true); - - if (await JSObject.EvaluateAsync(jsTrue)) - { - window.console.log("It's true!"); - } - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/Pages/Index.razor b/src/DynamicJS/samples/SampleWasmApp/Pages/Index.razor deleted file mode 100644 index 196e74355..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/Pages/Index.razor +++ /dev/null @@ -1,67 +0,0 @@ -@page "/" -@inject IJSRuntime JSRuntime - -

Synchronous dynamic JS

- - -
-Will be replaced. -
- -
- - -@code { - private readonly string _textId = "some-text"; - - private InProcessDynamicJSProvider _dynamicJSProvider; - - protected override void OnInitialized() - { - _dynamicJSProvider = new InProcessDynamicJSProvider((IJSInProcessRuntime)JSRuntime); - } - - private void RunAdvanced() - { - var jsInProcessRuntime = (IJSInProcessRuntime)JSRuntime; - - using (var window = jsInProcessRuntime.GetInProcessDynamicWindow()) - { - window.console.log("Hello, world!"); - - var document = window.document; - var element = document.getElementById(_textId); - element.style = "background-color: green;"; - - if (element.innerText == "Will be replaced.") - { - element.innerText = "New text!"; - } - else - { - window.console.log("Nothing to change"); - } - - var jsObject = JSObject.Create(window, new - { - field = "this is a field", - nested = new - { - otherField = 3 - } - }); - - window.console.log(jsObject); - } - - using (var window = jsInProcessRuntime.GetInProcessDynamicWindow()) - { - var jsTrue = JSObject.Create(window, true); - - if (jsTrue) - { - window.console.log("It's true!"); - } - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/Program.cs b/src/DynamicJS/samples/SampleWasmApp/Program.cs deleted file mode 100644 index aacfed6d9..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/Program.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Net.Http; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Text; -using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.AspNetCore.DynamicJS; - -namespace SampleWasmApp -{ - 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(); - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/SampleWasmApp.csproj b/src/DynamicJS/samples/SampleWasmApp/SampleWasmApp.csproj deleted file mode 100644 index aab788a29..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/SampleWasmApp.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net5.0 - 8.0 - browser-wasm - true - - - - - - - - - - - - - diff --git a/src/DynamicJS/samples/SampleWasmApp/Shared/MainLayout.razor b/src/DynamicJS/samples/SampleWasmApp/Shared/MainLayout.razor deleted file mode 100644 index 11bacb509..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/Shared/MainLayout.razor +++ /dev/null @@ -1,8 +0,0 @@ -@inherits LayoutComponentBase - -Synchronous -Asynchronous - -
- -@Body diff --git a/src/DynamicJS/samples/SampleWasmApp/Shared/UsageCommon.razor b/src/DynamicJS/samples/SampleWasmApp/Shared/UsageCommon.razor deleted file mode 100644 index b08b28691..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/Shared/UsageCommon.razor +++ /dev/null @@ -1,403 +0,0 @@ - - -@foreach (var result in results) -{ -
-

@result.Key

- @result.Value.result -
-} - -@code { - private readonly IDictionary results = new Dictionary(); - - [Parameter] - public IDynamicJSProvider DynamicJSProvider { get; set; } - - private readonly (string description, object expected, Func> operation)[] tests; - - public UsageCommon() - { - tests = new (string, object, Func>)[] - { - ("Binary operator '+' (1 + 2)", 3, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a + b); - }), - ("Binary operator '+' ('1' + 2)", "12", window => - { - var a = JSObject.Create(window, "1"); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a + b); - }), - ("Binary operator '&' (42 & 79)", 10, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - - return DynamicJSProvider.Evaluate(a & b); - }), - ("Binary operator '&=' (a = 42, a &= 79)", 10, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - a &= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '/' (7 / 2)", 3.5f, window => - { - var a = JSObject.Create(window, 7); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a / b); - }), - ("Binary operator '/=' (a = 7, a /= 2)", 3.5f, window => - { - var a = JSObject.Create(window, 7); - var b = JSObject.Create(window, 2); - a /= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '^' (42 ^ 79)", 101, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - - return DynamicJSProvider.Evaluate(a ^ b); - }), - ("Binary operator '^=' (a = 42, a ^= 79)", 101, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - a ^= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '>' (2 > 1)", true, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 1); - - return DynamicJSProvider.Evaluate(a > b); - }), - ("Binary operator '>' (2 > 2)", false, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a > b); - }), - ("Binary operator '>=' (2 >= 1)", true, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 1); - - return DynamicJSProvider.Evaluate(a >= b); - }), - ("Binary operator '>=' (2 >= 2)", true, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a >= b); - }), - ("Binary operator '>=' (1 >= 2)", false, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a >= b); - }), - ("Binary operator '<<' (1 << 3)", 8, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a << b); - }), - ("Binary operator '<<=' (a = 1, a <<= 3)", 8, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 3); - a <<= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '<' (1 > 2)", true, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a < b); - }), - ("Binary operator '<' (2 < 2)", false, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a < b); - }), - ("Binary operator '<=' (1 <= 2)", true, window => - { - var a = JSObject.Create(window, 1); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a <= b); - }), - ("Binary operator '<=' (2 <= 2)", true, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(a <= b); - }), - ("Binary operator '<=' (2 <= 1)", false, window => - { - var a = JSObject.Create(window, 2); - var b = JSObject.Create(window, 1); - - return DynamicJSProvider.Evaluate(a <= b); - }), - ("Binary operator '%' (6 % 4)", 2, window => - { - var a = JSObject.Create(window, 6); - var b = JSObject.Create(window, 4); - - return DynamicJSProvider.Evaluate(a % b); - }), - ("Binary operator '%=' (a = 6, a %= 4)", 2, window => - { - var a = JSObject.Create(window, 6); - var b = JSObject.Create(window, 4); - a %= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '*' (8 * 3)", 24, window => - { - var a = JSObject.Create(window, 8); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a * b); - }), - ("Binary operator '*=' (a = 8, a *= 3)", 24, window => - { - var a = JSObject.Create(window, 8); - var b = JSObject.Create(window, 3); - a *= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '==' (3 == 3, or 3 === 3 in JS)", true, window => - { - var a = JSObject.Create(window, 3); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a == b); - }), - ("Binary operator '==' (3 == '3', or 3 === '3' in JS)", false, window => - { - var a = JSObject.Create(window, 3); - var b = JSObject.Create(window, "3"); - - return DynamicJSProvider.Evaluate(a == b); - }), - ("Binary operator '==' (Reference equality, === in JS)", true, window => - { - var a = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - var b = a; - - return DynamicJSProvider.Evaluate(a == b); - }), - ("Binary operator '==' (Reference inequality, === in JS)", false, window => - { - var a = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - var b = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - - return DynamicJSProvider.Evaluate(a == b); - }), - ("Binary operator '!=' (3 != 3, or 3 !== 3 in JS)", false, window => - { - var a = JSObject.Create(window, 3); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a != b); - }), - ("Binary operator '==' (3 == '3', or 3 === '3' in JS)", true, window => - { - var a = JSObject.Create(window, 3); - var b = JSObject.Create(window, "3"); - - return DynamicJSProvider.Evaluate(a != b); - }), - ("Binary operator '!=' (Reference equality, !== in JS)", false, window => - { - var a = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - var b = a; - - return DynamicJSProvider.Evaluate(a != b); - }), - ("Binary operator '!=' (Reference inequality, !== in JS)", true, window => - { - var a = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - var b = JSObject.Create(window, new - { - value = "String value", - nested = new - { - value = 1 - } - }); - - return DynamicJSProvider.Evaluate(a != b); - }), - ("Binary operator '|' (42 | 79)", 111, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - - return DynamicJSProvider.Evaluate(a | b); - }), - ("Binary operator '|=' (a = 42, a |= 79)", 111, window => - { - var a = JSObject.Create(window, 42); - var b = JSObject.Create(window, 79); - a |= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '>>' (32 >> 3)", 4, window => - { - var a = JSObject.Create(window, 32); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a >> b); - }), - ("Binary operator '>>=' (a = 32, a >>= 3)", 4, window => - { - var a = JSObject.Create(window, 32); - var b = JSObject.Create(window, 3); - a >>= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Binary operator '-' (5 - 3)", 2, window => - { - var a = JSObject.Create(window, 5); - var b = JSObject.Create(window, 3); - - return DynamicJSProvider.Evaluate(a - b); - }), - ("Binary operator '-=' (a = 5, a -= 3)", 2, window => - { - var a = JSObject.Create(window, 5); - var b = JSObject.Create(window, 3); - a -= b; - - return DynamicJSProvider.Evaluate(a); - }), - ("Unary operator '--' (a = 4, a--)", 4, window => - { - var a = JSObject.Create(window, 4); - - return DynamicJSProvider.Evaluate(a--); - }), - ("Unary operator '--' (a = 4, --a)", 3, window => - { - var a = JSObject.Create(window, 4); - - return DynamicJSProvider.Evaluate(--a); - }), - ("Unary operator '++' (a = 4, a++)", 4, window => - { - var a = JSObject.Create(window, 4); - - return DynamicJSProvider.Evaluate(a++); - }), - ("Unary operator '++' (a = 4, ++a)", 5, window => - { - var a = JSObject.Create(window, 4); - - return DynamicJSProvider.Evaluate(++a); - }), - ("Unary operator '-' (a = 2, -a)", -2, window => - { - var a = JSObject.Create(window, 2); - - return DynamicJSProvider.Evaluate(-a); - }), - ("Unary operator '!' (a = true, !a)", false, window => - { - var a = JSObject.Create(window, true); - - return DynamicJSProvider.Evaluate(!a); - }), - ("Unary operator '~' (a = 79, ~a)", -80, window => - { - var a = JSObject.Create(window, 79); - - return DynamicJSProvider.Evaluate(~a); - }), - ("Unary operator '+' (a = '9', +a)", 9, window => - { - var a = JSObject.Create(window, "9"); - - return DynamicJSProvider.Evaluate(+a); - }), - }; - } - - private async Task Run() - { - results.Clear(); - - foreach (var (name, expected, operation) in tests) - { - var result = await DynamicJSProvider.RunWithWindow(operation); - var passed = expected.Equals(result); - - results[name] = (passed, result); - } - } -} diff --git a/src/DynamicJS/samples/SampleWasmApp/_Imports.razor b/src/DynamicJS/samples/SampleWasmApp/_Imports.razor deleted file mode 100644 index aa06221d7..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/_Imports.razor +++ /dev/null @@ -1,10 +0,0 @@ -@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.WebAssembly.Http -@using Microsoft.AspNetCore.DynamicJS -@using Microsoft.JSInterop -@using SampleWasmApp -@using SampleWasmApp.Shared diff --git a/src/DynamicJS/samples/SampleWasmApp/wwwroot/index.html b/src/DynamicJS/samples/SampleWasmApp/wwwroot/index.html deleted file mode 100644 index 77c771458..000000000 --- a/src/DynamicJS/samples/SampleWasmApp/wwwroot/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - SampleWasmApp - - - - - Loading... - - - - - - diff --git a/src/DynamicJS/src/DynamicJSInterop.cs b/src/DynamicJS/src/DynamicJSInterop.cs deleted file mode 100644 index d145813de..000000000 --- a/src/DynamicJS/src/DynamicJSInterop.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal static class DynamicJSInterop - { - private const string JSFunctionsPrefix = "dynamicJS."; - - public const string Evaluate = JSFunctionsPrefix + "evaluate"; - } -} diff --git a/src/DynamicJS/src/Expressions/JSAssignmentExpression.cs b/src/DynamicJS/src/Expressions/JSAssignmentExpression.cs deleted file mode 100644 index 4fa3de825..000000000 --- a/src/DynamicJS/src/Expressions/JSAssignmentExpression.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSAssignmentExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Assignment; - - public long TargetObjectId { get; set; } - - public string Name { get; set; } = string.Empty; - - public object? Value { get; set; } - } -} diff --git a/src/DynamicJS/src/Expressions/JSBinaryExpression.cs b/src/DynamicJS/src/Expressions/JSBinaryExpression.cs deleted file mode 100644 index fe722cebf..000000000 --- a/src/DynamicJS/src/Expressions/JSBinaryExpression.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSBinaryExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Binary; - - public long TargetObjectId { get; set; } - - public ExpressionType Operation { get; set; } - - public object? Arg { get; set; } - } -} diff --git a/src/DynamicJS/src/Expressions/JSInstantiationExpression.cs b/src/DynamicJS/src/Expressions/JSInstantiationExpression.cs deleted file mode 100644 index 50a56511f..000000000 --- a/src/DynamicJS/src/Expressions/JSInstantiationExpression.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSInstantiationExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Instantiation; - - public long TargetObjectId { get; set; } - - public object? Value { get; set; } - } -} diff --git a/src/DynamicJS/src/Expressions/JSInvocationExpression.cs b/src/DynamicJS/src/Expressions/JSInvocationExpression.cs deleted file mode 100644 index ee636832b..000000000 --- a/src/DynamicJS/src/Expressions/JSInvocationExpression.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSInvocationExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Invocation; - - public long TargetObjectId { get; set; } - - public object?[]? Args { get; set; } - } -} diff --git a/src/DynamicJS/src/Expressions/JSMethodExpression.cs b/src/DynamicJS/src/Expressions/JSMethodExpression.cs deleted file mode 100644 index 0bdc97a4c..000000000 --- a/src/DynamicJS/src/Expressions/JSMethodExpression.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSMethodExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Method; - - public long TargetObjectId { get; set; } - - public string Name { get; set; } = string.Empty; - - public object?[]? Args { get; set; } - } -} diff --git a/src/DynamicJS/src/Expressions/JSPropertyExpression.cs b/src/DynamicJS/src/Expressions/JSPropertyExpression.cs deleted file mode 100644 index 6bc7f8e0c..000000000 --- a/src/DynamicJS/src/Expressions/JSPropertyExpression.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSPropertyExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Property; - - public long TargetObjectId { get; set; } - - public string Name { get; set; } = string.Empty; - } -} diff --git a/src/DynamicJS/src/Expressions/JSUnaryExpression.cs b/src/DynamicJS/src/Expressions/JSUnaryExpression.cs deleted file mode 100644 index f7380f46c..000000000 --- a/src/DynamicJS/src/Expressions/JSUnaryExpression.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq.Expressions; - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSUnaryExpression : IJSExpression - { - public JSExpressionType Type => JSExpressionType.Unary; - - public long TargetObjectId { get; set; } - - public ExpressionType Operation { get; set; } - } -} diff --git a/src/DynamicJS/src/IJSExpression.cs b/src/DynamicJS/src/IJSExpression.cs deleted file mode 100644 index 0b7d813aa..000000000 --- a/src/DynamicJS/src/IJSExpression.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal interface IJSExpression - { - JSExpressionType Type { get; } - - long TargetObjectId { get; set; } - } -} diff --git a/src/DynamicJS/src/InProcessEvaluator.cs b/src/DynamicJS/src/InProcessEvaluator.cs deleted file mode 100644 index 6661acf82..000000000 --- a/src/DynamicJS/src/InProcessEvaluator.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Reflection; -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class InProcessEvaluator - { - private readonly IJSInProcessRuntime _jsRuntime; - - private readonly MethodInfo _evaluateGenericMethodInfo; - - private readonly IDictionary _cachedDelegates; - - private delegate object EvaluateDelegate(long treeId, long targetObjectId, IEnumerable expressionList); - - public InProcessEvaluator(IJSInProcessRuntime jsRuntime) - { - _jsRuntime = jsRuntime; - _evaluateGenericMethodInfo = GetType().GetMethod(nameof(EvaluateGeneric), BindingFlags.Instance | BindingFlags.NonPublic)!; - _cachedDelegates = new Dictionary(); - } - - public object Evaluate(Type returnType, long treeId, long targetObjectId, IEnumerable expressionList) - { - if (!_cachedDelegates.TryGetValue(returnType, out var evaluate)) - { - var evaluateMethodInfo = _evaluateGenericMethodInfo.MakeGenericMethod(returnType); - evaluate = _cachedDelegates[returnType] = (EvaluateDelegate)Delegate.CreateDelegate(typeof(EvaluateDelegate), this, evaluateMethodInfo); - } - - return evaluate(treeId, targetObjectId, expressionList); - } - - private object EvaluateGeneric(long treeId, long targetObjectId, IEnumerable expressionList) - => _jsRuntime.Invoke(DynamicJSInterop.Evaluate, treeId, targetObjectId, expressionList)!; - } -} diff --git a/src/DynamicJS/src/JSExpressionTree.cs b/src/DynamicJS/src/JSExpressionTree.cs deleted file mode 100644 index bc44ce6f5..000000000 --- a/src/DynamicJS/src/JSExpressionTree.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSExpressionTree : IDisposable, IAsyncDisposable - { - private readonly IJSRuntime _jsRuntime; - - private readonly long _id; - - private readonly InProcessEvaluator? _inProcessEvaluator; - - private readonly IList _expressionList; - - private long _nextObjectId; - - private bool _disposed; - - internal JSObject Root { get; } - - public JSExpressionTree(IJSRuntime jsRuntime, long id, InProcessEvaluator? inProcessEvaluator = default) - { - _jsRuntime = jsRuntime; - _id = id; - _inProcessEvaluator = inProcessEvaluator; - _expressionList = new List(); - _nextObjectId = 1; - - Root = new JSObject(0, this); - } - - public JSObject AddExpression(IJSExpression expression) - { - ThrowIfDisposed(); - - var result = new JSObject(_nextObjectId, this); - - _nextObjectId++; - _expressionList.Add(expression); - - return result; - } - - public object Evaluate(Type returnType, long targetObjectId) - { - if (_inProcessEvaluator == null) - { - throw new InvalidOperationException( - $"Cannot synchronously evaluate an asynchronous JS expression tree as a {returnType}. " + - $"Use {nameof(JSObject.EvaluateAsync)} to evaluate the result asynchronously."); - } - - ThrowIfDisposed(); - - var result = _inProcessEvaluator.Evaluate(returnType, _id, targetObjectId, _expressionList); - _expressionList.Clear(); - - return result; - } - - public async ValueTask EvaluateAsync(long targetObjectId) - { - ThrowIfDisposed(); - - var result = await _jsRuntime.InvokeAsync(DynamicJSInterop.Evaluate, _id, targetObjectId, _expressionList); - _expressionList.Clear(); - - return result; - } - - public void Dispose() - { - if (_inProcessEvaluator == null) - { - throw new InvalidOperationException( - $"Cannot synchronously dispose an asynchronous JS expression tree. " + - $"Use {nameof(DisposeAsync)} to dispose the expression tree asynchronously."); - } - - if (_disposed) - { - return; - } - - // Evaluate the remaining expressions (targetObjectId of -1 clears the object cache). - _inProcessEvaluator.Evaluate(typeof(object), _id, -1, _expressionList); - _disposed = true; - } - - public async ValueTask DisposeAsync() - { - if (_disposed) - { - return; - } - - // Evaluate the remaining expressions (targetObjectId of -1 clears the object cache). - await _jsRuntime.InvokeAsync(DynamicJSInterop.Evaluate, _id, -1, _expressionList); - _disposed = true; - } - - private void ThrowIfDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException( - $"Cannot perform {nameof(JSObject)} operations after the root " + - $"{nameof(JSObject)} has been disposed!"); - } - } - } -} diff --git a/src/DynamicJS/src/JSExpressionType.cs b/src/DynamicJS/src/JSExpressionType.cs deleted file mode 100644 index aee17310c..000000000 --- a/src/DynamicJS/src/JSExpressionType.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal enum JSExpressionType - { - Property = 0, - Method = 1, - Invocation = 2, - Instantiation = 3, - Assignment = 4, - Binary = 5, - Unary = 6, - } -} diff --git a/src/DynamicJS/src/JSObject.cs b/src/DynamicJS/src/JSObject.cs deleted file mode 100644 index 1d9bbfb4c..000000000 --- a/src/DynamicJS/src/JSObject.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Dynamic; -using System.Linq.Expressions; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -namespace Microsoft.AspNetCore.DynamicJS -{ - /// - /// The .NET representation of a JavaScript object. - /// - [JsonConverter(typeof(JSObjectJsonConverter))] - public class JSObject : DynamicObject, IDisposable, IAsyncDisposable - { - private readonly JSExpressionTree _expressionTree; - - internal long Id { get; } - - /// - /// Creates a new instance from the provided root and .NET value. - /// - /// The root whose lifetime the new will match. - /// The .NET representation of the value of the new . - /// A new . - public static dynamic Create(JSObject root, object value) - { - if (root.Id != 0) - { - throw new InvalidOperationException( - $"Can only create new {nameof(JSObject)}s from an existing root {nameof(JSObject)}."); - } - - var expression = new JSInstantiationExpression - { - Value = value - }; - - var jsObject = root._expressionTree.AddExpression(expression); - expression.TargetObjectId = jsObject.Id; - - return jsObject; - } - - /// - /// Evaluates the value of the given . - /// - /// The expected result type. - /// The whose value should be evaluated. - /// - public static ValueTask EvaluateAsync(JSObject jsObject) - => jsObject._expressionTree.EvaluateAsync(jsObject.Id); - - internal JSObject(long id, JSExpressionTree jsExpressionTree) - { - Id = id; - _expressionTree = jsExpressionTree; - } - - private object ConvertTo(Type type) - { - if (type == typeof(object) || type == GetType()) - { - // If the target type is unspecific or equal to the existing type, return this instance. - return this; - } - else - { - // Otherwise, a synchronous evaluation is required. This will fail on an async expression tree. - return _expressionTree.Evaluate(type, Id); - } - } - - /// - public override bool TryConvert(ConvertBinder binder, out object? result) - { - result = ConvertTo(binder.Type); - return true; - } - - /// - public override bool TryGetMember(GetMemberBinder binder, out object? result) - { - result = _expressionTree.AddExpression(new JSPropertyExpression - { - TargetObjectId = Id, - Name = binder.Name - }); - return true; - } - - /// - public override bool TryInvokeMember(InvokeMemberBinder binder, object?[]? args, out object? result) - { - result = _expressionTree.AddExpression(new JSMethodExpression - { - TargetObjectId = Id, - Name = binder.Name, - Args = args - }); - return true; - } - - /// - public override bool TryInvoke(InvokeBinder binder, object?[]? args, out object? result) - { - result = _expressionTree.AddExpression(new JSInvocationExpression - { - TargetObjectId = Id, - Args = args - }); - return true; - } - - /// - public override bool TrySetMember(SetMemberBinder binder, object? value) - { - _expressionTree.AddExpression(new JSAssignmentExpression - { - TargetObjectId = Id, - Name = binder.Name, - Value = value - }); - return true; - } - - /// - public override bool TryBinaryOperation(BinaryOperationBinder binder, object? arg, out object? result) - { - result = AddBinaryExpression(binder.Operation, binder.ReturnType, arg); - return true; - } - - /// - public override bool TryUnaryOperation(UnaryOperationBinder binder, out object? result) - { - result = _expressionTree.AddExpression(new JSUnaryExpression - { - TargetObjectId = Id, - Operation = binder.Operation - }).ConvertTo(binder.ReturnType); - return true; - } - - /// - /// Represents an equality check between two instances. - /// - /// - /// This operation does not return a . Instead, it returns a - /// representing the result of the operation. Note that for this reason, - /// and have different behavior. - /// - /// A representing the result of the operation. - public static dynamic operator ==(JSObject jsObject1, JSObject jsObject2) - => jsObject1.AddBinaryExpression(ExpressionType.Equal, typeof(object), jsObject2); - - /// - /// Represents an inequality check between two instances. - /// - /// - /// This operation does not return a . Instead, it returns a - /// representing the result of the operation. Note that for this reason, ! - /// and have different behavior. - /// - /// A representing the result of the operation. - public static dynamic operator !=(JSObject jsObject1, JSObject jsObject2) - => jsObject1.AddBinaryExpression(ExpressionType.NotEqual, typeof(object), jsObject2); - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// - /// Since a is returned, a synchronous evaluation is implicitly performed. - /// For this reason, this operation is invalid in an asynchronous-only context. - /// - public override bool Equals(object? obj) - => (bool)AddBinaryExpression(ExpressionType.Equal, typeof(bool), obj); - - /// - public override int GetHashCode() - => base.GetHashCode(); - - private object AddBinaryExpression(ExpressionType operation, Type returnType, object? arg) - => _expressionTree.AddExpression(new JSBinaryExpression - { - TargetObjectId = Id, - Operation = operation, - Arg = arg - }).ConvertTo(returnType); - - /// - /// Disposes a root and all of its resources. - /// - /// - /// This operation performs a final synchronous evaluation of the remaining unevaluated expressions. - /// For this reason, this operation is invalid in an asynchronous-only context. - /// Use to dispose a root asynchronously. - /// - public void Dispose() - { - ThrowDisposeExceptionIfNonRoot(); - _expressionTree.Dispose(); - - GC.SuppressFinalize(this); - } - - /// - /// Disposes a root and all of its resources. - /// - /// - /// This operation performs a final asynchronous evaluation of the remaining unevaluated expressions. - /// - /// A representing the completion of the operation. - public ValueTask DisposeAsync() - { - ThrowDisposeExceptionIfNonRoot(); - return _expressionTree.DisposeAsync(); - } - - private void ThrowDisposeExceptionIfNonRoot() - { - if (Id != 0) - { - throw new InvalidOperationException($"Cannot dispose a non-root {nameof(JSObject)}."); - } - } - } -} diff --git a/src/DynamicJS/src/JSObjectJsonConverter.cs b/src/DynamicJS/src/JSObjectJsonConverter.cs deleted file mode 100644 index 1132fd2d6..000000000 --- a/src/DynamicJS/src/JSObjectJsonConverter.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Microsoft.AspNetCore.DynamicJS -{ - internal class JSObjectJsonConverter : JsonConverter - { - private static readonly string _objectIdKey = "__objectId"; - - public override JSObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new InvalidOperationException($"{typeof(JSObject)} does not support deserialization."); - } - - public override void Write(Utf8JsonWriter writer, JSObject value, JsonSerializerOptions options) - { - writer.WriteStartObject(); - writer.WriteNumber(_objectIdKey, value.Id); - writer.WriteEndObject(); - } - } -} diff --git a/src/DynamicJS/src/JSRuntimeExtensions.cs b/src/DynamicJS/src/JSRuntimeExtensions.cs deleted file mode 100644 index 90b082586..000000000 --- a/src/DynamicJS/src/JSRuntimeExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.JSInterop; - -namespace Microsoft.AspNetCore.DynamicJS -{ - /// - /// Contains extension methods for creating root instances. - /// - public static class JSRuntimeExtensions - { - private static InProcessEvaluator? _inProcessSyncEvaluator; - - private static long _nextTreeId; - - /// - /// Returns a dynamic representing the browser's window object. - /// - /// - /// If a relative to the returned needs to be evaluated as a .NET type, it must be done - /// via . Attempting to directly cast a - /// to a .NET type, either explicitly or implicitly, will throw an exception. - /// - /// The used to execute operations. - /// - public static dynamic GetDynamicWindow(this IJSRuntime jsRuntime) - { - return new JSExpressionTree(jsRuntime, _nextTreeId++).Root; - } - - /// - /// Returns a dynamic representing the browser's window object. - /// - /// - /// Operations performed involving the returned or its relatives do not need to be explicitly - /// evaluated. Instead, they occur when s are casted to other .NET types, either - /// explicitly or implicitly. - /// - /// The used to execute operations. - /// - public static dynamic GetInProcessDynamicWindow(this IJSInProcessRuntime jsRuntime) - { - _inProcessSyncEvaluator ??= new InProcessEvaluator(jsRuntime); - return new JSExpressionTree(jsRuntime, _nextTreeId++, _inProcessSyncEvaluator).Root; - } - } -} diff --git a/src/DynamicJS/src/Microsoft.AspNetCore.DynamicJS.csproj b/src/DynamicJS/src/Microsoft.AspNetCore.DynamicJS.csproj deleted file mode 100644 index cf0e7f0dc..000000000 --- a/src/DynamicJS/src/Microsoft.AspNetCore.DynamicJS.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net5.0 - 8.0 - enable - true - false - An API allowing JavaScipt-like interactions with JavaScript objects, all in a .NET context. - - - - - - - diff --git a/src/DynamicJS/src/wwwroot/dynamic.js b/src/DynamicJS/src/wwwroot/dynamic.js deleted file mode 100644 index 1a980510f..000000000 --- a/src/DynamicJS/src/wwwroot/dynamic.js +++ /dev/null @@ -1,224 +0,0 @@ -(function () { - const ExpressionType = { - PROPERTY: 0, - METHOD: 1, - INVOCATION: 2, - INSTANTIATION: 3, - ASSIGNMENT: 4, - BINARY: 5, - UNARY: 6, - }; - - // These values are a subset of those specified in .NET's System.Linq.Expressions.ExpressionType. - // The criteria for which values are included is based on - // https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.dynamicobject.trybinaryoperation - // and - // https://docs.microsoft.com/en-us/dotnet/api/system.dynamic.dynamicobject.tryunaryoperation - const Operation = { - ADD: 0, - AND: 2, - DIVIDE: 12, - EQUAL: 13, - EXCLUSIVE_OR: 14, - GREATER_THAN: 15, - GREATER_THAN_OR_EQUAL: 16, - LEFT_SHIFT: 19, - LESS_THAN: 20, - LESS_THAN_OR_EQUAL: 21, - MODULO: 25, - MULTIPLY: 26, - NEGATE: 28, - UNARY_PLUS: 29, - NOT: 34, - NOT_EQUAL: 35, - OR: 36, - RIGHT_SHIFT: 41, - SUBTRACT: 42, - DECREMENT: 49, - INCREMENT: 54, - ADD_ASSIGN: 63, - AND_ASSIGN: 64, - DIVIDE_ASSIGN: 65, - EXCLUSIVE_OR_ASSIGN: 66, - LEFT_SHIFT_ASSIGN: 67, - MODULO_ASSIGN: 68, - MULTIPLY_ASSIGN: 69, - OR_ASSIGN: 70, - RIGHT_SHIFT_ASSIGN: 72, - SUBTRACT_ASSIGN: 73, - ONES_COPMPLEMENT: 82, - IS_TRUE: 83, - IS_FALSE: 84, - }; - - const objectIdPropertyName = '__objectId'; - const objectCacheByTreeId = {}; - - function getOrCreateObjectCache(treeId) { - let cache = objectCacheByTreeId[treeId]; - - if (!cache) { - cache = [window]; - objectCacheByTreeId[treeId] = cache; - } - - return cache; - } - - function evaluateBinaryExpression(e, target) { - switch (e.operation) { - case Operation.ADD: - return target + e.arg; - case Operation.AND: - return target & e.arg; - case Operation.DIVIDE: - return target / e.arg; - case Operation.EQUAL: - return target === e.arg; - case Operation.EXCLUSIVE_OR: - return target ^ e.arg; - case Operation.GREATER_THAN: - return target > e.arg; - case Operation.GREATER_THAN_OR_EQUAL: - return target >= e.arg; - case Operation.LEFT_SHIFT: - return target << e.arg; - case Operation.LESS_THAN: - return target < e.arg; - case Operation.LESS_THAN_OR_EQUAL: - return target <= e.arg; - case Operation.MODULO: - return target % e.arg; - case Operation.MULTIPLY: - return target * e.arg; - case Operation.NOT_EQUAL: - return target !== e.arg; - case Operation.OR: - return target | e.arg; - case Operation.RIGHT_SHIFT: - return target >> e.arg; - case Operation.SUBTRACT: - return target - e.arg; - case Operation.ADD_ASSIGN: - return target += e.arg; - case Operation.AND_ASSIGN: - return target &= e.arg; - case Operation.DIVIDE_ASSIGN: - return target /= e.arg; - case Operation.EXCLUSIVE_OR_ASSIGN: - return target ^= e.arg; - case Operation.LEFT_SHIFT_ASSIGN: - return target <<= e.arg; - case Operation.MODULO_ASSIGN: - return target %= e.arg; - case Operation.MULTIPLY_ASSIGN: - return target *= e.arg; - case Operation.OR_ASSIGN: - return target |= e.arg; - case Operation.RIGHT_SHIFT_ASSIGN: - return target >>= e.arg; - case Operation.SUBTRACT_ASSIGN: - return target -= e.arg; - default: - throw new Error(`Unknown binary operation with ID ${e.operation}.`); - } - } - - function evaluateUnaryExpression(e, target) { - switch (e.operation) { - case Operation.NEGATE: - return -target; - case Operation.UNARY_PLUS: - return +target; - case Operation.NOT: - return !target; - case Operation.DECREMENT: - return --target; - case Operation.INCREMENT: - return ++target; - case Operation.ONES_COPMPLEMENT: - return ~target; - case Operation.IS_TRUE: - return !!target; - case Operation.IS_FALSE: - return !target; - default: - throw new Error(`Unknown unary operation with ID ${e.operation}.`); - } - } - - function evaluateExpression(e, target) { - switch (e.type) { - case ExpressionType.PROPERTY: - return target[e.name]; - case ExpressionType.METHOD: - return target[e.name].apply(target, e.args); - case ExpressionType.INVOCATION: - return target.apply(null, e.args); - case ExpressionType.INSTANTIATION: - return e.value; - case ExpressionType.ASSIGNMENT: - return target[e.name] = e.value; - case ExpressionType.BINARY: - return evaluateBinaryExpression(e, target); - case ExpressionType.UNARY: - return evaluateUnaryExpression(e, target); - default: - throw new Error(`Unknown expression type with ID ${e.type}.`); - } - } - - function generateRevivals(root, revivalsByObjectId) { - Object.entries(root).forEach(function ([key, value]) { - if (value !== null && typeof value === 'object') { - if (value.hasOwnProperty(objectIdPropertyName)) { - const objectId = value[objectIdPropertyName]; - const revivals = revivalsByObjectId[objectId] || (revivalsByObjectId[objectId] = []); - revivals.push({ - parent: root, - key, - }); - } else { - generateRevivals(value, revivalsByObjectId); - } - } - }); - } - - function evaluate(treeId, targetObjectId, expressionList) { - const cache = getOrCreateObjectCache(treeId); - const revivalsByObjectId = {}; - - expressionList.forEach(function (e) { - generateRevivals(e, revivalsByObjectId); - }); - - expressionList.forEach(function (e) { - const target = cache[e.targetObjectId]; - const result = evaluateExpression(e, target); - - const resultObjectId = cache.length; - const revivals = revivalsByObjectId[resultObjectId]; - - if (revivals) { - revivals.forEach(function ({ parent, key }) { - parent[key] = result; - }); - } - - cache[resultObjectId] = result; - }); - - if (targetObjectId < 0) { - // This signals that we don't expect a result, and the current state should be disposed. - delete objectCacheByTreeId[treeId]; - } else { - // Return the target object. - return cache[targetObjectId]; - } - } - - window.dynamicJS = { - evaluate, - }; -})();