TabState
Browser-tab scoped session state
Session array values that can differ per browser tab (a list page's filters, for example).
The tab id is minted by tabstate.js and kept in the tab's sessionStorage; AJAX requests send it as the X-Oncord-Tab header and page loads carry the oncord_tab cookie, which the script keeps pointed at the tab the next page request will come from.
Reads resolve the tab's copy first. A key the tab has never seen is copied in from the shared array at that moment (an unset key is pinned as unset), so a tab keeps showing what it displayed even after another tab changes the same key. Writes update both the tab's copy and the shared array - the shared array is what a new tab starts from. Without a (valid) tab id every method acts on the shared array only, which is the pre-tab behaviour.
A brand-new tab's first page is attributed to another tab (the cookie's), so every value a page render resolves is also echoed into the page as window.oncordTabStateRendered; tabstate.js posts that snapshot back (adopt()) when it finds the tab is new. The snapshot is what the page showed, so neither a change in the other tab while the request is in flight nor a cookie that has moved on by the time the script runs can leak into the new tab.
Each tab's copy is its own top-level session key (<array>:tab:<id>) because Session::write() merges per top-level key: concurrent tabs must not write the same key.
Methods
Invoke via \Framework\HTTP\TabState::method()
Click a method name to copy it.
Writes the values a page displayed into the requesting tab
Posted by tabstate.js from a tab that has just found out it is new (or a duplicate): its first page was rendered as another tab, and this is what that page showed. Keys the tab already holds are kept.
Return
Whether anything was adopted
Gets an array value for this tab
Returns whether an array value is set for this tab
Returns the requesting browser tab's id, or null when the request carries none
Sets an array value for this tab and as the shared default for new tabs