Skip to content

Commit f200db4

Browse files
Ensure arguments to escapeAll and quoteAll are actually arrays
1 parent 7a82c3f commit f200db4

5 files changed

Lines changed: 88 additions & 4 deletions

File tree

src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import process from "node:process";
1313

1414
import { parseOptions } from "./internal/options.js";
1515
import { getHelpersByPlatform } from "./internal/platforms.js";
16-
import { checkedToString } from "./internal/reflection.js";
16+
import { checkedToString, ensureArray } from "./internal/reflection.js";
1717

1818
/**
1919
* A class to escape user-controlled inputs to shell commands to prevent shell
@@ -127,6 +127,7 @@ export class Shescape {
127127
* @since 2.0.0
128128
*/
129129
escapeAll(args) {
130+
ensureArray(args);
130131
return args.map((arg) => this.escape(arg));
131132
}
132133

@@ -161,6 +162,7 @@ export class Shescape {
161162
* @since 2.0.0
162163
*/
163164
quoteAll(args) {
165+
ensureArray(args);
164166
return args.map((arg) => this.quote(arg));
165167
}
166168
}

src/internal/reflection.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@
44
*/
55

66
/**
7-
* The error message for incorrect parameter types.
7+
* The error message for non-array values.
88
*
99
* @constant
1010
* @type {string}
1111
*/
12-
const typeError =
12+
const typeErrorArray = "Shescape requires argument lists to be an array";
13+
14+
/**
15+
* The error message for non-stringable values.
16+
*
17+
* @constant
18+
* @type {string}
19+
*/
20+
const typeErrorString =
1321
"Shescape requires strings or values that can be converted into a string using .toString()";
1422

1523
/**
@@ -79,12 +87,24 @@ export function checkedToString(value) {
7987

8088
const maybeStr = maybeToString(value);
8189
if (maybeStr === null) {
82-
throw new TypeError(typeError);
90+
throw new TypeError(typeErrorString);
8391
}
8492

8593
return maybeStr;
8694
}
8795

96+
/**
97+
* Ensures a value is an array.
98+
*
99+
* @param {unknown} value The value of interest.
100+
* @throws {TypeError} The `value` is not an array.
101+
*/
102+
export function ensureArray(value) {
103+
if (!isArray(value)) {
104+
throw new TypeError(typeErrorArray);
105+
}
106+
}
107+
88108
/**
89109
* Checks if a value is a string.
90110
*
@@ -94,3 +114,11 @@ export function checkedToString(value) {
94114
export function isString(value) {
95115
return typeof value === typeofString;
96116
}
117+
118+
/**
119+
* Checks if a value is an array.
120+
*
121+
* @param {unknown} value The value of interest.
122+
* @throws {TypeError} The `value` is not an array.
123+
*/
124+
export const isArray = Array.isArray;

test/_constants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ export const illegalArgumentLists = [
2929
{ description: "typed array (uint8)", value: new Uint8Array() },
3030
{ description: "typed array (uint16)", value: new Uint16Array() },
3131
{ description: "typed array (uint32)", value: new Uint32Array() },
32+
{ description: "typed array (uint64)", value: new BigUint64Array() },
3233
{ description: "typed array (int8)", value: new Int8Array() },
3334
{ description: "typed array (int16)", value: new Int16Array() },
3435
{ description: "typed array (int32)", value: new Int32Array() },
36+
{ description: "typed array (int64)", value: new BigInt64Array() },
37+
{ description: "typed array (float16)", value: new Float16Array() },
38+
{ description: "typed array (float32)", value: new Float32Array() },
39+
{ description: "typed array (float64)", value: new Float64Array() },
40+
{ description: "typed array (clamped)", value: new Uint8ClampedArray() },
3541
];
3642

3743
/* OS platforms (based on https://nodejs.org/api/os.html#osplatform) */
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @overview Contains unit tests for the `ensureArray` function.
3+
* @license MIT
4+
*/
5+
6+
import { testProp } from "@fast-check/ava";
7+
import test from "ava";
8+
import * as fc from "fast-check";
9+
10+
import { ensureArray } from "../../../src/internal/reflection.js";
11+
12+
import { constants } from "./_.js";
13+
14+
testProp("arrays", [fc.array(fc.anything())], (t, value) => {
15+
t.notThrows(() => ensureArray(value));
16+
});
17+
18+
for (const { description, value } of constants.illegalArgumentLists) {
19+
test(description, (t) => {
20+
t.throws(() => ensureArray(value), {
21+
instanceOf: TypeError,
22+
message: "Shescape requires argument lists to be an array",
23+
});
24+
});
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @overview Contains unit tests for the `isString` function.
3+
* @license MIT
4+
*/
5+
6+
import { testProp } from "@fast-check/ava";
7+
import * as fc from "fast-check";
8+
9+
import { isArray } from "../../../src/internal/reflection.js";
10+
11+
testProp("arrays", [fc.array(fc.anything())], (t, value) => {
12+
const result = isArray(value);
13+
t.true(result);
14+
});
15+
16+
testProp(
17+
"non-arrays",
18+
[fc.anything().filter((value) => !Array.isArray(value))],
19+
(t, value) => {
20+
const result = isArray(value);
21+
t.false(result);
22+
},
23+
);

0 commit comments

Comments
 (0)