Skip to content

Commit 04defba

Browse files
lundibundiBethGriggs
authored andcommitted
lib: allow to validate enums with validateOneOf
PR-URL: #34070 Reviewed-By: Zeyu Yang <[email protected]> Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 258f64f commit 04defba

File tree

10 files changed

+108
-40
lines changed

10 files changed

+108
-40
lines changed

‎lib/_http_agent.js‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@ const{async_id_symbol } = require('internal/async_hooks').symbols;
3939
const{
4040
codes: {
4141
ERR_INVALID_ARG_TYPE,
42-
ERR_INVALID_OPT_VALUE,
4342
ERR_OUT_OF_RANGE,
4443
},
4544
}=require('internal/errors');
4645
const{ once }=require('internal/util');
47-
const{ validateNumber }=require('internal/validators');
46+
const{ validateNumber, validateOneOf}=require('internal/validators');
4847

4948
constkOnKeylog=Symbol('onkeylog');
5049
constkRequestOptions=Symbol('requestOptions');
@@ -99,9 +98,7 @@ function Agent(options){
9998
this.maxTotalSockets=this.options.maxTotalSockets;
10099
this.totalSocketCount=0;
101100

102-
if(this.scheduling!=='fifo'&&this.scheduling!=='lifo'){
103-
thrownewERR_INVALID_OPT_VALUE('scheduling',this.scheduling);
104-
}
101+
validateOneOf(this.scheduling,'scheduling',['fifo','lifo'],true);
105102

106103
if(this.maxTotalSockets!==undefined){
107104
validateNumber(this.maxTotalSockets,'maxTotalSockets');

‎lib/dns.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const{
4949
const{
5050
validatePort,
5151
validateString,
52+
validateOneOf,
5253
}=require('internal/validators');
5354

5455
const{
@@ -114,8 +115,7 @@ function lookup(hostname, options, callback){
114115
family=options>>>0;
115116
}
116117

117-
if(family!==0&&family!==4&&family!==6)
118-
thrownewERR_INVALID_OPT_VALUE('family',family);
118+
validateOneOf(family,'family',[0,4,6],true);
119119

120120
if(!hostname){
121121
emitInvalidHostnameWarning(hostname);

‎lib/internal/child_process.js‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const{
2121
ERR_MISSING_ARGS
2222
}
2323
}=require('internal/errors');
24-
const{ validateString }=require('internal/validators');
24+
const{ validateString, validateOneOf}=require('internal/validators');
2525
constEventEmitter=require('events');
2626
constnet=require('net');
2727
constdgram=require('dgram');
@@ -345,13 +345,9 @@ ChildProcess.prototype.spawn = function(options){
345345
constipcFd=stdio.ipcFd;
346346
stdio=options.stdio=stdio.stdio;
347347

348-
if(options.serialization!==undefined&&
349-
options.serialization!=='json'&&
350-
options.serialization!=='advanced'){
351-
thrownewERR_INVALID_OPT_VALUE('options.serialization',
352-
options.serialization);
353-
}
354348

349+
validateOneOf(options.serialization,'options.serialization',
350+
[undefined,'json','advanced'],true);
355351
constserialization=options.serialization||'json';
356352

357353
if(ipc!==undefined){

‎lib/internal/dns/promises.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ const{
3131
}=codes;
3232
const{
3333
validatePort,
34-
validateString
34+
validateString,
35+
validateOneOf,
3536
}=require('internal/validators');
3637

3738
functiononlookup(err,addresses){
@@ -116,8 +117,7 @@ function lookup(hostname, options){
116117
family=options>>>0;
117118
}
118119

119-
if(family!==0&&family!==4&&family!==6)
120-
thrownewERR_INVALID_OPT_VALUE('family',family);
120+
validateOneOf(family,'family',[0,4,6],true);
121121

122122
returncreateLookupPromise(family,hostname,all,hints,verbatim);
123123
}

‎lib/internal/validators.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const{
1313
ERR_SOCKET_BAD_PORT,
1414
ERR_INVALID_ARG_TYPE,
1515
ERR_INVALID_ARG_VALUE,
16+
ERR_INVALID_OPT_VALUE,
1617
ERR_OUT_OF_RANGE,
1718
ERR_UNKNOWN_SIGNAL,
1819
ERR_INVALID_CALLBACK,
@@ -126,6 +127,21 @@ function validateNumber(value, name){
126127
thrownewERR_INVALID_ARG_TYPE(name,'number',value);
127128
}
128129

130+
constvalidateOneOf=hideStackFrames((value,name,oneOf,option=false)=>{
131+
if(!oneOf.includes(value)){
132+
constallowed=oneOf
133+
.map((v)=>(typeofv==='string' ? `'${v}'` : String(v)))
134+
.join(', ');
135+
if(!option){
136+
constreason='must be one of: '+allowed;
137+
thrownewERR_INVALID_ARG_VALUE(name,value,reason);
138+
}else{
139+
constreason='Must be one of: '+allowed;
140+
thrownewERR_INVALID_OPT_VALUE(name,value,reason);
141+
}
142+
}
143+
});
144+
129145
functionvalidateBoolean(value,name){
130146
if(typeofvalue!=='boolean')
131147
thrownewERR_INVALID_ARG_TYPE(name,'boolean',value);
@@ -212,6 +228,7 @@ module.exports ={
212228
validateInteger,
213229
validateNumber,
214230
validateObject,
231+
validateOneOf,
215232
validatePort,
216233
validateSignalName,
217234
validateString,

‎lib/vm.js‎

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ const{
3939
const{
4040
ERR_CONTEXT_NOT_INITIALIZED,
4141
ERR_INVALID_ARG_TYPE,
42-
ERR_INVALID_ARG_VALUE,
4342
}=require('internal/errors').codes;
4443
const{
4544
isArrayBufferView,
@@ -52,6 +51,7 @@ const{
5251
validateBoolean,
5352
validateBuffer,
5453
validateObject,
54+
validateOneOf,
5555
}=require('internal/validators');
5656
const{
5757
kVmBreakFirstLineSymbol,
@@ -246,17 +246,11 @@ function createContext(contextObject ={}, options ={}){
246246

247247
letmicrotaskQueue=null;
248248
if(microtaskMode!==undefined){
249-
validateString(microtaskMode,'options.microtaskMode');
249+
validateOneOf(microtaskMode,'options.microtaskMode',
250+
['afterEvaluate',undefined]);
250251

251-
if(microtaskMode==='afterEvaluate'){
252+
if(microtaskMode==='afterEvaluate')
252253
microtaskQueue=newMicrotaskQueue();
253-
}else{
254-
thrownewERR_INVALID_ARG_VALUE(
255-
'options.microtaskQueue',
256-
microtaskQueue,
257-
'must be \'afterEvaluate\' or undefined'
258-
);
259-
}
260254
}
261255

262256
makeContext(contextObject,name,origin,strings,wasm,microtaskQueue);
@@ -395,16 +389,8 @@ function measureMemory(options ={}){
395389
emitExperimentalWarning('vm.measureMemory');
396390
validateObject(options,'options');
397391
const{ mode ='summary', execution ='default'}=options;
398-
if(mode!=='summary'&&mode!=='detailed'){
399-
thrownewERR_INVALID_ARG_VALUE(
400-
'options.mode',options.mode,
401-
'must be either \'summary\' or \'detailed\'');
402-
}
403-
if(execution!=='default'&&execution!=='eager'){
404-
thrownewERR_INVALID_ARG_VALUE(
405-
'options.execution',options.execution,
406-
'must be either \'default\' or \'eager\'');
407-
}
392+
validateOneOf(mode,'options.mode',['summary','detailed']);
393+
validateOneOf(execution,'options.execution',['default','eager']);
408394
constresult=_measureMemory(measureMemoryModes[mode],
409395
measureMemoryExecutions[execution]);
410396
if(result===undefined){

‎test/parallel/test-child-process-advanced-serialization.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ if (process.argv[2] !== 'child'){
1111
},{
1212
code: 'ERR_INVALID_OPT_VALUE',
1313
message: `The value "${value}" is invalid `+
14-
'for option "options.serialization"'
14+
'for option "options.serialization". '+
15+
"Must be one of: undefined, 'json', 'advanced'"
1516
});
1617
}
1718

‎test/parallel/test-dns-lookup.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ assert.throws(() =>{
7272
consterr={
7373
code: 'ERR_INVALID_OPT_VALUE',
7474
name: 'TypeError',
75-
message: 'The value "20" is invalid for option "family"'
75+
message: 'The value "20" is invalid for option "family". '+
76+
'Must be one of: 0, 4, 6'
7677
};
7778
constoptions={
7879
hints: 0,

‎test/parallel/test-http-agent-scheduling.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ function badSchedulingOptionTest(){
137137
assert.strictEqual(err.code,'ERR_INVALID_OPT_VALUE');
138138
assert.strictEqual(
139139
err.message,
140-
'The value "filo" is invalid for option "scheduling"'
140+
'The value "filo" is invalid for option "scheduling". '+
141+
"Must be one of: 'fifo', 'lifo'"
141142
);
142143
}
143144
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
require('../common');
5+
constassert=require('assert');
6+
const{ validateOneOf }=require('internal/validators');
7+
8+
{
9+
// validateOneOf number incorrect.
10+
constallowed=[2,3];
11+
assert.throws(()=>validateOneOf(1,'name',allowed),{
12+
code: 'ERR_INVALID_ARG_VALUE',
13+
// eslint-disable-next-line quotes
14+
message: `The argument 'name' must be one of: 2, 3. Received 1`
15+
});
16+
assert.throws(()=>validateOneOf(1,'name',allowed,true),{
17+
code: 'ERR_INVALID_OPT_VALUE',
18+
message: 'The value "1" is invalid for option "name". '+
19+
'Must be one of: 2, 3'
20+
});
21+
}
22+
23+
{
24+
// validateOneOf number correct.
25+
validateOneOf(2,'name',[1,2]);
26+
}
27+
28+
{
29+
// validateOneOf string incorrect.
30+
constallowed=['b','c'];
31+
assert.throws(()=>validateOneOf('a','name',allowed),{
32+
code: 'ERR_INVALID_ARG_VALUE',
33+
// eslint-disable-next-line quotes
34+
message: `The argument 'name' must be one of: 'b', 'c'. Received 'a'`
35+
});
36+
assert.throws(()=>validateOneOf('a','name',allowed,true),{
37+
code: 'ERR_INVALID_OPT_VALUE',
38+
// eslint-disable-next-line quotes
39+
message: `The value "a" is invalid for option "name". `+
40+
"Must be one of: 'b', 'c'",
41+
});
42+
}
43+
44+
{
45+
// validateOneOf string correct.
46+
validateOneOf('two','name',['one','two']);
47+
}
48+
49+
{
50+
// validateOneOf Symbol incorrect.
51+
constallowed=[Symbol.for('b'),Symbol.for('c')];
52+
assert.throws(()=>validateOneOf(Symbol.for('a'),'name',allowed),{
53+
code: 'ERR_INVALID_ARG_VALUE',
54+
// eslint-disable-next-line quotes
55+
message: `The argument 'name' must be one of: Symbol(b), Symbol(c). `+
56+
'Received Symbol(a)'
57+
});
58+
assert.throws(()=>validateOneOf(Symbol.for('a'),'name',allowed,true),{
59+
code: 'ERR_INVALID_OPT_VALUE',
60+
message: 'The value "Symbol(a)" is invalid for option "name". '+
61+
'Must be one of: Symbol(b), Symbol(c)',
62+
});
63+
}
64+
65+
{
66+
// validateOneOf Symbol correct.
67+
constallowed=[Symbol.for('b'),Symbol.for('c')];
68+
validateOneOf(Symbol.for('b'),'name',allowed);
69+
}

0 commit comments

Comments
(0)