facebook/reactMITd083ec1Report / request removal

Release, Build & Lint Scripts

The scripts/ directory contains repository-specific transforms and helpers around testing, release builds, version checks, and linting. The excerpts show custom Babel plugins alongside scripts that delegate to Babel or ESLint.

These tools make one source tree usable across different test environments and release workflows: tests can be gated by React version or feature conditions, while lint and release commands provide repeatable entry points.

Sources: scripts/babel/transform-react-version-pragma.js:8-111, scripts/jest/preprocessor.js:36-51, scripts/tasks/eslint.js:10-25

Core concepts

Custom Babel transforms

A custom Babel transform is repository code that visits test expressions and rewrites them into calls understood by the test harness. The version transform returns an ExpressionStatement visitor, while the gate transform implements its own ExpressionStatement method.

Sources: scripts/babel/transform-react-version-pragma.js:52-110, scripts/babel/transform-test-gate-pragma.js:271-331

Test pragma

A test pragma is a comment associated with a test call; getComments reads Babel comments or reconstructs adjacent comments from source ranges for Hermes AST input.

Sources: scripts/babel/getComments.js:10-28

Version gate

A version gate is a semver condition attached to a test through an @reactVersion comment, with the active version read from process.env.REACT_VERSION.

Sources: scripts/babel/transform-react-version-pragma.js:11-21, scripts/babel/transform-react-version-pragma.js:22-49

Environment gate

An environment gate is a restricted expression written after @gate; the plugin parses names, booleans, strings, equality, conjunction, disjunction, and parentheses into a Babel expression.

Sources: scripts/babel/transform-test-gate-pragma.js:10-25, scripts/babel/transform-test-gate-pragma.js:141-239

Off-the-shelf tooling

Off-the-shelf tooling handles general language and module transformations, while repository-specific plugins handle React test semantics. The Jest preprocessor installs CommonJS transformation, the infinite-loop transform, the test-gate transform, and block-scoping transformation.

Sources: scripts/jest/preprocessor.js:36-51

How test files are transformed

The Jest preprocessor registers the custom transforms alongside standard Babel plugins when processing tests. The supplied excerpts do not show the implementation of transform-prevent-infinite-loops, so its exact source-level rewrite cannot be established. What is visible is that the transform defines separate limits of 6000 source iterations and 5000 test iterations.

The runtime excerpt separately describes React’s nested-update protection and its “Maximum update depth exceeded” diagnostic, but it does not identify the Babel rewrite.

The gate transform follows this visible path from a pragma to a test wrapper:

Test gate transformation — How does an @gate comment become a gated test call?

Evidence

buildGateCondition scans comments for @gate , parses each condition with ctx as the identifier, and combines multiple conditions with logical &&. The visitor changes test, it, or fit into _test_gate or _test_gate_focus and prepends an arrow function receiving ctx. For test.only and it.only, it creates _test_gate_focus with the same context callback and original arguments.

The parser maps a name such as flag to ctx.flag, preserves string and boolean literals, and recursively handles parenthesized expressions. Unary ! is handled before primary expressions. Logical && and || become logical-expression nodes, while == and != become binary-expression nodes.

Sources: scripts/jest/preprocessor.js:36-55, scripts/babel/transform-prevent-infinite-loops.js:16, scripts/babel/transform-prevent-infinite-loops.js:19, packages/react-reconciler/src/ReactFiberWorkLoop.js:5242-5253, scripts/babel/transform-test-gate-pragma.js:241-266, scripts/babel/transform-test-gate-pragma.js:271-297, scripts/babel/transform-test-gate-pragma.js:301-322, scripts/babel/transform-test-gate-pragma.js:203-231, scripts/babel/transform-test-gate-pragma.js:191-201, scripts/babel/transform-test-gate-pragma.js:145-189

How React-version tests are selected

The version transform gathers adjacent comments and builds one string literal from comments beginning with @reactVersion . Multiple matching comments are concatenated with spaces.

