Architecture overview
LibJS consists of several key subsystems working together:Lexer & Parser
Source code tokenization and AST generation
Bytecode compiler
AST to bytecode compilation and optimization
Virtual machine
Bytecode execution and runtime management
Garbage collector
Automatic memory management via LibGC
Core components
Lexer and tokenization
The lexer (Lexer.cpp, Lexer.h) breaks JavaScript source code into tokens:
- Keywords:
function,class,const, etc. - Identifiers: Variable and function names
- Literals: Strings, numbers, booleans, null, undefined
- Operators: Arithmetic, logical, bitwise, assignment
- Punctuation: Braces, brackets, semicolons
Parser and AST
The parser (Parser.cpp, Parser.h) transforms tokens into an Abstract Syntax Tree:
AST.h, AST.cpp) represents the syntactic structure:
- Statements:
if,while,for,return, etc. - Expressions: Function calls, binary operations, member access
- Declarations: Variables, functions, classes
- Modules: Import/export statements
The parser is over 200,000 lines and handles all ECMAScript syntax including modern features like async/await, destructuring, and optional chaining.
Bytecode compilation
LibJS compiles the AST to bytecode for efficient execution: Directory structure:- Operations: Load, store, arithmetic, jumps, calls
- Registers: Virtual registers for values
- Basic blocks: Control flow graph nodes
- Optimizations: Constant folding, dead code elimination
Virtual machine
The VM (Runtime/VM.h, Runtime/VM.cpp) manages JavaScript execution:
Execution contexts
Call stack, variable scopes, and this binding
Well-known symbols
Built-in symbols like Symbol.iterator
String caching
Optimization for frequently used strings
Module loading
ESM module resolution and execution
Runtime objects
TheRuntime/ directory contains all built-in JavaScript objects:
- Constructor: Creates instances (e.g.,
ArrayConstructor) - Prototype: Methods available on instances (e.g.,
ArrayPrototype) - Object: Internal representation (e.g.,
Array)
Garbage collection
LibJS uses LibGC for automatic memory management:- GC::Cell: Base class for all GC-managed objects
- GC::Ref<T>: Non-null reference to GC object
- GC::Ptr<T>: Nullable pointer to GC object
- Root vectors: Temporary roots for stack values
ECMAScript compliance
LibJS implements modern ECMAScript features:| Feature | Status | Files |
|---|---|---|
| ES6 Classes | ✓ | Runtime/ECMAScriptFunctionObject.cpp |
| Arrow functions | ✓ | AST.h, Parser.cpp |
| Destructuring | ✓ | Parser.cpp, AST.h |
| Template literals | ✓ | Lexer.cpp, Parser.cpp |
| Promises | ✓ | Runtime/Promise.cpp |
| async/await | ✓ | Bytecode/, AST.cpp |
| Modules (ESM) | ✓ | Module.cpp, SourceTextModule.cpp |
| Generators | ✓ | Runtime/GeneratorObject.cpp |
| Proxies | ✓ | Runtime/ProxyObject.cpp |
| Symbols | ✓ | Runtime/Symbol.cpp |
Completions and error handling
LibJS uses the “completion” system from the ECMAScript spec:- Normal values: Successful execution
- Exceptions: Thrown errors
- Control flow:
break,continue,return
The
TRY() macro automatically propagates throw completions, similar to Rust’s ? operator or exception handling in other languages.Module system
LibJS implements ECMAScript modules: Module types:- SourceTextModule: Regular JavaScript modules (
.js,.mjs) - SyntheticModule: Programmatically created modules
- CyclicModule: Base for modules with cyclic dependencies
- Parse: Tokenize and parse module source
- Link: Resolve imports and exports
- Evaluate: Execute module code
- Cache: Store for future imports
Console API
TheConsole class (Console.cpp, Console.h) implements the console API:
log(),info(),warn(),error()trace(),assert()time(),timeEnd(),timeLog()group(),groupEnd(),groupCollapsed()clear(),count(),countReset()
Scope analysis
The scope collector (ScopeCollector.cpp, ScopeCollector.h) analyzes variable scopes:
- Lexical scoping: Block-level scopes for
letandconst - Function scoping: Function-level scopes for
var - Closure analysis: Captures and closures
- Hoisting: Variable and function hoisting
Integration with LibWeb
LibJS is deeply integrated with LibWeb:- Realms: Each document has a JS realm
- Global objects:
window,document, etc. - Event handlers: JavaScript event callbacks
- Promises: For async web APIs
- WebIDL bindings: Generated glue code
Development tools
AST dumping
Pretty printing
Syntax highlighting
Rust integration
LibJS includes experimental Rust integration:The Rust integration allows certain components to be implemented in Rust while maintaining C++ compatibility.
Performance optimizations
LibJS includes several performance optimizations:- String interning: Reuse identical strings
- Inline caching: Cache property lookups
- Bytecode compilation: Faster than AST interpretation
- JIT preparation: Architecture supports future JIT compilation
Related components
LibWeb
Web rendering engine using LibJS
LibWasm
WebAssembly implementation
LibGC
Garbage collection infrastructure