Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) #22064

Merged
merged 5 commits into from
Sep 27, 2021

Conversation

justingrant
Copy link
Contributor

@justingrant justingrant commented Aug 10, 2021

The new Temporal date/time API (currently stage 3) will throw when calling valueOf on instances of most Temporal types. React's current pattern for converting objects to strings is '' + value, which will break when the object is a Temporal.* object because the + operator calls valueOf.

Repro: https://codesandbox.io/s/gifted-kilby-76tes?file=/src/index.js

import ReactDOM from "react-dom";
import { Temporal } from "@js-temporal/polyfill";

ReactDOM.render(
  <input defaultValue={Temporal.PlainDate.from('2021-08-16')} />,
  document.getElementById("root")
);
  • Expected: The <input> element's initial value is '2021-08-16', which is what you get by calling toString().
  • Actual: exception thrown by Temporal.PlainDate.prototype.valueOf

UPDATE: this PR has evolved. See #22064 (comment) for the latest. Instead of combing through the React codebase trying to figure out which places could possibly be concatenating strings to objects, I globally replaced all use of '' + value with String(value) (which should yield the same output but won't call valueOf) and revised the lint rule to recommend the latter pattern. I'm not sure if a global change was the best approach; happy to revise if needed. But one advantage of a global change is that it allows for a lint rule to be created later that outlaws the '' + value pattern completely.

Note that String(value) is currently disallowed by a lint rule from #9082. This PR removes that rule.

Another alternative would be to leave that lint rule in place and use .concat(value) instead, but that syntax is currently disallowed by Flow. (See comments below for details.)

See tc39/proposal-temporal#1681 (comment) for notes from @ljharb (from TC39) about this issue.

Test Plan

I added tests to cover the repro case above, in a 2x2 matrix of value and defaultValue props and type="text" and type="date" input elements. To avoid taking an unnecessary dependency on the Temporal polyfill, I used a mocked class that throws on valueOf to simulate Temporal behavior. See #22064 (comment) for latest test info.

@sizebot
Copy link

sizebot commented Aug 10, 2021

Comparing: 3746eaf...c78cc77

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.min.js = 129.82 kB 129.83 kB = 41.38 kB 41.38 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js = 132.64 kB 132.65 kB = 42.34 kB 42.33 kB
facebook-www/ReactDOM-prod.classic.js = 411.75 kB 411.77 kB = 76.25 kB 76.26 kB
facebook-www/ReactDOM-prod.modern.js = 400.32 kB 400.34 kB = 74.54 kB 74.54 kB
facebook-www/ReactDOMForked-prod.classic.js = 411.75 kB 411.77 kB = 76.25 kB 76.26 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
facebook-react-native/react/cjs/JSXDEVRuntime-dev.js +10.45% 33.24 kB 36.71 kB +11.88% 9.44 kB 10.56 kB
facebook-react-native/react/cjs/JSXRuntime-dev.js +10.26% 33.84 kB 37.31 kB +11.68% 9.61 kB 10.74 kB
oss-experimental/react/cjs/react-jsx-dev-runtime.development.js +8.85% 38.39 kB 41.78 kB +10.14% 11.08 kB 12.20 kB
oss-stable-semver/react/cjs/react-jsx-dev-runtime.development.js +8.84% 38.42 kB 41.82 kB +10.10% 11.10 kB 12.22 kB
oss-stable/react/cjs/react-jsx-dev-runtime.development.js +8.84% 38.42 kB 41.82 kB +10.10% 11.10 kB 12.22 kB
oss-experimental/react/cjs/react-jsx-runtime.development.js +8.71% 38.98 kB 42.38 kB +9.94% 11.26 kB 12.38 kB
oss-stable-semver/react/cjs/react-jsx-runtime.development.js +8.70% 39.02 kB 42.42 kB +9.91% 11.28 kB 12.39 kB
oss-stable/react/cjs/react-jsx-runtime.development.js +8.70% 39.02 kB 42.42 kB +9.91% 11.28 kB 12.39 kB
facebook-www/JSXDEVRuntime-dev.modern.js +8.09% 42.09 kB 45.49 kB +9.45% 11.75 kB 12.86 kB
facebook-www/JSXDEVRuntime-dev.classic.js +8.09% 42.09 kB 45.49 kB +9.45% 11.75 kB 12.86 kB
oss-experimental/react/cjs/react-unstable-shared-subset.development.js +5.62% 71.06 kB 75.05 kB +6.42% 19.32 kB 20.56 kB
oss-stable-semver/react/cjs/react.development.js +4.73% 84.44 kB 88.43 kB +5.51% 22.62 kB 23.86 kB
oss-stable/react/cjs/react.development.js +4.73% 84.44 kB 88.43 kB +5.51% 22.62 kB 23.86 kB
oss-experimental/react/cjs/react.development.js +4.68% 85.37 kB 89.36 kB +5.47% 22.76 kB 24.00 kB
facebook-react-native/react/cjs/React-dev.js +4.16% 100.85 kB 105.05 kB +5.26% 24.40 kB 25.68 kB
oss-stable-semver/react/umd/react.development.js +3.86% 107.98 kB 112.15 kB +4.51% 27.60 kB 28.85 kB
oss-stable/react/umd/react.development.js +3.86% 107.98 kB 112.15 kB +4.51% 27.60 kB 28.85 kB
oss-experimental/react/umd/react.development.js +3.82% 108.95 kB 113.12 kB +4.49% 27.73 kB 28.98 kB
facebook-www/React-dev.modern.js +3.77% 109.39 kB 113.52 kB +4.75% 26.73 kB 28.00 kB
facebook-www/React-dev.classic.js +3.74% 110.41 kB 114.53 kB +4.72% 26.92 kB 28.19 kB
facebook-www/ReactDOMServer-dev.classic.js +3.66% 153.21 kB 158.81 kB +3.51% 38.88 kB 40.25 kB
facebook-www/ReactDOMServer-dev.modern.js +2.32% 213.66 kB 218.62 kB +2.98% 50.31 kB 51.81 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +2.30% 211.80 kB 216.67 kB +2.85% 50.84 kB 52.28 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +2.30% 211.80 kB 216.67 kB +2.85% 50.84 kB 52.28 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +2.30% 211.90 kB 216.76 kB +2.81% 50.99 kB 52.43 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +2.30% 211.90 kB 216.76 kB +2.81% 50.99 kB 52.43 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +2.29% 212.37 kB 217.24 kB +2.84% 50.99 kB 52.44 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +2.29% 212.47 kB 217.34 kB +2.81% 51.15 kB 52.58 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.development.js +2.29% 222.70 kB 227.79 kB +2.83% 51.57 kB 53.04 kB
oss-stable/react-dom/umd/react-dom-server.browser.development.js +2.29% 222.70 kB 227.79 kB +2.83% 51.57 kB 53.04 kB
oss-experimental/react-dom/umd/react-dom-server.browser.development.js +2.28% 223.32 kB 228.41 kB +2.83% 51.73 kB 53.19 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.27% 214.46 kB 219.33 kB +2.82% 51.33 kB 52.77 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.27% 214.46 kB 219.33 kB +2.82% 51.33 kB 52.77 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.26% 215.04 kB 219.91 kB +2.80% 51.48 kB 52.93 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.development.js +2.26% 225.44 kB 230.53 kB +2.81% 51.94 kB 53.40 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.development.js +2.26% 225.44 kB 230.53 kB +2.81% 51.94 kB 53.40 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.03 kB 220.90 kB +2.79% 51.76 kB 53.20 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.03 kB 220.90 kB +2.79% 51.76 kB 53.20 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js +2.25% 226.06 kB 231.15 kB +2.80% 52.09 kB 53.55 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.61 kB 221.48 kB +2.78% 51.92 kB 53.36 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer.development.js +13.72% 36.79 kB 41.84 kB +24.81% 7.50 kB 9.36 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-persistent.development.js +13.68% 36.92 kB 41.97 kB +24.73% 7.52 kB 9.38 kB
facebook-react-native/react/cjs/JSXDEVRuntime-dev.js +10.45% 33.24 kB 36.71 kB +11.88% 9.44 kB 10.56 kB
facebook-react-native/react/cjs/JSXRuntime-dev.js +10.26% 33.84 kB 37.31 kB +11.68% 9.61 kB 10.74 kB
oss-experimental/react/cjs/react-jsx-dev-runtime.development.js +8.85% 38.39 kB 41.78 kB +10.14% 11.08 kB 12.20 kB
oss-stable-semver/react/cjs/react-jsx-dev-runtime.development.js +8.84% 38.42 kB 41.82 kB +10.10% 11.10 kB 12.22 kB
oss-stable/react/cjs/react-jsx-dev-runtime.development.js +8.84% 38.42 kB 41.82 kB +10.10% 11.10 kB 12.22 kB
oss-experimental/react/cjs/react-jsx-runtime.development.js +8.71% 38.98 kB 42.38 kB +9.94% 11.26 kB 12.38 kB
oss-stable-semver/react/cjs/react-jsx-runtime.development.js +8.70% 39.02 kB 42.42 kB +9.91% 11.28 kB 12.39 kB
oss-stable/react/cjs/react-jsx-runtime.development.js +8.70% 39.02 kB 42.42 kB +9.91% 11.28 kB 12.39 kB
facebook-www/JSXDEVRuntime-dev.modern.js +8.09% 42.09 kB 45.49 kB +9.45% 11.75 kB 12.86 kB
facebook-www/JSXDEVRuntime-dev.classic.js +8.09% 42.09 kB 45.49 kB +9.45% 11.75 kB 12.86 kB
oss-experimental/react/cjs/react-unstable-shared-subset.development.js +5.62% 71.06 kB 75.05 kB +6.42% 19.32 kB 20.56 kB
oss-stable-semver/react/cjs/react.development.js +4.73% 84.44 kB 88.43 kB +5.51% 22.62 kB 23.86 kB
oss-stable/react/cjs/react.development.js +4.73% 84.44 kB 88.43 kB +5.51% 22.62 kB 23.86 kB
oss-experimental/react/cjs/react.development.js +4.68% 85.37 kB 89.36 kB +5.47% 22.76 kB 24.00 kB
facebook-react-native/react/cjs/React-dev.js +4.16% 100.85 kB 105.05 kB +5.26% 24.40 kB 25.68 kB
oss-stable-semver/react/umd/react.development.js +3.86% 107.98 kB 112.15 kB +4.51% 27.60 kB 28.85 kB
oss-stable/react/umd/react.development.js +3.86% 107.98 kB 112.15 kB +4.51% 27.60 kB 28.85 kB
oss-experimental/react/umd/react.development.js +3.82% 108.95 kB 113.12 kB +4.49% 27.73 kB 28.98 kB
facebook-www/React-dev.modern.js +3.77% 109.39 kB 113.52 kB +4.75% 26.73 kB 28.00 kB
facebook-www/React-dev.classic.js +3.74% 110.41 kB 114.53 kB +4.72% 26.92 kB 28.19 kB
facebook-www/ReactDOMServer-dev.classic.js +3.66% 153.21 kB 158.81 kB +3.51% 38.88 kB 40.25 kB
facebook-www/ReactDOMServer-dev.modern.js +2.32% 213.66 kB 218.62 kB +2.98% 50.31 kB 51.81 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +2.30% 211.80 kB 216.67 kB +2.85% 50.84 kB 52.28 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +2.30% 211.80 kB 216.67 kB +2.85% 50.84 kB 52.28 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +2.30% 211.90 kB 216.76 kB +2.81% 50.99 kB 52.43 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +2.30% 211.90 kB 216.76 kB +2.81% 50.99 kB 52.43 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +2.29% 212.37 kB 217.24 kB +2.84% 50.99 kB 52.44 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +2.29% 212.47 kB 217.34 kB +2.81% 51.15 kB 52.58 kB
oss-stable-semver/react-dom/umd/react-dom-server.browser.development.js +2.29% 222.70 kB 227.79 kB +2.83% 51.57 kB 53.04 kB
oss-stable/react-dom/umd/react-dom-server.browser.development.js +2.29% 222.70 kB 227.79 kB +2.83% 51.57 kB 53.04 kB
oss-experimental/react-dom/umd/react-dom-server.browser.development.js +2.28% 223.32 kB 228.41 kB +2.83% 51.73 kB 53.19 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.27% 214.46 kB 219.33 kB +2.82% 51.33 kB 52.77 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.27% 214.46 kB 219.33 kB +2.82% 51.33 kB 52.77 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +2.26% 215.04 kB 219.91 kB +2.80% 51.48 kB 52.93 kB
oss-stable-semver/react-dom/umd/react-dom-server-legacy.browser.development.js +2.26% 225.44 kB 230.53 kB +2.81% 51.94 kB 53.40 kB
oss-stable/react-dom/umd/react-dom-server-legacy.browser.development.js +2.26% 225.44 kB 230.53 kB +2.81% 51.94 kB 53.40 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.03 kB 220.90 kB +2.79% 51.76 kB 53.20 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.03 kB 220.90 kB +2.79% 51.76 kB 53.20 kB
oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js +2.25% 226.06 kB 231.15 kB +2.80% 52.09 kB 53.55 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +2.25% 216.61 kB 221.48 kB +2.78% 51.92 kB 53.36 kB
oss-experimental/create-subscription/cjs/create-subscription.development.js +1.18% 5.75 kB 5.82 kB +1.05% 2.09 kB 2.11 kB
oss-stable-semver/create-subscription/cjs/create-subscription.development.js +1.18% 5.75 kB 5.82 kB +1.05% 2.09 kB 2.11 kB
oss-stable/create-subscription/cjs/create-subscription.development.js +1.18% 5.75 kB 5.82 kB +1.05% 2.09 kB 2.11 kB
oss-experimental/use-sync-external-store/cjs/use-sync-external-store.native.development.js +0.92% 7.37 kB 7.44 kB +0.73% 3.02 kB 3.04 kB
oss-stable-semver/use-sync-external-store/cjs/use-sync-external-store.native.development.js +0.92% 7.37 kB 7.44 kB +0.73% 3.02 kB 3.04 kB
oss-stable/use-sync-external-store/cjs/use-sync-external-store.native.development.js +0.92% 7.37 kB 7.44 kB +0.73% 3.02 kB 3.04 kB
oss-experimental/react-server/cjs/react-server-flight.development.js +0.90% 27.23 kB 27.47 kB +0.55% 7.29 kB 7.33 kB
oss-stable-semver/react-server/cjs/react-server-flight.development.js +0.90% 27.23 kB 27.47 kB +0.55% 7.29 kB 7.33 kB
oss-stable/react-server/cjs/react-server-flight.development.js +0.90% 27.23 kB 27.47 kB +0.55% 7.29 kB 7.33 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.89% 27.46 kB 27.71 kB +0.52% 7.45 kB 7.49 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.89% 27.46 kB 27.71 kB +0.52% 7.45 kB 7.49 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.browser.development.server.js +0.89% 27.46 kB 27.71 kB +0.52% 7.45 kB 7.49 kB
facebook-relay/flight/ReactFlightNativeRelayServer-dev.js +0.89% 27.39 kB 27.63 kB +0.46% 7.25 kB 7.28 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.89% 27.63 kB 27.87 kB +0.54% 7.41 kB 7.45 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.89% 27.63 kB 27.87 kB +0.54% 7.41 kB 7.45 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-writer.node.development.server.js +0.89% 27.63 kB 27.87 kB +0.54% 7.41 kB 7.45 kB
oss-experimental/use-sync-external-store/cjs/use-sync-external-store.development.js +0.86% 7.89 kB 7.96 kB +0.70% 3.16 kB 3.18 kB
oss-stable-semver/use-sync-external-store/cjs/use-sync-external-store.development.js +0.86% 7.89 kB 7.96 kB +0.70% 3.16 kB 3.18 kB
oss-stable/use-sync-external-store/cjs/use-sync-external-store.development.js +0.86% 7.89 kB 7.96 kB +0.70% 3.16 kB 3.18 kB
oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.85% 29.21 kB 29.45 kB +0.49% 7.60 kB 7.63 kB
oss-stable-semver/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.85% 29.21 kB 29.45 kB +0.49% 7.60 kB 7.63 kB
oss-stable/react-server-dom-webpack/umd/react-server-dom-webpack-writer.browser.development.server.js +0.85% 29.21 kB 29.45 kB +0.49% 7.60 kB 7.63 kB
oss-experimental/react-cache/cjs/react-cache.development.js +0.81% 8.40 kB 8.47 kB +0.68% 2.81 kB 2.83 kB
oss-stable-semver/react-cache/cjs/react-cache.development.js +0.81% 8.40 kB 8.47 kB +0.68% 2.81 kB 2.83 kB
oss-stable/react-cache/cjs/react-cache.development.js +0.81% 8.40 kB 8.47 kB +0.68% 2.81 kB 2.83 kB
oss-experimental/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +0.80% 8.45 kB 8.52 kB +0.71% 2.82 kB 2.84 kB
oss-stable-semver/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +0.80% 8.45 kB 8.52 kB +0.71% 2.82 kB 2.84 kB
oss-stable/react-server-dom-webpack/esm/react-server-dom-webpack-node-loader.js +0.80% 8.45 kB 8.52 kB +0.71% 2.82 kB 2.84 kB
facebook-www/ReactDOMTesting-dev.modern.js +0.70% 959.19 kB 965.88 kB +0.80% 215.61 kB 217.34 kB
oss-experimental/react-fs/cjs/react-fs.node.development.server.js +0.68% 9.99 kB 10.06 kB +0.77% 2.46 kB 2.47 kB
oss-stable-semver/react-fs/cjs/react-fs.node.development.server.js +0.68% 9.99 kB 10.06 kB +0.77% 2.46 kB 2.47 kB
oss-stable/react-fs/cjs/react-fs.node.development.server.js +0.68% 9.99 kB 10.06 kB +0.77% 2.46 kB 2.47 kB
facebook-www/ReactDOMTesting-dev.classic.js +0.68% 986.26 kB 992.95 kB +0.70% 221.23 kB 222.78 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js +0.67% 982.99 kB 989.54 kB +0.74% 220.72 kB 222.36 kB
oss-stable/react-dom/cjs/react-dom.development.js +0.67% 982.99 kB 989.54 kB +0.74% 220.72 kB 222.36 kB
oss-stable-semver/react-dom/umd/react-dom.development.js +0.66% 1,032.76 kB 1,039.62 kB +0.78% 223.33 kB 225.07 kB
oss-stable/react-dom/umd/react-dom.development.js +0.66% 1,032.76 kB 1,039.62 kB +0.78% 223.33 kB 225.07 kB
oss-experimental/react-dom/cjs/react-dom.development.js +0.66% 1,000.83 kB 1,007.39 kB +0.74% 224.42 kB 226.08 kB
oss-experimental/react-dom/umd/react-dom.development.js +0.65% 1,051.56 kB 1,058.43 kB +0.77% 227.05 kB 228.79 kB
facebook-www/ReactFlightDOMRelayServer-dev.classic.js +0.64% 27.65 kB 27.83 kB +0.47% 7.19 kB 7.22 kB
facebook-www/ReactFlightDOMRelayServer-dev.modern.js +0.64% 27.65 kB 27.83 kB +0.47% 7.19 kB 7.22 kB
facebook-www/ReactDOMForked-dev.modern.js +0.63% 1,056.54 kB 1,063.23 kB +0.75% 234.03 kB 235.79 kB
facebook-www/ReactDOM-dev.modern.js +0.63% 1,056.54 kB 1,063.24 kB +0.75% 234.03 kB 235.79 kB
facebook-www/ReactDOMForked-dev.classic.js +0.62% 1,080.98 kB 1,087.68 kB +0.65% 239.08 kB 240.63 kB
facebook-www/ReactDOM-dev.classic.js +0.62% 1,080.99 kB 1,087.68 kB +0.65% 239.08 kB 240.63 kB
oss-experimental/jest-react/cjs/jest-react.development.js +0.61% 11.22 kB 11.29 kB +0.40% 3.79 kB 3.81 kB
oss-stable-semver/jest-react/cjs/jest-react.development.js +0.61% 11.22 kB 11.29 kB +0.40% 3.79 kB 3.81 kB
oss-stable/jest-react/cjs/jest-react.development.js +0.61% 11.22 kB 11.29 kB +0.40% 3.79 kB 3.81 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js +0.57% 625.78 kB 629.32 kB +0.95% 135.16 kB 136.45 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js +0.56% 614.86 kB 618.32 kB +0.94% 134.10 kB 135.35 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js +0.56% 614.86 kB 618.32 kB +0.94% 134.10 kB 135.35 kB
oss-stable-semver/react-test-renderer/umd/react-test-renderer.development.js +0.56% 644.88 kB 648.49 kB +0.97% 135.52 kB 136.83 kB
oss-stable/react-test-renderer/umd/react-test-renderer.development.js +0.56% 644.88 kB 648.49 kB +0.97% 135.52 kB 136.83 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js +0.55% 630.71 kB 634.17 kB +0.91% 137.46 kB 138.72 kB
facebook-www/ReactTestRenderer-dev.classic.js +0.55% 637.25 kB 640.72 kB +0.94% 136.41 kB 137.69 kB
facebook-www/ReactTestRenderer-dev.modern.js +0.55% 637.26 kB 640.74 kB +0.94% 136.42 kB 137.70 kB
oss-experimental/react-test-renderer/umd/react-test-renderer.development.js +0.54% 661.58 kB 665.18 kB +0.95% 138.94 kB 140.26 kB
react-native/implementations/ReactFabric-dev.js +0.54% 716.55 kB 720.42 kB +0.87% 155.09 kB 156.44 kB
react-native/implementations/ReactNativeRenderer-dev.js +0.53% 733.69 kB 737.56 kB +0.83% 158.98 kB 160.30 kB
react-native/implementations/ReactFabric-dev.fb.js +0.53% 736.66 kB 740.53 kB +0.84% 158.85 kB 160.18 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js +0.52% 716.65 kB 720.41 kB +0.85% 151.95 kB 153.24 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js +0.52% 716.65 kB 720.41 kB +0.85% 151.95 kB 153.24 kB
react-native/implementations/ReactNativeRenderer-dev.fb.js +0.52% 751.78 kB 755.66 kB +0.83% 162.25 kB 163.60 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js +0.51% 732.72 kB 736.48 kB +0.84% 155.39 kB 156.70 kB
oss-stable-semver/react-art/cjs/react-art.development.js +0.51% 664.01 kB 667.38 kB +0.89% 143.46 kB 144.75 kB
oss-stable/react-art/cjs/react-art.development.js +0.51% 664.01 kB 667.38 kB +0.89% 143.46 kB 144.75 kB
oss-experimental/react-art/cjs/react-art.development.js +0.50% 679.89 kB 683.26 kB +0.88% 146.85 kB 148.14 kB
facebook-www/ReactART-dev.modern.js +0.47% 718.69 kB 722.07 kB +0.81% 153.00 kB 154.23 kB
facebook-www/ReactART-dev.classic.js +0.46% 728.97 kB 732.35 kB +0.81% 155.11 kB 156.38 kB
oss-stable-semver/react-art/umd/react-art.development.js +0.46% 767.91 kB 771.42 kB +0.81% 161.79 kB 163.10 kB
oss-stable/react-art/umd/react-art.development.js +0.46% 767.91 kB 771.42 kB +0.81% 161.79 kB 163.10 kB
oss-experimental/react-art/umd/react-art.development.js +0.45% 784.63 kB 788.15 kB +0.77% 165.23 kB 166.51 kB
oss-experimental/react-reconciler/cjs/react-reconciler-reflection.development.js +0.35% 19.36 kB 19.43 kB +0.39% 5.58 kB 5.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler-reflection.development.js +0.35% 19.36 kB 19.43 kB +0.39% 5.58 kB 5.60 kB
oss-stable/react-reconciler/cjs/react-reconciler-reflection.development.js +0.35% 19.36 kB 19.43 kB +0.39% 5.58 kB 5.60 kB

