Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

browser compatibility #57

Merged
merged 2 commits into from

2 participants

@juliangruber

It's as fast as before and should now work in more browsers.

The test suite doesn't load in IE9, saying Object expected. Dunno where that's from.

@juliangruber juliangruber referenced this pull request in defunctzombie/node-browser-resolve
Merged

updated querystring #16

@tj
Owner
tj commented

LGTM, we almost might as well start using regular component deps but not a big deal

@tj tj merged commit 2640fab into from
@juliangruber

yeah, I thought about using components too. But then there'd prob. be many try catch requires at the top and also the shims I used are optimized for performance rather than file size.

Can you release this please?

@tj
Owner
tj commented

yeah true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 21, 2013
  1. @juliangruber

    shims for browser compat

    juliangruber authored
  2. @juliangruber

    speed up

    juliangruber authored
This page is out of date. Refresh to see the latest.
Showing with 179 additions and 64 deletions.
  1. +77 −27 index.js
  2. +102 −37 test/browser/qs.js
View
104 index.js
@@ -6,6 +6,58 @@
var toString = Object.prototype.toString;
/**
+ * Array#indexOf shim.
+ */
+
+var indexOf = typeof Array.prototype.indexOf === 'function'
+ ? function(arr, el) { return arr.indexOf(el); }
+ : function(arr, el) {
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] === el) return i;
+ }
+ return -1;
+ };
+
+/**
+ * Array.isArray shim.
+ */
+
+var isArray = Array.isArray || function(arr) {
+ return toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Object.keys shim.
+ */
+
+var objectKeys = Object.keys || function(obj) {
+ var ret = [];
+ for (var key in obj) ret.push(key);
+ return ret;
+};
+
+/**
+ * Array#forEach shim.
+ */
+
+var forEach = typeof Array.prototype.forEach === 'function'
+ ? function(arr, fn) { return arr.forEach(fn); }
+ : function(arr, fn) {
+ for (var i = 0; i < arr.length; i++) fn(arr[i]);
+ };
+
+/**
+ * Array#reduce shim.
+ */
+
+var reduce = function(arr, fn, initial) {
+ if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
+ var res = initial;
+ for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
+ return res;
+};
+
+/**
* Cache non-integer test regexp.
*/
@@ -23,7 +75,7 @@ function parse(parts, parent, key, val) {
var part = parts.shift();
// end
if (!part) {
- if (Array.isArray(parent[key])) {
+ if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
@@ -36,21 +88,21 @@ function parse(parts, parent, key, val) {
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
- if (Array.isArray(obj)) {
+ if (isArray(obj)) {
if ('' != val) obj.push(val);
} else if ('object' == typeof obj) {
- obj[Object.keys(obj).length] = val;
+ obj[objectKeys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
// prop
- } else if (~part.indexOf(']')) {
+ } else if (~indexOf(part, ']')) {
part = part.substr(0, part.length - 1);
- if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
- if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
@@ -61,14 +113,14 @@ function parse(parts, parent, key, val) {
*/
function merge(parent, key, val){
- if (~key.indexOf(']')) {
+ if (~indexOf(key, ']')) {
var parts = key.split('[')
, len = parts.length
, last = len - 1;
parse(parts, parent, 'base', val);
// optimize
} else {
- if (!isint.test(key) && Array.isArray(parent.base)) {
+ if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
@@ -85,7 +137,7 @@ function merge(parent, key, val){
function parseObject(obj){
var ret = { base: {} };
- Object.keys(obj).forEach(function(name){
+ forEach(objectKeys(obj), function(name){
merge(ret, name, obj[name]);
});
return ret.base;
@@ -96,21 +148,19 @@ function parseObject(obj){
*/
function parseString(str){
- return String(str)
- .split('&')
- .reduce(function(ret, pair){
- var eql = pair.indexOf('=')
- , brace = lastBraceInKey(pair)
- , key = pair.substr(0, brace || eql)
- , val = pair.substr(brace || eql, pair.length)
- , val = val.substr(val.indexOf('=') + 1, val.length);
-
- // ?foo
- if ('' == key) key = pair, val = '';
- if ('' == key) return ret;
-
- return merge(ret, decode(key), decode(val));
- }, { base: {} }).base;
+ return reduce(String(str).split('&'), function(ret, pair){
+ var eql = indexOf(pair, '=')
+ , brace = lastBraceInKey(pair)
+ , key = pair.substr(0, brace || eql)
+ , val = pair.substr(brace || eql, pair.length)
+ , val = val.substr(indexOf(val, '=') + 1, val.length);
+
+ // ?foo
+ if ('' == key) key = pair, val = '';
+ if ('' == key) return ret;
+
+ return merge(ret, decode(key), decode(val));
+ }, { base: {} }).base;
}
/**
@@ -137,7 +187,7 @@ exports.parse = function(str){
*/
var stringify = exports.stringify = function(obj, prefix) {
- if (Array.isArray(obj)) {
+ if (isArray(obj)) {
return stringifyArray(obj, prefix);
} else if ('[object Object]' == toString.call(obj)) {
return stringifyObject(obj, prefix);
@@ -191,7 +241,7 @@ function stringifyArray(arr, prefix) {
function stringifyObject(obj, prefix) {
var ret = []
- , keys = Object.keys(obj)
+ , keys = objectKeys(obj)
, key;
for (var i = 0, len = keys.length; i < len; ++i) {
@@ -223,7 +273,7 @@ function set(obj, key, val) {
var v = obj[key];
if (undefined === v) {
obj[key] = val;
- } else if (Array.isArray(v)) {
+ } else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
View
139 test/browser/qs.js
@@ -103,6 +103,58 @@ require.register("querystring", function(module, exports, require){
var toString = Object.prototype.toString;
/**
+ * Array#indexOf shim.
+ */
+
+var indexOf = typeof Array.prototype.indexOf === 'function'
+ ? function(arr, el) { return arr.indexOf(el); }
+ : function(arr, el) {
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] === el) return i;
+ }
+ return -1;
+ };
+
+/**
+ * Array.isArray shim.
+ */
+
+var isArray = Array.isArray || function(arr) {
+ return toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Object.keys shim.
+ */
+
+var objectKeys = Object.keys || function(obj) {
+ var ret = [];
+ for (var key in obj) ret.push(key);
+ return ret;
+};
+
+/**
+ * Array#forEach shim.
+ */
+
+var forEach = typeof Array.prototype.forEach === 'function'
+ ? function(arr, fn) { return arr.forEach(fn); }
+ : function(arr, fn) {
+ for (var i = 0; i < arr.length; i++) fn(arr[i]);
+ };
+
+/**
+ * Array#reduce shim.
+ */
+
+var reduce = function(arr, fn, initial) {
+ if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
+ var res = initial;
+ for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
+ return res;
+};
+
+/**
* Cache non-integer test regexp.
*/
@@ -120,7 +172,7 @@ function parse(parts, parent, key, val) {
var part = parts.shift();
// end
if (!part) {
- if (Array.isArray(parent[key])) {
+ if (isArray(parent[key])) {
parent[key].push(val);
} else if ('object' == typeof parent[key]) {
parent[key] = val;
@@ -133,21 +185,21 @@ function parse(parts, parent, key, val) {
} else {
var obj = parent[key] = parent[key] || [];
if (']' == part) {
- if (Array.isArray(obj)) {
+ if (isArray(obj)) {
if ('' != val) obj.push(val);
} else if ('object' == typeof obj) {
- obj[Object.keys(obj).length] = val;
+ obj[objectKeys(obj).length] = val;
} else {
obj = parent[key] = [parent[key], val];
}
// prop
- } else if (~part.indexOf(']')) {
+ } else if (~indexOf(part, ']')) {
part = part.substr(0, part.length - 1);
- if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
// key
} else {
- if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
parse(parts, obj, part, val);
}
}
@@ -158,14 +210,14 @@ function parse(parts, parent, key, val) {
*/
function merge(parent, key, val){
- if (~key.indexOf(']')) {
+ if (~indexOf(key, ']')) {
var parts = key.split('[')
, len = parts.length
, last = len - 1;
parse(parts, parent, 'base', val);
// optimize
} else {
- if (!isint.test(key) && Array.isArray(parent.base)) {
+ if (!isint.test(key) && isArray(parent.base)) {
var t = {};
for (var k in parent.base) t[k] = parent.base[k];
parent.base = t;
@@ -182,7 +234,7 @@ function merge(parent, key, val){
function parseObject(obj){
var ret = { base: {} };
- Object.keys(obj).forEach(function(name){
+ forEach(objectKeys(obj), function(name){
merge(ret, name, obj[name]);
});
return ret.base;
@@ -193,26 +245,19 @@ function parseObject(obj){
*/
function parseString(str){
- return String(str)
- .split('&')
- .reduce(function(ret, pair){
- try{
- pair = decodeURIComponent(pair.replace(/\+/g, ' '));
- } catch(e) {
- // ignore
- }
-
- var eql = pair.indexOf('=')
- , brace = lastBraceInKey(pair)
- , key = pair.substr(0, brace || eql)
- , val = pair.substr(brace || eql, pair.length)
- , val = val.substr(val.indexOf('=') + 1, val.length);
-
- // ?foo
- if ('' == key) key = pair, val = '';
-
- return merge(ret, key, val);
- }, { base: {} }).base;
+ return reduce(String(str).split('&'), function(ret, pair){
+ var eql = indexOf(pair, '=')
+ , brace = lastBraceInKey(pair)
+ , key = pair.substr(0, brace || eql)
+ , val = pair.substr(brace || eql, pair.length)
+ , val = val.substr(indexOf(val, '=') + 1, val.length);
+
+ // ?foo
+ if ('' == key) key = pair, val = '';
+ if ('' == key) return ret;
+
+ return merge(ret, decode(key), decode(val));
+ }, { base: {} }).base;
}
/**
@@ -239,14 +284,14 @@ exports.parse = function(str){
*/
var stringify = exports.stringify = function(obj, prefix) {
- if (Array.isArray(obj)) {
+ if (isArray(obj)) {
return stringifyArray(obj, prefix);
} else if ('[object Object]' == toString.call(obj)) {
return stringifyObject(obj, prefix);
} else if ('string' == typeof obj) {
return stringifyString(obj, prefix);
} else {
- return prefix + '=' + obj;
+ return prefix + '=' + encodeURIComponent(String(obj));
}
};
@@ -277,7 +322,7 @@ function stringifyArray(arr, prefix) {
var ret = [];
if (!prefix) throw new TypeError('stringify expects an object');
for (var i = 0; i < arr.length; i++) {
- ret.push(stringify(arr[i], prefix + '['+i+']'));
+ ret.push(stringify(arr[i], prefix + '[' + i + ']'));
}
return ret.join('&');
}
@@ -293,14 +338,18 @@ function stringifyArray(arr, prefix) {
function stringifyObject(obj, prefix) {
var ret = []
- , keys = Object.keys(obj)
+ , keys = objectKeys(obj)
, key;
for (var i = 0, len = keys.length; i < len; ++i) {
key = keys[i];
- ret.push(stringify(obj[key], prefix
- ? prefix + '[' + encodeURIComponent(key) + ']'
- : encodeURIComponent(key)));
+ if (null == obj[key]) {
+ ret.push(encodeURIComponent(key) + '=');
+ } else {
+ ret.push(stringify(obj[key], prefix
+ ? prefix + '[' + encodeURIComponent(key) + ']'
+ : encodeURIComponent(key)));
+ }
}
return ret.join('&');
@@ -321,7 +370,7 @@ function set(obj, key, val) {
var v = obj[key];
if (undefined === v) {
obj[key] = val;
- } else if (Array.isArray(v)) {
+ } else if (isArray(v)) {
v.push(val);
} else {
obj[key] = [v, val];
@@ -347,5 +396,21 @@ function lastBraceInKey(str) {
if ('=' == c && !brace) return i;
}
}
+
+/**
+ * Decode `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function decode(str) {
+ try {
+ return decodeURIComponent(str.replace(/\+/g, ' '));
+ } catch (err) {
+ return str;
+ }
+}
})();
});
Something went wrong with that request. Please try again.