react changelog


Welcome to the latest round of updates! We've been busy bees, buzzing around making improvements, squashing bugs, and adding cool new features to make your experience even better. Here's what's new:

New Features

  • Flight Prerendering with enableHalt: ๐Ÿš€ We've introduced the enableHalt feature for flight prerenders, allowing aborts to be treated as indefinitely stalled rather than errors. This makes the system more robust and user-friendly by pausing serialization for async data types when accessed by the client.
  • Dynamic Module Type Resolution: ๐Ÿ”„ A new environment configuration option lets you resolve imported module types on the fly, making the compiler more flexible and efficient.
  • DevTools Owner Path Identification: ๐Ÿ•ต๏ธโ€โ™‚๏ธ Now you can find Server Component owners by traversing the parent path, improving DevTools' functionality.
  • Function Return Type Inference: ๐Ÿง  The compiler now infers return types for function expressions, enhancing type management and error handling.
  • Ref-in-Render Fixture: ๐Ÿงฉ We've added a fixture to highlight issues with refs in render when using useCallback, improving documentation and testing.

Improvements

  • Ref Access Flexibility: ๐Ÿ”ง Functions containing refs can now be returned, offering more flexibility, especially in hooks.
  • Compiler Return Identifier: ๐Ÿท๏ธ We've added a returnIdentifier to function expressions for better type information management.
  • Ref Mutability Handling: ๐Ÿ”’ Refs and their .current values are now excluded from having mutable ranges, preserving memoization integrity.

Bugfixes

  • Rendering Aborts and Throws: ๐Ÿ› ๏ธ Fixed an issue where errors thrown after aborting a render were mishandled, ensuring proper error tracking and robustness.
  • Flight Halted Row Reversion: ๐Ÿ”„ We reverted the halted row feature in Flight, simplifying promise handling.
  • Turbopack Unbundled Removal: ๐Ÿ—‘๏ธ Removed the unbundled RSC prototype from Turbopack, focusing on integrated server/client experiences.

Chore

  • CI Configuration Cleanup: ๐Ÿงน Removed the CI_MAX_WORKERS option from Flow configurations as part of our migration to GitHub Actions.

That's all for now, folks! Keep exploring, keep building, and stay tuned for more exciting updates coming your way. ๐ŸŽ‰

Included Commits

2024-08-16T17:27:13 See commit

This commit addresses the treatment of refs and their associated values in React's compiler by excluding them from having mutable ranges. Previously, refs were incorrectly treated as mutable, which could lead to unintended consequences, such as extending the mutable range of other values through aliasing and disrupting memoization. The changes implemented in this pull request ensure that refs and their .current values are recognized as stable, thereby maintaining the integrity of memoization and preventing potential issues during rendering.

The modifications involve the introduction of a new function, isRefOrRefValue, which consolidates checks for refs and ref values. This function is then utilized throughout various parts of the compiler, particularly in areas that infer mutable lifetimes and ranges. Additionally, the commit includes updates to error handling, ensuring that accessing ref values during render will trigger appropriate validation errors. Overall, this change enhances the reliability of React's memoization mechanisms by clearly defining the behavior of refs in the context of mutability.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableLifetimes.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableRangesForAlias.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts
  • compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccesInRender.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.js
2024-08-16T17:27:13 See commit

This commit introduces a fixture to demonstrate an enforcement issue related to the use of refs within the render process when using the useCallback hook in React components. Specifically, it highlights that accessing the current property of a ref during render is invalid, which can lead to complications when useCallback is employed. The added test cases illustrate scenarios where this issue arises, providing clear error messages to guide developers in adhering to the correct usage patterns for refs and callbacks.

The commit includes several new test files that showcase the problem, including a function component Foo that attempts to return a callback that accesses a ref. The tests are designed to validate the enforcement of rules around ref access during render, ensuring that developers are aware of the restrictions imposed by React's rendering behavior. This addition serves to enhance the documentation and testing framework surrounding the use of refs and callbacks in React, ultimately contributing to better code quality and adherence to best practices.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.return-ref-callback.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.return-ref-callback.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-ref-in-render.js
2024-08-16T17:27:13 See commit

This commit updates the React compiler to allow functions that access refs to be returned, addressing a previous limitation that strictly prohibited such behavior. The change recognizes that returning functions accessing refs can be valid, particularly in the context of hooks where their return values may only be utilized in event handlers or effects. The commit modifies the validation logic within the compiler to permit this functionality while ensuring that direct access to ref values remains restricted during render.

The changes include the removal of outdated test fixtures that enforced the previous restriction and the addition of new tests that validate the updated behavior. The validation logic has been adjusted to allow functions containing refs to be returned, while still preventing direct access to the current property of refs during render, thereby maintaining the integrity of React's rendering rules. Overall, this commit enhances the flexibility of the React API regarding ref usage in functional components.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccesInRender.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.return-ref-callback.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/return-ref-callback.js
2024-08-16T21:21:57 See commit

