Skip to content

feat: fiber architecture rewrite with lane-based scheduler and type safety#50

Merged
MarcelOlsen merged 2 commits into
masterfrom
feat/fiber-rewrite
May 19, 2026
Merged

feat: fiber architecture rewrite with lane-based scheduler and type safety#50
MarcelOlsen merged 2 commits into
masterfrom
feat/fiber-rewrite

Conversation

@MarcelOlsen

Copy link
Copy Markdown
Owner

Overview

This PR replaces the old hook-based reconciler with a full fiber architecture modeled after React's internals. The public API surface remains compatible, but the internal reconciliation engine is completely rewritten.


Architecture

Fiber Tree

  • Work-in-progress / current dual tree for interruptible renders
  • Fiber nodes track lanes (pending work), flags (side effects), and effects (hook lifecycle)

Work Loop

  • performSyncWorkOnRoot — synchronous render + commit
  • performConcurrentWorkOnRoot — time-sliced render with shouldYield checks
  • ensureRootIsScheduled — routes sync lanes directly, non-sync lanes via scheduler

Begin / Complete Work

  • beginWork — builds WIP fibers from element tree, calls component functions, reconciles children
  • completeWork — finalizes host component props, creates DOM nodes, propagates effects upward

Commit Phase

  • commitRoot — three-pass commit: mutation (DOM changes) → layout effects → passive effects flush
  • commitWork.ts — DOM mutation helpers (create, insert, update, delete)
  • commitRoot.ts — effect list traversal and execution order

Lane-Based Priority System

  • 16-bit branded Lane / Lanes types with bitwise operations
  • mergeLanes, intersectLanes, removeLanes, getHighestPriorityLane
  • Lane entanglement for transition batching
  • Priority levels: SyncLane, InputContinuousLane, DefaultLane, TransitionLane1/2, IdleLane

Scheduler

  • Binary min-heap (O(log n)) for task queue instead of Array.sort()
  • scheduleCallback, shouldYield, cancelCallback, runWithPriority
  • lanesToSchedulerPriority / schedulerPriorityToLane bridge

Type Safety Hardening

  • src/fiber/bitwise.ts — centralised unsafe-cast boundary for all Lane / Lanes / Flags conversions. Zero stray as number elsewhere.
  • Lanes = Lane alias — resolves impossible branded-type incompatibilities at every function boundary while keeping type branding.
  • HookEffectTag = number — bitwise OR on effect tags naturally produces number; using a branded union would fail.
  • Compile-time enforcementtests/fiber/types.typecheck.ts with @ts-expect-error directives that fail on regression.

New Modules (17 files)

Module Purpose
src/fiber/bitwise.ts Branded type conversion helpers
src/fiber/minHeap.ts Binary min-heap for scheduler task queue
src/fiber/workLoop.ts Work loop + sync + concurrent rendering paths
src/fiber/beginWork.ts Begin work phase
src/fiber/completeWork.ts Complete work phase
src/fiber/commitWork.ts DOM mutation helpers
src/fiber/commitRoot.ts Commit root orchestration
src/fiber/scheduler.ts Priority task scheduler
src/fiber/lanes.ts Lane priority system
src/fiber/childReconciler.ts Child reconciliation with key-based diffing
src/fiber/fiberHooks.ts Hook implementations for fiber architecture
src/fiber/effectList.ts Effect collection and execution
src/fiber/workInProgress.ts WIP tree management
src/fiber/createFiber.ts Fiber factory functions
src/fiber/typeGuards.ts Runtime type guards and assertions
src/fiber/hydration.ts SSR hydration support
src/fiber/resumability.ts Serialization / deserialization for SSR

Removed Modules (7 files)

  • src/dom-renderer/index.ts — replaced by fiber commit phase
  • src/fragments/index.ts — inlined into core
  • src/hooks/index.ts / src/hooks/types.ts — replaced by fiberHooks.ts
  • src/reconciler/index.ts — replaced by full fiber reconciler
  • tests/MiniReact.reconciler.test.ts — superseded by fiber tests
  • .trae/rules/project_rules.md — stale project rules

