summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/querystring.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/jetpack/sdk/querystring.js')
-rw-r--r--toolkit/jetpack/sdk/querystring.js121
1 files changed, 121 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/querystring.js b/toolkit/jetpack/sdk/querystring.js
new file mode 100644
index 000000000..9982a00ab
--- /dev/null
+++ b/toolkit/jetpack/sdk/querystring.js
@@ -0,0 +1,121 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+var unescape = decodeURIComponent;
+exports.unescape = unescape;
+
+// encodes a string safely for application/x-www-form-urlencoded
+// adheres to RFC 3986
+// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent
+function escape(query) {
+ return encodeURIComponent(query).
+ replace(/%20/g, '+').
+ replace(/!/g, '%21').
+ replace(/'/g, '%27').
+ replace(/\(/g, '%28').
+ replace(/\)/g, '%29').
+ replace(/\*/g, '%2A');
+}
+exports.escape = escape;
+
+// Converts an object of unordered key-vals to a string that can be passed
+// as part of a request
+function stringify(options, separator, assigner) {
+ separator = separator || '&';
+ assigner = assigner || '=';
+ // Explicitly return null if we have null, and empty string, or empty object.
+ if (!options)
+ return '';
+
+ // If content is already a string, just return it as is.
+ if (typeof(options) == 'string')
+ return options;
+
+ // At this point we have a k:v object. Iterate over it and encode each value.
+ // Arrays and nested objects will get encoded as needed. For example...
+ //
+ // { foo: [1, 2, { omg: 'bbq', 'all your base!': 'are belong to us' }], bar: 'baz' }
+ //
+ // will be encoded as
+ //
+ // foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz
+ //
+ // Keys (including '[' and ']') and values will be encoded with
+ // `escape` before returning.
+ //
+ // Execution was inspired by jQuery, but some details have changed and numeric
+ // array keys are included (whereas they are not in jQuery).
+
+ let encodedContent = [];
+ function add(key, val) {
+ encodedContent.push(escape(key) + assigner + escape(val));
+ }
+
+ function make(key, value) {
+ if (value && typeof(value) === 'object')
+ Object.keys(value).forEach(function(name) {
+ make(key + '[' + name + ']', value[name]);
+ });
+ else
+ add(key, value);
+ }
+
+ Object.keys(options).forEach(function(name) { make(name, options[name]); });
+ return encodedContent.join(separator);
+
+ //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had
+ // trouble getting that working. It would also be nice to stay
+ // backwards-compat as long as possible. Keeping this in for now...
+ // let formData = Cc['@mozilla.org/files/formdata;1'].
+ // createInstance(Ci.nsIDOMFormData);
+ // for ([k, v] in Iterator(content)) {
+ // formData.append(k, v);
+ // }
+ // return formData;
+}
+exports.stringify = stringify;
+
+// Exporting aliases that nodejs implements just for the sake of
+// interoperability.
+exports.encode = stringify;
+exports.serialize = stringify;
+
+// Note: That `stringify` and `parse` aren't bijective as we use `stringify`
+// as it was implement in request module, but implement `parse` to match nodejs
+// behavior.
+// TODO: Make `stringify` implement API as in nodejs and figure out backwards
+// compatibility.
+function parse(query, separator, assigner) {
+ separator = separator || '&';
+ assigner = assigner || '=';
+ let result = {};
+
+ if (typeof query !== 'string' || query.length === 0)
+ return result;
+
+ query.split(separator).forEach(function(chunk) {
+ let pair = chunk.split(assigner);
+ let key = unescape(pair[0]);
+ let value = unescape(pair.slice(1).join(assigner));
+
+ if (!(key in result))
+ result[key] = value;
+ else if (Array.isArray(result[key]))
+ result[key].push(value);
+ else
+ result[key] = [result[key], value];
+ });
+
+ return result;
+};
+exports.parse = parse;
+// Exporting aliases that nodejs implements just for the sake of
+// interoperability.
+exports.decode = parse;