-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
require-atomic-updates false positive #11899
Comments
Thank you for your report. I think this is intentional behavior because that |
Ok, but that's pretty aggressive assumption, as in many cases that can be an intentional well-thought construct In place where it reported for me, it's totally intentional and there's no way to write it differently (aside of dropping async/await), due to that I needed to turn off this rule globally. Still I'd love it to report for me cases as |
I would say that if nothing else, error message is pretty misleading.
That is simply not true, because Also, it's not following the rule definition which clearly states that following must be true:
|
Here's a pretty vanilla Express middleware that triggers this problem, as you might see in any app that does virtual hosting based on the URL, if you're looking for a concrete example: export function populateAccount() {
return function(req, res, next) {
Promise.resolve()
.then(async () => {
const host = req.headers['host'];
req.account = await getAccount(host);
})
.then(() => next(), next);
};
}
/*eslint require-atomic-updates: error */ |
see: eslint/eslint#11899 didn't figure out what happened
@mysticatea could the following POC also be related to the issue? function dataGetter() {
return {};
}
function anotherDataGetter() {
return {};
}
async function main() {
let get_data = await dataGetter();
const get_another_data = await anotherDataGetter(get_data.id);
(() => {
get_data[get_another_data.foo] = 1;
});
// Error Here: Possible race condition: `get_data` might be reassigned based on an outdated value of `get_data`.
get_data = {
...get_data,
...get_another_data,
};
}
main(); |
There is a workaround: // Given:
const obj = {foo: 'bar'};
// Instead of:
obj.prop = 'whatever';
// Do:
Object.assign(obj, {prop: 'whatever'}); This way the rule is not triggered (as expected). |
It is my understanding that Even if you awaited a promise that did 100 things to the same object that To assume that the promise does this on a "might", and invoke an eslint error, seems like an attempt to oversimplify async programming to me. If eslint isn't sophisticated enough to point out BOTH lines of code, that are "racing" to overwrite something (race condition), then it probably needs to keep its might-suspicions to itself (until it gains that sophistication). Don't block my build on a "might". It takes two to race. If I've got a race condition, show me both lines of code that are racing each other. Here's my example: |
@Lonniebiz what if the other line of code is located somewhere in a 3rd-party lib? Looking through entire node_modules to find that line does no sound as a good idea. |
This is a real issue (I'm hitting all the examples pasted above), and one that was not mentioned in the migration guide for ESLint 6.0.0. I can appreciate theories on how these cases are at least on paper unsafe, but that kind of behavior should then at least exist behind a flag. Right now, we're losing a valuable feature because the only way to deal with this situation is to turn the rule off. |
I think that might be a non-issue, I don't think you should be setting up your eslint to run through entire node_modules. This would be outside your context/source code and it would be up to the original maintainer of that said library to fix those issues (or yourself without an appropriate PR). |
We have to disable this rule in our company due to many false positives. In paper rule is great and should prevent many bugs, but feels like it's not quite ready yet. |
I'm not even sure you should even warn when side-effects are obvious and likely intentional. |
@mysticatea May I ask what the plan is? Will the behavior of this rule be reverted, or otherwise? Current behavior is keeping people from upgrading to ESLint 6. It would be good to know what the official stance is. If it's "won't fix", then we'll just all turn off this rule and move on with our lives. If it's "will fix in 6.0.2", then we know we can wait for a bit, and it will resolve itself. |
Here is a perfectly valid koa snippet that is faulted by this rule: router.post('/webhook', async (ctx) => {
await processRequest(ctx.request.body);
ctx.body = 'OK';
}); |
I would like to speak up in support of the rule. Mutation and async programming is a source of many errors in the codebases I had worked on and this rule has been very beneficial to bring them to light. I would also like to speak up in favor of keeping it in recommended ruleset, to help expose these difficult issues for less experienced contributors. The false positives are, of course, a major issue, as it leads to the rule being disabled or ignored. Perhaps we can introduce more ways to explicitly mark up objects that we are allowed to mutate? This can already be done somewhat using renaming a variable in one’s scope, but it looks like a hack, since at the end of the day the object maintains identity: app.get('/', async (ctx) => {
const myCtx = ctx;
await process(myCtx.request.body);
myCtx.body = 'OK';
}); An explicit comment could indicate the author’s intent and judgement. At this stage it is almost identical to app.get('/', async (ctx) => {
// eslint-we-own: ctx
await process(ctx.request.body);
ctx.body = 'OK';
}); For common patterns like the Koa context, it would be convenient to whitelist the variables we are allowed to mutate by name in the configuration: {
"require-atomic-updates": ["error", {
"skip-variables": ["ctx"]
}]
} |
@denis-sokolov There are too many situations already, when people are treated as idiots ("for their own safety", of course). Do not create another one, please. |
This rule seems prone to false positives, and thus it may be more misleading than useful (for now). See: eslint/eslint#11899
due to false positives eslint/eslint#11899
It is very broken, per eslint/eslint#11899.
It was waay too buggy: eslint/eslint#11899
I think we should add an option to ignore assignments to properties. That is, to report only assignments to variables if this option is enabled. |
Agree. I’m not sure the current default actually makes sense but an option is an easy way to address it. |
* support async benchmark tests * Add benchmarks for sync and async list fields * Support returning async iterables from resolver functions Support returning async iterables from resolver functions * add benchmark tests for async iterable list fields * Add @defer directive to specified directives # Conflicts: # src/index.d.ts # src/type/directives.d.ts # src/type/directives.ts # src/type/index.js * Implement support for @defer directive * Add @stream directive to specified directives # Conflicts: # src/index.d.ts # src/type/directives.d.ts # src/type/directives.ts # src/type/index.js * Implement support for @stream directive # Conflicts: # src/execution/execute.ts # src/validation/index.d.ts # src/validation/index.ts * add defer/stream support for subscriptions (#7) # Conflicts: # src/subscription/subscribe.ts * Return underlying AsyncIterators when execute result is returned (graphql#2843) # Conflicts: # src/execution/execute.ts * fix(race): concurrent next calls with defer/stream (graphql#2975) * fix(race): concurrent next calls * refactor test * use invariant * disable eslint error * fix * Update executor * Disable require-atomic-updates eslint/eslint#11899 * Fix merege * Further merge fixes * run prettier * add changeset * Update defer/stream to return AsyncGenerator ...instead of AsyncIterable, to match v16 * add optional arguments to disable incremental delivery * Subscription root field by spec cannot be inside deferred fragment * Use spread initializers * fix code coverage Co-authored-by: Rob Richard <[email protected]> Co-authored-by: Liliana Matos <[email protected]>
* feat: add `allowProperties` option to require-atomic-updates Fixes #11899 * fix description of the option * Update docs/rules/require-atomic-updates.md Co-authored-by: Nicholas C. Zakas <[email protected]> * Update docs/rules/require-atomic-updates.md Co-authored-by: Nicholas C. Zakas <[email protected]> * Update docs/rules/require-atomic-updates.md Co-authored-by: Nicholas C. Zakas <[email protected]> * Update docs/rules/require-atomic-updates.md Co-authored-by: Nicholas C. Zakas <[email protected]> * Update docs * Update docs Co-authored-by: Nicholas C. Zakas <[email protected]> Co-authored-by: Nicholas C. Zakas <[email protected]>
Tell us about your environment
What parser (default, Babel-ESLint, etc.) are you using?
Default
Please show your full configuration:
https://github.com/medikoo/eslint-config-medikoo/blob/master/index.js
What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.
What did you expect to happen?
No error reported
What actually happened? Please include the actual, raw output from ESLint.
Error reported:
Are you willing to submit a pull request to fix this bug?
Not at this point
The text was updated successfully, but these errors were encountered: