Skip to content

Incorporate dual-thread architecture.#70

Draft
dmjio wants to merge 46 commits intomasterfrom
incorporate-dual-thread-arch
Draft

Incorporate dual-thread architecture.#70
dmjio wants to merge 46 commits intomasterfrom
incorporate-dual-thread-arch

Conversation

@dmjio
Copy link
Member

@dmjio dmjio commented Feb 2, 2026

Incorporate dual-thread architecture 🍜 🐈

Intro 🧵🧵

This PR splits up processing of events and DOM operations across both background and main threads. This should give us access to native modules in swift / kotlin via the BTS.

This works by abstracting out all DOM operations during diffing for transfer via Web Worker to the MTS from the BTS. It also splits up event delegation to occur between both MTS and BTS threads (for events marked as background-only specifically). The patch infrastructure has already been added into miso so we just need to consume it and pass messages via the Web Workers.

Architecture 🏗️

sequenceDiagram
    participant MTS as MTS
    participant BTS as BTS
    participant MISO as Miso Runtime

    MISO->>BTS: Initialize Component tree
    BTS->>MTS: Receive BTS + MTS events
    MTS->>MTS: Register events
    BTS->>MTS: Component mount / model hydration   
    BTS->>MTS: Initial draw (Patches)
    MTS->>MTS: DOM update
    MTS->>MTS: Receive / Process MTS Event
    MTS->>MTS: Receive BTS Event
    MTS->>BTS: Forward BTS Event (e.g., tap)
    BTS->>MISO: Update State / Perform Effects
    MISO->>MISO: Native module access
    MISO->>BTS: Diff + Create Patches
    BTS->>MTS: Forward Patches
    MTS->>MTS: DOM Update

Loading

TODO 🚧

  • Define PATCH protocol between BTS and MTS for DOM, Event, Component model hydration.
  • Implement drawingContext + eventContext for BTS & MTS.
    • Implement InsertBefore
    • Implement SwapDOMRefs
    • Implement CreateElement
    • Implement CreateElementNS
    • Implement CreateTextNode
    • Implement SetAttribute
    • Implement SetAttributeNS
    • Implement AppendChild
    • Implement RemoveChild
    • Implement ReplaceChild
    • Implement RemoveAttribute
    • Implement SetTextContent
    • Implement SetInlineStyle
    • Implement Flush
    • Implement AddClass
    • Implement RemoveClass
    • Implement AddEventListeners
    • Implement MountComponent
    • Implement UnmountComponent
    • Implement ModelHydration
  • Consume types from miso
  • Use ReactLynx plugin (does proper code splitting on designated 'main thread' events).
  • Init globalThis.patches and globalThis.nodeId on BTS
  • Set miso.drawingContext = patchDrawingContext on BTS
  • Define two drawing context (MTS & BTS).
  • Use capture
  • Implement ProcessEvent (via delegator imp.)
    • Map NodeId wrapper over each element in event stack.
    • Use delegateEvent
  • Update miso to add mount / unmount FFI calls for ComponentContext<T>, and for model hydration. No-op in miso, but used in lynx for model hydration. Also required for main thread events.
  • Abstract requestAnimationFrame into DrawingContext<T> (BTS shouldn't rAF).
  • Make main thread events exist top-level (move out of Component)
  • Use __CreateComponent to populate components map.

Etc.

Adding Main Thread Events can be implemented later (not required for access to native modules). This requires the BTS to deliver events to the main thread on app load (since they're defined in Haskell and not JS).

  • Some additional work can be done in miso to abstract out event delegation into the EventContext.

  • We'll also need to upstream the protocol defined in miso-lynx back into miso and have miso-lynx consume it via npm (once stable).

Considerations

  • We could allow the MTS to perform the initial draw, and send the next nodeId to BTS for all subsequent draws. This might be more performant and necessary for IFR.

dmjio added 11 commits February 2, 2026 16:36
🚧 :wip:

```
sequenceDiagram
    participant UI as UI Thread
    participant MT as Message Transporter
    participant WT as Background Thread
    participant SM as State Manager

    UI->>MT: User Event (e.g., click)
    MT->>WT: Forward Event
    WT->>SM: Process Logic/Update State
    SM->>WT: State Update / Effects
    WT->>MT: Diff (make patches)
    MT->>UI: Forward patches
    UI->>UI: DOM Update
```

This PR splits up processing of events and DOM operations across both background and main threads.
This should give us access to native modules in `swift` / `kotlin`, etc.

This works by abstracting out all DOM operations during diffing for
transfer via Web Worker to the MTS from the BTS. Much of this has
already been incorporated into miso so we just need to wire it up.

- [x] Define `PATCH` protocol between BTS and MTS for DOM and event messages.
- [ ] Implement `InsertBefore`
- [ ] Implement `SwapDOMRefs`
- [x] Implement `CreateElement`
- [x] Implement `CreateElementNS`
- [ ] Implement `CreateTextNode`
- [ ] Implement `SetAttribute`
- [ ] Implement `SetAttributeNS`
- [ ] Implement `AppendChild`
- [ ] Implement `RemoveChild`
- [ ] Implement `ReplaceChild`
- [ ] Implement `RemoveAttribute`
- [ ] Implement `SetTextContent`
- [ ] Implement `SetInlineStyle`
- [ ] Implement `MountComponent`
- [ ] Implement `UnmountComponent`
- [ ] Implement `ModelHydration`
- [ ] Implement `AddClass`
- [ ] Implement `RemoveClass`
- [x] Implement `AddEventListeners`
- [ ] Implement `ProcessEvent` (must be done in `miso`)
- [ ] Implement `Flush`
- [ ] Use `ReactLynx` plugin (does proper code splitting on designed `'main thread'` events).

Adding Main Thread Events support is optional (for now) and can be
implemented later. This requires the BG thread to deliver events
to the main thread on app load (since they're defined in Haskell and not JS).

Some additional work will need to be done in `miso` to abstract out
event delegation into the `EventContext`.

We'll also need to upstream the protocol defined in `miso-lynx` back
into `miso` and have `miso-lynx` consume it via `npm` (once its stable).
@dmjio dmjio force-pushed the incorporate-dual-thread-arch branch from a65c506 to c3f4bb8 Compare February 3, 2026 03:07
@dmjio
Copy link
Member Author

dmjio commented Feb 4, 2026

dmjio/miso#1395

@dmjio dmjio force-pushed the incorporate-dual-thread-arch branch from dc8d96e to 41c66c6 Compare February 5, 2026 00:30
@dmjio dmjio force-pushed the incorporate-dual-thread-arch branch from 341f2fb to 69d4f42 Compare February 5, 2026 17:05
@dmjio
Copy link
Member Author

dmjio commented Feb 6, 2026

image

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