Skip to content

Commit 9dc78d0

Browse files
authored
Fix false positives for <script setup> in vue/no-lifecycle-after-await, vue/no-watch-after-await, vue/no-restricted-call-after-await rules. (#1569)
1 parent cac3beb commit 9dc78d0

6 files changed

+70
-159
lines changed

Diff for: lib/rules/no-lifecycle-after-await.js

+11-36
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,19 @@ module.exports = {
4848
/**
4949
* @typedef {object} ScopeStack
5050
* @property {ScopeStack | null} upper
51-
* @property {FunctionDeclaration | FunctionExpression | ArrowFunctionExpression | Program} scopeNode
51+
* @property {FunctionDeclaration | FunctionExpression | ArrowFunctionExpression} scopeNode
5252
*/
5353
/** @type {Set<ESNode>} */
5454
const lifecycleHookCallNodes = new Set()
55-
/** @type {Map<FunctionDeclaration | FunctionExpression | ArrowFunctionExpression | Program, SetupScopeData>} */
55+
/** @type {Map<FunctionDeclaration | FunctionExpression | ArrowFunctionExpression, SetupScopeData>} */
5656
const setupScopes = new Map()
5757

5858
/** @type {ScopeStack | null} */
5959
let scopeStack = null
6060

6161
return utils.compositingVisitors(
6262
{
63-
/**
64-
* @param {Program} node
65-
*/
66-
Program(node) {
67-
scopeStack = {
68-
upper: scopeStack,
69-
scopeNode: node
70-
}
71-
63+
Program() {
7264
const tracker = new ReferenceTracker(context.getScope())
7365
const traceMap = {
7466
/** @type {TraceMap} */
@@ -85,6 +77,14 @@ module.exports = {
8577
for (const { node } of tracker.iterateEsmReferences(traceMap)) {
8678
lifecycleHookCallNodes.add(node)
8779
}
80+
}
81+
},
82+
utils.defineVueVisitor(context, {
83+
onSetupFunctionEnter(node) {
84+
setupScopes.set(node, {
85+
afterAwait: false,
86+
range: node.range
87+
})
8888
},
8989
/**
9090
* @param {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression} node
@@ -133,31 +133,6 @@ module.exports = {
133133
messageId: 'forbidden'
134134
})
135135
}
136-
}
137-
},
138-
(() => {
139-
const scriptSetup = utils.getScriptSetupElement(context)
140-
if (!scriptSetup) {
141-
return {}
142-
}
143-
return {
144-
/**
145-
* @param {Program} node
146-
*/
147-
Program(node) {
148-
setupScopes.set(node, {
149-
afterAwait: false,
150-
range: scriptSetup.range
151-
})
152-
}
153-
}
154-
})(),
155-
utils.defineVueVisitor(context, {
156-
onSetupFunctionEnter(node) {
157-
setupScopes.set(node, {
158-
afterAwait: false,
159-
range: node.range
160-
})
161136
},
162137
onSetupFunctionExit(node) {
163138
setupScopes.delete(node)

Diff for: lib/rules/no-restricted-call-after-await.js

+10-32
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ module.exports = {
6262

6363
/** @type {Map<ESNode, string>} */
6464
const restrictedCallNodes = new Map()
65-
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program, SetupScopeData>} */
65+
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration, SetupScopeData>} */
6666
const setupScopes = new Map()
6767

6868
/**x
6969
* @typedef {object} ScopeStack
7070
* @property {ScopeStack | null} upper
71-
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program} scopeNode
71+
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} scopeNode
7272
*/
7373
/** @type {ScopeStack | null} */
7474
let scopeStack = null
@@ -142,11 +142,6 @@ module.exports = {
142142
{
143143
/** @param {Program} node */
144144
Program(node) {
145-
scopeStack = {
146-
upper: scopeStack,
147-
scopeNode: node
148-
}
149-
150145
const tracker = new ReferenceTracker(context.getScope())
151146

152147
for (const option of context.options) {
@@ -181,6 +176,14 @@ module.exports = {
181176
}
182177
}
183178
}
179+
}
180+
},
181+
utils.defineVueVisitor(context, {
182+
onSetupFunctionEnter(node) {
183+
setupScopes.set(node, {
184+
afterAwait: false,
185+
range: node.range
186+
})
184187
},
185188
/** @param {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} node */
186189
':function'(node) {
@@ -225,31 +228,6 @@ module.exports = {
225228
data: { message }
226229
})
227230
}
228-
}
229-
},
230-
(() => {
231-
const scriptSetup = utils.getScriptSetupElement(context)
232-
if (!scriptSetup) {
233-
return {}
234-
}
235-
return {
236-
/**
237-
* @param {Program} node
238-
*/
239-
Program(node) {
240-
setupScopes.set(node, {
241-
afterAwait: false,
242-
range: scriptSetup.range
243-
})
244-
}
245-
}
246-
})(),
247-
utils.defineVueVisitor(context, {
248-
onSetupFunctionEnter(node) {
249-
setupScopes.set(node, {
250-
afterAwait: false,
251-
range: node.range
252-
})
253231
},
254232
onSetupFunctionExit(node) {
255233
setupScopes.delete(node)

Diff for: lib/rules/no-watch-after-await.js

+11-34
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,20 @@ module.exports = {
6262
* @property {boolean} afterAwait
6363
* @property {[number,number]} range
6464
*/
65-
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program, SetupScopeData>} */
65+
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration, SetupScopeData>} */
6666
const setupScopes = new Map()
6767

6868
/**
6969
* @typedef {object} ScopeStack
7070
* @property {ScopeStack | null} upper
71-
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program} scopeNode
71+
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} scopeNode
7272
*/
7373
/** @type {ScopeStack | null} */
7474
let scopeStack = null
7575

7676
return utils.compositingVisitors(
7777
{
78-
/** @param {Program} node */
79-
Program(node) {
80-
scopeStack = {
81-
upper: scopeStack,
82-
scopeNode: node
83-
}
84-
78+
Program() {
8579
const tracker = new ReferenceTracker(context.getScope())
8680
const traceMap = {
8781
vue: {
@@ -98,6 +92,14 @@ module.exports = {
9892
for (const { node } of tracker.iterateEsmReferences(traceMap)) {
9993
watchCallNodes.add(node)
10094
}
95+
}
96+
},
97+
utils.defineVueVisitor(context, {
98+
onSetupFunctionEnter(node) {
99+
setupScopes.set(node, {
100+
afterAwait: false,
101+
range: node.range
102+
})
101103
},
102104
/** @param {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} node */
103105
':function'(node) {
@@ -140,31 +142,6 @@ module.exports = {
140142
messageId: 'forbidden'
141143
})
142144
}
143-
}
144-
},
145-
(() => {
146-
const scriptSetup = utils.getScriptSetupElement(context)
147-
if (!scriptSetup) {
148-
return {}
149-
}
150-
return {
151-
/**
152-
* @param {Program} node
153-
*/
154-
Program(node) {
155-
setupScopes.set(node, {
156-
afterAwait: false,
157-
range: scriptSetup.range
158-
})
159-
}
160-
}
161-
})(),
162-
utils.defineVueVisitor(context, {
163-
onSetupFunctionEnter(node) {
164-
setupScopes.set(node, {
165-
afterAwait: false,
166-
range: node.range
167-
})
168145
},
169146
onSetupFunctionExit(node) {
170147
setupScopes.delete(node)

Diff for: tests/lib/rules/no-lifecycle-after-await.js

+12-18
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,18 @@ tester.run('no-lifecycle-after-await', rule, {
139139
<script>
140140
import {onMounted} from 'vue'
141141
await doSomething()
142+
onMounted(() => { /* ... */ }) // not error
143+
</script>
144+
`,
145+
parserOptions: { ecmaVersion: 2022 }
146+
},
147+
{
148+
filename: 'test.vue',
149+
code: `
150+
<script setup>
151+
import {onMounted} from 'vue'
152+
await doSomething()
153+
142154
onMounted(() => { /* ... */ }) // not error
143155
</script>
144156
`,
@@ -261,24 +273,6 @@ tester.run('no-lifecycle-after-await', rule, {
261273
messageId: 'forbidden'
262274
}
263275
]
264-
},
265-
{
266-
filename: 'test.vue',
267-
code: `
268-
<script setup>
269-
import {onMounted} from 'vue'
270-
await doSomething()
271-
272-
onMounted(() => { /* ... */ }) // error
273-
</script>
274-
`,
275-
parserOptions: { ecmaVersion: 2022 },
276-
errors: [
277-
{
278-
messageId: 'forbidden',
279-
line: 6
280-
}
281-
]
282276
}
283277
]
284278
})

Diff for: tests/lib/rules/no-restricted-call-after-await.js

+12-19
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ tester.run('no-restricted-call-after-await', rule, {
137137
`,
138138
options: [{ module: 'vue-i18n', path: 'useI18n' }],
139139
parserOptions: { ecmaVersion: 2022 }
140+
},
141+
{
142+
filename: 'test.vue',
143+
code: `
144+
<script setup>
145+
import {useI18n} from 'vue-i18n'
146+
await doSomething()
147+
useI18n()
148+
</script>
149+
`,
150+
parserOptions: { ecmaVersion: 2022 },
151+
options: [{ module: 'vue-i18n', path: 'useI18n' }]
140152
}
141153
],
142154
invalid: [
@@ -389,25 +401,6 @@ tester.run('no-restricted-call-after-await', rule, {
389401
line: 7
390402
}
391403
]
392-
},
393-
{
394-
filename: 'test.vue',
395-
code: `
396-
<script setup>
397-
import {useI18n} from 'vue-i18n'
398-
await doSomething()
399-
useI18n()
400-
</script>
401-
`,
402-
parserOptions: { ecmaVersion: 2022 },
403-
options: [{ module: 'vue-i18n', path: 'useI18n' }],
404-
errors: [
405-
{
406-
message:
407-
'The `import("vue-i18n").useI18n` after `await` expression are forbidden.',
408-
line: 5
409-
}
410-
]
411404
}
412405
]
413406
})

Diff for: tests/lib/rules/no-watch-after-await.js

+14-20
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ tester.run('no-watch-after-await', rule, {
155155
</script>
156156
`,
157157
parserOptions: { ecmaVersion: 2022 }
158+
},
159+
{
160+
filename: 'test.vue',
161+
code: `
162+
<script setup>
163+
import {watch} from 'vue'
164+
watch(foo, () => { /* ... */ })
165+
166+
await doSomething()
167+
168+
watch(foo, () => { /* ... */ })
169+
</script>
170+
`,
171+
parserOptions: { ecmaVersion: 2022 }
158172
}
159173
],
160174
invalid: [
@@ -236,26 +250,6 @@ tester.run('no-watch-after-await', rule, {
236250
line: 12
237251
}
238252
]
239-
},
240-
{
241-
filename: 'test.vue',
242-
code: `
243-
<script setup>
244-
import {watch} from 'vue'
245-
watch(foo, () => { /* ... */ })
246-
247-
await doSomething()
248-
249-
watch(foo, () => { /* ... */ })
250-
</script>
251-
`,
252-
parserOptions: { ecmaVersion: 2022 },
253-
errors: [
254-
{
255-
message: 'The `watch` after `await` expression are forbidden.',
256-
line: 8
257-
}
258-
]
259253
}
260254
]
261255
})

0 commit comments

Comments
 (0)