code: function processForEach(state, node, data) {
    state.stack.push('foreach');
    try {
      var originalValue = node.getAttribute('foreach');
      var value = originalValue;
  
      var paramName = 'param';
      if (value.charAt(0) === '$') {
        // No custom loop variable name. Use the default: 'param'
        value = stripBraces(state, value);
      }
      else {
        // Extract the loop variable name from 'NAME in ${ARRAY}'
        var nameArr = value.split(' in ');
        paramName = nameArr[0].trim();
        value = stripBraces(state, nameArr[1].trim());
      }
      node.removeAttribute('foreach');
      try {
        var evaled = envEval(state, value, data, originalValue);
        var cState = cloneState(state);
        handleAsync(evaled, node, function(reply, siblingNode) {
          processForEachLoop(cState, reply, node, siblingNode, data, paramName);
        });
        node.parentNode.removeChild(node);
      }
      catch (ex) {
        handleError(state, 'Error with \'' + value + '\'', ex);
      }
    }
    finally {
      state.stack.pop();
    }
  }
docs: Handle <x foreach="param in ${array}"> and the special case of
  <loop foreach="param in ${array}">.
  This function is responsible for extracting what it has to do from the
  attributes, and getting the data to work on (including resolving promises
  in getting the array). It delegates to processForEachLoop to actually
  unroll the data.
  @param node An element with a 'foreach' attribute
  @param data The data to use with envEval()