Skip to content

Commit a8528e6

Browse files
committed
fix: address positional argument strict() bug introduced in #766 (#784)
1 parent 23ccbb1 commit a8528e6

File tree

4 files changed

+44
-12
lines changed

4 files changed

+44
-12
lines changed

lib/command.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ module.exports = function (yargs, usage, validation) {
140140
// what does yargs look like after the buidler is run?
141141
var innerArgv = parsed.argv
142142
var innerYargs = null
143+
var positionalMap = {}
143144

144145
currentContext.commands.push(command)
145146
if (typeof commandHandler.builder === 'function') {
@@ -173,15 +174,17 @@ module.exports = function (yargs, usage, validation) {
173174
aliases = innerYargs.parsed.aliases
174175
}
175176

176-
if (!yargs._hasOutput()) populatePositionals(commandHandler, innerArgv, currentContext, yargs)
177-
178-
if (commandHandler.handler && !yargs._hasOutput()) {
179-
commandHandler.handler(innerArgv)
177+
if (!yargs._hasOutput()) {
178+
positionalMap = populatePositionals(commandHandler, innerArgv, currentContext, yargs)
180179
}
181180

182181
// we apply validation post-hoc, so that custom
183182
// checks get passed populated positional arguments.
184-
yargs._runValidation(innerArgv, aliases)
183+
yargs._runValidation(innerArgv, aliases, positionalMap)
184+
185+
if (commandHandler.handler && !yargs._hasOutput()) {
186+
commandHandler.handler(innerArgv)
187+
}
185188

186189
currentContext.commands.pop()
187190
numFiles = currentContext.files.length - numFiles
@@ -196,25 +199,27 @@ module.exports = function (yargs, usage, validation) {
196199
argv._ = argv._.slice(context.commands.length) // nuke the current commands
197200
var demanded = commandHandler.demanded.slice(0)
198201
var optional = commandHandler.optional.slice(0)
202+
var positionalMap = {}
199203

200204
validation.positionalCount(demanded.length, argv._.length)
201205

202206
while (demanded.length) {
203207
var demand = demanded.shift()
204-
populatePositional(demand, argv, yargs)
208+
populatePositional(demand, argv, yargs, positionalMap)
205209
}
206210

207211
while (optional.length) {
208212
var maybe = optional.shift()
209-
populatePositional(maybe, argv, yargs)
213+
populatePositional(maybe, argv, yargs, positionalMap)
210214
}
211215

212216
argv._ = context.commands.concat(argv._)
217+
return positionalMap
213218
}
214219

215220
// populate a single positional argument and its
216221
// aliases onto argv.
217-
function populatePositional (positional, argv, yargs) {
222+
function populatePositional (positional, argv, yargs, positionalMap) {
218223
// "positional" consists of the positional.cmd, an array representing
219224
// the positional's name and aliases, and positional.variadic
220225
// indicating whether or not it is a variadic array.
@@ -229,6 +234,7 @@ module.exports = function (yargs, usage, validation) {
229234
if (value) argv[cmd] = value
230235
else argv[cmd] = value = argv._.shift()
231236
}
237+
positionalMap[cmd] = true
232238
postProcessPositional(yargs, argv, cmd)
233239
addCamelCaseExpansions(argv, cmd)
234240
}

lib/validation.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ module.exports = function (yargs, usage, y18n) {
116116
}
117117

118118
// check for unknown arguments (strict-mode).
119-
self.unknownArguments = function (argv, aliases) {
119+
self.unknownArguments = function (argv, aliases, positionalMap) {
120120
const aliasLookup = {}
121121
const descriptions = usage.getDescriptions()
122122
const demandedOptions = yargs.getDemandedOptions()
@@ -134,6 +134,7 @@ module.exports = function (yargs, usage, y18n) {
134134
if (key !== '$0' && key !== '_' &&
135135
!descriptions.hasOwnProperty(key) &&
136136
!demandedOptions.hasOwnProperty(key) &&
137+
!positionalMap.hasOwnProperty(key) &&
137138
!aliasLookup.hasOwnProperty(key)) {
138139
unknown.push(key)
139140
}

test/command.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,31 @@ describe('Command', function () {
986986
yargs.argv // parse and run command
987987
commandCalled.should.be.true
988988
})
989+
990+
// address regression introduced in #766, thanks @nexdrew!
991+
it('does not fail strict check due to postional command arguments', function (done) {
992+
yargs()
993+
.strict()
994+
.command('hi <name>', 'The hi command')
995+
.parse('hi ben', function (err, argv, output) {
996+
expect(err).to.equal(null)
997+
return done()
998+
})
999+
})
1000+
1001+
it('does not fire command if validation fails', function (done) {
1002+
var commandRun = false
1003+
yargs()
1004+
.strict()
1005+
.command('hi <name>', 'The hi command', function () {}, function (argv) {
1006+
commandRun = true
1007+
})
1008+
.parse('hi ben --hello=world', function (err, argv, output) {
1009+
commandRun.should.equal(false)
1010+
err.message.should.equal('Unknown argument: hello')
1011+
return done()
1012+
})
1013+
})
9891014
})
9901015

9911016
describe('types', function () {

yargs.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,18 +1051,18 @@ function Yargs (processArgs, cwd, parentRequire) {
10511051
// if we're executed via bash completion, don't
10521052
// bother with validation.
10531053
if (!argv[completion.completionKey]) {
1054-
self._runValidation(argv, aliases)
1054+
self._runValidation(argv, aliases, {})
10551055
}
10561056
}
10571057

10581058
return setPlaceholderKeys(argv)
10591059
}
10601060

1061-
self._runValidation = function (argv, aliases) {
1061+
self._runValidation = function (argv, aliases, positionalMap) {
10621062
validation.nonOptionCount(argv)
10631063
validation.missingArgumentValue(argv)
10641064
validation.requiredArguments(argv)
1065-
if (strict) validation.unknownArguments(argv, aliases)
1065+
if (strict) validation.unknownArguments(argv, aliases, positionalMap)
10661066
validation.customChecks(argv, aliases)
10671067
validation.limitedChoices(argv)
10681068
validation.implications(argv)

0 commit comments

Comments
 (0)