Language
On this page 11
The parser is a hand-written recursive-descent + precedence-climbing parser
(src/parser.zig)
over a single-pass lexer. Semantics live in the tree-walking evaluator
(src/interpreter.zig),
with a bytecode VM for the constructs that need suspend/resume — see
Execution tiers.
Both strict mode and sloppy mode are implemented, including the Annex B web-compatibility semantics that the corpus scores.
Declarations and bindings
var,let,const, with a real Temporal Dead Zone.- Block, function, module,
catch, and per-iteration scoping.for (let …)heads create a fresh binding per iteration so body closures capture correctly. - Destructuring in declarations, assignments, and parameters — array and object patterns, defaults, nested patterns, rest elements, and object rest to a member target (which runs the setter).
- Global
var/functionbindings live both in the environment and as own properties of the global object; global lexical bindings live only in the environment. Redeclaration conflicts are reported as early errors.
Operators
The full operator set: arithmetic including **, bitwise and shifts, logical,
nullish coalescing ??, optional chaining ?., logical assignment
(&&=, ||=, ??=), comma, typeof / void / delete, in, instanceof
(honouring Symbol.hasInstance), and new.target.
Coercion follows the specified evaluation order — ToNumeric of the left
operand fully, including its Symbol rejection, before the right. String
relational comparison is by UTF-16 code unit, and BigInt comparison against
Number/String is exact rather than float-approximated.
Functions
- Function declarations and expressions, arrow functions, concise methods, getters and setters, and computed keys.
- Default, rest, and destructured parameters. A parameter list containing a default gets its own scope, distinct from the body's variable environment.
arguments— mapped for simple sloppy parameter lists, unmapped otherwise, withlengthbehaving as an ordinary configurable data property.- Closures,
thisbinding,new,super, and the%ThrowTypeError%poison pill on strictcaller/arguments. - Proper tail calls in strict code, via the VM's heap-allocated activation stack — recursion depth is bounded by the logical call-depth cap, not the native OS stack.
Classes
classdeclarations and expressions, inheritance,superin constructors, methods, and property accesses.- Instance and static public fields (created with
CreateDataPropertyOrThrow, not[[Set]]), private fields, methods, and accessors,#x in objbrand checks, andstatic {}initializer blocks. - The class name is bound inside its own body as a
const, in TDZ during heritage evaluation. - Field initializers and static blocks are
[[Call]]ed, sonew.targetisundefinedinside them — including inside a directeval, and lexically for an arrow defined there. - Each evaluation of a class produces distinct private names, so two instances from two evaluations do not share brands.
accessor xauto-accessor fields parse. Decorator lists parse and are discarded — decorator application is not implemented.
Generators, async, and iteration
- Generators, async functions, async generators, and
for await…of. yield,yield*,await, and top-levelawaitin modules.- Iterators close on abrupt completion — a throwing destructuring target or body
runs the iterator's
return. - Iterator helpers on
Iterator.prototype:map,filter,take,drop,flatMap,reduce,toArray,forEach,some,every,find, plusIterator.from, sequencing (concat,zip,zipKeyed), andSymbol.dispose.AsyncIteratoris present as the async counterpart.
These constructs always compile to the bytecode VM, because suspend/resume cannot be expressed by the tree-walker.
Control flow and errors
if/else, while, do…while, for, for…in, for…of, for await…of,
switch (with its own lexical scope), labelled statements, break/continue,
try/catch/finally with optional catch binding, throw, and with.
finally semantics are exact: a pending break/continue/return/throw from
the try is held aside while the finally block runs clean, and the block's own
abrupt completion overrides it.
The Error family is Error, TypeError, RangeError, ReferenceError,
SyntaxError, EvalError, URIError, AggregateError, SuppressedError, and
OutOfMemoryError.
Explicit resource management
using x = res; and await using x = res; are implemented, with
DisposeResources running at the end of blocks, switch bodies, for
statements, for…of iterations, and generator / async function / async
generator bodies — on both normal and abrupt completion. Initializer validation
(a resource whose Symbol.dispose / Symbol.asyncDispose is not callable)
throws at registration.
Modules
import/exportdeclarations, namespace imports, and re-exports.- Dynamic
import(), including its rejection paths, plus theimport.deferandimport.sourcephase forms. import.meta.- Top-level
await, with module-graph and async-module evaluation ordering scored by the corpus.
The engine does not resolve module specifiers itself.
Context.evaluateModule(entry_path, entry_source, host) takes a host hook so the
embedder owns resolution and loading — see Embedding.
eval and realms
Direct and indirect eval are implemented with the correct variable
environments: a sloppy direct eval's function-level var and function
declarations create deletable bindings, a direct eval in a parameter
default may not var-declare a parameter name, and a direct eval in a class
field initializer inherits that context's restrictions lexically.
$262.createRealm() is available to the conformance harness; well-known symbols
are shared across realms so symbol identity holds.
Regular expressions
RegExp is backed by the sibling zig-regex
package compiled with an ecmascript flag, so ECMAScript-only rules are
enforced (no standalone (?ims) modifiers, no quantified lookbehind, named
backreference resolution). RegExp.escape is available.
Where the paths differ
Nearly all code runs on the tree-walking evaluator. The bytecode VM runs generators, async functions, async generators, and the narrow set of plain functions that benefit from it. Because the corpus exercises the VM far less than the tree-walker, VM/tree-walker divergence is a known bug surface; see Execution tiers for the tiering rules and how divergence is hunted.