no-this-in-fetch-data.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /**
  2. * @fileoverview disallow `this` in `asyncData/fetch`
  3. * @author Xin Du <clark.duxin@gmail.com>
  4. */
  5. 'use strict'
  6. const satisfies = require('semver/ranges/intersects')
  7. const utils = require('../utils')
  8. const resolver = require('../utils/resolver')
  9. // ------------------------------------------------------------------------------
  10. // Rule Definition
  11. // ------------------------------------------------------------------------------
  12. module.exports = {
  13. meta: {
  14. docs: {
  15. description: 'disallow `this` in `asyncData/fetch`',
  16. category: 'base'
  17. },
  18. messages: {
  19. noThis: 'Unexpected this in {{funcName}}.'
  20. }
  21. },
  22. create (context) {
  23. // variables should be defined here
  24. const forbiddenNodes = new Map()
  25. const options = context.options[0] || {}
  26. const HOOKS = new Set(
  27. ['asyncData'].concat(options.methods || [])
  28. )
  29. const { version } = resolver
  30. // new fetch API can use `this` since 2.12.0
  31. if (version && satisfies(version, '<2.12.0')) {
  32. HOOKS.add('fetch')
  33. }
  34. let nodeUsingThis = []
  35. // ----------------------------------------------------------------------
  36. // Helpers
  37. // ----------------------------------------------------------------------
  38. function enterFunction () {
  39. nodeUsingThis = []
  40. }
  41. function exitFunction (node) {
  42. if (nodeUsingThis.length > 0) {
  43. forbiddenNodes.set(node, nodeUsingThis)
  44. }
  45. }
  46. function markThisUsed (node) {
  47. nodeUsingThis.push(node)
  48. }
  49. // ----------------------------------------------------------------------
  50. // Public
  51. // ----------------------------------------------------------------------
  52. return {
  53. FunctionExpression: enterFunction,
  54. 'FunctionExpression:exit': exitFunction,
  55. ArrowFunctionExpression: enterFunction,
  56. 'ArrowFunctionExpression:exit': exitFunction,
  57. ThisExpression: markThisUsed,
  58. Super: markThisUsed,
  59. ...utils.executeOnVue(context, obj => {
  60. for (const funcName of HOOKS) {
  61. const prop = utils.getFunctionWithName(obj, funcName)
  62. if (prop && forbiddenNodes.has(prop.value)) {
  63. for (const node of forbiddenNodes.get(prop.value)) {
  64. context.report({
  65. node: node,
  66. messageId: 'noThis',
  67. data: {
  68. funcName
  69. }
  70. })
  71. }
  72. }
  73. }
  74. })
  75. }
  76. }
  77. }