search ESC

Searching…

No results for "".

Type at least 2 characters to search.

Docs

The semantics hold

DuskPlugin.install() takes a semantics handle for the whole process, because every snapshot, q handle and actionability check reads the semantics tree. The cost is that every frame of a dusk-driven app also builds that tree, which an app without dusk (and without a screen reader) does not. ext.dusk.semantics_hold lets dusk:perf_run --semantics-pass measure the app without it, for one timed window.


ext.dusk.semantics_hold

Param Meaning
action=release Drops dusk's handle. Refused unless a perf session is open, so the tree can only go away inside a timed window.
action=acquire Takes the handle again, then awaits one frame (bounded, 200 ms) so the tree exists again when it answers.
{"action": "release", "released": true, "semanticsEnabled": false, "heldByPlatform": false}
{"action": "acquire", "acquired": true, "semanticsEnabled": true, "treeReady": true}

semanticsEnabled stays true after a release when something else holds a handle: the tree only goes away when the last handle does. heldByPlatform is platformDispatcher.semanticsEnabled, true when the platform holds a handle of its own. On Flutter web that is every real app once it has sent a semantics tree: the engine turns semantics on at the first update and nothing turns it off, so a release there answers semanticsEnabled: true, heldByPlatform: true. On a native device it is true while an accessibility service runs. heldByPlatform: false with semanticsEnabled: true is another SemanticsHandle in the app (or the test harness). DuskPlugin.semanticsReleased reads the state in-app.

The caller owns the pairing: acquire after perf_end, so the acquire's full tree rebuild is not a frame of the session, and acquire even when a step or perf_end failed. perf_end also re-takes a handle left released, as a safety net for a caller that died in between. dusk:perf_run does all of it.


Driving while the tree is released

Anything that resolves a target reads the tree, so while it is released nothing may: ext.dusk.find, a q action and a snapshot would all see no nodes, and a transient handle taken to look would rebuild the tree inside the window being measured. Resolve first, with the tree on, then dispatch by coordinates:

Extension Records the point (tree on) Dispatches by coordinates
ext.dusk.tap reportPoint: true adds point: {x, y} {x, y} with no ref
ext.dusk.drag reportPoint: true adds from and to; startRef plus dx/dy drags by an offset {x, y, toX, toY} with no ref
ext.dusk.hover reportPoint: true adds point (a wheel then goes through CDP)

A coordinate dispatch has no element, so none of the actionability gate's checks can run. Its response always carries:

"checks": {"gate": "skipped", "semantics": "released", "why": "..."}

semantics is held or released; the enabled check is the one that reads the tree. Nothing about a coordinate dispatch proves what it landed on: it is a replay of a point that was valid when the tree was on, for a screen that is expected to be in the same state.


See also