Browser Showcase

examples/interactive-showcase/ — Vite-powered live demo covering all 7 public APIs:

  • useState — counter with history
  • useEffect + useRef — interval timer with animated display
  • useMemo + useCallback — filterable list with render count
  • createContext + useContext — theme switcher
  • createPortal — floating panel outside root DOM
  • Fragment — dynamic grid columns
  • useReducer — todo list with add/remove

Run with: cd examples/interactive-showcase && npx vite


Test Coverage

  • 473 tests, 0 failures, 1,526 expectations across 38 files
  • 9 new test modules covering previously untested internals:
    • bitwise.test.ts, minHeap.test.ts, typeGuards.test.ts, lanes.test.ts
    • scheduler.test.ts, resumability.test.ts, hydration.test.ts
    • fiberUtils.test.ts, commitIntegration.test.ts
  • Compile-time type enforcement: tests/fiber/types.typecheck.ts

Breaking Changes

None for the public API. All internal refactoring. Existing consumers using:

import { createElement, render, useState, useEffect, useReducer, useRef, useMemo, useCallback, createContext, useContext, createPortal, Fragment } from "@marcelolsen/mini-react";

…will continue to work without changes.


Verification

# Tests
bun test

# Type check
bun run typecheck   # 0 errors

Checklist

  • Tests pass (473 / 473)
  • Type check clean (0 errors)
  • Biome checks pass on new files
  • Showcase example runs in browser
  • No public API breakage

Closes the entire fiber architecture stack (fiber/lanes, fiber/scheduler, fiber/workloop, fiber/public-api, fiber/tests, fiber/type-safety).

@MarcelOlsen
MarcelOlsen force-pushed the feat/fiber-rewrite branch from 4d9c089 to 0f92c9d Compare May 2, 2026 13:06
…afety

BREAKING CHANGE: Replaces the old hook-based reconciler with a full fiber
architecture modeled after React's internals. The public API surface remains
compatible, but the internal reconciliation engine is completely new.

## New Architecture
- **Fiber tree**: work-in-progress / current dual tree for interruptible renders
- **Work loop**:  and
- **Begin / Complete work**: separate phases for building and finalizing fibers
- **Commit phase**: mutation + layout effects, then passive effects flush
- **Lane-based priority system**: 16-bit branded  /  with merge,
  intersect, highest-priority selection, and entanglement
- **Scheduler**: binary min-heap () with ,
  , and priority-based task ordering
- **Concurrent rendering groundwork**: time-slicing ready, sync path still default

## Type Safety Hardening
- Centralised unsafe-cast boundary:  — all  /
   /  conversions live here; zero stray  elsewhere
-  alias resolves impossible branded-type incompatibilities
-  (bitwise OR produces  naturally)
- Compile-time enforcement:  with
   directives

## New Modules
-  — branded type conversion helpers
-  — binary min-heap for scheduler task queue
-  — work loop + sync + concurrent rendering paths
-  — begin work phase
-  — complete work phase
-  — DOM mutation helpers
-  — commit root orchestration
-  — priority task scheduler
-  — lane priority system
-  — child reconciliation with key-based diff
-  — hook implementations for fiber architecture
-  — effect collection and execution
-  — WIP tree management
-  — fiber factory functions
-  — runtime type guards and assertions
-  — SSR hydration support
-  — serialization / deserialization for SSR
-  — live Vite-powered browser demo

## Tests
- 9 new test modules covering previously untested internals
- 473 tests, 0 failures, 1,526 expectations across 38 files

## Verification
```bash
bun test          # 473 pass, 0 fail
bun run typecheck # 0 errors
```
@MarcelOlsen
MarcelOlsen force-pushed the feat/fiber-rewrite branch from 0f92c9d to a7d6b69 Compare May 2, 2026 13:26
@MarcelOlsen
MarcelOlsen merged commit d59020e into master May 19, 2026
4 checks passed
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