]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Rule to disallow assignments to native objects or read-only global variables | |
3 | * @author Ilya Volodin | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | //------------------------------------------------------------------------------ | |
9 | // Rule Definition | |
10 | //------------------------------------------------------------------------------ | |
11 | ||
34eeec05 | 12 | /** @type {import('../shared/types').Rule} */ |
eb39fafa DC |
13 | module.exports = { |
14 | meta: { | |
15 | type: "suggestion", | |
16 | ||
17 | docs: { | |
8f9d1d4d | 18 | description: "Disallow assignments to native objects or read-only global variables", |
eb39fafa DC |
19 | recommended: true, |
20 | url: "https://eslint.org/docs/rules/no-global-assign" | |
21 | }, | |
22 | ||
23 | schema: [ | |
24 | { | |
25 | type: "object", | |
26 | properties: { | |
27 | exceptions: { | |
28 | type: "array", | |
29 | items: { type: "string" }, | |
30 | uniqueItems: true | |
31 | } | |
32 | }, | |
33 | additionalProperties: false | |
34 | } | |
35 | ], | |
36 | ||
37 | messages: { | |
38 | globalShouldNotBeModified: "Read-only global '{{name}}' should not be modified." | |
39 | } | |
40 | }, | |
41 | ||
42 | create(context) { | |
43 | const config = context.options[0]; | |
44 | const exceptions = (config && config.exceptions) || []; | |
45 | ||
46 | /** | |
47 | * Reports write references. | |
48 | * @param {Reference} reference A reference to check. | |
49 | * @param {int} index The index of the reference in the references. | |
50 | * @param {Reference[]} references The array that the reference belongs to. | |
51 | * @returns {void} | |
52 | */ | |
53 | function checkReference(reference, index, references) { | |
54 | const identifier = reference.identifier; | |
55 | ||
56 | if (reference.init === false && | |
57 | reference.isWrite() && | |
58 | ||
59 | /* | |
60 | * Destructuring assignments can have multiple default value, | |
61 | * so possibly there are multiple writeable references for the same identifier. | |
62 | */ | |
63 | (index === 0 || references[index - 1].identifier !== identifier) | |
64 | ) { | |
65 | context.report({ | |
66 | node: identifier, | |
67 | messageId: "globalShouldNotBeModified", | |
68 | data: { | |
69 | name: identifier.name | |
70 | } | |
71 | }); | |
72 | } | |
73 | } | |
74 | ||
75 | /** | |
76 | * Reports write references if a given variable is read-only builtin. | |
77 | * @param {Variable} variable A variable to check. | |
78 | * @returns {void} | |
79 | */ | |
80 | function checkVariable(variable) { | |
8f9d1d4d | 81 | if (variable.writeable === false && !exceptions.includes(variable.name)) { |
eb39fafa DC |
82 | variable.references.forEach(checkReference); |
83 | } | |
84 | } | |
85 | ||
86 | return { | |
87 | Program() { | |
88 | const globalScope = context.getScope(); | |
89 | ||
90 | globalScope.variables.forEach(checkVariable); | |
91 | } | |
92 | }; | |
93 | } | |
94 | }; |