···11import { FieldNode, DocumentNode, FragmentDefinitionNode } from 'graphql';
22+import { CombinedError } from '@urql/core';
2334import {
45 getSelectionSet,
···67 SelectionSet,
78 getFragmentTypeName,
89 getFieldAlias,
99-} from '../ast';
1010-1111-import {
1210 getFragments,
1311 getMainOperation,
1412 normalizeVariables,
···4442 ensureData,
4543 makeContext,
4644 updateContext,
4545+ getFieldError,
4746} from './shared';
48474948import {
···6261 store: Store,
6362 request: OperationRequest,
6463 data?: Data,
6464+ error?: CombinedError | undefined,
6565 key?: number
6666): QueryResult => {
6767 initDataState('read', store.data, (data && key) || null);
6868- const result = read(store, request, data);
6868+ const result = read(store, request, data, error);
6969 clearDataState();
7070 return result;
7171};
···7373export const read = (
7474 store: Store,
7575 request: OperationRequest,
7676- input?: Data
7676+ input?: Data,
7777+ error?: CombinedError | undefined
7778): QueryResult => {
7879 const operation = getMainOperation(request.query);
7980 const rootKey = store.rootFields[operation.operation];
···8485 normalizeVariables(operation, request.variables),
8586 getFragments(request.query),
8687 rootKey,
8787- rootKey
8888+ rootKey,
8989+ false,
9090+ error
8891 );
89929093 if (process.env.NODE_ENV !== 'production') {
···117120 select: SelectionSet,
118121 originalData: Data
119122): Data => {
120120- if (typeof originalData.__typename !== 'string') {
123123+ const typename = ctx.store.rootNames[entityKey]
124124+ ? entityKey
125125+ : originalData.__typename;
126126+ if (typeof typename !== 'string') {
121127 return originalData;
122128 }
123129124130 const iterate = makeSelectionIterator(entityKey, entityKey, select, ctx);
125125- const data = {} as Data;
126126- data.__typename = originalData.__typename;
131131+ const data = { __typename: typename };
127132128133 let node: FieldNode | void;
129134 while ((node = iterate())) {
130135 const fieldAlias = getFieldAlias(node);
131136 const fieldValue = originalData[fieldAlias];
132137 // Add the current alias to the walked path before processing the field's value
133133- if (process.env.NODE_ENV !== 'production')
134134- ctx.__internal.path.push(fieldAlias);
138138+ ctx.__internal.path.push(fieldAlias);
135139 // Process the root field's value
136140 if (node.selectionSet && fieldValue !== null) {
137141 const fieldData = ensureData(fieldValue);
···140144 data[fieldAlias] = fieldValue;
141145 }
142146 // After processing the field, remove the current alias from the path again
143143- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.pop();
147147+ ctx.__internal.path.pop();
144148 }
145149146150 return data;
···155159 const newData = new Array(originalData.length);
156160 for (let i = 0, l = originalData.length; i < l; i++) {
157161 // Add the current index to the walked path before reading the field's value
158158- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.push(i);
162162+ ctx.__internal.path.push(i);
159163 // Recursively read the root field's value
160164 newData[i] = readRootField(ctx, select, originalData[i]);
161165 // After processing the field, remove the current index from the path
162162- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.pop();
166166+ ctx.__internal.path.pop();
163167 }
164168165169 return newData;
···312316 // means that the value is missing from the cache
313317 let dataFieldValue: void | DataField;
314318 // Add the current alias to the walked path before processing the field's value
315315- if (process.env.NODE_ENV !== 'production')
316316- ctx.__internal.path.push(fieldAlias);
319319+ ctx.__internal.path.push(fieldAlias);
317320318321 if (resultValue !== undefined && node.selectionSet === undefined) {
319322 // The field is a scalar and can be retrieved directly from the result
···396399 }
397400 }
398401402402+ // If we have an error registered for the current field change undefined values to null
403403+ if (dataFieldValue === undefined && !!getFieldError(ctx)) {
404404+ hasPartials = true;
405405+ dataFieldValue = null;
406406+ }
407407+399408 // After processing the field, remove the current alias from the path again
400400- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.pop();
409409+ ctx.__internal.path.pop();
410410+401411 // Now that dataFieldValue has been retrieved it'll be set on data
402412 // If it's uncached (undefined) but nullable we can continue assembling
403413 // a partial query result
···442452 const data = new Array(result.length);
443453 for (let i = 0, l = result.length; i < l; i++) {
444454 // Add the current index to the walked path before reading the field's value
445445- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.push(i);
455455+ ctx.__internal.path.push(i);
446456 // Recursively read resolver result
447457 const childResult = resolveResolverResult(
448458 ctx,
···455465 result[i]
456466 );
457467 // After processing the field, remove the current index from the path
458458- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.pop();
468468+ ctx.__internal.path.pop();
459469 // Check the result for cache-missed values
460470 if (childResult === undefined && !_isListNullable) {
461471 return undefined;
···504514 const newLink = new Array(link.length);
505515 for (let i = 0, l = link.length; i < l; i++) {
506516 // Add the current index to the walked path before reading the field's value
507507- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.push(i);
517517+ ctx.__internal.path.push(i);
508518 // Recursively read the link
509519 const childLink = resolveLink(
510520 ctx,
···515525 prevData != null ? prevData[i] : undefined
516526 );
517527 // After processing the field, remove the current index from the path
518518- if (process.env.NODE_ENV !== 'production') ctx.__internal.path.pop();
528528+ ctx.__internal.path.pop();
519529 // Check the result for cache-missed values
520530 if (childLink === undefined && !_isListNullable) {
521531 return undefined;