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>

authored by kitten.sh Jovi De Croock and committed by GitHub dfaf56f2 a5bc925a

+5
.changeset/plenty-carrots-confess.md
··· 1 + --- 2 + '@urql/core': patch 3 + --- 4 + 5 + Remove `for-of` syntax from `@urql/core` helpers for JSC memory reduction.
+2 -1
packages/core/src/client.ts
··· 649 649 } else { 650 650 // If the current result has queued up an operation of the same 651 651 // key, then `stale` refers to it 652 - for (const operation of queue) { 652 + for (let i = 0; i < queue.length; i++) { 653 + const operation = queue[i]; 653 654 if (operation.key === result.operation.key) { 654 655 dispatched.delete(operation.key); 655 656 break;
+3 -2
packages/core/src/gql.ts
··· 78 78 } 79 79 80 80 source.unshift(keyDocument(body)); 81 - for (const document of source) { 82 - for (const definition of document.definitions) { 81 + for (let i = 0; i < source.length; i++) { 82 + for (let j = 0; j < source[i].definitions.length; j++) { 83 + const definition = source[i].definitions[j]; 83 84 if (definition.kind === Kind.FRAGMENT_DEFINITION) { 84 85 const name = definition.name.value; 85 86 const value = stringifyDocument(definition);
+3 -1
packages/core/src/utils/collectTypenames.ts
··· 5 5 6 6 const collectTypes = (obj: EntityLike | EntityLike[], types: Set<string>) => { 7 7 if (Array.isArray(obj)) { 8 - for (const item of obj) collectTypes(item, types); 8 + for (let i = 0, l = obj.length; i < l; i++) { 9 + collectTypes(obj[i], types); 10 + } 9 11 } else if (typeof obj === 'object' && obj !== null) { 10 12 for (const key in obj) { 11 13 if (key === '__typename' && typeof obj[key] === 'string') {
+2 -2
packages/core/src/utils/error.ts
··· 8 8 let error = ''; 9 9 if (networkErr) return `[Network] ${networkErr.message}`; 10 10 if (graphQlErrs) { 11 - for (const err of graphQlErrs) { 11 + for (let i = 0, l = graphQlErrs.length; i < l; i++) { 12 12 if (error) error += '\n'; 13 - error += `[GraphQL] ${err.message}`; 13 + error += `[GraphQL] ${graphQlErrs[i].message}`; 14 14 } 15 15 } 16 16 return error;
+6 -4
packages/core/src/utils/formatDocument.ts
··· 16 16 ): FormattedNode<T> => { 17 17 if ('definitions' in node) { 18 18 const definitions: FormattedNode<DefinitionNode>[] = []; 19 - for (const definition of node.definitions) { 20 - const newDefinition = formatNode(definition); 19 + for (let i = 0, l = node.definitions.length; i < l; i++) { 20 + const newDefinition = formatNode(node.definitions[i]); 21 21 definitions.push(newDefinition); 22 22 } 23 23 ··· 27 27 if ('directives' in node && node.directives && node.directives.length) { 28 28 const directives: DirectiveNode[] = []; 29 29 const _directives = {}; 30 - for (const directive of node.directives) { 30 + for (let i = 0, l = node.directives.length; i < l; i++) { 31 + const directive = node.directives[i]; 31 32 let name = directive.name.value; 32 33 if (name[0] !== '_') { 33 34 directives.push(directive); ··· 43 44 const selections: FormattedNode<SelectionNode>[] = []; 44 45 let hasTypename = node.kind === Kind.OPERATION_DEFINITION; 45 46 if (node.selectionSet) { 46 - for (const selection of node.selectionSet.selections || []) { 47 + for (let i = 0, l = node.selectionSet.selections.length; i < l; i++) { 48 + const selection = node.selectionSet.selections[i]; 47 49 hasTypename = 48 50 hasTypename || 49 51 (selection.kind === Kind.FIELD &&
+4 -2
packages/core/src/utils/request.ts
··· 180 180 * @returns the operation's name contained within the document, or `undefined` 181 181 */ 182 182 export const getOperationName = (query: DocumentNode): string | undefined => { 183 - for (const node of query.definitions) { 183 + for (let i = 0, l = query.definitions.length; i < l; i++) { 184 + const node = query.definitions[i]; 184 185 if (node.kind === Kind.OPERATION_DEFINITION) { 185 186 return node.name ? node.name.value : undefined; 186 187 } ··· 192 193 * @returns the operation's type contained within the document, or `undefined` 193 194 */ 194 195 export const getOperationType = (query: DocumentNode): string | undefined => { 195 - for (const node of query.definitions) { 196 + for (let i = 0, l = query.definitions.length; i < l; i++) { 197 + const node = query.definitions[i]; 196 198 if (node.kind === Kind.OPERATION_DEFINITION) { 197 199 return node.operation; 198 200 }
+9 -3
packages/core/src/utils/result.ts
··· 53 53 54 54 const deepMerge = (target: any, source: any): any => { 55 55 if (typeof target === 'object' && target != null) { 56 + if (Array.isArray(target)) { 57 + target = [...target]; 58 + for (let i = 0, l = source.length; i < l; i++) 59 + target[i] = deepMerge(target[i], source[i]); 60 + } 56 61 if ( 57 62 !target.constructor || 58 63 target.constructor === Object || 59 64 Array.isArray(target) 60 65 ) { 61 - target = Array.isArray(target) ? [...target] : { ...target }; 62 - for (const key of Object.keys(source)) 66 + target = { ...target }; 67 + for (const key in source) 63 68 target[key] = deepMerge(target[key], source[key]); 64 69 return target; 65 70 } ··· 108 113 109 114 const withData = { data: prevResult.data }; 110 115 if (incremental) { 111 - for (const patch of incremental) { 116 + for (let i = 0, l = incremental.length; i < l; i++) { 117 + const patch = incremental[i]; 112 118 if (Array.isArray(patch.errors)) { 113 119 errors.push(...(patch.errors as any)); 114 120 }
+6 -6
packages/core/src/utils/variables.ts
··· 12 12 return stringify(x.toJSON(), includeFiles); 13 13 } else if (Array.isArray(x)) { 14 14 let out = '['; 15 - for (const value of x) { 15 + for (let i = 0, l = x.length; i < l; i++) { 16 16 if (out.length > 1) out += ','; 17 - out += stringify(value, includeFiles) || 'null'; 17 + out += stringify(x[i], includeFiles) || 'null'; 18 18 } 19 19 out += ']'; 20 20 return out; ··· 39 39 40 40 seen.add(x); 41 41 let out = '{'; 42 - for (const key of keys) { 43 - const value = stringify(x[key], includeFiles); 42 + for (let i = 0, l = keys.length; i < l; i++) { 43 + const value = stringify(x[keys[i]], includeFiles); 44 44 if (value) { 45 45 if (out.length > 1) out += ','; 46 - out += stringify(key, includeFiles) + ':' + value; 46 + out += stringify(keys[i], includeFiles) + ':' + value; 47 47 } 48 48 } 49 49 ··· 62 62 map.set(path, x as File | Blob); 63 63 } else { 64 64 seen.add(x); 65 - for (const key of Object.keys(x)) extract(map, `${path}.${key}`, x[key]); 65 + for (const key in x) extract(map, `${path}.${key}`, x[key]); 66 66 } 67 67 }; 68 68