Reference
60-second design-review scan + two-tab hands-on. Print-friendly.
window.postMessage / ports, not BroadcastChannel.
postMessage →
close() on teardown; namespaced channel names.
| Risk | What to check |
|---|---|
| Origin / name | Exact origin partitioning; exact channel string; typos = silent silence |
| Sender excluded | Local UI path exists without relying on self-echo |
| Order / delivery | Best-effort notify; no total order across agents; not a commit log |
| Closed channel |
No post after close(); unmount cleanup doesn’t
leave stale refs posting
|
| Payload size | Clone cost; keep signals small |
| Support | Modern Chromium / Firefox / Safari 15.4+ baseline; fallback if needed |
| Truth | Server or durable client store owns authority; BC is a hint |
new BroadcastChannel("lab") and logs
onmessage.
postMessage({ type: "ping", n: 1 }) — Tab B
logs; Tab A does not log its own post.
"Lab" — silence (exact match).
close() on Tab A’s channel, then post again — expect
InvalidStateError.
// Logout
doLogoutLocal(); showLoggedOut(); ch.postMessage({ type: "logout" });
// Theme (persist separately)
applyTheme(v); localStorage.setItem("theme", v);
ch.postMessage({ type: "theme", value: v });
// Invalidate list (truth = server or IDB)
ch.postMessage({ type: "invalidate", resource: "orders" });
// peers: refetch or re-read store — do not trust the message alone