Known patches
Contents
- node-babel7 8
- builtins 3
- chalk 5
- coffeescript 2
- cosmi-config 7
- crypto-random-string 3
- execa 6
- formidable 3
- is-plain-object 5
- jest 29
- js-tokens 6
- js-yaml 4
- mime 2
- minimatch 9
- mkdirp 1
- path-to-regex 6 (also express)
- readable-stream 3
- regenerate-unicode-properties 10
- rollup 3
- schema-utils 3
- semver 7
- signal-exit 4
- sinon 21 / @sinonjs/fake-timers >= 13
- yargs 15
node-babel7 8
Babel 8 is ESM-only, dropped its stage-4 plugins and changed several defaults. Beware: two of those changes are silent — the build stays green while the shipped output changes. On any package that publishes a bundle, compare the new binary with the one in the archive (dpkg-deb -x both trees, then diff -rq).
Silent output changes
preset-env without targets no longer compiles to ES5. It falls back to the browserslist defaults query where Babel 7 transpiled everything, so published bundles suddenly contain const, arrows and classes. { ie: '11' } is the equivalent of Babel 7's "no target":
modules: "auto" now keeps the ES modules when the babeljs CLI is used, because the CLI advertises supportsStaticESM. dist/ stops being requirable (Cannot use import statement outside a module, or ERR_MODULE_NOT_FOUND on a dependency). Set "modules": "commonjs" explicitly, or pass --plugins @babel/plugin-transform-modules-commonjs on the command line. Note that package.json's "babel" key is ignored in Babel 8: move the config to babel.config.json.
loose → assumptions
loose and spec are now errors on preset-env (they are merely deprecated on the individual plugins, no need to touch those). The exact expansion is a root-level assumptions block — not preset options:
1 assumptions: {
2 constantReexports: true, constantSuper: true, enumerableModuleMeta: true,
3 ignoreFunctionLength: true, ignoreToPrimitiveHint: true, iterableIsArray: true,
4 mutableTemplateObject: true, noClassCalls: true, noDocumentAll: true,
5 noIncompleteNsImportDetection: true, noNewArrows: true,
6 objectRestNoSymbols: true, privateFieldsAsProperties: true, pureGetters: true,
7 setClassMethods: true, setComputedProperties: true, setPublicClassFields: true,
8 setSpreadProperties: true, skipForOfIteratorClosing: true,
9 superIsCallableConstructor: true
10 }
Two traps here:
arrayLikeIsIterable and iterableIsArray are incompatible: loose maps to the latter, omit the former.
loose also disabled transform-typeof-symbol, and no assumption covers it. On top of the assumptions, exclude it explicitly or the _typeof helper appears in the output:
assumptions are global and leak into explicitly listed plugins. A package that had loose on preset-env but listed @babel/plugin-transform-object-rest-spread separately had a strict spread; drop objectRestNoSymbols / setSpreadProperties / iterableIsArray in that case.
Removed options
bugfixes on preset-env (bugfix plugins are always on now)
allowDeclareFields on plugin-transform-typescript (always on) — Babel 8 only, needs node-babel7 (>= 8~)
useESModules, regenerator and helpers on plugin-transform-runtime
isTSX and allExtensions on preset-typescript (see ignoreExtensions)
Removed and renamed plugins
the stage-4 @babel/plugin-proposal-* are renamed @babel/plugin-transform-* (class-properties, class-static-block, private-methods, numeric-separator, logical-assignment-operators, nullish-coalescing-operator, optional-chaining, export-namespace-from, dynamic-import, object-rest-spread); most are covered by preset-env and can simply be dropped
@babel/plugin-syntax-import-assertions → @babel/plugin-syntax-import-attributes
these @babel/plugin-syntax-* still ship, but as their last Babel 7 release, and so declare assertVersion(7): async-generators, bigint, class-properties, class-static-block, dynamic-import, import-meta, json-strings, logical-assignment-operators, nullish-coalescing-operator, numeric-separator, object-rest-spread, optional-catch-binding, optional-chaining, private-property-in-object, top-level-await. Drop them, the syntax is standard. Nothing fails at build time — require() succeeds — and the run-time error does not name the culprit: "Requires Babel "7.x-0", but was loaded with "8.0.1"". @babel/plugin-syntax-import-attributes is not in that list (it declares ^7.22.0 || ^8.0.0-0): keep it
@babel/plugin-transform-object-assign and @babel/highlight are gone without a successor — remove them from debian/nodejs/extlinks too, otherwise dh_auto_configure fails with "is required by debian/nodejs/extlinks but not available"
helpers: @babel/helper-split-export-declaration → path.splitExportDeclaration(), @babel/helper-function-name → path.ensureFunctionName(false)
plugin-proposal-decorators
The legacy boolean is gone, and version dropped the dated proposal revisions: 'legacy' and '2023-11' are the only values left, so '2021-12', '2022-03', '2023-01' and '2023-05' all have to move to '2023-11'. Both forms fail on the first transform, not at build time:
The decorators plugin requires a 'version' option, whose value must be one of: '2023-11' or 'legacy'. The '.version' option must be one of 'legacy' or '2023-11'.
preset-typescript: type-only imports are kept
onlyRemoveTypeImports used to default to false (a specifier only used in a type position, and the whole import once empty, were dropped); it now defaults to true. A declarations-only package is therefore really loaded (Cannot find module '@types/…'), and a type-only import cycle becomes a real one (Class extends value undefined is not a constructor or null, or a TDZ after rollup reorders the modules).
Per-file alternative: turn the offending imports into import type.
preset-react
the default runtime went from classic to automatic: JSX now compiles to react/jsx-runtime imports instead of React.createElement, which breaks bundles whose config does not declare that dependency. Use ['@babel/preset-react', { runtime: 'classic' }] for a faithful port.
preset-react pulls in syntax-jsx unconditionally, and that now wins over the ?TypeScript extension detection: a generic arrow function in a .ts file is parsed as JSX (Unexpected token >. Did you mean > ?). Move the preset to an override that skips .ts:
Sourcemaps
Mappings are no longer named: where Babel 7 carried the original identifier, Babel 8 leaves name at null. Harmless at run time, but any test comparing a whole mapping fails - update the fixtures, not the code.
API
transform() and loadPartialConfig() require a callback: use transformSync() / loadPartialConfigSync()
plugins doing api.assertVersion(7) must be widened to api.assertVersion('^7.0.0-0 || ^8.0.0-0')
Babel 8 is ESM: import * as babel from '@babel/core' (no default export), and require('@babel/register') yields the namespace — call .default on it
removed from @babel/traverse's NodePath: visit(), pushContext(), popContext(); node builders are lowercase-first
@babel/types tightened its unions: MemberExpression#object is Expression | Super, LVal no longer covers RestElement/AssignmentPattern (they moved to PatternLike, along with the new VoidPattern), and ClassDeclaration#id is nullable
@babel/parser merged some tokens: ... , ...${ and #name` replace the old sequences
No longer pulled in
Babel 8 dropped its lodash, source-map and source-map-support dependencies. Any package relying on them being installed transitively must build-depend on them (with the <!nocheck> profile and a TAB + test marker in debian/nodejs/extlinks when they are only needed by the test suite) and add them to Depends when they are used at run time.
Finally, when a CommonJS bundle is produced with esbuild, import.meta is replaced by an empty object and Babel 8's createRequire(import.meta.url) receives undefined; define it back:
--define:import.meta.url=__fileUrl \
--banner:js="const __fileUrl = require('url').pathToFileURL(__filename).href;"
builtins 3
chalk 5
node-chalk provides 2 distinct API:
- ES API which is chalk@5
CommonJS API which is both compatible with chalk@4 and chalk@5 (done to help during transition) with some changes
1 @@ -2,7 +2,7 @@
2 const EventEmitter = require('events')
3 const { resolve, dirname, join } = require('path')
4 const Config = require('@npmcli/config')
5 -const chalk = require('chalk')
6 +const {Chalk} = require('chalk')
7 const which = require('which')
8 const fs = require('fs/promises')
9
10 @@ -352,7 +352,7 @@
11 if (!this.color) {
12 level = 0
13 }
14 - this.#chalk = new chalk.Instance({ level })
15 + this.#chalk = new Chalk({ level })
16 }
17 return this.#chalk
18 }
This works well except during typescript transpilation. For package that needs chalk@4 typescript declarations, a workaround can be to install in node_modules (for dh-sequence-nodejs packages: in debian/build_modules) a forged @types/chalk and drop node_modules/chalk link.
download chalk@^4 and copy index.d.ts
create @types/chalk/package.json with this content:
coffeescript 2
See http://coffeescript.org/v2/#breaking-changes-super-this
cosmi-config 7
1 - const config = require('cosmiconfig')
2 - opts = config('postcss', options)
3 + const {cosmiconfig} = require('cosmiconfig')
4 + opts = cosmiconfig('postcss', options)
5
6 - const config = require('cosmiconfig')
7 - const result = config('postcss', options).searchSync(path)
8 + const {cosmiconfigSync} = require('cosmiconfig')
9 + const result = cosmiconfigSync('postcss', options).search(path)
10
crypto-random-string 3
execa 6
formidable 3
is-plain-object 5
- const isPlainObject = require('is-plain-object');
+ const {isPlainObject} = require('is-plain-object');
jest 29
Snapshot format changed with jest 29. To go back to previous format, simply add this in package.json
See https://jestjs.io/docs/upgrading-to-jest29 for more
js-tokens 6
js-token was a regex until version 6, then a function.
js-yaml 4
mime 2
Version 2 is a breaking change from 1.x. Specifically:
lookup() renamed to getType()
extension() renamed to getExtension()
charset() and load() methods have been removed
minimatch 9
mkdirp 1
path-to-regex 6 (also express)
- pathToRegex('*')
+ pathToRegex('(*)')
+ // OR
+ pathToRegex(':foo*')In express:
- app.get("*", ...args)
+ app.get("(*)", ...args)
readable-stream 3
regenerate-unicode-properties 10
rollup 3
"rollup 3" no longer accepts hybrid ES/CJS configuration files. Example:
1 --- a/rollup.config.js
2 +++ b/rollup.config.js
3 @@ -1,7 +1,7 @@
4 -import buble from 'rollup-plugin-buble';
5 -import pkg from './package.json';
6 +const buble = require('rollup-plugin-buble');
7 +const pkg = require('./package.json');
8
9 -export default {
10 +module.exports = {
11 input: 'src/index.js',
12
13 external: [
schema-utils 3
- const validateOptions = require("schema-utils");
+ const validateOptions = require("schema-utils").validate;
- import validateOptions from 'schema-utils';
+ import { validate as validateOptions } from 'schema-utils';
semver 7
signal-exit 4
sinon 21 / @sinonjs/fake-timers >= 13
Important: setImmediate must remain in the toFake list. Undici (and other libraries) use setImmediate in their callback chains, and clock.tick() needs to process these for tests to complete.
