addon-sdk/source/lib/sdk/querystring.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/addon-sdk/source/lib/sdk/querystring.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,121 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +'use strict';
     1.9 +
    1.10 +module.metadata = {
    1.11 +  "stability": "unstable"
    1.12 +};
    1.13 +
    1.14 +let unescape = decodeURIComponent;
    1.15 +exports.unescape = unescape;
    1.16 +
    1.17 +// encodes a string safely for application/x-www-form-urlencoded
    1.18 +// adheres to RFC 3986
    1.19 +// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent
    1.20 +function escape(query) {
    1.21 +  return encodeURIComponent(query).
    1.22 +    replace(/%20/g, '+').
    1.23 +    replace(/!/g, '%21').
    1.24 +    replace(/'/g, '%27').
    1.25 +    replace(/\(/g, '%28').
    1.26 +    replace(/\)/g, '%29').
    1.27 +    replace(/\*/g, '%2A');
    1.28 +}
    1.29 +exports.escape = escape;
    1.30 +
    1.31 +// Converts an object of unordered key-vals to a string that can be passed
    1.32 +// as part of a request
    1.33 +function stringify(options, separator, assigner) {
    1.34 +  separator = separator || '&';
    1.35 +  assigner = assigner || '=';
    1.36 +  // Explicitly return null if we have null, and empty string, or empty object.
    1.37 +  if (!options)
    1.38 +    return '';
    1.39 +
    1.40 +  // If content is already a string, just return it as is.
    1.41 +  if (typeof(options) == 'string')
    1.42 +    return options;
    1.43 +
    1.44 +  // At this point we have a k:v object. Iterate over it and encode each value.
    1.45 +  // Arrays and nested objects will get encoded as needed. For example...
    1.46 +  //
    1.47 +  //   { foo: [1, 2, { omg: 'bbq', 'all your base!': 'are belong to us' }], bar: 'baz' }
    1.48 +  //
    1.49 +  // will be encoded as
    1.50 +  //
    1.51 +  //   foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz
    1.52 +  //
    1.53 +  // Keys (including '[' and ']') and values will be encoded with
    1.54 +  // `escape` before returning.
    1.55 +  //
    1.56 +  // Execution was inspired by jQuery, but some details have changed and numeric
    1.57 +  // array keys are included (whereas they are not in jQuery).
    1.58 +
    1.59 +  let encodedContent = [];
    1.60 +  function add(key, val) {
    1.61 +    encodedContent.push(escape(key) + assigner + escape(val));
    1.62 +  }
    1.63 +
    1.64 +  function make(key, value) {
    1.65 +    if (value && typeof(value) === 'object')
    1.66 +      Object.keys(value).forEach(function(name) {
    1.67 +        make(key + '[' + name + ']', value[name]);
    1.68 +      });
    1.69 +    else
    1.70 +      add(key, value);
    1.71 +  }
    1.72 +
    1.73 +  Object.keys(options).forEach(function(name) { make(name, options[name]); });
    1.74 +  return encodedContent.join(separator);
    1.75 +
    1.76 +  //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had
    1.77 +  //        trouble getting that working. It would also be nice to stay
    1.78 +  //        backwards-compat as long as possible. Keeping this in for now...
    1.79 +  // let formData = Cc['@mozilla.org/files/formdata;1'].
    1.80 +  //                createInstance(Ci.nsIDOMFormData);
    1.81 +  // for ([k, v] in Iterator(content)) {
    1.82 +  //   formData.append(k, v);
    1.83 +  // }
    1.84 +  // return formData;
    1.85 +}
    1.86 +exports.stringify = stringify;
    1.87 +
    1.88 +// Exporting aliases that nodejs implements just for the sake of
    1.89 +// interoperability.
    1.90 +exports.encode = stringify;
    1.91 +exports.serialize = stringify;
    1.92 +
    1.93 +// Note: That `stringify` and `parse` aren't bijective as we use `stringify`
    1.94 +// as it was implement in request module, but implement `parse` to match nodejs
    1.95 +// behavior.
    1.96 +// TODO: Make `stringify` implement API as in nodejs and figure out backwards
    1.97 +// compatibility.
    1.98 +function parse(query, separator, assigner) {
    1.99 +  separator = separator || '&';
   1.100 +  assigner = assigner || '=';
   1.101 +  let result = {};
   1.102 +
   1.103 +  if (typeof query !== 'string' || query.length === 0)
   1.104 +    return result;
   1.105 +
   1.106 +  query.split(separator).forEach(function(chunk) {
   1.107 +    let pair = chunk.split(assigner);
   1.108 +    let key = unescape(pair[0]);
   1.109 +    let value = unescape(pair.slice(1).join(assigner));
   1.110 +
   1.111 +    if (!(key in result))
   1.112 +      result[key] = value;
   1.113 +    else if (Array.isArray(result[key]))
   1.114 +      result[key].push(value);
   1.115 +    else
   1.116 +      result[key] = [result[key], value];
   1.117 +  });
   1.118 +
   1.119 +  return result;
   1.120 +};
   1.121 +exports.parse = parse;
   1.122 +// Exporting aliases that nodejs implements just for the sake of
   1.123 +// interoperability.
   1.124 +exports.decode = parse;

mercurial