passedRefs

tcmts.cli.placement.passedRefs · #cn7rb4lq · term · runs anywhere

The definitions a definition's code (its stored IR) uses as values: given to something (a prop, an argument, .bind(…)), not called, and not rendered as an element's tag. What a server component passes this way, a browser component can call.

export function passedRefs(ir: unknown): Set<string> {
  const out = new Set<string>();
  const isRef = (n: unknown): n is [string, string] =>
    Array.isArray(n) && n[0] === "Ref" && typeof n[1] === "string";
  const visit = (node: unknown) => {
    if (!Array.isArray(node)) return;
    if (isRef(node)) {
      out.add(node[1]);
      return;
    }
    const tag = node[0];
    for (const c of node.slice(1)) {
      // `f(…)`, `new F(…)`, f`…` call it; `<F />` renders it
      if (
        Array.isArray(c) &&
        ((c[0] === "expression" && (tag === "CallExpression" || tag === "NewExpression")) ||
          (c[0] === "tag" && tag === "TaggedTemplateExpression") ||
          (c[0] === "tagName" && /^Jsx/.test(String(tag)))) &&
        isRef(c[1])
      )
        continue;
      visit(c);
    }
  };
  visit(typeof ir === "string" ? JSON.parse(ir) : ir);
  return out;
}

used by