Generated by 🚫 dangerJS against c78cc77

@bvaughn
Copy link
Contributor

bvaughn commented Aug 13, 2021

Just to be clear, what is the (new) expected behavior after this change?

From testing it myself, it seems that rendering a Temporal value directly throws the following:

use compare() or equals() to compare Temporal.ZonedDateTime

This seems to occur before and after the change made in this PR. Am I misunderstanding something?

@justingrant
Copy link
Contributor Author

Just to be clear, what is the (new) expected behavior after this change?

@bvaughn Rendering Temporal objects should call toString() on those objects, which will not throw, and should not call valueOf(), which will throw.

This seems to occur before and after the change made in this PR. Am I misunderstanding something?

Hmm, are there more places in react besides toStringValue.js where objects are converted to strings using + or any other valueOf-calling code?

FWIW, I ran into this exception while converting one of my own projects over to use Temporal. The change in this PR stopped the exception from showing up in my app. But perhaps there are other ways of rendering that my app was not using?

@bvaughn
Copy link
Contributor

bvaughn commented Aug 13, 2021

It's possible I messed up last night when verifying this change, but I forked your Code Sandbox with an embedded copy of react-dom that has this change.

Hmm, are there more places in react besides toStringValue.js where objects are converted to strings using + or any other valueOf-calling code?

Yes. The underlying error here is:

Objects are not valid as a React child

This code path is being hit because rendering objects (including temporal values) directly is not supported by React:

