1# Maintaining V8 in Node.js 2 3## Background 4 5V8 follows the Chromium release schedule. The support horizon for Chromium is 6different compared to the support horizon for Node.js. As a result, Node.js 7needs to support multiple versions of V8 longer than what upstream needs 8to support. V8 branches in Node.js lack of an official maintenance process due 9to a missing LTS supported branch. 10 11This document attempts to outline the current maintenance processes, proposes 12a workflow for maintaining the V8 branches in both Node.js LTS and current 13releases, and discusses how the Node.js and V8 teams at Google can help. 14 15## V8 release schedule 16 17V8 and Chromium follow a 18[roughly 6-week release cadence][ChromiumReleaseCalendar]. At any given time 19there are three V8 branches that are **active**. 20 21For example, at the time of this writing: 22 23* **Stable**: V8 5.4 is currently shipping as part of Chromium stable. This 24 branch was created approx. 6 weeks before from when V8 5.3 shipped as stable. 25* **Beta**: V8 5.5 is currently in beta. It will be promoted to stable next; 26 approximately 6 weeks after V8 5.4 shipped as stable. 27* **Master**: V8 tip-of-tree corresponds to V8 5.6. This branch gets regularly 28 released as part of the Chromium **canary** builds. This branch will be 29 promoted to beta next when V8 5.5 ships as stable. 30 31All older branches are abandoned and are not maintained by the V8 team. 32 33### V8 merge process overview 34 35The process for backporting bug fixes to active branches is officially 36documented [on the V8 wiki][V8MergingPatching]. The summary of the process is: 37 38* V8 only supports active branches. There is no testing done on any branches 39 older than the current stable/beta/master. 40* A fix needing backport is tagged w/ *merge-request-x.x* tag. This can be done 41 by anyone interested in getting the fix backported. Issues with this tag are 42 reviewed by the V8 team regularly as candidates for backporting. 43* Fixes need some 'baking time' before they can be approved for backporting. 44 This means waiting a few days to ensure that no issues are detected on the 45 canary/beta builds. 46* Once ready, the issue is tagged w/ *merge-approved-x.x* and one can do the 47 actual merge by using the scripts on the [wiki page][V8MergingPatching]. 48* Merge requests to an abandoned branch will be rejected. 49* Only bug fixes are accepted for backporting. 50 51## Node.js support requirements 52 53At any given time Node.js needs to be maintaining a few different V8 branches 54for the various Current, LTS, and nightly releases. At present this list 55includes the following branches<sup>1</sup>: 56 57<table> 58 <tr> 59 <td><strong>Release</strong> 60 </td> 61 <td><strong>Support Start</strong> 62 </td> 63 <td><strong>Support End</strong> 64 </td> 65 <td><strong>V8 version</strong> 66 </td> 67 <td><strong>V8 branch released</strong> 68 </td> 69 <td><strong>V8 branch abandoned</strong> 70 </td> 71 </tr> 72 <tr> 73 <td>Node.js 4.x 74 </td> 75 <td>2015-10-01 76 </td> 77 <td>April 2018 78 </td> 79 <td>4.5 80 </td> 81 <td>2015-09-01 82 </td> 83 <td>2015-10-13 84 </td> 85 </tr> 86 <tr> 87 <td>Node.js 6.x 88 </td> 89 <td>2016-04-01 90 </td> 91 <td>April 2019 92 </td> 93 <td>5.1 94 </td> 95 <td>2016-05-31 96 </td> 97 <td>2016-06-26 98 </td> 99 </tr> 100 <tr> 101 <td>Node.js 8.x 102 </td> 103 <td>2017-05-30 104 </td> 105 <td>December 2019 106 </td> 107 <td>6.1 (soon to be 6.2) 108 </td> 109 <td>2017-10-17 (6.2) 110 </td> 111 <td>~2017-12-05 (6.2) 112 </td> 113 </tr> 114 <tr> 115 <td>Node.js 9.x 116 </td> 117 <td>2017-10-31 118 </td> 119 <td>April 2018 120 </td> 121 <td>6.2 122 </td> 123 <td>2017-10-17 124 </td> 125 <td>~2017-12-05 126 </td> 127 </tr> 128 <tr> 129 <td>master 130 </td> 131 <td>N/A 132 </td> 133 <td>N/A 134 </td> 135 <td>6.2 136 </td> 137 <td>2017-10-17 138 </td> 139 <td>~2017-12-05 140 </td> 141 </tr> 142</table> 143 144The versions of V8 used in Node.js v4.x, v6.x, and 8.x have already been 145abandoned by upstream V8. However, Node.js needs to continue supporting 146these branches for many months (Current branches) or several 147years (LTS branches). 148 149## Maintenance process 150 151Once a bug in Node.js has been identified to be caused by V8, the first step is 152to identify the versions of Node.js and V8 affected. The bug may be present in 153multiple different locations, each of which follows a slightly different 154process. 155 156* Unfixed bugs. The bug exists in the V8 master branch. 157* Fixed, but needs backport. The bug may need porting to one or more branches. 158 * Backporting to active branches. 159 * Backporting to abandoned branches. 160* Backports identified by the V8 team. Bugs identified by upstream V8 that we 161 haven't encountered in Node.js yet. 162 163### Unfixed upstream bugs 164 165If the bug can be reproduced on the [Node.js `canary` branch][], Chromium 166canary, or V8 tip-of-tree, and the test case is valid, then the bug needs to be 167fixed upstream first. 168 169* Start by opening a bug upstream using [this template][V8TemplateUpstreamBug]. 170* Make sure to include a link to the corresponding Node.js issue 171 (if one exists). 172* If the fix is simple enough, you may fix it yourself; 173 [contributions][V8Contributing] are welcome. 174* V8's build waterfall tests your change. 175* Once the bug is fixed it may still need backporting, if it exists in other V8 176 branches that are still active or are branches that Node.js cares about. 177 Follow the process for backporting below. 178 179### Backporting to active branches 180 181If the bug exists in any of the active V8 branches, we may need to get the fix 182backported. At any given time, there are [two active branches][V8ActiveBranches] 183(beta and stable) in addition to master. The following steps are needed to 184backport the fix: 185 186* Identify which version of V8 the bug was fixed in. 187* Identify if any active V8 branches still contain the bug: 188* A tracking bug is needed to request a backport. 189 * If there isn't already a V8 bug tracking the fix, open a new merge request 190 bug using this [Node.js specific template][V8TemplateMergeRequest]. 191 * If a bug already exists 192 * Add a reference to the GitHub issue. 193 * Attach *merge-request-x.x* labels to the bug for any active branches 194 that still contain the bug. 195* Once the merge has been approved, it should be merged using the 196 [merge script documented in the V8 wiki][V8MergingPatching]. Merging requires 197 commit access to the V8 repository. If you don't have commit access you can 198 indicate someone on the V8 team can do the merge for you. 199* It is possible that the merge request may not get approved, for example if it 200 is considered to be a feature or otherwise too risky for V8 stable. In such 201 cases we float the patch on the Node.js side. See the process on 'Backporting 202 to Abandoned branches'. 203* Once the fix has been merged upstream, it can be picked up during an update of 204 the V8 branch (see below). 205 206### Backporting to abandoned branches 207 208Abandoned V8 branches are supported in the Node.js repository. The fix needs 209to be cherry-picked in the Node.js repository and V8-CI must test the change. 210 211* For each abandoned V8 branch corresponding to an LTS branch that is affected 212 by the bug: 213 * Checkout a branch off the appropriate *vY.x-staging* branch (e.g. 214 *v6.x-staging* to fix an issue in V8 5.1). 215 * Cherry-pick the commit(s) from the V8 repository. 216 * Increase the `v8_embedder_string` number in `common.gypi`. 217 * In some cases the patch may require extra effort to merge in case V8 has 218 changed substantially. For important issues, we may be able to lean on the 219 V8 team to get help with reimplementing the patch. 220 * Open a cherry-pick pull request on `nodejs/node` targeting the 221 *vY.x-staging* branch and notify the `@nodejs/v8` team. 222 * Run the Node.js [V8 CI][] in addition to the [Node.js CI][]. 223 The CI uses the `test-v8` target in the `Makefile`, which uses 224 `tools/make-v8.sh` to reconstruct a git tree in the `deps/v8` directory to 225 run V8 tests<sup>2</sup>. 226 227The [`git-node`][] tool can be used to simplify this task. Run 228`git node v8 backport <sha>` to cherry-pick a commit. 229 230An example for workflow how to cherry-pick consider the bug 231[RegExp show inconsistent result with other browsers](https://crbug.com/v8/5199). 232From the bug we can see that it was merged by V8 into 5.2 and 5.3, and not into 233V8 5.1 (since it was already abandoned). Since Node.js `v6.x` uses V8 5.1, the 234fix needed to be cherry-picked. To cherry-pick, here's an example workflow: 235 236* Download and apply the commit linked-to in the issue (in this case a51f429). 237 `curl -L https://github.com/v8/v8/commit/a51f429.patch | git am -3 238 --directory=deps/v8`. If the branches have diverged significantly, this may 239 not apply cleanly. It may help to try to cherry-pick the merge to the oldest 240 branch that was done upstream in V8. In this example, this would be the patch 241 from the merge to 5.2. The hope is that this would be closer to the V8 5.1, 242 and has a better chance of applying cleanly. 243* Modify the commit message to match the format we use for V8 backports and 244 replace yourself as the author. `git commit --amend --reset-author`. You may 245 want to add extra description if necessary to indicate the impact of the fix 246 on Node.js. In this case the original issue was descriptive enough. Example: 247 248```console 249deps: cherry-pick a51f429 from V8 upstream 250 251Original commit message: 252 [regexp] Fix case-insensitive matching for one-byte subjects. 253 254 The bug occurs because we do not canonicalize character class ranges 255 before adding case equivalents. While adding case equivalents, we abort 256 early for one-byte subject strings, assuming that the ranges are sorted. 257 Which they are not. 258 259 R=marja@chromium.org 260 BUG=v8:5199 261 262 Review-Url: https://codereview.chromium.org/2159683002 263 Cr-Commit-Position: refs/heads/master@{#37833} 264 265Refs: https://github.com/v8/v8/commit/a51f429772d1e796744244128c9feeab4c26a854 266PR-URL: https://github.com/nodejs/node/pull/7833 267``` 268 269* Open a PR against the `v6.x-staging` branch in the Node.js repository. Launch 270 the normal and [V8 CI][] using the Node.js CI system. We only needed to 271 backport to `v6.x` as the other LTS branches weren't affected by this bug. 272 273### Backports identified by the V8 team 274 275For bugs found through the browser or other channels, the V8 team marks bugs 276that might be applicable to the abandoned branches in use by Node.js. This is 277done through manual tagging by the V8 team and through an automated process that 278tags any fix that gets backported to the stable branch (as it is likely 279candidate for backporting further). 280 281Such fixes are tagged with the following labels in the V8 issue tracker: 282 283* `NodeJS-Backport-Review` ([V8][NodeJS-Backport-Review-V8], 284 [Chromium][NodeJS-Backport-Review-Chromium]): to be reviewed if this is 285 applicable to abandoned branches in use by Node.js. This list if regularly 286 reviewed by the Node.js team at Google to determine applicability to Node.js. 287* `NodeJS-Backport-Approved` ([V8][NodeJS-Backport-Approved-V8], 288 [Chromium][NodeJS-Backport-Approved-Chromium]): marks bugs that are deemed 289 relevant to Node.js and should be backported. 290* `NodeJS-Backport-Done` ([V8][NodeJS-Backport-Done-V8], 291 [Chromium][NodeJS-Backport-Done-Chromium]): Backport for Node.js has been 292 performed already. 293* `NodeJS-Backport-Rejected` ([V8][NodeJS-Backport-Rejected-V8], 294 [Chromium][NodeJS-Backport-Rejected-Chromium]): Backport for Node.js is not 295 desired. 296 297The backlog of issues with such is regularly reviewed by the node-team at Google 298to shepherd through the backport process. External contributors are welcome to 299collaborate on the backport process as well. Some of the bugs may be 300security issues and will not be visible to external collaborators. 301 302## Updating V8 303 304Node.js keeps a vendored copy of V8 inside of the deps/ directory. In addition, 305Node.js may need to float patches that do not exist upstream. This means that 306some care may need to be taken to update the vendored copy of V8. 307 308V8 builds against the version of ICU supplied by Node.js, 309see [maintaining-icu.md](./maintaining-icu.md) for special considerations. 310Specifically, a V8 update may necessitate an ICU update. 311 312### Minor updates (patch level) 313 314Because there may be floating patches on the version of V8 in Node.js, it is 315safest to apply the patch level updates as a patch. For example, imagine that 316upstream V8 is at 5.0.71.47 and Node.js is at 5.0.71.32. It would be best to 317compute the diff between these tags on the V8 repository, and then apply that 318patch on the copy of V8 in Node.js. This should preserve the patches/backports 319that Node.js may be floating (or else cause a merge conflict). 320 321The rough outline of the process is: 322 323```bash 324# Assuming your fork of Node.js is checked out in $NODE_DIR 325# and you want to update the Node.js master branch. 326# Find the current (OLD) version in 327# $NODE_DIR/deps/v8/include/v8-version.h 328cd $NODE_DIR 329git checkout master 330git merge --ff-only origin/master 331git checkout -b V8_NEW_VERSION 332curl -L https://github.com/v8/v8/compare/${V8_OLD_VERSION}...${V8_NEW_VERSION}.patch | git apply --directory=deps/v8 333# You may want to amend the commit message to describe the nature of the update 334``` 335 336V8 also keeps tags of the form *5.4-lkgr* which point to the *Last Known Good 337Revision* from the 5.4 branch that can be useful in the update process above. 338 339The [`git-node`][] tool can be used to simplify this task. Run `git node v8 minor` 340to apply a minor update. 341 342### Major updates 343 344We upgrade the version of V8 in Node.js master whenever a V8 release goes stable 345upstream, that is, whenever a new release of Chrome comes out. 346 347Upgrading major versions would be much harder to do with the patch mechanism 348above. A better strategy is to 349 3501. Audit the current master branch and look at the patches that have been 351 floated since the last major V8 update. 3521. Replace the copy of V8 in Node.js with a fresh checkout of the latest stable 353 V8 branch. Special care must be taken to recursively update the DEPS that V8 354 has a compile time dependency on (at the moment of this writing, these are 355 only trace_event and gtest_prod.h) 3561. Reset the `v8_embedder_string` variable to "-node.0" in `common.gypi`. 3571. Refloat (cherry-pick) all the patches from list computed in 1) as necessary. 358 Some of the patches may no longer be necessary. 359 360To audit for floating patches: 361 362```bash 363git log --oneline deps/v8 364``` 365 366To replace the copy of V8 in Node.js, use the [`git-node`][] tool. For example, 367if you want to replace the copy of V8 in Node.js with the branch-head for V8 5.1 368branch: 369 370```bash 371cd $NODE_DIR 372git node v8 major --branch=5.1-lkgr 373``` 374 375This should be followed up with manual refloating of all relevant patches. 376 377## Proposal: Using a fork repository to track upstream V8 378 379The fact that Node.js keeps a vendored, potentially edited copy of V8 in deps/ 380makes the above processes a bit complicated. An alternative proposal would be to 381create a fork of V8 at `nodejs/v8` that would be used to maintain the V8 382branches. This has several benefits: 383 384* The process to update the version of V8 in Node.js could be automated to track 385 the tips of various V8 branches in `nodejs/v8`. 386* It would simplify cherry-picking and porting of fixes between branches as the 387 version bumps in `v8-version.h` would happen as part of this update instead of 388 on every change. 389* It would simplify the V8-CI and make it more automatable. 390* The history of the V8 branch in `nodejs/v8` becomes purer and it would make it 391 easier to pull in the V8 team for help with reviewing. 392* It would make it simpler to setup an automated build that tracks Node.js 393 master + V8 lkgr integration build. 394 395This would require some tooling to: 396 397* A script that would update the V8 in a specific Node.js branch with V8 from 398 upstream (dependent on branch abandoned vs. active). 399* We need a script to bump V8 version numbers when a new version of V8 is 400 promoted from `nodejs/v8` to `nodejs/node`. 401* Enabled the V8-CI build in Jenkins to build from the `nodejs/v8` fork. 402 403<!-- Footnotes themselves at the bottom. --> 404### Notes 405 406<sup>1</sup>Node.js 0.12 and older are intentionally omitted from this document 407as their support has ended. 408 409<sup>2</sup>The V8 tests still require Python 2. To run these tests locally, 410you can run `PYTHON2 ./configure.py` before running `make test-v8`, in the root 411of this repository. On macOS, this also requires a full Xcode install, 412not just the "command line tools" for Xcode. 413 414[ChromiumReleaseCalendar]: https://www.chromium.org/developers/calendar 415[Node.js CI]: https://ci.nodejs.org/job/node-test-pull-request/ 416[Node.js `canary` branch]: https://github.com/nodejs/node-v8/tree/canary 417[NodeJS-Backport-Approved-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Approved 418[NodeJS-Backport-Approved-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Approved 419[NodeJS-Backport-Done-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Done 420[NodeJS-Backport-Done-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Done 421[NodeJS-Backport-Rejected-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Rejected 422[NodeJS-Backport-Rejected-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Rejected 423[NodeJS-Backport-Review-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Review 424[NodeJS-Backport-Review-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Review 425[V8 CI]: https://ci.nodejs.org/job/node-test-commit-v8-linux/ 426[V8ActiveBranches]: https://build.chromium.org/p/client.v8.branches/console 427[V8Contributing]: https://github.com/v8/v8/wiki/Contributing 428[V8MergingPatching]: https://github.com/v8/v8/wiki/Merging%20&%20Patching 429[V8TemplateMergeRequest]: https://bugs.chromium.org/p/v8/issues/entry?template=Node.js%20merge%20request 430[V8TemplateUpstreamBug]: https://bugs.chromium.org/p/v8/issues/entry?template=Node.js%20upstream%20bug 431[`git-node`]: https://github.com/nodejs/node-core-utils/blob/HEAD/docs/git-node.md#git-node-v8 432