Memory leak regression testing with V8/Node.js, part 2 - finalizer-based testing

In the previous blog post, I talked about how Node.js used memory usage measurement to test against memory leaks. Sometimes that’s good enough to provide valid tests. Sometimes we want the test to be more precises and focus on the status of specific objects. This can be quite tricky with what’s available to interact with V8’s garbage collector.

Read More

Memory leak regression testing with V8/Node.js, part 1 - memory usage-based testing

Like many other relatively big piece of software, Node.js is no stranger to memory leaks, and with them, fixes and regression tests. Testing against memory leak regressions, however, can be particularly tricky in a runtime with a garbage-collected heap, and quite a few of these tests became source of flakes in the Node.js CI. In the past few months, I’ve been doing some work to improve the reliability of these tests. I’ve also come across a few bug reports in the Node.js issue tracker memory leaks that turn out to be false alarms because the reproductions made incorrect assumptions. Here are my notes about the testing strategies Node.js uses against memory leak regression, my observations about them, and why I added a new testing strategy with a new V8 API. Hopefully this can help the readers write less unreliable memory regression tests/memory leak reproductions.

Read More

Fixing Node.js vm APIs, part 4 - hitting the compilation cache again

In the last post I wrote about how I finally managed to fix the memory problems in the vm APIs, and it turned out that there was another issue blocking users from upgrading away from the End-of-Life Node.js v16 - vm.Script compilation could be ~100x slower in v16 in some cases. In this post, let’s look at what was causing the performance regression, and the fix/workaround developed for it.

Read More

Fixing Node.js vm APIs, part 3 - verifying the fixes

In the last post I wrote about how a new memory management model in Node.js vm APIs was designed to fix the long-standing leaks and use-after-free issues, and we finally put together a PR that the Node.js core CI and CITGM CI were happy with. The road to landing it and releasing it to LTS still turned out to be bumpy, however.

Read More

Fixing Node.js vm APIs, part 2 - reworking the memory management

In the last post, I wrote about how I came to work on a memory leak in the vm compilation APIs in Node.js, attempted a fix, and reverted it because the fix turned out to be unsound and introduced a use-after-free. In this post I will write about how I got to another fix that ended up working.

Read More

Fixing Node.js vm APIs, part 1 - memory leaks and segmentation faults

This year I spent some time fixing a few long-standing issues in the Node.js vm APIs that had been blocking users from upgrading away from Node.js v16 (End-of-Life). It had been an interesting journey, so I decided to write a few blog posts about it. Hopefully they can be helpful for posterity.

Read More

Fixing snapshot support of class fields in V8

Up until V8 10.0, the class field initializers had been broken in the V8 startup snapshot - a feature used by embedders like Node.js and Deno to speed up the bootstrapping of themselves or user applications. This post is going to cover how the startup snapshot support was implemented, as part of the work our team did on the class features in V8. To learn about the optimizations we did for instance initialization with the new class features, checkout another post published in the V8 blog.

Read More

Building V8 on an M1 MacBook

Update: this blog post is now outdated. Since some time around 2022-2023 no more extra setup is required to build V8 on Apple ARM64 CPUs. This post is only preserved here for archeological purpose.

Read More

How does Node.js load its built-in/native modules?

This post stems from a recent Twitter conversation and a bug I was trying to fix. I’ve also seen some questions asked in the issue tracker about this from time to time. A lot of people are already aware that a substantial part of Node.js is implemented in JavaScript, and many naturally think that Node.js loads its builtins from separate JS files on disk when the process is launched (which is very intuitive, but not true unless you use a special build-time flag). So in this post I’ll try to explain how the whole thing comes together at the moment, hopefully it can be helpful to someone searching about it on the Internet or to code archeologists in the future.

Read More

Uncaught exceptions in Node.js

In this post, I’ll jot down some notes that I took when refactoring the uncaught exception handling routines in Node.js. Hopefully it could be useful for other people who are interested in this part of the code base, or for code archaeologists in the future.

Read More