function throwOnInvalidObjectType(returnFiber, newChild) {
  if (returnFiber.type !== 'textarea') {
    {
      {
        throw Error( "Objects are not valid as a React child (found: " + (Object.prototype.toString.call(newChild) === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : newChild) + "). If you meant to render a collection of children, use an array instead." );
      }
    }
  }

@ljharb
Copy link
Contributor

ljharb commented Aug 13, 2021

The issue there is the error message - newChild can’t be naively plussed into the string, for Symbols even if not Temporal, it needs to be wrapped in String() or a template literal.

@bvaughn
Copy link
Contributor

bvaughn commented Aug 13, 2021

The issue there is the error message ...

Yeah. I agree. Just pointing out that the change in this PR alone won't be sufficient to avoid the error mentioned from being thrown.

If we update the other code as well though, then at least we'll see the actual React error. 😄

@justingrant
Copy link
Contributor Author

Yeah. I agree. Just pointing out that the change in this PR alone won't be sufficient to avoid the error mentioned from being thrown.

It will actually avoid the error in some cases, like the case I ran into in my app. Here's the call stack where I got the error (pre-PR):

PlainTime.valueOf (plaintime.ts:400)
toString (react-dom.development.js:1294)
postMountWrapper (react-dom.development.js:1600)
setInitialProperties (react-dom.development.js:9142)
finalizeInitialChildren (react-dom.development.js:10201)
completeWork (react-dom.development.js:19470)
completeUnitOfWork (react-dom.development.js:22815)
performUnitOfWork (react-dom.development.js:22787)
workLoopSync (react-dom.development.js:22707)
renderRootSync (react-dom.development.js:22670)
performSyncWorkOnRoot (react-dom.development.js:22293)
(anonymous) (react-dom.development.js:11327)
unstable_runWithPriority (scheduler.development.js:468)
runWithPriority$1 (react-dom.development.js:11276)
flushSyncCallbackQueueImpl (react-dom.development.js:11322)
flushSyncCallbackQueue (react-dom.development.js:11309)
discreteUpdates$1 (react-dom.development.js:22420)
discreteUpdates (react-dom.development.js:3756)
dispatchDiscreteEvent (react-dom.development.js:5889)

The problematic line in postMountWrapper was this:

var initialValue = toString(node._wrapperState.initialValue); // Do not assign value if it is already set. This prevents user text input

The component where the error happens is a time picker that combines an user-typeable time with a dropdown box to pick from pre-populated every-half-hour times. Its UI is implemented via a react-select component. The element in this call stack is an HTML <input type='hidden'> which my code didn't create, so I'm not sure if it's react-select or react itself that's creating it.

@bvaughn - You'd surely understand this call stack better than me, but it looks like there's another way (besides rendering) where react-dom's custom toString can call valueOf. In this case, the PR prevented all errors in my code because I wasn't rendering a Temporal object, just using it as a prop.

BTW, it's really hard to track down errors like this because the call stack where the error happens is unrelated to my own code!

@bvaughn
Copy link
Contributor

bvaughn commented Aug 13, 2021

I don't think you need to track down all of the sources of this potential error, but the change set here should probably be sufficient to at least fix the repro case 😄 So I suggest also updating the other place I linked to.

@justingrant
Copy link
Contributor Author

the change set here should probably be sufficient to at least fix the repro case 😄

Lol, yep! In my OP I admitted I was baffled at why Temporal objects were being rendered when my own wasn't. From the call stack above I now understand this mystery, because the failure was happening before rendering got a chance to fail.

So I suggest also updating the other place I linked to.

Got it, makes sense. I'll pick this up next week and add the error message noted above to the PR. If I find any other places vulnerable to the same problem, I'll fix those too.

Also, @ljharb's note about Symbol showing the same behavior is helpful, because then I may be able to repro this without relying on mocking a Temporal-like object.

BTW, @bvaughn where is the right place to add tests for this PR? The tests in the https://github.com/facebook/react/tree/main/packages/react-dom/src/client/__tests__ folder are, uh, kinda sparse. Is there some other place where tests go for this code?

@bvaughn
Copy link
Contributor

bvaughn commented Aug 13, 2021

Either https://github.com/facebook/react/tree/main/packages/react-dom/src/client/__tests__ or https://github.com/facebook/react/tree/main/packages/react-dom/src/__tests__ seem like reasonable places to add a test probably 😁

@justingrant
Copy link
Contributor Author

Cool, thx. BTW, it looks like the pattern /'' \+ [^']/ is used in 38 places in react-dom. Not all of them can have user-provided objects as the RHS, but I'll look through the list and replace those with concat that look like they may be vulnerable. There may be other patterns too (like the one you quoted above) that won't match this regex, but at least I can try to tackle the low-hanging fruit.

@justingrant justingrant force-pushed the patch-2 branch 2 times, most recently from 1123e68 to 5fb8b08 Compare August 16, 2021 04:16
@@ -103,7 +103,7 @@ function printWarning(level, format, args) {
}

var argsWithFormat = args.map(function (item) {
return '' + item;
return ''.concat(item);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's worth noting that using concat means that react will start breaking if someone does delete String.prototype.concat; whereas using String would only break if someone did the much less likely delete window.String (and caching String somewhere would prevent this entirely)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the code in this PR from ''.concat( to String( would be a trivial search and replace operation, and I'd be happy to do it.

@bvaughn - I've learned enough while building this PR that I now know how to disable the lint rule that disallows String(x), but I'm not sure why that rule is there in the first place and whether FB would be OK with it being disabled. Do you know?

FWIW, I agree with @ljharb that String(x) may be better here. It also may bypass facebook/flow#8728 which is currently blocking this PR from passing its Flow tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I found the original PR that added this no-String() lint rule: #9082.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's worth noting that using concat means that react will start breaking if someone does delete String.prototype.concat; whereas using String would only break if someone did the much less likely delete window.String (and caching String somewhere would prevent this entirely)

This seems like a pretty unlikely scenario and one that we don't really try to support with any other prototype methods1. (We often close over global APIs e.g. window.performance or window.setTimeout but generally not methods on prototypes.)

1 The one exception is, I believe, Object.prototype.hasOwnProperty.

justingrant added a commit to justingrant/flow that referenced this pull request Aug 16, 2021
According to MDN docs for the `concat()` method of the `String` type: 

> If the arguments are not of the type string, they are converted to string
> values before concatenating.

Passing numbers, objects, etc to `String.prototype.concat` is is valid JS
behavior but causes an error in Flow. It's also blocking 
facebook/react#22064.

This commit changes the arg type: `Array<string>` -> `Array<mixed>`.
@justingrant
Copy link
Contributor Author

This code path is being hit because rendering objects (including temporal values) directly is not supported by React:

function throwOnInvalidObjectType(returnFiber, newChild) {
  if (returnFiber.type !== 'textarea') {
    {
      {
        throw Error( "Objects are not valid as a React child (found: " + (Object.prototype.toString.call(newChild) === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : newChild) + "). If you meant to render a collection of children, use an array instead." );
      }
    }
  }

After fruitlessly hunting for this code, turns out that it's already been fixed by #20617 back in January with the code below:

function throwOnInvalidObjectType(returnFiber, newChild) {
  var childString = Object.prototype.toString.call(newChild);

  {
    {
      throw Error( "Objects are not valid as a React child (found: " + (childString === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : childString) + "). If you meant to render a collection of children, use an array instead." );
    }
  }
}

@bvaughn
Copy link
Contributor

bvaughn commented Aug 16, 2021

After fruitlessly hunting for this code, turns out that it's already been fixed by #20617 back in January with the code below:

Oh okay, nice find.

@justingrant
Copy link
Contributor Author

Yesterday I discovered that Flow blocks ''.concat(value) when it has non-string arguments, even though MDN and the ES spec says that arguments of any type are accepted. But a lint rule blocks String(value) because of #9082.

I didn't want to leave this PR in a failing state, so I added another commit that switched from ''.concat(value) to String(value) and removed the no-String() lint rule. At least now this PR will be all green while Flow decides whether to accept facebook/flow#8729 and React decides whether String() is OK. If the decision ends up as "use concat", then it will be easy to switch back by ignoring the final commit.

Also, I cleaned up the OP and added a simple 1-line-of-JSX repro that wasn't fixed by #20617.

Finally, I added tests and rearranged commits:

  1. Failing tests using variations of the new repro above, but using a mock class instead of a Temporal dependency
  2. ''.concat(value) solution, which will fail Flow checks unless Allow mixed args to String.prototype.concat() flow#8729 is accepted.
  3. String(value) solution which passes all tests by removing the anti-String() lint rule. If this isn't an OK solution, just remove this commit and merge the others.

I'd be happy to implement alternative solutions too, just let me know. Here's a comprehensive list copied from #9082 (comment):

  • Use String(value) ?
  • Use string interpolation? (which will transpile down to concat(), AFAIK)
  • Use ''.concat(value) and change the Flow typing of String.prototype.concat to accept mixed args?
  • Use ''.concat(value) and add type casts to bypass the Flow problem?
  • Keep '' + value as the general pattern but special-case places where value can be an object?
  • Something else?

justingrant added a commit to justingrant/flow that referenced this pull request Aug 16, 2021
According to MDN docs for the `concat()` method of the `String` type:

> If the arguments are not of the type string, they are converted to string
> values before concatenating.

Passing numbers, objects, etc to `String.prototype.concat` is is valid JS
behavior but currently causes an error in Flow. It also may be blocking
facebook/react#22064.

This commit changes the arg type: `Array<string>` -> `Array<mixed>`.
justingrant added a commit to justingrant/flow that referenced this pull request Aug 17, 2021
According to MDN docs for the `concat()` method of the `String` type:

> If the arguments are not of the type string, they are converted to string
> values before concatenating.

Passing numbers, objects, etc to `String.prototype.concat` is is valid JS
behavior but currently causes an error in Flow. It also may be blocking
facebook/react#22064.

This commit changes the arg type: `Array<string>` -> `Array<mixed>`.
justingrant added a commit to justingrant/flow that referenced this pull request Aug 17, 2021
According to MDN docs for the `concat()` method of the `String` type:

> If the arguments are not of the type string, they are converted to string
> values before concatenating.

Passing numbers, objects, etc to `String.prototype.concat` is is valid JS
behavior but currently causes an error in Flow. It also may be blocking
facebook/react#22064.

This commit changes the arg type: `Array<string>` -> `Array<mixed>`.
@justingrant
Copy link
Contributor Author

We would very much appreciate if you're willing to finish what you've started here!

OK, happy to help! I'd like to get this done ASAP as I want to clear the decks for other work. There's a few open issues and questions remaining. Would it be possible to answer these soon? Copying below.

2. Is there a better way other than throw new TypeError(msg) to throw an exception in DEV? In particular, how can the developer figure out where in their JSX the problem is?

5. Should I fix #22309 while I'm in the neighborhood? The fix is deleting one line of unused code. Otherwise, if that bug is fixed it's a guaranteed merge conflict with this PR.

Unless the answers to the questions above cause more code changes, then I think this PR is ready for review.

One thing that came up during our discussion is that we could use a different lint rule for DEV/prod.

👍 I just pushed a new commit that adds an option to the safe-string-coercion rule to allow or disallow String(value). It's disallowed in prod code files and allowed elsewhere. LMK if this isn't what you had in mind.

FYI, there's only 5 lines in prod code (all error handling) where String() is used.

(For example, we have a Lint rule currently that only allows certain things inside of a __DEV__ block.) Maybe we could do this for String(value) as well?

That's no-production-logging. IMHO, it's not worth the complexity to do it here, given that only 1 of the 5 prod uses of String() is inside a __DEV__ block. (Most error handling code runs in prod too!) LMK know if you really want this and I'll put it in. Otherwise I won't bother.

@bvaughn
Copy link
Contributor

bvaughn commented Sep 17, 2021

2. Is there a better way other than throw new TypeError(msg) to throw an exception in DEV? In particular, how can the developer figure out where in their JSX the problem is?

I believe we usually log to console.error if we want the component stack. (Things logged to console.error automatically get a component stack appended as long as the package from which you're calling it has access to the React object.)

5. Should I fix #22309 while I'm in the neighborhood? The fix is deleting one line of unused code. Otherwise, if that bug is fixed it's a guaranteed merge conflict with this PR.

I don't have context about this, but it looks like Sebastian suggested that fix was fine:
#22309 (comment)

Maybe just do it as a separate/stacked PR in case we need to revert one of them later?

(For example, we have a Lint rule currently that only allows certain things inside of a __DEV__ block.) Maybe we could do this for String(value) as well?

That's no-production-logging. IMHO, it's not worth the complexity to do it here, given that only 1 of the 5 prod uses of String() is inside a __DEV__ block. (Most error handling code runs in prod too!) LMK know if you really want this and I'll put it in. Otherwise I won't bother.

I don't feel strongly. The team seemed to prefer it yesterday but I don't think we had context of there only being 5 places. I assume it's okay to just disable lint via comments since there are so few.

@justingrant
Copy link
Contributor Author

I believe we usually log to console.error if we want the component stack. (Things logged to console.error automatically get a component stack appended as long as the package from which you're calling it has access to the React object.)

OK, I'll change the check functions to add a console.error call. Not sure yet whether this should be "instead of throwing" or "in addition to throwing" in the check function. Will try both and see which is easier to debug in a real app. (There will be an exception thrown regardless, the only question is whether it should be thrown by the check function or by regular React code after the check function returns.)

The only problem I can see with adding console.error is that tests get more complicated. There's no toErrorDevAndThenThrow matcher already, so I'll learn about how to make one. Hopefully won't be too hard.

AFAICT, once I make this change then I believe all the open issues will be resolved and will be ready to review. 🎉

Maybe just do it as a separate/stacked PR in case we need to revert one of them later?

👍 Looks like there's a new contributor who may want to fix that one-liner, so I'll just leave it out of this PR and play merge chicken. If the other one is merged first, it will be a simple rebase to fix this one.

I don't feel strongly. The team seemed to prefer it yesterday but I don't think we had context of there only being 5 places. I assume it's okay to just disable lint via comments since there are so few.

Cool, I'll leave it out. There's actually only one line which is affected. The other 4 aren't in a __DEV__ block (and shouldn't be) because they are part of prod error handling code.

@justingrant
Copy link
Contributor Author

justingrant commented Sep 20, 2021

Open issues are now all resolved, so I think this PR is now ready for review. 🎉

How can I test this PR locally with one of my apps? Normally I'd just use npm pack and then npm install the resulting .tgz. But I wasn't sure how to do this given React's monorepo structure. EDIT: Ifigured it out. See https://reactjs.org/docs/how-to-contribute.html#development-workflow

I checked in two changes today to complete this PR:

Switched check functions from throwing to console.error. The goal of this change was to pick up component stacks. The coercion will still throw, but will throw inside the userland value implementation instead of inside the check function. Note that key coercion doesn't seem to include stacks; not sure why we get component stacks for props but not for keys.

Made lint rule smarter and removed most // eslint-disable* comments. Improving the rule was easier than I expected, so now the rule is silenced if any of the following are true:

  • There's a call to a coercion-check function inside a DEV block immediately before the coercion.
  • The coercion is wrapped in an if ( typeof...) test that verifies the type is safe to coerce: string, number, boolean, bigint, or undefined.
  • The value being coerced is a common numeric variable name like i, idx, or lineNumber.
  • The value is the result of a unary expression like +x or an update expression like x++ or ++x.

The added smarts made it possible to remove almost all of the // eslint-disable* comments, with only a few manual disables left e.g. for coercions inside a ternary. The lint rule also now returns detailed error messages explaining what's wrong.

@bvaughn
Copy link
Contributor

bvaughn commented Sep 20, 2021

Thanks for pushing this across the finish line! Tagging some potential reviewers.

@justingrant
Copy link
Contributor Author

justingrant commented Sep 20, 2021

Thanks @bvaughn! BTW, I figured out this morning how to test this PR locally, and after trying it in my own apps I pushed a minor change to one file to improve debugging DX. Now the check functions, in addition to console.error, will also throw. I added explanatory comments right before the line that throws, so that users in a debugger who end up at that line of code will will have an easier time figuring out what happened and how to fix it.

This commit also fixes a bug where some DEV code was incorrectly outside an if (__DEV__) block.

I don't plan to make any more commits until reviewer feedback comes in.

Currently, react uses `'' + value` to coerce mixed values to strings.
This code will throw for Temporal objects or symbols.

To make string-coercion safer and to improve user-facing error messages,
This commit adds a new ESLint rule called `safe-string-coercion`.

This rule has two modes: a production mode and a non-production mode.
* If the `isProductionUserAppCode` option is true, then `'' + value`
  coercions are allowed (because they're faster, although they may
  throw) and `String(value)` coercions are disallowed. Exception:
  when building error messages or running DEV-only code in prod
  files, `String()` should be used because it won't throw.
* If the `isProductionUserAppCode` option is false, then `'' + value`
  coercions are disallowed (because they may throw, and in non-prod
  code it's not worth the risk) and `String(value)` are allowed.

Production mode is used for all files which will be bundled with
developers' userland apps. Non-prod mode is used for all other React
code: tests, DEV blocks, devtools extension, etc.

In production mode, in addiiton to flagging `String(value)` calls,
the rule will also flag `'' + value` or `value + ''` coercions that may
throw. The rule is smart enough to silence itself in the following
"will never throw" cases:
* When the coercion is wrapped in a `typeof` test that restricts to safe
  (non-symbol, non-object) types. Example:
    if (typeof value === 'string' || typeof value === 'number') {
      thisWontReport('' + value);
    }
* When what's being coerced is a unary function result, because unary
   functions never return an object or a symbol.
* When the coerced value is a commonly-used numeric identifier:
  `i`, `idx`, or `lineNumber`.
* When the statement immeidately before the coercion is a DEV-only
  call to a function from shared/CheckStringCoercion.js. This call is a
  no-op in production, but in DEV it will show a console error
  explaining the problem, then will throw right after a long explanatory
  code comment so that debugger users will have an idea what's going on.
  The check function call must be in the following format:
    if (__DEV__) {
      checkXxxxxStringCoercion(value);
    };

Manually disabling the rule is usually not necessary because almost all
prod use of the `'' + value` pattern falls into one of the categories
above. But in the rare cases where the rule isn't smart enough to detect
safe usage (e.g. when a coercion is inside a nested ternary operator),
manually disabling the rule will be needed.

The rule should also be manually disabled in prod error handling code
where `String(value)` should be used for coercions, because it'd be
bad to throw while building an error message or stack trace!

The prod and non-prod modes have differentiated error messages to
explain how to do a proper coercion in that mode.

If a production check call is needed but is missing or incorrect
(e.g. not in a DEV block or not immediately before the coercion), then
a context-sensitive error message will be reported so that developers
can figure out what's wrong and how to fix the problem.

Because string coercions are now handled by the `safe-string-coercion`
rule, the `no-primitive-constructor` rule no longer flags `String()`
usage. It still flags `new String(value)` because that usage is almost
always a bug.
This commit adds DEV-only functions to check whether coercing
values to strings using the `'' + value` pattern will throw. If it will
throw, these functions will:
1. Display a console error with a friendly error message describing
   the problem and the developer can fix it.
2. Perform the coercion, which will throw. Right before the line where
   the throwing happens, there's a long code comment that will help
   debugger users (or others looking at the exception call stack) figure
   out what happened and how to fix the problem.

One of these check functions should be called before all string coercion
of user-provided values, except when the the coercion is guaranteed not
to throw, e.g.
* if inside a typeof check like `if (typeof value === 'string')`
* if coercing the result of a unary function like `+value` or `value++`
* if coercing a variable named in a whitelist of numeric identifiers:
  `i`, `idx`, or `lineNumber`.

The new `safe-string-coercion` internal ESLint rule enforces that
these check functions are called when they are required.

Only use these check functions in production code that will be bundled
with user apps.  For non-prod code (and for production error-handling
code), use `String(value)` instead which may be a little slower but will
never throw.
Added failing tests to verify:
* That input, select, and textarea elements with value and defaultValue
  set to Temporal-like objects which will throw when coerced to string
  using the `'' + value` pattern.
* That text elements will throw for Temporal-like objects
* That dangerouslySetInnerHTML will *not* throw for Temporal-like
  objects because this value is not cast to a string before passing to
  the DOM.
* That keys that are Temporal-like objects will throw

All tests above validate the friendly error messages thrown.
This commit switches non-production code from `'' + value` (which
throws for Temporal objects and symbols) to instead use `String(value)`
which won't throw for these or other future plus-phobic types.

"Non-produciton code" includes anything not bundled into user apps:
* Tests and test utilities. Note that I didn't change legacy React
  test fixtures because I assumed it was good for those files to
  act just like old React, including coercion behavior.
* Build scripts
* Dev tools package - In addition to switching to `String`, I also
  removed special-case code for coercing symbols which is now
  unnecessary.
This commit adds DEV-only function calls to to check if string coercion
using `'' + value` will throw, which it will if the value is a Temporal
object or a symbol because those types can't be added with `+`.

If it will throw, then in DEV these checks will show a console error
to help the user undertsand what went wrong and how to fix the
problem. After emitting the console error, the check functions will
retry the coercion which will throw with a call stack that's easy (or
at least easier!) to troubleshoot because the exception happens right
after a long comment explaining the issue. So whether the user is in
a debugger, looking at the browser console, or viewing the in-browser
DEV call stack, it should be easy to understand and fix the problem.

In most cases, the safe-string-coercion ESLint rule is smart enough to
detect when a coercion is safe. But in rare cases (e.g. when a coercion
is inside a ternary) this rule will have to be manually disabled.

This commit also switches error-handling code to use `String(value)`
for coercion, because it's bad to crash when you're trying to build
an error message or a call stack!  Because `String()` is usually
disallowed by the `safe-string-coercion` ESLint rule in production
code, the rule must be disabled when `String()` is used.
@justingrant
Copy link
Contributor Author

Other PRs were merged last week that overlapped with this one, so I just rebased to fix conflicts. Also cleaned up commits to make it easier to review one piece at a time. And rewrote commit messages to better document each piece of this PR.

Any idea when this PR can be reviewed? I'm happy to keep it up to date as other PRs are merged, but I suspect that will get tiring if I have to keep doing it for a long time.

@acdlite
Copy link
Collaborator

acdlite commented Sep 27, 2021

Talked with the rest of the team, we're going to go ahead and merge this. Thanks for your excellent and thorough work on this PR!

@acdlite acdlite merged commit c88fb49 into facebook:main Sep 27, 2021
@justingrant
Copy link
Contributor Author

Wow, great! Thanks @bvaughn @gaearon @acdlite for your help! This relatively narrow change should make it easier for developers to be successful using Temporal and React together.

As an aside, custom ESLint rules are so cool! This PR was the first time I'd built one and it was easier than I though it'd be. Amazing what neat things you can do with them. Thanks for the reason to learn this.

@bvaughn
Copy link
Contributor

bvaughn commented Sep 27, 2021

Thanks for your hard work here 😄

facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Oct 12, 2021
Summary:
This sync includes the following changes:
- **[579c008a7](facebook/react@579c008a7 )**: [Fizz/Flight] pipeToNodeWritable(..., writable).startWriting() -> renderToPipeableStream(...).pipe(writable) ([#22450](facebook/react#22450)) //<Sebastian Markbåge>//
- **[f2c381131](facebook/react@f2c381131 )**: fix: useSyncExternalStoreExtra ([#22500](facebook/react#22500)) //<Daishi Kato>//
- **[0ecbbe142](facebook/react@0ecbbe142 )**: Sync hydrate discrete events in capture phase and dont replay discrete events ([#22448](facebook/react#22448)) //<salazarm>//
- **[a724a3b57](facebook/react@a724a3b57 )**: [RFC] Codemod invariant -> throw new Error ([#22435](facebook/react#22435)) //<Andrew Clark>//
- **[201af81b0](facebook/react@201af81b0 )**: Release pooled cache reference in complete/unwind ([#22464](facebook/react#22464)) //<Joseph Savona>//
- **[033efe731](facebook/react@033efe731 )**: Call get snapshot in useSyncExternalStore server shim ([#22453](facebook/react#22453)) //<salazarm>//
- **[7843b142a](facebook/react@7843b142a )**: [Fizz/Flight] Pass in Destination lazily to startFlowing instead of in createRequest ([#22449](facebook/react#22449)) //<Sebastian Markbåge>//
- **[d9fb383d6](facebook/react@d9fb383d6 )**: Extract queueing logic into shared functions ([#22452](facebook/react#22452)) //<Andrew Clark>//
- **[9175f4d15](facebook/react@9175f4d15 )**: Scheduling Profiler: Show Suspense resource .displayName ([#22451](facebook/react#22451)) //<Brian Vaughn>//
- **[eba248c39](facebook/react@eba248c39 )**: [Fizz/Flight] Remove reentrancy hack ([#22446](facebook/react#22446)) //<Sebastian Markbåge>//
- **[66388150e](facebook/react@66388150e )**: Remove usereducer eager bailout ([#22445](facebook/react#22445)) //<Joseph Savona>//
- **[d3e086932](facebook/react@d3e086932 )**: Make root.unmount() synchronous  ([#22444](facebook/react#22444)) //<Andrew Clark>//
- **[2cc6d79c9](facebook/react@2cc6d79c9 )**: Rename onReadyToStream to onCompleteShell ([#22443](facebook/react#22443)) //<Sebastian Markbåge>//
- **[c88fb49d3](facebook/react@c88fb49d3 )**: Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) ([#22064](facebook/react#22064)) //<Justin Grant>//
- **[05726d72c](facebook/react@05726d72c )**: [Fix] Errors should not "unsuspend" a transition ([#22423](facebook/react#22423)) //<Andrew Clark>//
- **[3746eaf98](facebook/react@3746eaf98 )**: Packages/React/src/ReactLazy ---> changing -1 to unintialized ([#22421](facebook/react#22421)) //<BIKI DAS>//
- **[04ccc01d9](facebook/react@04ccc01d9 )**: Hydration errors should force a client render ([#22416](facebook/react#22416)) //<Andrew Clark>//
- **[029fdcebb](facebook/react@029fdcebb )**: root.hydrate -> root.isDehydrated ([#22420](facebook/react#22420)) //<Andrew Clark>//
- **[af87f5a83](facebook/react@af87f5a83 )**: Scheduling Profiler marks should include thrown Errors ([#22417](facebook/react#22417)) //<Brian Vaughn>//
- **[d47339ea3](facebook/react@d47339ea3 )**: [Fizz] Remove assignID mechanism ([#22410](facebook/react#22410)) //<Sebastian Markbåge>//
- **[3a50d9557](facebook/react@3a50d9557 )**: Never attach ping listeners in legacy Suspense ([#22407](facebook/react#22407)) //<Andrew Clark>//
- **[82c8fa90b](facebook/react@82c8fa90b )**: Add back useMutableSource temporarily ([#22396](facebook/react#22396)) //<Andrew Clark>//
- **[5b57bc6e3](facebook/react@5b57bc6e3 )**: [Draft] don't patch console during first render ([#22308](facebook/react#22308)) //<Luna Ruan>//
- **[cf07c3df1](facebook/react@cf07c3df1 )**: Delete all but one `build2` reference ([#22391](facebook/react#22391)) //<Andrew Clark>//
- **[bb0d06935](facebook/react@bb0d06935 )**: [build2 -> build] Local scripts //<Andrew Clark>//
- **[0c81d347b](facebook/react@0c81d347b )**: Write artifacts to `build` instead of `build2` //<Andrew Clark>//
- **[4da03c9fb](facebook/react@4da03c9fb )**: useSyncExternalStore React Native version ([#22367](facebook/react#22367)) //<salazarm>//
- **[48d475c9e](facebook/react@48d475c9e )**: correct typos ([#22294](facebook/react#22294)) //<Bowen>//
- **[cb6c619c0](facebook/react@cb6c619c0 )**: Remove Fiber fields that were used for hydrating useMutableSource ([#22368](facebook/react#22368)) //<Sebastian Silbermann>//
- **[64e70f82e](facebook/react@64e70f82e )**: [Fizz] add avoidThisFallback support ([#22318](facebook/react#22318)) //<salazarm>//
- **[3ee7a004e](facebook/react@3ee7a004e )**: devtools: Display actual ReactDOM API name in root type ([#22363](facebook/react#22363)) //<Sebastian Silbermann>//
- **[79b8fc667](facebook/react@79b8fc667 )**: Implement getServerSnapshot in userspace shim ([#22359](facebook/react#22359)) //<Andrew Clark>//
- **[86b3e2461](facebook/react@86b3e2461 )**: Implement useSyncExternalStore on server ([#22347](facebook/react#22347)) //<Andrew Clark>//
- **[8209de269](facebook/react@8209de269 )**: Delete useMutableSource implementation ([#22292](facebook/react#22292)) //<Andrew Clark>//

Changelog:
[General][Changed] - React Native sync for revisions e8feb11...afcb9cd

jest_e2e[run_all_tests]

Reviewed By: yungsters

Differential Revision: D31541359

fbshipit-source-id: c35941bc303fdf55cb061e9996200dc868a6f2af
@gaearon gaearon mentioned this pull request Mar 29, 2022
zhengjitf pushed a commit to zhengjitf/react that referenced this pull request Apr 15, 2022
….) (facebook#22064)

* Revise ESLint rules for string coercion

Currently, react uses `'' + value` to coerce mixed values to strings.
This code will throw for Temporal objects or symbols.

To make string-coercion safer and to improve user-facing error messages,
This commit adds a new ESLint rule called `safe-string-coercion`.

This rule has two modes: a production mode and a non-production mode.
* If the `isProductionUserAppCode` option is true, then `'' + value`
  coercions are allowed (because they're faster, although they may
  throw) and `String(value)` coercions are disallowed. Exception:
  when building error messages or running DEV-only code in prod
  files, `String()` should be used because it won't throw.
* If the `isProductionUserAppCode` option is false, then `'' + value`
  coercions are disallowed (because they may throw, and in non-prod
  code it's not worth the risk) and `String(value)` are allowed.

Production mode is used for all files which will be bundled with
developers' userland apps. Non-prod mode is used for all other React
code: tests, DEV blocks, devtools extension, etc.

In production mode, in addiiton to flagging `String(value)` calls,
the rule will also flag `'' + value` or `value + ''` coercions that may
throw. The rule is smart enough to silence itself in the following
"will never throw" cases:
* When the coercion is wrapped in a `typeof` test that restricts to safe
  (non-symbol, non-object) types. Example:
    if (typeof value === 'string' || typeof value === 'number') {
      thisWontReport('' + value);
    }
* When what's being coerced is a unary function result, because unary
   functions never return an object or a symbol.
* When the coerced value is a commonly-used numeric identifier:
  `i`, `idx`, or `lineNumber`.
* When the statement immeidately before the coercion is a DEV-only
  call to a function from shared/CheckStringCoercion.js. This call is a
  no-op in production, but in DEV it will show a console error
  explaining the problem, then will throw right after a long explanatory
  code comment so that debugger users will have an idea what's going on.
  The check function call must be in the following format:
    if (__DEV__) {
      checkXxxxxStringCoercion(value);
    };

Manually disabling the rule is usually not necessary because almost all
prod use of the `'' + value` pattern falls into one of the categories
above. But in the rare cases where the rule isn't smart enough to detect
safe usage (e.g. when a coercion is inside a nested ternary operator),
manually disabling the rule will be needed.

The rule should also be manually disabled in prod error handling code
where `String(value)` should be used for coercions, because it'd be
bad to throw while building an error message or stack trace!

The prod and non-prod modes have differentiated error messages to
explain how to do a proper coercion in that mode.

If a production check call is needed but is missing or incorrect
(e.g. not in a DEV block or not immediately before the coercion), then
a context-sensitive error message will be reported so that developers
can figure out what's wrong and how to fix the problem.

Because string coercions are now handled by the `safe-string-coercion`
rule, the `no-primitive-constructor` rule no longer flags `String()`
usage. It still flags `new String(value)` because that usage is almost
always a bug.

* Add DEV-only string coercion check functions

This commit adds DEV-only functions to check whether coercing
values to strings using the `'' + value` pattern will throw. If it will
throw, these functions will:
1. Display a console error with a friendly error message describing
   the problem and the developer can fix it.
2. Perform the coercion, which will throw. Right before the line where
   the throwing happens, there's a long code comment that will help
   debugger users (or others looking at the exception call stack) figure
   out what happened and how to fix the problem.

One of these check functions should be called before all string coercion
of user-provided values, except when the the coercion is guaranteed not
to throw, e.g.
* if inside a typeof check like `if (typeof value === 'string')`
* if coercing the result of a unary function like `+value` or `value++`
* if coercing a variable named in a whitelist of numeric identifiers:
  `i`, `idx`, or `lineNumber`.

The new `safe-string-coercion` internal ESLint rule enforces that
these check functions are called when they are required.

Only use these check functions in production code that will be bundled
with user apps.  For non-prod code (and for production error-handling
code), use `String(value)` instead which may be a little slower but will
never throw.

* Add failing tests for string coercion

Added failing tests to verify:
* That input, select, and textarea elements with value and defaultValue
  set to Temporal-like objects which will throw when coerced to string
  using the `'' + value` pattern.
* That text elements will throw for Temporal-like objects
* That dangerouslySetInnerHTML will *not* throw for Temporal-like
  objects because this value is not cast to a string before passing to
  the DOM.
* That keys that are Temporal-like objects will throw

All tests above validate the friendly error messages thrown.

* Use `String(value)` for coercion in non-prod files

This commit switches non-production code from `'' + value` (which
throws for Temporal objects and symbols) to instead use `String(value)`
which won't throw for these or other future plus-phobic types.

"Non-produciton code" includes anything not bundled into user apps:
* Tests and test utilities. Note that I didn't change legacy React
  test fixtures because I assumed it was good for those files to
  act just like old React, including coercion behavior.
* Build scripts
* Dev tools package - In addition to switching to `String`, I also
  removed special-case code for coercing symbols which is now
  unnecessary.

* Add DEV-only string coercion checks to prod files

This commit adds DEV-only function calls to to check if string coercion
using `'' + value` will throw, which it will if the value is a Temporal
object or a symbol because those types can't be added with `+`.

If it will throw, then in DEV these checks will show a console error
to help the user undertsand what went wrong and how to fix the
problem. After emitting the console error, the check functions will
retry the coercion which will throw with a call stack that's easy (or
at least easier!) to troubleshoot because the exception happens right
after a long comment explaining the issue. So whether the user is in
a debugger, looking at the browser console, or viewing the in-browser
DEV call stack, it should be easy to understand and fix the problem.

In most cases, the safe-string-coercion ESLint rule is smart enough to
detect when a coercion is safe. But in rare cases (e.g. when a coercion
is inside a ternary) this rule will have to be manually disabled.

This commit also switches error-handling code to use `String(value)`
for coercion, because it's bad to crash when you're trying to build
an error message or a call stack!  Because `String()` is usually
disallowed by the `safe-string-coercion` ESLint rule in production
code, the rule must be disabled when `String()` is used.
Belle59 added a commit to Belle59/react that referenced this pull request Nov 8, 2022
….1 October 13, 2022 * [standalone] Stop highlighting events when a component is selected ([tyao1](https://github.com/tyao1) in [facebook#25448](facebook#25448))  ---  ### 4.26.0 September 16, 2022  * Show DevTools icons in Edge browser panel ([itskolli](https://github.com/itskolli) in [facebook#25257](facebook#25257)) * [Bugfix] Don't hide fragment if it has a key ([lunaruan](https://github.com/lunaruan) in [facebook#25197](facebook#25197)) * Handle info, group, and groupCollapsed in Strict Mode logging ([timneutkens](https://github.com/timneutkens) in [facebook#25172](facebook#25172)) * Highlight RN elements on hover ([tyao1](https://github.com/tyao1) in [facebook#25106](facebook#25106)) * Remove ForwardRef/Memo from display name if `displayName` is set ([eps1lon](https://github.com/eps1lon) in [facebook#21952](facebook#21952))  ---  ### 4.25.0 July 13, 2022  * Timeline Profiler Sidebar with component tree ([lunaruan](https://github.com/lunaruan) and [blakef](https://github.com/blakef) in [facebook#24816](facebook#24816), [facebook#24815](facebook#24815), [facebook#24814](facebook#24814), [facebook#24805](facebook#24805), [facebook#24776](facebook#24776)) * [DevTools][Bugfix] Fix DevTools Perf Issue When Unmounting Large React Subtrees ([lunaruan](https://github.com/lunaruan) in [facebook#24863](facebook#24863)) * Enable "reload & profile" button for timeline view ([mondaychen](https://github.com/mondaychen) in [facebook#24702](facebook#24702)) * Find best renderer when inspecting app with mutilple react roots ([mondaychen](https://github.com/mondaychen) in [facebook#24665](facebook#24665)) * Only polyfill requestAnimationFrame when necessary ([mondaychen](https://github.com/mondaychen) in [facebook#24651](facebook#24651))  ---  ### 4.24.7 May 31, 2022  * mock requestAnimationFrame with setTimeout as a temporary fix for facebook#24626 ([mondaychen](https://github.com/mondaychen) in [facebook#24633](facebook#24633)) * Fix formatWithStyles not styling the results if the first argument is an object + Added unit tests ([lunaruan](https://github.com/lunaruan) in [facebook#24554](facebook#24554))  ---  ### 4.24.6 May 12, 2022  * fix a bug in console.log with non-string args ([mondaychen](https://github.com/mondaychen) in [facebook#24546](facebook#24546)) * Add Pragma to Only Run Tests if Version Requirement Satisfied ([lunaruan](https://github.com/lunaruan) in [facebook#24533](facebook#24533)) * [DevTools][Bug] Fix Race Condition When Unmounting Fibers ([lunaruan](https://github.com/lunaruan) in [facebook#24510](facebook#24510)) * [React DevTools] Improve DevTools UI when Inspecting a user Component that Throws an Error  ([mondaychen](https://github.com/mondaychen) in [facebook#24248](facebook#24248))  ---  ### 4.24.5 May 5, 2022  * Fixed potential undefined error in `TreeContext` reducer ([bvaughn](https://github.com/bvaughn) in [facebook#24501](facebook#24501)) * Fix error where Profiler sometimes incorrectlyed reported that a `forwardRef` did not render ([lunaruan](https://github.com/lunaruan) in [facebook#24494](facebook#24494)) * Fix regex for `formateWithStyles` function ([lunaruan](https://github.com/lunaruan) in [facebook#24486](facebook#24486)) * Fixed wrong method call for LRU cache ([bvaughn](https://github.com/bvaughn) in [facebook#24477](facebook#24477)) * Synchronize implementations of second render logging ([billyjanitsch](https://github.com/billyjanitsch) in [facebook#24381](facebook#24381)) * Don't stringify objects for console log second render ([lunaruan](https://github.com/lunaruan) in [facebook#24373](facebook#24373))  ---  ### 4.24.4 April 8, 2022  * Allow react-devtools-inline `createStore()` method to override Store config params ([bvaughn](https://github.com/bvaughn) in [facebook#24303](facebook#24303)) * [ReactDebugTools] wrap uncaught error from rendering user's component ([mondaychen](https://github.com/mondaychen) in [facebook#24216](facebook#24216))  ---  ### 4.24.3 March 29, 2022  #### Bugfix * Profiler should only report stateful hooks that change between renders ([bvaughn](https://github.com/bvaughn) in [facebook#24189](facebook#24189)) * Ignore duplicate welcome "message" events ([bvaughn](https://github.com/bvaughn) in [facebook#24186](facebook#24186)) * Attach DevTools Tree keyboard events to the Tree container (not the document) ([bvaughn](https://github.com/bvaughn) in [facebook#24164](facebook#24164))  ---  ### 4.24.2 March 24, 2022  #### Bugfix * Show upgrade/downgrade instructions inline for errors thrown by the Store due to incompatible protocol (mismatched backend and frontend versions) ([bvaughn](https://github.com/bvaughn) in [facebook#24147](facebook#24147)) * Inspecting an element in a nested renderer no longer throws ([lunaruan](https://github.com/lunaruan) in [facebook#24116](facebook#24116))  ---  ### 4.24.1 March 15, 2022  #### Bugfix * Disable unsupported Bridge protocol version dialog and add workaround for old protocol operations format ([bvaughn](https://github.com/bvaughn) in [facebook#24093](facebook#24093))  ---  ### 4.24.0 March 10, 2022  #### Feature * Show DevTools backend and frontend versions in UI ([bvaughn](https://github.com/bvaughn) in [facebook#23399](facebook#23399)) * Timeline profiler refactored to support reading basic profiling data directly from React ([bvaughn](https://github.com/bvaughn) in [facebook#22529](facebook#22529))  #### Bugfix * Better handle undefined `Error` stacks in DevTools error boundary ([bvaughn](https://github.com/bvaughn) in [facebook#24065](facebook#24065)) * Fixed edge case bug in Profiler commit filtering ([bvaughn](https://github.com/bvaughn) in [facebook#24031](facebook#24031)) * Gracefully handle empty "xstyle" prop values ([lunaruan](https://github.com/lunaruan) in [facebook#23279](facebook#23279) and [bvaughn](https://github.com/bvaughn) in [facebook#23190](facebook#23190)) * Add `<TracingMarker>` component boilerplate ([lunaruan](https://github.com/lunaruan) in [facebook#23275](facebook#23275))  #### Misc * Remove object-assign polyfill ([sebmarkbage](https://github.com/sebmarkbage) in [facebook#23351](facebook#23351))  #### Breaking change * Move createRoot/hydrateRoot to react-dom/client ([sebmarkbage](https://github.com/sebmarkbage) in [facebook#23385](facebook#23385)).  Technically this is a breaking change for projects using `react-devtools-inline`, but since this package already depends on the _experimental_ release channel, we are going to include it in 4.24.  ---  ### 4.23.0 January 24, 2022  #### Feature * DevTools: Only show StrictMode badge on root elements ([bvaughn](https://github.com/bvaughn) in [facebook#23012](facebook#23012))  #### Bugfix * Don't crawl unmounted subtrees when profiling starts ([bvaughn](https://github.com/bvaughn) in [facebook#23162](facebook#23162)) * Filter deleted components from the updaters list to avoid runtime errors later ([lunaruan](https://github.com/lunaruan) in [facebook#23156](facebook#23156))  #### Misc * DevTools (not React) logs Timeline performance data to the User Timing API ([bvaughn](https://github.com/bvaughn) in [facebook#23102](facebook#23102))  ---  ### 4.22.1 December 14, 2021  * Fix invalid `require()` statements in `react-devtools-inline` ([bvaughn](https://github.com/bvaughn) in [facebook#22961](facebook#22961)) * Fix invalid `files` array in `react-devtools` `package.json` ([bvaughn](https://github.com/bvaughn) in [facebook#22960](facebook#22960))  ---  ### 4.22.0 December 13, 2021  #### A note for React Native users React DevTools has [two main pieces](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#overview): * The *frontend* users interact with (the Components tree, the Profiler, etc.). * The *backend* which runs in the same context as React itself. (In the web page with React DOM or shipped on the device with the React Native runtime.)  This release updates the [**protocol** that DevTools uses](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#serializing-the-tree) to communicate between the "frontend" and "backend" components.  Because React Native embeds a copy of the React DevTools "backend" ([`react-devtools-core/backend`](https://www.npmjs.com/package/react-devtools-core)), the "frontend" (UI) needs to match. This means you may be prompted to upgrade (or downgrade) your React DevTools based on which version of React Native your app uses.  #### Features * Support multiple DevTools instances per page ([@bvaughn](https://github.com/bvaughn) in [facebook#22949](facebook#22949)) * Advocate for StrictMode usage within Components tree ([@bvaughn](https://github.com/bvaughn) in [facebook#22886](facebook#22886)) * StyleX plug-in for resolving atomic styles to values for props.xstyle ([@bvaughn](https://github.com/bvaughn) in [facebook#22808](facebook#22808)) * Timeline search ([@bvaughn](https://github.com/bvaughn) in [facebook#22799](facebook#22799)) * Timeline: Improved snapshot view ([@bvaughn](https://github.com/bvaughn) in [facebook#22706](facebook#22706)) * Display root type for root updates in "what caused this update?" ([@eps1lon](https://github.com/eps1lon) in [facebook#22599](facebook#22599))  #### Bugfix * DevTools should inject itself for XHTML pages too (not just HTML) ([@bvaughn](https://github.com/bvaughn) in [facebook#22932](facebook#22932)) * Don't restore profiling data if we're profling ([@eps1lon](https://github.com/eps1lon) in [facebook#22753](facebook#22753)) * DevTools should properly report re-renders due to (use)context changes ([@bvaughn](https://github.com/bvaughn) in [facebook#22746](facebook#22746)) * Filter empty commits (all Fibers bailed out) from Profiler ([@bvaughn](https://github.com/bvaughn) in [facebook#22745](facebook#22745)) * Accept json file in import fileinput ([@jyash97](https://github.com/jyash97) in [facebook#22717](facebook#22717)) * Expose css vars to reach-ui portal components ([@jyash97](https://github.com/jyash97) in [facebook#22716](facebook#22716)) * Fix DevTools advanced tooltip display conditional check ([@bvaughn](https://github.com/bvaughn) in [facebook#22669](facebook#22669))  #### Misc * Emit new event when DevTools connects in standalone app ([@jstejada](https://github.com/jstejada) in [facebook#22848](facebook#22848))  ---  ### 4.21.0 October 31, 2021  #### Features * Scheduling Profiler: Add marks for component effects (mount and unmount) ([@bvaughn](https://github.com/bvaughn) in [facebook#22578](facebook#22578)) * Scheduling Profiler: De-emphasize React internal frames ([bvaughn](https://github.com/bvaughn) in [facebook#22588](facebook#22588))   #### Bugfix * Revert logic for checking for duplicate installations of DevTools potentially causing issues loading Components tab ([@jstejada](https://github.com/jstejada) in [facebook#22638](facebook#22638)) * Scheduling Profiler does not warn about long transitions ([@bvaughn](https://github.com/bvaughn) in [facebook#22614](facebook#22614)) * Re-enable 'Reload and Start Profiling' for Microsoft Edge ([@eoandersson](https://github.com/eoandersson) in [facebook#22631](facebook#22631))   #### Misc * DevTools supports ENV-injected version for better internal bug reports ([@bvaughn](https://github.com/bvaughn) in [facebook#22635](facebook#22635)) * Fix typos ([@KonstHardy](https://github.com/KonstHardy) in [facebook#22494](facebook#22494))  ---  ### 4.20.2 October 20, 2021  #### Bugfix * Dev Tools: Relax constraint on passing extensionId for backend init ([@jstejada](https://github.com/jstejada) in [facebook#22597](facebook#22597)) * DevTools: Fix passing extensionId in evaled postMessage calls ([@jstejada](https://github.com/jstejada) in [facebook#22590](facebook#22590))  ---  ### 4.20.1 October 19, 2021  #### Bugfix * Only show DevTools warning about unrecognized build in Chrome ([@jstejada](https://github.com/jstejada) in [facebook#22571](facebook#22571)) * DevTools: Include Edge in browser name detection ([@jstejada](https://github.com/jstejada) in [facebook#22584](facebook#22584))  ---  ### 4.20.0 October 15, 2021  #### Features * Allow to use the Profiler when no client is connected in standalone DevTools ([@gabrieltrompiz](https://github.com/gabrieltrompiz) in [facebook#22551](facebook#22551))  #### Bugfix * Surface backend errors during inspection in the frontend UI ([@bvaughn](https://github.com/bvaughn) in [facebook#22546](facebook#22546)) * Prevent splash page in standalone app from becoming unresponsive after the disconnection of a client  (facebook#22558) ([@gabrieltrompiz](https://github.com/gabrieltrompiz) in [facebook#22560](facebook#22560)) * Prevent errors/crashing when multiple installs of DevTools are present ([@jstejada](https://github.com/jstejada) in [facebook#22517](facebook#22517)) * Update Fiber logic in backend renderer to match implementation in React ([@jstejada](https://github.com/jstejada) in [facebook#22527](facebook#22527))  #### Misc * Show warning in UI when duplicate installations of DevTools extension are detected ([@jstejada](https://github.com/jstejada) in [facebook#22563](facebook#22563)) * Improved filenames of built worker files ([@akgupta0777](https://github.com/akgupta0777) in [facebook#22559](facebook#22559))  ---  ### 4.19.2 October 8, 2021  #### Bugfix * Show different error boundary UI for timeouts than normal errors ([bvaughn](https://github.com/bvaughn) in [facebook#22483](facebook#22483)) * Fixed bug where deleting a component filter would also close the settings modal ([Biki-das](https://github.com/Biki-das) in [facebook#22484](facebook#22484))  ---  ### 4.19.1 October 1, 2021  #### Bugfix * Fixed potential cache miss when inspecting elements ([bvaughn](https://github.com/bvaughn) in [facebook#22472](facebook#22472))  ---  ### 4.19.0 September 29, 2021  #### Features * Scheduling Profiler: Show Suspense resource .displayName ([bvaughn](https://github.com/bvaughn) in [facebook#22451](facebook#22451)) * Scheduling Profiler marks should include thrown Errors ([bvaughn](https://github.com/bvaughn) in [facebook#22419](facebook#22419)) * Don't patch console during first render in strict mode ([lunaruan](https://github.com/lunaruan) in [facebook#22308](facebook#22308)) * Show which hook indices changed when profiling for all builds ([bvaughn](https://github.com/bvaughn) in [facebook#22365](facebook#22365)) * Display actual ReactDOM API name in root type ([eps1lon](https://github.com/eps1lon) in [facebook#22363](facebook#22363)) * Add named hooks support to standalone and inline DevTools ([jstejada](https://github.com/jstejada) in [facebook#22320](facebook#22320) and [bvaughn](https://github.com/bvaughn) in [facebook#22263](facebook#22263)) #### Bugfix * DevTools encoding supports multibyte characters (e.g. "🟩") ([bvaughn](https://github.com/bvaughn) in [facebook#22424](facebook#22424)) * Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) ([justingrant](https://github.com/justingrant) in [facebook#22064](facebook#22064)) * Fix memory leak caused by not storing alternate Fiber pointer ([bvaughn](https://github.com/bvaughn) in [facebook#22346](facebook#22346)) * Fix call stack exceeded error in `utfDecodeString()` ([bvaughn](https://github.com/bvaughn) in [facebook#22330](facebook#22330)) * Fix runtime error when inspecting an element times out ([jstejada](https://github.com/jstejada) in [facebook#22329](facebook#22329))  #### Performance * DevTools: Lazily parse indexed map sections ([bvaughn](https://github.com/bvaughn) in [facebook#22415](facebook#22415)) * DevTools: Hook names optimizations ([bvaughn](https://github.com/bvaughn) in [facebook#22403](facebook#22403)) * Replaced `network.onRequestFinished()` caching with `network.getHAR()` ([bvaughn](https://github.com/bvaughn) in [facebook#22285](facebook#22285))  ---  ### 4.18.0 September 1, 2021  #### Features * DevTools: Improve named hooks network caching ([bvaughn](https://github.com/bvaughn) in [facebook#22198](facebook#22198)) * Console Logging for StrictMode Double Rendering ([lunaruan](https://github.com/lunaruan) in [facebook#22030](facebook#22030))  ---  ### Bugfix * Fix react-devtools-inline size issues ([lunaruan](https://github.com/lunaruan) in [facebook#22232](facebook#22232)) * devtools: Don't display hook index of useContext ([eps1lon](https://github.com/eps1lon) in [facebook#22200](facebook#22200)) * Throw error in console without interfering with logs ([lunaruan](https://github.com/lunaruan) in [facebook#22175](facebook#22175))   ---  ### 4.17.0 August 24, 2021  #### Features * Scheduling Profiler: Add network measures ([bvaughn](https://github.com/bvaughn) in [facebook#22112](facebook#22112)) * Add options for disabling some features ([hbenl](https://github.com/hbenl) in [facebook#22136](facebook#22136))  #### Bugfix * Fixed broken scroll-to error or warning feature ([bvaughn](https://github.com/bvaughn) and [eps1lon](https://github.com/eps1lon) in [facebook#22147](facebook#22147) and [facebook#22144](facebook#22144)) * Replaced WeakMap with LRU for inspected element cache ([bvaughn](https://github.com/bvaughn) in [facebook#22160](facebook#22160)) * Add more detailed error handling if profiling data does not have any React marks ([byronluk](https://github.com/byronluk) in [facebook#22157](facebook#22157)) * Various named hooks bug fixes ([jstejada](https://github.com/jstejada) in [facebook#22129](facebook#22129), [facebook#22128](facebook#22128), [facebook#22096](facebook#22096), and [facebook#22148](facebook#22148)) * Fix tooltip wheel event regression ([bvaughn](https://github.com/bvaughn) in [facebook#22130](facebook#22130)) * Replace `source-map` library with `source-map-js` for named hooks source map parsing ([bvaughn](https://github.com/bvaughn) in [facebook#22126](facebook#22126))  ---  ### 4.16.0 August 16, 2021 #### Features * Scheduling Profiler: Inline snapshots ([bvaughn](https://github.com/bvaughn) in [facebook#22091](facebook#22091) and[bvaughn](https://github.com/bvaughn) in [facebook#22088](facebook#22088)) #### Bugfix * split parsing code to unblock Firefox release ([lunaruan](https://github.com/lunaruan) in [facebook#22102](facebook#22102)) * Scheduling profiler: Canvas views clip by default ([bvaughn](https://github.com/bvaughn) in [facebook#22100](facebook#22100)) * Fixed Components tree indentation bug for Chrome extension ([bvaughn](https://github.com/bvaughn) in [facebook#22083](facebook#22083))  ---  ### 4.15.0 August 11, 2021  #### Features * Added new scheduling profiler tool ([bvaughn](https://github.com/bvaughn), [kartikcho](https://github.com/kartikcho), and [taneliang](https://github.com/taneliang) in [facebook#22006](facebook#22006), [facebook#21990](facebook#21990), [facebook#22013](facebook#22013), [facebook#21897](facebook#21897), [facebook#22029](facebook#22029), [facebook#22038](facebook#22038), [facebook#22043](facebook#22043), [facebook#21947](facebook#21947), [facebook#21966](facebook#21966), [facebook#21970](facebook#21970), [facebook#21971](facebook#21971), [facebook#21975](facebook#21975)). * Parsing source code for extracting names for hooks now happens in a worker ([tsirlucas](https://github.com/tsirlucas) in [facebook#21902](facebook#21902)). * Format hyperlink text as a clickable link ([kkragoth](https://github.com/kkragoth) in [facebook#21964](facebook#21964)). * Named hooks can now be extracted from extended source maps ([jstejada](https://github.com/jstejada) [facebook#22010](facebook#22010), [facebook#22073](facebook#22073)). * Hook indices now show up as a reason why a component rendered in the profiler ([mrkev](https://github.com/mrkev) in [facebook#22073](facebook#22073)). * Optimize images in DevTools ([ilhamsyahids](https://github.com/ilhamsyahids) in [facebook#21968](facebook#21968)).  #### Bugfix * Named hooks cache is correctly cleared after Fast Refresh ([bvaughn](https://github.com/bvaughn) in [facebook#21891](facebook#21891)). * Hook names are correctly extracted when parsing nested hook calls ([jstejada](https://github.com/jstejada) in [facebook#22037](facebook#22037), [facebook#21996](facebook#21996)). * Highlight updates with memoized components ([Selnapenek](https://github.com/Selnapenek) in [facebook#22008](facebook#22008)). * Set app icon on MacOS ([christian-schulze](https://github.com/christian-schulze) in [facebook#21908](facebook#21908)). * Updated @reach packages to fix unmount bug ([bvaughn](https://github.com/bvaughn) in [facebook#22075](facebook#22075)).  #### Misc * Refactor imperative theme code ([houssemchebeb](https://github.com/houssemchebeb) in [facebook#21950](facebook#21950)). * Change some remaining instances of master -> main ([shubham9411](https://github.com/shubham9411) in [facebook#21982](facebook#21982)).  ##### Scheduling profiler  ###### What is React working on?  React’s previous Profiler primarily reports how fast (or slow) components are when rendering. It didn’t provide an overview of *what React is doing* (the actual cooperative scheduling bits). The new profiler does. It shows when components schedule state updates and when React works on them. It also shows how React categorizes and prioritizing what it works on.  Here’s a profile for a simple app that uses only the legacy (synchronous) `ReactDOM.render` API. The profiler shows that all of the work scheduled and rendered by this app is done at *synchronous* priority:  https://user-images.githubusercontent.com/29597/129042321-56985f5a-264e-4f3a-a8b7-9371d75c690f.mp4  Here’s a more interesting profile for an app that’s rendered at _default_ priority using the new [`createRoot` API](reactwg/react-18#5), then updates _synchronously_ in response to an “input” event to manage a ["controlled component"](https://reactjs.org/docs/forms.html#controlled-components):  https://user-images.githubusercontent.com/29597/129074959-50912a63-0215-4be5-b51b-1e0004fcd2a1.mp4  Here’s part of a profile showing an idle app (no JavaScript running). In this case, React does some pre-rendering work for components that are “offscreen” (not currently displayed).  https://user-images.githubusercontent.com/29597/128971757-612f232f-c64f-4447-a766-66a0516e8f49.mp4  Note that “offscreen” refers to a new API and set of features that we haven’t talked about much yet except for [some passing references](reactwg/react-18#18 (reply in thread)). We’ll talk more about it in future posts.  ###### What are “transitions” and how do they work? We recently shared an update about the new [`startTransition` API](reactwg/react-18#41). This API helps apps feel responsive even when there are large updates by splitting the work into (1) a quick update to show that the app has received some input and (2) a slower update (the “transition”) that actually does any heavy lifting needed as a result of the input.  Here is an example profile that uses the transition API. First React renders a small update that shows the user some visual feedback (like updating a controlled component or showing an inline loading indicator). Then it renders a larger update that, in this case, computes some expensive value.  https://user-images.githubusercontent.com/29597/129079176-0995c8c0-e95a-4f44-8d55-891a7efa35c0.mp4  ###### How does Suspense impact rendering performance?  You may have heard mention of “suspense” in past talks or seen it referenced [in our docs](https://reactjs.org/docs/react-api.html#suspense). Although full support for data fetching via Suspense is [expected to be released sometime after React 18.0](reactwg/react-18#47 (comment)), you can use Suspense today for things like lazy-loading React components. The new profiler shows when components suspend during render and how that impacts overall rendering performance.  Here’s an example profile that suspends during the initial render to lazy-load a component using [`React.lazy`](https://reactjs.org/docs/code-splitting.html#reactlazy). While this component is loading, React shows a “fallback“ (placeholder UI). Once the component finishes loading, React retries the render and commits the final UI.  https://user-images.githubusercontent.com/29597/129054366-2700e7e8-0172-4f61-9453-475acd740456.mp4  We plan to expand support for Suspense in the coming weeks to more explicitly show when suspense fallbacks are rendered and which subsequent renders are related to an initial update that suspended.  ###### What else might cause a render to get delayed?  Suspense can cause a render to get delayed as React waits for data to load, but React can also get stuck waiting on a lot of JavaScript to run.  React profiling tools have previously focused on only reporting what React (or React components) are doing, but any JavaScript the browser runs affects performance. The new profiler shows non-React JavaScript as well, making it easy to see when it delays React from rendering.  https://user-images.githubusercontent.com/29597/128971952-7c4e7e11-f4fb-497e-b643-4d9b3994b590.mp4  ###### What can you do to improve performance?  Until now, DevTools (and the Profiler) has provided information without commentary. The new profiler takes a more active approach– highlighting where we think performance can be improved and providing suggestions.  For example, suspending during an update is generally a bad user experience because it causes previously shown components to be unmounted (hidden) so the fallback can be shown while data loads. This can be avoided using the new [Transition API](reactwg/react-18#41). If you forget to add a transition to an update that suspends, the new profiler will warn you about this:  https://user-images.githubusercontent.com/29597/128972228-3b23f01a-8017-43ad-b371-975ffed26c06.mp4  The new profiler also warns about scheduling a long, synchronous React update inside of event handler.  https://user-images.githubusercontent.com/29597/128972000-d7477ba3-b779-46f2-b141-aaa712e9d6d2.mp4  Another thing the new profiler will warn about is long-running renders scheduled from layout effects (`useLayoutEffect` or `componentDidMount`/`componentDidUpdate`). These updates (called “nested updates”) are sometimes necessary to adjust layout before the browser paints, but they should be *fast*. Slow nested updates make the browser feel unresponsive.  https://user-images.githubusercontent.com/29597/128972017-3ed0e682-751c-46fb-a6c5-271f255c8087.mp4  ---  ### 4.14.0 July 17, 2021 #### Features * Display hook names for inspected components ([saphal1998](https://github.com/saphal1998), [VibhorCodecianGupta](https://github.com/VibhorCodecianGupta), [bvaughn](https://github.com/bvaughn), and [motiz88](https://github.com/motiz88) in [facebook#21641](facebook#21641), [facebook#21790](facebook#21790), [facebook#21814](facebook#21814), [facebook#21815](facebook#21815), [facebook#21831](facebook#21831), [facebook#21833](facebook#21833), [facebook#21835](facebook#21835), [facebook#21865](facebook#21865), [facebook#21871](facebook#21871), [facebook#21874](facebook#21874), [facebook#21891](facebook#21891)) * Control for manually toggling error boundaries ([baopham](https://github.com/baopham) in [facebook#21583](facebook#21583)) * Allow user to manually enter Profiler commit number to jump between commits ([srubin](https://github.com/srubin) in [facebook#19957](facebook#19957))  ##### Display hook names for inspected components ![DevTools parsing hook names](https://user-images.githubusercontent.com/29597/124013541-68c2cb00-d9b0-11eb-83ab-81a5180da46b.gif)  ##### Control for manually toggling error boundaries ![DevTools error boundary toggle](https://user-images.githubusercontent.com/29597/125891522-30f0d99d-407f-4c31-b5a7-e9d0bd3fa554.gif)  ---  ### 4.13.5 May 25, 2021 #### Bugfix * Handle edge case where a component mounts before its "owner" (in DEV mode) that previously caused a validation error ([bvaughn](https://github.com/bvaughn) in [facebook#21562](facebook#21562))  ---  ### 4.13.4 May 20, 2021 #### Bugfix * Fix edge-case Fast Refresh bug that caused Fibers with warnings/errors to be untracked prematurely (which broke componentinspection in DevTools) ([bvaughn](https://github.com/bvaughn) in [facebook#21536](facebook#21536)) * Revert force deep re-mount when Fast Refresh detected (was no longer necessary) ([bvaughn](https://github.com/bvaughn) in [facebook#21539](facebook#21539))  ---  ### 4.13.3 May 19, 2021 #### Misc * Updated `react` and `react-dom` API imports in preparation for upcoming stable release ([bvaughn](https://github.com/bvaughn) in [facebook#21488](facebook#21488))  #### Bugfix * Reload all roots after Fast Refresh force-remount (to avoid corrupted Store state) ([bvaughn](https://github.com/bvaughn) in [facebook#21516](facebook#21516) and [facebook#21523](facebook#21523)) * Errors thrown by Store can be dismissed so DevTools remain usable in many cases ([bvaughn](https://github.com/bvaughn) in [facebook#21520](facebook#21520)) * Bugfix for `useState()` object with `hasOwnProperty` key ([bvaughn](https://github.com/bvaughn) in [facebook#21524](facebook#21524)) * Fixed string concatenation problem when a `Symbol` was logged to `console.error` or `console.warn` ([bvaughn](https://github.com/bvaughn) in [facebook#21521](facebook#21521)) * DevTools: Fixed version range NPM syntax  ([bvaughn](https://github.com/bvaughn) in [9cf1069](facebook@9cf1069#diff)) * Tweaked DevTools error template title to match issue form template ([bvaughn](https://github.com/bvaughn) in [1a2d792](facebook@1a2d792))  ---  ### 4.13.2 May 7, 2021 #### Misc * Improved bug report template to use new [GitHub issue forms](https://gh-community.github.io/issue-template-feedback/structured/) ([bvaughn](https://github.com/bvaughn) in [facebook#21450](facebook#21450))  ---  ### 4.13.1 April 28, 2021 #### Bugfix * Improve display name logic for `React.memo` components ([bvaughn](https://github.com/bvaughn) in [facebook#21392](facebook#21392)) * Fixed potential runtime error with Suspense in versions <= 17 ([bvaughn](https://github.com/bvaughn) in [facebook#21432](facebook#21432)) * Errors thrown in the Store are no longer silent ([bvaughn](https://github.com/bvaughn) in [facebook#21426](facebook#21426))  #### Misc * Improved bug report template ([bvaughn](https://github.com/bvaughn) in [facebook#21413](facebook#21413)), [facebook#21421](facebook#21421))  ---  ### 4.13.0 April 28, 2021 #### Features * Add Bridge protocol version backend/frontend ([bvaughn](https://github.com/bvaughn) in [facebook#21331](facebook#21331))  #### Bugfix * DevTools iterates over siblings during mount (rather than recursing) to avoid stack overflow errors ([bvaughn](https://github.com/bvaughn) in [facebook#21377](facebook#21377)) * Multiple error dialogs can be visible at once ([bvaughn](https://github.com/bvaughn) in [facebook#21370](facebook#21370)) * Console patching should handle Symbols without erroring ([bvaughn](https://github.com/bvaughn) in [facebook#21368](facebook#21368))  ###### Bridge protocol version backend/frontend During initialization, DevTools now checks to ensure it's compatible with the ["backend"](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md#overview) that's embedded within a renderer like React Native. If the two aren't compatible, upgrade instructions will be shown:  <img width="400" height="233" alt="Dialog displaying downgrade instructions for the React DevTools frontend to connect to an older backend version" src="https://user-images.githubusercontent.com/29597/115997927-f77f2a00-a5b2-11eb-9098-20042b664cea.png">      <img width="400" height="233" alt="Dialog displaying upgrade instructions for the React DevTools frontend to connect to a newer backend version" src="https://user-images.githubusercontent.com/29597/115997965-167dbc00-a5b3-11eb-9cbc-082c65077a6e.png">  Learn more about this change at [fb.me/devtools-unsupported-bridge-protocol](https://fb.me/devtools-unsupported-bridge-protocol)  ---  ### 4.12.4 April 19, 2021 #### Bugfix * Remove `@octokit/rest` dependency because of a problem with transitive dependencies ([bvaughn](https://github.com/bvaughn) in [facebook#21317](facebook#21317))  ---  ### 4.12.3 April 19, 2021 #### Bugfix * Wrapped quotation marks around Fiber ids or indices for all DevTools errors to better support GitHub fuzzy error search ([bvaughn](https://github.com/bvaughn) in [facebook#21314](facebook#21314))  ---  ### 4.12.2 April 16, 2021 #### Bugfix * DevTools reliably suppresses console logs when generating component stacks ([bvaughn](https://github.com/bvaughn) in [facebook#21301](facebook#21301))  ---  ### 4.12.1 April 14, 2021 Although this release is being made for all NPM packages, only the `react-devtools-inline` package contains changes. #### Bugfix * Fixed `react-devtools-inline` bug in frontend `initialize` method ([bvaughn](https://github.com/bvaughn) in [facebook#21265](facebook#21265))  ---  ### 4.12.0 April 12, 2021 Although this release is being made for all NPM packages, only the `react-devtools-inline` package contains changes. #### Features * Added `createBridge` and `createStore` exports to the `react-devtools-inline/frontend` entrypoint to support advanced use cases ([bvaughn](https://github.com/bvaughn) in [facebook#21032](facebook#21032))  ---  ### 4.11.1 April 11, 2021 #### Bugfix * Fixed broken import in `react-devtools-inline` for feature flags file ([bvaughn](https://github.com/bvaughn) in [facebook#21237](facebook#21237))  ---  ### 4.11.0 April 9, 2021 #### Bugfix * `$r` should contain hooks property when it is `forwardRef` or `memo` component  ([meowtec](https://github.com/meowtec) in [facebook#20626](facebook#20626)) * Ensure `sync-xhr` is allowed before reload and profile ([ChrisDobby](https://github.com/ChrisDobby) in [facebook#20879](facebook#20879)) * Bump electron version from 9.1.0 to 11.1.0 for darwin-arm64 builds ([jaiwanth-v](https://github.com/jaiwanth-v) in [facebook#20496](facebook#20496)) * Fixed primitive hook badge colors for light theme ([bvaughn](https://github.com/bvaughn) in [facebook#21034](facebook#21034)) * Increased minimum Chrome/Firefox versions from 51/54 to 60/55 to reduce polyfill code. ([bvaughn](https://github.com/bvaughn) in [facebook#21185](facebook#21185)) * Fix can't expand prop value in some scenario ([iChenLei](https://github.com/iChenLei) in [facebook#20534](facebook#20534)) * Flush updated passive warning/error info after delay ([bvaughn](https://github.com/bvaughn) in [facebook#20931](facebook#20931)) * Patch console methods even when only show-inline-warnings/errors enabled ([bvaughn](https://github.com/bvaughn) in [facebook#20688](facebook#20688)) * React Native fixes for new inline errors feature ([bvaughn](https://github.com/bvaughn) in [facebook#20502](facebook#20502)) * Fixed invalid work tag constants that affected a certain range of React versions ([bvaughn](https://github.com/bvaughn) in [facebook#20362](facebook#20362))  #### Features * Improve Profiler commit-selector UX ([bvaughn](https://github.com/bvaughn) in [facebook#20943](facebook#20943)) * Swap `log` with `cbrt` for commit bar height ([bvaughn](https://github.com/bvaughn) in [facebook#20952](facebook#20952)) * Integrate with new experimental React Suspense features to improve props loading and inspection UX ([bvaughn](https://github.com/bvaughn) in [facebook#20548](facebook#20548), [facebook#20789](facebook#20789), [facebook#20458](facebook#20458)) * Expose DEV-mode warnings in devtools UI ([eps1lon](https://github.com/eps1lon) in [facebook#20463](facebook#20463)) * Display shortcuts for prev/next search result ([eps1lon](https://github.com/eps1lon) in [facebook#20470](facebook#20470)) * Increase the clickable area of the prop value ([TryingToImprove](https://github.com/TryingToImprove) in [facebook#20428](facebook#20428))  #### Experimental features The following features are only enabled when used with (experimental) builds of React: * Shows which fibers scheduled the current update ([bvaughn](https://github.com/bvaughn) in [facebook#21171](facebook#21171)) * Add commit and post-commit durations to Profiler UI ([bvaughn](https://github.com/bvaughn) in [facebook#20984](facebook#20984), [facebook#21183](facebook#21183)) * Show which hooks (indices) changed when profiling ([bvaughn](https://github.com/bvaughn) in [facebook#20998](facebook#20998))  ###### Improve Profiler commit-selector UX  ![Video demonstrating tooltip with commit duration and time](https://user-images.githubusercontent.com/29597/110225725-30a1f480-7eb6-11eb-9825-4c762ffde0bb.gif)  ![Graphic illustrating Profiler bar heights using different scales](https://user-images.githubusercontent.com/29597/110361997-bafd6c00-800e-11eb-92d8-d411e6c79d84.png)  ###### Expose DEV-mode warnings in devtools UI ![Inline warnings and errors](https://user-images.githubusercontent.com/29597/114225729-adeed800-9940-11eb-8df2-34d8b0ead3b8.png)  ###### Shows which fibers scheduled the current update ![Shows which fibers scheduled the current update](https://user-images.githubusercontent.com/29597/114225931-eee6ec80-9940-11eb-90cc-fe6630fbfc08.gif)  ###### Add commit and post-commit durations to Profiler UI ![Add commit and post-commit durations to Profiler UI](https://user-images.githubusercontent.com/29597/114225991-00c88f80-9941-11eb-84df-e2af04ecef1c.gif)  ###### Show which hooks (indices) changed when profiling ![Show which hooks (indices) changed when profiling](https://user-images.githubusercontent.com/29597/114225838-d37be180-9940-11eb-93f8-93e0115421c8.png)  ---  ### 4.10.4 May 20, 2021 #### Bugfix * Ported passive effects sync flushing/bubbling bugfix ([bvaughn](https://github.com/bvaughn) in [facebook#21540](facebook#21540))  ---  ### 4.10.3 April 27, 2021 #### Bugfix * Replaced Facebook-internal fburl.com link with public fb.me link for Bridge protocol mismatch info page ([bvaughn](https://github.com/bvaughn) in [facebook#21344](facebook#21344))  ---  ### 4.10.2 April 27, 2021 #### Features * Added Bridge protocol check and warning dialog if embedded DevTools backend is incompatible with DevTools UI ([bvaughn](https://github.com/bvaughn) in [facebook#21344](facebook#21344))  ---  ### 4.10.1 November 12, 2020 #### Bugfix * Fixed invalid internal work tag mappings ([bvaughn](https://github.com/bvaughn) in [facebook#20362](facebook#20362))  ---  ### 4.10.0 November 12, 2020 #### Features * Make DevTools Websocket retry delay configurable ([bvaughn](https://github.com/bvaughn) in [facebook#20107](facebook#20107)) #### Bugfix * Fix error loading source maps for devtools extension ([sytranvn](https://github.com/sytranvn) in [facebook#20079](facebook#20079)) * Remove css-sourcemap for `react-devtools-inline` ([sean9keenan](https://github.com/sean9keenan) in [facebook#20170](facebook#20170)) * Decrease NPM update notification/prompt for standalone DevTools ([recurx](https://github.com/recurx) in [facebook#20078](facebook#20078))  ---  ### 4.9.0 October 19, 2020 #### Features * [Improved DevTools editing interface](#improved-devtools-editing-interface) ([bvaughn](https://github.com/bvaughn) in [facebook#19774](facebook#19774)) * Add ⎇ + arrow key navigation ([bvaughn](https://github.com/bvaughn) in [facebook#19741](facebook#19741)) * Add checkbox toggle for boolean values ([mdaj06](https://github.com/mdaj06) in [facebook#19714](facebook#19714)) * Show symbols used as keys in state ([omarsy](https://github.com/omarsy) in [facebook#19786](facebook#19786)) * Add new (unstable) `SuspenseList` component type ([bpernick](https://github.com/bpernick) in [facebook#19684](facebook#19684))  #### Bugfix * Show proper icon/tooltip for restricted browser pages ([sktguha](https://github.com/sktguha) in [facebook#20023](facebook#20023)) * Fix emoji character shown in Chrome developer tools panel ([bvaughn](https://github.com/bvaughn) in [facebook#19603](facebook#19603)) * Don't open two tabs in Firefox when clicking on troubleshooting instructions ([unbyte](https://github.com/unbyte) in [facebook#19632](facebook#19632)) * Support inner component `_debugOwner` in memo ([bvaughn](https://github.com/bvaughn) in [facebook#19556](facebook#19556)) * Proxied methods should be safely dehydrated for display ([@pfongkye](https://github.com/pfongkye) in [b6e1d08](facebook@b6e1d08) * Property list values should show whitespace ([sammarks](https://github.com/sammarks) in [facebook#19640](facebook#19640)) * Fix crash when inspecting document.all ([omarsy](https://github.com/omarsy) in [facebook#19619](facebook#19619)) * Don't call generators during inspection since they may be stateful ([todortotev](https://github.com/todortotev) in [facebook#19831](facebook#19831)) * Fix bad null check in DevTools highlight code ([bvaughn](https://github.com/bvaughn) in [facebook#20010](facebook#20010)) * Handled a missing suspense fiber when suspense is filtered on the profiler ([IDrissAitHafid](https://github.com/IDrissAitHafid) in [#ISSUE](https://github.com/facebook/react/pull/ISSUE)) * Fixed unfound node error when Suspense is filtered ([IDrissAitHafid](https://github.com/IDrissAitHafid) in [facebook#20019](facebook#20019)) * Always overrides the dispatcher when shallow rendering ([bvaughn](https://github.com/bvaughn) in [facebook#20011](facebook#20011)) * Frevent phishing attacks ([iamwilson](https://github.com/iamwilson) in [facebook#19934](facebook#19934))  ---  ### Other * Enable source maps for DevTools production builds ([jpribyl ](https://github.com/jpribyl ) in [facebook#19773](facebook#19773)) * Drop support for IE 11 ([bvaughn](https://github.com/bvaughn) in [facebook#19875](facebook#19875)) * Remove ReactJS.org version check "cheat" ([sktguha](https://github.com/sktguha) in [facebook#19939](facebook#19939)) * Update outdated links and fix two broken links ([sktguha](https://github.com/sktguha) in [facebook#19985](facebook#19985)) * Remove support for deprecated/unreleased React Flare event system ([trueadm](https://github.com/trueadm) in [facebook#19520](facebook#19520))  ###### Improved DevTools editing interface  **Improved parsing** Value parsing logic has been relaxed so as to no longer require quotes around strings or double quotes: ![looser parsing logic](https://user-images.githubusercontent.com/29597/93407442-36504300-f860-11ea-90e8-5ad54c9b8b34.gif)  **Modifying arrays** New values can be added to array props/state/hooks now. Existing values can also be deleted: ![adding and removing values from an array](https://user-images.githubusercontent.com/29597/93407457-3ea87e00-f860-11ea-8b85-a41904e6c25f.gif)  **Modifying objects** New keys can be added to object props/state/hooks now. Existing keys can be renamed or deleted entirely: ![adding/renaming/removing object properties](https://user-images.githubusercontent.com/29597/93407464-449e5f00-f860-11ea-909b-49dafb56f6c5.gif)  ---  ### 4.8.2 July 15, 2020 #### Bugfix * Fix broken `Suspense` heuristic ([bvaughn](https://github.com/bvaughn) in [facebook#19373](facebook#19373)) * Fixed error with standalone in HTTPS mode ([b-ponomarenko](https://github.com/b-ponomarenko) in [facebook#19336](facebook#19336)) * Disable DevTools minification ([bvaughn](https://github.com/bvaughn) in [facebook#19369](facebook#19369))  ---  ### 4.8.1 July 10, 2020 #### Bugfix * Fix break-on-warning to truly be off by default. ([gaearon](https://github.com/gaearon) in [facebook#19309](facebook#19309))  ---  ### 4.8.0 July 9, 2020 #### Features * Add SSL support to React devtools standalone ([ittaibaratz](https://github.com/ittaibaratz) in [facebook#19191](facebook#19191)) * New break-on-warning feature (off by default) ([bvaughn](https://github.com/bvaughn) in [facebook#19048](facebook#19048))  #### Bugfix * Updates Electron version for react-devtools to pull in several security fixes ([gsimone](https://github.com/gsimone) in [facebook#19280](facebook#19280)) * Remove unnecessary tag end from CommitRanked view ([finico](https://github.com/finico) in [facebook#19195](facebook#19195)) * Shutdown DevTools Bridge synchronously when unmounting ([bvaughn](https://github.com/bvaughn) in [facebook#19180](facebook#19180))  ---  ### 4.7.0 May 18, 2020  #### Features * Improved appended component stacks for third party warnings to be more like native ([bvaughn](https://github.com/bvaughn) in [facebook#18656](facebook#18656)) * Improve inline search results by highlighting match on HOC badge ([bl00mber](https://github.com/bl00mber) in [facebook#18802](facebook#18802)) * Add key badge to inspected element in right hand pane ([karlhorky]](https://github.com/karlhorky) in [facebook#18737](facebook#18737)) * Improve Profiler snapshot selector drag-and-drop UX ([bl00mber](https://github.com/bl00mber) in [facebook#18852](facebook#18852)) * Profiler tooltip now includes self duration to make it easier to scan times without requiring selection ([bvaughn](https://github.com/bvaughn) in [facebook#18510](facebook#18510)) * Rendered by list also now highlights native elements on hover ([hristo-kanchev](https://github.com/hristo-kanchev) in [facebook#18479](facebook#18479)) * Add in-page highlighting for mouse-over interactions in Profiler ([bl00mber](https://github.com/bl00mber) in [facebook#18745](facebook#18745))  #### Bugfix * Fix Profiler bug "_Could not find commit data for root_" by resetting selected node on root change ([bl00mber](https://github.com/bl00mber) in [facebook#18880](facebook#18880)) * Add `imported` flag to Profiling data to more reliably differentiate between imported and session data ([bl00mber](https://github.com/bl00mber) in [facebook#18913](facebook#18913)) * Disable Profiler filtering to avoid edge case runtime error "_Cannot read property 'duration' of undefined_" ([bvaughn](https://github.com/bvaughn) in [facebook#18862](facebook#18862)) * Fix Profiler bug "_cannot read property 'memoizedState' of null_" ([bvaughn](https://github.com/bvaughn) in [facebook#18522](facebook#18522)) * Whitespace search results highlighting bug fix ([bvaughn](https://github.com/bvaughn) in [facebook#18527](facebook#18527)) * Improved confusing Profiler tooltip text for components that did not render ([bvaughn](https://github.com/bvaughn) in [facebook#18523](facebook#18523)) * Fix edge case performance issue when highlight elements enabled ([Faelivrinx](https://github.com/Faelivrinx) in [facebook#18498](facebook#18498)) * Disabled Webpack auto polyfill for `setImmediate` ([bvaughn](https://github.com/bvaughn) in [facebook#18860](facebook#18860)) * Fix mouse interactions for standalone DevTools on Linux ([bl00mber](https://github.com/bl00mber) in [facebook#18772](facebook#18772))  ---  ### 4.6.0 March 26, 2020  #### Features * Add shortcut keys for tab switching ([kerolloz](https://github.com/kerolloz) in [facebook#18248](facebook#18248))  #### Bugfix * Improve display of complex values for `useDebugValue` ([eps1lon](https://github.com/eps1lon) in [facebook#18070](facebook#18070)) * Fix minor CSS layout issue that broke Profiler commit selector UI ([bvaughn](https://github.com/bvaughn) in [facebook#18286](facebook#18286)) * Inlined DevTools event emitter implementation to fix a source of Profiler bugs ([bvaughn](https://github.com/bvaughn) in [facebook#18378](facebook#18378))  #### Cleanup * Remove "es6-symbol" dependency from "react-devtools-inline" package ([bvaughn](https://github.com/bvaughn) in [facebook#18397](facebook#18397))  ---  ### 4.5.0 March 3, 2020  #### Features * Improve function props display for inspected elements ([bvaughn](https://github.com/bvaughn) in [facebook#17789](facebook#17789)) * Re-enabled context menu for Firefox extension ([bvaughn](https://github.com/bvaughn) in [facebook#17838](facebook#17838)) * Apply changes to props/state/hooks on blur (rather than on ENTER) ([muratcatal](https://github.com/muratcatal) in [facebook#17062](facebook#17062)) * Add info tooltip to nodes in Profiler ([M-Izadmehr](https://github.com/M-Izadmehr) in [facebook#18048](facebook#18048)) * Added resize support to Components panel ([hristo-kanchev](https://github.com/hristo-kanchev) in [facebook#18046](facebook#18046))  #### Bugfix * Improve how empty commits are filtered ([nutboltu](https://github.com/nutboltu) in [facebook#17931](facebook#17931)) * BigInt serialize issue in devtools copy to clipboard ([bvaughn](https://github.com/bvaughn) in [facebook#17771](facebook#17771)) * Renamed "backend.js" to "react_devtools_backend.js" to reduce potential confusion from profiling ([bvaughn](https://github.com/bvaughn) in [facebook#17790](facebook#17790)) * Update root styles to prevent `box-sizing` style from leaking outside of inline target ([GasimGasimzada](https://github.com/GasimGasimzada) in [facebook#17775](facebook#17775)) * Fix "_Cannot read property 'sub' of undefined_" error when navigating to plain-text pages ([wfnuser](https://github.com/wfnuser) in [facebook#17848](facebook#17848)) * Fix potential error with composite hooks during shallow re-rendering ([bvaughn](https://github.com/bvaughn) in [facebook#18130](facebook#18130)) * Scope dev tools wildcard styles within DevTools CSS class ([@GasimGasimzada](https://github.com/GasimGasimzada) in [9cc094a](facebook@9cc094a#diff-ab5ee5655b2aac3260e1f836546a13c9))  ###### Info summary tooltips  ![Profiler tooltips in Flamegraph chart](https://user-images.githubusercontent.com/28848972/74614074-09468100-5115-11ea-8c87-c224d229ef15.gif)  ![Profiler tooltips in Ranked chart](https://user-images.githubusercontent.com/28848972/74614072-08155400-5115-11ea-8d19-7ab3d27b9b0a.gif)  ###### Components panel resize  ![Horizontal Components panel resizing](https://user-images.githubusercontent.com/23095052/74603147-ca7edf80-50b0-11ea-887f-db7ada855c50.gif)  ![Vertical Components panel resizing](https://user-images.githubusercontent.com/23095052/74603149-d074c080-50b0-11ea-820f-63db30b4c285.gif)  ---  ### 4.4.0 January 3, 2020 #### Features * Re-enabled "copy" prop/state/hooks context menu option for Firefox ([bvaughn](https://github.com/bvaughn),[rpl](https://github.com/rpl) in [facebook#17740](facebook#17740)) * Shift+Enter focuses previous search result in Components tree ([Bo-Duke](https://github.com/Bo-Duke) in [facebook#17005](facebook#17005)) * Properly display formatted `RegExp` values in props/state panel([bvaughn](https://github.com/bvaughn) in [facebook#17690](facebook#17690)) * Profiler commit selector wraps around for easier navigation of large profiles ([bvaughn](https://github.com/bvaughn) in [facebook#17760](facebook#17760)) #### Bugfix * Check `document.contentType` before injecting hook to avoid breaking XML file syntax highlighting in Firefox ([bvaughn](https://github.com/bvaughn) in [facebook#17739](facebook#17739)) * Fix standalone UI not responding to mouse interactions due to `webkit-app-region` style ([cwatson88](https://github.com/cwatson88) in [facebook#17584](facebook#17584)) * Support inspecting object values with null protos ([bvaughn](https://github.com/bvaughn) in [facebook#17757](facebook#17757)) * Support inspecting values that have overridden `hasOwnProperty` attribute ([bvaughn](https://github.com/bvaughn) in [facebook#17768](facebook#17768)) * Fixed regression that made Profiler "Could not find node…" error happen more frequently ([bvaughn](https://github.com/bvaughn) in [facebook#17759](facebook#17759))  ---  ### 4.3.0 December 20, 2019 #### Features * Show component location for selected element in bottom/right panel ([bvaughn](https://github.com/bvaughn) in [facebook#17567](facebook#17567)) * Improved inspected element values with inline previews ([bvaughn](https://github.com/bvaughn) in [facebook#17579](facebook#17579)) * Improved selection and toggling for inspected element panel ([bvaughn](https://github.com/bvaughn) in [facebook#17588](facebook#17588)) * Copy context menu for inspecting and copying props/state/hooks/context values ([bvaughn](https://github.com/bvaughn) in [facebook#17608](facebook#17608)) #### Bug fixes * Fix serialization for `BigInt` type so that it does not break inspection panel. ([nutboltu](https://github.com/nutboltu) in [facebook#17233](facebook#17233)) * Fix display name logic for `forwardRef`s that use `displayName` property ([zthxxx](https://github.com/zthxxx) in [facebook#17613](facebook#17613))  ---  ### 4.2.1 November 27, 2019 #### Bug fixes * Profiler automatically filters certain types of empty (no work) commits. ([bvaughn](https://github.com/bvaughn) in [facebook#17253](facebook#17253)) * Fix memoized components showing as "Anonymous" in Components tab. ([wsmd](https://github.com/wsmd) in [facebook#17274](facebook#17274)) * Edge-case bugfix for non-string element keys. ([bvaughn](https://github.com/bvaughn) in [facebook#17164](facebook#17164))  ---  ### 4.2.0 October 3, 2019 #### Features * "Highlight updates" feature added for browser extensions and `react-devtools-inline` NPM package. ([bvaughn](https://github.com/bvaughn) in [facebook#16989](facebook#16989))  ---  ### 4.1.3 September 30, 2019 #### Bug fixes * Fixed regression where DevTools wouldn't properly connect with apps when using the `file://` protocol. ([linshunghuang](https://github.com/linshunghuang) in [facebook#16953](facebook#16953))  ---  ### 4.1.2 September 27, 2019 #### Bug fixes * Fixed an infinite loop that occurred in some cases with prop values of `NaN`. ([bvaughn](https://github.com/bvaughn) in [facebook#16934](facebook#16934))  ---  ### 4.1.1 September 26, 2019 #### Bug fixes * Fixed bug where Components panel was always empty for certain users. ([linshunghuang](https://github.com/linshunghuang) in [facebook#16900](facebook#16900)) * Fixed regression in DevTools editable hooks interface that caused primitive values to be shown as `undefined`. ([bvaughn](https://github.com/bvaughn) in [facebook#16867](facebook#16867)) * Fixed bug where DevTools showed stale values in props/state/hooks editing interface. ([bvaughn](https://github.com/bvaughn) in [facebook#16878](facebook#16878)) * Show unsupported version dialog with downgrade instructions. ([bvaughn](https://github.com/bvaughn) in [facebook#16897](facebook#16897))  ---  ### 4.1.0 September 19, 2019 #### Features * Props/state editor supports adding new values and changing value types. ([hristo-kanchev](https://github.com/hristo-kanchev) in [facebook#16700](facebook#16700)) #### Bug fixes * Profiler correctly saves/exports profiling data in Firefox now. ([hristo-kanchev](https://github.com/hristo-kanchev) in [facebook#16612](facebook#16612)) * Class components now show "legacy context" header (rather than "context") for legacy API. ([hristo-kanchev](https://github.com/hristo-kanchev) in [facebook#16617](facebook#16617)) * Show component source button ("<>") now highlights the `render` method for class components. ([theKashey](https://github.com/theKashey) in [facebook#16759](facebook#16759)) * Bugfix for components with non-standard object values for `function.name`. ([LetItRock](https://github.com/LetItRock) in [facebook#16798](facebook#16798))  ---  ### 4.0.6 August 26, 2019 #### Bug fixes * Remove ⚛️ emoji prefix from Firefox extension tab labels * Standalone polyfills `Symbol` usage  ---  ### 4.0.5 August 19, 2019 #### Bug fixes * Props, state, and context values are alpha sorted. * Standalone DevTools properly serves backend script over localhost:8097  ---  ### 4.0.4 August 18, 2019 #### Bug fixes * Bugfix for potential error if a min-duration commit filter is applied after selecting a fiber in the Profiler UI.  ---  ### 4.0.3 August 17, 2019 #### Bug fixes * ES6 `Map` and `Set`, typed arrays, and other unserializable types (e.g. Immutable JS) can now be inspected. * Empty objects and arrays now display an "(empty)" label to the right to reduce confusion. * Components that use only the `useContext` hook now properly display hooks values in side panel. * Style editor now supports single quotes around string values (e.g. both `"red"` and `'red'`). * Fixed edge case bug that prevented profiling when both React v16 and v15 were present on a page.  ---  ### 4.0.2 August 15, 2019 #### Permissions cleanup * Removed unnecessary `webNavigation ` permission from Chrome and Firefox extensions.  ---  ### 4.0.1 August 15, 2019 #### Permissions cleanup * Removed unnecessary `<all_urls>`, `background`, and `tabs` permissions from Chrome and Firefox extensions.  ---  ### 4.0.0 August 15, 2019  ---  ### General changes  #### Improved performance The legacy DevTools extension used to add significant performance overhead, making it unusable for some larger React applications. That overhead has been effectively eliminated in version 4.  [Learn more](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md) about the performance optimizations that made this possible.  #### Component stacks  React component authors have often requested a way to log warnings that include the React ["component stack"](https://reactjs.org/docs/error-boundaries.html#component-stack-traces). DevTools now provides an option to automatically append this information to warnings (`console.warn`) and errors (`console.error`).  ![Example console warning with component stack added](https://user-images.githubusercontent.com/29597/62228120-eec3da80-b371-11e9-81bb-018c1e577389.png)  It can be disabled in the general settings panel:  ![Settings panel showing "component stacks" option](https://user-images.githubusercontent.com/29597/62227882-8f65ca80-b371-11e9-8a4e-5d27011ad1aa.png)  ---  ### Components tree changes  #### Component filters  Large component trees can sometimes be hard to navigate. DevTools now provides a way to filter components so that you can hide ones you're not interested in seeing.  ![Component filter demo video](https://user-images.githubusercontent.com/29597/62229209-0bf9a880-b374-11e9-8f84-cebd6c1a016b.gif)  Host nodes (e.g. HTML `<div>`, React Native `View`) are now hidden by default, but you can see them by disabling that filter.  Filter preferences are remembered between sessions.  #### No more inline props  Components in the tree no longer show inline props. This was done to [make DevTools faster](https://github.com/facebook/react/blob/main/packages/react-devtools/OVERVIEW.md) and to make it easier to browse larger component trees.  You can view a component's props, state, and hooks by selecting it:  ![Inspecting props](https://user-images.githubusercontent.c…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants