function executeEmptyTraversal(root, frameState) {
  const { canTraverse, updateTile, loadTile, touchTile } =
    Cesium3DTilesetTraversal;
  let allDescendantsLoaded = true;
  const stack = emptyTraversal.stack;
  stack.push(root);

  while (stack.length > 0) {
    emptyTraversal.stackMaximumLength = Math.max(
      emptyTraversal.stackMaximumLength,
      stack.length,
    );

    const tile = stack.pop();
    const children = tile.children;
    const childrenLength = children.length;

    // Only traverse if the tile is empty - traversal stops at descendants with content
    const traverse = !tile.hasRenderableContent && canTraverse(tile);

    // Traversal stops but the tile does not have content yet
    // There will be holes if the parent tries to refine to its children, so don't refine
    if (!traverse && !tile.contentAvailable) {
      allDescendantsLoaded = false;
    }

    updateTile(tile, frameState);
    if (!tile.isVisible) {
      // Load tiles that aren't visible since they are still needed for the parent to refine
      loadTile(tile, frameState);
      touchTile(tile, frameState);
    }

    if (traverse) {
      for (let i = 0; i < childrenLength; ++i) {
        const child = children[i];
        stack.push(child);
      }
    }
  }

  return root.hasEmptyContent || allDescendantsLoaded;
}
Depth-first traversal that checks if all nearest descendants with content are loaded.
Ignores visibility.

@private
@param {Cesium3DTile} root
@param {FrameState} frameState
@returns {boolean}