xo 2.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,386 +0,0 @@
1
- const isPropertyContainer = (value) => typeof value === 'function' || (typeof value === 'object' && value !== null);
2
- const isIdentifierNode = (node) => node.type === 'Identifier' && 'name' in node && typeof node.name === 'string';
3
- const isLiteralNode = (node) => node.type === 'Literal';
4
- const isMemberExpressionNode = (node) => node.type === 'MemberExpression'
5
- && 'computed' in node
6
- && typeof node.computed === 'boolean'
7
- && 'object' in node
8
- && 'property' in node;
9
- const isBinaryExpressionNode = (node) => node.type === 'BinaryExpression'
10
- && 'operator' in node
11
- && typeof node.operator === 'string'
12
- && 'left' in node
13
- && 'right' in node;
14
- const isNewExpressionNode = (node) => node.type === 'NewExpression' && 'callee' in node;
15
- const createPropertyInfo = (value, extraProperties = []) => {
16
- const all = new Set();
17
- const callable = new Set();
18
- for (const propertyName of extraProperties) {
19
- all.add(propertyName);
20
- }
21
- for (let currentValue = value; isPropertyContainer(currentValue); currentValue = Object.getPrototypeOf(currentValue)) {
22
- for (const propertyName of Object.getOwnPropertyNames(currentValue)) {
23
- all.add(propertyName);
24
- const descriptor = Object.getOwnPropertyDescriptor(currentValue, propertyName);
25
- if (typeof descriptor?.value === 'function') {
26
- callable.add(propertyName);
27
- }
28
- }
29
- }
30
- return {
31
- all,
32
- callable,
33
- };
34
- };
35
- const emptyFunction = () => undefined;
36
- // Keep the checked native object list explicit so rule behavior stays predictable.
37
- const nativeObjectDefinitions = [
38
- {
39
- typeName: 'Array',
40
- instance: [],
41
- static: Array,
42
- prototype: Array.prototype,
43
- },
44
- {
45
- typeName: 'ArrayBuffer',
46
- instance: new ArrayBuffer(0),
47
- static: ArrayBuffer,
48
- prototype: ArrayBuffer.prototype,
49
- },
50
- {
51
- typeName: 'Boolean',
52
- instance: Boolean.prototype,
53
- static: Boolean,
54
- prototype: Boolean.prototype,
55
- },
56
- {
57
- typeName: 'DataView',
58
- instance: new DataView(new ArrayBuffer(1)),
59
- static: DataView,
60
- prototype: DataView.prototype,
61
- },
62
- {
63
- typeName: 'Date',
64
- instance: new Date(),
65
- static: Date,
66
- prototype: Date.prototype,
67
- },
68
- {
69
- typeName: 'Float32Array',
70
- instance: new Float32Array(),
71
- static: Float32Array,
72
- prototype: Float32Array.prototype,
73
- },
74
- {
75
- typeName: 'Float64Array',
76
- instance: new Float64Array(),
77
- static: Float64Array,
78
- prototype: Float64Array.prototype,
79
- },
80
- {
81
- typeName: 'Function',
82
- instance: emptyFunction,
83
- static: Function,
84
- prototype: Function.prototype,
85
- },
86
- {
87
- typeName: 'Int8Array',
88
- instance: new Int8Array(),
89
- static: Int8Array,
90
- prototype: Int8Array.prototype,
91
- },
92
- {
93
- typeName: 'Int16Array',
94
- instance: new Int16Array(),
95
- static: Int16Array,
96
- prototype: Int16Array.prototype,
97
- },
98
- {
99
- typeName: 'Int32Array',
100
- instance: new Int32Array(),
101
- static: Int32Array,
102
- prototype: Int32Array.prototype,
103
- },
104
- {
105
- typeName: 'Map',
106
- instance: new Map(),
107
- static: Map,
108
- prototype: Map.prototype,
109
- },
110
- {
111
- typeName: 'Number',
112
- instance: Number.prototype,
113
- static: Number,
114
- prototype: Number.prototype,
115
- },
116
- {
117
- typeName: 'Object',
118
- instance: {},
119
- static: Object,
120
- prototype: Object.prototype,
121
- },
122
- {
123
- typeName: 'Promise',
124
- instance: Promise.resolve(),
125
- static: Promise,
126
- prototype: Promise.prototype,
127
- },
128
- {
129
- typeName: 'RegExp',
130
- instance: /./v,
131
- static: RegExp,
132
- prototype: RegExp.prototype,
133
- },
134
- {
135
- typeName: 'Set',
136
- instance: new Set(),
137
- static: Set,
138
- prototype: Set.prototype,
139
- },
140
- {
141
- typeName: 'String',
142
- instance: String.prototype,
143
- instanceProperties: ['length'],
144
- static: String,
145
- prototype: String.prototype,
146
- },
147
- {
148
- typeName: 'Uint8Array',
149
- instance: new Uint8Array(),
150
- static: Uint8Array,
151
- prototype: Uint8Array.prototype,
152
- },
153
- {
154
- typeName: 'Uint8ClampedArray',
155
- instance: new Uint8ClampedArray(),
156
- static: Uint8ClampedArray,
157
- prototype: Uint8ClampedArray.prototype,
158
- },
159
- {
160
- typeName: 'Uint16Array',
161
- instance: new Uint16Array(),
162
- static: Uint16Array,
163
- prototype: Uint16Array.prototype,
164
- },
165
- {
166
- typeName: 'Uint32Array',
167
- instance: new Uint32Array(),
168
- static: Uint32Array,
169
- prototype: Uint32Array.prototype,
170
- },
171
- {
172
- typeName: 'URL',
173
- instance: new URL('https://example.com'),
174
- static: URL,
175
- prototype: URL.prototype,
176
- },
177
- {
178
- typeName: 'URLSearchParams',
179
- instance: new URLSearchParams(),
180
- static: URLSearchParams,
181
- prototype: URLSearchParams.prototype,
182
- },
183
- {
184
- typeName: 'JSON',
185
- static: JSON,
186
- },
187
- {
188
- typeName: 'Math',
189
- static: Math,
190
- },
191
- {
192
- typeName: 'Reflect',
193
- static: Reflect,
194
- },
195
- ];
196
- const nativeObjects = new Map();
197
- for (const nativeObjectDefinition of nativeObjectDefinitions) {
198
- const nativeObjectInfo = {};
199
- if (nativeObjectDefinition.instance) {
200
- nativeObjectInfo.instance = createPropertyInfo(nativeObjectDefinition.instance, nativeObjectDefinition.instanceProperties);
201
- }
202
- if (nativeObjectDefinition.prototype) {
203
- nativeObjectInfo.prototype = createPropertyInfo(nativeObjectDefinition.prototype);
204
- }
205
- if (nativeObjectDefinition.static) {
206
- nativeObjectInfo.static = createPropertyInfo(nativeObjectDefinition.static);
207
- }
208
- nativeObjects.set(nativeObjectDefinition.typeName, nativeObjectInfo);
209
- }
210
- const getPropertyName = (memberExpression) => {
211
- const { property } = memberExpression;
212
- if (memberExpression.computed) {
213
- return isLiteralNode(property) && typeof property.value === 'string' ? property.value : undefined;
214
- }
215
- return isIdentifierNode(property) ? property.name : undefined;
216
- };
217
- const resolveBinaryExpressionType = (binaryExpression) => {
218
- if (binaryExpression.operator !== '+') {
219
- return undefined;
220
- }
221
- const leftReference = resolveNativeObjectReference(binaryExpression.left);
222
- const rightReference = resolveNativeObjectReference(binaryExpression.right);
223
- if (leftReference?.usage !== 'instance' || rightReference?.usage !== 'instance') {
224
- return undefined;
225
- }
226
- if (leftReference.typeName === 'String' || rightReference.typeName === 'String') {
227
- return {
228
- typeName: 'String',
229
- usage: 'instance',
230
- };
231
- }
232
- return undefined;
233
- };
234
- const resolveIdentifierReference = (node) => {
235
- if (!nativeObjects.has(node.name)) {
236
- return undefined;
237
- }
238
- return {
239
- typeName: node.name,
240
- usage: 'static',
241
- };
242
- };
243
- const resolveLiteralReference = (node) => {
244
- if (node.regex) {
245
- return {
246
- typeName: 'RegExp',
247
- usage: 'instance',
248
- };
249
- }
250
- if (typeof node.value === 'boolean') {
251
- return {
252
- typeName: 'Boolean',
253
- usage: 'instance',
254
- };
255
- }
256
- if (typeof node.value === 'number') {
257
- return {
258
- typeName: 'Number',
259
- usage: 'instance',
260
- };
261
- }
262
- if (typeof node.value === 'string') {
263
- return {
264
- typeName: 'String',
265
- usage: 'instance',
266
- };
267
- }
268
- return undefined;
269
- };
270
- const resolvePrototypeReference = (node) => {
271
- if (getPropertyName(node) !== 'prototype' || !isIdentifierNode(node.object) || !nativeObjects.has(node.object.name)) {
272
- return undefined;
273
- }
274
- return {
275
- typeName: node.object.name,
276
- usage: 'prototype',
277
- };
278
- };
279
- const resolveNewExpressionReference = (node) => {
280
- if (!isIdentifierNode(node.callee) || !nativeObjects.has(node.callee.name)) {
281
- return undefined;
282
- }
283
- return {
284
- typeName: node.callee.name,
285
- usage: 'instance',
286
- };
287
- };
288
- function resolveNativeObjectReference(node) {
289
- if (!node) {
290
- return undefined;
291
- }
292
- if (isMemberExpressionNode(node)) {
293
- return resolvePrototypeReference(node);
294
- }
295
- if (isBinaryExpressionNode(node)) {
296
- return resolveBinaryExpressionType(node);
297
- }
298
- if (isLiteralNode(node)) {
299
- return resolveLiteralReference(node);
300
- }
301
- if (isIdentifierNode(node)) {
302
- return resolveIdentifierReference(node);
303
- }
304
- if (isNewExpressionNode(node)) {
305
- return resolveNewExpressionReference(node);
306
- }
307
- switch (node.type) {
308
- case 'ArrayExpression': {
309
- return {
310
- typeName: 'Array',
311
- usage: 'instance',
312
- };
313
- }
314
- case 'ArrowFunctionExpression':
315
- case 'FunctionExpression': {
316
- return {
317
- typeName: 'Function',
318
- usage: 'instance',
319
- };
320
- }
321
- case 'ObjectExpression': {
322
- return {
323
- typeName: 'Object',
324
- usage: 'instance',
325
- };
326
- }
327
- case 'TemplateLiteral': {
328
- return {
329
- typeName: 'String',
330
- usage: 'instance',
331
- };
332
- }
333
- default: {
334
- return undefined;
335
- }
336
- }
337
- }
338
- const noUseExtendNativeRule = {
339
- meta: {
340
- type: 'problem',
341
- docs: {
342
- description: 'Disallow relying on non-standard properties on native objects',
343
- },
344
- messages: {
345
- unexpected: 'Avoid relying on extended native objects.',
346
- },
347
- schema: [],
348
- },
349
- create(context) {
350
- return {
351
- // eslint-disable-next-line @typescript-eslint/naming-convention
352
- MemberExpression(node) {
353
- const propertyName = getPropertyName(node);
354
- if (!propertyName) {
355
- return;
356
- }
357
- const nativeObjectReference = resolveNativeObjectReference(node.object);
358
- if (!nativeObjectReference) {
359
- return;
360
- }
361
- const propertyInfo = nativeObjects.get(nativeObjectReference.typeName)?.[nativeObjectReference.usage];
362
- if (!propertyInfo) {
363
- return;
364
- }
365
- const isCall = node.parent.type === 'CallExpression' && node.parent.callee === node;
366
- if (isCall) {
367
- if (!propertyInfo.callable.has(propertyName)) {
368
- context.report({
369
- node,
370
- messageId: 'unexpected',
371
- });
372
- }
373
- return;
374
- }
375
- if (!propertyInfo.all.has(propertyName)) {
376
- context.report({
377
- node,
378
- messageId: 'unexpected',
379
- });
380
- }
381
- },
382
- };
383
- },
384
- };
385
- export default noUseExtendNativeRule;
386
- //# sourceMappingURL=no-use-extend-native.js.map