Repository: facebook/react
File: packages/react-debug-tools/src/ReactDebugHooks.js (JavaScript)

Code before:
    primitiveStackCache = cache;
  }
  return primitiveStackCache;
}

let currentFiber: null | Fiber = null;
let currentHook: null | Hook = null;
let currentContextDependency: null | ContextDependency<mixed> = null;

function nextHook(): null | Hook {
  const hook = currentHook;
  if (hook !== null) {
    currentHook = hook.next;
  }
  return hook;
}

function readContext<T>(context: ReactContext<T>): T {
  if (context === GetPrimitiveStackCacheContext) {
    // This is a read for filling the primitive stack cache.
    // There's no sensible value to return.
    return (null: any);
  }
  if (currentFiber === null) {
    // Hook inspection without access to the Fiber tree.
    return context._currentValue;
  }
  if (currentContextDependency === null) {
    throw new Error(
      'Context reads do not line up with context dependencies. This is a bug in React.',
    );
  }

  // For now we don't expose readContext usage in the hooks debugging info.
  const value = ((currentContextDependency.memoizedValue: any): T);
  currentContextDependency = currentContextDependency.next;

  return value;
}

const SuspenseException: mixed = new Error(
  "Suspense Exception: This is not a real error! It's an implementation " +
    'detail of `use` to interrupt the current render. You must either ' +
    'rethrow it immediately, or move the `use` call outside of the ' +
    '`try/catch` block. Capturing without rethrowing will lead to ' +
    'unexpected behavior.\n\n' +
    'To handle async errors, wrap your component in an error boundary, or ' +
    "call the promise's `.catch` method and pass the result to `use`",
);

function use<T>(usable: Usable<T>): T {

Review comment (bug):
This is only for `ReactDebugTools.inspectHooks` where we don't have access to the current fiber (we have tests that would break if we throw just because `currentContextDependency` is null). 

Code after:
    for (let i = 0; i < readHookLog.length; i++) {
      const hook = readHookLog[i];
      cache.set(hook.primitive, ErrorStackParser.parse(hook.stackError));
    }
    primitiveStackCache = cache;
  }
  return primitiveStackCache;
}

let currentFiber: null | Fiber = null;
let currentHook: null | Hook = null;
let currentContextDependency: null | ContextDependency<mixed> = null;

function nextHook(): null | Hook {
  const hook = currentHook;
  if (hook !== null) {
    currentHook = hook.next;
  }
  return hook;
}

function readContext<T>(context: ReactContext<T>): T {
  if (currentFiber === null) {
    // Hook inspection without access to the Fiber tree
    // e.g. when warming up the primitive stack cache or during `ReactDebugTools.inspectHooks()`.
    return context._currentValue;
  } else {
    if (currentContextDependency === null) {
      throw new Error(
        'Context reads do not line up with context dependencies. This is a bug in React Debug Tools.',
      );
    }

    // For now we don't expose readContext usage in the hooks debugging info.
    const value = hasOwnProperty.call(currentContextDependency, 'memoizedValue')
      ? // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
        ((currentContextDependency.memoizedValue: any): T)
      : // Before React 18, we did not have `memoizedValue` so we rely on `setupContexts` in those versions.
        // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
        ((currentContextDependency.context._currentValue: any): T);
    // $FlowFixMe[incompatible-use] Flow thinks `hasOwnProperty` mutates `currentContextDependency`
    currentContextDependency = currentContextDependency.next;

    return value;
  }
}

const SuspenseException: mixed = new Error(
  "Suspense Exception: This is not a real error! It's an implementation " +
    'detail of `use` to interrupt the current render. You must either ' +
    'rethrow it immediately, or move the `use` call outside of the ' +