Environments and detection
The same dashlet code runs in all three environments. This page explains how the library decides which one it is in, and why host events cannot be missed even when they arrive before your code is ready.
1. The three environments
| Environment | Where | Wire |
|---|---|---|
|
Dashlet in a sandboxed iframe inside the enaio webclient |
|
|
Dashlet in the embedded WebView2 of the Windows rich client |
Injected |
|
Plain tab, dev server, or any non-enaio embed |
No bridge, no events; the bounded degraded state (fallback, never a hang) |
In every environment the init promise resolves to the same normalized
InitContext — the environment only changes
which wire is live.
2. How the library decides: the detection state machine
start -> detecting
| bridge found (immediate probe or poll tick)
+-----> rich client self-init (bridge read) -> initialized
| webclient onInit accepted (origin OK, first event)
+-----> webclient init -> initialized
| detection cap elapsed (no bridge, no event)
+-----> standalone (observable degradation, not an error)
Settling rules:
-
The state machine settles exactly once;
initresolves exactly once and never rejects — the standalone branch is an observable fallback, not an error. -
Rich client: the bridge may be injected late, so detection polls
window.osClient(pollIntervalMs, default 50 ms) until it appears or the detection cap (detectionTimeoutMs, default 5000 ms) elapses. Bridge capability probes are throw-safe: depending on the client version, reading an unknown member either throws or returnsundefined— both mean "not present". The bridge itself may be callable: the WebView2 rich client (measured on 12.0.713) injects a host-object proxy around a function, sotypeof window.osClientis'function'; the probes accept an object bridge and a callable bridge alike. Once the bridge read succeeds, the rich-client initialization proceeds with zero host calls. -
Webclient: the first
onInitaccepted by origin validation settles the state (see Origin configuration). After the first webclient event, the client type declared by the host is definitive — a client type ofrich_clientreroutes resolution to the rich-client path. -
Standalone: no bridge and no accepted event within the cap — the fallback state, documented in Standalone operation.
3. Import-time self-registration: never miss a host event
Registration of the host interface does not depend on your framework or on
user code calling installDashletGlobal "soon enough". Importing the package
already does the following synchronously at module-evaluation time:
-
installs
window.osDashletInitimmediately — the rich client fires its first call without waiting forload; -
attaches the single buffering
messagelistener — the onlymessagelistener a dashlet window ever needs.
Host calls and postMessage events arriving before installDashletGlobal
runs are buffered — bounded, in arrival order — and flushed when the dashlet
is configured; they are never dropped. Registration is idempotent: the
installed global is a stable per-window dispatcher, and re-registration
adds or removes handlers atomically without losing a call that arrives in
between.
Additionally, an onInit listener registered after the init already
settled (for example by a framework after mount) is replayed immediately with
the settled context — late registration never misses the init.
4. The v10.10 warm-up quirk
On client version 10.10, osjxGetEnvironment(n) returns empty values until
the client has finished warming up. If the self-init bridge read yields no
environment values at all, the library runs a bounded warm-up (the poll
interval, capped by detectionTimeoutMs plus an internal 10 s hard cap) and
refreshes + re-emits the
populated context via the update slot once the values appear — never a hang,
and never a silent overwrite of values that were already read.