Lexing turns JavaScript source into tokens, removing whitespace and comments and converting string and number syntax into values. Parsing organizes those tokens into an abstract syntax tree, with nodes for functions, calls, identifiers, and literals. Pietruszewski notes that JavaScript syntax can be ambiguous, so parsing uses context to distinguish cases such as division and regular expressions.
Hermes Hacking: Demystifying JavaScript Engines
Speaker
Radek Pietruszewski, CTO of Nozbe and author of open-source React Native libraries, explains JavaScript engines and Hermes at React Native EU 2023.
An AST interpreter evaluates each node, working through expressions such as `1 + 2 * 3` and looking up variables in an execution context. A practical interpreter also needs to handle function declarations, hoisting, nested scopes, and the call stack. Pietruszewski uses `const a = 1` followed by `console.log(a + 2)` to show how declarations and calls are evaluated.
A bytecode interpreter first compiles the AST into a flat sequence of simple instructions, then executes them on a virtual machine with registers and locals. Pietruszewski says this layout can improve performance because execution follows a compact instruction buffer instead of jumping among AST objects in memory. Hermes also uses an intermediate representation, applies optimization passes, and generates bytecode ahead of execution.
Pietruszewski describes mark-and-sweep collection: the engine follows references from roots such as globals, event handlers, and stack locals, then frees objects it cannot reach. Collection may pause execution, so the hard engineering problem is reducing pauses and doing more work concurrently. He points to Hermes documentation and a WebKit post by Filip Pizło for deeper reading.
Takeaways
- A basic understanding of engines does not require a compiler background; tracing tokens, AST nodes, and execution makes the stages approachable.
- AST interpretation is intuitive, while bytecode turns execution into a flat sequence of instructions that can be optimized.
- JavaScript parsing needs grammar context to resolve ambiguous syntax such as division versus regular expressions.
- Garbage collection keeps reachable objects alive and reclaims unreachable ones; pause time and concurrency are the main performance challenges.
Mentioned in this talk
Search inside this talk
What was claimed 10
- role atRadek Pietruszewski is CTO at Nozbe
“I'm a technical director at Nozbe”
0:05inSuccessful Web & React Native Code Sharing StrategiesYouTube Verified2 sources· Talk
- builtRadek Pietruszewski built Zacs
“and Zacs”
YouTube Unverified1 source· Talk
- built
“I'm also the author of open-source React Native libraries like WatermelonDB”
YouTube Unverified1 source· Talk
- uses
Hermes Agent uses bytecode
“Bytecode is the sort of modern approach to writing interpreters, and this is how Hermes works.”
YouTube Unverified1 source· Talk
- builtAndreas Kling built JS Lib
“his JavaScript interpreter, JS Lib”
YouTube Unverified1 source· Talk
- feature
Hermes Agent: Lexing, parsing, IR generation, optimization, and bytecode generation happen ahead of time
“In Hermes, all of these steps except execution happen ahead of time.”
YouTube Unverified1 source· Talk
- feature
Hermes Agent: Optimization passes on the intermediate representation before bytecode generation
“Then there are multiple optimization passes on the IR”
YouTube Unverified1 source· Talk
- uses
“Instead, we generate something called an intermediate representation”
YouTube Unverified1 source· Talk
- built
“posts on the WebKit blog by Filip Pizło, such as this one: “Retreating Wavefront Concurrent Garbage Collector.””
YouTube Unverified1 source· Talk
- feature
Hermes Agent: Two garbage collectors, one simple and one more complicated
“Hermes has two different garbage collectors, a simple one and a slightly more complicated one.”
YouTube Unverified1 source· Talk





