protocol

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 24, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package protocol implements the binary wire protocol for Vango V2.

The protocol is optimized for minimal bandwidth and fast encoding/decoding. It defines how events flow from client to server and patches flow from server to client over WebSocket connections.

Design Goals

  • Minimal size: Typical event < 10 bytes, typical patch < 20 bytes
  • Fast encoding/decoding: No reflection, direct byte manipulation
  • Reliable delivery: Sequence numbers, acknowledgments
  • Reconnection: Resync capability after disconnect
  • Extensible: Version negotiation, reserved opcodes

Wire Format

All messages are framed with a 4-byte header:

┌─────────────┬──────────────┬───────────────────────────────┐
│ Frame Type  │ Flags        │ Payload Length                │
│ (1 byte)    │ (1 byte)     │ (2 bytes, big-endian)         │
└─────────────┴──────────────┴───────────────────────────────┘

Frame Types

  • FrameHandshake (0x00): Connection setup
  • FrameEvent (0x01): Client → Server events
  • FramePatches (0x02): Server → Client patches
  • FrameControl (0x03): Control messages (ping, resync)
  • FrameAck (0x04): Acknowledgment
  • FrameError (0x05): Error message

Encoding

The protocol uses several encoding strategies:

  • Varint: Compact encoding for small integers (protobuf-style)
  • ZigZag: Signed integers encoded as unsigned varints
  • Length-prefixed: Strings and byte arrays prefixed with varint length
  • Big-endian: Fixed-width integers (uint16, uint32, uint64)

Events

Events are sent from client to server when user interactions occur. Each event includes a sequence number, event type, hydration ID (HID), and type-specific payload.

Example click event encoding:

[Seq: varint][Type: 0x01][HID: len-prefixed string]
Total: ~5 bytes for "h1"

Patches

Patches are sent from server to client to update the DOM. Each patch includes an operation type, target HID, and operation-specific data.

Example SetText patch encoding:

[Op: 0x01][HID: len-prefixed][Value: len-prefixed]
Total: ~15 bytes for updating "h1" with "Hello"

Handshake

Connection establishment uses ClientHello and ServerHello messages:

Client                          Server
  │                                │
  │──── ClientHello ─────────────>│
  │     (version, csrf, session)  │
  │                                │
  │<──── ServerHello ─────────────│
  │     (status, session, time)   │
  │                                │

Error ServerHello messages may include an optional auth-expired reason byte.

Control Messages

  • Ping/Pong: Heartbeat for connection health
  • ResyncRequest: Client requests missed patches after reconnect
  • ResyncPatches/ResyncFull: Server response with missed data
  • SessionRefresh: Server notifies client of schema refresh
  • SessionRefreshAck: Client acknowledges session refresh
  • Close: Graceful session termination

Usage Example

// Encode an event
event := &Event{
    Seq:     1,
    Type:    EventClick,
    HID:     "h42",
}
data := EncodeEvent(event)

// Decode an event
decoded, err := DecodeEvent(data)
if err != nil {
    // Handle error
}

// Encode patches
pf := &PatchesFrame{
    Seq: 1,
    Patches: []Patch{
        NewSetTextPatch("h1", "Hello, World!"),
        NewSetAttrPatch("h2", "class", "active"),
    },
}
data = EncodePatches(pf)

// Decode patches
decoded, err := DecodePatches(data)

Performance

Target metrics:

  • Event encode/decode: < 500ns
  • Patch encode/decode: < 500ns
  • 100 patches encode: < 50μs
  • 100 patches decode: < 50μs

File Structure

The package is organized as follows:

  • varint.go: Varint encoding/decoding
  • encoder.go: Binary encoder
  • decoder.go: Binary decoder
  • frame.go: Frame types and transport
  • event.go: Event types and encoding
  • patch.go: Patch types and encoding
  • vnode.go: VNode wire format
  • handshake.go: Handshake protocol
  • control.go: Control messages
  • ack.go: Acknowledgment
  • error.go: Error messages

Index

Constants

View Source
const (
	// DefaultMaxAllocation is the default maximum allocation size (4MB).
	// This is sufficient for normal binary patches and events.
	DefaultMaxAllocation = 4 * 1024 * 1024

	// HardMaxAllocation is the absolute ceiling for allocations (16MB).
	// Even if configured higher, allocations are capped at this limit.
	HardMaxAllocation = 16 * 1024 * 1024

	// MaxCollectionCount is the maximum number of items in a collection (array/map).
	// This prevents OOM from huge counts with small per-item overhead.
	MaxCollectionCount = 100_000
)

Allocation limits to prevent DoS attacks via malicious length prefixes.

View Source
const (
	// FrameHeaderSize is the size of the frame header in bytes.
	FrameHeaderSize = 4

	// MaxPayloadSize is the maximum payload size (2^16 - 1 bytes).
	MaxPayloadSize = 65535

	// MaxFrameSize is the maximum complete frame size in bytes (header + payload).
	MaxFrameSize = FrameHeaderSize + MaxPayloadSize
)

Frame constants.

View Source
const (
	ServerFlagCompression uint16 = 0x0001 // Server supports compression
	ServerFlagBinaryBlobs uint16 = 0x0002 // Server supports binary blob uploads
	ServerFlagStreaming   uint16 = 0x0004 // Server supports streaming responses
)

Server capability flags.

View Source
const (
	// MaxVNodeDepth limits the maximum nesting depth of VNode trees.
	// This prevents stack overflow from maliciously deep component trees.
	// 256 levels is sufficient for any reasonable component hierarchy.
	MaxVNodeDepth = 256

	// MaxPatchDepth limits the maximum nesting depth of patch structures.
	// Patches can contain VNodes (InsertNode, ReplaceNode), so this must
	// account for VNode nesting within patches.
	MaxPatchDepth = 128
)

Depth limits to prevent stack overflow attacks via deeply nested structures. These limits complement the allocation limits in decoder.go.

View Source
const DefaultWindow = 100

DefaultWindow is the default receive window size.

View Source
const MaxHookDepth = 64

MaxHookDepth is the maximum nesting depth for hook values. Prevents stack overflow from maliciously deeply nested payloads.

View Source
const MaxVarintLen = 10

MaxVarintLen is the maximum number of bytes a varint can occupy. A uint64 requires at most 10 bytes in varint encoding.

Variables

