function annotateStacktrace (stack, formatInternal, eToString = null) {
  const frames = stack.split('\n');
  const annotated = [];
  if (eToString && eToString.indexOf(frames[0]) !== -1) {
    // In Firefox and Safari e.stack starts with frame 0, but in V8 (Chrome/Node.js),
    // e.stack starts first stringified message. Preserve this separately,
    // so that, below, we can distinguish between internal frames on top
    // (to remove) vs later internal frames (to format differently).
    annotated.push(frames.shift());
  }
  let initialInternal = true;
  for (let i = 0; i < frames.length; i++) {
    const frame = frames[i];
    // Example of internal stack trace (Node 16+)
    // "at wrapModuleLoad (node:internal/modules/cjs/loader:234:24)"
    const isInternal = ((fileName && frame.indexOf(fileName) !== -1) || frame.indexOf('node:internal/') !== -1);
    if (!isInternal) {
      initialInternal = false;
    }
    // Remove initial internal frames entirely.
    if (!initialInternal) {
      annotated.push(isInternal ? formatInternal(frame) : frame);
    }
  }

  return annotated.join('\n');
}
Responsibilities:
- For internal errors from QUnit itself, remove the first qunit.js frames.
- For errors in Node.js, format any remaining qunit.js and node:internal
  frames as internal (i.e. grey out).

@param {string} stack Error#stack
@param {Function} formatInternal Format a string in an "internal" color
@param {string|null} [eToString] Error#toString() to help remove
 noise from Node.js/V8 stack traces.