Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash when using objectsInObjects option in vue/object-curly-spacing rule. #1515

Merged
merged 1 commit into from Jun 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions lib/utils/index.js
Expand Up @@ -101,6 +101,7 @@ const SVG_ELEMENT_NAMES = new Set(require('./svg-elements.json'))
const VOID_ELEMENT_NAMES = new Set(require('./void-elements.json'))
const path = require('path')
const vueEslintParser = require('vue-eslint-parser')
const traverseNodes = vueEslintParser.AST.traverseNodes
const { findVariable } = require('eslint-utils')

/**
Expand Down Expand Up @@ -142,11 +143,56 @@ function wrapContextToOverrideTokenMethods(context, tokenStore) {
: []
return tokensAndComments
}

/** @param {number} index */
function getNodeByRangeIndex(index) {
const templateBody = eslintSourceCode.ast.templateBody
if (!templateBody) {
return eslintSourceCode.ast
}

/** @type {ASTNode} */
let result = eslintSourceCode.ast
/** @type {ASTNode[]} */
const skipNodes = []
let breakFlag = false

traverseNodes(templateBody, {
enterNode(node, parent) {
if (breakFlag) {
return
}
if (skipNodes[0] === parent) {
skipNodes.unshift(node)
return
}
if (node.range[0] <= index && index < node.range[1]) {
result = node
} else {
skipNodes.unshift(node)
}
},
leaveNode(node) {
if (breakFlag) {
return
}
if (result === node) {
breakFlag = true
} else if (skipNodes[0] === node) {
skipNodes.shift()
}
}
})
return result
}
const sourceCode = new Proxy(Object.assign({}, eslintSourceCode), {
get(_object, key) {
if (key === 'tokensAndComments') {
return getTokensAndComments()
}
if (key === 'getNodeByRangeIndex') {
return getNodeByRangeIndex
}
// @ts-expect-error
return key in tokenStore ? tokenStore[key] : eslintSourceCode[key]
}
Expand Down
60 changes: 60 additions & 0 deletions tests/lib/rules/object-curly-spacing.js
Expand Up @@ -26,6 +26,20 @@ tester.run('object-curly-spacing', rule, {
{
code: '<template><div :[{a:1}]="a" /></template>',
options: ['always']
},
{
code: `
<template>
<div v-bind="{foo: {bar: 'baz'} }">
Hello World
</div>
</template>`,
options: [
'never',
{
objectsInObjects: true
}
]
}
],
invalid: [
Expand Down Expand Up @@ -97,6 +111,52 @@ tester.run('object-curly-spacing', rule, {
"A space is required after '{'.",
"A space is required before '}'."
]
},
{
code: `
<template>
<div v-bind="{ foo: { bar: 'baz' }}">
Hello World
</div>
</template>`,
options: [
'never',
{
objectsInObjects: true
}
],
output: `
<template>
<div v-bind="{foo: {bar: 'baz'} }">
Hello World
</div>
</template>`,
errors: [
"There should be no space after '{'.",
"There should be no space after '{'.",
"There should be no space before '}'.",
"A space is required before '}'."
]
},
{
code: `
<template>
<div v-bind="{ foo: { bar: 'baz' }}">
Hello World
</div>
</template>`,
options: ['never'],
output: `
<template>
<div v-bind="{foo: {bar: 'baz'}}">
Hello World
</div>
</template>`,
errors: [
"There should be no space after '{'.",
"There should be no space after '{'.",
"There should be no space before '}'."
]
}
]
})