From c0c1a728510ac529e39f1ffcdb2a1b2704a6200a Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Mon, 28 Sep 2026 06:25:36 +0000 Subject: [PATCH] The write compare was comparing two orderings of the same set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rega's L43 check: three of four pass — the row-click shader compile is 0 ms on both engines (was 3.8 s / 7.5 s), the tab visit is no worse, the highlight stays. The collapse did not: still nine setPaintProperty calls per row click instead of three. Their hypothesis is right, and I had the evidence before I wrote the code. The two callers build the same region from different lists — node.isoCodes and mapLayers.regionIsoMap[slug] — and they do not agree on ORDER. rega said so in the very first stack trace on this bug: "a case over ['IND',…]" from one path, "a case over ['MYS',…], a different literal order" from the other. I then wrote a JSON-string compare, which cannot match two orderings of one set. The pre-warm half worked because that expression is a shared constant; this half compared text that was never going to be equal. The list is now canonical before both the compare and the write — de-duplicated, upper-cased, sorted — so the expression is a function of the SET, which is the thing the two callers actually agree on. Order is irrelevant to `in` membership, and the case normalisation is a no-op on today's data (both lists come from the same regions dataset, and the highlight matches now, so they are already upper-case); it is there so a future source that ships lower-case cannot silently select nothing. ★ IT IS ALSO A TEST, and worth reading as one. If the count drops to 3, the two sources agree about which countries are in a region. If it does not, they disagree about the CONTENT — a data defect this compare would otherwise have hidden behind a last-writer-wins repaint, and the next thing to chase. Verified: gates:pre 13/13. Chained on f7a2f001 (same file). Needs rega: re-count with the same probe. --- plugin-designs/doxa-research-map/research-map.vue | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugin-designs/doxa-research-map/research-map.vue b/plugin-designs/doxa-research-map/research-map.vue index a33a225f9..3c8a6aa93 100644 --- a/plugin-designs/doxa-research-map/research-map.vue +++ b/plugin-designs/doxa-research-map/research-map.vue @@ -1113,7 +1113,19 @@ const REGION_IDLE_COLOR = ['case', ['has', 'iso_3166_1_alpha_3'], 'rgba(60,60,80 const REGION_IDLE_WIDTH = ['case', ['has', 'iso_3166_1_alpha_3'], 0.6, 0.6] function paintRegionScope(m, isoCodes) { if (!m || !m.getLayer('regions-fill')) return - const list = Array.isArray(isoCodes) ? isoCodes.filter(Boolean) : [] + // ★ CANONICAL FIRST, OR THE COMPARE BELOW IS A LIE (rega, L43: still 9 writes per click, not 3). + // The two sources build the same region from different lists — node.isoCodes and + // mapLayers.regionIsoMap[slug] — and they do not agree on ORDER. rega had already told me that in + // the very first stack trace ("a case over ['IND',…]" then "a case over ['MYS',…], a different + // literal order") and I wrote a JSON-string compare anyway, which can never match two orderings of + // the same set. Sorting and de-duplicating makes the expression a function of the SET, which is what + // the two callers actually agree on. + // + // It is also a test: if the write count does not drop to 3, the two sources disagree about WHICH + // countries are in the region, which is a data defect this compare would otherwise have hidden. + const list = Array.isArray(isoCodes) + ? [...new Set(isoCodes.filter(Boolean).map((c) => String(c).toUpperCase()))].sort() + : [] const isoArr = ['literal', list] const fill = list.length ? ['case', ['in', ['get', 'iso_3166_1_alpha_3'], isoArr], 0.85, 0.15] : REGION_IDLE_FILL const color = list.length ? ['case', ['in', ['get', 'iso_3166_1_alpha_3'], isoArr], '#111827', 'rgba(60,60,80,0.15)'] : REGION_IDLE_COLOR