A register-based reactivity system designed for dependency tracking and automated state synchronization within virtual machine architecture.
TypeScript
15
158 commits
updated Sep 20, 2026
Register-Based Bytecode Virtual Machine UI Framework
256-Register Virtual Machine • AOT Bytecode Stream • Comment-Anchored Reactive Regions • Zero Virtual DOM
Have questions, feature ideas, or want to discuss compiler optimizations and register VM architecture?
Connect with core developers, ask questions, share feedback, and help shape the future of DriftJS.
DriftJS is a frontend UI framework powered by an in-browser register-based Bytecode Virtual Machine (VM).
Unlike traditional Virtual DOM frameworks (e.g., React) that re-evaluate large tree structures or compiler-only reactive frameworks (e.g., Svelte), DriftJS compiles .drift single-file templates into compact binary-serializable bytecode streams (CompiledModule). At runtime, a lightweight 256-register VM executes these instructions directly against the DOM with minimal memory allocation and surgical updates.
r0–r255) for DOM elements, text nodes, and primitives—avoiding the overhead and memory churn of virtual DOM trees..drift Single File Components ahead-of-time into binary-like instruction streams and static constant pools, with reactive state dependencies mapped directly to bytecode program counters.<!--if-->, <!--for-->) to isolate dynamic subtrees, enabling surgical, in-place updates without traversing or re-evaluating surrounding component trees.driftjs-dom) and headlessly on the server (driftjs-ssr), producing identical comment anchors for 1:1 SSR hydration.Create a new DriftJS app instantly using create-drift:
pnpm create drift my-app
# or using npm / yarn / bun
npm create drift my-app
DriftJS is organized as a monorepo published on npm:
| Package | Path | Description |
|---|---|---|
create-drift | packages/cli | Interactive CLI scaffolding tool (npm create drift) |
driftjs-compiler | packages/compiler | Lexer, Parser, Transformer, & Bytecode Generator emitting CompiledModule bytecode |
driftjs-dom | packages/dom | 256-Register Client VM, DOM reconciler, SSR hydration, & mount() API |
driftjs-router | packages/router | Client-side SPA routing engine with history drivers & matched route views |
driftjs-ssr | packages/ssr | Headless Server-Side Rendering VM engine (renderToString()) |
driftjs-shared | packages/utils | Shared Scope, Context API, and Expression Evaluator engine |
driftjs-vite-plugin | packages/vite-plugin | Vite plugin transforming .drift SFCs into synthetic ESM modules |
driftjs-vscode | packages/vscode-plugin | VS Code Extension for .drift SFC syntax highlighting & diagnostics |
template | template | Starter project template with Vite, TypeScript, and .drift counter example |
The compilation and execution workflow consists of 5 tightly decoupled stages:
.drift Template
│
▼
[ DriftLexer ] ──────► On-demand parser-driven tokenization
│
▼
[ DriftParser ] ─────► AST construction (ProgramNode, ElementNode, IfNode, ForNode, etc.)
│
▼
[ DriftTransformer ] ─► Whitespace stripping & JS expression enrichment
│
▼
[ DriftGenerator ] ───► Emits 15-Opcode Bytecode Array, Constant Pool, & Reactive Bindings
│
▼
[ DriftClientVM / DriftServerVM ] ──► Executes Bytecode via 256 Registers & Reactive Anchors
.drift)A .drift component blends standard HTML markup with JavaScript state logic inside top-level <script> blocks and control directives (@if, @for, @switch).
<script>)Declare component reactive state and functions inside a top-level <script> block. Any top-level let or const declarations automatically become part of the component's reactive scope.
<script>
// Declare reactive state variables
let user = "Alex";
let items = [
{ id: 1, text: "Build DriftJS Compiler", done: true },
{ id: 2, text: "Write Keyed LIS Reconciler", done: true },
{ id: 3, text: "Deploy Web App", done: false }
];
let filter = "all";
// Event handlers & state mutation functions
function toggleItem(id) {
items = items.map(item => item.id === id ? { ...item, done: !item.done } : item);
}
function removeItem(id) {
items = items.filter(item => item.id !== id);
}
function setFilter(newFilter) {
filter = newFilter;
}
</script>
{ ... })Embed dynamic values directly within DOM text content using curly braces {}. Any valid JavaScript expression is supported and evaluated inside the component scope.
<!-- Property access -->
<h1>Welcome back, {user}!</h1>
<!-- Calculations & JavaScript expressions -->
<p>Total Tasks: {items.length}</p>
<p>Completed Tasks: {items.filter(i => i.done).length}</p>
<!-- Ternary conditional expressions -->
<p>Status: {items.every(i => i.done) ? "All Completed! 🎉" : "In Progress ⏳"}</p>
Attributes can be static strings, dynamic JavaScript expressions, or event handlers.
<!-- Static attributes -->
<div class="task-card" data-category="work">
<!-- Dynamic string evaluation -->
<div class={filter === "all" ? "tab active" : "tab"}>
<!-- Boolean attributes (attribute present when true, removed when false) -->
<button disabled={items.length === 0}>Clear All</button>
onclick={...}, oninput={...})Event handlers automatically hook into DriftJS's central event delegation engine. Any state mutated inside an event handler triggers targeted DOM updates automatically.
<!-- Direct function binding -->
<button onclick={ () => setFilter("all") }>Show All</button>
<button onclick={ () => setFilter("pending") }>Show Pending</button>
<!-- Inline arrow functions with parameters -->
<button onclick={ () => toggleItem(item.id) }>Toggle Status</button>
<button onclick={ () => removeItem(item.id) }>Delete Task</button>
@if, @else if, @else)Render DOM subtrees conditionally based on reactive conditions. Conditional blocks are anchored by comment nodes (<!--if--> / <!--/if-->) for targeted sub-tree mounting.
@if filter === "all" {
<p class="badge badge-info">Showing all {items.length} items</p>
}
@else if filter === "pending" {
<p class="badge badge-warning">Showing pending items only</p>
}
@else {
<p class="badge badge-success">Completed items view</p>
}
@for)Iterate over arrays using @for. DriftJS reconciliation uses the Keyed LIS (Longest Increasing Subsequence) algorithm to re-order and patch DOM elements efficiently with minimal node recreations.
@for item in items {
<div class="task-row">
<span class={item.done ? "line-through" : ""}>{item.text}</span>
<button onclick={ () => toggleItem(item.id) }>Check</button>
</div>
}
@for (item, index) in items {
<li class="list-item">
<span class="index">#{index + 1}</span>
<span class="title">{item.text}</span>
<button onclick={ () => removeItem(item.id) }>Remove</button>
</li>
}
@switch, @case, @default)Pattern match discriminant expressions into distinct @case branches.
@switch filter {
@case "all" {
<div class="view-all">All Tasks Summary</div>
}
@case "pending" {
<div class="view-pending">Pending Tasks Overview</div>
}
@default {
<div class="view-default">Custom Filter Mode</div>
}
}
Here is an example of complete .drift component combining script scope, state reactivity, interpolations, conditional blocks, and loop reconciliation:
<script>
let newTaskTitle = "";
let priority = "medium";
let tasks = [
{ id: 101, title: "Configure Vite Plugin", priority: "high", done: true },
{ id: 102, title: "Optimize VM Registers", priority: "high", done: false },
{ id: 103, title: "Write Benchmarks", priority: "medium", done: false }
];
function toggleTask(id) {
tasks = tasks.map(t => t.id === id ? { ...t, done: !t.done } : t);
}
function deleteTask(id) {
tasks = tasks.filter(t => t.id !== id);
}
</script>
<div class="app-container">
<header class="app-header">
<h1>Task Board</h1>
<span class="counter">Pending: {tasks.filter(t => !t.done).length} / {tasks.length}</span>
</header>
@if tasks.length === 0 {
<div class="empty-state">
<p>🎉 All tasks are completed! Enjoy your day.</p>
</div>
}
@else {
<ul class="task-list">
@for (task, idx) in tasks {
<li class={task.done ? "task-item completed" : "task-item"}>
<span class="task-num">#{idx + 1}</span>
<span class="task-title">{task.title}</span>
@switch task.priority {
@case "high" { <span class="tag tag-red">High Priority</span> }
@case "medium" { <span class="tag tag-amber">Medium Priority</span> }
@default { <span class="tag tag-gray">Low Priority</span> }
}
<button onclick={ () => toggleTask(task.id) }>
{task.done ? "Undo" : "Complete"}
</button>
<button class="danger" onclick={ () => deleteTask(task.id) }>Delete</button>
</li>
}
</ul>
}
</div>
DriftJS relies on a streamlined 15-opcode ISA. Detailed specifications are in docs/ISA.md.
^20.0.0 or higherpnpm ^9.0.0 or higherClone the repository:
git clone https://github.com/hrutavmodha/driftjs.git
cd driftjs
Install dependencies:
pnpm install
Build all workspace packages:
pnpm build
Run the test suite:
pnpm test
All unit and integration tests across the test suites will run via Vitest.
Typecheck workspace:
pnpm typecheck
Run starter application:
cd template
pnpm dev
We welcome contributions of all kinds! Whether you want to fix bugs, optimize VM opcode execution, improve compiler error reporting, add developer tools, or expand benchmark coverage:
git checkout -b feature/my-feature).pnpm test).pnpm typecheck).Together, let's make DriftJS a production-grade, ultra-fast UI framework!
MIT © Hrutav Modha
TypeScript
89.1%
CSS
5.6%
JavaScript
3.3%
A register-based reactivity system designed for dependency tracking and automated state synchronization within virtual machine architecture.
TypeScript
15
158 commits
updated Sep 20, 2026
Register-Based Bytecode Virtual Machine UI Framework
256-Register Virtual Machine • AOT Bytecode Stream • Comment-Anchored Reactive Regions • Zero Virtual DOM
Have questions, feature ideas, or want to discuss compiler optimizations and register VM architecture?
Connect with core developers, ask questions, share feedback, and help shape the future of DriftJS.
DriftJS is a frontend UI framework powered by an in-browser register-based Bytecode Virtual Machine (VM).
Unlike traditional Virtual DOM frameworks (e.g., React) that re-evaluate large tree structures or compiler-only reactive frameworks (e.g., Svelte), DriftJS compiles .drift single-file templates into compact binary-serializable bytecode streams (CompiledModule). At runtime, a lightweight 256-register VM executes these instructions directly against the DOM with minimal memory allocation and surgical updates.
r0–r255) for DOM elements, text nodes, and primitives—avoiding the overhead and memory churn of virtual DOM trees..drift Single File Components ahead-of-time into binary-like instruction streams and static constant pools, with reactive state dependencies mapped directly to bytecode program counters.<!--if-->, <!--for-->) to isolate dynamic subtrees, enabling surgical, in-place updates without traversing or re-evaluating surrounding component trees.driftjs-dom) and headlessly on the server (driftjs-ssr), producing identical comment anchors for 1:1 SSR hydration.Create a new DriftJS app instantly using create-drift:
pnpm create drift my-app
# or using npm / yarn / bun
npm create drift my-app
DriftJS is organized as a monorepo published on npm:
| Package | Path | Description |
|---|---|---|
create-drift | packages/cli | Interactive CLI scaffolding tool (npm create drift) |
driftjs-compiler | packages/compiler | Lexer, Parser, Transformer, & Bytecode Generator emitting CompiledModule bytecode |
driftjs-dom | packages/dom | 256-Register Client VM, DOM reconciler, SSR hydration, & mount() API |
driftjs-router | packages/router | Client-side SPA routing engine with history drivers & matched route views |
driftjs-ssr | packages/ssr | Headless Server-Side Rendering VM engine (renderToString()) |
driftjs-shared | packages/utils | Shared Scope, Context API, and Expression Evaluator engine |
driftjs-vite-plugin | packages/vite-plugin | Vite plugin transforming .drift SFCs into synthetic ESM modules |
driftjs-vscode | packages/vscode-plugin | VS Code Extension for .drift SFC syntax highlighting & diagnostics |
template | template | Starter project template with Vite, TypeScript, and .drift counter example |
The compilation and execution workflow consists of 5 tightly decoupled stages:
.drift Template
│
▼
[ DriftLexer ] ──────► On-demand parser-driven tokenization
│
▼
[ DriftParser ] ─────► AST construction (ProgramNode, ElementNode, IfNode, ForNode, etc.)
│
▼
[ DriftTransformer ] ─► Whitespace stripping & JS expression enrichment
│
▼
[ DriftGenerator ] ───► Emits 15-Opcode Bytecode Array, Constant Pool, & Reactive Bindings
│
▼
[ DriftClientVM / DriftServerVM ] ──► Executes Bytecode via 256 Registers & Reactive Anchors
.drift)A .drift component blends standard HTML markup with JavaScript state logic inside top-level <script> blocks and control directives (@if, @for, @switch).
<script>)Declare component reactive state and functions inside a top-level <script> block. Any top-level let or const declarations automatically become part of the component's reactive scope.
<script>
// Declare reactive state variables
let user = "Alex";
let items = [
{ id: 1, text: "Build DriftJS Compiler", done: true },
{ id: 2, text: "Write Keyed LIS Reconciler", done: true },
{ id: 3, text: "Deploy Web App", done: false }
];
let filter = "all";
// Event handlers & state mutation functions
function toggleItem(id) {
items = items.map(item => item.id === id ? { ...item, done: !item.done } : item);
}
function removeItem(id) {
items = items.filter(item => item.id !== id);
}
function setFilter(newFilter) {
filter = newFilter;
}
</script>
{ ... })Embed dynamic values directly within DOM text content using curly braces {}. Any valid JavaScript expression is supported and evaluated inside the component scope.
<!-- Property access -->
<h1>Welcome back, {user}!</h1>
<!-- Calculations & JavaScript expressions -->
<p>Total Tasks: {items.length}</p>
<p>Completed Tasks: {items.filter(i => i.done).length}</p>
<!-- Ternary conditional expressions -->
<p>Status: {items.every(i => i.done) ? "All Completed! 🎉" : "In Progress ⏳"}</p>
Attributes can be static strings, dynamic JavaScript expressions, or event handlers.
<!-- Static attributes -->
<div class="task-card" data-category="work">
<!-- Dynamic string evaluation -->
<div class={filter === "all" ? "tab active" : "tab"}>
<!-- Boolean attributes (attribute present when true, removed when false) -->
<button disabled={items.length === 0}>Clear All</button>
onclick={...}, oninput={...})Event handlers automatically hook into DriftJS's central event delegation engine. Any state mutated inside an event handler triggers targeted DOM updates automatically.
<!-- Direct function binding -->
<button onclick={ () => setFilter("all") }>Show All</button>
<button onclick={ () => setFilter("pending") }>Show Pending</button>
<!-- Inline arrow functions with parameters -->
<button onclick={ () => toggleItem(item.id) }>Toggle Status</button>
<button onclick={ () => removeItem(item.id) }>Delete Task</button>
@if, @else if, @else)Render DOM subtrees conditionally based on reactive conditions. Conditional blocks are anchored by comment nodes (<!--if--> / <!--/if-->) for targeted sub-tree mounting.
@if filter === "all" {
<p class="badge badge-info">Showing all {items.length} items</p>
}
@else if filter === "pending" {
<p class="badge badge-warning">Showing pending items only</p>
}
@else {
<p class="badge badge-success">Completed items view</p>
}
@for)Iterate over arrays using @for. DriftJS reconciliation uses the Keyed LIS (Longest Increasing Subsequence) algorithm to re-order and patch DOM elements efficiently with minimal node recreations.
@for item in items {
<div class="task-row">
<span class={item.done ? "line-through" : ""}>{item.text}</span>
<button onclick={ () => toggleItem(item.id) }>Check</button>
</div>
}
@for (item, index) in items {
<li class="list-item">
<span class="index">#{index + 1}</span>
<span class="title">{item.text}</span>
<button onclick={ () => removeItem(item.id) }>Remove</button>
</li>
}
@switch, @case, @default)Pattern match discriminant expressions into distinct @case branches.
@switch filter {
@case "all" {
<div class="view-all">All Tasks Summary</div>
}
@case "pending" {
<div class="view-pending">Pending Tasks Overview</div>
}
@default {
<div class="view-default">Custom Filter Mode</div>
}
}
Here is an example of complete .drift component combining script scope, state reactivity, interpolations, conditional blocks, and loop reconciliation:
<script>
let newTaskTitle = "";
let priority = "medium";
let tasks = [
{ id: 101, title: "Configure Vite Plugin", priority: "high", done: true },
{ id: 102, title: "Optimize VM Registers", priority: "high", done: false },
{ id: 103, title: "Write Benchmarks", priority: "medium", done: false }
];
function toggleTask(id) {
tasks = tasks.map(t => t.id === id ? { ...t, done: !t.done } : t);
}
function deleteTask(id) {
tasks = tasks.filter(t => t.id !== id);
}
</script>
<div class="app-container">
<header class="app-header">
<h1>Task Board</h1>
<span class="counter">Pending: {tasks.filter(t => !t.done).length} / {tasks.length}</span>
</header>
@if tasks.length === 0 {
<div class="empty-state">
<p>🎉 All tasks are completed! Enjoy your day.</p>
</div>
}
@else {
<ul class="task-list">
@for (task, idx) in tasks {
<li class={task.done ? "task-item completed" : "task-item"}>
<span class="task-num">#{idx + 1}</span>
<span class="task-title">{task.title}</span>
@switch task.priority {
@case "high" { <span class="tag tag-red">High Priority</span> }
@case "medium" { <span class="tag tag-amber">Medium Priority</span> }
@default { <span class="tag tag-gray">Low Priority</span> }
}
<button onclick={ () => toggleTask(task.id) }>
{task.done ? "Undo" : "Complete"}
</button>
<button class="danger" onclick={ () => deleteTask(task.id) }>Delete</button>
</li>
}
</ul>
}
</div>
DriftJS relies on a streamlined 15-opcode ISA. Detailed specifications are in docs/ISA.md.
^20.0.0 or higherpnpm ^9.0.0 or higherClone the repository:
git clone https://github.com/hrutavmodha/driftjs.git
cd driftjs
Install dependencies:
pnpm install
Build all workspace packages:
pnpm build
Run the test suite:
pnpm test
All unit and integration tests across the test suites will run via Vitest.
Typecheck workspace:
pnpm typecheck
Run starter application:
cd template
pnpm dev
We welcome contributions of all kinds! Whether you want to fix bugs, optimize VM opcode execution, improve compiler error reporting, add developer tools, or expand benchmark coverage:
git checkout -b feature/my-feature).pnpm test).pnpm typecheck).Together, let's make DriftJS a production-grade, ultra-fast UI framework!
MIT © Hrutav Modha
TypeScript
89.1%
CSS
5.6%
JavaScript
3.3%