summaryrefslogtreecommitdiff
path: root/lib/url.js
diff options
context:
space:
mode:
authorTimothy Gu <timothygu99@gmail.com>2017-02-03 22:06:04 -0800
committerTimothy Gu <timothygu99@gmail.com>2017-02-14 12:13:11 -0800
commitc6b12d0984cc2891433b57cf344b433059681667 (patch)
tree676f8de002d49b555ca931c05410e7e227da7cd2 /lib/url.js
parentb738cbcdd381a3bcef0111d75d5081bec70d8ce4 (diff)
downloadandroid-node-v8-c6b12d0984cc2891433b57cf344b433059681667.tar.gz
android-node-v8-c6b12d0984cc2891433b57cf344b433059681667.tar.bz2
android-node-v8-c6b12d0984cc2891433b57cf344b433059681667.zip
url: fix surrogate handling in encodeAuth()
Also factor out common parts in querystring and url. PR-URL: https://github.com/nodejs/node/pull/11161 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
Diffstat (limited to 'lib/url.js')
-rw-r--r--lib/url.js84
1 files changed, 75 insertions, 9 deletions
diff --git a/lib/url.js b/lib/url.js
index 57f04d5f3f..5d59d3c10f 100644
--- a/lib/url.js
+++ b/lib/url.js
@@ -10,8 +10,8 @@ function importPunycode() {
const { toASCII } = importPunycode();
+const { StorageObject, hexTable } = require('internal/querystring');
const internalUrl = require('internal/url');
-const encodeAuth = internalUrl.encodeAuth;
exports.parse = urlParse;
exports.resolve = urlResolve;
exports.resolveObject = urlResolveObject;
@@ -76,12 +76,6 @@ const slashedProtocol = {
};
const querystring = require('querystring');
-// This constructor is used to store parsed query string values. Instantiating
-// this is faster than explicitly calling `Object.create(null)` to get a
-// "clean" empty object (tested with v8 v4.9).
-function ParsedQueryString() {}
-ParsedQueryString.prototype = Object.create(null);
-
function urlParse(url, parseQueryString, slashesDenoteHost) {
if (url instanceof Url) return url;
@@ -190,7 +184,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
}
} else if (parseQueryString) {
this.search = '';
- this.query = new ParsedQueryString();
+ this.query = new StorageObject();
}
return this;
}
@@ -380,7 +374,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
} else if (parseQueryString) {
// no query string, but parseQueryString still requested
this.search = '';
- this.query = new ParsedQueryString();
+ this.query = new StorageObject();
}
var firstIdx = (questionIdx !== -1 &&
@@ -948,3 +942,75 @@ function spliceOne(list, index) {
list[i] = list[k];
list.pop();
}
+
+// These characters do not need escaping:
+// ! - . _ ~
+// ' ( ) * :
+// digits
+// alpha (uppercase)
+// alpha (lowercase)
+const noEscapeAuth = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0x0F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1F
+ 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, // 0x20 - 0x2F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 0x30 - 0x3F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 0x4F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50 - 0x5F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 // 0x70 - 0x7F
+];
+
+function encodeAuth(str) {
+ // faster encodeURIComponent alternative for encoding auth uri components
+ var out = '';
+ var lastPos = 0;
+ for (var i = 0; i < str.length; ++i) {
+ var c = str.charCodeAt(i);
+
+ // ASCII
+ if (c < 0x80) {
+ if (noEscapeAuth[c] === 1)
+ continue;
+ if (lastPos < i)
+ out += str.slice(lastPos, i);
+ lastPos = i + 1;
+ out += hexTable[c];
+ continue;
+ }
+
+ if (lastPos < i)
+ out += str.slice(lastPos, i);
+
+ // Multi-byte characters ...
+ if (c < 0x800) {
+ lastPos = i + 1;
+ out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)];
+ continue;
+ }
+ if (c < 0xD800 || c >= 0xE000) {
+ lastPos = i + 1;
+ out += hexTable[0xE0 | (c >> 12)] +
+ hexTable[0x80 | ((c >> 6) & 0x3F)] +
+ hexTable[0x80 | (c & 0x3F)];
+ continue;
+ }
+ // Surrogate pair
+ ++i;
+ var c2;
+ if (i < str.length)
+ c2 = str.charCodeAt(i) & 0x3FF;
+ else
+ c2 = 0;
+ lastPos = i + 1;
+ c = 0x10000 + (((c & 0x3FF) << 10) | c2);
+ out += hexTable[0xF0 | (c >> 18)] +
+ hexTable[0x80 | ((c >> 12) & 0x3F)] +
+ hexTable[0x80 | ((c >> 6) & 0x3F)] +
+ hexTable[0x80 | (c & 0x3F)];
+ }
+ if (lastPos === 0)
+ return str;
+ if (lastPos < str.length)
+ return out + str.slice(lastPos);
+ return out;
+}