A complete ECMAScript 2024 (ES15) JavaScript engine implemented from scratch in pure Go, with zero CGO dependencies.
| Language | Go 1.21+ |
| Lines of Code | ~35,000 |
| Files | 38 Go files |
| ECMAScript Target | ES2024 (ES15) |
| Architecture | Recursive descent parser + Tree-walk interpreter |
| GC | Go runtime GC (with WeakRef/WeakMap soft emulation) |
| JIT | None (interpreted) |
Source Code → Lexer → Parser → AST → Interpreter → Result
↓
+------------------+
| Runtime System |
| - Value types |
| - Objects |
| - Environments |
| - Realm |
+------------------+
↓
+------------------+
| Built-in Objects |
| Object/Array/... |
| Promise/Symbol |
| Temporal/Atomics |
+------------------+
| Package | Files | Lines | Description |
|---|---|---|---|
token |
1 | 377 | Token types and keywords for ES2024 |
ast |
1 | 830 | 63 AST node types, 5 interfaces |
lexer |
2 | 2,236 | Lexical analyzer + comprehensive tests |
parser |
1 | ~4,000 | Recursive descent parser (110+ methods) |
runtime |
5 | 2,718 | Value system, Objects, Environments, References, Realms |
specutils |
1 | 1,535 | 59 ECMA-262 abstract operations |
interpreter |
1 | 3,241 | Tree-walk execution engine |
builtin |
13 | 8,208 | All built-in objects (Object, Array, String, ..., console) |
promise |
2 | 2,260 | Promise + async/await + microtask queue |
symbol |
1 | 521 | Symbol + all 13 well-known symbols |
proxy |
1 | 1,060 | Proxy with all 13 traps + revocable |
reflect |
1 | 535 | Reflect API (13 methods) |
module |
1 | 1,149 | ES Module system with loader |
temporal |
1 | 2,249 | Temporal API (9 types, 144 methods) |
atomics |
1 | 716 | Atomics API (13 operations, waitAsync) |
internal |
4 | 3,070 | Generators, WeakRefs, ArrayBuffer, Iterator Helpers |
- All data types (undefined, null, boolean, string, symbol, number, bigint, object)
- All operators (arithmetic, bitwise, logical, comparison, instanceof, in)
- All statements (if/else, switch, for, while, do-while, try/catch/finally, with)
- Functions (declarations, expressions, arrow functions)
- Objects (literals, property access, prototype chain)
- Arrays and array methods
- Strings and string methods
- Regular expressions (all flags including ES2024
/v) - Strict mode
- Automatic semicolon insertion (ASI)
- let / const (block scoping)
- Classes (declaration, expression, static, extends, super)
- Template literals and tagged templates
- Destructuring (array, object, nested, with defaults)
- Default parameters
- Rest parameters
- Spread operator
- for...of loops
- Generators (function* / yield)
- Symbols and well-known symbols
- Proxy objects
- Reflect API
- Modules (import / export)
- Exponentiation operator (**)
- Array.prototype.includes()
- Async/await
- Object.entries(), Object.values(), Object.fromEntries()
- String padding (padStart/padEnd)
- Object.getOwnPropertyDescriptors()
- Trailing commas in function params
- Async iteration (for await...of)
- Promise.finally()
- Rest/Spread properties
- BigInt
- Optional catch binding
- Object.fromEntries()
- String.prototype.trimStart/trimEnd()
- Array.prototype.flat/flatMap()
- Object.fromEntries()
- Optional chaining (?.)
- Nullish coalescing (??)
- Logical assignment (&&=, ||=, ??=)
- Numeric separators (1_000_000)
- Promise.any() + AggregateError
- String.prototype.replaceAll()
- Array.prototype.at()
- Class fields and private methods
- Class static block
- Top-level await
- Error cause option
- Array.prototype.findLast/findLastIndex()
- Array.prototype.toReversed/toSorted/toSpliced/with()
- Object.groupBy() / Map.groupBy()
- Array.prototype.groupBy() (toSorted/toReversed/toSpliced family)
- Promise.withResolvers()
- String.prototype.isWellFormed() / toWellFormed()
- RegExp
/vflag (unicodeSets) - Temporal API (PlainDate, PlainTime, PlainDateTime, ZonedDateTime, Instant, Duration, PlainYearMonth, PlainMonthDay)
- Atomics.waitAsync()
- Resizable ArrayBuffer
- ArrayBuffer.transfer()
- Iterator helpers (map, filter, take, drop, flatMap, reduce, toArray, etc.)
# Evaluate an expression
go run main.go -e "1 + 2"
# Run a script file
go run main.go script.js
# Interactive REPL
go run main.go -ipackage main
import (
"fmt"
"github.com/gorjs/engine/interpreter"
"github.com/gorjs/engine/lexer"
"github.com/gorjs/engine/parser"
)
func main() {
source := `let x = [1, 2, 3]; x.map(n => n * 2);`
l := lexer.New(source)
p := parser.New(l)
program := p.ParseProgram()
interp := interpreter.New()
result, err := interp.Eval(program)
if err != nil {
panic(err)
}
fmt.Println(result.ToString()) // [2, 4, 6]
}- Value system: 8 ECMAScript types with proper coercion rules
- Object model: Full internal method protocol (OrdinaryGet, OrdinarySet, etc.)
- Property descriptors: Data and accessor properties with configurable/writable/enumerable flags
- Environment records: Declarative, Object, Global, and Function environment records
- Reference type: Spec-compliant reference resolution
- Completion records: Normal/Break/Continue/Return/Throw for control flow
- Prototype chain: Correct Object.prototype → null chain for all built-ins
- 16 constructors (Object, Function, Array, String, Number, Boolean, Date, RegExp, Error + 7 error subtypes, AggregateError)
- 3 global objects (Math, JSON, console)
- 225+ prototype methods
- All Symbol well-known methods (iterator, asyncIterator, hasInstance, toPrimitive, etc.)
- Full Promise/A+ compliance
- Promise Resolution Procedure with thenable support
- All combinators: all, allSettled, any, race, withResolvers
- Async/await with microtask queue
- Performance: Tree-walk interpreter, no JIT. Slower than V8/SpiderMonkey by design.
- WeakRef: True weak references require Go GC integration. Currently map-based with documented limitation.
- TypedArrays: Not yet implemented (ArrayBuffer is available as foundation).
- Intl API: Internationalization API not implemented.
- DOM/Window: No browser APIs (fetch, setTimeout, etc.) — pure language engine.
- Debugger: No debugging protocol support.
Commits: 4
Go files: 38
Total lines: ~35,000
Packages: 16
AST node types: 63
Parser methods: 110+
Spec abstract operations: 59
Built-in methods: 225+
Well-known symbols: 13
Proxy traps: 13
Promise combinators: 7
Temporal types: 9
MIT