UNPKG

4.14 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * strict-local
8 * @format
9 */
10'use strict';
11
12var _objectSpread2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/objectSpread"));
13
14var _toConsumableArray2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/toConsumableArray"));
15
16var FAIL = 'fail';
17var PASS = 'pass';
18var VARIABLE = 'variable';
19/**
20 * A tranform that removes unreachable IR nodes from all documents in a corpus.
21 * The following nodes are removed:
22 * - Any node with `@include(if: false)`
23 * - Any node with `@skip(if: true)`
24 * - Any node with empty `selections`
25 */
26
27function skipUnreachableNodeTransform(context) {
28 var fragments = new Map();
29
30 var nextContext = require("./GraphQLIRTransformer").transform(context, {
31 Root: function Root(node) {
32 return transformNode(context, fragments, node);
33 },
34 // Fragments are included below where referenced.
35 // Unreferenced fragments are not included.
36 Fragment: function Fragment(id) {
37 return null;
38 }
39 });
40
41 return Array.from(fragments.values()).reduce(function (ctx, fragment) {
42 return fragment ? ctx.add(fragment) : ctx;
43 }, nextContext);
44}
45
46function transformNode(context, fragments, node) {
47 var queue = (0, _toConsumableArray2["default"])(node.selections);
48 var selections;
49
50 while (queue.length) {
51 var selection = queue.shift();
52 var nextSelection = void 0;
53
54 switch (selection.kind) {
55 case 'Condition':
56 var match = testCondition(selection);
57
58 if (match === PASS) {
59 queue.unshift.apply(queue, (0, _toConsumableArray2["default"])(selection.selections));
60 } else if (match === VARIABLE) {
61 nextSelection = transformNode(context, fragments, selection);
62 }
63
64 break;
65
66 case 'FragmentSpread':
67 {
68 // Skip fragment spreads if the referenced fragment is empty
69 if (!fragments.has(selection.name)) {
70 var fragment = context.getFragment(selection.name);
71 var nextFragment = transformNode(context, fragments, fragment);
72 fragments.set(selection.name, nextFragment);
73 }
74
75 if (fragments.get(selection.name)) {
76 nextSelection = selection;
77 }
78
79 break;
80 }
81
82 case 'MatchBranch':
83 nextSelection = transformNode(context, fragments, selection);
84 break;
85
86 case 'LinkedField':
87 nextSelection = transformNode(context, fragments, selection);
88 break;
89
90 case 'InlineFragment':
91 // TODO combine with the LinkedField case when flow supports this
92 nextSelection = transformNode(context, fragments, selection);
93 break;
94
95 case 'Defer':
96 nextSelection = transformNode(context, fragments, selection);
97 break;
98
99 case 'Stream':
100 nextSelection = transformNode(context, fragments, selection);
101 break;
102
103 case 'ScalarField':
104 nextSelection = selection;
105 break;
106
107 case 'MatchField':
108 nextSelection = transformNode(context, fragments, selection);
109 break;
110
111 default:
112 selection.kind;
113 !false ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'SkipUnreachableNodeTransform: Unexpected selection kind `%s`.', selection.kind) : require("fbjs/lib/invariant")(false) : void 0;
114 }
115
116 if (nextSelection) {
117 selections = selections || [];
118 selections.push(nextSelection);
119 }
120 }
121
122 if (selections) {
123 return (0, _objectSpread2["default"])({}, node, {
124 selections: selections
125 });
126 }
127
128 return null;
129}
130/**
131 * Determines whether a condition statically passes/fails or is unknown
132 * (variable).
133 */
134
135
136function testCondition(condition) {
137 if (condition.condition.kind === 'Variable') {
138 return VARIABLE;
139 }
140
141 return condition.condition.value === condition.passingValue ? PASS : FAIL;
142}
143
144module.exports = {
145 transform: skipUnreachableNodeTransform
146};
\No newline at end of file