Stumbled across an odd issue:
[email protected]
[email protected]
var a = `${() => {
`${''}`
}}`;
var b = `${''}`;
vagrant@vagrant:~/tmp$ eslint --rule {"indent":[2]} --parser babel-eslint test.js
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at RegExp.test (<anonymous>)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:445:32)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
at OffsetStorage.getDesiredIndent (/vagrant/node_modules/eslint/lib/rules/indent.js:451:45)
This originally happened in my application's mid-size state store file, and I reduced it down to this with the issue staying constant. I wasn't able to replicate the issue without the backticks so I'm assuming this is specific to babel-eslint and not base eslint, but I don't know for certain - happy to move this.
It's pretty easy to work around once you know what's causing the problem, as even a minor change will cause the issue to stop occurring. I ended up changing the arrow function to use parentheses instead of curly braces and it went away.
I have recently run into this error as well, have yet to determine the offending code. Will update this thread if I determine what is causing it.
Got the same error and posted a duplicate issue but it contains a snippet to reproduce the error: https://github.com/babel/babel-eslint/issues/609#issue-313450649
package.json
"babel-eslint": "8.2.3",
"eslint": "4.19.1",
Eslint Rule:
"indent": [2, 2],
Result:
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at RegExp.test (<anonymous>)
Does this happen with the default parser (Espree) too? If so, this bug should be filed with ESLint core, since that's where the code for the indent rule is.
@kaicataldo it looks like its an issue related to how we convert Babylon template tokens, I published a PR for a fix if you want to review (https://github.com/babel/babel-eslint/pull/610)!
Just published 8.2.4, which should fix this issue!
Still can reproduce this bug. @existentialism
@zhangtemplar please give a reduced test case and I’ll look into it
@existentialism Sure, check this one:
/* eslint-disable */
import {
createUser, deleteUser, deleteUserUser,
queryMore, queryReportee, queryReporter,
queryUser,
queryUserByProject, queryUserFrom, queryUserTo,
queryUserUser,
updateUser,
} from '../services/api';
import { getCurrentUser } from '../utils/authority';
import { setGroup } from '../utils/group';
/**
* Builds the query to perform aggregation query for user.
*
* @param payload an object for the query
* @return {{}}
*/
function buildQueryForAggeregation(payload) {
const query = {
$projection: {
'user.id': 1,
'user.name': 1,
'user.keyword': 1,
'user.abstract': 1,
'user.time': 1,
'user.logo': 1,
id: 1,
fromId: 1,
toId: 1,
name: 1,
time: 1,
type: 1,
},
};
if (payload !== null) {
query.$where = payload;
} else {
query.$where = {};
}
return query;
}
function merge(response) {
const list = {};
response._items.forEach((relationship) => {
relationship.user.forEach((user) => { list[user.id] = user; });
});
return {
...response,
_items: Object.values(list),
};
}
export default {
namespace: 'user',
state: {
list: null,
currentUser: null,
item: null,
// meta data associated with this query, e.g., total number of results available to query.
meta: null,
// links for navigation purpose.
links: null,
// the groups and its members
group: null,
},
/** 数据字典 */
FIELDS : {
ch :{
id: { name: 'ID', hint: '用户唯一标识' },
name: { name: '用户名', hint: '用户名不能为空' },
abstract: { name: '简介', hint: '个人简介,不超过20字' },
detail: { name: '详细介绍', hint: '详细介绍,不超过200字' },
type: { name: '用户类型', hint: '用户类型' },
keyword: { name: '关键词', hint: '多个词语请用逗号分隔' },
email: { name: '邮箱', hint: '' },
phone: { name: '手机', hint: '' },
password: { name: '密码', hint: '密码' },
website: { name: '网站', hint: '网站URL' },
address: { name: '住址', hint: '常用住址' },
capital: { name: '总投资额', hint: '总投资额' },
netCapital: { name: '单项投资额', hint: '单项投资额' },
title: { name: '头衔', hint: '头衔' },
company: { name: '公司', hint: '公司' },
education: { name: '学历', hint: '学历' },
credit: { name: '信用', hint: '保留' },
},
en :{
id: { name: 'ID', hint: 'User uniquely identifier.' },
name: { name: 'Name', hint: 'Username cannot be empty.' },
abstract: { name: 'Abstract', hint: 'Your personal profile, not more than 20 words' },
detail: { name: 'Detail', hint: 'Your detailed introduction, not more than 200 words.' },
type: { name: 'Type', hint: 'User type.' },
keyword: { name: 'Keyword', hint: 'Please use a comma to separate.' },
email: { name: 'Email', hint: '' },
phone: { name: 'Phone', hint: '' },
password: { name: 'Password', hint: 'Password' },
website: { name: 'Website', hint: 'Website URL' },
address: { name: 'Address', hint: 'Common Address' },
capital: { name: 'Capital', hint: 'Total Investment' },
netCapital: { name: 'Net Capital', hint: 'Single Investment' },
title: { name: 'Title', hint: 'Title' },
company: { name: 'Company', hint: 'Company' },
education: { name: 'Education', hint: 'Education' },
credit: { name: 'Reserved', hint: 'Reserved' },
},
},
/**
* User types on a bit map.
*/
USER_TYPES: {
expert: 1,
investor: 2,
service: 4,
government: 8,
entrepenuer: 16,
angel: 32,
competitor: 64,
judges: 128,
// Those two types are not supposed to change by an user.
admin: 1073741824,
group: 2147483648,
},
/**
* @return object 标准的user数据结构
* */
getTemplate: () => {
return {
id: '',
name: '',
abstract: '',
detail: '',
creationTime: 0,
type: 0,
keyword: [],
email: '',
phone: '',
password: '',
website: '',
address: '',
capital: 0.0,
netCapital: 0.0,
title: '',
company: '',
education: '',
credit: 0.0,
}
},
effects: {
*update({ payload, callback }, { call, put }) {
let response = null;
if (payload.href) {
console.log('update user for %o', payload);
response = yield call(updateUser, payload);
} else {
console.log('create user for %o', payload);
response = yield call(createUser, payload.body);
}
if (callback) {
callback(response);
} else {
yield put({
type: 'queryItem',
payload: response,
});
}
},
*fetchCurrent({ payload, callback }, { put }) {
if (callback) {
callback(getCurrentUser());
} else {
yield put({
type: 'saveCurrentUser',
payload: getCurrentUser(),
});
}
},
*verifyId({ payload, callback }, { call, put }) {
console.log('search user with: %o', payload);
const response = yield call(queryUser, `where=${
encodeURIComponent(JSON.stringify({ id: payload }))}&projection=${
encodeURIComponent(JSON.stringify({ id: 1, name: 1 }))}`);
if (callback) {
callback(response);
} else {
yield put({
type: 'queryList',
payload: response,
});
}
},
*fetchByName({ payload, callback }, { call, put }) {
console.log('search user with: %o', payload);
const response = yield call(queryUser, `where=${
encodeURIComponent(JSON.stringify({ name: { $regex: `(?i)^${payload}` } }))}&projection=${
encodeURIComponent(JSON.stringify({ id: 1, name: 1 }))}`);
if (callback) {
callback(response);
} else {
yield put({
type: 'queryList',
payload: response,
});
}
},
*fetchById({ payload, callback }, { call, put }) {
const id = typeof payload === 'string' ? payload : payload.id;
console.log('request user with %s', id);
const response = yield call(queryUser, `where=${
encodeURIComponent(JSON.stringify({ id }))}`);
if (callback) {
callback(response);
} else {
yield put({
type: 'queryItem',
payload: response,
});
}
},
*fetchMore({ payload, callback }, { call, put }) {
const response = yield call(queryMore, payload);
const result = payload.includes('project/from') ||
payload.includes('user/from') ||
payload.includes('user/to')
? merge(response)
: response;
if (callback) {
callback(result);
} else {
yield put({
type: 'queryList',
payload: result,
});
}
},
*fetchByType({ payload, callback }, { call, put }) {
console.log('search user with: %o', payload);
const query = payload === null ? null : { type: { $bitsAnySet: payload } };
yield put({
type: 'search',
payload: query,
callback,
})
},
*fetchByProject({ payload, callback }, { call, put }) {
console.log('search user by project with: %o', payload);
const query = buildQueryForAggeregation(payload);
const response = yield call(
queryUserByProject,
`aggregate=${encodeURIComponent(JSON.stringify(query))}`);
const result = merge(response);
if (callback) {
callback(result);
} else {
yield put({
type: 'queryList',
payload: result,
});
}
},
*fetchAsFrom({ payload, callback }, { call, put }) {
console.log('search user as fromId with: %o', payload);
const query = buildQueryForAggeregation(payload);
const response = yield call(
queryUserFrom,
`aggregate=${encodeURIComponent(JSON.stringify(query))}`);
const result = merge(response);
if (callback) {
callback(result);
} else {
yield put({
type: 'queryList',
payload: result,
});
}
},
*fetchAsTo({ payload, callback }, { call, put }) {
console.log('search user as toId with: %o', payload);
const query = buildQueryForAggeregation(payload);
const response = yield call(
queryUserTo,
`aggregate=${encodeURIComponent(JSON.stringify(query))}`);
const result = merge(response);
if (callback) {
callback(result);
} else {
yield put({
type: 'queryList',
payload: result,
});
}
},
*search({ payload, callback }, { call, put }) {
console.log('search project with: %o', payload);
const query = payload === null
? ''
: `where=${encodeURIComponent(JSON.stringify(payload))}&`;
const response = yield call(queryUser, `${query}projection=${
encodeURIComponent(JSON.stringify({
id: 1,
name: 1,
keyword: 1,
abstract: 1,
time: 1,
logo: 1,
}))}`);
if (callback) {
callback(response);
} else {
yield put({
type: 'queryList',
payload: response,
});
}
},
*deleteGroup({ payload, callback }, { call, put }) {
console.log('delete group and user-user relationship with: %o', payload);
// Find all the relationship related to this group.
const response = yield call(
queryUserUser,
`where=${encodeURIComponent(JSON.stringify({
$or: [
{ fromId: payload.id },
{ toId: payload.id }
],
type: 4
}))}`);
// Remove the group
console.log('delete group %o', payload._id);
yield call(deleteUser, { href: payload._id, etag: null } );
// Remove all the related relationship
for (let item of response._items) {
console.log('delete user user relationship %o', item._id);
yield call(deleteUserUser, { href: item._id, etag: null });
}
if (callback) {
callback(response);
} else {
yield put({
type: 'queryItem',
payload: response,
});
}
},
*fetchColleague({ payload, callback }, { call, put }) {
const reporteeQuery = {
fromId: payload,
type: 4,
};
const projection = {
'manager.id': 1,
'manager.user.id': 1,
'manager.user.name': 1,
'manager.user.abstract': 1,
'member.id': 1,
'member.user.id': 1,
'member.user.name': 1,
'member.user.abstract': 1,
};
const reportee = yield call(queryReportee, `aggregate=${
encodeURIComponent(JSON.stringify({
$where: reporteeQuery, $projection: projection }))}`);
const reporterQuery = {
toId: payload,
type: 4,
};
const reporter = yield call(queryReporter, `aggregate=${
encodeURIComponent(JSON.stringify({
$where: reporterQuery, $projection: projection }))}`);
// merge the groups.
const groups = {};
const reduce = (data, from, to) => {
data._items[0][from].forEach(item => {
const { id, user } = item;
if (!Object.prototype.hasOwnProperty.call(groups, id)) {
groups[id] = { managers: [], members: [] };
}
groups[id][to].push(...user);
});
};
reduce(reportee, 'manager', 'managers');
reduce(reportee, 'member', 'members');
reduce(reporter, 'manager', 'managers');
reduce(reporter, 'member', 'members');
setGroup(groups);
/* eslint-enable no-param-reassign,prefer-destructuring */
if (callback) {
callback(groups);
} else {
yield put({
type: 'queryGroup',
payload: groups,
});
}
},
},
reducers: {
/**
* Saves the results to list.
*
* @return state/list
*/
queryList(state, action) {
console.log('%d users are fetched', action.payload._items.length);
return {
...state,
list: action.payload._items,
meta: Object.prototype.hasOwnProperty.call(action.payload, '_meta')
? action.payload._meta
: null,
links: Object.prototype.hasOwnProperty.call(action.payload, '_links')
? action.payload._links
: null,
};
},
/**
* Saves the result to item.
*
* @return state/item
*/
queryItem(state, action) {
return {
...state,
item: Object.prototype.hasOwnProperty.call(action.payload, '_items') &&
action.payload._items.length > 0
? action.payload._items[0]
: action.payload,
};
},
save(state, action) {
return {
...state,
list: action.payload,
};
},
saveCurrentUser(state, action) {
return {
...state,
currentUser: action.payload,
};
},
changeNotifyCount(state, action) {
return {
...state,
currentUser: {
...state.currentUser,
notifyCount: action.payload,
},
};
},
queryGroup(state, action) {
return {
...state,
group: action.payload,
};
},
},
};
this code work:
return props.error ? 'border-bottom: 1px solid ' + color.red : 'border-bottom: 1px solid rgba(0, 0, 0, 0.12)'
this code falls with Maximum call stack size exceeded:
return props.error ? `border-bottom: 1px solid ${color.red}`: `border-bottom: 1px solid rgba(0, 0, 0, 0.12)`;
different single quotes
Most helpful comment
Just published 8.2.4, which should fix this issue!