Skip to content

Commit e916558

Browse files
feat(getStaticValue): added more safe calls (#76)
1 parent 5b1d059 commit e916558

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

src/get-static-value.mjs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ const builtinNames = Object.freeze(
6666
const callAllowed = new Set(
6767
[
6868
Array.isArray,
69+
Array.of,
70+
Array.prototype.at,
71+
Array.prototype.concat,
72+
Array.prototype.entries,
73+
Array.prototype.every,
74+
Array.prototype.filter,
75+
Array.prototype.find,
76+
Array.prototype.findIndex,
77+
Array.prototype.flat,
78+
Array.prototype.includes,
79+
Array.prototype.indexOf,
80+
Array.prototype.join,
81+
Array.prototype.keys,
82+
Array.prototype.lastIndexOf,
83+
Array.prototype.slice,
84+
Array.prototype.some,
85+
Array.prototype.toString,
86+
Array.prototype.values,
6987
typeof BigInt === "function" ? BigInt : undefined,
7088
Boolean,
7189
Date,
@@ -78,6 +96,12 @@ const callAllowed = new Set(
7896
isFinite,
7997
isNaN,
8098
isPrototypeOf,
99+
Map,
100+
Map.prototype.entries,
101+
Map.prototype.get,
102+
Map.prototype.has,
103+
Map.prototype.keys,
104+
Map.prototype.values,
81105
...Object.getOwnPropertyNames(Math)
82106
.filter((k) => k !== "random")
83107
.map((k) => Math[k])
@@ -87,6 +111,10 @@ const callAllowed = new Set(
87111
Number.isNaN,
88112
Number.parseFloat,
89113
Number.parseInt,
114+
Number.prototype.toExponential,
115+
Number.prototype.toFixed,
116+
Number.prototype.toPrecision,
117+
Number.prototype.toString,
90118
Object,
91119
Object.entries,
92120
Object.is,
@@ -98,10 +126,39 @@ const callAllowed = new Set(
98126
parseFloat,
99127
parseInt,
100128
RegExp,
129+
Set,
130+
Set.prototype.entries,
131+
Set.prototype.has,
132+
Set.prototype.keys,
133+
Set.prototype.values,
101134
String,
102135
String.fromCharCode,
103136
String.fromCodePoint,
104137
String.raw,
138+
String.prototype.at,
139+
String.prototype.charAt,
140+
String.prototype.charCodeAt,
141+
String.prototype.codePointAt,
142+
String.prototype.concat,
143+
String.prototype.endsWith,
144+
String.prototype.includes,
145+
String.prototype.indexOf,
146+
String.prototype.lastIndexOf,
147+
String.prototype.normalize,
148+
String.prototype.padEnd,
149+
String.prototype.padStart,
150+
String.prototype.slice,
151+
String.prototype.startsWith,
152+
String.prototype.substr,
153+
String.prototype.substring,
154+
String.prototype.toLowerCase,
155+
String.prototype.toString,
156+
String.prototype.toUpperCase,
157+
String.prototype.trim,
158+
String.prototype.trimEnd,
159+
String.prototype.trimLeft,
160+
String.prototype.trimRight,
161+
String.prototype.trimStart,
105162
Symbol.for,
106163
Symbol.keyFor,
107164
unescape,

test/get-static-value.mjs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ describe("The 'getStaticValue' function", () => {
3737
{ code: "1 ^ 15", expected: { value: 14 } },
3838
{ code: "3 & 2", expected: { value: 2 } },
3939
{ code: "a + 1", expected: null },
40+
{
41+
code: "(123.456).toExponential()",
42+
expected: { value: "1.23456e+2" },
43+
},
44+
{ code: "(123.456).toExponential(3)", expected: { value: "1.235e+2" } },
45+
{ code: "(123.456).toFixed()", expected: { value: "123" } },
46+
{ code: "(123.456).toFixed(1)", expected: { value: "123.5" } },
47+
{ code: "(123.456).toPrecision()", expected: { value: "123.456" } },
48+
{ code: "(123.456).toPrecision(2)", expected: { value: "1.2e+2" } },
49+
{ code: "(123.456).toString()", expected: { value: "123.456" } },
50+
{ code: "(123).toString(16)", expected: { value: "7b" } },
4051
{ code: "String(7)", expected: { value: "7" } },
4152
{ code: "Math.round(0.7)", expected: { value: 1 } },
4253
{ code: "Math['round'](0.4)", expected: { value: 0 } },
@@ -84,6 +95,50 @@ describe("The 'getStaticValue' function", () => {
8495
{ code: "Object.xxx", expected: { value: undefined } },
8596
{ code: "new Array(2)", expected: null },
8697
{ code: "new Array(len)", expected: null },
98+
{ code: "Array.of()", expected: { value: [] } },
99+
{ code: "Array.of(1)", expected: { value: [1] } },
100+
{ code: "Array.of(1, 2)", expected: { value: [1, 2] } },
101+
{
102+
code: "[0,1,2].at(-1)",
103+
expected: Array.prototype.at ? { value: 2 } : null,
104+
},
105+
{
106+
code: "[0,1,2].concat([3,4], [5])",
107+
expected: { value: [0, 1, 2, 3, 4, 5] },
108+
},
109+
{ code: "[0,1,2].every(Boolean)", expected: { value: false } },
110+
{ code: "[0,1,2].filter(Boolean)", expected: { value: [1, 2] } },
111+
{ code: "[0,1,2].find((i) => i === 2)", expected: null },
112+
{ code: "[0,1,2].findIndex((i) => i === 2)", expected: null },
113+
{
114+
code: "[-1, [0,1,2], [[4]]].flat()",
115+
expected: { value: [-1, 0, 1, 2, [4]] },
116+
},
117+
{ code: "[0,1,2].includes(4)", expected: { value: false } },
118+
{ code: "[0,1,2].indexOf(4)", expected: { value: -1 } },
119+
{ code: "[0,1,2].join()", expected: { value: "0,1,2" } },
120+
{ code: "[0,1,2].join('|')", expected: { value: "0|1|2" } },
121+
{ code: "[1,1,1].lastIndexOf(1)", expected: { value: 2 } },
122+
{ code: "[0,1,2].slice(1)", expected: { value: [1, 2] } },
123+
{ code: "[0,1,2].some(Boolean)", expected: { value: true } },
124+
{ code: "[0,1,2].toString()", expected: { value: "0,1,2" } },
125+
{ code: "String([0,1,2])", expected: { value: "0,1,2" } },
126+
{ code: "[...[0,1,,2].keys()]", expected: { value: [0, 1, 2, 3] } },
127+
{
128+
code: "[...[0,1,,2].values()]",
129+
expected: { value: [0, 1, undefined, 2] },
130+
},
131+
{
132+
code: "[...[0,1,,2].entries()]",
133+
expected: {
134+
value: [
135+
[0, 0],
136+
[1, 1],
137+
[2, undefined],
138+
[3, 2],
139+
],
140+
},
141+
},
87142
{ code: "({})", expected: { value: {} } },
88143
{
89144
code: "({a: 1, b: 2, c: 3})",
@@ -105,6 +160,12 @@ describe("The 'getStaticValue' function", () => {
105160
{ code: "String.raw`\\unicode`", expected: { value: "\\unicode" } },
106161
{ code: "`he${a}o`", expected: null }, //eslint-disable-line no-template-curly-in-string
107162
{ code: "x`hello`", expected: null },
163+
{ code: "' foo '.trim()", expected: { value: "foo" } },
164+
{ code: "' foo '.trim().toUpperCase()", expected: { value: "FOO" } },
165+
{ code: "' foo '.indexOf('f')", expected: { value: 2 } },
166+
{ code: "' foo '.charAt(4)", expected: { value: "o" } },
167+
{ code: "' foo '.charCodeAt(400)", expected: { value: NaN } },
168+
{ code: "' foo '.repeat(1e12)", expected: null },
108169
{ code: "-1", expected: { value: -1 } },
109170
{ code: "+'1'", expected: { value: 1 } },
110171
{ code: "!0", expected: { value: true } },
@@ -243,6 +304,31 @@ const aMap = Object.freeze({
243304
code: "({'a': 1, 1e+1: 2, 2n: 3})",
244305
expected: { value: { a: 1, 10: 2, 2: 3 } },
245306
},
307+
{
308+
code: "new Set([1,2])",
309+
expected: { value: new Set([1, 2]) },
310+
},
311+
{
312+
code: "new Set([1,2]).has(2)",
313+
expected: { value: true },
314+
},
315+
{
316+
code: "new Map([[1,2], [4,6]])",
317+
expected: {
318+
value: new Map([
319+
[1, 2],
320+
[4, 6],
321+
]),
322+
},
323+
},
324+
{
325+
code: "const m = new Map([[1,2], [4,6]]); m.get(1)",
326+
expected: { value: 2 },
327+
},
328+
{
329+
code: "const m = new Map([[1,2], [4,6]]); m.has(2)",
330+
expected: { value: false },
331+
},
246332
...(semver.gte(eslint.Linter.version, "8.0.0")
247333
? [
248334
{

0 commit comments

Comments
 (0)