Repository: angular/angular
File: packages/core/src/render3/di.ts (TypeScript)

Code before:
/**
 * Used in ngDevMode to keep the injection path in case of cycles in DI.
 */
let injectionPath: string[] = [];

/**
 * Retrieve or instantiate the injectable from the `LView` at particular `index`.
 *
 * This function checks to see if the value has already been instantiated and if so returns the
 * cached `injectable`. Otherwise if it detects that the value is still a factory it
 * instantiates the `injectable` and caches the value.
 */
export function getNodeInjectable(
  lView: LView,
  tView: TView,
  index: number,
  tNode: TDirectiveHostNode,
  flags?: InternalInjectFlags,
): any {
  let value = lView[index];
  const tData = tView.data;
  if (value instanceof NodeInjectorFactory) {
    const factory: NodeInjectorFactory = value;
    ngDevMode && injectionPath.push(factory.name ?? 'unknown');
    if (factory.resolving) {
      const token = stringifyForError(tData[index]);
      if (ngDevMode) {
        throw cyclicDependencyErrorWithDetails(token, injectionPath);
      } else {
        throw cyclicDependencyError(token);
      }
    }
    const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
    factory.resolving = true;

    // tData indexes mirror the concrete instances in its corresponding LView.
    // lView[index] here is either the injectable instance itself or a factory,
    // therefore tData[index] is the constructor of that injectable or a
    // definition object that contains the constructor in a `.type` field.
    const token =
      (tData[index] as DirectiveDef<unknown> | ComponentDef<unknown>).type || tData[index];

    let prevInjectContext: InjectorProfilerContext | undefined;
    if (ngDevMode) {
      const injector = new NodeInjector(tNode, lView);
      prevInjectContext = setInjectorProfilerContext({injector, token});
    }

    const previousInjectImplementation = factory.injectImpl
      ? setInjectImplementation(factory.injectImpl)
      : null;

Review comment (bug):
I'm not sure we can do this. DI errors can still show up in production and this will make it harder to debug.

Code after:
/**
 * Used in ngDevMode to keep the injection path in case of cycles in DI.
 */
let injectionPath: string[] = [];

/**
 * Retrieve or instantiate the injectable from the `LView` at particular `index`.
 *
 * This function checks to see if the value has already been instantiated and if so returns the
 * cached `injectable`. Otherwise if it detects that the value is still a factory it
 * instantiates the `injectable` and caches the value.
 */
export function getNodeInjectable(
  lView: LView,
  tView: TView,
  index: number,
  tNode: TDirectiveHostNode,
  flags?: InternalInjectFlags,
): any {
  let value = lView[index];
  const tData = tView.data;
  if (value instanceof NodeInjectorFactory) {
    const factory: NodeInjectorFactory = value;
    ngDevMode && injectionPath.push(factory.name ?? 'unknown');
    if (factory.resolving) {
      let token = '';
      if (ngDevMode) {
        token = stringifyForError(tData[index]);
        throw cyclicDependencyErrorWithDetails(token, injectionPath);
      } else {
        throw cyclicDependencyError(token);
      }
    }
    const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
    factory.resolving = true;

    // tData indexes mirror the concrete instances in its corresponding LView.
    // lView[index] here is either the injectable instance itself or a factory,
    // therefore tData[index] is the constructor of that injectable or a
    // definition object that contains the constructor in a `.type` field.
    const token =
      (tData[index] as DirectiveDef<unknown> | ComponentDef<unknown>).type || tData[index];

    let prevInjectContext: InjectorProfilerContext | undefined;
    if (ngDevMode) {
      const injector = new NodeInjector(tNode, lView);
      prevInjectContext = setInjectorProfilerContext({injector, token});
    }

    const previousInjectImplementation = factory.injectImpl
      ? setInjectImplementation(factory.injectImpl)