From 70181d50b6c004582fda509d47babf9cd0c2b522 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 26 Aug 2026 09:53:24 +0000 Subject: [PATCH] test(app-shell): spell the `__proto__` instrument fixture as a computed key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `fields: { __proto__: … }` in an object literal is the Annex B.3.1 prototype setter: it sets `[[Prototype]]` and creates no own key, so the instrument assertion was parsing `fields: {}` and asserting an empty field map is legal. It would have stayed green if `ObjectSchema` began refusing the name. Spell the fixture `['__proto__']` so it carries the key it claims to, and pin the literal-versus-computed distinction as an executable control rather than a comment, mirroring `MetadataFieldsPage.fieldsMapKeying.test.tsx`. The two request-byte assertions are honest already — they read `JSON.parse` output, where `__proto__` is an own property — and keep their assertions; one comment records why that provenance is what makes them honest. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q --- .changeset/proto-instrument-fixture.md | 9 +++++++++ ...MetadataService.objectPayloadFieldsMap.test.ts | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .changeset/proto-instrument-fixture.md diff --git a/.changeset/proto-instrument-fixture.md b/.changeset/proto-instrument-fixture.md new file mode 100644 index 000000000..a3e358f90 --- /dev/null +++ b/.changeset/proto-instrument-fixture.md @@ -0,0 +1,9 @@ +--- +--- + +Test-only (objectui#6524): the `__proto__` instrument fixture in +`MetadataService.objectPayloadFieldsMap.test.ts` was spelled as a plain object +literal, which per Annex B.3.1 sets the prototype instead of adding a key — so +the assertion parsed an empty `fields` map and would have stayed green if the +spec began refusing the name. Respelled as a computed key and pinned with the +literal-versus-computed control. No published behaviour changes. diff --git a/packages/app-shell/src/services/MetadataService.objectPayloadFieldsMap.test.ts b/packages/app-shell/src/services/MetadataService.objectPayloadFieldsMap.test.ts index cbf8a343e..05beca166 100644 --- a/packages/app-shell/src/services/MetadataService.objectPayloadFieldsMap.test.ts +++ b/packages/app-shell/src/services/MetadataService.objectPayloadFieldsMap.test.ts @@ -152,7 +152,17 @@ describe('the instrument', () => { it('keys the record with a snake_case rule — `__proto__` is a LEGAL field name', () => { // Which is why `toFieldsMap` builds through `Object.fromEntries`: plain // assignment would invoke the prototype setter and drop the field silently. - expect(ObjectSchema.safeParse({ name: 'account', label: 'Account', fields: { __proto__: { type: 'text', label: 'P' } } }).success).toBe(true); + // + // The fixture below spells the key `['__proto__']` DELIBERATELY, and the + // two controls are why (objectui#6524). Per Annex B.3.1 a PLAIN + // `{ __proto__: v }` inside an object literal SETS THE PROTOTYPE and adds + // no own key, so the plainly-spelled fixture this test used to carry handed + // `fields: {}` to the schema: green, and green forever, even if the spec + // began refusing the name. Only the computed form reaches the key rule this + // test claims to pin. + expect(Object.keys({ __proto__: { type: 'text', label: 'P' } })).toEqual([]); + expect(Object.keys({ ['__proto__']: { type: 'text', label: 'P' } })).toEqual(['__proto__']); + expect(ObjectSchema.safeParse({ name: 'account', label: 'Account', fields: { ['__proto__']: { type: 'text', label: 'P' } } }).success).toBe(true); expect(issuesOf(ObjectSchema.safeParse({ name: 'account', label: 'Account', fields: { firstName: { type: 'text', label: 'F' } } }))).toEqual([ 'invalid_key @ fields.firstName', ]); @@ -359,6 +369,9 @@ describe('objectui#6240 · a field with no name FAILS LOUDLY, and nothing is sen { name: 'amount', type: 'number', label: 'Amount' }, ]); expect(Object.keys(fieldsOf(puts))).toEqual(['__proto__', 'amount']); + // Honest ONLY because `fieldsOf` reads `JSON.parse` of the captured bytes, + // where `__proto__` is an own property: a refactor that built this object + // from a literal instead would turn the read below into a prototype read. expect(fieldsOf(puts).__proto__).toMatchObject({ type: 'text', label: 'Proto' }); }); });