Phase 2 Technical Specification: Component Architecture & V1 Scope Boundary
1. Executive Summary & Orchestration Boundary
WebDB enforces a strict architectural boundary between Host Orchestration (JavaScript/TypeScript) and the Engine Core (Strict C-Style JS in V1, Compiled C/Wasm in V2).
All asynchronous operations (disk I/O, IndexedDB transactions, OPFS sync handles, microtask scheduling, and user Promise resolution) remain exclusively in the Host Layer. The Engine Core is a pure, synchronous, deterministic byte-manipulation state machine that accepts raw memory offsets, loops over binary bytecode, and returns numeric status codes.
2. Component Responsibility Matrix
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ HOST LAYER (JavaScript / TypeScript) │
│ │
│ [Fluent Query Builder] ──► [Binary Bytecode Compiler] ──► [Async FIFO Query Queue] │
│ │ │ │
│ ▼ ▼ │
│ [Schema Catalog Manager] [Single VmContext Lease] │
│ │ │ │
│ ▼ ▼ │
│ [VFS Adapter (OPFS/IDB)] ◄── [Cache Controller & LRU] ◄── [Transaction Coordinator] │
└─────────────────────────────────────────┬───────────────────────────────────────────────┘
│ Numeric FFI (vm_step(ctxOffset))
┌─────────────────────────────────────────▼───────────────────────────────────────────────┐
│ ENGINE CORE (V1: Strict C-Style JS / V2: C compiled to wasm32-nostdlib) │
│ │
│ [Bytecode VM Loop] ──► [Slotted Page Engine] ──► [B+Tree Traversal Engine] │
│ │ │
│ ├──► [Transient Query Arena (Hash Tables / Sorters)] │
│ └──► [Output Result Marshaller (Binary Record Packing)] │
└─────────────────────────────────────────────────────────────────────────────────────────┘2.1 Detailed Component Breakdown
| Component Name | Layer | V1 Implementation | V2 Implementation | Invariants & Responsibilities |
|---|---|---|---|---|
| Fluent Query Builder | Host | TypeScript | TypeScript | Validates table/column names; builds query AST; enforces type constraints before bytecode emission. |
| Binary Bytecode Compiler | Host | TypeScript | TypeScript | Translates query AST into flat Uint8Array bytecode; resolves column names to numeric indices; emits jump labels. |
| Async FIFO Query Queue | Host | TypeScript | TypeScript | Strictly serializes execution through the single active VmContext. Manages user Promise resolution. |
| Transaction Coordinator | Host | TypeScript | TypeScript | Enforces Exclusive Transaction Lease; manages BEGIN, COMMIT, ROLLBACK; writes WAL commit markers. |
| VFS Orchestrator | Host | TypeScript | TypeScript | Drives block I/O against OPFS (FileSystemSyncAccessHandle) or IndexedDB Object Stores via IVfsAdapter. |
| Cache Controller & LRU | Host | TypeScript | TypeScript | Tracks resident Page IDs in cache slots; enforces Pinning Invariant; coordinates WAL eviction flushes. |
| Result Hydrator | Host | TypeScript | TypeScript | Deserializes binary row records from the Output Result Buffer into JavaScript objects (Record<string, any>). |
| VM Execution Loop | Core | C-Style JS | C / Wasm | Synchronous while loop running switch (opcode). Manipulates ArrayBuffer directly without dynamic allocations. |
| Slotted Page Engine | Core | C-Style JS | C / Wasm | Reads/writes 4KB pages; slot directory pointer arithmetic; dynamic null-bitmap checking; 2048B limit enforcement. |
| B+Tree Traverser | Core | C-Style JS | C / Wasm | Iterative tree search using cursors[16] stack; searches sorted keys; advances across leaf sibling pointers. |
| Result Marshaller | Core | C-Style JS | C / Wasm | Copies filtered rows into Output Result Buffer; yields STATUS_BUFFER_FULL when 64KB capacity is reached. |
3. Strict FFI Interface Specification (Host Engine Core)
To guarantee that V1 (JS) and V2 (Wasm) are 100% interchangeable without modifying a single line of Host JS code, all engine entry points accept and return only primitive numbers:
typescript
// Core Engine Exported Signatures
interface WebDbCoreEngine {
/**
* Initializes the engine memory offsets and cache geometry.
* @param cacheOffset Byte offset where 4KB cache slots begin (0x000000)
* @param slotCount Total number of 4KB slots (e.g. 1024)
* @param scratchOffset Byte offset for scratchpad and VmContext (0x401080)
*/
vm_init(cacheOffset: number, slotCount: number, scratchOffset: number): void;
/**
* Executes bytecode instructions until completion, yield, or error.
* @param ctxOffset Byte offset of the active VmContext struct
* @returns VmStatus code (0=RUNNING, 1=DONE, 2=PAGE_FAULT, 3=BUFFER_FULL, 4=ERROR)
*/
vm_step(ctxOffset: number): number;
/**
* Compacts and defragments a slotted page in-place.
* @param pageSlotOffset Byte offset of the 4KB page slot in memory
* @returns 0 on success, or error status code
*/
page_defrag(pageSlotOffset: number): number;
}4. Explicit V1 Query Scope & Limitations
4.1 Fully Supported Scope in V1
- Connection & Configuration:
WebDB.open({ name, storage: 'opfs' | 'idb' | 'auto', cacheSize: '2MB' | '4MB' | '8MB' }).
- Schema DDL:
createTable(name, columns)(up to 10 tables, up to 16 columns per table in Page 1 catalog; supportsint32,int64,float64,text,blob,uuid, andulid).dropTable(name).createIndex(tableName, columnName).
- Data Mutation (DML):
insert(tableName, row).update(tableName, values).where(...).delete(tableName).where(...).
- Query Operators:
- Projections & Aggregations:
select([...columns])with aggregate functions (count(),count(col),sum(col),avg(col),min(col),max(col)). - Comparisons:
=,!=,>,>=,<,<=. - SQLite Null Checks:
whereNull(col),whereNotNull(col). - Grouping & Aggregation:
groupBy(col | cols[])(up to 8 columns max) andhaving(...). - Pagination:
limit(n),offset(n). - Sorting:
orderBy(col, 'asc' | 'desc')or multi-columnorderBy([{ column, direction?, nulls? }, ...])(max 8 columns, SQLite null collation).
- Projections & Aggregations:
- Transactions:
await db.transaction(async (tx) => { ... })with atomic auto-rollback on error.
- Extensibility & Diagnostics:
- UDF Registration:
db.registerFunction(name, fn). - Inspection:
query.explain()(high-level plan + VDBE disassembly).
- UDF Registration:
4.2 Explicitly Deferred Features (Scheduled for V1.1+)
- 3+ table joins,
FULL OUTER JOIN, andRIGHT JOIN(only single-table queries and simple 2-table inner/left joins supported in V1; see limitations.md §4.4–4.6). - Subqueries (uncorrelated scalar,
IN,EXISTS, correlated subqueries) and window functions (OVER (PARTITION BY ...)) (deferred to V1.1+; see limitations.md §4.5–4.6). - Dynamic
ALTER TABLEschema mutations (tables must be recreated in V1). - Composite multi-column secondary indexes (single-column secondary indexes only in V1).
5. Exhaustive Edge Cases & Failure Modes
A. Identifier & Schema Validation
- [ ] Case-Insensitive Identifiers: Table and column names must resolve case-insensitively (e.g.
users,USERS,Usersresolve to the same table ID). - [ ] Identifier Length Clamping: Table and column names exceeding 15 ASCII characters must be rejected with
IdentifierTooLongError. - [ ] Duplicate Table / Column Names: Creating a table with duplicate column names or creating an existing table without
ifNotExistsmust throwTableAlreadyExistsError.
B. Serialization & Constraint Violations
- [ ] Missing Table Handling: Executing a query or insert on a non-existent table must throw
TableNotFoundError. - [ ] Type Coercion & Range Safety: Passing a floating-point number into an
INT32column must truncate cleanly to 32-bit signed integer or throwInvalidDataTypeErroron overflow. - [ ]
NOT NULLConstraint Guard: Any attempt to set aNOT NULLcolumn tonullorundefinedmust throwNotNullConstraintErrorimmediately before writing dirty bytes. - [ ] Order By Column Ceiling: Querying with
sort columns must throw TooManyOrderByColumnsErrorat compile time. - [ ] Group By Column Ceiling: Querying with
grouping columns must throw TooManyGroupByColumnsErrorat compile time.
C. Queue & Concurrency Fail-Fasts
- [ ] Exclusive Transaction Lease Starvation: Non-transaction queries enqueued during an active
db.transaction()must wait in FIFO order without timing out or throwing lock conflicts. - [ ] Abandoned Transaction Timeout: If user transaction code hangs on an unresolved network
Promiseinsidedb.transaction(), the JS Host must timeout after 30 seconds, automatically triggerROLLBACK, release the lease, and unblock the queue.
6. Verification & Test Suite (tests/components_scope.test.ts)
- Schema DDL & Casing: Create
MyTable; assert queries againstmytablesucceed. - Identifier Limits: Assert table names of 16+ characters throw
IdentifierTooLongError. - Queue Serialization: Dispatch 100 concurrent
Promise.allread/write queries; assert zero race conditions and 100% deterministic results. - Transaction Lease Isolation: Dispatch a write query outside a transaction while a transaction is sleeping; assert write query executes strictly after
COMMIT.