Skip to content

Conversation

@Adityakumar37
Copy link

@jdesrosiers

What’s included

New normalization handlers

  • items-draft04.js — implements pre-2020 tuple validation semantics

  • additionalItems-draft04.js — implements legacy handling for items beyond the tuple
    Correct keyword registration

  • https://json-schema.org/keyword/draft-04/items

  • https://json-schema.org/keyword/draft-04/additionalItems

  • New test coverage

    • Added draft-2019-09 tests using compatibility: "<=2019"
    • Tests are mapped from existing prefixItems / items cases where behavior differs
      No behavior changes for draft-2020-12 or newer drafts

Implementation details

  • items-draft04 mirrors the behavior of prefixItems:

    • Applies tuple validation by index
    • Calls evaluateSchema per array position
    • Always returns a NormalizedOutput[] (no null values)
  • additionalItems-draft04 mirrors the draft-2020-12 items handler:

    • Only applies when items is an array (tuple form)
    • Starts validating from items.length
    • Correctly handles true, false, and schema values
  • Both handlers are implemented as simple applicators.


Test status

All existing tests pass
New draft-2019-09 tests pass
Total: 200 / 200 tests passing


Notes

This implementation follows the guidance discussed in the issue:

  • Explicit handlers for legacy semantics
  • Test mapping approach instead of duplicating cases
  • No localization changes required

Happy to adjust anything if you’d like a different structure or naming.

Copy link
Collaborator

@jdesrosiers jdesrosiers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're trying to do too much. The changes to these keywords from 2019-09 to 2020-12 were almost entirely renaming. You just need to make copies of the existing items and prefixItems handlers and make minor edits. If your handlers look significantly different than the 2020-12 versions of these keywords, you're on the wrong track.

One test isn't close to enough. Like, I said before, go through the existing tests, translate them to 2019-09, and remove any duplicates. There are six tests that use the prefixItems keyword not counting unevaluatedItems tests. I expect at least that many new tests.

ProTip: Always make an effort to match the code style used in the repo you're contributing to. Install the ESLint plugin in your editor to get code style hints as you work.

ProTip: Always run the test, lint, and type-check scripts before submitting a PR (see "Contributing" in the README). The automation is there to double check us because we all forget things sometimes, but it looks unprofessional when you submit something that isn't ready.

Comment on lines +32 to +45
let index = 0;
while (true) {
const itemNode = Instance.step(String(index), instance);
if (!itemNode) break;

outputs.push(
evaluateSchema(
/** @type {string} */ (items),
itemNode,
context
)
);
index++;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a for..of loop using Instance.iter.

Comment on lines +37 to +43
outputs.push(
evaluateSchema(
/** @type {string} */ (items),
itemNode,
context
)
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no good reason for this function can to span more than one line. While there are some exceptions, please avoid multi-line function calls in this repo.

*/

/** @type NormalizationHandler */
const itemsDraft04 = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick with the naming convention used in all the other normalization handlers.

Suggested change
const itemsDraft04 = {
const itemsDraft04NormalizationHandler = {

Comment on lines +18 to +64
// If items is not a tuple, additionalItems is ignored
const items =
/** @type {{ schema?: { items?: unknown } }} */
(context).schema?.items;


if (!Array.isArray(items)) {
return outputs;
}

const startIndex = items.length;

// additionalItems: true → always valid
if (additionalItems === true) {
return outputs;
}

let index = startIndex;

while (true) {
const itemNode = Instance.step(String(index), instance);
if (!itemNode) break;

// additionalItems: false → validate against false schema
if (additionalItems === false) {
outputs.push(
evaluateSchema(
/** @type {string} */ ("false"),
itemNode,
context
)
);


} else {
// additionalItems is a schema
outputs.push(
evaluateSchema(
/** @type {string} */ (additionalItems),
itemNode,
context
)
);
}

index++;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current items keyword is literally no more than a rename of additionalItems. This handler should look a lot more like the current items normalization handler.

Comment on lines +6 to +27
{
"description": "items (tuple validation) - draft 2019-09",
"compatibility": "<=2019",
"schema": {
"type": "array",
"items": [
{ "type": "number" }
]
},
"instance": ["foo"],
"errors": [
{
"messageId": "type-message",
"messageParams": {
"expectedTypes": { "or": ["number"] }
},
"instanceLocation": "#/0",
"schemaLocations": ["#/items/0/type"]
}
]
}
,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be indented properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants