Skip to content

Commit b132191

Browse files
authored
Update vue/no-restricted-call-after-await rule to support <script setup> (#1551)
1 parent cd2ad1c commit b132191

File tree

2 files changed

+87
-23
lines changed

2 files changed

+87
-23
lines changed

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

+56-23
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,21 @@ module.exports = {
5454
},
5555
/** @param {RuleContext} context */
5656
create(context) {
57+
/**
58+
* @typedef {object} SetupScopeData
59+
* @property {boolean} afterAwait
60+
* @property {[number,number]} range
61+
*/
62+
5763
/** @type {Map<ESNode, string>} */
5864
const restrictedCallNodes = new Map()
59-
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration, { setupProperty: Property, afterAwait: boolean }>} */
60-
const setupFunctions = new Map()
65+
/** @type {Map<FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program, SetupScopeData>} */
66+
const setupScopes = new Map()
6167

6268
/**x
6369
* @typedef {object} ScopeStack
6470
* @property {ScopeStack | null} upper
65-
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} functionNode
71+
* @property {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration | Program} scopeNode
6672
*/
6773
/** @type {ScopeStack | null} */
6874
let scopeStack = null
@@ -136,6 +142,11 @@ module.exports = {
136142
{
137143
/** @param {Program} node */
138144
Program(node) {
145+
scopeStack = {
146+
upper: scopeStack,
147+
scopeNode: node
148+
}
149+
139150
const tracker = new ReferenceTracker(context.getScope())
140151

141152
for (const option of context.options) {
@@ -170,39 +181,39 @@ module.exports = {
170181
}
171182
}
172183
}
173-
}
174-
},
175-
utils.defineVueVisitor(context, {
184+
},
176185
/** @param {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} node */
177186
':function'(node) {
178187
scopeStack = {
179188
upper: scopeStack,
180-
functionNode: node
189+
scopeNode: node
181190
}
182191
},
183-
onSetupFunctionEnter(node) {
184-
setupFunctions.set(node, {
185-
setupProperty: node.parent,
186-
afterAwait: false
187-
})
192+
':function:exit'() {
193+
scopeStack = scopeStack && scopeStack.upper
188194
},
189-
AwaitExpression() {
195+
/** @param {AwaitExpression} node */
196+
AwaitExpression(node) {
190197
if (!scopeStack) {
191198
return
192199
}
193-
const setupFunctionData = setupFunctions.get(scopeStack.functionNode)
194-
if (!setupFunctionData) {
200+
const setupScope = setupScopes.get(scopeStack.scopeNode)
201+
if (!setupScope || !utils.inRange(setupScope.range, node)) {
195202
return
196203
}
197-
setupFunctionData.afterAwait = true
204+
setupScope.afterAwait = true
198205
},
199206
/** @param {CallExpression} node */
200207
CallExpression(node) {
201208
if (!scopeStack) {
202209
return
203210
}
204-
const setupFunctionData = setupFunctions.get(scopeStack.functionNode)
205-
if (!setupFunctionData || !setupFunctionData.afterAwait) {
211+
const setupScope = setupScopes.get(scopeStack.scopeNode)
212+
if (
213+
!setupScope ||
214+
!setupScope.afterAwait ||
215+
!utils.inRange(setupScope.range, node)
216+
) {
206217
return
207218
}
208219

@@ -214,12 +225,34 @@ module.exports = {
214225
data: { message }
215226
})
216227
}
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+
})
217253
},
218-
/** @param {FunctionExpression | ArrowFunctionExpression | FunctionDeclaration} node */
219-
':function:exit'(node) {
220-
scopeStack = scopeStack && scopeStack.upper
221-
222-
setupFunctions.delete(node)
254+
onSetupFunctionExit(node) {
255+
setupScopes.delete(node)
223256
}
224257
})
225258
)

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

+31
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ tester.run('no-restricted-call-after-await', rule, {
125125
{ module: './baz', path: 'qux' },
126126
{ module: 'vue-i18n', path: 'useI18n' }
127127
]
128+
},
129+
{
130+
filename: 'test.vue',
131+
code: `
132+
<script setup>
133+
import {useI18n} from 'vue-i18n'
134+
useI18n()
135+
await doSomething()
136+
</script>
137+
`,
138+
options: [{ module: 'vue-i18n', path: 'useI18n' }],
139+
parserOptions: { ecmaVersion: 2022 }
128140
}
129141
],
130142
invalid: [
@@ -377,6 +389,25 @@ tester.run('no-restricted-call-after-await', rule, {
377389
line: 7
378390
}
379391
]
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+
]
380411
}
381412
]
382413
})

0 commit comments

Comments
 (0)