View Source
var (
	ErrBufferTooShort     = errors.New("protocol: buffer too short")
	ErrVarintOverflow     = errors.New("protocol: varint overflow")
	ErrInvalidBool        = errors.New("protocol: invalid boolean value")
	ErrAllocationTooLarge = errors.New("protocol: allocation size exceeds limit")
	ErrCollectionTooLarge = errors.New("protocol: collection count exceeds limit")
)

Common decoding errors.

View Source
var (
	ErrInvalidEventType = errors.New("protocol: invalid event type")
	ErrInvalidPayload   = errors.New("protocol: invalid event payload")
	ErrMaxDepthExceeded = errors.New("protocol: maximum nesting depth exceeded")
)

Event encoding errors.

View Source
var (
	ErrFrameTooLarge     = errors.New("protocol: frame payload too large")
	ErrInvalidFrameType  = errors.New("protocol: invalid frame type")
	ErrTrailingFrameData = errors.New("protocol: trailing bytes after frame payload")
)

Frame errors.

View Source
var CurrentVersion = ProtocolVersion{Major: 2, Minor: 1}

CurrentVersion is the current protocol version.

Functions

func CompareProtocolVersion

func CompareProtocolVersion(a, b ProtocolVersion) int

CompareProtocolVersion compares two protocol versions lexicographically. It returns:

-1 when a < b
 0 when a == b
+1 when a > b

func DecodeFrameHeader

func DecodeFrameHeader(data []byte) (FrameType, FrameFlags, int, error)

DecodeFrameHeader decodes just the frame header, returning type, flags, and payload length.

func DecodeSvarint

func DecodeSvarint(buf []byte) (int64, int)

DecodeSvarint decodes a signed varint using ZigZag decoding. Returns (value, bytesRead). Negative bytesRead indicates error (see DecodeUvarint).

func DecodeUvarint

func DecodeUvarint(buf []byte) (uint64, int)

DecodeUvarint decodes an unsigned varint from buf. Returns (value, bytesRead). If bytesRead < 0, decoding failed:

  • -1: buffer too short (incomplete varint)
  • -2: varint overflow (more than 10 bytes)

func EncodeAck

func EncodeAck(ack *Ack) []byte

EncodeAck encodes an Ack to bytes.

func EncodeAckTo

func EncodeAckTo(e *Encoder, ack *Ack)

EncodeAckTo encodes an Ack using the provided encoder.

func EncodeClientHello

func EncodeClientHello(ch *ClientHello) []byte

EncodeClientHello encodes a ClientHello to bytes.

func EncodeClientHelloTo

func EncodeClientHelloTo(e *Encoder, ch *ClientHello)

EncodeClientHelloTo encodes a ClientHello using the provided encoder.

func EncodeControl

func EncodeControl(ct ControlType, payload any) []byte

EncodeControl encodes a control message to bytes.

func EncodeControlTo

func EncodeControlTo(e *Encoder, ct ControlType, payload any)

EncodeControlTo encodes a control message using the provided encoder.

func EncodeErrorMessage

func EncodeErrorMessage(em *ErrorMessage) []byte

EncodeErrorMessage encodes an ErrorMessage to bytes.

func EncodeErrorMessageTo

func EncodeErrorMessageTo(e *Encoder, em *ErrorMessage)

EncodeErrorMessageTo encodes an ErrorMessage using the provided encoder.

func EncodeEvent

func EncodeEvent(e *Event) []byte

EncodeEvent encodes an event to bytes.

func EncodeEventTo

func EncodeEventTo(enc *Encoder, e *Event)

EncodeEventTo encodes an event using the provided encoder.

func EncodePatches

func EncodePatches(pf *PatchesFrame) []byte

EncodePatches encodes a patches frame to bytes.

func EncodePatchesTo

func EncodePatchesTo(e *Encoder, pf *PatchesFrame)

EncodePatchesTo encodes a patches frame using the provided encoder.

func EncodeServerHello

func EncodeServerHello(sh *ServerHello) []byte

EncodeServerHello encodes a ServerHello to bytes.

func EncodeServerHelloTo

func EncodeServerHelloTo(e *Encoder, sh *ServerHello)

EncodeServerHelloTo encodes a ServerHello using the provided encoder.

func EncodeSvarint

func EncodeSvarint(buf []byte, v int64) int

EncodeSvarint encodes a signed integer as a varint using ZigZag encoding. Returns the number of bytes written. ZigZag maps signed integers to unsigned: 0->0, -1->1, 1->2, -2->3, 2->4, etc.

func EncodeUvarint

func EncodeUvarint(buf []byte, v uint64) int

EncodeUvarint encodes an unsigned integer as a varint into buf. Returns the number of bytes written. buf must have at least MaxVarintLen bytes available. Uses protobuf-style encoding: 7 bits of data per byte, MSB indicates continuation.

func EncodeVNodeWire

func EncodeVNodeWire(e *Encoder, node *VNodeWire)

EncodeVNodeWire encodes a VNodeWire to bytes using the provided encoder.

func NewAuthCommand

func NewAuthCommand(cmd *AuthCommand) (ControlType, *AuthCommand)

NewAuthCommand creates a new AuthCommand message.

func NewClose

func NewClose(reason CloseReason, message string) (ControlType, *CloseMessage)

NewClose creates a new Close message.

func NewHookRevert

func NewHookRevert(hid string) (ControlType, *HookRevert)

NewHookRevert creates a new HookRevert message.

func NewPing

func NewPing(timestamp uint64) (ControlType, *PingPong)

NewPing creates a new Ping message.

func NewPong

func NewPong(timestamp uint64) (ControlType, *PingPong)

NewPong creates a new Pong message.

func NewResyncFull

func NewResyncFull(html string) (ControlType, *ResyncResponse)

NewResyncFull creates a new ResyncFull response.

func NewResyncPatches

func NewResyncPatches(fromSeq uint64, patches []Patch) (ControlType, *ResyncResponse)

NewResyncPatches creates a new ResyncPatches response.

func NewResyncRequest

func NewResyncRequest(lastSeq uint64) (ControlType, *ResyncRequest)

NewResyncRequest creates a new ResyncRequest message.

func NewSessionRefresh

func NewSessionRefresh(cmd *SessionRefreshCommand) (ControlType, *SessionRefreshCommand)

NewSessionRefresh creates a new session refresh control message.

func NewSessionRefreshAck

func NewSessionRefreshAck(source string) (ControlType, *SessionRefreshAck)

NewSessionRefreshAck creates a new session refresh acknowledgment.

func SvarintLen

func SvarintLen(v int64) int

SvarintLen returns the number of bytes needed to encode v as a signed varint.

func UvarintLen

