Repository navigation
Accept a $ref in place of a whole allOf/anyOf/oneOf/prefixItems list instead of a TypeError - #888
Draft
claude[bot] wants to merge 1 commit into
Draft
claude[bot] wants to merge 1 commit into
claude[bot] wants to merge 1 commit into
Conversation
…ems` list, and reject one that leads to no list of schemas by position, instead of a TypeError
Before dereferencing, `traverse` assumed a list keyword's value is an array and died with
`TypeError: arr.forEach is not a function` on the `{$ref}` object standing in for it. The walk
now visits such a value as a schema, and the resolver judges what it led to once dereferencing
is done: an array of schemas compiles (an intersection, a union, a tuple); anything else --
a file holding one schema, an `enum`'s values, `true`, `null` -- is reported with the keyword,
its position and the `$ref`. The judging walk runs only for documents the prenormalizer marked
as holding such a value, so schemas without one pay nothing for it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Output change: none for any existing schema (no snapshot entry moves; three are added for the new cases). Invalid schemas that master compiled around are now rejected: see "Also rejected" below. Draft until its check passes.
A
$refstanding in for a wholeallOf,anyOf,oneOforprefixItemslist --allOf: {$ref: "mixins.json"}, or{$ref: "#/definitions/base/allOf"}-- crashed before anything was dereferenced withTypeError: arr.forEach is not a function(the walk insrc/utils.tsassumed an array). Now it compiles when the$refleads to a list of schemas, and is rejected with the keyword, its position and the$refwhen it leads to anything else.Before / after, for
record: {type: "object", allOf: {$ref: "SchemaLists/ObjectSchemas.json"}}(a file holding two object schemas) andvalue: {anyOf: {$ref: "SchemaLists/lists.json#/scalars"}}:When the
$refleads to something that is no list of schemas:A
$refin a list position leading to a string,nullor an empty file was already reported (#877); that report is unchanged and still comes first. Atitlebeside the stand-in is dropped (as beside any$ref); any other sibling keyword is rejected as above.Also rejected, where master compiled around an invalid schema: a
null,false,0or""written in place of a list (allOf: nullcompiled to the object type;prefixItems: nulltounknown[]) now gets the same "must be a list of schemas: found …" message; and a bad stand-in under OpenAPIcomponents/schemas, which master never walked and printed as a literal type (export type Pet = "x" & "y"), gets the message too. Incidentally fixed: a property namedallOfunder a keyword this tool does not know (contains,propertyNames) crashed master with the same TypeError and now compiles.How
traversevisits a non-array value under a list keyword as a schema, so the{$ref}reaches the ref-parser like any other.rejectNonSchemaLists): a walk over the schema positions from the root, throwing for a list keyword whose value is not an array, or is an array a$refled to whose members are not all schemas. A list written in place keeps today's member-by-member judgement, so this does not overlap Reject a$refin place of a schema that leads to an array (anenum, arequiredlist, an array document) instead of emitting a tuple #886.compile()on the Azure template), so it runs only for documents the prenormalizer marked as holding a$refor a non-schema at a list keyword (ListsToJudge), and for a file that is itself a list of schemas. Real schemas have properties namedallOf(Azure'sMicrosoft.Securitydoes), so a schema object without a$refis not a mark. Master vs this head, 7 alternating runs, min/median ms: Azure 5209/5263 vs 5154/5256; FHIR 537/551 vs 525/552.Tests
Seven e2e cases,
test/e2e/refInPlaceOfSchemaList.*.ts: external file (a whole-file array and pointers into a file), in-document pointers, a stand-in inside a file that is itself a list, and four rejections (anenum's values, one schema, a sibling keyword,nullin place). Six fail on master with the TypeError;inArrayDocumentalready compiled there and guards the gate.CI=true bun run test: 690 pass, 0 fail (master 5caacfc: 686).bun run corpusandbun run conformance: same as master (26 × 3 compile and type-check; all 2404 groups match the baseline).$ref-target probe differs from master in exactly the whole-list rowspos.wholeAllOf.str(TypeError → the Report a$refwhose target is not a schema (empty file,null/string/number document, plain-text YAML) instead of crashing #877 report) andarr.wholeAllOf.schemasDoc(TypeError →string & number); the array probe in its fourallOf.whole.*/anyOf.whole.*rows only.json2tson a schema with the stand-in prints the type; on a bad one prints the message above.Not changed: a list written in place whose members are no schemas (
allOf: [1, 2], a member$refonto anenum; #886 covers the latter), and a schema object written in place of a list (allOf: {type: "number"}), which still reaches the parser'smembers.mapTypeError as on master.git merge-treeagainst every open draft, #879 to #887: all clean.Changelog
$refstanding in for a wholeallOf/anyOf/oneOf/prefixItemslist compiles, or is rejected by position, instead of throwingTypeError: arr.forEach is not a function.