|
4 | 4 |
|
5 | 5 | * [Issues and Pull Requests](#issues-and-pull-requests)
|
6 | 6 | * [Accepting Modifications](#accepting-modifications)
|
| 7 | + - [Internal vs. Public API](#internal-vs-public-api) |
| 8 | + - [Breaking Changes](#breaking-changes) |
| 9 | + - [Deprecations](#deprecations) |
7 | 10 | - [Involving the CTC](#involving-the-ctc)
|
8 | 11 | * [Landing Pull Requests](#landing-pull-requests)
|
9 | 12 | - [Technical HOWTO](#technical-howto)
|
@@ -81,6 +84,205 @@ All pull requests that modify executable code should be subjected to
|
81 | 84 | continuous integration tests on the
|
82 | 85 | [project CI server](https://ci.nodejs.org/).
|
83 | 86 |
|
| 87 | +### Internal vs. Public API |
| 88 | + |
| 89 | +Due to the nature of the JavaScript language, it can often be difficult to |
| 90 | +establish a clear distinction between which parts of the Node.js implementation |
| 91 | +represent the "public" API Node.js users should assume to be stable and which |
| 92 | +are considered part of the "internal" implementation detail of Node.js itself. |
| 93 | +A general rule of thumb has been to base the determination off what |
| 94 | +functionality is actually *documented* in the official Node.js API |
| 95 | +documentation. However, it has been repeatedly demonstrated that either the |
| 96 | +documentation does not completely cover implemented behavior or that Node.js |
| 97 | +users have come to rely heavily on undocumented aspects of the Node.js |
| 98 | +implementation. |
| 99 | + |
| 100 | +While there are numerous exceptions, the following general rules should be |
| 101 | +followed to determine which aspects of the Node.js API are considered |
| 102 | +"internal": |
| 103 | + |
| 104 | +- Any and all functionality exposed via `process.binding(...)` is considered to |
| 105 | + be internal and *not* part of the Node.js Public API. |
| 106 | +- Any and all functionality implemented in `lib/internal/**/*.js` that is not |
| 107 | + re-exported by code in `lib/*.js`, or is not documented as part of the |
| 108 | + Node.js Public API, is considered to be internal. |
| 109 | +- Any object property or method whose key is a non-exported `Symbol` is |
| 110 | + considered to be an internal property. |
| 111 | +- Any object property or method whose key begins with the underscore `_` prefix, |
| 112 | + and is not documented as part of the Node.js Public API, is considered to be |
| 113 | + an internal property. |
| 114 | +- Any object, property, method, argument, behavior, or event not documented in |
| 115 | + the Node.js documentation is considered to be internal. |
| 116 | +- Any native C/C++ APIs/ABIs exported by the Node.js `*.h` header files that |
| 117 | + are hidden behind the `NODE_WANT_INTERNALS` flag are considered to be |
| 118 | + internal. |
| 119 | + |
| 120 | +Exception to each of these points can be made if use or behavior of a given |
| 121 | +internal API can be demonstrated to be sufficiently relied upon by the Node.js |
| 122 | +ecosystem such that any changes would cause too much breakage. The threshhold |
| 123 | +for what qualifies as "too much breakage" is to be decided on a case-by-case |
| 124 | +basis by the CTC. |
| 125 | + |
| 126 | +If it is determined that a currently undocumented object, property, method, |
| 127 | +argument, or event *should* be documented, then a pull request adding the |
| 128 | +documentation is required in order for it to be considered part of the "public" |
| 129 | +API. |
| 130 | + |
| 131 | +Making a determination about whether something *should* be documented can be |
| 132 | +difficult and will need to be handled on a case-by-case basis. For instance, if |
| 133 | +one documented API cannot be used successfully without the use of a second |
| 134 | +*currently undocumented* API, then the second API *should* be documented. If |
| 135 | +using an API in a manner currently undocumented achieves a particular useful |
| 136 | +result, a decision will need to be made whether or not that falls within the |
| 137 | +supported scope of that API; and if it does, it should be documented. |
| 138 | + |
| 139 | +Breaking changes to internal elements are permitted in semver-patch or |
| 140 | +semver-minor commits but Collaborators should take significant care when |
| 141 | +making and reviewing such changes. Before landing such commits, an effort |
| 142 | +must be made to determine the potential impact of the change in the ecosystem |
| 143 | +by analyzing current use and by validating such changes through ecosystem |
| 144 | +testing using the [Canary in the Goldmine](https://github.com/nodejs/citgm) |
| 145 | +tool. If a change cannot be made without ecosystem breakage, then CTC review is |
| 146 | +required before landing the change as anything less than semver-major. |
| 147 | + |
| 148 | +If a determination is made that a particular internal API (for instance, an |
| 149 | +underscore `_` prefixed property) is sufficiently relied upon by the ecosystem |
| 150 | +such that any changes may break user code, then serious consideration should be |
| 151 | +given to providing an alternative Public API for that functionality before any |
| 152 | +breaking changes are made. |
| 153 | + |
| 154 | +### Breaking Changes |
| 155 | + |
| 156 | +Backwards-incompatible changes may land on the master branch at any time after |
| 157 | +sufficient review by collaborators and approval of at least two CTC members. |
| 158 | + |
| 159 | +Examples of breaking changes include, but are not necessarily limited to, |
| 160 | +removal or redefinition of existing API arguments, changing return values |
| 161 | +(except when return values do not currently exist), removing or modifying existing properties on an options argument, adding or removing errors, |
| 162 | +changing error messages in any way, altering expected timing of an event (e.g. |
| 163 | +moving from sync to async responses or vice versa), and changing the |
| 164 | +non-internal side effects of using a particular API. |
| 165 | + |
| 166 | +With a few notable exceptions outlined below, when backwards incompatible |
| 167 | +changes to a *Public* API are necessary, the existing API *must* be deprecated |
| 168 | +*first* and the new API either introduced in parallel or added after the next |
| 169 | +major Node.js version following the deprecation as a replacement for the |
| 170 | +deprecated API. In other words, as a general rule, existing *Public* APIs |
| 171 | +*must not* change (in a backwards incompatible way) without a deprecation. |
| 172 | + |
| 173 | +Exception to this rule is given in the following cases: |
| 174 | + |
| 175 | +* Adding or removing errors thrown or reported by a Public API; |
| 176 | +* Changing error messages; |
| 177 | +* Altering the timing and non-internal side effects of the Public API. |
| 178 | + |
| 179 | +Such changes *must* be handled as semver-major changes but MAY be landed |
| 180 | +without a [Deprecation cycle](#deprecation-cycle). |
| 181 | + |
| 182 | +From time-to-time, in particularly exceptional cases, the CTC may be asked to |
| 183 | +consider and approve additional exceptions to this rule. |
| 184 | + |
| 185 | +Purely additive changes (e.g. adding new events to EventEmitter |
| 186 | +implementations, adding new arguments to a method in a way that allows |
| 187 | +existing code to continue working without modification, or adding new |
| 188 | +properties to an options argument) are handled as semver-minor changes. |
| 189 | + |
| 190 | +Note that errors thrown, along with behaviors and APIs implemented by |
| 191 | +dependencies of Node.js (e.g. those originating from V8) are generally not |
| 192 | +under the control of Node.js and therefore *are not directly subject to this |
| 193 | +policy*. However, care should still be taken when landing updates to |
| 194 | +dependencies when it is known or expected that breaking changes to error |
| 195 | +handling may have been made. Additional CI testing may be required. |
| 196 | + |
| 197 | +#### When breaking changes actually break things |
| 198 | + |
| 199 | +Breaking changes are difficult primarily because they change the fundamental |
| 200 | +assumptions a user of Node.js has when writing their code and can cause |
| 201 | +existing code to stop functioning as expected -- costing developers and users |
| 202 | +time and energy to fix. |
| 203 | + |
| 204 | +Because breaking (semver-major) changes are permitted to land in master at any |
| 205 | +time, it should be *understood and expected* that at least some subset of the |
| 206 | +user ecosystem *may* be adversely affected *in the short term* when attempting |
| 207 | +to build and use Node.js directly from master. This potential instability is |
| 208 | +precisely why Node.js offers distinct Current and LTS release streams that |
| 209 | +offer explicit stability guarantees. |
| 210 | + |
| 211 | +Specifically: |
| 212 | + |
| 213 | +* Breaking changes should *never* land in Current or LTS except when: |
| 214 | + * Resolving critical security issues. |
| 215 | + * Fixing a critical bug (e.g. fixing a memory leak) requires a breaking |
| 216 | + change. |
| 217 | + * There is CTC consensus that the change is required. |
| 218 | +* If a breaking commit does accidentally land in a Current or LTS branch, an |
| 219 | + attempt to fix the issue will be made before the next release; If no fix is |
| 220 | + provided then the commit will be reverted. |
| 221 | + |
| 222 | +When any change is landed in master, and it is determined that the such |
| 223 | +changes *do* break existing code, a decision may be made to revert those |
| 224 | +changes either temporarily or permanently. However, the decision to revert or |
| 225 | +not can often be based on many complex factors that are not easily codified. It |
| 226 | +is also possible that the breaking commit can be labeled retroactively as a |
| 227 | +semver-major change that will not be backported to Current or LTS branches. |
| 228 | + |
| 229 | +### Deprecations |
| 230 | + |
| 231 | +Deprecation refers to the identification of Public APIs that should no longer |
| 232 | +be used and that may be removed or modified in non-backwards compatible ways in |
| 233 | +a future major release of Node.js. Deprecation *may* be used with internal APIs |
| 234 | +if there is expected impact on the user community. |
| 235 | + |
| 236 | +Node.js uses three fundamental Deprecation levels: |
| 237 | + |
| 238 | +* *Documentation-Only Deprecation* refers to elements of the Public API that are |
| 239 | + being staged for deprecation in a future Node.js major release. An explicit |
| 240 | + notice indicating the deprecated status is added to the API documentation |
| 241 | + *but no functional changes are implemented in the code*. There will be no |
| 242 | + runtime deprecation warning emitted for such deprecations. |
| 243 | + |
| 244 | +* *Runtime Deprecation* refers to the use of process warnings emitted at |
| 245 | + runtime the first time that a deprecated API is used. A command-line |
| 246 | + switch can be used to escalate such warnings into runtime errors that will |
| 247 | + cause the Node.js process to exit. As with Documentation-Only Deprecation, |
| 248 | + the documentation for the API must be updated to clearly indicate the |
| 249 | + deprecated status. |
| 250 | + |
| 251 | +* *End-of-life* refers to APIs that have gone through Runtime Deprecation and |
| 252 | + are ready to be removed from Node.js entirely. |
| 253 | + |
| 254 | +Documentation-Only Deprecations *may* be handled as semver-minor or |
| 255 | +semver-major changes. Such deprecations have no impact on the successful |
| 256 | +operation of running code and therefore should not be viewed as breaking |
| 257 | +changes. |
| 258 | + |
| 259 | +Runtime Deprecations and End-of-life APIs (internal or public) *must* be |
| 260 | +handled as semver-major changes unless there is CTC consensus to land the |
| 261 | +deprecation as a semver-minor. |
| 262 | + |
| 263 | +All Documentation-Only and Runtime deprecations will be assigned a unique |
| 264 | +identifier that can be used to persistently refer to the deprecation in |
| 265 | +documentation, emitted process warnings, or errors thrown. Documentation for |
| 266 | +these identifiers will be included in the Node.js API documentation and will |
| 267 | +be immutable once assigned. Even if End-of-Life code is removed from Node.js, |
| 268 | +the documentation for the assigned deprecation identifier must remain in the |
| 269 | +Node.js API documentation. |
| 270 | + |
| 271 | +<a id="deprecation-cycle"></a> |
| 272 | +A "Deprecation cycle" is one full Node.js major release during which an API |
| 273 | +has been in one of the three Deprecation levels. (Note that Documentation-Only |
| 274 | +Deprecations may land in a Node.js minor release but must not be upgraded to |
| 275 | +a Runtime Deprecation until the next major release.) |
| 276 | + |
| 277 | +No API can be moved to End-of-life without first having gone through a |
| 278 | +Runtime Deprecation cycle. |
| 279 | + |
| 280 | +A best effort will be made to communicate pending deprecations and associated |
| 281 | +mitigations with the ecosystem as soon as possible (preferably *before* the pull |
| 282 | +request adding the deprecation lands in master). All deprecations included in |
| 283 | +a Node.js release should be listed prominently in the "Notable Changes" section |
| 284 | +of the release notes. |
| 285 | + |
84 | 286 | ### Involving the CTC
|
85 | 287 |
|
86 | 288 | Collaborators may opt to elevate pull requests or issues to the CTC for
|
@@ -253,15 +455,15 @@ You can find more information [in the full LTS plan](https://github.com/nodejs/l
|
253 | 455 |
|
254 | 456 | #### How does LTS work?
|
255 | 457 |
|
256 |
| -Once a stable branch enters LTS, changes in that branch are limited to bug |
| 458 | +Once a Current branch enters LTS, changes in that branch are limited to bug |
257 | 459 | fixes, security updates, possible npm updates, documentation updates, and
|
258 | 460 | certain performance improvements that can be demonstrated to not break existing
|
259 | 461 | applications. Semver-minor changes are only permitted if required for bug fixes
|
260 | 462 | and then only on a case-by-case basis with LTS WG and possibly Core Technical
|
261 | 463 | Committee (CTC) review. Semver-major changes are permitted only if required for
|
262 | 464 | security related fixes.
|
263 | 465 |
|
264 |
| -Once a stable branch moves into Maintenance mode, only **critical** bugs, |
| 466 | +Once a Current branch moves into Maintenance mode, only **critical** bugs, |
265 | 467 | **critical** security fixes, and documentation updates will be permitted.
|
266 | 468 |
|
267 | 469 | #### Landing semver-minor commits in LTS
|
|
0 commit comments