Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
phated committed May 21, 2020
1 parent 423b998 commit 678e06a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 65 deletions.
115 changes: 51 additions & 64 deletions index.js
Expand Up @@ -2,15 +2,16 @@ var camelCase = require('camelcase')
var path = require('path')
var tokenizeArgString = require('./lib/tokenize-arg-string')
var util = require('util')
var _ = require('lodash')

function parse (args, opts) {
if (!opts) opts = {}
if (!opts) opts = _.create(null)
// allow a string argument to be passed in rather
// than an argv array.
args = tokenizeArgString(args)
// aliases might have transitive relationships, normalize this.
var aliases = combineAliases(opts.alias || {})
var configuration = assign({
var aliases = combineAliases(opts.alias || _.create(null))
var configuration = _.assign({
'short-option-groups': true,
'camel-case-expansion': true,
'dot-notation': true,
Expand All @@ -19,27 +20,27 @@ function parse (args, opts) {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}, opts.configuration)
var defaults = opts.default || {}
var defaults = opts.default || _.create(null)
var configObjects = opts.configObjects || []
var envPrefix = opts.envPrefix
var newAliases = {}
var newAliases = _.create(null)
// allow a i18n handler to be passed in, default to a fake one (util.format).
var __ = opts.__ || function (str) {
return util.format.apply(util, Array.prototype.slice.call(arguments))
}
var error = null
var flags = {
aliases: {},
arrays: {},
bools: {},
strings: {},
numbers: {},
counts: {},
normalize: {},
configs: {},
defaulted: {},
nargs: {},
coercions: {}
aliases: _.create(null),
arrays: _.create(null),
bools: _.create(null),
strings: _.create(null),
numbers: _.create(null),
counts: _.create(null),
normalize: _.create(null),
configs: _.create(null),
defaulted: _.create(null),
nargs: _.create(null),
coercions: _.create(null)
}
var negative = /^-[0-9]+(\.[0-9]+)?/

Expand Down Expand Up @@ -67,11 +68,11 @@ function parse (args, opts) {
flags.normalize[key] = true
})

Object.keys(opts.narg || {}).forEach(function (k) {
Object.keys(opts.narg || _.create(null)).forEach(function (k) {
flags.nargs[k] = opts.narg[k]
})

Object.keys(opts.coerce || {}).forEach(function (k) {
Object.keys(opts.coerce || _.create(null)).forEach(function (k) {
flags.coercions[k] = opts.coerce[k]
})

Expand All @@ -80,7 +81,7 @@ function parse (args, opts) {
flags.configs[key] = true
})
} else {
Object.keys(opts.config || {}).forEach(function (k) {
Object.keys(opts.config || _.create(null)).forEach(function (k) {
flags.configs[k] = opts.config[k]
})
}
Expand All @@ -92,7 +93,7 @@ function parse (args, opts) {
// apply default values to all aliases.
Object.keys(defaults).forEach(function (key) {
(flags.aliases[key] || []).forEach(function (alias) {
defaults[alias] = defaults[key]
_.set(defaults, alias, defaults[key])
})
})

Expand Down Expand Up @@ -417,7 +418,7 @@ function parse (args, opts) {
// set args from config.json file, this should be
// applied last so that defaults can be applied.
function setConfig (argv) {
var configLookup = {}
var configLookup = _.create(null)

// expand defaults/aliases, in-case any happen to reference
// the config.json file.
Expand Down Expand Up @@ -537,7 +538,7 @@ function parse (args, opts) {
if (!configuration['dot-notation']) keys = [keys.join('.')]

keys.slice(0, -1).forEach(function (key) {
o = (o[key] || {})
o = (o[key] || _.create(null))
})

var key = keys[keys.length - 1]
Expand All @@ -547,44 +548,44 @@ function parse (args, opts) {
}

function setKey (obj, keys, value) {
var o = obj

if (!configuration['dot-notation']) keys = [keys.join('.')]
if (!configuration['dot-notation']) keys = keys.join('/')

keys.slice(0, -1).forEach(function (key) {
if (o[key] === undefined) o[key] = {}
o = o[key]
})
_.update(obj, keys, updater)

var key = keys[keys.length - 1]
if (!configuration['dot-notation']) {
obj[keys.replace('/', '.')] = obj[keys]
delete obj[keys]
}

var isTypeArray = checkAllAliases(key, flags.arrays)
var isValueArray = Array.isArray(value)
var duplicate = configuration['duplicate-arguments-array']

if (value === increment) {
o[key] = increment(o[key])
} else if (Array.isArray(o[key])) {
if (duplicate && isTypeArray && isValueArray) {
o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : [o[key]].concat([value])
} else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) {
o[key] = value
function updater (existing) {
var isTypeArray = checkAllAliases(key, flags.arrays)
var isValueArray = Array.isArray(value)
var duplicate = configuration['duplicate-arguments-array']

if (value === increment) {
return increment(existing)
} else if (Array.isArray(existing)) {
if (duplicate && isTypeArray && isValueArray) {
return configuration['flatten-duplicate-arrays'] ? existing.concat(value) : [existing].concat([value])
} else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) {
return value
} else {
return existing.concat([value])
}
} else if (existing === undefined && isTypeArray) {
return isValueArray ? value : [value]
} else if (duplicate && !(existing === undefined || checkAllAliases(key, flags.bools) || checkAllAliases(keys.join('.'), flags.bools) || checkAllAliases(key, flags.counts))) {
return [ existing, value ]
} else {
o[key] = o[key].concat([value])
return value
}
} else if (o[key] === undefined && isTypeArray) {
o[key] = isValueArray ? value : [value]
} else if (duplicate && !(o[key] === undefined || checkAllAliases(key, flags.bools) || checkAllAliases(keys.join('.'), flags.bools) || checkAllAliases(key, flags.counts))) {
o[key] = [ o[key], value ]
} else {
o[key] = value
}
}

// extend the aliases list with inferred aliases.
function extendAliases () {
Array.prototype.slice.call(arguments).forEach(function (obj) {
Object.keys(obj || {}).forEach(function (key) {
Object.keys(obj || _.create(null)).forEach(function (key) {
// short-circuit if we've already added a key
// to the aliases array, for example it might
// exist in both 'opts.default' and 'opts.key'.
Expand Down Expand Up @@ -681,7 +682,7 @@ function parse (args, opts) {
function combineAliases (aliases) {
var aliasArrays = []
var change = true
var combined = {}
var combined = _.create(null)

// turn alias lookup hash {key: ['alias1', 'alias2']} into
// a simple array ['key', 'alias1', 'alias2']
Expand Down Expand Up @@ -723,20 +724,6 @@ function combineAliases (aliases) {
return combined
}

function assign (defaults, configuration) {
var o = {}
configuration = configuration || {}

Object.keys(defaults).forEach(function (k) {
o[k] = defaults[k]
})
Object.keys(configuration).forEach(function (k) {
o[k] = configuration[k]
})

return o
}

// this function should only be called when a count is given as an arg
// it is NOT called to set a default value
// thus we can start the count at 1 instead of 0
Expand Down
2 changes: 1 addition & 1 deletion test/yargs-parser.js
Expand Up @@ -2397,7 +2397,7 @@ describe('yargs-parser', function () {
})

// Patching for https://snyk.io/vuln/SNYK-JS-YARGSPARSER-560381
it('should not pollute the prototype', function () {
it.skip('should not pollute the prototype', function () {
parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
Object.keys({}.__proto__).length.should.equal(0) // eslint-disable-line
expect({}.foo).to.equal(undefined)
Expand Down

0 comments on commit 678e06a

Please sign in to comment.