Skip to content

Commit 313f899

Browse files
committed
feat(schema): cache generated field objects
This makes sure that the same field definition always ends up becoming the exact same field object, making it possible to use `===` to compare them.
1 parent c121f06 commit 313f899

File tree

8 files changed

+72
-55
lines changed

8 files changed

+72
-55
lines changed

packages/@sanity/schema/src/legacy/Schema.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1+
import {startCase} from 'lodash'
2+
13
import * as types from './types'
4+
import {lazyGetter} from './types/utils'
5+
6+
interface ExtendHelper {
7+
/** Creates a new type based on the definition. */
8+
(memberDef: any): any
9+
10+
cached(def: any): any
11+
cachedField(fieldDef: any): any
12+
cachedObjectField(fieldDef: any): any
13+
}
214

315
function compileRegistry(schemaDef: any) {
416
const registry = Object.create(null)
@@ -21,6 +33,56 @@ function compileRegistry(schemaDef: any) {
2133
return acc
2234
}, {})
2335

36+
const memberCache = new Map()
37+
const fieldCache = new Map()
38+
const objectFieldCache = new Map()
39+
40+
const extendHelper: ExtendHelper = Object.assign(extendMember, {
41+
cached(def: any) {
42+
let member = memberCache.get(def)
43+
if (!member) {
44+
member = extendMember(def)
45+
memberCache.set(def, member)
46+
}
47+
return member
48+
},
49+
50+
cachedField(fieldDef: any) {
51+
let field = fieldCache.get(fieldDef)
52+
if (!field) {
53+
const {name, ...type} = fieldDef
54+
field = {
55+
name,
56+
type: extendMember(type),
57+
}
58+
fieldCache.set(fieldDef, field)
59+
}
60+
return field
61+
},
62+
63+
cachedObjectField(fieldDef: any) {
64+
let field = objectFieldCache.get(fieldDef)
65+
if (!field) {
66+
const {name, fieldset, group, ...rest} = fieldDef
67+
68+
field = {
69+
name,
70+
group,
71+
fieldset,
72+
}
73+
74+
lazyGetter(field, 'type', () => {
75+
return extendMember({
76+
...rest,
77+
title: fieldDef.title || startCase(name),
78+
})
79+
})
80+
objectFieldCache.set(fieldDef, field)
81+
}
82+
return field
83+
},
84+
})
85+
2486
schemaDef.types.forEach(add)
2587

2688
return {
@@ -39,7 +101,7 @@ function compileRegistry(schemaDef: any) {
39101

40102
function extendMember(memberDef: any) {
41103
ensure(memberDef.type)
42-
return registry[memberDef.type].extend(memberDef, extendMember).get()
104+
return registry[memberDef.type].extend(memberDef, extendHelper).get()
43105
}
44106

45107
function add(typeDef: any) {

packages/@sanity/schema/src/legacy/types/array.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ export const ArrayType = {
2121
type: ARRAY_CORE,
2222
})
2323
lazyGetter(parsed, 'of', () => {
24-
return subTypeDef.of.map((ofTypeDef: any) => {
25-
return createMemberType(ofTypeDef)
26-
})
24+
return subTypeDef.of.map((ofTypeDef: any) => createMemberType.cached(ofTypeDef))
2725
})
2826
lazyGetter(parsed, OWN_PROPS_NAME, () => ({...subTypeDef, of: parsed.of}), {
2927
enumerable: false,

packages/@sanity/schema/src/legacy/types/blocks/block.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,7 @@ export const BlockType = {
7272
})
7373

7474
lazyGetter(parsed, 'fields', () => {
75-
return fields.map((fieldDef) => {
76-
const {name, ...type} = fieldDef
77-
return {
78-
name: name,
79-
type: extendMember(type),
80-
}
81-
})
75+
return fields.map((fieldDef) => extendMember.cachedField(fieldDef))
8276
})
8377

8478
lazyGetter(parsed, 'preview', createPreviewGetter(subTypeDef))

packages/@sanity/schema/src/legacy/types/blocks/span.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,7 @@ export const SpanType = {
5656
})
5757

5858
lazyGetter(parsed, 'fields', () => {
59-
return fields.map((fieldDef) => {
60-
const {name, ...type} = fieldDef
61-
return {
62-
name: name,
63-
type: extendMember(type),
64-
}
65-
})
59+
return fields.map((fieldDef) => extendMember.cachedField(fieldDef))
6660
})
6761

6862
lazyGetter(parsed, 'annotations', () => annotations.map(extendMember))

packages/@sanity/schema/src/legacy/types/crossDatasetReference.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,7 @@ export const CrossDatasetReferenceType = {
7979
)
8080

8181
lazyGetter(parsed, 'fields', () => {
82-
return REFERENCE_FIELDS.map((fieldDef) => {
83-
const {name, ...type} = fieldDef
84-
return {
85-
name: name,
86-
type: createMemberType(type),
87-
}
88-
})
82+
return REFERENCE_FIELDS.map((fieldDef) => createMemberType.cachedField(fieldDef))
8983
})
9084

9185
lazyGetter(parsed, 'to', () => {

packages/@sanity/schema/src/legacy/types/globalDocumentReference.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,7 @@ export const GlobalDocumentReferenceType = {
6666
)
6767

6868
lazyGetter(parsed, 'fields', () => {
69-
return REFERENCE_FIELDS.map((fieldDef) => {
70-
const {name, ...type} = fieldDef
71-
return {
72-
name: name,
73-
type: createMemberType(type),
74-
}
75-
})
69+
return REFERENCE_FIELDS.map((fieldDef) => createMemberType.cachedField(fieldDef))
7670
})
7771

7872
lazyGetter(parsed, 'to', () => {

packages/@sanity/schema/src/legacy/types/object.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,9 @@ export const ObjectType = {
4242
title: subTypeDef.title || (subTypeDef.name ? startCase(subTypeDef.name) : 'Object'),
4343
options: options,
4444
orderings: subTypeDef.orderings || guessOrderingConfig(subTypeDef),
45-
fields: subTypeDef.fields.map((fieldDef: any) => {
46-
const {name, fieldset, group, ...rest} = fieldDef
47-
48-
const compiledField = {
49-
name,
50-
group,
51-
fieldset,
52-
}
53-
54-
return lazyGetter(compiledField, 'type', () => {
55-
return createMemberType({
56-
...rest,
57-
title: fieldDef.title || startCase(name),
58-
})
59-
})
60-
}),
45+
fields: subTypeDef.fields.map((fieldDef: any) =>
46+
createMemberType.cachedObjectField(fieldDef),
47+
),
6148
}
6249

6350
const parsed = Object.assign(pick(this.get(), OVERRIDABLE_FIELDS), ownProps, {

packages/@sanity/schema/src/legacy/types/reference.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,7 @@ export const ReferenceType = {
6363
})
6464

6565
lazyGetter(parsed, 'fields', () => {
66-
return REFERENCE_FIELDS.map((fieldDef) => {
67-
const {name, ...type} = fieldDef
68-
return {
69-
name: name,
70-
type: createMemberType(type),
71-
}
72-
})
66+
return REFERENCE_FIELDS.map((fieldDef) => createMemberType.cachedField(fieldDef))
7367
})
7468

7569
lazyGetter(parsed, 'fieldsets', () => {

0 commit comments

Comments
 (0)