This commit introduces a new feature called enableHalt for flight prerenders, allowing aborts to be treated as indefinitely stalled outcomes rather than resulting in errors. When enableHalt is activated, the serialization process for regular tasks is modified to create a promise that never settles. For asynchronous data types like ReadableStreams, Blobs, and Async Iterators, the serialization is paused, leaving them in an unfinished state when accessed by the client. This enhancement aims to improve the handling of prerender aborts, making the system more robust and user-friendly.

Furthermore, when a prerender is aborted with enableHalt enabled, the abort reason is communicated back to the upstream producers of the affected async iterators, blobs, and streams. The commit also lays the groundwork for potential future features that would allow developers to consume a signal within a render to cancel additional tasks, with the abort reason being forwarded accordingly. Various files across the React server and testing packages were modified to implement this feature, reflecting its integration into the broader React ecosystem.

Files changed

  • packages/react-server-dom-esm/src/server/ReactFlightDOMServerNode.js
  • packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerBrowser.js
  • packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js
  • packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
  • packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
  • packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
  • packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMNode-test.js
  • packages/react-server-dom-webpack/src/server/ReactFlightDOMServerBrowser.js
  • packages/react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js
  • packages/react-server/src/ReactFlightServer.js
  • packages/shared/ReactFeatureFlags.js
  • packages/shared/forks/ReactFeatureFlags.native-fb.js
  • packages/shared/forks/ReactFeatureFlags.native-oss.js
  • packages/shared/forks/ReactFeatureFlags.test-renderer.js
  • packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
  • packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
  • packages/shared/forks/ReactFeatureFlags.www.js
2024-08-16T23:52:11 See commit

This commit introduces a new mechanism in React DevTools to identify owners of Server Components by traversing the parent path, as these components are not stateful and can exist in multiple places or be nested within each other. The change aims to enhance the ability to locate the appropriate instance of a Server Component by utilizing a heuristic approach that searches through the parent path, which is typically where the owner can be found. This development is a step towards eliminating the reliance on a global fiberToFiberInstance map, allowing for a more efficient and contextual lookup using the shadow tree.

While this method works well for most cases, it has limitations, particularly when dealing with complex structures like React ART trees nested within DOM trees, where owners may not be found along the parent stack. The commit notes that ideally, such trees should be represented within the DOM tree in DevTools, which would resolve this issue by maintaining a clear association between roots and their DOM parents upon mounting. Overall, the update enhances the functionality of DevTools while addressing specific edge cases that may require further refinement in future iterations.

Files changed

  • packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
  • packages/react-devtools-shared/src/backend/fiber/renderer.js
2024-08-17T01:29:18 See commit

This commit addresses an issue in the React framework where an error could be thrown after an abort signal during the rendering process, leading to improper error handling. The previous implementation utilized an AbortSigil to denote when a rendering task needed to be aborted, but throwing an error interrupted this tracking mechanism, causing errors to be handled incorrectly. The changes made in this commit rework the abort logic to ensure that throws occurring after an abort are managed correctly, enhancing the robustness of the rendering process.

The modifications include updates to both the test suite and the core rendering logic. A new test has been added to verify that throwing an error after an abort is handled appropriately, which involves capturing the error and ensuring that the rendering status reflects the abort condition. Additionally, the core rendering functions have been adjusted to check the request's status instead of relying on the AbortSigil, thereby improving the overall error handling mechanism in scenarios where rendering is aborted. This change aims to improve the reliability of the React rendering system when faced with concurrent rendering scenarios involving aborts and throws.

Files changed

  • packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
  • packages/react-server/src/ReactFizzServer.js
2024-08-19T20:34:38 See commit

This commit reverts a previous change related to handling "halted rows" in the React Flight framework, specifically the implementation of an infinite promise that never resolves. The developers decided against maintaining this halted row functionality, indicating that it was not a desirable feature after all. The reversion affects several files, including modifications to the handling of promises within the ReactFlightClient.js and ReactFlightServer.js files.

In the updated code, the handling of promise states has been simplified. The commit removes the logic for creating an infinite promise and instead focuses on resolving blocked responses only if a specific feature flag (enableHalt) is enabled. Additionally, some test cases were adjusted to reflect these changes, including the removal of expectations related to the promise's status being 'blocked.' Overall, this reversion aims to streamline promise handling in the React Flight architecture.

Files changed

  • packages/react-client/src/ReactFlightClient.js
  • packages/react-client/src/__tests__/ReactFlight-test.js
  • packages/react-server/src/ReactFlightServer.js
2024-08-20T15:05:49 See commit

This commit removes the CI_MAX_WORKERS option from the Flow configuration files in the React repository. The option was originally used in CircleCI but is no longer necessary now that the project has transitioned to GitHub Actions for continuous integration. The change simplifies the configuration by eliminating outdated settings that are no longer relevant to the current CI environment.