For ordinary test, it, and fit calls, a matching pragma changes the callee name and inserts the version condition as the first argument. Focused fit becomes _test_react_version_focus; the other calls become _test_react_version. Without a matching pragma, an active REACT_VERSION_ENV changes the call to _test_ignore_for_react_version.

For test.only and it.only, a matching pragma replaces the member call with _test_react_version_focus; without a pragma, an active REACT_VERSION_ENV replaces it with _test_ignore_for_react_version.

The central rewrite is visible here:

if (condition !== null) {
  callee.name =
    callee.name === 'fit'
      ? '_test_react_version_focus'
      : '_test_react_version';
  expression.arguments = [condition, ...expression.arguments];
} else if (REACT_VERSION_ENV) {
  callee.name = '_test_ignore_for_react_version';
}

The transform preserves the test body and changes the call shape so the test harness can apply the version condition or ignore the test for the active version.

The version visitor’s call order is:

Version pragma handling — How does a version pragma reach the rewritten test call?

Evidence

Sources: scripts/babel/transform-react-version-pragma.js:22-49, scripts/babel/getComments.js:10-28, scripts/babel/transform-react-version-pragma.js:63-77, scripts/babel/transform-react-version-pragma.js:81-101, scripts/babel/transform-react-version-pragma.js:67-77

Where custom tooling meets Babel and ESLint

The repository-specific transforms sit inside Babel’s Jest preprocessing path beside standard Babel plugins rather than replacing them. The local TypeScript Babel configuration also uses standard syntax, Flow, class, private-method, environment, and TypeScript plugins.

Linting has a separate entry point. scripts/tasks/eslint.js parses command-line arguments with minimist, calls runESLint with onlyChanged: false, reports success or failure, and exits with status 1 on failure. The shown wrapper does not expose the internal implementation of runESLint, so it does not establish the repository’s complete ESLint configuration.

Release scripts are thin orchestration layers in the shown excerpts. build-release-locally.js is an escape hatch for special-case manual builds, optimized for speed and simplicity rather than running all CI tests. The version-update command delegates to updateVersionsForNext and wraps it with logPromise.

Sources: scripts/jest/preprocessor.js:36-51, babel.config-ts.js:6-17, scripts/tasks/eslint.js:10-25, scripts/release/build-release-locally.js:5-17, scripts/release/build-release-locally-commands/update-version-numbers.js:5-12

How it connects

Jest’s preprocessor connects test source to the custom Babel transforms and to Node-compatible CommonJS output. For the broader build and test lifecycle, start with Build, Test, and Feature Flags.

The Babel transforms provide the test-level gating mechanism; the harness that consumes _test_gate, _test_react_version, and related helper calls is not included in the supplied excerpts. For surrounding test configuration and gate pragmas, continue to Jest Test Infrastructure.

Linting is invoked through a dedicated task that delegates to runESLint, while Babel handles syntax and module transforms. For the lint rules that analyze hooks, see ESLint Plugin: react-hooks.

Release-local scripts are explicitly separate from the typical CI-artifact release path described in their comments. For artifact preparation and publishing, continue to Release & Publishing Pipeline.

Sources: scripts/jest/preprocessor.js:36-51, scripts/tasks/eslint.js:10-25

Key takeaways

  • The exact infinite-loop Babel rewrite is not shown; only its Jest registration and iteration limits are established.
  • @gate expressions become context callbacks passed to _test_gate or _test_gate_focus.
  • @reactVersion conditions become version-aware test calls, with special handling for focused tests and test.only.
  • Custom transforms handle React-specific test semantics, while Babel and ESLint provide general transformation and linting infrastructure.

Sources: scripts/babel/transform-prevent-infinite-loops.js:16, scripts/babel/transform-prevent-infinite-loops.js:19, scripts/babel/transform-test-gate-pragma.js:241-266, scripts/jest/preprocessor.js:36-51, scripts/tasks/eslint.js:10-25

Want this for your repos?

Try Angada AI Wiki