Skip to content

ES2020 optimizations #3687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ overrides:
'@typescript-eslint/parameter-properties': error
'@typescript-eslint/prefer-as-const': error
'@typescript-eslint/prefer-enum-initializers': error
'@typescript-eslint/prefer-for-of': error
'@typescript-eslint/prefer-for-of': off
'@typescript-eslint/prefer-function-type': error
'@typescript-eslint/prefer-includes': error
'@typescript-eslint/prefer-literal-enum-member': error
Expand Down
6 changes: 4 additions & 2 deletions src/execution/collectFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ export function collectSubfields(
): Map<string, ReadonlyArray<FieldNode>> {
const subFieldNodes = new AccumulatorMap<string, FieldNode>();
const visitedFragmentNames = new Set<string>();
for (const node of fieldNodes) {
for (let i = 0; i < fieldNodes.length; i++) {
const node = fieldNodes[i];
if (node.selectionSet) {
collectFieldsImpl(
schema,
Expand All @@ -96,7 +97,8 @@ function collectFieldsImpl(
fields: AccumulatorMap<string, FieldNode>,
visitedFragmentNames: Set<string>,
): void {
for (const selection of selectionSet.selections) {
for (let i = 0; i < selectionSet.selections.length; i++) {
const selection = selectionSet.selections[i];
switch (selection.kind) {
case Kind.FIELD: {
if (!shouldIncludeNode(variableValues, selection)) {
Expand Down
11 changes: 8 additions & 3 deletions src/execution/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ export function buildExecutionContext(

let operation: OperationDefinitionNode | undefined;
const fragments: ObjMap<FragmentDefinitionNode> = Object.create(null);
for (const definition of document.definitions) {
for (let i = 0; i < document.definitions.length; i++) {
const definition = document.definitions[i];
switch (definition.kind) {
case Kind.OPERATION_DEFINITION:
if (operationName == null) {
Expand Down Expand Up @@ -431,7 +432,9 @@ function executeFields(
const results = Object.create(null);
let containsPromise = false;

for (const [responseName, fieldNodes] of fields.entries()) {
const fieldsEntries = Array.from(fields.entries());
for (let i = 0; i < fieldsEntries.length; i++) {
const { 0: responseName, 1: fieldNodes } = fieldsEntries[i];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { 0: responseName, 1: fieldNodes } = fieldsEntries[i];
const [responseName, fieldNodes] = fieldsEntries[i];

This version is less wierd

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That version invokes the iterator and is very slow though

const fieldPath = addPath(path, responseName, parentType.name);
const result = executeField(
exeContext,
Expand Down Expand Up @@ -1227,7 +1230,9 @@ function executeSubscription(
rootType,
operation.selectionSet,
);
const [responseName, fieldNodes] = [...rootFields.entries()][0];
const { 0: responseName, 1: fieldNodes } = Array.from(
rootFields.entries(),
)[0];
const fieldName = fieldNodes[0].name.value;
const fieldDef = schema.getField(rootType, fieldName);

Expand Down
6 changes: 4 additions & 2 deletions src/execution/values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ function coerceVariableValues(
onError: (error: GraphQLError) => void,
): { [variable: string]: unknown } {
const coercedValues: { [variable: string]: unknown } = {};
for (const varDefNode of varDefNodes) {
for (let i = 0; i < varDefNodes.length; i++) {
const varDefNode = varDefNodes[i];
const varName = varDefNode.variable.name.value;
const varType = typeFromAST(schema, varDefNode.type);
if (!isInputType(varType)) {
Expand Down Expand Up @@ -161,7 +162,8 @@ export function getArgumentValues(
const argumentNodes = node.arguments ?? [];
const argNodeMap = keyMap(argumentNodes, (arg) => arg.name.value);

for (const argDef of def.args) {
for (let i = 0; i < def.args.length; i++) {
const argDef = def.args[i];
const name = argDef.name;
const argType = argDef.type;
const argumentNode = argNodeMap[name];
Expand Down
3 changes: 2 additions & 1 deletion src/jsutils/groupBy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export function groupBy<K, T>(
keyFn: (item: T) => K,
): Map<K, ReadonlyArray<T>> {
const result = new AccumulatorMap<K, T>();
for (const item of list) {
for (let i = 0; i < list.length; i++) {
const item = list[i];
result.add(keyFn(item), item);
}
return result;
Expand Down
5 changes: 3 additions & 2 deletions src/jsutils/keyMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ export function keyMap<T>(
keyFn: (item: T) => string,
): ObjMap<T> {
const result = Object.create(null);
for (const item of list) {
result[keyFn(item)] = item;
for (let i = 0; i < list.length; i++) {
const key = list[i];
result[keyFn(key)] = key;
}
return result;
}
3 changes: 2 additions & 1 deletion src/jsutils/keyValMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export function keyValMap<T, V>(
valFn: (item: T) => V,
): ObjMap<V> {
const result = Object.create(null);
for (const item of list) {
for (let i = 0; i < list.length; i++) {
const item = list[i];
result[keyFn(item)] = valFn(item);
}
return result;
Expand Down
5 changes: 3 additions & 2 deletions src/jsutils/mapValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ export function mapValue<T, V>(
fn: (value: T, key: string) => V,
): ObjMap<V> {
const result = Object.create(null);

for (const key of Object.keys(map)) {
const keys = Object.keys(map);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
result[key] = fn(map[key], key);
}
return result;
Expand Down
2 changes: 1 addition & 1 deletion src/jsutils/promiseForObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function promiseForObject<T>(
): Promise<ObjMap<T>> {
return Promise.all(Object.values(object)).then((resolvedValues) => {
const resolvedObject = Object.create(null);
for (const [i, key] of Object.keys(object).entries()) {
for (const { 0: i, 1: key } of Object.keys(object).entries()) {
resolvedObject[key] = resolvedValues[i];
}
return resolvedObject;
Expand Down
4 changes: 3 additions & 1 deletion src/jsutils/toObjMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ export function toObjMap<T>(
}

const map = Object.create(null);
for (const [key, value] of Object.entries(obj)) {
const entries = Object.entries(obj);
for (let i = 0; i < entries.length; i++) {
const { 0: key, 1: value } = entries[i];
map[key] = value;
}
return map;
Expand Down
13 changes: 9 additions & 4 deletions src/language/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export type ASTVisitorKeyMap = {
};

export const BREAK: unknown = Object.freeze({});
const KINDS = Object.values(Kind);

/**
* visit() will walk through an AST using a depth-first traversal, calling
Expand Down Expand Up @@ -180,7 +181,8 @@ export function visit(
visitorKeys: ASTVisitorKeyMap = QueryDocumentKeys,
): any {
const enterLeaveMap = new Map<Kind, EnterLeaveVisitor<ASTNode>>();
for (const kind of Object.values(Kind)) {
for (let i = 0; i < KINDS.length; i++) {
const kind = KINDS[i];
enterLeaveMap.set(kind, getEnterLeaveForKind(visitor, kind));
}

Expand Down Expand Up @@ -210,7 +212,8 @@ export function visit(
node = node.slice();

let editOffset = 0;
for (const [editKey, editValue] of edits) {
for (let i = 0; i < edits.length; i++) {
const { 0: editKey, 1: editValue } = edits[i];
const arrayKey = editKey - editOffset;
if (editValue === null) {
node.splice(arrayKey, 1);
Expand All @@ -224,7 +227,8 @@ export function visit(
{},
Object.getOwnPropertyDescriptors(node),
);
for (const [editKey, editValue] of edits) {
for (let i = 0; i < edits.length; i++) {
const { 0: editKey, 1: editValue } = edits[i];
node[editKey] = editValue;
}
}
Expand Down Expand Up @@ -314,7 +318,8 @@ export function visitInParallel(
const skipping = new Array(visitors.length).fill(null);
const mergedVisitor = Object.create(null);

for (const kind of Object.values(Kind)) {
for (let j = 0; j < KINDS.length; j++) {
const kind = KINDS[j];
let hasVisitor = false;
const enterList = new Array(visitors.length).fill(undefined);
const leaveList = new Array(visitors.length).fill(undefined);
Expand Down
57 changes: 36 additions & 21 deletions src/type/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ export class GraphQLSchema {
// the set of "collected" types, so `collectReferencedTypes` ignore them.
const allReferencedTypes = new Set<GraphQLNamedType>(config.types);
if (config.types != null) {
for (const type of config.types) {
for (let i = 0; i < config.types.length; i++) {
const type = config.types[i];
// When we ready to process this type, we remove it from "collected" types
// and then add it together with all dependent types in the correct position.
allReferencedTypes.delete(type);
Expand All @@ -190,10 +191,12 @@ export class GraphQLSchema {
collectReferencedTypes(this._subscriptionType, allReferencedTypes);
}

for (const directive of this._directives) {
for (let i = 0; i < this._directives.length; i++) {
const directive = this._directives[i];
// Directives are not validated until validateSchema() is called.
if (isDirective(directive)) {
for (const arg of directive.args) {
for (let j = 0; j < directive.args.length; j++) {
const arg = directive.args[j];
collectReferencedTypes(arg.type, allReferencedTypes);
}
}
Expand All @@ -206,7 +209,9 @@ export class GraphQLSchema {
// Keep track of all implementations by interface name.
this._implementationsMap = Object.create(null);

for (const namedType of allReferencedTypes) {
const refTypes = Array.from(allReferencedTypes);
for (let j = 0; j < refTypes.length; j++) {
const namedType = refTypes[j];
if (namedType == null) {
continue;
}
Expand All @@ -221,7 +226,9 @@ export class GraphQLSchema {

if (isInterfaceType(namedType)) {
// Store implementations by interface.
for (const iface of namedType.getInterfaces()) {
const interfaces = namedType.getInterfaces();
for (let i = 0; i < interfaces.length; i++) {
const iface = interfaces[i];
if (isInterfaceType(iface)) {
let implementations = this._implementationsMap[iface.name];
if (implementations === undefined) {
Expand All @@ -236,7 +243,9 @@ export class GraphQLSchema {
}
} else if (isObjectType(namedType)) {
// Store implementations by objects.
for (const iface of namedType.getInterfaces()) {
const interfaces = namedType.getInterfaces();
for (let i = 0; i < interfaces.length; i++) {
const iface = interfaces[i];
if (isInterfaceType(iface)) {
let implementations = this._implementationsMap[iface.name];
if (implementations === undefined) {
Expand Down Expand Up @@ -313,16 +322,17 @@ export class GraphQLSchema {
map = Object.create(null);

if (isUnionType(abstractType)) {
for (const type of abstractType.getTypes()) {
map[type.name] = true;
const types = abstractType.getTypes();
for (let i = 0; i < types.length; i++) {
map[types[i].name] = true;
}
} else {
const implementations = this.getImplementations(abstractType);
for (const type of implementations.objects) {
map[type.name] = true;
for (let i = 0; i < implementations.objects.length; i++) {
map[implementations.objects[i].name] = true;
}
for (const type of implementations.interfaces) {
map[type.name] = true;
for (let i = 0; i < implementations.interfaces.length; i++) {
map[implementations.interfaces[i].name] = true;
}
}

Expand Down Expand Up @@ -437,23 +447,28 @@ function collectReferencedTypes(
if (!typeSet.has(namedType)) {
typeSet.add(namedType);
if (isUnionType(namedType)) {
for (const memberType of namedType.getTypes()) {
collectReferencedTypes(memberType, typeSet);
const types = namedType.getTypes();
for (let i = 0; i < types.length; i++) {
collectReferencedTypes(types[i], typeSet);
}
} else if (isObjectType(namedType) || isInterfaceType(namedType)) {
for (const interfaceType of namedType.getInterfaces()) {
collectReferencedTypes(interfaceType, typeSet);
const interfaces = namedType.getInterfaces();
for (let i = 0; i < interfaces.length; i++) {
collectReferencedTypes(interfaces[i], typeSet);
}

for (const field of Object.values(namedType.getFields())) {
const fields = Object.values(namedType.getFields());
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
collectReferencedTypes(field.type, typeSet);
for (const arg of field.args) {
collectReferencedTypes(arg.type, typeSet);
for (let j = 0; j < field.args.length; j++) {
collectReferencedTypes(field.args[j].type, typeSet);
}
}
} else if (isInputObjectType(namedType)) {
for (const field of Object.values(namedType.getFields())) {
collectReferencedTypes(field.type, typeSet);
const fields = Object.values(namedType.getFields());
for (let i = 0; i < fields.length; i++) {
collectReferencedTypes(fields[i].type, typeSet);
}
}
}
Expand Down
Loading