Skip to content

Main-thread event handlers use Lynx-first syntax, no Vue event abstraction #158

@Huxpro

Description

@Huxpro

Current behavior

Main-thread event handlers bypass Vue's event system entirely. They use Lynx's native binding syntax via v-bind:

<view :main-thread-bindtap="handler" />
<view :main-thread-catchtap="handler" />

This is because main-thread handlers are worklet context objects ({_wkltId, _c}), not plain JS functions. They go through a completely separate pipeline:

  1. BG side: patchProp detects main-thread- prefix, calls registerWorkletCtx(), pushes SET_WORKLET_EVENT op
  2. MT side: ops-apply.ts calls __AddEvent with the worklet context, runWorklet() executes directly on MT (zero thread crossing)

What this means

Since MT events don't go through Vue's v-on (@) system:

  • No @ syntax: Can't write @main-thread-tap="handler". Must use :main-thread-bindtap.
  • No event modifiers: .once, .stop, .self, .prevent are unavailable. Vue's compiler generates modifier support (e.g. onTapOnce prop keys, withModifiers() wrappers) only for v-on events.
  • No modifier shorthand: .stop must be expressed as :main-thread-catchtap (switching from bind to catch prefix manually).

Why

This is a deliberate "Lynx-first" design. MT events exist for zero-latency interaction (no thread crossing), and the binding syntax directly maps to Lynx's native bindEvent/catchEvent/bindGlobalEvent/catchGlobalEvent system. Routing through Vue's event abstraction would add complexity without clear benefit, since:

  • .stop is already covered by catchEvent (:main-thread-catchtap)
  • .prevent is a no-op in Lynx (no browser default actions)
  • .once and .self can be implemented inside the worklet handler itself
  • Supporting @ syntax would require a Vue compiler plugin to map Vue event names to Lynx event types, plus a way to encode modifier metadata into worklet context objects

Recommendation

Likely won't fix. The current Lynx-native syntax is explicit and maps directly to the underlying platform. Documenting the distinction clearly (BG events use Vue syntax, MT events use Lynx syntax) is probably the right path.

If demand arises, the lowest-cost improvement would be supporting Once suffix stripping on MT event prop keys (e.g. :main-thread-bindtapOnce), since the registration still happens in patchProp on BG and the once-guard could be applied on the MT side in ops-apply.ts. But this invents non-standard Vue syntax.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions