code: function parse(x) {
  	// just return the argument unchanged if it's not a string
  	if (! (typeof x == 'string' || x instanceof String)) return x
  	// parse with regular expressions. 
  	// The first step comes straight from the rfc: https://tools.ietf.org/html/rfc3986#appendix-B
  	var m = [].slice.call(x.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/))
  	// m is now an array with a whole bunch of parts, but we need to further parse field #4 in case it contains credentials
  	m = m.concat((m[ 4] || '').match(/^(([^@]+)?@)?([^:]+)(:(.*))?/))
  	// m now contains the combined results from the previous matches. Finally parse field #12 for username password
  	m = m.concat((m[12] || '').match(/^([^:]+)?(:(.*))?/))
  	// define an index to get at the fields we actually care about
  	var IDX = {protocol:1, username:17, password:19, hostname:13, port:15, pathname:5, search:6, hash:8}
  	// loop through all keys and accumulate them in the result object
  	return Object.keys(IDX).reduce(function(r, p){r[p] = m[IDX[p]] || ''; return r}, {})
  }
docs: IMPLEMENTATION