Skip to content

Commit 9d7ff2a

Browse files
committed
removed ui:definitions embedding, use registry instead
1 parent b49c7e4 commit 9d7ff2a

File tree

2 files changed

+16
-40
lines changed

2 files changed

+16
-40
lines changed

packages/utils/src/resolveUiSchema.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ const ARRAY_KEYWORDS = [ONE_OF_KEY, ANY_OF_KEY, ALL_OF_KEY] as const;
2929
/** Expands `ui:definitions` into the uiSchema by walking the schema tree and finding all `$ref`s.
3030
* Called once at form initialization to pre-expand definitions into the uiSchema structure.
3131
*
32-
* For recursive schemas, definitions are embedded at recursion points for runtime lookup.
32+
* For recursive schemas, expansion stops at recursion points to avoid infinite loops.
33+
* Runtime resolution via `resolveUiSchema` handles these cases using registry definitions.
3334
*
3435
* @param currentSchema - The current schema node being processed
3536
* @param rootSchema - The root JSON schema (for resolving `$ref`s)
@@ -63,7 +64,6 @@ export function expandUiSchemaDefinitions<
6364
}
6465

6566
if (isRecursive) {
66-
result['ui:definitions'] = definitions;
6767
return result;
6868
}
6969

@@ -162,8 +162,7 @@ export default function resolveUiSchema<
162162
S extends StrictRJSFSchema = RJSFSchema,
163163
F extends FormContextType = any,
164164
>(schema: S, localUiSchema: UiSchema<T, S, F> | undefined, registry: Registry<T, S, F>): UiSchema<T, S, F> {
165-
const embeddedDefinitions = localUiSchema?.['ui:definitions'] as UiSchemaDefinitions<T, S, F> | undefined;
166-
const definitions = embeddedDefinitions || registry.uiSchemaDefinitions;
165+
const definitions = registry.uiSchemaDefinitions;
167166

168167
if (!definitions) {
169168
return localUiSchema || {};
@@ -175,18 +174,10 @@ export default function resolveUiSchema<
175174
}
176175

177176
const definitionUiSchema = definitions[ref];
178-
let result: UiSchema<T, S, F>;
179177

180178
if (!localUiSchema || Object.keys(localUiSchema).length === 0) {
181-
result = { ...definitionUiSchema };
182-
} else {
183-
result = mergeObjects(definitionUiSchema as GenericObjectType, localUiSchema as GenericObjectType) as UiSchema<
184-
T,
185-
S,
186-
F
187-
>;
179+
return { ...definitionUiSchema };
188180
}
189181

190-
result['ui:definitions'] = definitions;
191-
return result;
182+
return mergeObjects(definitionUiSchema as GenericObjectType, localUiSchema as GenericObjectType) as UiSchema<T, S, F>;
192183
}

packages/utils/test/resolveUiSchema.test.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('expandUiSchemaDefinitions()', () => {
8888
});
8989
});
9090

91-
it('embeds ui:definitions at recursion points for recursive schemas', () => {
91+
it('stops expansion at recursion points for recursive schemas', () => {
9292
const schema: RJSFSchema = { $ref: '#/$defs/node' };
9393
const rootSchema: RJSFSchema = {
9494
$defs: {
@@ -108,8 +108,10 @@ describe('expandUiSchemaDefinitions()', () => {
108108

109109
// First level should have the definition applied
110110
expect(result.name).toEqual({ 'ui:placeholder': 'Node name' });
111-
// children.items should have embedded ui:definitions for runtime resolution
112-
expect(result.children?.items?.['ui:definitions']).toEqual(definitions);
111+
// children.items should have definition applied but no embedded ui:definitions
112+
// (runtime resolution uses registry.uiSchemaDefinitions instead)
113+
expect(result.children?.items?.name).toEqual({ 'ui:placeholder': 'Node name' });
114+
expect(result.children?.items?.['ui:definitions']).toBeUndefined();
113115
});
114116

115117
it('handles failed $ref resolution gracefully', () => {
@@ -347,22 +349,16 @@ describe('resolveUiSchema()', () => {
347349
expect(resolveUiSchema({ $ref: '#/$defs/node' }, local, registry)).toEqual(local);
348350
});
349351

350-
it('returns definition with embedded ui:definitions when $ref matches and no local uiSchema', () => {
352+
it('returns definition when $ref matches and no local uiSchema', () => {
351353
const definitions = { '#/$defs/node': { name: { 'ui:placeholder': 'Node name' } } };
352354
const reg = { ...registry, uiSchemaDefinitions: definitions };
353-
expect(resolveUiSchema({ $ref: '#/$defs/node' }, undefined, reg)).toEqual({
354-
...definitions['#/$defs/node'],
355-
'ui:definitions': definitions,
356-
});
355+
expect(resolveUiSchema({ $ref: '#/$defs/node' }, undefined, reg)).toEqual(definitions['#/$defs/node']);
357356
});
358357

359-
it('returns definition with embedded ui:definitions when $ref matches and local uiSchema is empty object', () => {
358+
it('returns definition when $ref matches and local uiSchema is empty object', () => {
360359
const definitions = { '#/$defs/node': { name: { 'ui:placeholder': 'Node name' } } };
361360
const reg = { ...registry, uiSchemaDefinitions: definitions };
362-
expect(resolveUiSchema({ $ref: '#/$defs/node' }, {}, reg)).toEqual({
363-
...definitions['#/$defs/node'],
364-
'ui:definitions': definitions,
365-
});
361+
expect(resolveUiSchema({ $ref: '#/$defs/node' }, {}, reg)).toEqual(definitions['#/$defs/node']);
366362
});
367363

368364
it('returns local uiSchema when schema has no $ref', () => {
@@ -385,7 +381,7 @@ describe('resolveUiSchema()', () => {
385381
expect(resolveUiSchema({ $ref: '#/$defs/node' }, undefined, reg)).toEqual({});
386382
});
387383

388-
it('merges local override on top of definition with embedded ui:definitions', () => {
384+
it('merges local override on top of definition', () => {
389385
const definitions = {
390386
'#/$defs/node': { name: { 'ui:placeholder': 'Default' }, children: { 'ui:orderable': false } },
391387
};
@@ -395,11 +391,10 @@ describe('resolveUiSchema()', () => {
395391
expect(resolveUiSchema({ $ref: '#/$defs/node' }, local, reg)).toEqual({
396392
name: { 'ui:placeholder': 'Override', 'ui:autofocus': true },
397393
children: { 'ui:orderable': false },
398-
'ui:definitions': definitions,
399394
});
400395
});
401396

402-
it('deep merges nested properties preserving unoverridden values with embedded ui:definitions', () => {
397+
it('deep merges nested properties preserving unoverridden values', () => {
403398
const definitions = {
404399
'#/$defs/node': {
405400
name: { 'ui:placeholder': 'Default', 'ui:disabled': true },
@@ -412,16 +407,6 @@ describe('resolveUiSchema()', () => {
412407
expect(resolveUiSchema({ $ref: '#/$defs/node' }, local, reg)).toEqual({
413408
name: { 'ui:placeholder': 'Override', 'ui:disabled': true },
414409
'ui:order': ['name', 'children'],
415-
'ui:definitions': definitions,
416-
});
417-
});
418-
419-
it('uses embedded ui:definitions from local uiSchema when registry has none', () => {
420-
const embeddedDefs = { '#/$defs/node': { name: { 'ui:placeholder': 'Embedded' } } };
421-
const local: UiSchema = { 'ui:definitions': embeddedDefs };
422-
expect(resolveUiSchema({ $ref: '#/$defs/node' }, local, registry)).toEqual({
423-
name: { 'ui:placeholder': 'Embedded' },
424-
'ui:definitions': embeddedDefs,
425410
});
426411
});
427412
});

0 commit comments

Comments
 (0)