UNPKG

4.38 kBJavaScriptView Raw
1import { __rest } from "tslib";
2import equal from "@wry/equality";
3import { createFragmentMap, getFragmentDefinitions, getFragmentFromSelection, getMainDefinition, isField, resultKeyNameFromField, shouldInclude, } from "../utilities/index.js";
4// Returns true if aResult and bResult are deeply equal according to the fields
5// selected by the given query, ignoring any fields marked as @nonreactive.
6export function equalByQuery(query, _a, _b, variables) {
7 var aData = _a.data, aRest = __rest(_a, ["data"]);
8 var bData = _b.data, bRest = __rest(_b, ["data"]);
9 return (equal(aRest, bRest) &&
10 equalBySelectionSet(getMainDefinition(query).selectionSet, aData, bData, {
11 fragmentMap: createFragmentMap(getFragmentDefinitions(query)),
12 variables: variables,
13 }));
14}
15function equalBySelectionSet(selectionSet, aResult, bResult, context) {
16 if (aResult === bResult) {
17 return true;
18 }
19 var seenSelections = new Set();
20 // Returning true from this Array.prototype.every callback function skips the
21 // current field/subtree. Returning false aborts the entire traversal
22 // immediately, causing equalBySelectionSet to return false.
23 return selectionSet.selections.every(function (selection) {
24 // Avoid re-processing the same selection at the same level of recursion, in
25 // case the same field gets included via multiple indirect fragment spreads.
26 if (seenSelections.has(selection))
27 return true;
28 seenSelections.add(selection);
29 // Ignore @skip(if: true) and @include(if: false) fields.
30 if (!shouldInclude(selection, context.variables))
31 return true;
32 // If the field or (named) fragment spread has a @nonreactive directive on
33 // it, we don't care if it's different, so we pretend it's the same.
34 if (selectionHasNonreactiveDirective(selection))
35 return true;
36 if (isField(selection)) {
37 var resultKey = resultKeyNameFromField(selection);
38 var aResultChild = aResult && aResult[resultKey];
39 var bResultChild = bResult && bResult[resultKey];
40 var childSelectionSet = selection.selectionSet;
41 if (!childSelectionSet) {
42 // These are scalar values, so we can compare them with deep equal
43 // without redoing the main recursive work.
44 return equal(aResultChild, bResultChild);
45 }
46 var aChildIsArray = Array.isArray(aResultChild);
47 var bChildIsArray = Array.isArray(bResultChild);
48 if (aChildIsArray !== bChildIsArray)
49 return false;
50 if (aChildIsArray && bChildIsArray) {
51 var length_1 = aResultChild.length;
52 if (bResultChild.length !== length_1) {
53 return false;
54 }
55 for (var i = 0; i < length_1; ++i) {
56 if (!equalBySelectionSet(childSelectionSet, aResultChild[i], bResultChild[i], context)) {
57 return false;
58 }
59 }
60 return true;
61 }
62 return equalBySelectionSet(childSelectionSet, aResultChild, bResultChild, context);
63 }
64 else {
65 var fragment = getFragmentFromSelection(selection, context.fragmentMap);
66 if (fragment) {
67 // The fragment might === selection if it's an inline fragment, but
68 // could be !== if it's a named fragment ...spread.
69 if (selectionHasNonreactiveDirective(fragment))
70 return true;
71 return equalBySelectionSet(fragment.selectionSet,
72 // Notice that we reuse the same aResult and bResult values here,
73 // since the fragment ...spread does not specify a field name, but
74 // consists of multiple fields (within the fragment's selection set)
75 // that should be applied to the current result value(s).
76 aResult, bResult, context);
77 }
78 }
79 });
80}
81function selectionHasNonreactiveDirective(selection) {
82 return (!!selection.directives && selection.directives.some(directiveIsNonreactive));
83}
84function directiveIsNonreactive(dir) {
85 return dir.name.value === "nonreactive";
86}
87//# sourceMappingURL=equalByQuery.js.map
\No newline at end of file