• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 4-week release cadence][ChromiumReleaseCalendar]. At any given time
19there are several V8 branches that are **active**, see the
20[V8 release process](https://v8.dev/docs/release-process). All older branches
21are abandoned and are not maintained by the V8 team.
22
23### V8 merge process overview
24
25The process for backporting bug fixes to active branches is officially
26documented [on the V8 wiki][V8MergingPatching]. The summary of the process is:
27
28* V8 only supports active branches. There is no testing done on any branches
29  older than the current stable/beta/master.
30* A fix needing backport is tagged w/ _merge-request-x.x_ tag. This can be done
31  by anyone interested in getting the fix backported. Issues with this tag are
32  reviewed by the V8 team regularly as candidates for backporting.
33* Fixes need some 'baking time' before they can be approved for backporting.
34  This means waiting a few days to ensure that no issues are detected on the
35  canary/beta builds.
36* Once ready, the issue is tagged w/ _merge-approved-x.x_ and one can do the
37  actual merge by using the scripts on the [wiki page][V8MergingPatching].
38* Merge requests to an abandoned branch will be rejected.
39* Only bug fixes are accepted for backporting.
40
41## Node.js support requirements
42
43At any given time Node.js needs to be maintaining a few different V8 branches
44for the various Current, LTS, and nightly releases.
45The versions of V8 used in Node.js may have already been
46abandoned by upstream V8. However, Node.js needs to continue supporting
47these branches for many months (Current branches) or several
48years (LTS branches).
49
50## Maintenance process
51
52Once a bug in Node.js has been identified to be caused by V8, the first step is
53to identify the versions of Node.js and V8 affected. The bug may be present in
54multiple different locations, each of which follows a slightly different
55process.
56
57* Unfixed bugs. The bug exists in the V8 master branch.
58* Fixed, but needs backport. The bug may need porting to one or more branches.
59  * Backporting to active branches.
60  * Backporting to abandoned branches.
61* Backports identified by the V8 team. Bugs identified by upstream V8 that we
62  haven't encountered in Node.js yet.
63
64### Unfixed upstream bugs
65
66If the bug can be reproduced on the [Node.js `canary` branch][], Chromium
67canary, or V8 tip-of-tree, and the test case is valid, then the bug needs to be
68fixed upstream first.
69
70* Start by opening a bug upstream using [this template][V8TemplateUpstreamBug].
71* Make sure to include a link to the corresponding Node.js issue
72  (if one exists).
73* If the fix is simple enough, you may fix it yourself;
74  [contributions][V8Contributing] are welcome.
75* V8's build waterfall tests your change.
76* Once the bug is fixed it may still need backporting, if it exists in other V8
77  branches that are still active or are branches that Node.js cares about.
78  Follow the process for backporting below.
79
80### Backporting to active branches
81
82If the bug exists in any of the active V8 branches, we may need to get the fix
83backported. At any given time, there are [two active branches][V8ActiveBranches]
84(beta and stable) in addition to master. The following steps are needed to
85backport the fix:
86
87* Identify which version of V8 the bug was fixed in.
88* Identify if any active V8 branches still contain the bug:
89* A tracking bug is needed to request a backport.
90  * If there isn't already a V8 bug tracking the fix, open a new merge request
91    bug using this [Node.js specific template][V8TemplateMergeRequest].
92  * If a bug already exists
93    * Add a reference to the GitHub issue.
94    * Attach _merge-request-x.x_ labels to the bug for any active branches
95      that still contain the bug.
96* Once the merge has been approved, it should be merged using the
97  [merge script documented in the V8 wiki][V8MergingPatching]. Merging requires
98  commit access to the V8 repository. If you don't have commit access you can
99  indicate someone on the V8 team can do the merge for you.
100* It is possible that the merge request may not get approved, for example if it
101  is considered to be a feature or otherwise too risky for V8 stable. In such
102  cases we float the patch on the Node.js side. See the process on 'Backporting
103  to Abandoned branches'.
104* Once the fix has been merged upstream, it can be picked up during an update of
105  the V8 branch (see below).
106
107### Backporting to abandoned branches
108
109Abandoned V8 branches are supported in the Node.js repository. The fix needs
110to be cherry-picked in the Node.js repository and V8-CI must test the change.
111
112As an example for how to backport changes, consider the bug
113[RegExp show inconsistent result with other browsers](https://crbug.com/v8/5199).
114From the bug we can see that it was merged by V8 into 5.2 and 5.3, and not into
115V8 5.1 (since it was already abandoned). Since Node.js `v6.x` uses V8 5.1, the
116fix needed to be backported.
117
118#### Backporting with `git-node` (recommended)
119
120You can use [`git-node`][] to help you backport patches. This removes
121some manual steps and is recommended.
122
123Here are the steps for the bug mentioned above:
124
1251. Install `git-node` by installing [`node-core-utils`][].
1262. Install the prerequisites for [`git-node-v8`][].
1273. Find the commit hash linked-to in the issue (in this case a51f429).
1284. Checkout a branch off the appropriate _vY.x-staging_ branch (e.g.
129   _v6.x-staging_ to fix an issue in V8 5.1).
1305. Run `git node v8 backport a51f429`.
1316. If there are conflicts, `git-node` will wait for you to resolve them:
132
133```console
134$ git node v8 backport a51f429
135✔ Update local V8 clone
136❯ V8 commit backport
137  ✔ Get current V8 version
138  ✔ Generate patches
139  ❯ Apply and commit patches to deps/v8
140    ❯ Commit a51f429772d1
141      ⠏ Apply patch
142      ◼ Increment embedder version number
143      ◼ Commit patch
144
145? Resolve merge conflicts and enter 'RESOLVED' ‣
146```
147
148Resolve conflicts, stage the files (you may need to open another terminal or use
149a GUI git client), then return to the terminal running `git-node`, type
150`RESOLVED`, and hit <kbd>Enter</kbd>.
151
1527. After you resolve conflicts (or if there are no conflicts), the
153   output should look like this:
154
155```console
156$ git node v8 backport a51f429
157✔ Update local V8 clone
158✔ V8 commit backport
159```
160
1618. Open a PR against the v6.x-staging branch in the Node.js repository.
162   Launch the normal and [V8 CI][] using the Node.js CI system. We only
163   needed to backport to v6.x as the other LTS branches weren't affected
164   by this bug.
165
166See [`git-node-v8-backport`][] for more documentation and additional options.
167
168#### Backporting manually
169
170* For each abandoned V8 branch corresponding to an LTS branch that is affected
171  by the bug:
172  * Checkout a branch off the appropriate _vY.x-staging_ branch (e.g.
173    _v6.x-staging_ to fix an issue in V8 5.1).
174  * Cherry-pick the commit(s) from the V8 repository.
175  * Increase the `v8_embedder_string` number in `common.gypi`.
176  * In some cases the patch may require extra effort to merge in case V8 has
177    changed substantially. For important issues, we may be able to lean on the
178    V8 team to get help with reimplementing the patch.
179  * Open a cherry-pick pull request on `nodejs/node` targeting the
180    _vY.x-staging_ branch and notify the `@nodejs/v8` team.
181  * Run the Node.js [V8 CI][] in addition to the [Node.js CI][].
182    The CI uses the `test-v8` target in the `Makefile`, which uses
183    `tools/make-v8.sh` to reconstruct a git tree in the `deps/v8` directory to
184    run V8 tests.[^1]
185
186Here are the steps for the bug mentioned above:
187
188* Download and apply the commit linked-to in the issue (in this case a51f429):
189
190  ```console
191  curl -L https://github.com/v8/v8/commit/a51f429.patch | git am -3 --directory=deps/v8
192  ```
193
194  If the branches have diverged significantly, this may not apply cleanly. It
195  may help to try to cherry-pick the merge to the oldest branch that was done
196  upstream in V8. In this example, this would be the patch from the merge to
197  5.2. The hope is that this would be closer to the V8 5.1, and has a better
198  chance of applying cleanly.
199* Modify the commit message to match the format we use for V8 backports and
200  replace yourself as the author. `git commit --amend --reset-author`. You may
201  want to add extra description if necessary to indicate the impact of the fix
202  on Node.js. In this case the original issue was descriptive enough. Example:
203
204```console
205deps: cherry-pick a51f429 from V8 upstream
206
207Original commit message:
208  [regexp] Fix case-insensitive matching for one-byte subjects.
209
210  The bug occurs because we do not canonicalize character class ranges
211  before adding case equivalents. While adding case equivalents, we abort
212  early for one-byte subject strings, assuming that the ranges are sorted.
213  Which they are not.
214
215  R=marja@chromium.org
216  BUG=v8:5199
217
218  Review-Url: https://codereview.chromium.org/2159683002
219  Cr-Commit-Position: refs/heads/master@{#37833}
220
221Refs: https://github.com/v8/v8/commit/a51f429772d1e796744244128c9feeab4c26a854
222PR-URL: https://github.com/nodejs/node/pull/7833
223```
224
225* Increase the `v8_embedder_string` number in `common.gypi`.
226* Open a PR against the `v6.x-staging` branch in the Node.js repository. Launch
227  the normal and [V8 CI][] using the Node.js CI system. We only needed to
228  backport to `v6.x` as the other LTS branches weren't affected by this bug.
229
230### Backports identified by the V8 team
231
232For bugs found through the browser or other channels, the V8 team marks bugs
233that might be applicable to the abandoned branches in use by Node.js. This is
234done through manual tagging by the V8 team and through an automated process that
235tags any fix that gets backported to the stable branch (as it is likely
236candidate for backporting further).
237
238Such fixes are tagged with the following labels in the V8 issue tracker:
239
240* `NodeJS-Backport-Review` ([V8][NodeJS-Backport-Review-V8],
241  [Chromium][NodeJS-Backport-Review-Chromium]): to be reviewed if this is
242  applicable to abandoned branches in use by Node.js. This list if regularly
243  reviewed by the Node.js team at Google to determine applicability to Node.js.
244* `NodeJS-Backport-Approved` ([V8][NodeJS-Backport-Approved-V8],
245  [Chromium][NodeJS-Backport-Approved-Chromium]): marks bugs that are deemed
246  relevant to Node.js and should be backported.
247* `NodeJS-Backport-Done` ([V8][NodeJS-Backport-Done-V8],
248  [Chromium][NodeJS-Backport-Done-Chromium]): Backport for Node.js has been
249  performed already.
250* `NodeJS-Backport-Rejected` ([V8][NodeJS-Backport-Rejected-V8],
251  [Chromium][NodeJS-Backport-Rejected-Chromium]): Backport for Node.js is not
252  desired.
253
254The backlog of issues with such is regularly reviewed by the node-team at Google
255to shepherd through the backport process. External contributors are welcome to
256collaborate on the backport process as well. Some of the bugs may be
257security issues and will not be visible to external collaborators.
258
259## Updating V8
260
261Node.js keeps a vendored copy of V8 inside of the deps/ directory. In addition,
262Node.js may need to float patches that do not exist upstream. This means that
263some care may need to be taken to update the vendored copy of V8.
264
265V8 builds against the version of ICU supplied by Node.js,
266see [maintaining-icu.md](./maintaining-icu.md) for special considerations.
267Specifically, a V8 update may necessitate an ICU update.
268
269### Minor updates (patch level)
270
271Because there may be floating patches on the version of V8 in Node.js, it is
272safest to apply the patch level updates as a patch. For example, imagine that
273upstream V8 is at 5.0.71.47 and Node.js is at 5.0.71.32. It would be best to
274compute the diff between these tags on the V8 repository, and then apply that
275patch on the copy of V8 in Node.js. This should preserve the patches/backports
276that Node.js may be floating (or else cause a merge conflict).
277
278#### Applying minor updates with `git-node` (recommended)
279
2801. Install [`git-node`][] by installing [`node-core-utils`][].
2812. Install the prerequisites for [`git-node-v8`][].
2823. Run `git node v8 minor` to apply a minor update.
283
284See [`git-node-v8-minor`][] for more documentation and additional options.
285
286#### Applying minor updates manually
287
288The rough outline of the process is:
289
290```bash
291# Assuming your fork of Node.js is checked out in $NODE_DIR
292# and you want to update the Node.js main branch.
293# Find the current (OLD) version in
294# $NODE_DIR/deps/v8/include/v8-version.h
295cd $NODE_DIR
296git checkout main
297git merge --ff-only origin/main
298git checkout -b V8_NEW_VERSION
299curl -L https://github.com/v8/v8/compare/${V8_OLD_VERSION}...${V8_NEW_VERSION}.patch | git apply --directory=deps/v8
300# You may want to amend the commit message to describe the nature of the update
301```
302
303V8 also keeps tags of the form _5.4-lkgr_ which point to the _Last Known Good
304Revision_ from the 5.4 branch that can be useful in the update process above.
305
306### Major updates
307
308We upgrade the version of V8 in Node.js `main` whenever a V8 release goes stable
309upstream, that is, whenever a new release of Chrome comes out.
310
311Upgrading major versions would be much harder to do with the patch mechanism
312above. A better strategy is to
313
3141. Audit the current `main` branch and look at the patches that have been
315   floated since the last major V8 update.
3162. Replace the copy of V8 in Node.js with a fresh checkout of the latest stable
317   V8 branch. Special care must be taken to recursively update the DEPS that V8
318   has a compile time dependency on (at the moment of this writing, these are
319   only trace\_event and gtest\_prod.h)
3203. Reset the `v8_embedder_string` variable to "-node.0" in `common.gypi`.
3214. Refloat (cherry-pick) all the patches from list computed in 1) as necessary.
322   Some of the patches may no longer be necessary.
323
324To audit for floating patches:
325
326```bash
327git log --oneline deps/v8
328```
329
330To replace the copy of V8 in Node.js, use the [`git-node`][] tool. For example,
331if you want to replace the copy of V8 in Node.js with the branch-head for V8 5.1
332branch:
333
334```bash
335cd $NODE_DIR
336git node v8 major --branch=5.1-lkgr
337```
338
339This should be followed up with manual refloating of all relevant patches.
340
341## Proposal: Using a fork repository to track upstream V8
342
343The fact that Node.js keeps a vendored, potentially edited copy of V8 in deps/
344makes the above processes a bit complicated. An alternative proposal would be to
345create a fork of V8 at `nodejs/v8` that would be used to maintain the V8
346branches. This has several benefits:
347
348* The process to update the version of V8 in Node.js could be automated to track
349  the tips of various V8 branches in `nodejs/v8`.
350* It would simplify cherry-picking and porting of fixes between branches as the
351  version bumps in `v8-version.h` would happen as part of this update instead of
352  on every change.
353* It would simplify the V8-CI and make it more automatable.
354* The history of the V8 branch in `nodejs/v8` becomes purer and it would make it
355  easier to pull in the V8 team for help with reviewing.
356* It would make it simpler to setup an automated build that tracks Node.js
357  `main` + V8 lkgr integration build.
358
359This would require some tooling to:
360
361* A script that would update the V8 in a specific Node.js branch with V8 from
362  upstream (dependent on branch abandoned vs. active).
363* We need a script to bump V8 version numbers when a new version of V8 is
364  promoted from `nodejs/v8` to `nodejs/node`.
365* Enabled the V8-CI build in Jenkins to build from the `nodejs/v8` fork.
366
367[^1]: On macOS, the V8 tests require a full Xcode install, not just the "command
368    line tools" for Xcode.
369
370[ChromiumReleaseCalendar]: https://www.chromium.org/developers/calendar
371[Node.js CI]: https://ci.nodejs.org/job/node-test-pull-request/
372[Node.js `canary` branch]: https://github.com/nodejs/node-v8/tree/canary
373[NodeJS-Backport-Approved-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Approved
374[NodeJS-Backport-Approved-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Approved
375[NodeJS-Backport-Done-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Done
376[NodeJS-Backport-Done-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Done
377[NodeJS-Backport-Rejected-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Rejected
378[NodeJS-Backport-Rejected-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Rejected
379[NodeJS-Backport-Review-Chromium]: https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3ANodeJS-Backport-Review
380[NodeJS-Backport-Review-V8]: https://bugs.chromium.org/p/v8/issues/list?can=1&q=label%3ANodeJS-Backport-Review
381[V8 CI]: https://ci.nodejs.org/job/node-test-commit-v8-linux/
382[V8ActiveBranches]: https://build.chromium.org/p/client.v8.branches/console
383[V8Contributing]: https://v8.dev/docs/contribute
384[V8MergingPatching]: https://v8.dev/docs/merge-patch
385[V8TemplateMergeRequest]: https://bugs.chromium.org/p/v8/issues/entry?template=Node.js%20merge%20request
386[V8TemplateUpstreamBug]: https://bugs.chromium.org/p/v8/issues/entry?template=Node.js%20upstream%20bug
387[`git-node-v8-backport`]: https://github.com/nodejs/node-core-utils/blob/main/docs/git-node.md#git-node-v8-backport-sha
388[`git-node-v8-minor`]: https://github.com/nodejs/node-core-utils/blob/main/docs/git-node.md#git-node-v8-minor
389[`git-node-v8`]: https://github.com/nodejs/node-core-utils/blob/HEAD/docs/git-node.md#git-node-v8
390[`git-node`]: https://github.com/nodejs/node-core-utils/blob/HEAD/docs/git-node.md#git-node-v8
391[`node-core-utils`]: https://github.com/nodejs/node-core-utils#Install
392