Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

fix(core): Remove `for-of` syntax from core helpers for JSC memory reduction (#3690)

Co-authored-by: Jovi De Croock <decroockjovi@gmail.com>

+5
.changeset/plenty-carrots-confess.md
···
+
---
+
'@urql/core': patch
+
---
+
+
Remove `for-of` syntax from `@urql/core` helpers for JSC memory reduction.
+2 -1
packages/core/src/client.ts
···
} else {
// If the current result has queued up an operation of the same
// key, then `stale` refers to it
-
for (const operation of queue) {
+
for (let i = 0; i < queue.length; i++) {
+
const operation = queue[i];
if (operation.key === result.operation.key) {
dispatched.delete(operation.key);
break;
+3 -2
packages/core/src/gql.ts
···
}
source.unshift(keyDocument(body));
-
for (const document of source) {
-
for (const definition of document.definitions) {
+
for (let i = 0; i < source.length; i++) {
+
for (let j = 0; j < source[i].definitions.length; j++) {
+
const definition = source[i].definitions[j];
if (definition.kind === Kind.FRAGMENT_DEFINITION) {
const name = definition.name.value;
const value = stringifyDocument(definition);
+3 -1
packages/core/src/utils/collectTypenames.ts
···
const collectTypes = (obj: EntityLike | EntityLike[], types: Set<string>) => {
if (Array.isArray(obj)) {
-
for (const item of obj) collectTypes(item, types);
+
for (let i = 0, l = obj.length; i < l; i++) {
+
collectTypes(obj[i], types);
+
}
} else if (typeof obj === 'object' && obj !== null) {
for (const key in obj) {
if (key === '__typename' && typeof obj[key] === 'string') {
+2 -2
packages/core/src/utils/error.ts
···
let error = '';
if (networkErr) return `[Network] ${networkErr.message}`;
if (graphQlErrs) {
-
for (const err of graphQlErrs) {
+
for (let i = 0, l = graphQlErrs.length; i < l; i++) {
if (error) error += '\n';
-
error += `[GraphQL] ${err.message}`;
+
error += `[GraphQL] ${graphQlErrs[i].message}`;
}
}
return error;
+6 -4
packages/core/src/utils/formatDocument.ts
···
): FormattedNode<T> => {
if ('definitions' in node) {
const definitions: FormattedNode<DefinitionNode>[] = [];
-
for (const definition of node.definitions) {
-
const newDefinition = formatNode(definition);
+
for (let i = 0, l = node.definitions.length; i < l; i++) {
+
const newDefinition = formatNode(node.definitions[i]);
definitions.push(newDefinition);
}
···
if ('directives' in node && node.directives && node.directives.length) {
const directives: DirectiveNode[] = [];
const _directives = {};
-
for (const directive of node.directives) {
+
for (let i = 0, l = node.directives.length; i < l; i++) {
+
const directive = node.directives[i];
let name = directive.name.value;
if (name[0] !== '_') {
directives.push(directive);
···
const selections: FormattedNode<SelectionNode>[] = [];
let hasTypename = node.kind === Kind.OPERATION_DEFINITION;
if (node.selectionSet) {
-
for (const selection of node.selectionSet.selections || []) {
+
for (let i = 0, l = node.selectionSet.selections.length; i < l; i++) {
+
const selection = node.selectionSet.selections[i];
hasTypename =
hasTypename ||
(selection.kind === Kind.FIELD &&
+4 -2
packages/core/src/utils/request.ts
···
* @returns the operation's name contained within the document, or `undefined`
*/
export const getOperationName = (query: DocumentNode): string | undefined => {
-
for (const node of query.definitions) {
+
for (let i = 0, l = query.definitions.length; i < l; i++) {
+
const node = query.definitions[i];
if (node.kind === Kind.OPERATION_DEFINITION) {
return node.name ? node.name.value : undefined;
}
···
* @returns the operation's type contained within the document, or `undefined`
*/
export const getOperationType = (query: DocumentNode): string | undefined => {
-
for (const node of query.definitions) {
+
for (let i = 0, l = query.definitions.length; i < l; i++) {
+
const node = query.definitions[i];
if (node.kind === Kind.OPERATION_DEFINITION) {
return node.operation;
}
+9 -3
packages/core/src/utils/result.ts
···
const deepMerge = (target: any, source: any): any => {
if (typeof target === 'object' && target != null) {
+
if (Array.isArray(target)) {
+
target = [...target];
+
for (let i = 0, l = source.length; i < l; i++)
+
target[i] = deepMerge(target[i], source[i]);
+
}
if (
!target.constructor ||
target.constructor === Object ||
Array.isArray(target)
) {
-
target = Array.isArray(target) ? [...target] : { ...target };
-
for (const key of Object.keys(source))
+
target = { ...target };
+
for (const key in source)
target[key] = deepMerge(target[key], source[key]);
return target;
}
···
const withData = { data: prevResult.data };
if (incremental) {
-
for (const patch of incremental) {
+
for (let i = 0, l = incremental.length; i < l; i++) {
+
const patch = incremental[i];
if (Array.isArray(patch.errors)) {
errors.push(...(patch.errors as any));
}
+6 -6
packages/core/src/utils/variables.ts
···
return stringify(x.toJSON(), includeFiles);
} else if (Array.isArray(x)) {
let out = '[';
-
for (const value of x) {
+
for (let i = 0, l = x.length; i < l; i++) {
if (out.length > 1) out += ',';
-
out += stringify(value, includeFiles) || 'null';
+
out += stringify(x[i], includeFiles) || 'null';
}
out += ']';
return out;
···
seen.add(x);
let out = '{';
-
for (const key of keys) {
-
const value = stringify(x[key], includeFiles);
+
for (let i = 0, l = keys.length; i < l; i++) {
+
const value = stringify(x[keys[i]], includeFiles);
if (value) {
if (out.length > 1) out += ',';
-
out += stringify(key, includeFiles) + ':' + value;
+
out += stringify(keys[i], includeFiles) + ':' + value;
}
}
···
map.set(path, x as File | Blob);
} else {
seen.add(x);
-
for (const key of Object.keys(x)) extract(map, `${path}.${key}`, x[key]);
+
for (const key in x) extract(map, `${path}.${key}`, x[key]);
}
};