func UvarintLen(v uint64) int

UvarintLen returns the number of bytes needed to encode v as a varint.

func WriteFrame

func WriteFrame(w io.Writer, f *Frame) error

WriteFrame writes a complete frame to an io.Writer.

Types

type Ack

type Ack struct {
	LastSeq uint64 // Last received sequence number
	Window  uint64 // Receive window size (how many more patches client can accept)
}

Ack is sent by the client to acknowledge received patches. It serves multiple purposes:

  1. Garbage collection of patch history on the server
  2. Flow control (server knows client's processing capacity)
  3. Detecting client lag

func DecodeAck

func DecodeAck(data []byte) (*Ack, error)

DecodeAck decodes an Ack from bytes.

func DecodeAckFrom

func DecodeAckFrom(d *Decoder) (*Ack, error)

DecodeAckFrom decodes an Ack from a decoder.

func NewAck

func NewAck(lastSeq, window uint64) *Ack

NewAck creates a new Ack with the given sequence and window.

type AnimationEventData

type AnimationEventData struct {
	AnimationName string
	ElapsedTime   float64
	PseudoElement string
}

AnimationEventData contains CSS animation event data.

type AuthAction

type AuthAction uint8

AuthAction defines the type of auth command to execute on the client.

const (
	AuthActionForceReload  AuthAction = 0x01
	AuthActionHardNavigate AuthAction = 0x02
	AuthActionBroadcast    AuthAction = 0x03
)

type AuthCommand

type AuthCommand struct {
	Action  AuthAction
	Reason  uint8
	Path    string
	Channel string
	Type    string
}

AuthCommand is sent by the server when auth expires.

type BannerSpec

type BannerSpec struct {
	Message   string
	Detail    string
	DismissMS uint16
	CSSClass  string
}

BannerSpec is an optional banner payload for schema refresh messaging.

type ClientHello

type ClientHello struct {
	Version   ProtocolVersion // Protocol version
	CSRFToken string          // CSRF token for validation
	SessionID string          // Existing session ID (empty if new)
	LastSeq   uint32          // Last seen sequence number
	ViewportW uint16          // Viewport width
	ViewportH uint16          // Viewport height
	TZOffset  int16           // Timezone offset in minutes from UTC
}

ClientHello is sent by the client after WebSocket connection is established.

func DecodeClientHello

func DecodeClientHello(data []byte) (*ClientHello, error)

DecodeClientHello decodes a ClientHello from bytes.

func DecodeClientHelloFrom

func DecodeClientHelloFrom(d *Decoder) (*ClientHello, error)

DecodeClientHelloFrom decodes a ClientHello from a decoder.

func NewClientHello

func NewClientHello(csrfToken string) *ClientHello

NewClientHello creates a new ClientHello with default version.

type CloseMessage

type CloseMessage struct {
	Reason  CloseReason
	Message string
}

CloseMessage is sent when closing a session.

type CloseReason

type CloseReason uint8

CloseReason indicates why a session is being closed.

const (
	CloseNormal         CloseReason = 0x00 // Normal closure
	CloseGoingAway      CloseReason = 0x01 // Client/server going away
	CloseSessionExpired CloseReason = 0x02 // Session expired
	CloseServerShutdown CloseReason = 0x03 // Server shutting down
	CloseError          CloseReason = 0x04 // Error occurred
)

func (CloseReason) String

func (cr CloseReason) String() string

String returns the string representation of the close reason.

type ControlType

type ControlType uint8

ControlType identifies the type of control message.

const (
	ControlPing              ControlType = 0x01 // Client/server ping
	ControlPong              ControlType = 0x02 // Response to ping
	ControlResyncRequest     ControlType = 0x10 // Client requests missed patches
	ControlResyncPatches     ControlType = 0x11 // Server sends missed patches
	ControlResyncFull        ControlType = 0x12 // Server sends full HTML reload
	ControlHookRevert        ControlType = 0x30 // Server requests hook revert by HID
	ControlAuthCommand       ControlType = 0x31 // Server auth command (reload, navigate, broadcast)
	ControlSessionRefresh    ControlType = 0x32 // Server session refresh notification
	ControlSessionRefreshAck ControlType = 0x33 // Client acknowledges session refresh
	ControlClose             ControlType = 0x20 // Session close
)

func DecodeControl

func DecodeControl(data []byte) (ControlType, any, error)

DecodeControl decodes a control message from bytes. Returns the control type and the decoded payload.

func DecodeControlFrom

func DecodeControlFrom(d *Decoder) (ControlType, any, error)

DecodeControlFrom decodes a control message from a decoder.

func (ControlType) String

func (ct ControlType) String() string

String returns the string representation of the control type.

type CustomEventData

type CustomEventData struct {
	Name string
	Data []byte
}

CustomEventData contains custom event data.

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder is a binary decoder that reads from a byte buffer.

func NewDecoder

func NewDecoder(buf []byte) *Decoder

NewDecoder creates a new decoder from the given byte slice.

func (*Decoder) EOF

func (d *Decoder) EOF() bool

EOF returns true if all bytes have been read.

func (*Decoder) Position

func (d *Decoder) Position() int

Position returns the current read position.

func (*Decoder) ReadBool

func (d *Decoder) ReadBool() (bool, error)

ReadBool reads a boolean (single byte: 0x00=false, 0x01=true).

func (*Decoder) ReadByte

func (d *Decoder) ReadByte() (byte, error)

ReadByte reads a single byte.

func (*Decoder) ReadBytes

func (d *Decoder) ReadBytes(n int) ([]byte, error)

ReadBytes reads exactly n bytes and returns them. The returned slice references the decoder's buffer; do not modify.

func (*Decoder) ReadCollectionCount

func (d *Decoder) ReadCollectionCount() (int, error)

ReadCollectionCount reads a varint count and validates it against limits. Returns ErrCollectionTooLarge if count exceeds MaxCollectionCount. This should be used when reading the size of arrays, maps, or other collections.

func (*Decoder) ReadFloat32

func (d *Decoder) ReadFloat32() (float32, error)

ReadFloat32 reads a float32 in IEEE 754 format (big-endian).

func (*Decoder) ReadFloat64

func (d *Decoder) ReadFloat64() (float64, error)

ReadFloat64 reads a float64 in IEEE 754 format (big-endian).

func (*Decoder) ReadInt16

func (d *Decoder) ReadInt16() (int16, error)

ReadInt16 reads an int16 in big-endian byte order.

func (*Decoder) ReadInt32

func (d *Decoder) ReadInt32() (int32, error)

ReadInt32 reads an int32 in big-endian byte order.

func (*Decoder) ReadInt64

func (d *Decoder) ReadInt64() (int64, error)

ReadInt64 reads an int64 in big-endian byte order.

func (*Decoder) ReadLenBytes

func (d *Decoder) ReadLenBytes() ([]byte, error)

ReadLenBytes reads length-prefixed bytes. Returns a copy of the bytes (safe to retain). Returns ErrAllocationTooLarge if the byte slice exceeds DefaultMaxAllocation.

func (*Decoder) ReadString

func (d *Decoder) ReadString() (string, error)

ReadString reads a length-prefixed UTF-8 string. Returns ErrAllocationTooLarge if the string exceeds DefaultMaxAllocation.

func (*Decoder) ReadSvarint

func (d *Decoder) ReadSvarint() (int64, error)

ReadSvarint reads a signed varint using ZigZag decoding.

func (*Decoder) ReadUint16

func (d *Decoder) ReadUint16() (uint16, error)

ReadUint16 reads a uint16 in big-endian byte order.

func (*Decoder) ReadUint32

func (d *Decoder) ReadUint32() (uint32, error)

ReadUint32 reads a uint32 in big-endian byte order.

func (*Decoder) ReadUint64

func (d *Decoder) ReadUint64() (uint64, error)

ReadUint64 reads a uint64 in big-endian byte order.

func (*Decoder) ReadUvarint

func (d *Decoder) ReadUvarint() (uint64, error)

ReadUvarint reads an unsigned varint.

func (*Decoder) Remaining

func (d *Decoder) Remaining() int

Remaining returns the number of unread bytes.

func (*Decoder) Skip

func (d *Decoder) Skip(n int) error

Skip advances the position by n bytes.

type DepthLimits

type DepthLimits struct {
	// MaxVNodeDepth is the maximum VNode tree depth.
	VNodeDepth int

	// MaxPatchDepth is the maximum patch structure depth.
	PatchDepth int

	// MaxHookDepth is the maximum JSON payload depth.
	HookDepth int
}

DepthLimits allows configuring custom depth limits for decoding. Use DefaultDepthLimits() for sensible defaults.

func DefaultDepthLimits

func DefaultDepthLimits() *DepthLimits

DefaultDepthLimits returns the default depth limits.

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder is a binary encoder that appends data to an internal buffer. It is designed for efficient encoding without allocations in the hot path.

func NewEncoder

func NewEncoder() *Encoder

NewEncoder creates a new encoder with a default initial capacity.

func NewEncoderWithCap

func NewEncoderWithCap(cap int) *Encoder

NewEncoderWithCap creates a new encoder with the specified initial capacity.

func (*Encoder) Bytes

func (e *Encoder) Bytes() []byte

Bytes returns the encoded bytes. The returned slice is valid until the next call to Reset or any Write method.

func (*Encoder) Len

func (e *Encoder) Len() int

Len returns the number of bytes currently encoded.

func (*Encoder) Reset

func (e *Encoder) Reset()

Reset resets the encoder to empty state, reusing the underlying buffer.

func (*Encoder) WriteBool

func (e *Encoder) WriteBool(b bool)

WriteBool appends a boolean as a single byte (0x00 or 0x01).

func (*Encoder) WriteByte

func (e *Encoder) WriteByte(b byte) error

WriteByte appends a single byte. It implements io.ByteWriter for compatibility with standard interfaces. The encoder cannot error, so this always returns nil.

func (*Encoder) WriteByteUnsafe

func (e *Encoder) WriteByteUnsafe(b byte)

WriteByteUnsafe appends a single byte without returning an error. Use internally to avoid repetitive nil error handling.

func (*Encoder) WriteBytes

func (e *Encoder) WriteBytes(b []byte)

WriteBytes appends raw bytes.

func (*Encoder) WriteFloat32

func (e *Encoder) WriteFloat32(v float32)

WriteFloat32 appends a float32 in IEEE 754 format (big-endian).

func (*Encoder) WriteFloat64

func (e *Encoder) WriteFloat64(v float64)

WriteFloat64 appends a float64 in IEEE 754 format (big-endian).

func (*Encoder) WriteInt16

func (e *Encoder) WriteInt16(v int16)

WriteInt16 appends an int16 in big-endian byte order.

func (*Encoder) WriteInt32

func (e *Encoder) WriteInt32(v int32)

WriteInt32 appends an int32 in big-endian byte order.

func (*Encoder) WriteInt64

func (e *Encoder) WriteInt64(v int64)

WriteInt64 appends an int64 in big-endian byte order.

func (*Encoder) WriteLenBytes

func (e *Encoder) WriteLenBytes(b []byte)

WriteLenBytes appends length-prefixed bytes. Format: varint length + bytes

func (*Encoder) WriteString

func (e *Encoder) WriteString(s string)

WriteString appends a length-prefixed UTF-8 string. Format: varint length + string bytes

func (*Encoder) WriteSvarint

func (e *Encoder) WriteSvarint(v int64)

WriteSvarint appends a signed varint using ZigZag encoding.

func (*Encoder) WriteUint16

func (e *Encoder) WriteUint16(v uint16)

WriteUint16 appends a uint16 in big-endian byte order.

func (*Encoder) WriteUint32

func (e *Encoder) WriteUint32(v uint32)

WriteUint32 appends a uint32 in big-endian byte order.

func (*Encoder) WriteUint64

func (e *Encoder) WriteUint64(v uint64)

WriteUint64 appends a uint64 in big-endian byte order.

func (*Encoder) WriteUvarint

func (e *Encoder) WriteUvarint(v uint64)

WriteUvarint appends an unsigned varint.

type ErrorCode

type ErrorCode uint16

ErrorCode identifies the type of error.

const (
	ErrUnknown         ErrorCode = 0x0000 // Unknown error
	ErrInvalidFrame    ErrorCode = 0x0001 // Malformed frame
	ErrInvalidEvent    ErrorCode = 0x0002 // Malformed event
	ErrHandlerNotFound ErrorCode = 0x0003 // No handler for HID
	ErrHandlerPanic    ErrorCode = 0x0004 // Handler panicked
	ErrSessionExpired  ErrorCode = 0x0005 // Session no longer valid
	ErrRateLimited     ErrorCode = 0x0006 // Too many requests
	ErrServerError     ErrorCode = 0x0100 // Internal server error
	ErrNotAuthorized   ErrorCode = 0x0101 // Not authorized
	ErrNotFound        ErrorCode = 0x0102 // Resource not found
	ErrValidation      ErrorCode = 0x0103 // Validation failed
	ErrRouteError      ErrorCode = 0x0104 // Route matching/navigation error
)

func (ErrorCode) String

func (ec ErrorCode) String() string

String returns the string representation of the error code.

type ErrorMessage

type ErrorMessage struct {
	Code    ErrorCode // Error code
	Message string    // Human-readable error message
	Fatal   bool      // If true, connection should be closed
}

ErrorMessage is sent when an error occurs.

func DecodeErrorMessage

func DecodeErrorMessage(data []byte) (*ErrorMessage, error)

DecodeErrorMessage decodes an ErrorMessage from bytes.

func DecodeErrorMessageFrom

func DecodeErrorMessageFrom(d *Decoder) (*ErrorMessage, error)

DecodeErrorMessageFrom decodes an ErrorMessage from a decoder.

func NewError

func NewError(code ErrorCode, message string) *ErrorMessage

NewError creates a new non-fatal ErrorMessage.

func NewFatalError

func NewFatalError(code ErrorCode, message string) *ErrorMessage

NewFatalError creates a new fatal ErrorMessage.

func (*ErrorMessage) Error

func (em *ErrorMessage) Error() string

Error implements the error interface.

func (*ErrorMessage) IsFatal

func (em *ErrorMessage) IsFatal() bool

IsFatal returns true if this error should close the connection.

type Event

type Event struct {
	Seq     uint64
	Type    EventType
	HID     string
	Payload any // Type-specific payload (nil for simple events like Click)
}

Event represents a decoded event from the client.

func DecodeEvent

func DecodeEvent(data []byte) (*Event, error)

DecodeEvent decodes an event from bytes.

func DecodeEventFrom

func DecodeEventFrom(d *Decoder) (*Event, error)

DecodeEventFrom decodes an event from a decoder.

type EventType

type EventType uint8

EventType identifies the type of client event.

const (
	// Mouse events (0x01-0x08)
	EventClick      EventType = 0x01
	EventDblClick   EventType = 0x02
	EventMouseDown  EventType = 0x03
	EventMouseUp    EventType = 0x04
	EventMouseMove  EventType = 0x05
	EventMouseEnter EventType = 0x06
	EventMouseLeave EventType = 0x07
	EventWheel      EventType = 0x08 // Mouse wheel event

	// Form events (0x10-0x14)
	EventInput  EventType = 0x10
	EventChange EventType = 0x11
	EventSubmit EventType = 0x12
	EventFocus  EventType = 0x13
	EventBlur   EventType = 0x14

	// Keyboard events (0x20-0x22)
	EventKeyDown  EventType = 0x20
	EventKeyUp    EventType = 0x21
	EventKeyPress EventType = 0x22

	// Scroll/Resize events (0x30-0x31)
	EventScroll EventType = 0x30
	EventResize EventType = 0x31

	// Touch events (0x40-0x42)
	EventTouchStart EventType = 0x40
	EventTouchMove  EventType = 0x41
	EventTouchEnd   EventType = 0x42

	// Drag events (0x50-0x52)
	EventDragStart EventType = 0x50
	EventDragEnd   EventType = 0x51
	EventDrop      EventType = 0x52

	// Animation events (0x53-0x56)
	EventAnimationStart     EventType = 0x53
	EventAnimationEnd       EventType = 0x54
	EventAnimationIteration EventType = 0x55
	EventAnimationCancel    EventType = 0x56

	// Transition events (0x57-0x5A)
	EventTransitionStart  EventType = 0x57
	EventTransitionEnd    EventType = 0x58
	EventTransitionRun    EventType = 0x59
	EventTransitionCancel EventType = 0x5A

	// Special events (0x60+)
	EventHook     EventType = 0x60 // Client hook event
	EventNavigate EventType = 0x70 // Navigation request
	EventCustom   EventType = 0xFF // Custom event
)

Event type constants.

func (EventType) String

func (et EventType) String() string

String returns the string representation of the event type.

type Frame

type Frame struct {
	Type    FrameType
	Flags   FrameFlags
	Payload []byte
}

Frame represents a protocol frame with header and payload.

Wire format (4 bytes header + variable payload):

┌─────────────┬──────────────┬───────────────────────────────┐
│ Frame Type  │ Flags        │ Payload Length                │
│ (1 byte)    │ (1 byte)     │ (2 bytes, big-endian)         │
└─────────────┴──────────────┴───────────────────────────────┘
│                                                             │
│  Payload (variable length)                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

func DecodeFrame

func DecodeFrame(data []byte) (*Frame, error)

DecodeFrame decodes a frame from bytes. The input must contain at least the header (4 bytes) and full payload.

func NewFrame

func NewFrame(ft FrameType, payload []byte) *Frame

NewFrame creates a new frame with the given type and payload.

func NewFrameWithFlags

func NewFrameWithFlags(ft FrameType, flags FrameFlags, payload []byte) *Frame

NewFrameWithFlags creates a new frame with the given type, flags, and payload.

func ReadFrame

func ReadFrame(r io.Reader) (*Frame, error)

ReadFrame reads a complete frame from an io.Reader.

func (*Frame) Encode

func (f *Frame) Encode() []byte

Encode encodes the frame to bytes including the header.

func (*Frame) EncodeTo

func (f *Frame) EncodeTo(e *Encoder)

EncodeTo encodes the frame using the provided encoder.

type FrameFlags

type FrameFlags uint8

FrameFlags are optional flags for frame processing.

const (
	FlagCompressed FrameFlags = 0x01 // Payload is gzip compressed
	FlagSequenced  FrameFlags = 0x02 // Includes sequence number
	FlagFinal      FrameFlags = 0x04 // Last frame in batch
	FlagPriority   FrameFlags = 0x08 // High priority (skip queue)
)

func (FrameFlags) Has

func (ff FrameFlags) Has(flag FrameFlags) bool

Has returns true if the flags contain the specified flag.

type FrameType

type FrameType uint8

FrameType identifies the type of frame.

const (
	FrameHandshake FrameType = 0x00 // Connection setup
	FrameEvent     FrameType = 0x01 // Client → Server events
	FramePatches   FrameType = 0x02 // Server → Client patches
	FrameControl   FrameType = 0x03 // Control messages (ping, etc.)
	FrameAck       FrameType = 0x04 // Acknowledgment
	FrameError     FrameType = 0x05 // Error message
)

func (FrameType) String

func (ft FrameType) String() string

String returns the string representation of the frame type.

type HandshakeStatus

type HandshakeStatus uint8

HandshakeStatus represents the result of a handshake.

const (
	HandshakeOK              HandshakeStatus = 0x00
	HandshakeVersionMismatch HandshakeStatus = 0x01
	HandshakeInvalidCSRF     HandshakeStatus = 0x02
	HandshakeSessionExpired  HandshakeStatus = 0x03
	HandshakeServerBusy      HandshakeStatus = 0x04
	HandshakeUpgradeRequired HandshakeStatus = 0x05
	HandshakeInvalidFormat   HandshakeStatus = 0x06 // Malformed handshake message
	HandshakeNotAuthorized   HandshakeStatus = 0x07 // Authentication failed
	HandshakeInternalError   HandshakeStatus = 0x08 // Server error
	HandshakeLimitExceeded   HandshakeStatus = 0x09 // Per-IP session limit exceeded
	HandshakeSchemaMismatch  HandshakeStatus = 0x0A // Persisted schema incompatible
)

func HandshakeStatusForVersion

func HandshakeStatusForVersion(client, server ProtocolVersion) HandshakeStatus

HandshakeStatusForVersion returns the handshake status implied by client/server protocol versions.

Policy:

  • Exact match is required for a successful handshake.
  • Lower client versions are rejected with HandshakeUpgradeRequired.
  • Higher client versions are rejected with HandshakeVersionMismatch.

func (HandshakeStatus) String

func (hs HandshakeStatus) String() string

String returns the string representation of the handshake status.

type HookEventData

type HookEventData struct {
	Name string
	Data map[string]any
}

HookEventData contains client hook event data.

type HookRevert

type HookRevert struct {
	HID string
}

HookRevert instructs the client to run the registered revert callback for the hook instance.

type HookValueType

type HookValueType uint8

HookValueType identifies the type of a hook data value.

const (
	HookValueNull   HookValueType = 0x00
	HookValueBool   HookValueType = 0x01
	HookValueInt    HookValueType = 0x02
	HookValueFloat  HookValueType = 0x03
	HookValueString HookValueType = 0x04
	HookValueArray  HookValueType = 0x05
	HookValueObject HookValueType = 0x06
)

type InputEventData

type InputEventData struct {
	Value     string
	InputType string // e.g., "insertText", "deleteContentBackward"
	Data      string // Inserted text (if any)
}

InputEventData contains input event data with full details.

type KeyboardEventData

type KeyboardEventData struct {
	Key       string
	Code      string // Physical key code (e.g., "KeyA", "Enter")
	Modifiers Modifiers
	Repeat    bool  // True if key is held down (auto-repeat)
	Location  uint8 // 0=standard, 1=left, 2=right, 3=numpad
}

KeyboardEventData contains keyboard event data.

type Modifiers

type Modifiers uint8

Modifiers represents keyboard/mouse modifier keys.

const (
	ModCtrl  Modifiers = 0x01
	ModShift Modifiers = 0x02
	ModAlt   Modifiers = 0x04
	ModMeta  Modifiers = 0x08
)

func (Modifiers) Has

func (m Modifiers) Has(mod Modifiers) bool

Has returns true if the specified modifier is set.

type MouseEventData

type MouseEventData struct {
	ClientX   int
	ClientY   int
	PageX     int // Position relative to document
	PageY     int
	OffsetX   int // Position relative to target element
	OffsetY   int
	Button    uint8
	Buttons   uint8 // Bitmask of currently pressed buttons
	Modifiers Modifiers
}

MouseEventData contains mouse event data.

type NavigateEventData struct {
	Path    string
	Replace bool
}

NavigateEventData contains navigation event data.

type Patch

type Patch struct {
	Op       PatchOp
	HID      string            // Target element's hydration ID
	Key      string            // Attribute/style/class key
	Value    string            // Value for text/attr/style/class
	ParentID string            // Parent HID for InsertNode/MoveNode/*At operations
	Index    int               // Insert/Move/*At position
	Node     *VNodeWire        // For InsertNode/ReplaceNode
	Bool     bool              // For SetChecked/SetSelected
	X        int               // For ScrollTo
	Y        int               // For ScrollTo
	Behavior ScrollBehavior    // For ScrollTo
	Params   map[string]string // URL query delta; empty value means remove key
	Path     string            // For NavPush/NavReplace (includes query string)
}

Patch represents a single DOM operation.

func NewAddClassPatch

func NewAddClassPatch(hid, class string) Patch

NewAddClassPatch creates an AddClass patch.

func NewBlurPatch

func NewBlurPatch(hid string) Patch

NewBlurPatch creates a Blur patch.

func NewDispatchPatch

func NewDispatchPatch(hid, eventName, detail string) Patch

NewDispatchPatch creates a Dispatch patch.

func NewFocusPatch

func NewFocusPatch(hid string) Patch

NewFocusPatch creates a Focus patch.

func NewInsertNodePatch

func NewInsertNodePatch(hid, parentID string, index int, node *VNodeWire) Patch

NewInsertNodePatch creates an InsertNode patch.

func NewMoveNodePatch

func NewMoveNodePatch(hid, parentID string, index int) Patch

NewMoveNodePatch creates a MoveNode patch.

func NewNavPushPatch

func NewNavPushPatch(path string) Patch

NewNavPushPatch creates a NavPush patch for full navigation (adds history entry). The path should be a relative path starting with "/" and may include query string. SECURITY: The path must be validated server-side to prevent open-redirect attacks.

func NewNavReplacePatch

func NewNavReplacePatch(path string) Patch

NewNavReplacePatch creates a NavReplace patch for full navigation (replaces history). The path should be a relative path starting with "/" and may include query string. SECURITY: The path must be validated server-side to prevent open-redirect attacks.

func NewRemoveAttrPatch

func NewRemoveAttrPatch(hid, key string) Patch

NewRemoveAttrPatch creates a RemoveAttr patch.

func NewRemoveClassPatch

func NewRemoveClassPatch(hid, class string) Patch

NewRemoveClassPatch creates a RemoveClass patch.

func NewRemoveNodeAtPatch

func NewRemoveNodeAtPatch(parentID string, index int) Patch

NewRemoveNodeAtPatch creates a RemoveNodeAt patch.

func NewRemoveNodePatch

func NewRemoveNodePatch(hid string) Patch

NewRemoveNodePatch creates a RemoveNode patch.

func NewRemoveStylePatch

func NewRemoveStylePatch(hid, property string) Patch

NewRemoveStylePatch creates a RemoveStyle patch.

func NewReplaceNodeAtPatch

func NewReplaceNodeAtPatch(parentID string, index int, node *VNodeWire) Patch

NewReplaceNodeAtPatch creates a ReplaceNodeAt patch.

func NewReplaceNodePatch

func NewReplaceNodePatch(hid string, node *VNodeWire) Patch

NewReplaceNodePatch creates a ReplaceNode patch.

func NewScrollToPatch

func NewScrollToPatch(hid string, x, y int, behavior ScrollBehavior) Patch

NewScrollToPatch creates a ScrollTo patch.

func NewSetAttrPatch

func NewSetAttrPatch(hid, key, value string) Patch

NewSetAttrPatch creates a SetAttr patch.

func NewSetCheckedPatch

func NewSetCheckedPatch(hid string, checked bool) Patch

NewSetCheckedPatch creates a SetChecked patch.

func NewSetDataPatch

func NewSetDataPatch(hid, key, value string) Patch

NewSetDataPatch creates a SetData patch.

func NewSetSelectedPatch

func NewSetSelectedPatch(hid string, selected bool) Patch

NewSetSelectedPatch creates a SetSelected patch.

func NewSetStylePatch

func NewSetStylePatch(hid, property, value string) Patch

NewSetStylePatch creates a SetStyle patch.

func NewSetTextAtPatch

func NewSetTextAtPatch(parentID string, index int, text string) Patch

NewSetTextAtPatch creates a SetTextAt patch.

func NewSetTextPatch

func NewSetTextPatch(hid, text string) Patch

NewSetTextPatch creates a SetText patch.

func NewSetValuePatch

func NewSetValuePatch(hid, value string) Patch

NewSetValuePatch creates a SetValue patch.

func NewToggleClassPatch

func NewToggleClassPatch(hid, class string) Patch

NewToggleClassPatch creates a ToggleClass patch.

func NewURLPushPatch

func NewURLPushPatch(params map[string]string) Patch

NewURLPushPatch creates a URLPush patch (adds history entry).

func NewURLReplacePatch

func NewURLReplacePatch(params map[string]string) Patch

NewURLReplacePatch creates a URLReplace patch (replaces current entry).

type PatchOp

type PatchOp uint8

PatchOp is the type of patch operation. This is a superset of vdom.PatchOp, with additional operations for the protocol.

const (
	// Core operations (matching vdom.PatchOp)
	PatchSetText     PatchOp = 0x01 // Update text content
	PatchSetAttr     PatchOp = 0x02 // Set attribute
	PatchRemoveAttr  PatchOp = 0x03 // Remove attribute
	PatchInsertNode  PatchOp = 0x04 // Insert new node
	PatchRemoveNode  PatchOp = 0x05 // Remove node
	PatchMoveNode    PatchOp = 0x06 // Move node
	PatchReplaceNode PatchOp = 0x07 // Replace node
	PatchSetValue    PatchOp = 0x08 // Set input value
	PatchSetChecked  PatchOp = 0x09 // Set checkbox checked
	PatchSetSelected PatchOp = 0x0A // Set select option selected
	PatchFocus       PatchOp = 0x0B // Focus element

	// Extended operations (protocol-only)
	PatchBlur          PatchOp = 0x0C // Blur element
	PatchScrollTo      PatchOp = 0x0D // Scroll to position
	PatchAddClass      PatchOp = 0x10 // Add CSS class
	PatchRemoveClass   PatchOp = 0x11 // Remove CSS class
	PatchToggleClass   PatchOp = 0x12 // Toggle CSS class
	PatchSetStyle      PatchOp = 0x13 // Set style property
	PatchRemoveStyle   PatchOp = 0x14 // Remove style property
	PatchSetData       PatchOp = 0x15 // Set data attribute
	PatchSetTextAt     PatchOp = 0x16 // Set text by parent/index
	PatchRemoveNodeAt  PatchOp = 0x17 // Remove node by parent/index
	PatchReplaceNodeAt PatchOp = 0x18 // Replace node by parent/index
	PatchDispatch      PatchOp = 0x20 // Dispatch client event

	// URL operations (Phase 12: URLParam 2.0)
	// Params are delta updates: keys omitted are left unchanged.
	// Empty-string values are delete tombstones for removing query keys.
	PatchURLPush    PatchOp = 0x30 // Update query params delta, push to history
	PatchURLReplace PatchOp = 0x31 // Update query params delta, replace current entry

	// Navigation operations (full route navigation)
	PatchNavPush    PatchOp = 0x32 // Full navigation, push history (NAV_PUSH)
	PatchNavReplace PatchOp = 0x33 // Full navigation, replace history (NAV_REPLACE)
)

Patch operation constants. Values 0x01-0x0B match vdom.PatchOp for compatibility.

func (PatchOp) String

func (op PatchOp) String() string

String returns the string representation of the patch operation.

type PatchesFrame

type PatchesFrame struct {
	Seq     uint64
	Patches []Patch
}

PatchesFrame represents a batch of patches with sequence number.

func DecodePatches

func DecodePatches(data []byte) (*PatchesFrame, error)

DecodePatches decodes a patches frame from bytes.

func DecodePatchesFrom

func DecodePatchesFrom(d *Decoder) (*PatchesFrame, error)

DecodePatchesFrom decodes a patches frame from a decoder. SECURITY: Enforces MaxPatchDepth to prevent stack overflow attacks.

type PingPong

type PingPong struct {
	Timestamp uint64 // Unix timestamp in milliseconds
}

PingPong is the payload for Ping and Pong messages.

type ProtocolVersion

type ProtocolVersion struct {
	Major uint8
	Minor uint8
}

ProtocolVersion represents a protocol version as major.minor.

type ResizeEventData

type ResizeEventData struct {
	Width  int
	Height int
}

ResizeEventData contains resize event data.

type ResyncRequest

type ResyncRequest struct {
	LastSeq uint64 // Last received sequence number
}

ResyncRequest is sent by client to request missed patches.

type ResyncResponse

type ResyncResponse struct {
	Type    ControlType // ResyncPatches or ResyncFull
	FromSeq uint64      // Starting sequence number (for ResyncPatches)
	Patches []Patch     // Missed patches (for ResyncPatches)
	HTML    string      // Full HTML (for ResyncFull)
}

ResyncResponse is sent by server with missed patches or full reload.

type SchemaRefreshReason

type SchemaRefreshReason uint8

SchemaRefreshReason indicates why a session refresh was triggered.

const (
	SchemaRefreshUnknown          SchemaRefreshReason = 0x00
	SchemaRefreshIDRemoved        SchemaRefreshReason = 0x01
	SchemaRefreshIDTypeChanged    SchemaRefreshReason = 0x02
	SchemaRefreshColdDeploy       SchemaRefreshReason = 0x03
	SchemaRefreshHashMismatch     SchemaRefreshReason = 0x04
	SchemaRefreshRuntimeViolation SchemaRefreshReason = 0x05
)

func (SchemaRefreshReason) String

func (sr SchemaRefreshReason) String() string

String returns the string representation of the schema refresh reason.

type ScrollBehavior

type ScrollBehavior uint8

ScrollBehavior represents the scroll behavior for PatchScrollTo.

const (
	ScrollInstant ScrollBehavior = 0
	ScrollSmooth  ScrollBehavior = 1
)

type ScrollEventData

type ScrollEventData struct {
	ScrollTop  int
	ScrollLeft int
}

ScrollEventData contains scroll event data.

type ServerHello

type ServerHello struct {
	Status     HandshakeStatus // Handshake result
	SessionID  string          // Session ID (new or existing)
	NextSeq    uint32          // Next expected sequence number
	ServerTime uint64          // Server time in Unix milliseconds
	Flags      uint16          // Server capability flags
	// AuthReason is an optional auth expiration reason for error handshakes.
	// AuthReasonSet indicates whether the reason was included in the payload.
	AuthReason    uint8
	AuthReasonSet bool
	// SchemaReason is provided when Status == HandshakeSchemaMismatch.
	SchemaReason    SchemaRefreshReason
	SchemaReasonSet bool
	// Banner payload (optional).
	BannerMessage   string
	BannerDetail    string
	BannerDismissMS uint16
	BannerCSSClass  string
	BannerSet       bool
}

ServerHello is the server's response to ClientHello.

func DecodeServerHello

func DecodeServerHello(data []byte) (*ServerHello, error)

DecodeServerHello decodes a ServerHello from bytes.

func DecodeServerHelloFrom

func DecodeServerHelloFrom(d *Decoder) (*ServerHello, error)

DecodeServerHelloFrom decodes a ServerHello from a decoder.

func NewServerHello

func NewServerHello(sessionID string, nextSeq uint32, serverTime uint64) *ServerHello

NewServerHello creates a new successful ServerHello.

func NewServerHelloError

func NewServerHelloError(status HandshakeStatus) *ServerHello

NewServerHelloError creates a ServerHello with an error status.

func NewServerHelloErrorWithReason

func NewServerHelloErrorWithReason(status HandshakeStatus, reason uint8) *ServerHello

NewServerHelloErrorWithReason creates a ServerHello with an error status and reason.

func NewServerHelloSchemaError

func NewServerHelloSchemaError(reason SchemaRefreshReason, banner BannerSpec) *ServerHello

NewServerHelloSchemaError creates a schema mismatch ServerHello with banner payload.

type SessionRefreshAck

type SessionRefreshAck struct {
	Source string
}

SessionRefreshAck acknowledges a session refresh notification.

type SessionRefreshCommand

type SessionRefreshCommand struct {
	Reason   SchemaRefreshReason
	DevMode  bool
	Message  string
	Detail   string
	DelayMS  uint16
	CSSClass string
}

SessionRefreshCommand notifies the client of a session refresh.

type SubmitEventData

type SubmitEventData struct {
	Fields map[string]string
}

SubmitEventData contains form submission data.

type TouchEventData

type TouchEventData struct {
	Touches        []TouchPoint // All current touches
	TargetTouches  []TouchPoint // Touches on this element
	ChangedTouches []TouchPoint // Touches that changed in this event
}

TouchEventData contains touch event data.

type TouchPoint

type TouchPoint struct {
	ID      int
	ClientX int
	ClientY int
	PageX   int // Position relative to document
	PageY   int
}

TouchPoint represents a single touch point.

type TransitionEventData

type TransitionEventData struct {
	PropertyName  string
	ElapsedTime   float64
	PseudoElement string
}

TransitionEventData contains CSS transition event data.

type VNodeWire

type VNodeWire struct {
	Kind     vdom.VKind        // Node type
	Tag      string            // Element tag name
	HID      string            // Hydration ID
	Attrs    map[string]string // String attributes only (no handlers)
	Children []*VNodeWire      // Child nodes
	Text     string            // For Text and Raw nodes
}

VNodeWire is the wire format for VNodes. It contains only serializable data (no event handlers or components).

func DecodeVNodeWire

func DecodeVNodeWire(d *Decoder) (*VNodeWire, error)

DecodeVNodeWire decodes a VNodeWire from the decoder. SECURITY: Enforces MaxVNodeDepth to prevent stack overflow attacks.

func NewElementWire

func NewElementWire(tag string, attrs map[string]string, children ...*VNodeWire) *VNodeWire

NewElementWire creates an element VNodeWire.

func NewFragmentWire

func NewFragmentWire(children ...*VNodeWire) *VNodeWire

NewFragmentWire creates a fragment VNodeWire.

func NewRawWire

func NewRawWire(html string) *VNodeWire

NewRawWire creates a raw HTML VNodeWire.

func NewTextWire

func NewTextWire(text string) *VNodeWire

NewTextWire creates a text VNodeWire.

func VNodeToWire

func VNodeToWire(node *vdom.VNode) *VNodeWire

VNodeToWire converts a vdom.VNode to wire format. Event handlers are stripped; only string attributes are included. Component nodes should be rendered before calling this function.

func VNodeToWireWithPolicy

func VNodeToWireWithPolicy(node *vdom.VNode, policy vdom.URLPolicy) *VNodeWire

VNodeToWireWithPolicy converts a vdom.VNode to wire format using the provided URL policy. The policy should be normalized (use NormalizeURLPolicy or URLPolicyFromSchemes). Raw HTML nodes are sink-sanitized unless policy.AllowUnsafeRawHTML is true.

func (*VNodeWire) ToVNode

func (w *VNodeWire) ToVNode() *vdom.VNode

ToVNode converts a VNodeWire back to a vdom.VNode. Note: Event handlers cannot be restored from wire format.

type WheelEventData

type WheelEventData struct {
	DeltaX    float64
	DeltaY    float64
	DeltaZ    float64
	DeltaMode uint8 // 0=pixels, 1=lines, 2=pages
	ClientX   int
	ClientY   int
	Modifiers Modifiers
}

WheelEventData contains mouse wheel event data.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL