From 5c2f0f05578f1b1c724229126392ced1574ae121 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Thu, 4 Feb 2021 01:34:30 -0700
Subject: [PATCH] chore: eslint no-restricted-syntax
---
.eslintrc | 31 +++++++++++-----------
install/web.js | 18 ++++++-------
src/analytics.js | 10 +++----
src/database/mongo/helpers.js | 12 ++++-----
src/flags.js | 50 ++++++++++++++++-------------------
src/install.js | 7 +----
src/meta/settings.js | 10 +++----
src/middleware/headers.js | 6 ++---
src/plugins/index.js | 8 +-----
src/settings.js | 38 +++++++++-----------------
src/socket.io/admin/config.js | 13 +++------
src/socket.io/admin/rooms.js | 30 ++++++++++-----------
src/user/data.js | 6 ++---
src/user/jobs.js | 12 ++++-----
src/user/reset.js | 4 +--
src/webserver.js | 6 ++---
src/widgets/index.js | 7 +----
test/api.js | 8 +++---
test/flags.js | 40 +++++++++++-----------------
19 files changed, 125 insertions(+), 191 deletions(-)
diff --git a/.eslintrc b/.eslintrc
index 17eef35ba7..5cd72ea708 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -65,22 +65,21 @@
"AssignmentExpression": { "array": false, "object": false }
}],
// identical to airbnb rule, except for allowing for..of, because we want to use it
- // "no-restricted-syntax": [
- // "error",
- // {
- // "selector": "ForInStatement",
- // "message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
- // },
- // {
- // "selector": "LabeledStatement",
- // "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
- // },
- // {
- // "selector": "WithStatement",
- // "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
- // }
- // ],
- "no-restricted-syntax": "off",
+ "no-restricted-syntax": [
+ "error",
+ {
+ "selector": "ForInStatement",
+ "message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
+ },
+ {
+ "selector": "LabeledStatement",
+ "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
+ },
+ {
+ "selector": "WithStatement",
+ "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
+ }
+ ],
// allow lines of up to 120 characters
// "max-len": ["error", { "code": 120, "tabWidth": 2, "ignoreUrls": true, "ignoreStrings": true, "ignoreTemplateLiterals": true, "ignoreRegExpLiterals": true }],
"max-len": "off", // do this LAST
diff --git a/install/web.js b/install/web.js
index baf4a16a65..5c5d3d2d8c 100644
--- a/install/web.js
+++ b/install/web.js
@@ -151,9 +151,9 @@ function install(req, res) {
req.setTimeout(0);
installing = true;
const setupEnvVars = nconf.get();
- for (const i in req.body) {
- if (req.body.hasOwnProperty(i) && !process.env.hasOwnProperty(i)) {
- setupEnvVars[i.replace(':', '__')] = req.body[i];
+ for (const [key, value] of Object.entries(req.body)) {
+ if (!process.env.hasOwnProperty(key)) {
+ setupEnvVars[key.replace(':', '__')] = value;
}
}
@@ -161,12 +161,12 @@ function install(req, res) {
const pushToRoot = function (parentKey, key) {
setupEnvVars[`${parentKey}__${key}`] = setupEnvVars[parentKey][key];
};
- for (const j in setupEnvVars) {
- if (setupEnvVars.hasOwnProperty(j) && typeof setupEnvVars[j] === 'object' && setupEnvVars[j] !== null && !Array.isArray(setupEnvVars[j])) {
- Object.keys(setupEnvVars[j]).forEach(pushToRoot.bind(null, j));
- delete setupEnvVars[j];
- } else if (Array.isArray(setupEnvVars[j])) {
- setupEnvVars[j] = JSON.stringify(setupEnvVars[j]);
+ for (const [parentKey, value] of Object.entries(setupEnvVars)) {
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
+ Object.keys(value).forEach(key => pushToRoot(parentKey, key));
+ delete setupEnvVars[parentKey];
+ } else if (Array.isArray(value)) {
+ setupEnvVars[parentKey] = JSON.stringify(value);
}
}
diff --git a/src/analytics.js b/src/analytics.js
index 3b3a995b34..dbc601b689 100644
--- a/src/analytics.js
+++ b/src/analytics.js
@@ -128,13 +128,9 @@ Analytics.writeData = async function () {
uniqueIPCount = 0;
}
- if (Object.keys(counters).length > 0) {
- for (const key in counters) {
- if (counters.hasOwnProperty(key)) {
- dbQueue.push(db.sortedSetIncrBy(`analytics:${key}`, counters[key], today.getTime()));
- delete counters[key];
- }
- }
+ for (const [key, value] of Object.entries(counters)) {
+ dbQueue.push(db.sortedSetIncrBy(`analytics:${key}`, value, today.getTime()));
+ delete counters[key];
}
try {
await Promise.all(dbQueue);
diff --git a/src/database/mongo/helpers.js b/src/database/mongo/helpers.js
index 60f18381a5..4259771b2e 100644
--- a/src/database/mongo/helpers.js
+++ b/src/database/mongo/helpers.js
@@ -28,9 +28,9 @@ helpers.fieldToString = function (field) {
helpers.serializeData = function (data) {
const serialized = {};
- for (const field in data) {
- if (data.hasOwnProperty(field) && field !== '') {
- serialized[helpers.fieldToString(field)] = data[field];
+ for (const [field, value] of Object.entries(data)) {
+ if (field !== '') {
+ serialized[helpers.fieldToString(field)] = value;
}
}
return serialized;
@@ -38,10 +38,8 @@ helpers.serializeData = function (data) {
helpers.deserializeData = function (data) {
const deserialized = {};
- for (const field in data) {
- if (data.hasOwnProperty(field)) {
- deserialized[field.replace(/\uff0E/g, '.')] = data[field];
- }
+ for (const [field, value] of Object.entries(data)) {
+ deserialized[field.replace(/\uff0E/g, '.')] = value;
}
return deserialized;
};
diff --git a/src/flags.js b/src/flags.js
index 913e21543d..3fd707058d 100644
--- a/src/flags.js
+++ b/src/flags.js
@@ -135,13 +135,11 @@ Flags.getFlagIdsWithFilters = async function ({ filters, uid }) {
filters.page = filters.hasOwnProperty('page') ? Math.abs(parseInt(filters.page, 10) || 1) : 1;
filters.perPage = filters.hasOwnProperty('perPage') ? Math.abs(parseInt(filters.perPage, 10) || 20) : 20;
- for (const type in filters) {
- if (filters.hasOwnProperty(type)) {
- if (Flags._filters.hasOwnProperty(type)) {
- Flags._filters[type](sets, orSets, filters[type], uid);
- } else {
- winston.warn(`[flags/list] No flag filter type found: ${type}`);
- }
+ for (const type of Object.keys(filters)) {
+ if (Flags._filters.hasOwnProperty(type)) {
+ Flags._filters[type](sets, orSets, filters[type], uid);
+ } else {
+ winston.warn(`[flags/list] No flag filter type found: ${type}`);
}
}
sets = (sets.length || orSets.length) ? sets : ['flags:datetime']; // No filter default
@@ -586,29 +584,27 @@ Flags.update = async function (flagId, uid, changeset) {
// Retrieve existing flag data to compare for history-saving/reference purposes
const tasks = [];
- for (const prop in changeset) {
- if (changeset.hasOwnProperty(prop)) {
- if (current[prop] === changeset[prop]) {
+ for (const prop of Object.keys(changeset)) {
+ if (current[prop] === changeset[prop]) {
+ delete changeset[prop];
+ } else if (prop === 'state') {
+ if (!Flags._constants.states.includes(changeset[prop])) {
delete changeset[prop];
- } else if (prop === 'state') {
- if (!Flags._constants.states.includes(changeset[prop])) {
- delete changeset[prop];
- } else {
- tasks.push(db.sortedSetAdd(`flags:byState:${changeset[prop]}`, now, flagId));
- tasks.push(db.sortedSetRemove(`flags:byState:${current[prop]}`, flagId));
- if (changeset[prop] === 'resolved' || changeset[prop] === 'rejected') {
- tasks.push(notifications.rescind(`flag:${current.type}:${current.targetId}`));
- }
- }
- } else if (prop === 'assignee') {
- /* eslint-disable-next-line */
- if (!await isAssignable(parseInt(changeset[prop], 10))) {
- delete changeset[prop];
- } else {
- tasks.push(db.sortedSetAdd(`flags:byAssignee:${changeset[prop]}`, now, flagId));
- tasks.push(notifyAssignee(changeset[prop]));
+ } else {
+ tasks.push(db.sortedSetAdd(`flags:byState:${changeset[prop]}`, now, flagId));
+ tasks.push(db.sortedSetRemove(`flags:byState:${current[prop]}`, flagId));
+ if (changeset[prop] === 'resolved' || changeset[prop] === 'rejected') {
+ tasks.push(notifications.rescind(`flag:${current.type}:${current.targetId}`));
}
}
+ } else if (prop === 'assignee') {
+ /* eslint-disable-next-line */
+ if (!await isAssignable(parseInt(changeset[prop], 10))) {
+ delete changeset[prop];
+ } else {
+ tasks.push(db.sortedSetAdd(`flags:byAssignee:${changeset[prop]}`, now, flagId));
+ tasks.push(notifyAssignee(changeset[prop]));
+ }
}
}
diff --git a/src/install.js b/src/install.js
index ee12efc3d8..41afe5e27d 100644
--- a/src/install.js
+++ b/src/install.js
@@ -150,12 +150,7 @@ async function setupConfig() {
async function completeConfigSetup(config) {
// Add CI object
if (install.ciVals) {
- config.test_database = {};
- for (const prop in install.ciVals) {
- if (install.ciVals.hasOwnProperty(prop)) {
- config.test_database[prop] = install.ciVals[prop];
- }
- }
+ config.test_database = { ...install.ciVals };
}
// Add package_manager object if set
diff --git a/src/meta/settings.js b/src/meta/settings.js
index 4936f9348c..63e7fe47f2 100644
--- a/src/meta/settings.js
+++ b/src/meta/settings.js
@@ -47,12 +47,10 @@ Settings.set = async function (hash, values, quiet) {
({ plugin: hash, settings: values, quiet } = await plugins.hooks.fire('filter:settings.set', { plugin: hash, settings: values, quiet }));
const sortedListData = {};
- for (const key in values) {
- if (values.hasOwnProperty(key)) {
- if (Array.isArray(values[key]) && typeof values[key][0] !== 'string') {
- sortedListData[key] = values[key];
- delete values[key];
- }
+ for (const [key, value] of Object.entries(values)) {
+ if (Array.isArray(value) && typeof value[0] !== 'string') {
+ sortedListData[key] = value;
+ delete values[key];
}
}
const sortedLists = Object.keys(sortedListData);
diff --git a/src/middleware/headers.js b/src/middleware/headers.js
index 6d46e8f21a..e06082851c 100644
--- a/src/middleware/headers.js
+++ b/src/middleware/headers.js
@@ -64,9 +64,9 @@ module.exports = function (middleware) {
headers['X-Upstream-Hostname'] = os.hostname();
}
- for (const key in headers) {
- if (headers.hasOwnProperty(key) && headers[key]) {
- res.setHeader(key, headers[key]);
+ for (const [key, value] of Object.entries(headers)) {
+ if (value) {
+ res.setHeader(key, value);
}
}
diff --git a/src/plugins/index.js b/src/plugins/index.js
index e0fa4f6d45..c03870fa37 100644
--- a/src/plugins/index.js
+++ b/src/plugins/index.js
@@ -241,13 +241,7 @@ Plugins.normalise = async function (apiReturn) {
pluginMap[plugin.id].outdated = semver.gt(pluginMap[plugin.id].latest, pluginMap[plugin.id].version);
});
- const pluginArray = [];
-
- for (const key in pluginMap) {
- if (pluginMap.hasOwnProperty(key)) {
- pluginArray.push(pluginMap[key]);
- }
- }
+ const pluginArray = Object.values(pluginMap);
pluginArray.sort((a, b) => {
if (a.name > b.name) {
diff --git a/src/settings.js b/src/settings.js
index 937aacf307..a8346fcb87 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -4,23 +4,16 @@ const meta = require('./meta');
const pubsub = require('./pubsub');
function expandObjBy(obj1, obj2) {
- let key;
- let val1;
- let val2;
- let xorValIsArray;
let changed = false;
- for (key in obj2) {
- if (obj2.hasOwnProperty(key)) {
- val2 = obj2[key];
- val1 = obj1[key];
- xorValIsArray = Array.isArray(val1) === Array.isArray(val2);
- if (xorValIsArray || !obj1.hasOwnProperty(key) || typeof val2 !== typeof val1) {
- obj1[key] = val2;
+ for (const [key, val2] of Object.entries(obj2)) {
+ const val1 = obj1[key];
+ const xorIsArray = Array.isArray(val1) === Array.isArray(val2);
+ if (xorIsArray || !obj1.hasOwnProperty(key) || typeof val2 !== typeof val1) {
+ obj1[key] = val2;
+ changed = true;
+ } else if (typeof val2 === 'object' && !Array.isArray(val2)) {
+ if (expandObjBy(val1, val2)) {
changed = true;
- } else if (typeof val2 === 'object' && !Array.isArray(val2)) {
- if (expandObjBy(val1, val2)) {
- changed = true;
- }
}
}
}
@@ -28,16 +21,11 @@ function expandObjBy(obj1, obj2) {
}
function trim(obj1, obj2) {
- let key;
- let val1;
- for (key in obj1) {
- if (obj1.hasOwnProperty(key)) {
- val1 = obj1[key];
- if (!obj2.hasOwnProperty(key)) {
- delete obj1[key];
- } else if (typeof val1 === 'object' && !Array.isArray(val1)) {
- trim(val1, obj2[key]);
- }
+ for (const [key, val1] of Object.entries(obj1)) {
+ if (!obj2.hasOwnProperty(key)) {
+ delete obj1[key];
+ } else if (typeof val1 === 'object' && !Array.isArray(val1)) {
+ trim(val1, obj2[key]);
}
}
}
diff --git a/src/socket.io/admin/config.js b/src/socket.io/admin/config.js
index f22bcd0609..f08aa1b186 100644
--- a/src/socket.io/admin/config.js
+++ b/src/socket.io/admin/config.js
@@ -32,15 +32,10 @@ Config.setMultiple = async function (socket, data) {
}
});
await meta.configs.setMultiple(data);
- for (const field in data) {
- if (data.hasOwnProperty(field)) {
- const setting = {
- key: field,
- value: data[field],
- };
- plugins.hooks.fire('action:config.set', setting);
- logger.monitorConfig({ io: index.server }, setting);
- }
+ for (const [key, value] of Object.entries(data)) {
+ const setting = { key, value };
+ plugins.hooks.fire('action:config.set', setting);
+ logger.monitorConfig({ io: index.server }, setting);
}
if (Object.keys(changes).length) {
changes.type = 'config-change';
diff --git a/src/socket.io/admin/rooms.js b/src/socket.io/admin/rooms.js
index 7b688a35b9..4aafe9fbf6 100644
--- a/src/socket.io/admin/rooms.js
+++ b/src/socket.io/admin/rooms.js
@@ -64,22 +64,20 @@ SocketRooms.getAll = async function () {
category: 0,
};
- for (const instance in stats) {
- if (stats.hasOwnProperty(instance)) {
- totals.onlineGuestCount += stats[instance].onlineGuestCount;
- totals.onlineRegisteredCount += stats[instance].onlineRegisteredCount;
- totals.socketCount += stats[instance].socketCount;
- totals.users.categories += stats[instance].users.categories;
- totals.users.recent += stats[instance].users.recent;
- totals.users.unread += stats[instance].users.unread;
- totals.users.topics += stats[instance].users.topics;
- totals.users.category += stats[instance].users.category;
-
- stats[instance].topics.forEach((topic) => {
- totals.topics[topic.tid] = totals.topics[topic.tid] || { count: 0, tid: topic.tid };
- totals.topics[topic.tid].count += topic.count;
- });
- }
+ for (const instance of Object.values(stats)) {
+ totals.onlineGuestCount += instance.onlineGuestCount;
+ totals.onlineRegisteredCount += instance.onlineRegisteredCount;
+ totals.socketCount += instance.socketCount;
+ totals.users.categories += instance.users.categories;
+ totals.users.recent += instance.users.recent;
+ totals.users.unread += instance.users.unread;
+ totals.users.topics += instance.users.topics;
+ totals.users.category += instance.users.category;
+
+ instance.topics.forEach((topic) => {
+ totals.topics[topic.tid] = totals.topics[topic.tid] || { count: 0, tid: topic.tid };
+ totals.topics[topic.tid].count += topic.count;
+ });
}
let topTenTopics = [];
diff --git a/src/user/data.js b/src/user/data.js
index 2f94f24c2a..bccea4c373 100644
--- a/src/user/data.js
+++ b/src/user/data.js
@@ -285,10 +285,8 @@ module.exports = function (User) {
User.setUserFields = async function (uid, data) {
await db.setObject(`user:${uid}`, data);
- for (const field in data) {
- if (data.hasOwnProperty(field)) {
- plugins.hooks.fire('action:user.set', { uid: uid, field: field, value: data[field], type: 'set' });
- }
+ for (const [field, value] of Object.entries(data)) {
+ plugins.hooks.fire('action:user.set', { uid, field, value, type: 'set' });
}
};
diff --git a/src/user/jobs.js b/src/user/jobs.js
index ce5808ac26..8e069f0435 100644
--- a/src/user/jobs.js
+++ b/src/user/jobs.js
@@ -46,13 +46,11 @@ module.exports = function (User) {
User.stopJobs = function () {
let terminated = 0;
// Terminate any active cron jobs
- for (const jobId in jobs) {
- if (jobs.hasOwnProperty(jobId)) {
- winston.verbose(`[user/jobs] Terminating job (${jobId})`);
- jobs[jobId].stop();
- delete jobs[jobId];
- terminated += 1;
- }
+ for (const jobId of Object.keys(jobs)) {
+ winston.verbose(`[user/jobs] Terminating job (${jobId})`);
+ jobs[jobId].stop();
+ delete jobs[jobId];
+ terminated += 1;
}
if (terminated > 0) {
winston.verbose(`[user/jobs] ${terminated} jobs terminated`);
diff --git a/src/user/reset.js b/src/user/reset.js
index 1fa3ff9082..6942dcb02b 100644
--- a/src/user/reset.js
+++ b/src/user/reset.js
@@ -131,8 +131,8 @@ UserReset.cleanByUid = async function (uid) {
await batch.processSortedSet('reset:issueDate', async (tokens) => {
const results = await db.getObjectFields('reset:uid', tokens);
- for (const code in results) {
- if (results.hasOwnProperty(code) && parseInt(results[code], 10) === uid) {
+ for (const [code, result] of Object.entries(results)) {
+ if (parseInt(result, 10) === uid) {
tokensToClean.push(code);
}
}
diff --git a/src/webserver.js b/src/webserver.js
index 743fd6dda7..a75549420a 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -70,10 +70,8 @@ server.on('connection', (conn) => {
exports.destroy = function (callback) {
server.close(callback);
- for (const key in connections) {
- if (connections.hasOwnProperty(key)) {
- connections[key].destroy();
- }
+ for (const connection of Object.values(connections)) {
+ connection.destroy();
}
};
diff --git a/src/widgets/index.js b/src/widgets/index.js
index d169876b85..eac16373fc 100644
--- a/src/widgets/index.js
+++ b/src/widgets/index.js
@@ -196,13 +196,8 @@ widgets.reset = async function () {
};
widgets.resetTemplate = async function (template) {
- let toBeDrafted = [];
const area = await db.getObject(`widgets:${template}.tpl`);
- for (const location in area) {
- if (area.hasOwnProperty(location)) {
- toBeDrafted = toBeDrafted.concat(JSON.parse(area[location]));
- }
- }
+ const toBeDrafted = _.flatMap(Object.values(area), value => JSON.parse(value));
await db.delete(`widgets:${template}.tpl`);
let draftWidgets = await db.getObjectField('widgets:global', 'drafts');
draftWidgets = JSON.parse(draftWidgets).concat(toBeDrafted);
diff --git a/test/api.js b/test/api.js
index fb32d5f998..e3623412b0 100644
--- a/test/api.js
+++ b/test/api.js
@@ -420,11 +420,9 @@ describe('API', async () => {
return memo;
}, {});
- for (const header in expectedHeaders) {
- if (expectedHeaders.hasOwnProperty(header)) {
- assert(response.headers[header.toLowerCase()]);
- assert.strictEqual(response.headers[header.toLowerCase()], expectedHeaders[header]);
- }
+ for (const header of Object.keys(expectedHeaders)) {
+ assert(response.headers[header.toLowerCase()]);
+ assert.strictEqual(response.headers[header.toLowerCase()], expectedHeaders[header]);
}
return;
}
diff --git a/test/flags.js b/test/flags.js
index f2bf1e5cc0..0f9b48ac0c 100644
--- a/test/flags.js
+++ b/test/flags.js
@@ -55,11 +55,9 @@ describe('Flags', () => {
target_readable: 'Post 1',
};
assert(flagData);
- for (const key in compare) {
- if (compare.hasOwnProperty(key)) {
- assert.ok(flagData[key], `undefined key ${key}`);
- assert.equal(flagData[key], compare[key]);
- }
+ for (const key of Object.keys(compare)) {
+ assert.ok(flagData[key], `undefined key ${key}`);
+ assert.equal(flagData[key], compare[key]);
}
done();
@@ -131,11 +129,9 @@ describe('Flags', () => {
target_readable: 'Post 1',
};
assert(flagData);
- for (const key in compare) {
- if (compare.hasOwnProperty(key)) {
- assert.ok(flagData[key], `undefined key ${key}`);
- assert.equal(flagData[key], compare[key]);
- }
+ for (const key of Object.keys(compare)) {
+ assert.ok(flagData[key], `undefined key ${key}`);
+ assert.equal(flagData[key], compare[key]);
}
done();
@@ -483,11 +479,9 @@ describe('Flags', () => {
content: 'This is flaggable content',
};
- for (const key in compare) {
- if (compare.hasOwnProperty(key)) {
- assert.ok(data[key]);
- assert.equal(data[key], compare[key]);
- }
+ for (const key of Object.keys(compare)) {
+ assert.ok(data[key]);
+ assert.equal(data[key], compare[key]);
}
done();
@@ -503,11 +497,9 @@ describe('Flags', () => {
email: 'b@c.com',
};
- for (const key in compare) {
- if (compare.hasOwnProperty(key)) {
- assert.ok(data[key]);
- assert.equal(data[key], compare[key]);
- }
+ for (const key of Object.keys(compare)) {
+ assert.ok(data[key]);
+ assert.equal(data[key], compare[key]);
}
done();
@@ -644,11 +636,9 @@ describe('Flags', () => {
};
const data = notes[1];
- for (const key in compare) {
- if (compare.hasOwnProperty(key)) {
- assert.ok(data[key]);
- assert.strictEqual(data[key], compare[key]);
- }
+ for (const key of Object.keys(compare)) {
+ assert.ok(data[key]);
+ assert.strictEqual(data[key], compare[key]);
}
done();