* The actual URL instance. Instead of returning an object we've opted-in to * create an actual constructor as it's much more memory efficient and * faster and it pleases my OCD. * * @constructor * @param {String} address URL we want to parse. * @param {Object|String} location Location defaults
(address, location, parser)
| 7990 | * @api public |
| 7991 | */ |
| 7992 | function URL(address, location, parser) { |
| 7993 | if (!(this instanceof URL)) { |
| 7994 | return new URL(address, location, parser); |
| 7995 | } |
| 7996 | |
| 7997 | var relative, extracted, parse, instruction, index, key |
| 7998 | , instructions = rules.slice() |
| 7999 | , type = typeof location |
| 8000 | , url = this |
| 8001 | , i = 0; |
| 8002 | |
| 8003 | // |
| 8004 | // The following if statements allows this module two have compatibility with |
| 8005 | // 2 different API: |
| 8006 | // |
| 8007 | // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments |
| 8008 | // where the boolean indicates that the query string should also be parsed. |
| 8009 | // |
| 8010 | // 2. The `URL` interface of the browser which accepts a URL, object as |
| 8011 | // arguments. The supplied object will be used as default values / fall-back |
| 8012 | // for relative paths. |
| 8013 | // |
| 8014 | if ('object' !== type && 'string' !== type) { |
| 8015 | parser = location; |
| 8016 | location = null; |
| 8017 | } |
| 8018 | |
| 8019 | if (parser && 'function' !== typeof parser) parser = qs.parse; |
| 8020 | |
| 8021 | location = lolcation(location); |
| 8022 | |
| 8023 | // |
| 8024 | // Extract protocol information before running the instructions. |
| 8025 | // |
| 8026 | extracted = extractProtocol(address || ''); |
| 8027 | relative = !extracted.protocol && !extracted.slashes; |
| 8028 | url.slashes = extracted.slashes || relative && location.slashes; |
| 8029 | url.protocol = extracted.protocol || location.protocol || ''; |
| 8030 | address = extracted.rest; |
| 8031 | |
| 8032 | // |
| 8033 | // When the authority component is absent the URL starts with a path |
| 8034 | // component. |
| 8035 | // |
| 8036 | if (!extracted.slashes) instructions[2] = [/(.*)/, 'pathname']; |
| 8037 | |
| 8038 | for (; i < instructions.length; i++) { |
| 8039 | instruction = instructions[i]; |
| 8040 | parse = instruction[0]; |
| 8041 | key = instruction[1]; |
| 8042 | |
| 8043 | if (parse !== parse) { |
| 8044 | url[key] = address; |
| 8045 | } else if ('string' === typeof parse) { |
| 8046 | if (~(index = address.indexOf(parse))) { |
| 8047 | if ('number' === typeof instruction[2]) { |
| 8048 | url[key] = address.slice(0, index); |
| 8049 | address = address.slice(index + instruction[2]); |
nothing calls this directly
no test coverage detected