Skip to content

Bugfix/general audit#24

Merged
hexplus merged 28 commits intomainfrom
bugfix/general-audit
Apr 14, 2026
Merged

Bugfix/general audit#24
hexplus merged 28 commits intomainfrom
bugfix/general-audit

Conversation

@hexplus
Copy link
Copy Markdown
Owner

@hexplus hexplus commented Apr 14, 2026

Description

Comprehensive hardening pass across reactivity, rendering, SSR, widgets, security, and build tooling.

Reactivity & rendering

  • New retrack() primitive for derived pulls (skips cleanup+re-add Set churn; preserves dynamic-dep correctness)
  • effect() gains onCleanup callback param for ergonomic teardown
  • derived() gains equals option to suppress equivalent recomputes
  • Dispose re-entry safe (snapshot-then-delete + bounded extra-pass drain)
  • each() itemGetter wraps in untracked() so rows don't over-subscribe
  • bindChildNode O(n²) diff → O(n+m) with Set; dedupes duplicate node refs
  • batch flush wrapped in try/finally so throwing subscriber can't strand pendingSignals
  • lifecycle.fireUnmount defers + re-checks isConnected (no false unmount on re-parent)
  • keepAlive disposed flag; cached subtrees cleaned on anchor dispose

SSR

  • hydrate() / hydrateIslands / hydrateProgressively use replaceChildren/replaceWith so reactive bindings actually drive the visible DOM
  • runInSSRContext uses AsyncLocalStorage for per-request isolation
  • serializeState with byte cap + escape U+2028/9; deserializeState dev-warn without validator

Async & data

  • workerFn per-task FIFO queue + addEventListener (no onmessage crosstalk); terminate-on-error
  • infiniteQuery generation guard + abort on key change
  • offlineStore single-tx put/remove, cursor-snapshot sync, pull skips items with pending local edits
  • query dedup promise capture, sync-throw cleanup, onSettled in finally, idempotent dispose + gcTimer dedup
  • chunkLoader true LRU, invalidate clears preloaded, closures replace this.load
  • serviceWorker listener tracking + detach on update
  • incrementalRegeneration, routerSSR, wakeLock, clearQueryCache refetchers: .catch instead of silent

Widgets — WAI-ARIA bind() layer

  • Tabs / Accordion / Tooltip / Popover / Combobox / Select / FileUpload / datePicker
  • Keyboard + roving tabindex per APG spec, idempotent via WeakMap, full attribute restore on dispose
  • Loading + toast live-region semantics; a11y.announce isConnected-guarded; FocusTrap keydown cleanup
  • datePicker day-1 anchor fixes Jan-31→Mar-3 overflow
  • form wrappedSet clears manualErrors on edit

Security

  • URL_ATTRIBUTES adds xlink:href, formtarget, ping, data
  • persist + dragDrop JSON.parse revivers block __proto__/constructor/prototype
  • loadRemoteModule / loadWasmModule / preloadWasm require allowedOrigins or explicit unsafelyAllowAnyOrigin (CWE-829)
  • compiled.staticTemplate / precompile require TrustedHTML brand (CWE-79)
  • Router refuses protocol-relative redirects (CWE-601)
  • Redirect queueMicrotask navigations .catch unhandled rejections
  • speech.ts utterance listeners { once: true } + disposed-guard

API / ergonomics

  • Renames: useSelectorselect (redux/zustand), useDefaultPluginRegistrysetDefaultPluginRegistry
  • Exports: takePendingError, trustHTML/TrustedHTML, Dispose type, __resetQueryCache, __resetDialogStack, __removeRouterPagehideHandler
  • Error-prefix standardized to [SibuJS] across modules
  • Router pagehide listener lazy-initialized on first createRouter() (honors sideEffects: false)

Build / release

  • tsup --clean; ./cdn subpath export; publishConfig.provenance: true
  • publish.mjs publishes BEFORE git commit/tag (no orphan commits on publish failure)
  • runArgs throws on failure (was silently returning null)
  • tsconfig.json drops types: ["vitest"] — zero src/ deps on test-only types

Performance

  • propagateDirty iterative worklist with already-dirty skip
  • bindChildNode Set-based reuse detection
  • Speech polling only while active (was constant 5Hz)
  • Spring animation is now dt-aware (frame-rate independent + NaN guards)
  • Exponential backoff + jitter on socket/stream auto-reconnect + maxReconnects=10 default

Tests / DX

  • +10 new tests (keepAlive LRU/dispose, pluginRegistry isolation, widget ARIA bind)
  • noUnusedVariables + unused biome suppressions cleaned
  • dispose.ts snapshots childNodes (no live NodeList mutation during walk)

Related Issue

Closes #

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • I have read CONTRIBUTING.md
  • My code builds without errors
  • I have tested my changes
  • I have updated documentation if needed

hexplus added 28 commits March 28, 2026 15:11
…crosstalk, dispose re-entry; add retrack() for derived pulls; widget ARIA bind() (Tabs/Accordion/Tooltip/Popover/Combobox/Select/FileUpload/datePicker); effect() onCleanup; security (xlink:href, JSON reviver, loadRemoteModule/Wasm allowlist); lazy router pagehide; publish.mjs order + provenance; bench 2187/2187 tests, 0 lint
@hexplus hexplus merged commit 6b2afe4 into main Apr 14, 2026
1 check passed
@hexplus hexplus deleted the bugfix/general-audit branch April 14, 2026 23:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant