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
|
|
@ -368,17 +368,15 @@ function collapsed<T extends NullableUnionSchema>(
|
|||
* an optimistic guess, and a schema this module cannot read renders through the
|
||||
* JSON editor with its constraints intact.
|
||||
*/
|
||||
/** Whether an absent or null-naming `type` leaves null on the table. */
|
||||
function typeAdmitsNull(type: string | string[] | undefined): boolean {
|
||||
return type === undefined || typeNamesNull(type);
|
||||
}
|
||||
|
||||
export function admitsNull(schema: NullableUnionSchema): boolean {
|
||||
if (nullExcludedBySiblings(schema)) {
|
||||
return false;
|
||||
}
|
||||
// `const: null` admits null and nothing else, whatever the schema says (or
|
||||
// omits) about `type`. Without this a required field pinned to null is seeded
|
||||
// with the only value it accepts and then reported as missing, leaving submit
|
||||
// permanently disabled on a form the user cannot change (#2123).
|
||||
if (schema.const === null) {
|
||||
return true;
|
||||
}
|
||||
// Applicators this module does not evaluate. `not: { type: "null" }` rules
|
||||
// null out; `allOf` can add a member that does; and `oneOf` requires
|
||||
// **exactly one** branch to match, so a null branch does not by itself mean
|
||||
|
|
@ -388,6 +386,20 @@ export function admitsNull(schema: NullableUnionSchema): boolean {
|
|||
if (hasOpaqueApplicator(schema)) {
|
||||
return false;
|
||||
}
|
||||
// `const: null` admits null and nothing else — the case a required field
|
||||
// pinned to null needs, or it is seeded with the only value it accepts and
|
||||
// then reported missing, leaving submit permanently disabled on a field the
|
||||
// user cannot change (#2123).
|
||||
//
|
||||
// Claimed only where the siblings agree, since `const` is conjunctive with
|
||||
// them rather than an override: `{ type: "string", const: null }` and
|
||||
// `{ const: null, anyOf: [...] }` reject every value, and saying otherwise
|
||||
// would let the gate accept a `null` the schema forbids. The opaque
|
||||
// applicators (`not`, `allOf`, `oneOf`) are already refused above.
|
||||
if (schema.const === null) {
|
||||
return schema.anyOf === undefined && typeAdmitsNull(schema.type);
|
||||
}
|
||||
|
||||
if (schema.nullable === true) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue