function processScript(el, opt_synchronous, opt_baseUrl) {
  if (!(el.type in SUPPORTED_SCRIPT_TYPES)) return el;

  var doc = el.ownerDocument;
  if (el.text || el.innerText) {
    // Synchronous block.
    // This happens inline in process so that we can preserve the synchronous
    // behavior.
    log('process of sync script', el);
    showActivityIndicator(doc);
    var resultText = processOrCache(
        el.text || el.innerText,
        nextModuleId++,
        global['wtfi']['options']);
    if (el.text) {
      el.text = resultText;
    } else if (el.innerText) {
      el.innerText = resultText;
    }
    hideActivityIndicator(doc);
    el['__wtfi__'] = true;
    return el;
  } else if (el.src && el.src.length && opt_synchronous) {
    // Synchronous src.
    log('process of sync script', el);
    showActivityIndicator(doc);
    var src = opt_baseUrl ? resolveUrl(opt_baseUrl, el.getAttribute('src')) : el.src;
    var xhr = new XMLHttpRequest();
    xhr.onload = function(e) {
      if (xhr.status != 200) {
        return;
      }
      var responseText = xhr.responseText;
      var resultText = processOrCache(
          xhr.responseText,
          nextModuleId++,
          global['wtfi']['options'],
          src);
      el['__wtfi__'] = true;
      el.src = null;
      el.removeAttribute('src');
      el.text = resultText;
      var loadEvent = new Event('load');
      loadEvent.target = el;
      loadEvent.srcElement = el;
      el.dispatchEvent(loadEvent);
      hideActivityIndicator(doc);
    };
    xhr.open('GET', src, false);
    try {
      xhr.send();
    } catch (e) {
      warn('Unable to fetch ' + src + ' - using uninstrumented version');
      el['__wtfi__'] = true;
    }

    return el;
  } else if (el.src && el.src.length && !opt_synchronous) {
    // Asynchronous src.
    log('process of async script', el);
    showActivityIndicator(doc);
    // Don't actually add the element yet - wait. We fake the add here so that
    // we can replace it with the modified one later.
    var asyncScript = {
      el: el,
      replacementEl: doc.createElement('script'),
      src: opt_baseUrl ? resolveUrl(opt_baseUrl, el.getAttribute('src')) : el.src
    };
    el.src = null;
    el.removeAttribute('src');

    // TODO(benvanik): dispatch to web worker.
    var xhr = new XMLHttpRequest();
    xhr.onload = function(e) {
      if (xhr.status != 200) {
        return;
      }
      var moduleId = nextModuleId++;

      processOrCacheAsync(
          xhr.responseText,
          moduleId,
          global['wtfi']['options'],
          asyncScript.src,
          function(resultText) {
            el['__wtfi__'] = true;
            el.text = resultText;
            asyncScript.replacementEl.parentNode.replaceChild(
                asyncScript.el, asyncScript.replacementEl);
            var loadEvent = new Event('load');
            loadEvent.target = el;
            loadEvent.srcElement = el;
            el.dispatchEvent(loadEvent);
            hideActivityIndicator(doc);
          });
    };
    xhr.open('GET', asyncScript.src, !opt_synchronous);
    xhr.send();

    // Return replacement <script> - we'll swap it later.
    asyncScript.replacementEl['__wtfi__'] = true;
    return asyncScript.replacementEl;
  } else {
    log('unknown script type', el);
    return el;
  }
}
Processes a script element.
@param {!HTMLScriptElement} el Input script element.
@param {boolean=} opt_synchronous Whether to do fetches synchronously.
@param {string=} opt_baseUrl Base URL override.
@return {!HTMLScriptElement} Processed script element. Likely the same as the
     input element.