relay-compiler 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. package/LICENSE +16 -26
  2. package/bin/relay-compiler +7348 -5939
  3. package/index.js +3 -6
  4. package/lib/{FileParser.js → ASTCache.js} +17 -14
  5. package/lib/ASTConvert.js +84 -70
  6. package/lib/CodegenDirectory.js +122 -28
  7. package/lib/{RelayCodegenRunner.js → CodegenRunner.js} +110 -186
  8. package/lib/CodegenTypes.js +12 -0
  9. package/lib/{RelayCodegenWatcher.js → CodegenWatcher.js} +53 -43
  10. package/lib/DefaultHandleKey.js +2 -4
  11. package/lib/DotGraphQLParser.js +27 -0
  12. package/lib/FilterDirectivesTransform.js +11 -11
  13. package/lib/FindGraphQLTags.js +33 -52
  14. package/lib/FlattenTransform.js +197 -0
  15. package/lib/GraphQLCompilerContext.js +158 -0
  16. package/lib/GraphQLCompilerProfiler.js +271 -0
  17. package/lib/GraphQLCompilerPublic.js +27 -22
  18. package/lib/GraphQLCompilerUserError.js +26 -0
  19. package/lib/GraphQLConsoleReporter.js +58 -0
  20. package/lib/GraphQLIR.js +12 -0
  21. package/lib/{RelayPrinter.js → GraphQLIRPrinter.js} +42 -38
  22. package/lib/{RelayIRTransformer.js → GraphQLIRTransformer.js} +47 -38
  23. package/lib/GraphQLIRTransforms.js +6 -15
  24. package/lib/{RelayIRVisitor.js → GraphQLIRVisitor.js} +7 -6
  25. package/lib/GraphQLMultiReporter.js +50 -0
  26. package/lib/GraphQLParser.js +743 -0
  27. package/lib/GraphQLReporter.js +12 -0
  28. package/lib/GraphQLSchemaUtils.js +10 -36
  29. package/lib/GraphQLValidator.js +13 -15
  30. package/lib/{RelayWatchmanClient.js → GraphQLWatchmanClient.js} +15 -17
  31. package/lib/InlineFragmentsTransform.js +48 -0
  32. package/lib/PatchedBabelGenerator.js +58 -0
  33. package/lib/RelayApplyFragmentArgumentTransform.js +37 -18
  34. package/lib/RelayCodeGenerator.js +130 -60
  35. package/lib/RelayCompilerBin.js +80 -35
  36. package/lib/RelayCompilerCache.js +18 -11
  37. package/lib/RelayCompilerPublic.js +24 -10
  38. package/lib/RelayCompilerScope.js +2 -4
  39. package/lib/RelayConcreteNode.js +31 -14
  40. package/lib/RelayConnectionConstants.js +2 -4
  41. package/lib/RelayConnectionTransform.js +34 -38
  42. package/lib/RelayDefaultHandleKey.js +2 -4
  43. package/lib/RelayDeferrableFragmentTransform.js +464 -0
  44. package/lib/RelayError.js +2 -6
  45. package/lib/RelayFieldHandleTransform.js +15 -11
  46. package/lib/RelayFileWriter.js +119 -98
  47. package/lib/RelayFlowBabelFactories.js +113 -0
  48. package/lib/RelayFlowGenerator.js +180 -200
  49. package/lib/RelayFlowTypeTransformers.js +109 -0
  50. package/lib/RelayGenerateIDFieldTransform.js +131 -0
  51. package/lib/RelayGenerateTypeNameTransform.js +75 -0
  52. package/lib/RelayGraphQLEnumsGenerator.js +65 -0
  53. package/lib/RelayIRTransforms.js +19 -23
  54. package/lib/RelayInternalTypes.js +2 -5
  55. package/lib/RelayInternals.js +2 -5
  56. package/lib/RelayJSModuleParser.js +64 -0
  57. package/lib/RelayMaskTransform.js +129 -0
  58. package/lib/RelayMetricsRecorder.js +9 -9
  59. package/lib/RelayMockRenderer.js +3 -8
  60. package/lib/RelayNetworkDebug.js +4 -7
  61. package/lib/RelayParser.js +28 -645
  62. package/lib/RelayProfiler.js +7 -7
  63. package/lib/RelayQueryCaching.js +2 -5
  64. package/lib/RelayRelayDirectiveTransform.js +47 -33
  65. package/lib/RelayRuntimeTypes.js +22 -0
  66. package/lib/RelayShallowMock.js +4 -7
  67. package/lib/RelaySkipHandleFieldTransform.js +13 -11
  68. package/lib/RelayTaskQueue.js +2 -5
  69. package/lib/RelayTransformUtils.js +20 -0
  70. package/lib/RelayTypes.js +2 -5
  71. package/lib/RelayValidator.js +9 -8
  72. package/lib/RelayViewerHandleTransform.js +22 -18
  73. package/lib/SkipClientFieldTransform.js +36 -53
  74. package/lib/SkipRedundantNodesTransform.js +22 -29
  75. package/lib/SkipUnreachableNodeTransform.js +57 -36
  76. package/lib/SourceControl.js +61 -0
  77. package/lib/StripUnusedVariablesTransform.js +86 -41
  78. package/lib/areEqualOSS.js +2 -4
  79. package/lib/compileRelayArtifacts.js +72 -0
  80. package/lib/dedent.js +2 -5
  81. package/lib/dedupeJSONStringify.js +132 -0
  82. package/lib/deepFreeze.js +3 -5
  83. package/lib/deepMergeAssignments.js +68 -0
  84. package/lib/filterContextForNode.js +5 -7
  85. package/lib/formatGeneratedModule.js +5 -9
  86. package/lib/{getIdentifierForRelayArgumentValue.js → getIdentifierForArgumentValue.js} +8 -10
  87. package/lib/getIdentifierForSelection.js +37 -0
  88. package/lib/getLiteralArgumentValues.js +26 -0
  89. package/lib/getModuleName.js +2 -4
  90. package/lib/getRelayHandleKey.js +2 -4
  91. package/lib/isCompatibleRelayFragmentType.js +2 -5
  92. package/lib/isEquivalentType.js +55 -0
  93. package/lib/isPromise.js +2 -5
  94. package/lib/isScalarAndEqual.js +3 -5
  95. package/lib/murmurHash.js +2 -4
  96. package/lib/nullthrowsOSS.js +7 -5
  97. package/lib/recycleNodesInto.js +2 -4
  98. package/lib/relayUnstableBatchedUpdates.js +2 -5
  99. package/lib/relayUnstableBatchedUpdates.native.js +2 -5
  100. package/lib/requestsForOperation.js +75 -0
  101. package/lib/simpleClone.js +2 -4
  102. package/lib/stableCopy.js +35 -0
  103. package/lib/testEditDistance.js +2 -5
  104. package/lib/throwFailedPromise.js +2 -5
  105. package/lib/writeRelayGeneratedFile.js +84 -50
  106. package/package.json +16 -15
  107. package/relay-compiler.js +7208 -5872
  108. package/relay-compiler.min.js +7200 -5867
  109. package/ARCHITECTURE.md +0 -94
  110. package/PATENTS +0 -33
  111. package/lib/AutoAliasTransform.js +0 -80
  112. package/lib/GraphQLFileParser.js +0 -27
  113. package/lib/GraphQLTextParser.js +0 -46
  114. package/lib/RelayCodegenTypes.js +0 -14
  115. package/lib/RelayCompiledTypes.js +0 -13
  116. package/lib/RelayCompiler.js +0 -144
  117. package/lib/RelayCompilerContext.js +0 -133
  118. package/lib/RelayCompilerUserError.js +0 -30
  119. package/lib/RelayConsoleReporter.js +0 -40
  120. package/lib/RelayFileIRParser.js +0 -66
  121. package/lib/RelayFlattenTransform.js +0 -278
  122. package/lib/RelayFlowParser.js +0 -188
  123. package/lib/RelayGenerateRequisiteFieldsTransform.js +0 -189
  124. package/lib/RelayIR.js +0 -14
  125. package/lib/RelayMultiReporter.js +0 -40
  126. package/lib/RelayReporter.js +0 -14
  127. package/lib/RelayTestSchema.js +0 -21
  128. package/lib/formatStorageKey.js +0 -37
  129. package/lib/getIdentifierForRelaySelection.js +0 -54
  130. package/lib/getRelayLiteralArgumentValues.js +0 -28
  131. package/lib/parseGraphQLText.js +0 -33
  132. package/lib/prettyStringify.js +0 -35
  133. package/lib/printFlowTypes.js +0 -282
  134. package/lib/stableJSONStringify.js +0 -45
  135. package/lib/stableJSONStringifyOSS.js +0 -44
  136. package/lib/transformInputObjectToIR.js +0 -85
  137. package/lib/writeLegacyFlowFile.js +0 -24
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Copyright (c) 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
3
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
8
6
  *
