fix: web text corruption, blocking-load notice, no-cache dev server
**Most UI text drew with raylib's built-in font, not the loaded one.** Thirteen call sites used DrawText/MeasureText directly instead of the project's DrawTextScaled/MeasureTextScaled wrappers, so the cursor and marker readouts, spectrum panel labels and export toast rendered from raylib's default bitmap atlas. On desktop that merely looked slightly off; on web it renders as garbage. The only raw calls left are the two fallbacks inside the wrappers themselves. **The rail tooltip held a dangling pointer.** RailButton stored a TextFormat() result for the deferred draw pass, and raylib documents that string as expiring once TextFormat has been called a few more times — which it has by then. It copies into owned storage now. **Loading a large file in the browser looked like a crash.** The web build computes its whole STFT in one synchronous pass, with no frame presented in between, so nothing drawn on the canvas during that window ever reaches the screen. A notice now goes into the host DOM instead, which the browser paints independently, and yields once so that paint actually happens before the work starts. Because that yield unwinds the stack under ASYNCIFY, the load block is guarded by stftBusy — without it the re-entered main loop calls ComputeSTFTInit again and frees the STFT the suspended call is still building. **Removed EXPORTED_FUNCTIONS from the web link flags.** It replaces emscripten's default export list rather than extending it, so everything unnamed is dead-code-eliminated. The upload callback stays reachable via the EMSCRIPTEN_KEEPALIVE already on its definition. **Adds serve_web.py**, a dev server that sends no-store. Browsers cache .wasm hard enough that a plain reload runs a stale module while the page looks freshly loaded — which makes a rebuild appear to change nothing. That cost most of a debugging session today: three separate fixes were tested against a binary that never changed, each returning an identical fault at an identical address. README now points at it and says why. Documents the remaining web issue in known_bugs.md: large captures still corrupt text after loading. Leading theory is ALLOW_MEMORY_GROWTH reallocating the heap mid-load and invalidating pointers cached across that moment, which fits the symptom being text specifically. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V8ZWfr5XZyyDttvkhJUgHN
This commit is contained in:
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Dev server for bin/web with caching disabled.
|
||||
|
||||
The browser aggressively caches .wasm/.js, and a plain reload (Ctrl+R) will
|
||||
happily serve a stale module while the page *looks* freshly loaded — which makes
|
||||
"did my rebuild take effect?" impossible to answer and sends you chasing bugs
|
||||
that were already fixed. Everything here is served no-store so a rebuild is
|
||||
always what you get, regardless of how the page is reloaded.
|
||||
"""
|
||||
import http.server, socketserver, sys
|
||||
|
||||
PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8080
|
||||
|
||||
class NoCache(http.server.SimpleHTTPRequestHandler):
|
||||
def end_headers(self):
|
||||
self.send_header("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
|
||||
self.send_header("Pragma", "no-cache")
|
||||
self.send_header("Expires", "0")
|
||||
super().end_headers()
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
pass # quiet; the build script is the interesting output
|
||||
|
||||
socketserver.TCPServer.allow_reuse_address = True
|
||||
with socketserver.TCPServer(("", PORT), NoCache) as httpd:
|
||||
print(f"serving bin/web on http://localhost:{PORT}/rspektrum.html (no-store)")
|
||||
httpd.serve_forever()
|
||||
Reference in New Issue
Block a user