diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts index 05a4b4b91f557..2bccda3a2e930 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts @@ -184,25 +184,28 @@ function validateNoContextVariableAssignment( fn: HIRFunction, errors: CompilerError, ): void { + const context = new Set(fn.context.map(place => place.identifier.id)); for (const block of fn.body.blocks.values()) { for (const instr of block.instructions) { const value = instr.value; switch (value.kind) { case 'StoreContext': { - errors.pushDiagnostic( - CompilerDiagnostic.create({ - category: ErrorCategory.UseMemo, - reason: - 'useMemo() callbacks may not reassign variables declared outside of the callback', - description: - 'useMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function', - suggestions: null, - }).withDetails({ - kind: 'error', - loc: value.lvalue.place.loc, - message: 'Cannot reassign variable', - }), - ); + if (context.has(value.lvalue.place.identifier.id)) { + errors.pushDiagnostic( + CompilerDiagnostic.create({ + category: ErrorCategory.UseMemo, + reason: + 'useMemo() callbacks may not reassign variables declared outside of the callback', + description: + 'useMemo() callbacks must be pure functions and cannot reassign variables defined outside of the callback function', + suggestions: null, + }).withDetails({ + kind: 'error', + loc: value.lvalue.place.loc, + message: 'Cannot reassign variable', + }), + ); + } break; } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.expect.md new file mode 100644 index 0000000000000..29dc3afcd6fe8 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.expect.md @@ -0,0 +1,45 @@ + +## Input + +```javascript +// @flow +export hook useItemLanguage(items) { + return useMemo(() => { + let language: ?string = null; + items.forEach(item => { + if (item.language != null) { + language = item.language; + } + }); + return language; + }, [items]); +} + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +export function useItemLanguage(items) { + const $ = _c(2); + let language; + if ($[0] !== items) { + language = null; + items.forEach((item) => { + if (item.language != null) { + language = item.language; + } + }); + $[0] = items; + $[1] = language; + } else { + language = $[1]; + } + return language; +} + +``` + +### Eval output +(kind: exception) Fixture not implemented \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.js new file mode 100644 index 0000000000000..4ed89bfc64337 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/reassign-variable-in-usememo.js @@ -0,0 +1,12 @@ +// @flow +export hook useItemLanguage(items) { + return useMemo(() => { + let language: ?string = null; + items.forEach(item => { + if (item.language != null) { + language = item.language; + } + }); + return language; + }, [items]); +} diff --git a/packages/react-devtools-core/package.json b/packages/react-devtools-core/package.json index c8facd1a24d46..54b89e72e8ae5 100644 --- a/packages/react-devtools-core/package.json +++ b/packages/react-devtools-core/package.json @@ -1,6 +1,6 @@ { "name": "react-devtools-core", - "version": "7.0.0", + "version": "7.0.1", "description": "Use react-devtools outside of the browser", "license": "MIT", "main": "./dist/backend.js", diff --git a/packages/react-devtools-extensions/chrome/manifest.json b/packages/react-devtools-extensions/chrome/manifest.json index 0b5285e91a95a..9bb0ab1177ac4 100644 --- a/packages/react-devtools-extensions/chrome/manifest.json +++ b/packages/react-devtools-extensions/chrome/manifest.json @@ -2,8 +2,8 @@ "manifest_version": 3, "name": "React Developer Tools", "description": "Adds React debugging tools to the Chrome Developer Tools.", - "version": "7.0.0", - "version_name": "7.0.0", + "version": "7.0.1", + "version_name": "7.0.1", "minimum_chrome_version": "114", "icons": { "16": "icons/16-production.png", diff --git a/packages/react-devtools-extensions/edge/manifest.json b/packages/react-devtools-extensions/edge/manifest.json index 342af4abb3a43..55b7248f255bf 100644 --- a/packages/react-devtools-extensions/edge/manifest.json +++ b/packages/react-devtools-extensions/edge/manifest.json @@ -2,8 +2,8 @@ "manifest_version": 3, "name": "React Developer Tools", "description": "Adds React debugging tools to the Microsoft Edge Developer Tools.", - "version": "7.0.0", - "version_name": "7.0.0", + "version": "7.0.1", + "version_name": "7.0.1", "minimum_chrome_version": "114", "icons": { "16": "icons/16-production.png", diff --git a/packages/react-devtools-extensions/firefox/manifest.json b/packages/react-devtools-extensions/firefox/manifest.json index bc12ac0fcde26..f401708c21704 100644 --- a/packages/react-devtools-extensions/firefox/manifest.json +++ b/packages/react-devtools-extensions/firefox/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "React Developer Tools", "description": "Adds React debugging tools to the Firefox Developer Tools.", - "version": "7.0.0", + "version": "7.0.1", "browser_specific_settings": { "gecko": { "id": "@react-devtools", diff --git a/packages/react-devtools-extensions/src/main/cloneStyleTags.js b/packages/react-devtools-extensions/src/main/cloneStyleTags.js index dd84e01fc9ef8..caad2a361caa4 100644 --- a/packages/react-devtools-extensions/src/main/cloneStyleTags.js +++ b/packages/react-devtools-extensions/src/main/cloneStyleTags.js @@ -1,5 +1,14 @@ -function cloneStyleTags() { - const linkTags = []; +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export function cloneStyleTags(): Array { + const tags: Array = []; // eslint-disable-next-line no-for-of-loops/no-for-of-loops for (const linkTag of document.getElementsByTagName('link')) { @@ -11,11 +20,23 @@ function cloneStyleTags() { newLinkTag.setAttribute(attribute.nodeName, attribute.nodeValue); } - linkTags.push(newLinkTag); + tags.push(newLinkTag); } } - return linkTags; -} + // eslint-disable-next-line no-for-of-loops/no-for-of-loops + for (const styleTag of document.getElementsByTagName('style')) { + const newStyleTag = document.createElement('style'); + + // eslint-disable-next-line no-for-of-loops/no-for-of-loops + for (const attribute of styleTag.attributes) { + newStyleTag.setAttribute(attribute.nodeName, attribute.nodeValue); + } -export default cloneStyleTags; + newStyleTag.textContent = styleTag.textContent; + + tags.push(newStyleTag); + } + + return tags; +} diff --git a/packages/react-devtools-extensions/src/main/index.js b/packages/react-devtools-extensions/src/main/index.js index cec9fd6df454f..bc948d1e6d6c9 100644 --- a/packages/react-devtools-extensions/src/main/index.js +++ b/packages/react-devtools-extensions/src/main/index.js @@ -33,7 +33,7 @@ import { import {viewAttributeSource} from './sourceSelection'; import {startReactPolling} from './reactPolling'; -import cloneStyleTags from './cloneStyleTags'; +import {cloneStyleTags} from './cloneStyleTags'; import fetchFileWithCaching from './fetchFileWithCaching'; import injectBackendManager from './injectBackendManager'; import registerEventsLogger from './registerEventsLogger'; diff --git a/packages/react-devtools-extensions/utils.js b/packages/react-devtools-extensions/utils.js index 3b06bb71f7d4e..9f02e98d19883 100644 --- a/packages/react-devtools-extensions/utils.js +++ b/packages/react-devtools-extensions/utils.js @@ -6,7 +6,7 @@ */ const {execSync} = require('child_process'); -const {readFileSync} = require('fs'); +const {existsSync, readFileSync} = require('fs'); const {resolve} = require('path'); const GITHUB_URL = 'https://github.com/facebook/react'; @@ -18,8 +18,26 @@ function getGitCommit() { .trim(); } catch (error) { // Mozilla runs this command from a git archive. - // In that context, there is no Git revision. - return null; + // In that context, there is no Git context. + // Using the commit hash specified to download-experimental-build.js script as a fallback. + + // Try to read from build/COMMIT_SHA file + const commitShaPath = resolve(__dirname, '..', '..', 'build', 'COMMIT_SHA'); + if (!existsSync(commitShaPath)) { + throw new Error( + 'Could not find build/COMMIT_SHA file. Did you run scripts/release/download-experimental-build.js script?', + ); + } + + try { + const commitHash = readFileSync(commitShaPath, 'utf8').trim(); + // Return short hash (first 7 characters) to match abbreviated commit hash format + return commitHash.slice(0, 7); + } catch (readError) { + throw new Error( + `Failed to read build/COMMIT_SHA file: ${readError.message}`, + ); + } } } diff --git a/packages/react-devtools-extensions/webpack.config.js b/packages/react-devtools-extensions/webpack.config.js index 4592363c64a91..191eabc47cbf9 100644 --- a/packages/react-devtools-extensions/webpack.config.js +++ b/packages/react-devtools-extensions/webpack.config.js @@ -285,7 +285,7 @@ module.exports = { { loader: 'css-loader', options: { - sourceMap: true, + sourceMap: __DEV__, modules: true, localIdentName: '[local]___[hash:base64:5]', }, diff --git a/packages/react-devtools-inline/package.json b/packages/react-devtools-inline/package.json index 0363530cd1025..cc5fc51a6ef6c 100644 --- a/packages/react-devtools-inline/package.json +++ b/packages/react-devtools-inline/package.json @@ -1,6 +1,6 @@ { "name": "react-devtools-inline", - "version": "7.0.0", + "version": "7.0.1", "description": "Embed react-devtools within a website", "license": "MIT", "main": "./dist/backend.js", diff --git a/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.css b/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.css index bd13a89c6c901..98200ee9dfd30 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.css @@ -3,8 +3,9 @@ } .CallSite, .BuiltInCallSite { - display: block; + display: flex; padding-left: 1rem; + white-space-collapse: preserve; } .IgnoredCallSite, .BuiltInCallSite { @@ -20,13 +21,15 @@ white-space: pre; overflow: hidden; text-overflow: ellipsis; - flex: 1; cursor: pointer; border-radius: 0.125rem; - padding: 0px 2px; } .Link:hover { background-color: var(--color-background-hover); } +.ElementBadges { + margin-left: 0.25rem; +} + diff --git a/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.js b/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.js index d3d797f78103f..a3cf91f14b77e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/StackTraceView.js @@ -86,8 +86,10 @@ export function CallSiteView({ )} - - + ); } diff --git a/packages/react-devtools-timeline/package.json b/packages/react-devtools-timeline/package.json index 2f54399ce25d5..5e4df8355267e 100644 --- a/packages/react-devtools-timeline/package.json +++ b/packages/react-devtools-timeline/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "react-devtools-timeline", - "version": "7.0.0", + "version": "7.0.1", "license": "MIT", "dependencies": { "@elg/speedscope": "1.9.0-a6f84db", diff --git a/packages/react-devtools/CHANGELOG.md b/packages/react-devtools/CHANGELOG.md index 0fc637b9946f9..6c3ab1baf07eb 100644 --- a/packages/react-devtools/CHANGELOG.md +++ b/packages/react-devtools/CHANGELOG.md @@ -4,6 +4,15 @@ --- +### 7.0.1 +October 20, 2025 + +* Various UI improvements to experimental Suspense tab ([sebmarkbage](https://github.com/sebmarkbage) & [eps1lon](https://github.com/eps1lon)) +* devtools: fix ellipsis truncation for key values ([sophiebits](https://github.com/sophiebits) in [#34796](https://github.com/facebook/react/pull/34796)) +* fix(devtools): remove duplicated "Display density" field in General settings ([Anatole-Godard](https://github.com/Anatole-Godard) in [#34792](https://github.com/facebook/react/pull/34792)) + +--- + ### 7.0.0 Oct 2, 2025 diff --git a/packages/react-devtools/package.json b/packages/react-devtools/package.json index ea8bab1c95e5a..3d1a1bda2f3c7 100644 --- a/packages/react-devtools/package.json +++ b/packages/react-devtools/package.json @@ -1,6 +1,6 @@ { "name": "react-devtools", - "version": "7.0.0", + "version": "7.0.1", "description": "Use react-devtools outside of the browser", "license": "MIT", "repository": { @@ -26,7 +26,7 @@ "electron": "^23.1.2", "internal-ip": "^6.2.0", "minimist": "^1.2.3", - "react-devtools-core": "7.0.0", + "react-devtools-core": "7.0.1", "update-notifier": "^2.1.0" } }