Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

Commit

Permalink
feat: add no-timing-in-fetch-data
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkdo committed Dec 10, 2018
1 parent f4f750a commit 1436642
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 2 deletions.
50 changes: 50 additions & 0 deletions docs/rules/no-timing-in-fetch-data.md
@@ -0,0 +1,50 @@
# nuxt/no-timing-in-fetch-data

> disallow `setTimeout/setInterval` in `asyncData/fetch`
- :gear: This rule is included in `"plugin:nuxt/recommended"`.

## Rule Details

This rule is for preventing using `setTimeout/setInterval` in `asyncData/fetch` since it may lead to memory leak

Examples of **incorrect** code for this rule:

```js

export default {
async asyncData() {
let foo = 'baz'
},
fetch() {
let foo = 'baz'
}
}

```

Examples of **correct** code for this rule:

```js

export default {
asyncData() {
let foo = 'bar'
setTimeout(() => {
foo = 'baz'
}, 0)
},
fetch() {
let foo = 'bar'
setInterval(() => {
foo = 'baz'
}, 0)
}
}

```

## :mag: Implementation

- [Rule source](https://github.com/nuxt/eslint-plugin-nuxt/blob/master/lib/rules/no-timing-in-fetch-data.js)
- [Test source](https://github.com/nuxt/eslint-plugin-nuxt/blob/master/lib/rules/__test__/no-timing-in-fetch-data.test.js)
3 changes: 2 additions & 1 deletion lib/configs/ssr.js
@@ -1,6 +1,7 @@
module.exports = {
extends: require.resolve('./base.js'),
rules: {
'nuxt/no-globals-in-created': 'warn'
'nuxt/no-globals-in-created': 'warn',
'nuxt/no-timing-in-fetch-data': 'warn'
}
}
3 changes: 2 additions & 1 deletion lib/index.js
Expand Up @@ -4,7 +4,8 @@ module.exports = {
'no-this-in-fetch': require('./rules/no-this-in-fetch')
},
configs: {
'base': require('./configs/base')
'base': require('./configs/base'),
'ssr': require('./configs/ssr')
},
processors: {
'.vue': require('./processors')
Expand Down
94 changes: 94 additions & 0 deletions lib/rules/__test__/no-timing-in-fetch-data.test.js
@@ -0,0 +1,94 @@
/**
* @fileoverview disallow `setTimeout/setInterval` in `asyncData/fetch`
* @author Xin Du <clark.duxin@gmail.com>
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../no-timing-in-fetch-data')

var RuleTester = require('eslint').RuleTester

const parserOptions = {
ecmaVersion: 2018,
sourceType: 'module'
}

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var ruleTester = new RuleTester()
ruleTester.run('no-timing-in-fetch-data', rule, {

valid: [
{
filename: 'test.vue',
code: `
export default {
async asyncData() {
let foo = 'baz'
},
fetch() {
let foo = 'baz'
}
}
`,
parserOptions
}
],

invalid: [
{
filename: 'test.vue',
code: `
export default {
asyncData() {
let foo = 'bar'
setTimeout(() => {
foo = 'baz'
}, 0)
},
fetch() {
let foo = 'bar'
setInterval(() => {
foo = 'baz'
}, 0)
}
}
`,
errors: [{
message: 'Unexpected setTimeout in asyncData.',
type: 'CallExpression'
}, {
message: 'Unexpected setInterval in fetch.',
type: 'CallExpression'
}],
parserOptions
},
{
filename: 'test.vue',
code: `
export default {
asyncData() {
let timer = setInterval
},
fetch() {
let timer = setTimeout
}
}
`,
errors: [{
message: 'Unexpected setInterval in asyncData.',
type: 'VariableDeclarator'
}, {
message: 'Unexpected setTimeout in fetch.',
type: 'VariableDeclarator'
}],
parserOptions
}
]
})
70 changes: 70 additions & 0 deletions lib/rules/no-timing-in-fetch-data.js
@@ -0,0 +1,70 @@
/**
* @fileoverview disallow `setTimeout/setInterval` in `asyncData/fetch`
* @author Xin Du <clark.duxin@gmail.com>
*/
'use strict'

const utils = require('../utils')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: 'disallow `setTimeout/setInterval` in `asyncData/fetch`',
category: 'ssr'
},
messages: {
noTiming: 'Unexpected {{name}} in {{funcName}}.'
}
},

create: function (context) {
const forbiddenNodes = []
const options = context.options[0] || {}

const HOOKS = new Set(
['fetch', 'asyncData'].concat(options.methods || [])
)
const TIMING = ['setTimeout', 'setInterval']

function isTiming (name) {
return TIMING.includes(name)
}

return {
CallExpression: function (node) {
if (!node.callee) return

const name = node.callee.name

if (isTiming(name)) {
forbiddenNodes.push({ name, node })
}
},
VariableDeclarator (node) {
if (!node.init) return

const name = node.init.name

if (isTiming(name)) {
forbiddenNodes.push({ name, node })
}
},
...utils.executeOnVue(context, obj => {
for (const { funcName, name, node } of utils.getFunctionWithChild(obj, HOOKS, forbiddenNodes)) {
context.report({
node,
messageId: 'noTiming',
data: {
name,
funcName
}
})
}
})
}
}
}

0 comments on commit 1436642

Please sign in to comment.