fix(web): vendor the Macroquad browser loader

The page depended on the externally hosted miniquad bundle, which violates a
same-origin `script-src 'self'` policy and makes the game depend on a third
party at runtime. Vendor the current official loader alongside the web assets
and move the WASM `load` call into a local bootstrap script, preserving plugin
registration order without inline JavaScript.

Document the CSP requirement for WebAssembly compilation and same-origin
connections. The vendored bundle is the current response from the official
Macroquad loader URL and was syntax-checked before committing.

Test Plan:
- `just web-build` -- passed
- `node --check web/mq_js_bundle.js web/storage.js web/bootstrap.js` -- passed
- `prettier --check web/storage.js web/bootstrap.js` -- passed
- Browser smoke test with `script-src 'self' 'wasm-unsafe-eval'` and `connect-src 'self'` -- passed; 640x460 canvas and no CSP/script errors
- `git diff --cached --check` -- passed
This commit is contained in:
2026-08-29 17:12:43 +02:00
parent a81741b470
commit acb0c20b59
5 changed files with 18 additions and 7 deletions
+2
View File
@@ -10,6 +10,8 @@ and this project adheres to
### Fixed ### Fixed
- Bundle the official Macroquad browser loader and WASM bootstrap locally so a
CSP does not require inline JavaScript or code from `not-fl3.github.io`.
- Add the optional same-origin Axum/SQLite high-score service, browser - Add the optional same-origin Axum/SQLite high-score service, browser
fetch/submit integration, and an nginx reverse-proxy example. Browser fetch/submit integration, and an nginx reverse-proxy example. Browser
settings retain their local-storage fallback, while the shared table is settings retain their local-storage fallback, while the shared table is
+8 -3
View File
@@ -11,9 +11,14 @@ The game is compiled for `wasm32-unknown-unknown` and loaded into a fixed
a fallback copy of the high-score table are saved in `localStorage`; native a fallback copy of the high-score table are saved in `localStorage`; native
builds continue to use their normal per-user save file. builds continue to use their normal per-user save file.
The page uses Macroquad's official browser loader from the miniquad samples The page includes the official Macroquad browser loader locally. The WASM
site. The web page must be served over HTTP rather than opened directly from a bootstrap is local as well, so the page does not require inline or third-party
`file:` URL. JavaScript. The web page must be served over HTTP rather than opened directly
from a `file:` URL.
For a strict Content Security Policy, allow `script-src 'self'
'wasm-unsafe-eval'` for the browser's WebAssembly compilation and
`connect-src 'self'` for the local WASM and optional high-score API requests.
When the same-origin `/api/highscores` endpoint is available, the browser loads When the same-origin `/api/highscores` endpoint is available, the browser loads
and submits the shared top-ten table there. The small Axum service and an nginx and submits the shared top-ten table there. The small Axum service and an nginx
+3
View File
@@ -0,0 +1,3 @@
"use strict";
load("tdkpin-rs.wasm");
+2 -4
View File
@@ -46,10 +46,8 @@
<body> <body>
<canvas id="glcanvas" tabindex="1" aria-label="TDK Pinball Machine"></canvas> <canvas id="glcanvas" tabindex="1" aria-label="TDK Pinball Machine"></canvas>
<noscript>This game needs JavaScript enabled.</noscript> <noscript>This game needs JavaScript enabled.</noscript>
<script src="https://not-fl3.github.io/miniquad-samples/mq_js_bundle.js"></script> <script src="./mq_js_bundle.js"></script>
<script src="./storage.js"></script> <script src="./storage.js"></script>
<script> <script src="./bootstrap.js"></script>
load("tdkpin-rs.wasm");
</script>
</body> </body>
</html> </html>
File diff suppressed because one or more lines are too long