resolveUrl = function(urlStr, baseStr) {
  if (ASSUME_COMPLIANT_URL_API) {
    // Safari throws a TypeError if you call the constructor with a second
    // argument that isn't defined, so we can't pass baseStr all the time.
    return baseStr ? new NATIVE_URL(urlStr, baseStr) : new NATIVE_URL(urlStr);
  }

  // Ideally, this should effectively become
  // if Edge
  // and the else should effectively become
  // if IE

  // TODO(user) Some use of FEATURESET_YEAR near here would help strip
  // down the implementation even more for browsers we are more sure support the
  // URL Web API (including Edge). 2019? Maybe?

  if (supportsNativeURLConstructor) {
    if (!baseStr) {
      return urlParseWithCommonChecks(urlStr);
    }
    // Edge doesn't throw if baseStr is not a valid absolute URL when the
    // urlStr is absolute. This is against the spec, so try and parse this with
    // commonChecks (which will throw if baseStr is not a valid absolute URL).
    const baseUrl = urlParseWithCommonChecks(baseStr);

    // If urlStr is present and absolute, then only those values are used.
    try {
      return urlParseWithCommonChecks(urlStr);
    } catch (e) {
      // urlStr is not absolute. We shall give both pieces to the constructor
      // below and see what it thinks.
    }
    return new NATIVE_URL(urlStr, baseUrl.href);
  } else {
    if (!baseStr) {
      return createAnchorElementInIE(urlStr);
    }
    // It is against the spec to provide a baseStr that is not absolute.
    const baseUrl = createAnchorElementInIE(baseStr);

    // If urlStr is present and absolute, then only those values are used even
    // if baseStr is defined. The spec says we must try and parse baseStr first
    // (and error on it) before we do this though.
    try {
      return createAnchorElementInIE(urlStr);
    } catch (e) {
      // urlStr is not absolute. We shall assemble base pieces + url pieces
      // below.
      // Deliberate fallthrough
    }

    // If the base is present and absolute, check for special characters that
    // help determine what parts of base we use vs the relative parts.
    // This is similar to the [state machine][1] mentioned in the
    // spec except we already know that urlStr is NOT absolute.
    // [1]: https://url.spec.whatwg.org/#relative-state
    const newBaseStr = baseUrl.protocol + '//' +
        assembleUserInfo(baseUrl.username, baseUrl.password) + baseUrl.host;
    let /** string */ href;
    const firstChar = urlStr[0];
    if (firstChar === '/' || firstChar === '\\') {
      href = newBaseStr + urlStr;
    } else if (firstChar === '?') {
      href = newBaseStr + baseUrl.pathname + urlStr;
    } else if (!firstChar || firstChar === '#') {
      href = newBaseStr + baseUrl.pathname + baseUrl.search + urlStr;
    } else {
      // This doesn't start with any of the authority terminating characters,
      // but other browsers treat it implicitly as an extension to the existing
      // path, removing anything after the last '/' and appending urlStr to it.
      const lastPathSeparator = baseUrl.pathname.lastIndexOf('/');
      const path = lastPathSeparator > 0 ?
          baseUrl.pathname.substring(0, lastPathSeparator) :
          '';
      href = newBaseStr + path + '/' + urlStr;
    }
    return createAnchorElementInIE(href);
  }
}
Resolves the given url string (with the optional base) into a URL object
according to the [URL spec][https://url.spec.whatwg.org/]. Will throw an
error if the resulting URL is invalid or if the browser can't or won't use
that URL for some reason. Relative URLs are considered invalid without a base
and will throw an error - please use `resolveRelativeUrl` instead for this
use-case.

Note that calling resolveUrl with both urlStr and baseStr may have surprising
behavior. For example, any invocation with both parameters will never use the
hash value from baseStr. Similarly, passing a path segment in urlStr will
append (or replace) the path in baseStr, but will ALSO exclude the search and
hash portions of baseStr from the resulting URL. See the unit tests
(specifically testWithBase* test cases) for examples.

Compatibility notes:
- both IE (all versions) and Edge (EdgeHTML only) disallow URLs to have user
  information in them, and parsing those strings will throw an error.
- FireFox disallows URLs with just a password in the userinfo.
@param {string} urlStr A potential absolute URL as a string, or a relative
    URL if baseStr is provided.
@param {string=} baseStr An optional base url as a string, only required if
    the url is relative.
@return {!UrlLike} An object that describes the various parts of the URL if
    valid. Throws an error if invalid. While this object is the native URL
    object where possible, users should NOT rely on this property and instead
    treat it as a simple record.