From 25a06dc24c3f92a346e414e49005fa951fc9a1fe Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 12 May 2021 19:27:11 +0300 Subject: [PATCH] collectFields: use ES6 collections instead of Object.create(null) --- src/execution/execute.js | 40 +++++++++++++++++------------------ src/jsutils/promiseReduce.js | 18 ++++++++-------- src/subscription/subscribe.js | 6 +++--- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/execution/execute.js b/src/execution/execute.js index f3a88c8c0f..4486e95eea 100644 --- a/src/execution/execute.js +++ b/src/execution/execute.js @@ -333,8 +333,8 @@ function executeOperation( exeContext, type, operation.selectionSet, - Object.create(null), - Object.create(null), + new Map(), + new Set(), ); const path = undefined; @@ -369,12 +369,11 @@ function executeFieldsSerially( parentType: GraphQLObjectType, sourceValue: mixed, path: Path | void, - fields: ObjMap>, + fields: Map>, ): PromiseOrValue> { return promiseReduce( - Object.keys(fields), - (results, responseName) => { - const fieldNodes = fields[responseName]; + fields.entries(), + (results, [responseName, fieldNodes]) => { const fieldPath = addPath(path, responseName, parentType.name); const result = resolveField( exeContext, @@ -408,13 +407,12 @@ function executeFields( parentType: GraphQLObjectType, sourceValue: mixed, path: Path | void, - fields: ObjMap>, + fields: Map>, ): PromiseOrValue> { const results = Object.create(null); let containsPromise = false; - for (const responseName of Object.keys(fields)) { - const fieldNodes = fields[responseName]; + for (const [responseName, fieldNodes] of fields.entries()) { const fieldPath = addPath(path, responseName, parentType.name); const result = resolveField( exeContext, @@ -457,9 +455,9 @@ export function collectFields( exeContext: ExecutionContext, runtimeType: GraphQLObjectType, selectionSet: SelectionSetNode, - fields: ObjMap>, - visitedFragmentNames: ObjMap, -): ObjMap> { + fields: Map>, + visitedFragmentNames: Set, +): Map> { for (const selection of selectionSet.selections) { switch (selection.kind) { case Kind.FIELD: { @@ -467,10 +465,12 @@ export function collectFields( continue; } const name = getFieldEntryKey(selection); - if (!fields[name]) { - fields[name] = []; + const fieldList = fields.get(name); + if (fieldList !== undefined) { + fieldList.push(selection); + } else { + fields.set(name, [selection]); } - fields[name].push(selection); break; } case Kind.INLINE_FRAGMENT: { @@ -492,12 +492,12 @@ export function collectFields( case Kind.FRAGMENT_SPREAD: { const fragName = selection.name.value; if ( - visitedFragmentNames[fragName] || + visitedFragmentNames.has(fragName) || !shouldIncludeNode(exeContext, selection) ) { continue; } - visitedFragmentNames[fragName] = true; + visitedFragmentNames.add(fragName); const fragment = exeContext.fragments[fragName]; if ( !fragment || @@ -1085,9 +1085,9 @@ function _collectSubfields( exeContext: ExecutionContext, returnType: GraphQLObjectType, fieldNodes: $ReadOnlyArray, -): ObjMap> { - let subFieldNodes = Object.create(null); - const visitedFragmentNames = Object.create(null); +): Map> { + let subFieldNodes = new Map(); + const visitedFragmentNames = new Set(); for (const node of fieldNodes) { if (node.selectionSet) { subFieldNodes = collectFields( diff --git a/src/jsutils/promiseReduce.js b/src/jsutils/promiseReduce.js index de0ec20169..c92b934a71 100644 --- a/src/jsutils/promiseReduce.js +++ b/src/jsutils/promiseReduce.js @@ -10,15 +10,15 @@ import { isPromise } from './isPromise'; * return a Promise. */ export function promiseReduce( - values: $ReadOnlyArray, - callback: (accumulator: U, currentValue: T) => PromiseOrValue, + values: Iterable, + callbackFn: (accumulator: U, currentValue: T) => PromiseOrValue, initialValue: PromiseOrValue, ): PromiseOrValue { - return values.reduce( - (previous, value) => - isPromise(previous) - ? previous.then((resolved) => callback(resolved, value)) - : callback(previous, value), - initialValue, - ); + let accumulator = initialValue; + for (const value of values) { + accumulator = isPromise(accumulator) + ? accumulator.then((resolved) => callbackFn(resolved, value)) + : callbackFn(accumulator, value); + } + return accumulator; } diff --git a/src/subscription/subscribe.js b/src/subscription/subscribe.js index 94f1f83a00..7b41f7e466 100644 --- a/src/subscription/subscribe.js +++ b/src/subscription/subscribe.js @@ -195,10 +195,10 @@ async function executeSubscription( exeContext, type, operation.selectionSet, - Object.create(null), - Object.create(null), + new Map(), + new Set(), ); - const [responseName, fieldNodes] = Object.entries(fields)[0]; + const [responseName, fieldNodes] = [...fields.entries()][0]; const fieldName = fieldNodes[0].name.value; const fieldDef = getFieldDef(schema, type, fieldName);