async function injectScripts(data, info, isXml) {
  const { errors, [MORE]: more } = data;
  const CACHE = 'cache';
  if (errors) {
    logging.warn(errors);
  }
  info.gmi = {
    isIncognito: chrome.extension.inIncognitoContext,
  };
  bridgeInfo = createNullObj();
  bridgeInfo[PAGE] = info;
  bridgeInfo[CONTENT] = info;
  assign(bridge[CACHE], data[CACHE]);
  if (isXml || data[FORCE_CONTENT]) {
    pageInjectable = false;
  } else if (data[PAGE] && pageInjectable == null) {
    injectPageSandbox(data);
  }
  const toContent = data[SCRIPTS]
    .filter(scr => triageScript(scr) === CONTENT)
    .map(scr => [scr.id, scr.key.data]);
  const moreData = (more || toContent.length)
    && sendCmd('InjectionFeedback', {
      [FORCE_CONTENT]: !pageInjectable,
      [CONTENT]: toContent,
      [MORE]: more,
      url: IS_FIREFOX && location.href,
    });
  const getReadyState = describeProperty(Document[PROTO], 'readyState').get;
  const hasInvoker = contLists;
  if (hasInvoker) {
    setupContentInvoker();
  }
  tardyQueue = createNullObj();
  // Using a callback to avoid a microtask tick when the root element exists or appears.
  await onElement('*', injectAll, 'start');
  if (pageLists?.body || contLists?.body) {
    await onElement('body', injectAll, 'body');
  }
  if (more && (data = await moreData)) {
    assign(bridge[CACHE], data[CACHE]);
    if (document::getReadyState() === 'loading') {
      await new SafePromise(resolve => {
        /* Since most sites listen to DOMContentLoaded on `document`, we let them run first
         * by listening on `window` which follows `document` when the event bubbles up. */
        on('DOMContentLoaded', resolve, { once: true });
      });
      await 0; // let the site's listeners on `window` run first
    }
    for (const scr of data[SCRIPTS]) {
      triageScript(scr);
    }
    if (contLists && !hasInvoker) {
      setupContentInvoker();
    }
    await injectAll('end');
    await injectAll('idle');
  }
  // release for GC
  bridgeInfo = contLists = pageLists = VMInitInjection = null;
}
@param {VMInjection} data
@param {VMInjection.Info} info
@param {boolean} isXml