| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 | 'use strict';var getSideChannel = require('side-channel');var utils = require('./utils');var formats = require('./formats');var has = Object.prototype.hasOwnProperty;var arrayPrefixGenerators = {    brackets: function brackets(prefix) {        return prefix + '[]';    },    comma: 'comma',    indices: function indices(prefix, key) {        return prefix + '[' + key + ']';    },    repeat: function repeat(prefix) {        return prefix;    }};var isArray = Array.isArray;var push = Array.prototype.push;var pushToArray = function (arr, valueOrArray) {    push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);};var toISO = Date.prototype.toISOString;var defaultFormat = formats['default'];var defaults = {    addQueryPrefix: false,    allowDots: false,    allowEmptyArrays: false,    arrayFormat: 'indices',    charset: 'utf-8',    charsetSentinel: false,    commaRoundTrip: false,    delimiter: '&',    encode: true,    encodeDotInKeys: false,    encoder: utils.encode,    encodeValuesOnly: false,    filter: void undefined,    format: defaultFormat,    formatter: formats.formatters[defaultFormat],    // deprecated    indices: false,    serializeDate: function serializeDate(date) {        return toISO.call(date);    },    skipNulls: false,    strictNullHandling: false};var isNonNullishPrimitive = function isNonNullishPrimitive(v) {    return typeof v === 'string'        || typeof v === 'number'        || typeof v === 'boolean'        || typeof v === 'symbol'        || typeof v === 'bigint';};var sentinel = {};var stringify = function stringify(    object,    prefix,    generateArrayPrefix,    commaRoundTrip,    allowEmptyArrays,    strictNullHandling,    skipNulls,    encodeDotInKeys,    encoder,    filter,    sort,    allowDots,    serializeDate,    format,    formatter,    encodeValuesOnly,    charset,    sideChannel) {    var obj = object;    var tmpSc = sideChannel;    var step = 0;    var findFlag = false;    while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) {        // Where object last appeared in the ref tree        var pos = tmpSc.get(object);        step += 1;        if (typeof pos !== 'undefined') {            if (pos === step) {                throw new RangeError('Cyclic object value');            } else {                findFlag = true; // Break while            }        }        if (typeof tmpSc.get(sentinel) === 'undefined') {            step = 0;        }    }    if (typeof filter === 'function') {        obj = filter(prefix, obj);    } else if (obj instanceof Date) {        obj = serializeDate(obj);    } else if (generateArrayPrefix === 'comma' && isArray(obj)) {        obj = utils.maybeMap(obj, function (value) {            if (value instanceof Date) {                return serializeDate(value);            }            return value;        });    }    if (obj === null) {        if (strictNullHandling) {            return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix;        }        obj = '';    }    if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {        if (encoder) {            var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);            return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];        }        return [formatter(prefix) + '=' + formatter(String(obj))];    }    var values = [];    if (typeof obj === 'undefined') {        return values;    }    var objKeys;    if (generateArrayPrefix === 'comma' && isArray(obj)) {        // we need to join elements in        if (encodeValuesOnly && encoder) {            obj = utils.maybeMap(obj, encoder);        }        objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];    } else if (isArray(filter)) {        objKeys = filter;    } else {        var keys = Object.keys(obj);        objKeys = sort ? keys.sort(sort) : keys;    }    var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);    var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;    if (allowEmptyArrays && isArray(obj) && obj.length === 0) {        return adjustedPrefix + '[]';    }    for (var j = 0; j < objKeys.length; ++j) {        var key = objKeys[j];        var value = typeof key === 'object' && key && typeof key.value !== 'undefined'            ? key.value            : obj[key];        if (skipNulls && value === null) {            continue;        }        var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);        var keyPrefix = isArray(obj)            ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix            : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');        sideChannel.set(object, step);        var valueSideChannel = getSideChannel();        valueSideChannel.set(sentinel, sideChannel);        pushToArray(values, stringify(            value,            keyPrefix,            generateArrayPrefix,            commaRoundTrip,            allowEmptyArrays,            strictNullHandling,            skipNulls,            encodeDotInKeys,            generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,            filter,            sort,            allowDots,            serializeDate,            format,            formatter,            encodeValuesOnly,            charset,            valueSideChannel        ));    }    return values;};var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {    if (!opts) {        return defaults;    }    if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {        throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');    }    if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {        throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');    }    if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {        throw new TypeError('Encoder has to be a function.');    }    var charset = opts.charset || defaults.charset;    if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {        throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');    }    var format = formats['default'];    if (typeof opts.format !== 'undefined') {        if (!has.call(formats.formatters, opts.format)) {            throw new TypeError('Unknown format option provided.');        }        format = opts.format;    }    var formatter = formats.formatters[format];    var filter = defaults.filter;    if (typeof opts.filter === 'function' || isArray(opts.filter)) {        filter = opts.filter;    }    var arrayFormat;    if (opts.arrayFormat in arrayPrefixGenerators) {        arrayFormat = opts.arrayFormat;    } else if ('indices' in opts) {        arrayFormat = opts.indices ? 'indices' : 'repeat';    } else {        arrayFormat = defaults.arrayFormat;    }    if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {        throw new TypeError('`commaRoundTrip` must be a boolean, or absent');    }    var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;    return {        addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,        allowDots: allowDots,        allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,        arrayFormat: arrayFormat,        charset: charset,        charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,        commaRoundTrip: !!opts.commaRoundTrip,        delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,        encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,        encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,        encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,        encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,        filter: filter,        format: format,        formatter: formatter,        serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,        skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,        sort: typeof opts.sort === 'function' ? opts.sort : null,        strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling    };};module.exports = function (object, opts) {    var obj = object;    var options = normalizeStringifyOptions(opts);    var objKeys;    var filter;    if (typeof options.filter === 'function') {        filter = options.filter;        obj = filter('', obj);    } else if (isArray(options.filter)) {        filter = options.filter;        objKeys = filter;    }    var keys = [];    if (typeof obj !== 'object' || obj === null) {        return '';    }    var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];    var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;    if (!objKeys) {        objKeys = Object.keys(obj);    }    if (options.sort) {        objKeys.sort(options.sort);    }    var sideChannel = getSideChannel();    for (var i = 0; i < objKeys.length; ++i) {        var key = objKeys[i];        var value = obj[key];        if (options.skipNulls && value === null) {            continue;        }        pushToArray(keys, stringify(            value,            key,            generateArrayPrefix,            commaRoundTrip,            options.allowEmptyArrays,            options.strictNullHandling,            options.skipNulls,            options.encodeDotInKeys,            options.encode ? options.encoder : null,            options.filter,            options.sort,            options.allowDots,            options.serializeDate,            options.format,            options.formatter,            options.encodeValuesOnly,            options.charset,            sideChannel        ));    }    var joined = keys.join(options.delimiter);    var prefix = options.addQueryPrefix === true ? '?' : '';    if (options.charsetSentinel) {        if (options.charset === 'iso-8859-1') {            // encodeURIComponent('✓'), the "numeric entity" representation of a checkmark            prefix += 'utf8=%26%2310003%3B&';        } else {            // encodeURIComponent('✓')            prefix += 'utf8=%E2%9C%93&';        }    }    return joined.length > 0 ? prefix + joined : '';};
 |