{"title":"Joyee Cheung's Blog","link":[{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/atom.xml","rel":"self"}},{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/"}}],"updated":"2026-03-26T16:20:20.104Z","id":"https:\/\/joyeecheung.github.io\/blog\/","author":{"name":"Joyee Cheung"},"generator":"Hexo","entry":[{"title":"Teaching gdb to Unwind V8 JIT Frames on x64","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2026\/03\/24\/teaching-gdb-to-unwind-v8-jit-frames-on-x64\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2026\/03\/24\/teaching-gdb-to-unwind-v8-jit-frames-on-x64\/","published":"2026-03-23T23:00:00.000Z","updated":"2026-03-26T16:20:20.104Z","summary":"<p>Recently I landed a <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/chromium-review.googlesource.com\/c\/v8\/v8\/+\/7543454\">custom Python gdb unwinder in V8<\/a> that allows gdb to unwind through V8\u2019s JIT-compiled frames on x64","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"debugger","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/debugger\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}}]},{"title":"Tinkering with Node.js Core on ARM64 Windows","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2026\/01\/31\/tinkering-with-nodejs-core-on-arm64-windows\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2026\/01\/31\/tinkering-with-nodejs-core-on-arm64-windows\/","published":"2026-01-31T09:50:00.000Z","updated":"2026-04-01T01:16:02.347Z","summary":"<p>A while back, I wrote about <a href=\"\/blog\/2025\/02\/16\/building-nodejs-on-windows-with-clang-cl\/\" title=\"Building Node.js on Windows using the new ClangCL support\">Building Node.js on Windows using the new ClangCL support<\/a>, which was done on an actual x64 Windows machine","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"Windows","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Windows\/"}}]},{"title":"Improving Single Executable Application Building for Node.js","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2026\/01\/26\/improving-single-executable-application-building-for-node-js\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2026\/01\/26\/improving-single-executable-application-building-for-node-js\/","published":"2026-01-26T11:00:00.000Z","updated":"2026-03-24T13:15:57.978Z","summary":"<p>Recently, I <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/nodejs\/node\/pull\/61167\">landed a change that moves the Single Executable Application (SEA) build process directly into Node.js core<\/a> - a hobby project I\u2019d been tinkering with for some time","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"require(esm) in Node.js: implementer's tales","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2025\/12\/30\/require-esm-in-node-js-implementers-tales\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2025\/12\/30\/require-esm-in-node-js-implementers-tales\/","published":"2025-12-30T09:30:00.000Z","updated":"2026-01-05T10:36:11.058Z","summary":"<p>In earlier posts, I wrote about <a href=\"\/blog\/2024\/03\/18\/require-esm-in-node-js\/\" title=\"reviving require(esm)\">reviving require(esm)<\/a> and <a href=\"\/blog\/2025\/12\/30\/require-esm-in-node-js-from-experiment-to-stability\/\" title=\"its iteration process\">its iteration process<\/a>","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"require(esm)","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/require-esm\/"}}]},{"title":"require(esm) in Node.js: from experiment to stability","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2025\/12\/30\/require-esm-in-node-js-from-experiment-to-stability\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2025\/12\/30\/require-esm-in-node-js-from-experiment-to-stability\/","published":"2025-12-30T09:00:00.000Z","updated":"2026-01-05T10:36:13.445Z","summary":"<p>More than a year ago, I set out to revive <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/nodejs.org\/docs\/latest-v25.x\/api\/modules.html#loading-ecmascript-modules-using-require\"><code>require(esm)<\/code> in Node.js<\/a> and <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"require(esm)","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/require-esm\/"}}]},{"title":"Building Node.js on Windows with clang-cl","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2025\/02\/16\/building-nodejs-on-windows-with-clang-cl\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2025\/02\/16\/building-nodejs-on-windows-with-clang-cl\/","published":"2025-02-15T23:21:27.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>Recently Node.js started to support building with clang-cl on Windows. I happened to have the chance to try it out this week and while it still needs some fixups in my case, it\u2019s mostly working very well now. Here are some notes about this","category":[{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"Windows","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Windows\/"}}]},{"title":"Executable loading and startup performance on macOS","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2025\/01\/11\/executable-loading-and-startup-performance-on-macos\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2025\/01\/11\/executable-loading-and-startup-performance-on-macos\/","published":"2025-01-11T12:30:42.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>Recently, I <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/nodejs\/node\/pull\/56275\">fixed a macOS-specific startup performance regression in Node.js<\/a> after an extensive investigation. Along the way, I learned a lot about tools for macOS and Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"macOS","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/macOS\/"}},{"@attributes":{"term":"performance","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/performance\/"}}]},{"title":"Reproducible Node.js built-in snapshots, part 3 - fixing V8 startup snapshot","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-3\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-3\/","published":"2024-09-28T08:44:09.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>In the previous posts we looked into how the Node.js executable was made a bit more reproducible after the Node.js snapshot data and the V8 code cache were made reproducible, and did a bit of anatomy on the unreproducible V8 snapshot blobs","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Reproducible Node.js built-in snapshots, part 2 - V8 code cache and snapshot blobs","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-2\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-2\/","published":"2024-09-28T07:44:09.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>In <a href=\"\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-1\/\" title=\"the previous post\">the previous post<\/a>, we covered how the Node.js built-in snapshot is generated and embedded into the executable, and how I fixed the Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Reproducible Node.js built-in snapshots, part 1 - Overview and Node.js fixes","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-1\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/09\/28\/reproducible-nodejs-builtin-snapshots-1\/","published":"2024-09-28T06:44:09.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>In a recent effort to make the Node.js builds reproducible again (at least on Linux), a big remaining piece was the built-in snapshot. I wrote some notes about the journey of making the Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Things I learned from organizing a hybrid unconference","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/04\/21\/things-i-learned-from-organizing-a-hybrid-unconference\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/04\/21\/things-i-learned-from-organizing-a-hybrid-unconference\/","published":"2024-04-21T10:00:00.000Z","updated":"2025-06-14T14:38:21.422Z","summary":"<p>Recently, I co-organized a hybrid unconference - the <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/nodejs.org\/en\/about\/get-involved\/collab-summit\">Node.js collaboration summit<\/a> for <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/openjs-foundation\/summit\/issues\/387\">2024 H1<\/a>","category":[{"@attributes":{"term":"Organization","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Organization\/"}},{"@attributes":{"term":"Events","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Events\/"}}]},{"title":"require(esm) in Node.js","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/18\/require-esm-in-node-js\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/18\/require-esm-in-node-js\/","published":"2024-03-18T17:10:26.000Z","updated":"2025-12-30T18:58:11.237Z","summary":"<p>Recently I landed experimental <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/nodejs\/node\/pull\/51977\">support for <code>require()<\/code>-ing synchronous ES modules in Node.js<\/a>, a feature that has been long overdue","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}},{"@attributes":{"term":"require(esm)","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/require-esm\/"}}]},{"title":"Memory leak regression testing with V8\/Node.js, part 3 - heap iteration-based testing","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-3\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-3\/","published":"2024-03-17T17:48:11.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>In <a href=\"\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-2\/\" title=\"the previous blog post\">the previous blog post<\/a>, I described the heap snapshot trick as an \u201cabuse\u201d of the heap snapshot API, because heap snapshots are not designed to interact with the finalizers run in the heap","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Memory leak regression testing with V8\/Node.js, part 2 - finalizer-based testing","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-2\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-2\/","published":"2024-03-17T17:38:11.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>In <a href=\"\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-1\/\" title=\"the previous blog post\">the previous blog post<\/a>, I talked about how Node.js used memory usage measurement to test against memory leaks. Sometimes that\u2019s good enough to provide valid tests","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Memory leak regression testing with V8\/Node.js, part 1 - memory usage-based testing","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-1\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2024\/03\/17\/memory-leak-testing-v8-node-js-1\/","published":"2024-03-17T17:28:11.000Z","updated":"2025-06-14T14:38:21.421Z","summary":"<p>Like many other relatively big piece of software, Node.js is no stranger to memory leaks, and with them, fixes and regression tests","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Fixing Node.js vm APIs, part 4 - hitting the compilation cache again","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/31\/fixing-nodejs-vm-apis-4\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/31\/fixing-nodejs-vm-apis-4\/","published":"2023-12-31T20:28:11.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>In <a href=\"\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-3\/\" title=\"the last post\">the last post<\/a> I wrote about how I finally managed to fix the memory problems in the <code>vm<\/code> APIs, and it turned out that there was another issue blocking users from upgrading away from the End-of-Life Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Fixing Node.js vm APIs, part 3 - verifying the fixes","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-3\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-3\/","published":"2023-12-30T19:28:11.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>In <a href=\"\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-2\/\" title=\"the last post\">the last post<\/a> I wrote about how a new memory management model in Node.js <code>vm<\/code> APIs was designed to fix the long-standing leaks and use-after-free issues, and we finally put together a PR that the Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Fixing Node.js vm APIs, part 2 - reworking the memory management","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-2\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-2\/","published":"2023-12-30T18:28:11.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>In <a href=\"\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-1\/\" title=\"the last post\">the last post<\/a>, I wrote about how I came to work on a memory leak in the <code>vm<\/code> compilation APIs in Node","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Fixing Node.js vm APIs, part 1 - memory leaks and segmentation faults","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-1\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2023\/12\/30\/fixing-nodejs-vm-apis-1\/","published":"2023-12-30T17:28:11.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>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","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]},{"title":"Fixing snapshot support of class fields in V8","link":{"@attributes":{"href":"https:\/\/joyeecheung.github.io\/blog\/2022\/04\/14\/fixing-snapshot-support-of-class-fields-in-v8\/"}},"id":"https:\/\/joyeecheung.github.io\/blog\/2022\/04\/14\/fixing-snapshot-support-of-class-fields-in-v8\/","published":"2022-04-14T15:21:39.000Z","updated":"2025-06-14T14:38:21.420Z","summary":"<p>Up until V8 10.0, the class field initializers had been <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/twitter.com\/lcasdev\/status\/1398413245229195268\">broken<\/a> in <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/v8","category":[{"@attributes":{"term":"Tech","scheme":"https:\/\/joyeecheung.github.io\/blog\/categories\/Tech\/"}},{"@attributes":{"term":"V8","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/V8\/"}},{"@attributes":{"term":"Node.js","scheme":"https:\/\/joyeecheung.github.io\/blog\/tags\/Node-js\/"}}]}]}