Building a JS Engine -- For Fun!

Spanish audio is available in the player settings
Rate this content
Bookmark

Modern production-grade JS engines can seem intimidating, but that's not all there is! This lightning talk draws from my past experiences working on hobbyist JS engines, and it will cover the following:


- Different angles to approach this seemingly complex task

- Things you can learn along the way

- Some existing projects that optimize for fun (instead of chasing benchmarks), and what makes them unique


You'll see that you don't need a background in compiler design to get started exploring JS engine internals. Most importantly, it's fun!

This talk has been presented at JSNation 2024, check out the latest edition of this JavaScript Conference.

FAQ

Test262 is a website that tracks the test results of various JavaScript engines, showing detailed implementation statuses and helping developers see their progress.

Linus works at Bloomberg on JavaScript infrastructure and has been building a JavaScript engine for fun over the last few years.

You can get involved with JavaScript standards by contributing to projects on GitHub and participating in the TC39 standards body, as Linus did by starting out as an invited expert.

When building a JavaScript engine, consider the scope (ES5, ES6, ES Next, custom extensions), the language you will use, and the specific features you want to implement.

You can find over 50,000 tests for JavaScript engines that are maintained alongside the specification. These tests ensure that your implementation handles all edge cases correctly.

ECMA-262 is the specification for JavaScript, providing pseudo code and guidelines for implementing JavaScript engines.

Popular JavaScript engines include Spidermonkey, V8, and JavaScriptCore from WebKit.

Yes, you can build your own JavaScript engine for fun, and you can choose from various languages such as C, C++, Go, Java, JavaScript, or even raw assembly.

Popular JavaScript engines are complex due to their performance optimizations, multiple tiers of just-in-time compilers, and integration with browsers.

Building a JavaScript engine helps you learn about parsers, interpreters, bytecode, JIT compilation, and optimizations. It also deepens your understanding of JavaScript and exposes you to standards and new features.

Linus Groh
Linus Groh
9 min
13 Jun, 2024

Comments

Sign in or register to post your comment.
Video Summary and Transcription
The Talk discusses the basics of building a JS engine, highlighting the complexity and feature completeness of existing engines. It emphasizes the possibility of creating a simpler engine tailored to specific use cases and target audiences. The speaker suggests starting anywhere in the process and provides tips on using parser libraries, implementing runtime features, and ensuring correctness through testing. Additionally, the Talk encourages exploring JavaScript standards and engaging with the open-source community.

1. JS Engine Building Basics

Short description:

I'm Linus, I work at Bloomberg on JavaScript infrastructure. Today, I want to talk about building a JS engine for fun. Spidermankey, V8, and JavaScript Core are mature JS engines that made JavaScript viable at scale. However, they are complex and feature complete, making it difficult to find something simpler to implement. Additionally, they are tied to product roadmaps and require extensive integration. We can make our own JS engine using different languages and choosing the scope based on our use case and target audience.

I'm Linus, I work at Bloomberg on JavaScript infrastructure, and I want to talk about something briefly which I've been doing for the last few years which is building a JS engine for fun. But first of all, let's take a step back. We all know these, right? So, Spidermankey, V8, and JavaScript Core from WebKit, and they are great. I'm not here to change your opinion on that. These are all very mature, highly optimised JS engines and they basically made JavaScript viable at scale, and made it as popular as it is today both on the client and server side. This is all good.

But, they are also very complex. This has a reason, which is largely performance, so they are not just simple interpreters, they have these several tiers of just-in-time compilers that create native code, and obviously, all exist in browsers, so they need a lot of integration with that, and that makes them pretty intimidating and not as easy to get into. They also largely feature complete, so, obviously, these have been around for at least a decade, V8 and the others even longer, so it can be pretty difficult to find something to actually implement that is not purely performance-related, or pretty complex. They are all very competitive, again, for a reason, none of these want to fall behind, everyone wants to stay at the forefront of performance and compliance, but, again, that kind of can take the fun out of it a little bit. Lastly, they're tied to product roadmaps, at least in some sense, as they again exist in browsers and can't just do their own thing but have to follow along with everything else around it, which is more than just JavaScript.

And now you can just show up and participate, but that is more or less the exception rather than the norm. Most people who work on these are employed at Google, or Apple, or Mozilla, and do this as a full-time job. But we can make our own, for fun, to change that, and just see how that works. First of all, you need to pick a language to implement a language. Traditionally, that is C or C++ which gives you good speed by default and a lot of control over memory and allocations and all that. Now that can be pretty scary to some people. Obviously, these languages are not known to be safe, have a lot of issues that we can't really fix because of history. But the good thing is you don't have to use C or C++. There is a long list of languages here. I found at least one implementation in all of these, there might be even more, but you know, it could be whatever, Go, Java, JavaScript, any of these. Just pick whatever you want. You can even write one in raw86 assembly if that's your thing. You choose. Then, next up, you have to kind of pick a scope. Could be very simple, just ES5, transpiler still exists. You can use all the new features and compile them down, or anything in between, like ES6, mix it up, use the newer features, or you decide to target the latest and greatest, commonly known as ES Next, or you could implement custom extensions, for example, the quick JS engine, they have something like use strict, called use math, and that gives you some non-standard extensions. All of this kind of depends a bit on what your use case and your target audience is. Obviously, a browser needs more support for various features than just a simple implementation that serves as a plugin, for example, in a game engine. And there's also certain parts of the language that are commonly referred to as Annex B, which is just what they call it in the spec.