Specifically, the commit modifies two files: flowconfig and createFlowConfigs.js. In flowconfig, the line referencing CI_MAX_WORKERS has been deleted, while createFlowConfigs.js has had the corresponding code that replaced this placeholder with a specific value removed. Overall, this update reflects a clean-up of legacy code as part of the migration to a new CI system.

Files changed

  • scripts/flow/config/flowconfig
  • scripts/flow/createFlowConfigs.js
2024-08-21T13:58:31 See commit

The recent commit titled "Remove turbopack unbundled/register/loader" eliminates the unbundled version of React Server Components (RSC) from the Turbopack build. This unbundled format was primarily intended to showcase a prototype rather than serve as a functional configuration for various bundler combinations. Currently, there is no existing configuration in Turbopack that supports this mode, and it is unlikely that such support will be developed due to its focus on an integrated server/client experience.

The changes involve the removal of specific unbundled files and configurations from the react-server-dom-turbopack package, including the unbundled client and server files, as well as node register/loaders. Additionally, the package.json has been updated to reflect these removals, streamlining the package and aligning it more closely with the intended use of Turbopack. The commit also includes modifications to several test files and other related scripts to ensure consistency following the removal of the unbundled configurations.

Files changed

  • packages/react-server-dom-turbopack/esm/package.json
  • packages/react-server-dom-turbopack/node-register.js
  • packages/react-server-dom-turbopack/npm/node-register.js
  • packages/react-server-dom-turbopack/package.json
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOM-test.js
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMBrowser-test.js
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMEdge-test.js
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMNode-test.js
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReply-test.js
  • packages/react-server-dom-turbopack/src/__tests__/ReactFlightTurbopackDOMReplyEdge-test.js
  • packages/react-server-dom-turbopack/src/__tests__/utils/TurbopackMock.js
  • scripts/rollup/bundles.js
  • scripts/shared/inlinedHostConfigs.js
2024-08-21T22:45:30 See commit

This commit introduces a new configuration option for the environment that allows for a function to resolve the types of imported modules dynamically. Instead of requiring all known types to be specified upfront, this function can lazily provide TypeConfig objects based on the name of the imported module. The types can be structured as objects with valid identifier keys, functions, or references to built-in types. During type inference, the system will first attempt to resolve the module type using the getGlobalDeclaration() method, which was initially limited to known React modules. If successful, it will then attempt to access specific properties of the resolved module type.

Additionally, the commit outlines future considerations, such as implementing testing, caching module results to avoid repetitive parsing, and deciding on a strategy for handling invalid module typesโ€”suggesting that a fatal error might be preferable to indicate configuration issues. Various files related to the Babel plugin for React have been modified or added to accommodate these changes, enhancing the compiler's ability to handle imported module types more flexibly and efficiently.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts
  • compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
  • compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts
  • compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-declarations-and-locals.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/destructuring-mixed-scope-declarations-and-locals.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-logical.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-logical.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls-mutable-lambda.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls-mutable-lambda.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-in-hook.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/tagged-template-in-hook.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log-default-import.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log-default-import.tsx
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-log.tsx
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture-namespace-import.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture-namespace-import.tsx
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-provider-store-capture.tsx
  • compiler/packages/snap/src/compiler.ts
  • compiler/packages/snap/src/constants.ts
  • compiler/packages/snap/src/runner-worker.ts
  • compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts
  • compiler/packages/snap/src/sprout/shared-runtime.ts
2024-08-22T01:21:27 See commit

This commit introduces a new property called returnIdentifier to function expressions within the React compiler. The addition serves as a storage location for type information, which will be utilized in subsequent pull requests. The changes include modifications to several files, specifically enhancing the functionality of the HIR (High-Level Intermediate Representation) by integrating this new identifier into the function structure.

In terms of implementation, the returnIdentifier is created as a temporary placeholder during the function lowering process and is included in the HIRFunction type definition. This change is expected to facilitate better type management and error handling in future updates of the compiler. Additionally, the commit includes updates to error handling tests to reflect the changes made in the function return identifier logic.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md
2024-08-22T04:17:29 See commit

This commit enhances the type inference capabilities of the React compiler by allowing the inference of return types for function expressions. It utilizes a newly introduced returnIdentifier, which serves as a stable identifier for functions, enabling the compiler to establish equations in the InferTypes module to deduce return types effectively. The changes involve modifications across several files, particularly in the handling of function expressions and their return types, ensuring that the inferred types are correctly represented in the output.

In addition to the core functionality, the commit includes updates to various components of the codebase, such as adjustments in the printing of function types and improvements in the handling of reactive scopes. The updates also reflect in test cases, ensuring that the new return type inference logic is validated against expected outcomes. Overall, this commit contributes to a more robust type inference system within the React compiler, enhancing its ability to manage function expressions and their return types accurately.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts
  • compiler/packages/babel-plugin-react-compiler/src/Optimization/LowerContextAccess.ts
  • compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts
  • compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-const-declaration.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-let-declaration.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-nonescaping-invoked-callback-escaping-return.expect.md