V8 follows the Chromium release schedule. The support horizon for Chromium is different compared to the support horizon for Node.js. As a result, Node.js needs to support multiple versions of V8 longer than what upstream needs to support. V8 branches in Node.js lack of an official maintenance process due to a missing LTS supported branch.
This document attempts to outline the current maintenance processes, proposes a workflow for maintaining the V8 branches in both Node.js LTS and current releases, and discusses how the Node.js and V8 teams at Google can help.
V8 and Chromium follow a roughly 4-week release cadence. At any given time there are several V8 branches that are active, see the V8 release process. All older branches are abandoned and are not maintained by the V8 team.
The process for backporting bug fixes to active branches is officially documented on the V8 wiki. The summary of the process is:
At any given time Node.js needs to be maintaining a few different V8 branches for the various Current, LTS, and nightly releases. The versions of V8 used in Node.js may have already been abandoned by upstream V8. However, Node.js needs to continue supporting these branches for many months (Current branches) or several years (LTS branches).
Once a bug in Node.js has been identified to be caused by V8, the first step is to identify the versions of Node.js and V8 affected. The bug may be present in multiple different locations, each of which follows a slightly different process.
If the bug can be reproduced on the Node.js canary branch, Chromium canary, or V8 tip-of-tree, and the test case is valid, then the bug needs to be fixed upstream first.
If the bug exists in any of the active V8 branches, we may need to get the fix backported. At any given time, there are two active branches (beta and stable) in addition to master. The following steps are needed to backport the fix:
Abandoned V8 branches are supported in the Node.js repository. The fix needs to be cherry-picked in the Node.js repository and V8-CI must test the change.
As an example for how to backport changes, consider the bug RegExp show inconsistent result with other browsers. From the bug we can see that it was merged by V8 into 5.2 and 5.3, and not into V8 5.1 (since it was already abandoned). Since Node.js v6.x uses V8 5.1, the fix needed to be backported.
git-node (recommended)You can use git-node to help you backport patches. This removes some manual steps and is recommended.
Here are the steps for the bug mentioned above:
git-node by installing @node-core/utils.git-node-v8.git node v8 backport a51f429.git-node will wait for you to resolve them:$ git node v8 backport a51f429 ✔ Update local V8 clone ❯ V8 commit backport ✔ Get current V8 version ✔ Generate patches ❯ Apply and commit patches to deps/v8 ❯ Commit a51f429772d1 ⠏ Apply patch ◼ Increment embedder version number ◼ Commit patch ? Resolve merge conflicts and enter 'RESOLVED' ‣
Resolve conflicts, stage the files (you may need to open another terminal or use a GUI git client), then return to the terminal running git-node, type RESOLVED, and hit Enter.
$ git node v8 backport a51f429 ✔ Update local V8 clone ✔ V8 commit backport
See git-node-v8-backport for more documentation and additional options.
v8_embedder_string number in common.gypi.nodejs/node targeting the vY.x-staging branch and notify the @nodejs/v8 team.test-v8 target in the Makefile, which uses tools/make-v8.sh to reconstruct a git tree in the deps/v8 directory to run V8 tests.[^1]Here are the steps for the bug mentioned above:
Download and apply the commit linked-to in the issue (in this case a51f429):
curl -L https://github.com/v8/v8/commit/a51f429.patch | git am -3 --directory=deps/v8
If the branches have diverged significantly, this may not apply cleanly. It may help to try to cherry-pick the merge to the oldest branch that was done upstream in V8. In this example, this would be the patch from the merge to 5.2. The hope is that this would be closer to the V8 5.1, and has a better chance of applying cleanly.
Modify the commit message to match the format we use for V8 backports and replace yourself as the author. git commit --amend --reset-author. You may want to add extra description if necessary to indicate the impact of the fix on Node.js. In this case the original issue was descriptive enough. Example:
deps: cherry-pick a51f429 from V8 upstream Original commit message: [regexp] Fix case-insensitive matching for one-byte subjects. The bug occurs because we do not canonicalize character class ranges before adding case equivalents. While adding case equivalents, we abort early for one-byte subject strings, assuming that the ranges are sorted. Which they are not. R=marja@chromium.org BUG=v8:5199 Review-Url: https://codereview.chromium.org/2159683002 Cr-Commit-Position: refs/heads/master@{#37833} Refs: https://github.com/v8/v8/commit/a51f429772d1e796744244128c9feeab4c26a854 PR-URL: https://github.com/nodejs/node/pull/7833
v8_embedder_string number in common.gypi.v6.x-staging branch in the Node.js repository. Launch the normal and V8 CI using the Node.js CI system. We only needed to backport to v6.x as the other LTS branches weren't affected by this bug.For bugs found through the browser or other channels, the V8 team marks bugs that might be applicable to the abandoned branches in use by Node.js. This is done through manual tagging by the V8 team and through an automated process that tags any fix that gets backported to the stable branch (as it is likely candidate for backporting further).
Such fixes are tagged with the following labels in the V8 issue tracker:
NodeJS-Backport-Review (V8, Chromium): to be reviewed if this is applicable to abandoned branches in use by Node.js. This list if regularly reviewed by the Node.js team at Google to determine applicability to Node.js.NodeJS-Backport-Approved (V8, Chromium): marks bugs that are deemed relevant to Node.js and should be backported.NodeJS-Backport-Done (V8, Chromium): Backport for Node.js has been performed already.NodeJS-Backport-Rejected (V8, Chromium): Backport for Node.js is not desired.The backlog of issues with such is regularly reviewed by the node-team at Google to shepherd through the backport process. External contributors are welcome to collaborate on the backport process as well. Some of the bugs may be security issues and will not be visible to external collaborators.
Node.js keeps a vendored copy of V8 inside of the deps/ directory. In addition, Node.js may need to float patches that do not exist upstream. This means that some care may need to be taken to update the vendored copy of V8.
V8 builds against the version of ICU supplied by Node.js, see maintaining-icu.md for special considerations. Specifically, a V8 update may necessitate an ICU update.
Because there may be floating patches on the version of V8 in Node.js, it is safest to apply the patch level updates as a patch. For example, imagine that upstream V8 is at 5.0.71.47 and Node.js is at 5.0.71.32. It would be best to compute the diff between these tags on the V8 repository, and then apply that patch on the copy of V8 in Node.js. This should preserve the patches/backports that Node.js may be floating (or else cause a merge conflict).
git-node (recommended)git-node by installing @node-core/utils.git-node-v8.git node v8 minor to apply a minor update.See git-node-v8-minor for more documentation and additional options.
The rough outline of the process is:
# Assuming your fork of Node.js is checked out in $NODE_DIR # and you want to update the Node.js main branch. # Find the current (OLD) version in # $NODE_DIR/deps/v8/include/v8-version.h cd $NODE_DIR git checkout main git merge --ff-only origin/main git checkout -b V8_NEW_VERSION curl -L https://github.com/v8/v8/compare/${V8_OLD_VERSION}...${V8_NEW_VERSION}.patch | git apply --directory=deps/v8 # You may want to amend the commit message to describe the nature of the update
V8 also keeps tags of the form 5.4-lkgr which point to the Last Known Good Revision from the 5.4 branch that can be useful in the update process above.
We upgrade the version of V8 in Node.js main whenever a V8 release goes stable upstream, that is, whenever a new release of Chrome comes out.
Upgrading major versions would be much harder to do with the patch mechanism above. A better strategy is to
main branch and look at the patches that have been floated since the last major V8 update.v8_embedder_string variable to “-node.0” in common.gypi.To audit for floating patches:
git log --oneline deps/v8
To replace the copy of V8 in Node.js, use the git-node tool. For example, if you want to replace the copy of V8 in Node.js with the branch-head for V8 5.1 branch:
cd $NODE_DIR git node v8 major --branch=5.1-lkgr
This should be followed up with manual refloating of all relevant patches.
The fact that Node.js keeps a vendored, potentially edited copy of V8 in deps/ makes the above processes a bit complicated. An alternative proposal would be to create a fork of V8 at nodejs/v8 that would be used to maintain the V8 branches. This has several benefits:
nodejs/v8.v8-version.h would happen as part of this update instead of on every change.nodejs/v8 becomes purer and it would make it easier to pull in the V8 team for help with reviewing.main + V8 lkgr integration build.This would require some tooling to:
nodejs/v8 to nodejs/node.nodejs/v8 fork.[^1]: On macOS, the V8 tests require a full Xcode install, not just the “command line tools” for Xcode.