Repository: facebook/react
Pull request: Add more feature flag checks

This strips some more content out of the stable build.

A neat trick for finding missing feature flag checks is to find Symbol.for usages that shouldn't be there.

Unfortunately these Symbols don't get DCE. I think that's because they're still used in `case` statements.

Rollout removes most of our Symbol.for calls but it's not smart enough in all cases. Closure doesn't seem smart enough to know it's not a side-effect. So the net effect is that we still have some unused `Symbol.for(...)` calls in the bundle. After this change they're not used though.

Changed files:
filename: packages/react-reconciler/src/ReactFiber.new.js
patch: @@ -26,6 +26,7 @@ import {
   enableSyncDefaultUpdates,
   allowConcurrentByDefault,
   enableTransitionTracing,
+  enableDebugTracing,
 } from 'shared/ReactFeatureFlags';
 import {
   supportsPersistence,
@@ -492,10 +493,6 @@ export function createFiberFromTypeAndProps(
     getTag: switch (type) {
       case REACT_FRAGMENT_TYPE:
         return createFiberFromFragment(pendingProps.children, mode, lanes, key);
-      case REACT_DEBUG_TRACING_MODE_TYPE:
-        fiberTag = Mode;
-        mode |= DebugTracingMode;
-        break;
       case REACT_STRICT_MODE_TYPE:
         fiberTag = Mode;
         mode |= StrictLegacyMode;
@@ -529,6 +526,13 @@ export function createFiberFromTypeAndProps(
           return createFiberFromTracingMarker(pendingProps, mode, lanes, key);
         }
       // eslint-disable-next-line no-fallthrough
+      case REACT_DEBUG_TRACING_MODE_TYPE:
+        if (enableDebugTracing) {
+          fiberTag = Mode;
+          mode |= DebugTracingMode;
+          break;
+        }
+      // eslint-disable-next-line no-fallthrough
       default: {
         if (typeof type === 'object' && type !== null) {
           switch (type.$$typeof) {

filename: packages/react-reconciler/src/ReactFiber.old.js
patch: @@ -26,6 +26,7 @@ import {
   enableSyncDefaultUpdates,
   allowConcurrentByDefault,
   enableTransitionTracing,
+  enableDebugTracing,
 } from 'shared/ReactFeatureFlags';
 import {
   supportsPersistence,
@@ -492,10 +493,6 @@ export function createFiberFromTypeAndProps(
     getTag: switch (type) {
       case REACT_FRAGMENT_TYPE:
         return createFiberFromFragment(pendingProps.children, mode, lanes, key);
-      case REACT_DEBUG_TRACING_MODE_TYPE:
-        fiberTag = Mode;
-        mode |= DebugTracingMode;
-        break;
       case REACT_STRICT_MODE_TYPE:
         fiberTag = Mode;
         mode |= StrictLegacyMode;
@@ -529,6 +526,13 @@ export function createFiberFromTypeAndProps(
           return createFiberFromTracingMarker(pendingProps, mode, lanes, key);
         }
       // eslint-disable-next-line no-fallthrough
+      case REACT_DEBUG_TRACING_MODE_TYPE:
+        if (enableDebugTracing) {
+          fiberTag = Mode;
+          mode |= DebugTracingMode;
+          break;
+        }
+      // eslint-disable-next-line no-fallthrough
       default: {
         if (typeof type === 'object' && type !== null) {
           switch (type.$$typeof) {

filename: packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js
patch: @@ -45,7 +45,7 @@ describe('DebugTracing', () => {
     });
   });
 
-  // @gate experimental || www
+  // @gate enableDebugTracing
   it('should not log anything for sync render without suspends or state updates', () => {
     ReactTestRenderer.create(
       <React.unstable_DebugTracingMode>
@@ -56,8 +56,7 @@ describe('DebugTracing', () => {
     expect(logs).toEqual([]);
   });
 
-  // @gate build === 'development'
-  // @gate experimental || www
+  // @gate experimental && build === 'development' && enableDebugTracing
   it('should not log anything for concurrent render without suspends or state updates', () => {
     ReactTestRenderer.act(() =>
       ReactTestRenderer.create(
@@ -376,8 +375,7 @@ describe('DebugTracing', () => {
     ]);
   });
 
-  // @gate build === 'development'
-  // @gate experimental || www
+  // @gate experimental && build === 'development' && enableDebugTracing
   it('should not log anything outside of a unstable_DebugTracingMode subtree', () => {
     function ExampleThatCascades() {
       const [didMount, setDidMount] = React.useState(false);

filename: packages/shared/getComponentNameFromType.js
patch: @@ -26,6 +26,8 @@ import {
   REACT_TRACING_MARKER_TYPE,
 } from 'shared/ReactSymbols';
 
+import {enableTransitionTracing, enableCache} from './ReactFeatureFlags';
+
 // Keep in sync with react-reconciler/getComponentNameFromFiber
 function getWrappedName(
   outerType: mixed,
@@ -79,9 +81,14 @@ export default function getComponentNameFromType(type: mixed): string | null {
     case REACT_SUSPENSE_LIST_TYPE:
       return 'SuspenseList';
     case REACT_CACHE_TYPE:
-      return 'Cache';
+      if (enableCache) {
+        return 'Cache';
+      }
+    // eslint-disable-next-line no-fallthrough
     case REACT_TRACING_MARKER_TYPE:
-      return 'TracingMarker';
+      if (enableTransitionTracing) {
+        return 'TracingMarker';
+      }
   }
   if (typeof type === 'object') {
     switch (type.$$typeof) {

filename: packages/shared/isValidElementType.js
patch: @@ -29,6 +29,7 @@ import {
   enableScopeAPI,
   enableCache,
   enableTransitionTracing,
+  enableDebugTracing,
 } from './ReactFeatureFlags';
 
 const REACT_MODULE_REFERENCE: Symbol = Symbol.for('react.module.reference');
@@ -42,7 +43,7 @@ export default function isValidElementType(type: mixed) {
   if (
     type === REACT_FRAGMENT_TYPE ||
     type === REACT_PROFILER_TYPE ||
-    type === REACT_DEBUG_TRACING_MODE_TYPE ||
+    (enableDebugTracing && type === REACT_DEBUG_TRACING_MODE_TYPE) ||
     type === REACT_STRICT_MODE_TYPE ||
     type === REACT_SUSPENSE_TYPE ||
     type === REACT_SUSPENSE_LIST_TYPE ||