fix: address Copilot review round 5 — union member faithfulness, partial discriminators, const-null siblings
- rootUnion: union members get the same flattenability test as allOf members,
so a branch whose nested `allOf: [false]` makes it unsatisfiable is no
longer offered as a callable alternative with that constraint erased.
- selectBranchIndex: weigh only the pinned constants the caller SUPPLIED. One
it did not supply is a value this identification exists to seed, so
requiring it meant a deep link naming `kind` alone matched no branch
whenever the branches also pinned, say, a `version`. A supplied constant
that disagrees is still evidence against.
- admitsNull: `const: null` is conjunctive with its siblings, not an
override — `{ type: "string", const: null }` and
`{ const: null, anyOf: [...] }` reject every value, so the claim is made
only where the type and a sibling union leave null on the table.
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
7e4af5ed34
commit
f556f8831b
1 changed files with 103 additions and 14 deletions
|
|
@ -430,6 +430,11 @@ export function resolveRootUnion<T extends RootUnionSchema>(
|
|||
(branch) =>
|
||||
branch === null ||
|
||||
!isOfferable(branch) ||
|
||||
// The same faithfulness test the `allOf` fold applies: a member
|
||||
// carrying a constraint the merge does not copy — a nested `allOf`, a
|
||||
// `not`, a `$ref` — would have it erased along with the union keyword,
|
||||
// which can present an unsatisfiable branch as a callable one.
|
||||
!isFlattenable(branch) ||
|
||||
conflictsWithBase(base, branch),
|
||||
)
|
||||
) {
|
||||
|
|
@ -476,9 +481,14 @@ export function selectBranchIndex<T extends RootUnionSchema>(
|
|||
] as const,
|
||||
)
|
||||
.filter(([, constValue]) => constValue !== undefined);
|
||||
// Only the pinned names the caller actually supplied are evidence. A
|
||||
// constant it did not supply is one this identification exists to *seed* —
|
||||
// requiring it would mean a deep link naming `kind` alone matched no branch
|
||||
// whenever the branches also pin, say, a `version`.
|
||||
const supplied = pinned.filter(([name]) => values[name] !== undefined);
|
||||
if (
|
||||
pinned.length > 0 &&
|
||||
pinned.every(([name, constValue]) => values[name] === constValue)
|
||||
supplied.length > 0 &&
|
||||
supplied.every(([name, constValue]) => values[name] === constValue)
|
||||
) {
|
||||
matches.push(index);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue