[object Object]

← back to Quadrille Showroom

snapshot before Slice 2: cladToken boot-race guard (in-flight onload invalidation)

13c193b7524f798636b3fc0d241e66057725db04 · 2026-06-28 17:07:03 -0700 · Steve Abrams

Files touched

Diff

commit 13c193b7524f798636b3fc0d241e66057725db04
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jun 28 17:07:03 2026 -0700

    snapshot before Slice 2: cladToken boot-race guard (in-flight onload invalidation)
---
 public/js/showroom.js | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/public/js/showroom.js b/public/js/showroom.js
index 4ebdcf7..74afd17 100644
--- a/public/js/showroom.js
+++ b/public/js/showroom.js
@@ -746,13 +746,22 @@ function addWall(x, y, z, w, h, rotY, mat) {
 // WALL CLADDING — render the selected pattern onto the room walls
 // ============================================================
 const PHYS_TILE_M = 0.686; // assumed physical tile ≈ 27" so the pattern reads at room scale
+// Monotonic clad token: every cladWalls() bumps it; a deferred image onload only paints
+// if it's still the latest request AND walls should be clad (a wing is focused). This
+// kills the boot race where a transient Hero focus's async onload repainted the walls
+// AFTER enterGuidedDefault reverted them back to neutral cream (Slice-1 boot invariant).
+let _cladToken = 0;
+function _cladStillWanted(token) {
+  return token === _cladToken && (wallsAutoClad || focusedWing);
+}
 function cladWalls(imageUrl, isSeamlessTile) {
   if (!imageUrl || !roomWalls.length) return;
+  const token = ++_cladToken;
   const cached = imageTexCache[imageUrl];
-  if (cached && cached.texture && cached.texture.image) { applyWallImage(cached.texture.image, isSeamlessTile); return; }
+  if (cached && cached.texture && cached.texture.image) { if (_cladStillWanted(token)) applyWallImage(cached.texture.image, isSeamlessTile); return; }
   const src = imageUrl.charAt(0) === '/' ? imageUrl : ('/api/proxy/image?url=' + encodeURIComponent(imageUrl));
   const img = new Image();
-  img.onload = () => applyWallImage(img, isSeamlessTile);
+  img.onload = () => { if (_cladStillWanted(token)) applyWallImage(img, isSeamlessTile); };
   img.src = src;
 }
 
@@ -778,6 +787,7 @@ function applyWallImage(img, isSeamlessTile) {
 }
 
 function revertWalls() {
+  _cladToken++;                 // invalidate any in-flight clad onload (boot-race guard)
   roomWalls.forEach(w => {
     w.mesh.material = w.origMat;
     if (w.cladMat && w.cladMat.map) { w.cladMat.map.dispose(); w.cladMat.map = null; }

← 04ca167 /5x sweep-1 report: Slice-1 build verified clean (HTTP/rende  ·  back to Quadrille Showroom  ·  auto-save: 2026-06-28T17:15:46 (1 files) — public/js/showroo 966628f →