combineResults = (results) => {
  const messageLimit = 5;
  const downloadLimit = 5;
  let numMsgs = 0,
    suppressedMsgs = 0,
    suppressedErrors = 0;
  let numDownloads = 0,
    suppressedDownloads = 0;
  const result = { json: { success: "ok" } };
  const initOrPush = (newElement, memberName) => {
    if (result.json[memberName]) result.json[memberName].push(newElement);
    else result.json[memberName] = [newElement];
  };
  const initOnce = (newElement, memberName) => {
    if (typeof result[memberName] === "undefined")
      result.json[memberName] = newElement;
  };
  for (const result of results) {
    if (!result) continue;
    if (result.reload_page) initOnce(result.reload_page, "reload_page");
    if (result.goto) initOnce(result.goto, "goto");
    if (result.popup) initOnce(result.popup, "popup");
    if (result.notify) {
      if (numMsgs < messageLimit) {
        initOrPush(result.notify, "notify");
        ++numMsgs;
      } else ++suppressedMsgs;
    }
    if (result.error) {
      if (numMsgs < messageLimit) {
        initOrPush(result.error, "error");
        ++numMsgs;
      } else ++suppressedErrors;
    }
    if (result.download) {
      if (numDownloads < downloadLimit) {
        initOrPush(result.download, "download");
        ++numDownloads;
      } else suppressedDownloads++;
    }
    if (result.eval_js) initOrPush(result.eval_js, "eval_js");
  }
  let suppressedMsg = "";
  if (suppressedMsgs > 0) suppressedMsg = `${suppressedMsgs} messages`;
  if (suppressedErrors > 0)
    suppressedMsg += `${suppressedMsg ? ", " : ""}${suppressedErrors} errors`;
  if (suppressedMsg)
    result.json.suppressed = `And '${suppressedMsg}' were not shown`;
  return result;
}
combine multiple action results into one object
for 'reload_page, goto, popup' take the first
all other types are combined into arrays
@param results array of action results