WasmPlayer: browser-WASM AOT game player#1782
Merged
Merged
Conversation
- New `src/WasmPlayer/` project targeting `browser-wasm` with `[JSExport]` entry points for game control and `[JSImport]` callbacks for all UI events - Move `player.js` from `WebPlayer/wwwroot/` into `PlayerCore/Resources/` so it's shared between WebPlayer and WasmPlayer; update Game.razor src path - `index.html` embeds the playercore.htm UI inline for a standalone AppBundle - `wasm-player.js` replaces `playerweb.js` with WASM bridge calls behind the same `WebPlayer.*` surface API that playercore.js and player.js already use Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The publish output places dotnet.js at the root of the publish directory, not under _framework/ (that layout is only in AppBundle, used by WebEditor). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Content items with CopyToPublishDirectory go to the publish/ staging dir, not the AppBundle. Use an AfterTargets="_WasmGenerateAppBundle" target to copy player JS/CSS/HTML and lib/ assets directly to WasmAppDir (the AppBundle). Also fix dotnet.js import to use ./_framework/ (AppBundle layout). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Engine's reflection-based type discovery (Classes.GetImplementations + Activator.CreateInstance) is incompatible with the IL trimmer — trimming removes constructors that are only reached at runtime via Assembly.GetTypes(). Disable PublishTrimmed until the Engine gets explicit trimmer roots. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The package was never used in PlayerCore code. Its .NET Standard 2.0 assemblies reference System.Runtime.InteropServices.RuntimeInformation via token lookups that fail at load time in the browser-wasm runtime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
node src/WasmPlayer/dev-server.mjs starts a local server at :5175 that serves the Debug AppBundle with Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers required by the .NET WASM runtime. Also serves examples/ at /examples/* for easy game testing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…script error recursion - Enable RunAOTCompilation and IL trimming in WasmPlayer.csproj - Add WasmPlayer.linker.xml to preserve Engine assembly (uses reflection-based type discovery) - Replace reflection-based JsonSerializer calls with source-generated WasmJsonContext, and add SerializeJsArg() helper that dispatches on concrete type for object[] JS arguments (including QuestDictionary<string> and QuestList<string> passed to JS.updateObjectLinks etc.) - Fix infinite recursion in WorldModel.RunScriptAsync: the catch block calling PrintAsync() could re-enter OutputText, which would throw the same exception and recurse until stack overflow; guard with _reportingScriptError flag to skip the PrintAsync call on re-entry - paper.js null guard in playercore.js (paper.view may be null if canvas is missing) - Dev server --release flag support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- player.js sendCommand: reduce setTimeout from 100ms to 0ms — yields one browser tick so the input clears visually before WASM execution begins, without the previous artificial 100ms delay - CLAUDE.md: add WasmPlayer build and dev server commands; correct architecture entry (browser-wasm/AOT, not Blazor WebAssembly); expand WasmPlayer description with trimming/linker details - Delete docs/async-ncalc-wasm-plan.md (implementation complete) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…index.html Fetch playercore.htm at runtime (in parallel with the WASM runtime load via Promise.all) and inject it into the body, so playercore.htm remains the single source of truth. Add playercore.htm to the CopyPlayerAssetsToAppBundle target so it lands in the AppBundle. Move addPaperScript() from an inline script in index.html into wasm-player.js where it belongs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
browser-wasmtarget, AOT-compiled) that runs entirely as a static site with no server-side .NET requiredJSImport/JSExportfor JS↔C# interop; sharesPlayerCore,Engine, and all JS/CSS assets with the existing WebPlayerWasmPlayer.linker.xmlpreserving the Engine assembly (reflection-based type discovery)JsonSerializer.Serialize(object)calls with a source-generatedWasmJsonContextand aSerializeJsArg()helper that dispatches on concrete type (includingQuestDictionary<string>andQuestList<string>forupdateObjectLinksetc.)RunScriptAsync's catch block callingPrintAsynccould re-enterOutputText, which would throw the same exception and recurse until stack overflow; guarded with_reportingScriptErrorflagsrc/WasmPlayer/dev-server.mjs) sets required COOP/COEP headers forSharedArrayBufferand supports--releaseflagsendCommand(now 0ms — one browser tick to clear the input, then WASM runs)Test plan
dotnet build src/WasmPlayer/WasmPlayer.csproj(Debug)dotnet build --configuration Release src/WasmPlayer/WasmPlayer.csproj(AOT)node src/WasmPlayer/dev-server.mjs --release→ openhttp://localhost:5175/?game=/examples/simple.aslxdotnet test --configuration Releasepasses🤖 Generated with Claude Code