From 51d617eec0530cfac9358f4cf85805d1a622105a Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Fri, 6 Jun 2025 09:46:28 +0300 Subject: [PATCH 1/2] perf: introduce defineEnumValues This makes definition of enum values lazy similar to how field/input field definition is lazy. It brings a small performance improvement when using enums in large schemas, as the enum values are only defined when they are actually used --- src/type/definition.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/type/definition.ts b/src/type/definition.ts index b35c44947e..14d077d87b 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -1563,7 +1563,7 @@ export class GraphQLEnumType /* */ implements GraphQLSchemaElement { private _values: | ReadonlyArray */> - | (() => GraphQLEnumValueConfigMap); + | (() => ReadonlyArray) /* */; private _valueLookup: ReadonlyMap | null; private _nameLookup: ObjMap | null; @@ -1576,13 +1576,7 @@ export class GraphQLEnumType /* */ implements GraphQLSchemaElement { this.astNode = config.astNode; this.extensionASTNodes = config.extensionASTNodes ?? []; - this._values = - typeof config.values === 'function' - ? config.values - : Object.entries(config.values).map( - ([valueName, valueConfig]) => - new GraphQLEnumValue(this, valueName, valueConfig), - ); + this._values = defineEnumValues.bind(undefined, this, config.values); this._valueLookup = null; this._nameLookup = null; } @@ -1593,10 +1587,7 @@ export class GraphQLEnumType /* */ implements GraphQLSchemaElement { getValues(): ReadonlyArray */> { if (typeof this._values === 'function') { - this._values = Object.entries(this._values()).map( - ([valueName, valueConfig]) => - new GraphQLEnumValue(this, valueName, valueConfig), - ); + this._values = this._values(); } return this._values; } @@ -1722,6 +1713,18 @@ export class GraphQLEnumType /* */ implements GraphQLSchemaElement { } } +function defineEnumValues( + parentEnum: GraphQLEnumType, + values: ThunkObjMap */>, +): ReadonlyArray { + const valueMap = resolveObjMapThunk(values); + + return Object.entries(valueMap).map( + ([valueName, valueConfig]) => + new GraphQLEnumValue(parentEnum, valueName, valueConfig), + ); +} + function didYouMeanEnumValue( enumType: GraphQLEnumType, unknownValueStr: string, From e80c45d23115c0e6fbbbf5d6bd6bf1d9fbdf95b8 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Mon, 18 Aug 2025 05:04:23 +0300 Subject: [PATCH 2/2] update test this PR means that bad enum value names will not be checked unless type.getValues() is called in parallel to how bad field names are not checked unless type.getFields() is called. --- src/type/__tests__/definition-test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/type/__tests__/definition-test.ts b/src/type/__tests__/definition-test.ts index 8d9eeb4044..286aa1c6c7 100644 --- a/src/type/__tests__/definition-test.ts +++ b/src/type/__tests__/definition-test.ts @@ -794,15 +794,15 @@ describe('Type System: Enums', () => { }); it('rejects an Enum type with incorrectly named values', () => { - expect( - () => - new GraphQLEnumType({ - name: 'SomeEnum', - values: { - 'bad-name': {}, - }, - }), - ).to.throw('Names must only contain [_a-zA-Z0-9] but "bad-name" does not.'); + const enumType = new GraphQLEnumType({ + name: 'SomeEnum', + values: { + 'bad-name': {}, + }, + }); + expect(() => enumType.getValues()).to.throw( + 'Names must only contain [_a-zA-Z0-9] but "bad-name" does not.', + ); }); });