-
-
Notifications
You must be signed in to change notification settings - Fork 649
/
no-side-effects-in-computed-properties.js
86 lines (75 loc) · 2.47 KB
/
no-side-effects-in-computed-properties.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* @fileoverview Don't introduce side effects in computed properties
* @author Michał Sajnóg
*/
'use strict'
const utils = require('../utils')
/**
* @typedef {import('vue-eslint-parser').AST.ESLintObjectExpression} ObjectExpression
* @typedef {import('vue-eslint-parser').AST.ESLintMemberExpression} MemberExpression
* @typedef {import('../utils').ComponentComputedProperty} ComponentComputedProperty
*/
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'disallow side effects in computed properties',
categories: ['vue3-essential', 'essential'],
url: 'https://eslint.vuejs.org/rules/no-side-effects-in-computed-properties.html'
},
fixable: null,
schema: []
},
create (context) {
/** @type {Map<ObjectExpression, ComponentComputedProperty[]>} */
const computedPropertiesMap = new Map()
let scopeStack = { upper: null, body: null }
function onFunctionEnter (node) {
scopeStack = { upper: scopeStack, body: node.body }
}
function onFunctionExit () {
scopeStack = scopeStack.upper
}
return utils.defineVueVisitor(context, {
onVueObjectEnter (node) {
computedPropertiesMap.set(node, utils.getComputedProperties(node))
},
':function': onFunctionEnter,
':function:exit': onFunctionExit,
'MemberExpression > :matches(Identifier, ThisExpression)' (node, { node: vueNode }) {
const targetBody = scopeStack.body
const computedProperty = computedPropertiesMap.get(vueNode).find(cp => {
return (
cp.value &&
node.loc.start.line >= cp.value.loc.start.line &&
node.loc.end.line <= cp.value.loc.end.line &&
targetBody === cp.value
)
})
if (!computedProperty) {
return
}
if (!utils.isThis(node, context)) {
return
}
/** @type {MemberExpression} */
const mem = node.parent
if (mem.object !== node) {
return
}
const invalid = utils.findMutating(mem)
if (invalid) {
context.report({
node: invalid.node,
message: 'Unexpected side effect in "{{key}}" computed property.',
data: { key: computedProperty.key }
})
}
}
}
)
}
}