Skip to content

Validate the value written to the extensible key in its accessor - #80

Merged
samuelduchesne merged 1 commit into
mainfrom
fix-extensible-accessor-validation
Oct 21, 2026
Merged

samuelduchesne merged 1 commit into
mainfrom
fix-extensible-accessor-validation

Conversation

@samuelduchesne

Copy link
Copy Markdown
Contributor

Summary

The accessor for an object's extensible key (such as vertices or branches) stored any value it was given. Three consequences were observed:

  1. A string was written out as a malformed list.
  2. A repeat with an unknown field kept that field in epJSON output, where it is not a schema property, and lost it in IDF output.
  3. [null] was stored before the document's reference update failed on it, leaving the reference graph without the list's edges.

The accessor now throws a TypeError before writing unless the value is null, undefined, or an array of plain objects whose keys are all fields of the repeat. null and undefined still clear the list.

Changes

  • packages/core/src/shape.ts: the extensible key's accessor validates its value through extensibleValueProblem(value, groupFields), which is exported so that other writers can apply the same check. Property assignment and set both pass through it.
  • packages/core/tests/document.test.ts: set and property assignment reject four invalid values ('x', [null], [[1]], [{ bogus: 1 }]) and leave the object unchanged; null and undefined clear the list.
  • packages/core/tests/regressions.test.ts: [null] on a BranchList is rejected and the reference to the branch survives.
  • packages/core/tests/validate.test.ts: the test that builds a malformed object for validateObject now writes to the object's data directly, as a reader does, because set refuses the value.
  • CHANGELOG.md: entry under Unreleased, Changed.

Behaviour change

This is a behaviour change for set and property assignment, recorded under Changed. Values given at construction (by a reader, add or clone) do not pass through the accessor and are not checked here, because a reader must accept whatever a file holds; validateObject continues to report them. The Python library's single assignment already rejects the same values, so this aligns the two languages.

Stack

This is the base of a two-pull-request stack. The pull request for IdfObject.update (feature 015, idfkit/idfkit#235) builds on it: update refuses the same values during its examination, so that a malformed list cannot be written after earlier entries of the group.

Verification

  • npm run typecheck: passes.
  • npm run format:check: passes.
  • npm test: 907 of 907 tests pass across 35 files.
  • The two new tests fail on main without the change to shape.ts.

The accessor for the extensible key (such as vertices) stored any value.
A string was written out as a malformed list, a repeat with an unknown
field kept it in epJSON output and lost it in IDF output, and [null] was
stored before the reference update failed on it, leaving the reference
graph without the list's edges.

The accessor now throws a TypeError before writing unless the value is
null, undefined (both still clear the list), or an array of plain objects
whose keys are all fields of the repeat. Property assignment and set share
the check, and extensibleValueProblem exports it so that other writers can
ask the same question. Values given at construction do not pass through the
accessor; validateObject still reports them, and its test now builds the
malformed object the way a reader would.

The Python library's single assignment already rejects the same values.
@samuelduchesne
samuelduchesne requested a review from a team as a code owner October 21, 2026 15:25
@samuelduchesne
samuelduchesne added this pull request to stack #82 October 21, 2026 16:10
@samuelduchesne
samuelduchesne merged commit 797498e into main Oct 21, 2026
39 checks passed
samuelduchesne added a commit that referenced this pull request Oct 21, 2026
The level adds the five update cases, the update operation and the post-operation-epjson assertion, and removes the six typescript divergence entries for those cases, which #80 and #81 close. conformance.ts and the EPW sentinel table are regenerated from the new tag; only their recorded level changes. The publication gate's attested level moves with the pin, with the evidence taken at the tag in both languages.
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.

1 participant