.

2. Building a JS Engine

Short description:

You can start anywhere in building a JS engine. Use standalone parser libraries or create your own AST. Choose what to implement in the run-time side. Follow the ECMA 262 specification and run tests to ensure correctness and handle edge cases. Access 50,000 maintained tests at test262.fyi. Gain a better understanding of JavaScript and interact with standards contributors on GitHub. Explore fun projects that build JS engines.

It kind of only exists for legacy reasons, and, if they could delete it, they totally would, but, you know, history.

Again, you choose. Then, next up, you type git init, and you're kind of a bit lost where to even start. You might look at it using the script life cycle, so, like, first you pass the script. Obviously, you need to start with the parser, and then you need something that runs your script, and then you build the run time at the end. That's not really true.

You can basically start anywhere. Thanks to a lot of JS tooling, like formatters and linters, we have standalone parser libraries that you can just take, and then you get a quick start, or you just write your AST from hand in the beginning. That's something we did in the engine I worked on. And then later on, you can add the parser, and you already have something after that implemented, and it all fits together nicely. On the run-time side, again, that is huge, at least if you choose to implement all of it, so just pick whatever you want. It could be the classic string number, boolean prototype, or something more exciting like type arrays, or proxies, just start wherever you want. That is fine.

Then, obviously, you need to have a specification, known as ECMA 262. It's very complete, which is great. Nowadays, not a lot is unspecified. It largely looks like this, so you get a pseudo code that you can roughly translate into your own code. That might not seem like a whole lot of fun, but you still get to do a bunch of custom stuff like optimizations. This is really just focusing on the correctness and behavior. Then you need some tests, obviously. After you've implemented some stuff, you need to make sure it works correctly, handles all the edge cases.

Great news, you get 50,000 tests for free which are maintained next to the specification, so it's an actual official thing. It's a requirement nowadays for everything that goes into the language that it has new tests added to the test suite. Many new features are known to be fully tested. There's this wonderful website called test262.fyi that tracks the results of all the engines out there, and updates them every day, so you can see very detailed which engine implements which thing how well. I find personally that having a graph that shows you it goes up over time is very good for motivation.

More generally, you can obviously learn a huge amount of stuff if you do this. Things about how parsers work, interpreters, if you do bytecode engine code generation, if you want to do a JIT even, some native code, certain optimizations. For me, a huge thing was a better understanding of JavaScript itself, so, like, once you implement it, you really, really understand how things work under the hood. A few low-level concepts, and then one of my favorites is you get exposed to standards, so these new features don't appear out of nowhere, and you kind of get to interact with the people who add new things to JavaScript, and you can even get involved. It's all on GitHub.

Now, I do this. I'm a delegate for Bloomberg, but I started out as an invited expert in TC39, just like the standards body, and they reached out one day and thought, like, this is cool what you work on, do you want to get involved? And then lastly, here's a list of a few projects that you should definitely check out if this sounds interesting to you. These all do this for fun, like they don't aim to compete with V8, and all these big engines, they just do it for fun, so there's a few of them. Definitely check that out.

And that is that. If you have any questions, please find me afterwards or online. Thanks.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

