-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Breaking: Ajv to v8.5.0, added ajv-draft-04 (fixes #13888) #13911
Conversation
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
2 similar comments
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
Hi @epoberezkin!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the message to match this format, as we use it to generate changelogs and automate releases.
Read more about contributing to ESLint here |
@epoberezkin thanks for the PR! I marked this PR as a draft because of the rc version, and as "breaking" until we figure out whether or not it's a breaking change. |
How was this working at all, does Ajv in non-strict mode assume it's an "object"/"array" type if there is "properties"/"items"?
Should we then turn it off explicitly, to retain the previous behavior (and thus maybe avoid breaking plugins)?
Is there an overview of the differences between versions, so we could maybe try to estimate the impact on plugins? In particular, what was valid by draft-04, but would be invalid or ignored or maybe have different semantics with draft-07. |
No, it allows ANY data type, "property"/"items" only applies any restriction IF it is "object"/"array" - this is how JSON Schema specifies it. So if the data were an object/array it would validate it as expected, otherwise it would just allow it (incorrectly). It is a common mistake, that's why I made strict mode default.
We could, but:
I believe we should identify top-X (say, 5) most used plugins and update them too (if I am correct that they depend on eslint validation code), and release it as a minor version change - some small share of users will be affected, they'll have to lock the version, we can then fix any reported issues. To make any such change easier in the future it might be good to split validation code to the separate package, something like schema-utils in webpack, in which case eslint and plugins would depend on different versions of validation utils, and can be upgraded independently. Or we could take a cautious route and release it as a major version, but then users will be carrying 2 ajv versions for longer (and they would still not be able to migrate eslint until plugins migrate). I think npm have finally fixed that old issue when two different sub-dependency versions were breaking installation, so it's not such a big deal too. Your call. |
Thanks! I think I understand now.
Plugin rules usually define The schema itself isn't validated "in production". Only |
That’s what I thought. So it means that the plugins that have “id” (it’s now $id) or “exclusiveMaximum/Minimum” (it was boolean in draft-04, number now) would throw exception. I think both should be quite rare. The possible solution could be to add some code that would migrate plug-in schemas on the fly by replacing these two things (or we could just plug in json-schema-migrate) - what do you think? Feels wrong though, probably better just upgrade top X plugins.
Exactly. So if you want to do minor version upgrade, we could avoid adding “type”, so that users validation don’t fail even if they have incorrect config. |
There are two scenarios where schemas can be validated:
For end users, we already have validateSchema: false (which disables the most severe errors?). I believe the intention was always to not validate schemas in runtime. Enabling additional validations now will break end users that have valid configurations, so they'll have to wait for plugins to fix rule schemas and release new versions, although those plugins already work perfectly well for them. For example, linting of eslint/eslint repo itself as an end-user would be broken until I think we should turn off all validations of schemas in runtime, even for a major ESLint version, because it looks like it could cause a big breakage without clear benefits. As for the development, it certainly makes sense to consider enabling additional validations in (I'm aware that the incompatibility of schema versions is probably a bigger problem, just wanted to figure out how to handle validation changes first) |
Also, it seems that For example, an invalid const Ajv = require("ajv").default;
const ajv = new Ajv({
validateSchema: false,
strict: false,
strictTypes: false,
});
const schema = {
type: "arrayy", // typo
};
ajv.compile(schema); // Error: type must be JSONType or JSONType[]: arrayy |
Yes, in general the approach was to be stricter by default (with many restrictions flipping from opt-in to opt-out), and treating possible typos as errors - it's been the source of many user side bugs reported as Ajv bugs. The logic is that JSON Schema is a language with constrained vocabulary and for the absolute majority of users the expected behaviour is to fail on unknown words (rather than ignore them as the spec suggests) - same as programming languages behave. This blog post covers the scope of changes and the motivation: https://www.poberezkin.com/posts/2020-11-14-ajv-time-to-migrate-to-version-7.html |
This seem complicated enough that an RFC would seem to be in order to work out the details. Thoughts? |
There was an issue with I'm not sure if this has been fixed in npm < 7, but there's probably nothing we can do about it. Hopefully, it won't be happening since |
I’ve made the PR for table to upgrade to Ajv v7 - it doesn’t have to be a major version change there. |
Happy New year all! Ajv v7 is the main version since mid-December; no complaints about version conflicts so far. There's been a few minor bugs reported and fixed, mostly around new standalone code generation, - all good otherwise. Table was just released yesterday with ajv v7 in the same major version - thanks @gajus. Not sure how it is best to move it forward - how would you decide between the options here: #13911 (comment) ? There will be another major version release in the next 3-4 months, but it should be "mostly" backwards compatible. |
This is also a breaking change for end users. The new version of We could add try-catch around |
|
I have concerns about We can declare For example, I made a test project with the following dependencies (it's using ESLint from this branch): "dependencies": {
"ajv": "^6.10.0",
"eslint": "github:epoberezkin/eslint#epoberezkin/ajv-v7"
} Running ESLint failes, with this error:
because
so Since |
just moved it back to v8.0.0 project, as it seems a breaking change. :) |
I will see how to change it… Possibly in this case it should be a direct dependency indeed. |
Actually, try/catch may not be a good idea. It would be okay to just skip the validation, but it will also skip setting default values, so the rule might silently change behavior. |
@mdjermanovic The example in the comment with The only difference I can think of is the change from strictDefaults to strictKeywords. If it makes it simpler (e.g. could be released as a non-breaking change), I could add this option (strictDefaults) back? Let me know. Looking at ajv-draft-04 anyway. |
It's enabled in That said, we can assume that most plugins use |
We're adding only issues to the project, to avoid duplicates. I removed this PR from the project now (the related issue #13888 is already there). |
strict: "log", | ||
strictTuples: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strict: "log", | |
strictTuples: false, | |
strict: false, |
If we set strict: false
, then we don't need to explicitly set strictTuples: false
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct
const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema; | ||
const formattedValue = JSON.stringify(error.data); | ||
|
||
return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`; | ||
} | ||
|
||
const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath; | ||
const field = error.instancePath[0] === "." ? error.instancePath.slice(1) : error.instancePath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const field = error.instancePath[0] === "." ? error.instancePath.slice(1) : error.instancePath; | |
const field = error.instancePath[0] === "/" ? error.instancePath.slice(1) : error.instancePath; |
I guess the error.dataPath[0] === "."
condition doesn't make sense with the new path format, and that we would want to remove root /
?
@epoberezkin any news on this? I think that's the only major issue. Aside from that, this looks good assuming we'll set |
I noticed that
The problem is probably here: eslint/lib/rule-tester/rule-tester.js Line 557 in 278813a
We're validating the rule's schema for each test case (that seems unnecessary, but may take some time to analyze and fix). If the rule uses ESLint's shorthand array schema, then Ajv 6 used to cache compiled schemas by content, but Ajv 8 caches by reference? If that's the case, we can move |
@epoberezkin I'm closing this PR as described in #13888 (comment), Thanks for the PR, and thanks for all the work on Ajv! |
@mdjermanovic sorry, missed these comments...
That is correct. There is a reasonable argument for that, but it turns out to be a problem for quite a few users - e.g. ajv-validator/ajv#1413 It indeed highlights incorrect cases when the schema is compiled multiple times, so I don't think it should be reversed...
Are there notes? It would be great to formulate the changes needed that would make transition to the next major version easier - v6 is stable indeed, but there will be other dependencies going out of date, so at some point the migration would have to happen... |
See https://github.com/eslint/tsc-meetings for notes and transcripts of all TSC meetings. |
@nzakas - thank you - I will update the problem with peer dependency, and let's review for eslint v9. By then the main reason for migration could be security warnings in v6 dev dependencies (that of course can be addressed by additional v6 release:). Users do migrate to v8 - I estimate that about 20% of users migrated (based on the download count of ajv-formats that's only needed for v8, accounting for the fact that some know dependencies do not need ajv-formats). |
Prerequisites checklist
What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[ ] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[x] Other, please explain: Update Ajv version to v7
What changes did you make? (Give an overview)
additionalItems
keywords (it is possible though that the intention was to have only one item allowed in these schemas, in which case schemas have to be changed fromitems: {...}
toitems: [{...}], additionalItems: false
type
keywords (in the second commit).strictDefaults
option (strict mode is on by default now) and other deprecated optionIs there anything you'd like reviewers to focus on?
cc @nzakas