Skip to content

refactor: drop the liveMode IORef, thread live explicitly - #1633

Merged
dmjio merged 1 commit into
masterfrom
refactor/drop-livemode-ioref
Sep 3, 2026
Merged

refactor: drop the liveMode IORef, thread live explicitly#1633
dmjio merged 1 commit into
masterfrom
refactor/drop-livemode-ioref

Conversation

@dmjio

@dmjio dmjio commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the global liveMode :: IORef Bool (a NOINLINE / unsafePerformIO top-level ref set once in initComponent) and passes the live-reload flag as an explicit Bool argument through the runtime instead.

The flag gates key-based model recovery in initialize — outside hot reload, a keyed component must never inherit a previous (possibly unrelated) component's model just because it shares a Key. That rationale now lives on the parameter's haddock instead of the IORef's.

Changes (src/Miso/Runtime.hs)

  • initialize takes a new live :: Bool parameter (after isRoot); the readIORef liveMode at the model-recovery check is replaced by the parameter.
  • buildVTree gains the same parameter and threads it through both recursive child-building calls; its nested buildComp passes it to the recursive initialize for VComp / VCompStatic children — including keyed ones, where the flag actually matters.
  • initialDraw gains the parameter and forwards it to both of its buildVTree calls (initial draw and the hydration-failure redraw).
  • initComponent passes its existing live argument straight into initialize; the atomicWriteIORef liveMode live is deleted.
  • componentListener (NATIVE / Lynx MTS) takes live as well, supplied at its registration site in initComponent, so MTS-mounted children — and their keyed descendants via buildVTree — observe the same value the IORef would have held.
  • liveMode definition, NOINLINE pragma, and doc comment removed. The ref was not exported, so nothing outside Miso.Runtime is affected.
  • Cosmetic: initSubs type signature reformatted to one argument per line.

Verification

  • cabal build miso with the project defaults (+template-haskell +native, GHC 9.12.2) compiles cleanly — covers the NATIVE branch.
  • The non-native (web / SSR) flavor, built with only +template-haskell, compiles cleanly as well.

No behavior change intended: every call site receives exactly the value the IORef would have contained at that point.

Remove the global `liveMode :: IORef Bool` (a `NOINLINE` /
`unsafePerformIO` top-level ref set once in `initComponent`) and pass
the live-reload flag as an explicit `Bool` argument instead. The flag
gates key-based model recovery in `initialize` — outside hot reload, a
keyed component must never inherit a previous (possibly unrelated)
component's model just because it shares a `Key`.

## Changes

- **`initialize`**: takes a new `live :: Bool` parameter (documented
  with the recovery-gating rationale formerly on the IORef). The
  `readIORef liveMode` at the model-recovery check is replaced by the
  parameter.
- **`buildVTree`**: gains the same parameter and threads it through
  both recursive child-building calls; its nested `buildComp` passes it
  to the recursive `initialize` for `VComp` / `VCompStatic` children —
  including keyed ones, where the flag actually matters.
- **`initialDraw`**: gains the parameter and forwards it to both of its
  `buildVTree` calls (the initial draw and the hydration-failure
  redraw).
- **`initComponent`**: passes its existing `live` argument straight
  into `initialize`; the `atomicWriteIORef liveMode live` is deleted.
- **`componentListener`** (NATIVE / Lynx MTS): takes `live` as well,
  supplied at its registration site in `initComponent`, so MTS-mounted
  children — and their keyed descendants via `buildVTree` — observe the
  same value the IORef would have held.
- **`liveMode`** definition, its `NOINLINE` pragma, and its doc comment
  are removed. The ref was not exported, so no module outside
  `Miso.Runtime` is affected.
- Cosmetic: `initSubs` type signature reformatted to one argument per
  line.

## Verification

- `cabal build miso` (project default `+template-haskell +native`,
  GHC 9.12.2): compiles cleanly, covering the `NATIVE` branch.
- Non-native (web / SSR) flavor built via a temporary project file with
  only `+template-haskell`: compiles cleanly.

No behavior change intended: every call site receives exactly the value
the IORef would have contained at that point.
@dmjio
dmjio merged commit 7c94b81 into master Sep 3, 2026
6 checks passed
@dmjio
dmjio deleted the refactor/drop-livemode-ioref branch September 3, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant