Mounts and lifetimes
A mount is a view placed in a DOM element: its nodes, its instances' owners, effects and listeners, and a handle that disposes all of them. Mounting runs in the browser under Fable; the functions are in Ranvier.View.Dom.Mounting.
Mounting a component
let mounted =
Mounting.mount graph None report host None (fun context ->
Program.run (Component.render counter { Start = 0; Label = "Clicks" }) context.Backend)
Mounting.mount graph parentOwner report host before build:
| Argument | Meaning |
|---|---|
graph | The graph the mount's owners and effects belong to. |
parentOwner | None for a root of graph; Some owner to make the mount a child of owner, disposed with it. |
report | Receives exn list for failures outside every boundary after the build; see Failures. |
host | The element the mount inserts into. |
before | Some node inserts before a child of host; None appends. |
build | Runs once, untracked, with a BuildContext, and creates the mount's roots. |
build receives a BuildContext:
context.Backendis the backend thatProgram.run view context.Backendwrites into. EachProgram.runcall adds roots in order, and one mount can hold several views.context.Native (node, Owned)adds an existing DOM node as a root. AnOwnednode is removed when the mount is disposed; aBorrowednode returns to its original parent and position.context.OnCleanup cleanupregisters a cleanup on the mount's root owner.
The view sits between <!--ranvier:start--> and <!--ranvier:end--> comments in host. Existing children of host stay in place.
The Mounted handle
| Member | Meaning |
|---|---|
Dispose () | Runs every cleanup of the mount, then removes its nodes and listeners. |
Phase | SettingUp, Attached or Disposed. |
Failures | The failures recorded by the mount's teardown. |
Flush () | Runs pending graph work and, with queued commits, commits the queue now. |
CommitErrors | With queued commits, the setter failures of the last nonempty flush. |
MoveBefore (parent, before) | Moves an attached mount's nodes to another position. |
Disposing the graph also disposes every mount on it.
Instances and owners
Every instance (a component, an inlined child, a row, an arm, a boundary's content) runs its setup under an owner of its own, created under its parent's owner. Removing a row, switching an arm or disposing a mount disposes that owner:
- Cleanups run while the instance's nodes are still in the document:
Setup.OnCleanupcallbacks, hook cleanups, and the cleanups of signals, memos and effects created in setup, in the core's reverse acquisition order. - The nodes leave the document after every cleanup of the disposed tree has run.
A switched arm runs the previous arm's cleanups and removes its nodes before the new arm's setup runs. A list change that replaces a row sets up the new row before the replaced row's cleanups run.
Commit modes
Mounting.mountWith mode ... takes the same arguments after a CommitMode:
| Mode | DOM writes |
|---|---|
SynchronousCommits (what mount uses) | In the effect that read the new value: before the signal write returns, or at the end of the enclosing batch. |
QueuedCommits (failure, post) | Queued per binding; post schedules one flush. Microtask.mode failure posts to queueMicrotask. |
let mounted =
Mounting.mountWith (Microtask.mode Scheduling.CollectAndContinue) graph None report host None (fun context ->
Program.run (Component.render counter { Start = 0; Label = "Clicks" }) context.Backend)
Under queued commits, each binding has one slot in the mount's queue: repeated writes in one turn replace the slot's pending value, and a flush writes each slot once. The reactive computation still runs at once; only the DOM write waits. CollectAndContinue commits every slot and collects setter failures in CommitErrors; FailFastCancel stops at the first failure and cancels the remaining slots of that flush.
Hydration requires SynchronousCommits. Under QueuedCommits, Setup.CreateId issues ids in another format, which can differ from the server's; see Components.
Failures
| When | Where it goes |
|---|---|
build, or a setup outside every boundary, throws while mounting | The mount is disposed and the exception propagates from mount. |
| A hook throws during the first placement, outside every boundary | The mount is disposed and the exception propagates once the placement ends. |
| A binding read, a property setter or a handler throws later, under a boundary | The boundary's error view. |
| The same, outside every boundary | report, with the binding keeping its last value. |
| A mount created inside a batch or computation runs its hooks late, and one throws | report. |
Mounts inside mounts
A widget hook can start a second mount in its element and dispose it in the hook's cleanup. Nested mounts can use a different graph or commit mode: the playground's shell mounts its demo into a widget element with a commit mode chosen at runtime.