9
7
  * @providesModule SkipRedundantNodesTransform
10
8
  *
@@ -92,7 +90,7 @@ var IMap = require('immutable').Map;
92
90
  * cc
93
91
  * }
94
92
  * }
95
- * }
93
+ * }
96
94
  * ```
97
95
  *
98
96
  * Becomes
@@ -107,7 +105,7 @@ var IMap = require('immutable').Map;
107
105
  * cc
108
106
  * }
109
107
  * }
110
- * }
108
+ * }
111
109
  * ```
112
110
  *
113
111
  * 1 can be skipped because it is already fetched at the outer level.
@@ -120,16 +118,15 @@ var IMap = require('immutable').Map;
120
118
  * or nested maps for items with subselections (linked fields, inline fragments,
121
119
  * etc).
122
120
  */
123
- function transform(context) {
124
- return context.documents().reduce(function (ctx, node) {
125
- var selectionMap = new IMap();
126
- var transformed = transformNode(node, selectionMap);
127
- if (transformed) {
128
- return ctx.add(transformed.node);
129
- } else {
130
- return ctx;
131
- }
132
- }, new (require('./RelayCompilerContext'))(context.schema));
121
+ function skipRedundantNodesTransform(context) {
122
+ return require('./GraphQLIRTransformer').transform(context, {
123
+ Root: visitNode,
124
+ Fragment: visitNode
125
+ });
126
+ }
127
+
128
+ function visitNode(node) {
129
+ return transformNode(node, new IMap()).node;
133
130
  }
134
131
 
135
132
  /**
@@ -148,9 +145,10 @@ function transform(context) {
148
145
  function transformNode(node, selectionMap) {
149
146
  var selections = [];
150
147
  sortSelections(node.selections).forEach(function (selection) {
151
- var identifier = require('./getIdentifierForRelaySelection')(selection);
148
+ var identifier = require('./getIdentifierForSelection')(selection);
152
149
  switch (selection.kind) {
153
150
  case 'ScalarField':
151
+ case 'DeferrableFragmentSpread':
154
152
  case 'FragmentSpread':
155
153
  {
156
154
  if (!selectionMap.has(identifier)) {
@@ -162,7 +160,7 @@ function transformNode(node, selectionMap) {
162
160
  case 'LinkedField':
163
161
  {
164
162
  var transformed = transformNode(selection, selectionMap.get(identifier) || new IMap());
165
- if (transformed) {
163
+ if (transformed.node) {
166
164
  selections.push(transformed.node);
167
165
  selectionMap = selectionMap.set(identifier, transformed.selectionMap);
168
166
  }
@@ -174,7 +172,7 @@ function transformNode(node, selectionMap) {
174
172
  // Fork the selection map to prevent conditional selections from
175
173
  // affecting the outer "guaranteed" selections.
176
174
  var _transformed = transformNode(selection, selectionMap.get(identifier) || selectionMap);
177
- if (_transformed) {
175
+ if (_transformed.node) {
178
176
  selections.push(_transformed.node);
179
177
  selectionMap = selectionMap.set(identifier, _transformed.selectionMap);
180
178
  }
@@ -184,15 +182,8 @@ function transformNode(node, selectionMap) {
184
182
  require('fbjs/lib/invariant')(false, 'SkipRedundantNodesTransform: Unexpected node kind `%s`.', selection.kind);
185
183
  }
186
184
  });
187
- if (!selections.length) {
188
- return null;
189
- }
190
- return {
191
- selectionMap: selectionMap,
192
- node: (0, _extends3['default'])({}, node, {
193
- selections: selections
194
- })
195
- };
185
+ var nextNode = selections.length ? (0, _extends3['default'])({}, node, { selections: selections }) : null;
186
+ return { selectionMap: selectionMap, node: nextNode };
196
187
  }
197
188
 
198
189
  /**
@@ -204,4 +195,6 @@ function sortSelections(selections) {
204
195
  });
205
196
  }
206
197
 
207
- module.exports = { transform: transform };
198
+ module.exports = {
199
+ transform: skipRedundantNodesTransform
200
+ };
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Copyright (c) 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
3
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
8
6
  *
9
7
  * @providesModule SkipUnreachableNodeTransform
10
8
  *
@@ -30,18 +28,18 @@ var VARIABLE = 'variable';
30
28
  * - Any node with `@skip(if: true)`
31
29
  * - Any node with empty `selections`
32
30
  */
33
- function transform(context) {
34
- var documents = context.documents();
31
+ function skipUnreachableNodeTransform(context) {
35
32
  var fragments = new Map();
36
- var nextContext = documents.reduce(function (ctx, node) {
37
- if (node.kind === 'Root') {
38
- var transformedNode = transformNode(context, fragments, node);
39
- if (transformedNode) {
40
- return ctx.add(transformedNode);
41
- }
33
+ var nextContext = require('./GraphQLIRTransformer').transform(context, {
34
+ Root: function Root(node) {
35
+ return transformNode(context, fragments, node);
36
+ },
37
+ // Fragments are included below where referenced.
38
+ // Unreferenced fragments are not included.
39
+ Fragment: function Fragment(id) {
40
+ return null;
42
41
  }
43
- return ctx;
44
- }, new (require('./RelayCompilerContext'))(context.schema));
42
+ });
45
43
  return Array.from(fragments.values()).reduce(function (ctx, fragment) {
46
44
  return fragment ? ctx.add(fragment) : ctx;
47
45
  }, nextContext);
@@ -53,29 +51,50 @@ function transformNode(context, fragments, node) {
53
51
  while (queue.length) {
54
52
  var selection = queue.shift();
55
53
  var nextSelection = void 0;
56
- if (selection.kind === 'Condition') {
57
- var match = testCondition(selection);
58
- if (match === PASS) {
59
- queue.unshift.apply(queue, (0, _toConsumableArray3['default'])(selection.selections));
60
- } else if (match === VARIABLE) {
54
+ switch (selection.kind) {
55
+ case 'Condition':
56
+ var match = testCondition(selection);
57
+ if (match === PASS) {
58
+ queue.unshift.apply(queue, (0, _toConsumableArray3['default'])(selection.selections));
59
+ } else if (match === VARIABLE) {
60
+ nextSelection = transformNode(context, fragments, selection);
61
+ }
62
+ break;
63
+ case 'DeferrableFragmentSpread':
64
+ // Skip deferred fragment spreads if the referenced fragment is empty
65
+ if (!fragments.has(selection.name)) {
66
+ var fragment = context.getFragment(selection.name);
67
+ var nextFragment = transformNode(context, fragments, fragment);
68
+ fragments.set(selection.name, nextFragment);
69
+ }
70
+ if (fragments.get(selection.name)) {
71
+ nextSelection = selection;
72
+ }
73
+ break;
74
+ case 'FragmentSpread':
75
+ // Skip fragment spreads if the referenced fragment is empty
76
+ if (!fragments.has(selection.name)) {
77
+ var _fragment = context.getFragment(selection.name);
78
+ var _nextFragment = transformNode(context, fragments, _fragment);
79
+ fragments.set(selection.name, _nextFragment);
80
+ }
81
+ if (fragments.get(selection.name)) {
82
+ nextSelection = selection;
83
+ }
84
+ break;
85
+ case 'LinkedField':
61
86
  nextSelection = transformNode(context, fragments, selection);
62
- }
63
- } else if (selection.kind === 'FragmentSpread') {
64
- // Skip fragment spreads if the referenced fragment is empty
65
- if (!fragments.has(selection.name)) {
66
- var fragment = context.get(selection.name);
67
- require('fbjs/lib/invariant')(fragment && fragment.kind === 'Fragment', 'SkipUnreachableNodeTransform: Found a reference to undefined ' + 'fragment `%s`.', selection.name);
68
- var nextFragment = transformNode(context, fragments, fragment);
69
- fragments.set(selection.name, nextFragment);
70
- }
71
- if (fragments.get(selection.name)) {
87
+ break;
88
+ case 'InlineFragment':
89
+ // TODO combine with the LinkedField case when flow supports this
90
+ nextSelection = transformNode(context, fragments, selection);
91
+ break;
92
+ case 'ScalarField':
72
93
  nextSelection = selection;
73
- }
74
- } else if (selection.kind === 'LinkedField' || selection.kind === 'InlineFragment') {
75
- nextSelection = transformNode(context, fragments, selection);
76
- } else {
77
- // scalar field
78
- nextSelection = selection;
94
+ break;
95
+ default:
96
+ selection.kind;
97
+ require('fbjs/lib/invariant')(false, 'SkipUnreachableNodeTransform: Unexpected selection kind `%s`.', selection.kind);
79
98
  }
80
99
  if (nextSelection) {
81
100
  selections = selections || [];
@@ -101,4 +120,6 @@ function testCondition(condition) {
101
120
  return condition.condition.value === condition.passingValue ? PASS : FAIL;
102
121
  }
103
122
 
104
- module.exports = { transform: transform };
123
+ module.exports = {
124
+ transform: skipUnreachableNodeTransform
125
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Copyright (c) 2013-present, Facebook, Inc.
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
+ *
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
14
+
15
+ var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
16
+
17
+ var _toConsumableArray3 = _interopRequireDefault(require('babel-runtime/helpers/toConsumableArray'));
18
+
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20
+
21
+ function execFile(cmd, args) {
22
+ return new Promise(function (resolve, reject) {
23
+ require('child_process').execFile(cmd, args, function (err) {
24
+ if (err) {
25
+ reject(err);
26
+ } else {
27
+ resolve();
28
+ }
29
+ });
30
+ });
31
+ }
32
+
33
+ /**
34
+ * An abstraction over the source control system to make it injectable.
35
+ */
36
+
37
+
38
+ var SourceControlMercurial = {
39
+ addRemove: (() => {
40
+ var _ref = (0, _asyncToGenerator3.default)(function* (added, removed) {
41
+ // NOTE: Not using `hg addremove` as that has a bug when deleting a file
42
+ // that was just added, but not yet committed: T10711513
43
+ if (added.length > 0) {
44
+ yield execFile('hg', ['add'].concat((0, _toConsumableArray3['default'])(added)));
45
+ }
46
+ if (removed.length > 0) {
47
+ yield execFile('hg', ['forget'].concat((0, _toConsumableArray3['default'])(removed)));
48
+ }
49
+ });
50
+
51
+ function addRemove(_x, _x2) {
52
+ return _ref.apply(this, arguments);
53
+ }
54
+
55
+ return addRemove;
56
+ })()
57
+ };
58
+
59
+ module.exports = {
60
+ SourceControlMercurial: SourceControlMercurial
61
+ };
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Copyright (c) 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
3
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
8
6
  *
9
7
  * @providesModule StripUnusedVariablesTransform
10
8
  *
@@ -21,49 +19,96 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'd
21
19
  * A transform that removes variables from root queries that aren't referenced
22
20
  * by the query itself.
23
21
  */
24
- function transform(context) {
25
- return context.documents().reduce(function (ctx, node) {
26
- return ctx.add(node.kind === 'Root' ? transformRoot(context, node) : node);
27
- }, new (require('./RelayCompilerContext'))(context.schema));
28
- }
29
-
30
- function transformRoot(context, root) {
31
- var state = {
32
- referencedVariables: new Set()
33
- };
34
- var newContext = require('./RelayIRTransformer').transform(require('./filterContextForNode')(root, context), {
35
- Argument: visitArgument,
36
- Condition: visitCondition
37
- }, function () {
38
- return state;
22
+ function stripUnusedVariablesTransform(context) {
23
+ var fragmentToVariables = new Map();
24
+ var fragmentToFragmentSpreads = new Map();
25
+ var rootToVariables = new Map();
26
+ var rootToFragmentSpreads = new Map();
27
+ context.forEachDocument(function (document) {
28
+ var fragmentVariables = void 0;
29
+ var fragmentFragmentSpreads = void 0;
30
+ var rootVariables = void 0;
31
+ var rootFragmentSpreads = void 0;
32
+ require('./GraphQLIRVisitor').visit(document, {
33
+ Root: {
34
+ enter: function enter(root) {
35
+ rootVariables = new Set();
36
+ rootToVariables.set(root.name, rootVariables);
37
+ rootFragmentSpreads = new Set();
38
+ rootToFragmentSpreads.set(root.name, rootFragmentSpreads);
39
+ },
40
+ leave: function leave(root) {
41
+ rootVariables = null;
42
+ rootFragmentSpreads = null;
43
+ }
44
+ },
45
+ Fragment: {
46
+ enter: function enter(fragment) {
47
+ fragmentVariables = new Set();
48
+ fragmentToVariables.set(fragment.name, fragmentVariables);
49
+ fragmentFragmentSpreads = new Set();
50
+ fragmentToFragmentSpreads.set(fragment.name, fragmentFragmentSpreads);
51
+ },
52
+ leave: function leave(fragment) {
53
+ fragmentVariables = null;
54
+ fragmentFragmentSpreads = null;
55
+ }
56
+ },
57
+ Variable: function Variable(variable) {
58
+ fragmentVariables && fragmentVariables.add(variable.variableName);
59
+ rootVariables && rootVariables.add(variable.variableName);
60
+ },
61
+ FragmentSpread: function FragmentSpread(spread) {
62
+ fragmentFragmentSpreads && fragmentFragmentSpreads.add(spread.name);
63
+ rootFragmentSpreads && rootFragmentSpreads.add(spread.name);
64
+ }
65
+ });
39
66
  });
40
- var transformedNode = newContext.getRoot(root.name);
41
- /**
42
- * Remove the extraneous arguments *after* transform returns, since fragments
43
- * could be transformed after the root query.
44
- */
45
- return (0, _extends3['default'])({}, transformedNode, {
46
- argumentDefinitions: transformedNode.argumentDefinitions.filter(function (arg) {
47
- return state.referencedVariables.has(arg.name);
48
- })
67
+ var variablesMemo = new Map();
68
+ rootToVariables.forEach(function (variables, root) {
69
+ Array.from(require('./nullthrowsOSS')(rootToFragmentSpreads.get(root), 'root ' + root + ' wasn\'t found in StripUnusedVariablesTransform')).forEach(function (spread) {
70
+ return into(variables, allVariablesReferencedInFragment(variablesMemo, spread, fragmentToVariables, fragmentToFragmentSpreads));
71
+ });
72
+ });
73
+ return require('./GraphQLIRTransformer').transform(context, {
74
+ Root: function Root(root) {
75
+ return transformRoot(context, root, require('./nullthrowsOSS')(rootToVariables.get(root.name), 'root ' + root.name + ' wasn\'t found in StripUnusedVariablesTransform'));
76
+ },
77
+ // Include fragments, but do not traverse into them.
78
+ Fragment: function Fragment(id) {
79
+ return id;
80
+ }
49
81
  });
50
82
  }
51
83
 
52
- function visitArgument(argument, state) {
53
- var value = argument.value;
54
-
55
- if (value.kind === 'Variable') {
56
- state.referencedVariables.add(value.variableName);
84
+ function allVariablesReferencedInFragment(variablesMemo, fragment, fragmentToVariables, fragmentToFragmentSpreads) {
85
+ var variables = variablesMemo.get(fragment);
86
+ if (!variables) {
87
+ var directVariables = require('./nullthrowsOSS')(fragmentToVariables.get(fragment), 'fragment ' + fragment + ' wasn\'t found in StripUnusedVariablesTransform');
88
+ variables = Array.from(require('./nullthrowsOSS')(fragmentToFragmentSpreads.get(fragment), 'fragment ' + fragment + ' wasn\'t found in StripUnusedVariablesTransform')).reduce(function (allVariables, fragmentSpread) {
89
+ return into(allVariables, allVariablesReferencedInFragment(variablesMemo, fragmentSpread, fragmentToVariables, fragmentToFragmentSpreads));
90
+ }, directVariables);
91
+ variablesMemo.set(fragment, variables);
57
92
  }
58
- return argument;
93
+ return variables;
59
94
  }
60
95
 
61
- function visitCondition(condition, state) {
62
- var innerCondition = condition.condition;
63
- if (innerCondition.kind === 'Variable') {
64
- state.referencedVariables.add(innerCondition.variableName);
65
- }
66
- return condition;
96
+ function transformRoot(context, root, variables) {
97
+ return (0, _extends3['default'])({}, root, {
98
+ argumentDefinitions: root.argumentDefinitions.filter(function (arg) {
99
+ return variables.has(arg.name);
100
+ })
101
+ });
102
+ }
103
+
104
+ // Returns the union of setA and setB. Modifies setA!
105
+ function into(setA, setB) {
106
+ setB.forEach(function (item) {
107
+ return setA.add(item);
108
+ });
109
+ return setA;
67
110
  }
68
111
 
69
- module.exports = { transform: transform };
112
+ module.exports = {
113
+ transform: stripUnusedVariablesTransform
114
+ };
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Copyright (c) 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
3
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
8
6
  *
9
7
  * @providesModule areEqualOSS
10
8
  *
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Copyright (c) 2013-present, Facebook, Inc.
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
+ *
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ var _toConsumableArray3 = _interopRequireDefault(require('babel-runtime/helpers/toConsumableArray'));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16
+
17
+ var _require = require('./GraphQLCompilerPublic'),
18
+ Profiler = _require.Profiler;
19
+
20
+ // TODO T21875029 relay-runtime
21
+
22
+
23
+ /**
24
+ * Transforms the provided compiler context
25
+ *
26
+ * compileRelayArtifacts generates artifacts for Relay's runtime as a result of
27
+ * applying a series of transforms. Each kind of artifact is dependent on
28
+ * transforms being applied in the following order:
29
+ *
30
+ * - Fragment Readers: commonTransforms, fragmentTransforms
31
+ * - Operation Writers: commonTransforms, queryTransforms, codegenTransforms
32
+ * - GraphQL Text: commonTransforms, queryTransforms, printTransforms
33
+ *
34
+ * The order of the transforms applied for each artifact below is important.
35
+ * CompilerContext will memoize applying each transform, so while
36
+ * `commonTransforms` appears in each artifacts' application, it will not result
37
+ * in repeated work as long as the order remains consistent across each context.
38
+ */
39
+ function compileRelayArtifacts(context, transforms, reporter) {
40
+ return Profiler.run('GraphQLCompiler.compile', function () {
41
+ // The fragment is used for reading data from the normalized store.
42
+ var fragmentContext = context.applyTransforms([].concat((0, _toConsumableArray3['default'])(transforms.commonTransforms), (0, _toConsumableArray3['default'])(transforms.fragmentTransforms)), reporter);
43
+
44
+ // The unflattened query is used for printing, since flattening creates an
45
+ // invalid query.
46
+ var printContext = context.applyTransforms([].concat((0, _toConsumableArray3['default'])(transforms.commonTransforms), (0, _toConsumableArray3['default'])(transforms.queryTransforms), (0, _toConsumableArray3['default'])(transforms.printTransforms)), reporter);
47
+
48
+ // The flattened query is used for codegen in order to reduce the number of
49
+ // duplicate fields that must be processed during response normalization.
50
+ var codeGenContext = context.applyTransforms([].concat((0, _toConsumableArray3['default'])(transforms.commonTransforms), (0, _toConsumableArray3['default'])(transforms.queryTransforms), (0, _toConsumableArray3['default'])(transforms.codegenTransforms)), reporter);
51
+
52
+ return fragmentContext.documents().map(function (node) {
53
+ return require('./RelayCodeGenerator').generate(node.kind === 'Fragment' ? node : {
54
+ kind: 'Batch',
55
+ metadata: codeGenContext.getRoot(node.name).metadata || {},
56
+ name: node.name,
57
+ fragment: {
58
+ kind: 'Fragment',
59
+ argumentDefinitions: node.argumentDefinitions,
60
+ directives: node.directives,
61
+ metadata: null,
62
+ name: node.name,
63
+ selections: node.selections,
64
+ type: node.type
65
+ },
66
+ requests: require('./requestsForOperation')(printContext, codeGenContext, node.name)
67
+ });
68
+ });
69
+ });
70
+ }
71
+
72
+ module.exports = compileRelayArtifacts;
package/lib/dedent.js CHANGED
@@ -1,12 +1,9 @@
1
1
  /**
2
2
  * Copyright (c) 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
3
  *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
8
6
  *
9
- * @providesModule dedent
10
7
  *
11
8
  * @format
12
9
  */
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Copyright (c) 2013-present, Facebook, Inc.
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
+ * @providesModule dedupeJSONStringify
8
+ *
9
+ * @format
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ /**
15
+ * This function works similar to JSON.stringify except that for the case there
16
+ * are multiple common subtrees, it generates a string for a IIFE that re-uses
17
+ * the same objects for the duplicate subtrees.
18
+ */
19
+
20
+ function dedupeJSONStringify(jsonValue) {
21
+ var metadataForHash = new Map();
22
+ var metadataForVal = new WeakMap();
23
+ var varDefs = [];
24
+ collectMetadata(jsonValue);
25
+ collectDuplicates(jsonValue);
26
+ var code = printJSCode(false, '', jsonValue);
27
+ return varDefs.length === 0 ? code : '(function(){\nvar ' + varDefs.join(',\n') + ';\nreturn ' + code + ';\n})()';
28
+
29
+ // Collect common metadata for each object in the value tree, ensuring that
30
+ // equivalent values have the *same reference* to the same metadata. Note that
31
+ // the hashes generated are not exactly JSON, but still identify equivalent
32
+ // values. Runs in linear time due to hashing in a bottom-up recursion.
33
+ function collectMetadata(value) {
34
+ if (value == null || typeof value !== 'object') {
35
+ return JSON.stringify(value);
36
+ }
37
+ var hash = void 0;
38
+ if (Array.isArray(value)) {
39
+ hash = '[';
40
+ for (var i = 0; i < value.length; i++) {
41
+ hash += collectMetadata(value[i]) + ',';
42
+ }
43
+ } else {
44
+ hash = '{';
45
+ for (var k in value) {
46
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
47
+ hash += k + ':' + collectMetadata(value[k]) + ',';
48
+ }
49
+ }
50
+ }
51
+ var metadata = metadataForHash.get(hash);
52
+ if (!metadata) {
53
+ metadata = { value: value, hash: hash, isDuplicate: false };
54
+ metadataForHash.set(hash, metadata);
55
+ }
56
+ metadataForVal.set(value, metadata);
57
+ return hash;
58
+ }
59
+
60
+ // Using top-down recursion, linearly scan the JSON tree to determine which
61
+ // values should be deduplicated.
62
+ function collectDuplicates(value) {
63
+ if (value == null || typeof value !== 'object') {
64
+ return;
65
+ }
66
+ var metadata = metadataForVal.get(value);
67
+ // Only consider duplicates with hashes longer than 2 (excludes [] and {}).
68
+ if (metadata && metadata.value !== value && metadata.hash.length > 2) {
69
+ metadata.isDuplicate = true;
70
+ return;
71
+ }
72
+ if (Array.isArray(value)) {
73
+ for (var i = 0; i < value.length; i++) {
74
+ collectDuplicates(value[i]);
75
+ }
76
+ } else {
77
+ for (var k in value) {
78
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
79
+ collectDuplicates(value[k]);
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ // Stringify JS, replacing duplicates with variable references.
86
+ function printJSCode(isDupedVar, depth, value) {
87
+ if (value == null || typeof value !== 'object') {
88
+ return JSON.stringify(value);
89
+ }
90
+ // Only use variable references at depth beyond the top level.
91
+ if (depth !== '') {
92
+ var metadata = metadataForVal.get(value);
93
+ if (metadata && metadata.isDuplicate) {
94
+ if (!metadata.varName) {
95
+ var refCode = printJSCode(true, '', value);
96
+ metadata.varName = 'v' + varDefs.length;
97
+ varDefs.push(metadata.varName + ' = ' + refCode);
98
+ }
99
+ return metadata.varName;
100
+ }
101
+ }
102
+ var str = void 0;
103
+ var isEmpty = true;
104
+ var depth2 = depth + ' ';
105
+ if (Array.isArray(value)) {
106
+ // Empty arrays can only have one inferred flow type and then conflict if
107
+ // used in different places, this is unsound if we would write to them but
108
+ // this whole module is based on the idea of a read only JSON tree.
109
+ if (isDupedVar && value.length === 0) {
110
+ return '([]/*: any*/)';
111
+ }
112
+ str = '[';
113
+ for (var i = 0; i < value.length; i++) {
114
+ str += (isEmpty ? '\n' : ',\n') + depth2 + printJSCode(isDupedVar, depth2, value[i]);
115
+ isEmpty = false;
116
+ }
117
+ str += isEmpty ? ']' : '\n' + depth + ']';
118
+ } else {
119
+ str = '{';
120
+ for (var k in value) {
121
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
122
+ str += (isEmpty ? '\n' : ',\n') + depth2 + JSON.stringify(k) + ': ' + printJSCode(isDupedVar, depth2, value[k]);
123
+ isEmpty = false;
124
+ }
125
+ }
126
+ str += isEmpty ? '}' : '\n' + depth + '}';
127
+ }
128
+ return str;
129
+ }
130
+ }
131
+
132
+ module.exports = dedupeJSONStringify;