A Guide to React Rendering Behavior
React Advanced 2022React Advanced 2022
25 min
A Guide to React Rendering Behavior
Top Content
This transcription provides a brief guide to React rendering behavior. It explains the process of rendering, comparing new and old elements, and the importance of pure rendering without side effects. It also covers topics such as batching and double rendering, optimizing rendering and using context and Redux in React. Overall, it offers valuable insights for developers looking to understand and optimize React rendering.
Scaling Up with Remix and Micro Frontends
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
This talk discusses the usage of Microfrontends in Remix and introduces the Tiny Frontend library. Kazoo, a used car buying platform, follows a domain-driven design approach and encountered issues with granular slicing. Tiny Frontend aims to solve the slicing problem and promotes type safety and compatibility of shared dependencies. The speaker demonstrates how Tiny Frontend works with server-side rendering and how Remix can consume and update components without redeploying the app. The talk also explores the usage of micro frontends and the future support for Webpack Module Federation in Remix.
React Concurrency, Explained
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
Watch video: React Concurrency, Explained
React 18's concurrent rendering, specifically the useTransition hook, optimizes app performance by allowing non-urgent updates to be processed without freezing the UI. However, there are drawbacks such as longer processing time for non-urgent updates and increased CPU usage. The useTransition hook works similarly to throttling or bouncing, making it useful for addressing performance issues caused by multiple small components. Libraries like React Query may require the use of alternative APIs to handle urgent and non-urgent updates effectively.
Full Stack Components
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
RemixConf EU discussed full stack components and their benefits, such as marrying the backend and UI in the same file. The talk demonstrated the implementation of a combo box with search functionality using Remix and the Downshift library. It also highlighted the ease of creating resource routes in Remix and the importance of code organization and maintainability in full stack components. The speaker expressed gratitude towards the audience and discussed the future of Remix, including its acquisition by Shopify and the potential for collaboration with Hydrogen.
Debugging JS
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
Watch video: Debugging JS
Debugging JavaScript is a crucial skill that is often overlooked in the industry. It is important to understand the problem, reproduce the issue, and identify the root cause. Having a variety of debugging tools and techniques, such as console methods and graphical debuggers, is beneficial. Replay is a time-traveling debugger for JavaScript that allows users to record and inspect bugs. It works with Redux, plain React, and even minified code with the help of source maps.
Making JavaScript on WebAssembly Fast
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
WebAssembly enables optimizing JavaScript performance for different environments by deploying the JavaScript engine as a portable WebAssembly module. By making JavaScript on WebAssembly fast, instances can be created for each request, reducing latency and security risks. Initialization and runtime phases can be improved with tools like Wiser and snapshotting, resulting in faster startup times. Optimizing JavaScript performance in WebAssembly can be achieved through techniques like ahead-of-time compilation and inline caching. WebAssembly usage is growing outside the web, offering benefits like isolation and portability. Build sizes and snapshotting in WebAssembly depend on the application, and more information can be found on the Mozilla Hacks website and Bike Reliance site.

Workshops on related topic

React Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
Master JavaScript Patterns
JSNation 2024JSNation 2024
145 min
Master JavaScript Patterns
Top Content
Featured Workshop
Adrian Hajdin
Adrian Hajdin
During this workshop, participants will review the essential JavaScript patterns that every developer should know. Through hands-on exercises, real-world examples, and interactive discussions, attendees will deepen their understanding of best practices for organizing code, solving common challenges, and designing scalable architectures. By the end of the workshop, participants will gain newfound confidence in their ability to write high-quality JavaScript code that stands the test of time.
Points Covered:
1. Introduction to JavaScript Patterns2. Foundational Patterns3. Object Creation Patterns4. Behavioral Patterns5. Architectural Patterns6. Hands-On Exercises and Case Studies
How It Will Help Developers:
- Gain a deep understanding of JavaScript patterns and their applications in real-world scenarios- Learn best practices for organizing code, solving common challenges, and designing scalable architectures- Enhance problem-solving skills and code readability- Improve collaboration and communication within development teams- Accelerate career growth and opportunities for advancement in the software industry
Integrating LangChain with JavaScript for Web Developers
React Summit 2024React Summit 2024
92 min
Integrating LangChain with JavaScript for Web Developers
Featured Workshop
Vivek Nayyar
Vivek Nayyar
Dive into the world of AI with our interactive workshop designed specifically for web developers. "Hands-On AI: Integrating LangChain with JavaScript for Web Developers" offers a unique opportunity to bridge the gap between AI and web development. Despite the prominence of Python in AI development, the vast potential of JavaScript remains largely untapped. This workshop aims to change that.Throughout this hands-on session, participants will learn how to leverage LangChain—a tool designed to make large language models more accessible and useful—to build dynamic AI agents directly within JavaScript environments. This approach opens up new possibilities for enhancing web applications with intelligent features, from automated customer support to content generation and beyond.We'll start with the basics of LangChain and AI models, ensuring a solid foundation even for those new to AI. From there, we'll dive into practical exercises that demonstrate how to integrate these technologies into real-world JavaScript projects. Participants will work through examples, facing and overcoming the challenges of making AI work seamlessly on the web.This workshop is more than just a learning experience; it's a chance to be at the forefront of an emerging field. By the end, attendees will not only have gained valuable skills but also created AI-enhanced features they can take back to their projects or workplaces.Whether you're a seasoned web developer curious about AI or looking to expand your skillset into new and exciting areas, "Hands-On AI: Integrating LangChain with JavaScript for Web Developers" is your gateway to the future of web development. Join us to unlock the potential of AI in your web projects, making them smarter, more interactive, and more engaging for users.
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
WorkshopFree
Hussien Khayoon
Kahvi Patel
2 authors
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
Testing Web Applications Using Cypress
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
WorkshopFree
Gleb Bahmutov
Gleb Bahmutov
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.