Repository: babel/babel
File: packages/babel-traverse/src/visitors.ts (TypeScript)

Code before:
      );
    }
  }
}

export function merge<State>(
  visitors: Visitor<State>[],
): ExplodedVisitor<State>;
export function merge(
  visitors: Visitor<unknown>[],
  states?: any[],
  wrapper?: Function | null,
): ExplodedVisitor<unknown>;
export function merge(
  visitors: any[],
  states: any[] = [],
  wrapper?: VisitWrapper | null,
): ExplodedVisitor {
  // @ts-expect-error don't bother with internal flags so it can work with earlier @babel/core validations
  const mergedVisitor: ExplodedVisitor = {};

  for (let i = 0; i < visitors.length; i++) {
    const visitor = explode$1(visitors[i]);
    const state = states[i];

    let topVisitor: ExplVisitNode<unknown, Node> = visitor;
    if (state || wrapper) {
      topVisitor = wrapWithStateOrWrapper(topVisitor, state, wrapper);
    }
    mergePair(mergedVisitor, topVisitor);

    for (const key of Object.keys(visitor) as (keyof ExplodedVisitor)[]) {
      if (shouldIgnoreKey(key)) continue;

      let typeVisitor = visitor[key];

      // if we have state or wrapper then overload the callbacks to take it
      if (state || wrapper) {
        typeVisitor = wrapWithStateOrWrapper(typeVisitor, state, wrapper);
      }

      const nodeVisitor = (mergedVisitor[key] ||= {});
      mergePair(nodeVisitor, typeVisitor);
    }
  }

  if (process.env.BABEL_8_BREAKING) {
    return {
      ...mergedVisitor,
      _exploded: true,
      _verified: true,

Review comment (bug):
I'm surprised they would fail for enumerable `_exploded` but still work for non-enumerable `_exploded`.

Code after:
      );
    }
  }
}

export function merge<State>(
  visitors: Visitor<State>[],
): ExplodedVisitor<State>;
export function merge(
  visitors: Visitor<unknown>[],
  states?: any[],
  wrapper?: Function | null,
): ExplodedVisitor<unknown>;
export function merge(
  visitors: any[],
  states: any[] = [],
  wrapper?: VisitWrapper | null,
): ExplodedVisitor {
  const mergedVisitor: ExplodedVisitor = { _verified: true, _exploded: true };
  if (!process.env.BABEL_8_BREAKING) {
    // For compatibility with old Babel versions, we must hide _verified and _exploded.
    // Otherwise, old versions of the validator will throw sayng that `true` is not
    // a function, because it tries to validate it as a visitor.
    Object.defineProperty(mergedVisitor, "_exploded", { enumerable: false });
    Object.defineProperty(mergedVisitor, "_verified", { enumerable: false });
  }

  for (let i = 0; i < visitors.length; i++) {
    const visitor = explode$1(visitors[i]);
    const state = states[i];

    let topVisitor: ExplVisitNode<unknown, Node> = visitor;
    if (state || wrapper) {
      topVisitor = wrapWithStateOrWrapper(topVisitor, state, wrapper);
    }
    mergePair(mergedVisitor, topVisitor);

    for (const key of Object.keys(visitor) as (keyof ExplodedVisitor)[]) {
      if (shouldIgnoreKey(key)) continue;

      let typeVisitor = visitor[key];

      // if we have state or wrapper then overload the callbacks to take it
      if (state || wrapper) {
        typeVisitor = wrapWithStateOrWrapper(typeVisitor, state, wrapper);
      }

      const nodeVisitor = (mergedVisitor[key] ||= {});
      mergePair(nodeVisitor, typeVisitor);
    }
  }