relay-compiler 8.0.0 → 10.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. package/bin/RelayCompilerBin.js.flow +169 -0
  2. package/bin/RelayCompilerMain.js.flow +515 -0
  3. package/bin/__fixtures__/plugin-module.js.flow +17 -0
  4. package/bin/relay-compiler +8930 -8967
  5. package/codegen/CodegenDirectory.js.flow +375 -0
  6. package/codegen/CodegenRunner.js.flow +432 -0
  7. package/codegen/CodegenTypes.js.flow +28 -0
  8. package/codegen/CodegenWatcher.js.flow +254 -0
  9. package/codegen/NormalizationCodeGenerator.js.flow +563 -0
  10. package/codegen/ReaderCodeGenerator.js.flow +477 -0
  11. package/codegen/RelayCodeGenerator.js.flow +85 -0
  12. package/codegen/RelayFileWriter.js.flow +365 -0
  13. package/codegen/SourceControl.js.flow +58 -0
  14. package/codegen/compileRelayArtifacts.js.flow +182 -0
  15. package/codegen/createPrintRequireModuleDependency.js.flow +21 -0
  16. package/codegen/sortObjectByKey.js.flow +25 -0
  17. package/codegen/writeRelayGeneratedFile.js.flow +223 -0
  18. package/core/ASTCache.js.flow +73 -0
  19. package/core/ASTConvert.js.flow +233 -0
  20. package/core/CompilerContext.js.flow +190 -0
  21. package/core/CompilerError.js.flow +250 -0
  22. package/core/DotGraphQLParser.js.flow +39 -0
  23. package/core/GraphQLCompilerProfiler.js.flow +341 -0
  24. package/core/GraphQLDerivedFromMetadata.js.flow +36 -0
  25. package/core/GraphQLWatchmanClient.js.flow +111 -0
  26. package/core/IR.js.flow +327 -0
  27. package/core/IRPrinter.js.flow +482 -0
  28. package/core/IRTransformer.js.flow +377 -0
  29. package/core/IRValidator.js.flow +260 -0
  30. package/core/IRVisitor.js.flow +150 -0
  31. package/core/JSModuleParser.js.flow +24 -0
  32. package/core/RelayCompilerScope.js.flow +199 -0
  33. package/core/RelayFindGraphQLTags.js.flow +119 -0
  34. package/core/RelayGraphQLEnumsGenerator.js.flow +55 -0
  35. package/core/RelayIRTransforms.js.flow +131 -0
  36. package/core/RelayParser.js.flow +1731 -0
  37. package/core/RelaySourceModuleParser.js.flow +135 -0
  38. package/core/Schema.js.flow +1983 -0
  39. package/core/SchemaUtils.js.flow +120 -0
  40. package/core/filterContextForNode.js.flow +50 -0
  41. package/core/getFieldDefinition.js.flow +156 -0
  42. package/core/getIdentifierForArgumentValue.js.flow +49 -0
  43. package/core/getIdentifierForSelection.js.flow +69 -0
  44. package/core/getLiteralArgumentValues.js.flow +32 -0
  45. package/core/getNormalizationOperationName.js.flow +19 -0
  46. package/core/inferRootArgumentDefinitions.js.flow +323 -0
  47. package/index.js +1 -1
  48. package/index.js.flow +200 -0
  49. package/language/RelayLanguagePluginInterface.js.flow +283 -0
  50. package/language/javascript/FindGraphQLTags.js.flow +232 -0
  51. package/language/javascript/RelayFlowBabelFactories.js.flow +180 -0
  52. package/language/javascript/RelayFlowGenerator.js.flow +1042 -0
  53. package/language/javascript/RelayFlowTypeTransformers.js.flow +184 -0
  54. package/language/javascript/RelayLanguagePluginJavaScript.js.flow +34 -0
  55. package/language/javascript/formatGeneratedModule.js.flow +65 -0
  56. package/lib/bin/RelayCompilerBin.js +24 -7
  57. package/lib/bin/RelayCompilerMain.js +141 -136
  58. package/lib/codegen/CodegenDirectory.js +13 -8
  59. package/lib/codegen/CodegenRunner.js +37 -76
  60. package/lib/codegen/CodegenWatcher.js +13 -21
  61. package/lib/codegen/NormalizationCodeGenerator.js +117 -140
  62. package/lib/codegen/ReaderCodeGenerator.js +76 -117
  63. package/lib/codegen/RelayCodeGenerator.js +17 -6
  64. package/lib/codegen/RelayFileWriter.js +19 -40
  65. package/lib/codegen/compileRelayArtifacts.js +16 -30
  66. package/lib/codegen/sortObjectByKey.js +43 -0
  67. package/lib/codegen/writeRelayGeneratedFile.js +86 -95
  68. package/lib/core/ASTCache.js +2 -4
  69. package/lib/core/CompilerContext.js +2 -4
  70. package/lib/core/CompilerError.js +27 -54
  71. package/lib/core/GraphQLCompilerProfiler.js +8 -12
  72. package/lib/core/GraphQLDerivedFromMetadata.js +1 -10
  73. package/lib/core/GraphQLWatchmanClient.js +4 -12
  74. package/lib/core/IRPrinter.js +23 -21
  75. package/lib/core/IRTransformer.js +8 -16
  76. package/lib/core/IRValidator.js +1 -9
  77. package/lib/core/IRVisitor.js +0 -2
  78. package/lib/core/RelayCompilerScope.js +4 -4
  79. package/lib/core/RelayGraphQLEnumsGenerator.js +12 -15
  80. package/lib/core/RelayIRTransforms.js +16 -14
  81. package/lib/core/RelayParser.js +53 -89
  82. package/lib/core/RelaySourceModuleParser.js +3 -3
  83. package/lib/core/Schema.js +61 -73
  84. package/lib/core/SchemaUtils.js +15 -1
  85. package/lib/core/getFieldDefinition.js +12 -15
  86. package/lib/core/getIdentifierForSelection.js +2 -4
  87. package/lib/core/inferRootArgumentDefinitions.js +33 -73
  88. package/lib/index.js +4 -5
  89. package/lib/language/javascript/FindGraphQLTags.js +4 -3
  90. package/lib/language/javascript/RelayFlowGenerator.js +82 -171
  91. package/lib/language/javascript/RelayFlowTypeTransformers.js +1 -3
  92. package/lib/language/javascript/RelayLanguagePluginJavaScript.js +6 -4
  93. package/lib/language/javascript/formatGeneratedModule.js +11 -2
  94. package/lib/reporters/ConsoleReporter.js +1 -3
  95. package/lib/reporters/MultiReporter.js +1 -3
  96. package/lib/runner/Artifacts.js +69 -170
  97. package/lib/runner/BufferedFilesystem.js +32 -66
  98. package/lib/runner/GraphQLASTNodeGroup.js +54 -120
  99. package/lib/runner/GraphQLNodeMap.js +14 -19
  100. package/lib/runner/Sources.js +51 -85
  101. package/lib/runner/StrictMap.js +21 -37
  102. package/lib/runner/getChangedNodeNames.js +30 -62
  103. package/lib/transforms/ApplyFragmentArgumentTransform.js +73 -59
  104. package/lib/transforms/ClientExtensionsTransform.js +12 -16
  105. package/lib/transforms/ConnectionTransform.js +30 -37
  106. package/lib/transforms/DeclarativeConnectionMutationTransform.js +167 -0
  107. package/lib/transforms/DeferStreamTransform.js +30 -73
  108. package/lib/transforms/DisallowTypenameOnRoot.js +55 -0
  109. package/lib/transforms/FieldHandleTransform.js +6 -2
  110. package/lib/transforms/FlattenTransform.js +18 -45
  111. package/lib/transforms/GenerateIDFieldTransform.js +56 -35
  112. package/lib/transforms/GenerateTypeNameTransform.js +84 -10
  113. package/lib/transforms/InlineDataFragmentTransform.js +9 -4
  114. package/lib/transforms/MaskTransform.js +17 -17
  115. package/lib/transforms/MatchTransform.js +110 -32
  116. package/lib/transforms/RefetchableFragmentTransform.js +21 -38
  117. package/lib/transforms/RelayDirectiveTransform.js +8 -3
  118. package/lib/transforms/SkipClientExtensionsTransform.js +8 -0
  119. package/lib/transforms/SkipHandleFieldTransform.js +6 -2
  120. package/lib/transforms/SkipRedundantNodesTransform.js +7 -4
  121. package/lib/transforms/SkipSplitOperationTransform.js +32 -0
  122. package/lib/transforms/SkipUnreachableNodeTransform.js +9 -10
  123. package/lib/transforms/SkipUnusedVariablesTransform.js +18 -17
  124. package/lib/transforms/SplitModuleImportTransform.js +2 -2
  125. package/lib/transforms/TestOperationTransform.js +26 -22
  126. package/lib/transforms/ValidateGlobalVariablesTransform.js +18 -30
  127. package/lib/transforms/ValidateRequiredArgumentsTransform.js +12 -16
  128. package/lib/transforms/ValidateServerOnlyDirectivesTransform.js +16 -30
  129. package/lib/transforms/ValidateUnusedVariablesTransform.js +18 -30
  130. package/lib/transforms/query-generators/FetchableQueryGenerator.js +161 -0
  131. package/lib/transforms/query-generators/NodeQueryGenerator.js +22 -3
  132. package/lib/transforms/query-generators/QueryQueryGenerator.js +2 -1
  133. package/lib/transforms/query-generators/ViewerQueryGenerator.js +1 -0
  134. package/lib/transforms/query-generators/index.js +23 -6
  135. package/lib/transforms/query-generators/utils.js +17 -16
  136. package/lib/util/RelayCompilerCache.js +2 -4
  137. package/lib/util/argumentContainsVariables.js +37 -0
  138. package/lib/util/dedupeJSONStringify.js +15 -12
  139. package/lib/util/generateAbstractTypeRefinementKey.js +24 -0
  140. package/lib/util/getModuleName.js +3 -5
  141. package/lib/util/joinArgumentDefinitions.js +3 -1
  142. package/package.json +6 -6
  143. package/relay-compiler.js +4 -4
  144. package/relay-compiler.min.js +4 -4
  145. package/reporters/ConsoleReporter.js.flow +81 -0
  146. package/reporters/MultiReporter.js.flow +43 -0
  147. package/reporters/Reporter.js.flow +19 -0
  148. package/runner/Artifacts.js.flow +219 -0
  149. package/runner/BufferedFilesystem.js.flow +194 -0
  150. package/runner/GraphQLASTNodeGroup.js.flow +176 -0
  151. package/runner/GraphQLASTUtils.js.flow +26 -0
  152. package/runner/GraphQLNodeMap.js.flow +55 -0
  153. package/runner/Sources.js.flow +214 -0
  154. package/runner/StrictMap.js.flow +96 -0
  155. package/runner/compileArtifacts.js.flow +76 -0
  156. package/runner/extractAST.js.flow +100 -0
  157. package/runner/getChangedNodeNames.js.flow +48 -0
  158. package/runner/getSchemaInstance.js.flow +36 -0
  159. package/runner/types.js.flow +37 -0
  160. package/transforms/ApplyFragmentArgumentTransform.js.flow +526 -0
  161. package/transforms/ClientExtensionsTransform.js.flow +222 -0
  162. package/transforms/ConnectionTransform.js.flow +856 -0
  163. package/transforms/DeclarativeConnectionMutationTransform.js.flow +157 -0
  164. package/transforms/DeferStreamTransform.js.flow +265 -0
  165. package/transforms/DisallowIdAsAlias.js.flow +47 -0
  166. package/transforms/DisallowTypenameOnRoot.js.flow +45 -0
  167. package/transforms/FieldHandleTransform.js.flow +80 -0
  168. package/transforms/FilterDirectivesTransform.js.flow +45 -0
  169. package/transforms/FlattenTransform.js.flow +453 -0
  170. package/transforms/GenerateIDFieldTransform.js.flow +152 -0
  171. package/transforms/GenerateTypeNameTransform.js.flow +161 -0
  172. package/transforms/InlineDataFragmentTransform.js.flow +125 -0
  173. package/transforms/InlineFragmentsTransform.js.flow +71 -0
  174. package/transforms/MaskTransform.js.flow +126 -0
  175. package/transforms/MatchTransform.js.flow +583 -0
  176. package/transforms/RefetchableFragmentTransform.js.flow +272 -0
  177. package/transforms/RelayDirectiveTransform.js.flow +97 -0
  178. package/transforms/SkipClientExtensionsTransform.js.flow +54 -0
  179. package/transforms/SkipHandleFieldTransform.js.flow +44 -0
  180. package/transforms/SkipRedundantNodesTransform.js.flow +254 -0
  181. package/transforms/SkipSplitOperationTransform.js.flow +37 -0
  182. package/transforms/SkipUnreachableNodeTransform.js.flow +149 -0
  183. package/transforms/SkipUnusedVariablesTransform.js.flow +59 -0
  184. package/transforms/SplitModuleImportTransform.js.flow +98 -0
  185. package/transforms/TestOperationTransform.js.flow +142 -0
  186. package/transforms/TransformUtils.js.flow +26 -0
  187. package/transforms/ValidateGlobalVariablesTransform.js.flow +81 -0
  188. package/transforms/ValidateRequiredArgumentsTransform.js.flow +127 -0
  189. package/transforms/ValidateServerOnlyDirectivesTransform.js.flow +112 -0
  190. package/transforms/ValidateUnusedVariablesTransform.js.flow +89 -0
  191. package/transforms/query-generators/FetchableQueryGenerator.js.flow +189 -0
  192. package/transforms/query-generators/NodeQueryGenerator.js.flow +219 -0
  193. package/transforms/query-generators/QueryQueryGenerator.js.flow +57 -0
  194. package/transforms/query-generators/ViewerQueryGenerator.js.flow +97 -0
  195. package/transforms/query-generators/index.js.flow +90 -0
  196. package/transforms/query-generators/utils.js.flow +76 -0
  197. package/util/CodeMarker.js.flow +79 -0
  198. package/{lib/core/GraphQLIR.js → util/DefaultHandleKey.js.flow} +9 -2
  199. package/util/RelayCompilerCache.js.flow +88 -0
  200. package/util/Rollout.js.flow +39 -0
  201. package/util/TimeReporter.js.flow +79 -0
  202. package/util/areEqualOSS.js.flow +123 -0
  203. package/util/argumentContainsVariables.js.flow +38 -0
  204. package/util/dedupeJSONStringify.js.flow +152 -0
  205. package/util/generateAbstractTypeRefinementKey.js.flow +29 -0
  206. package/util/getDefinitionNodeHash.js.flow +25 -0
  207. package/util/getModuleName.js.flow +39 -0
  208. package/util/joinArgumentDefinitions.js.flow +105 -0
  209. package/util/md5.js.flow +22 -0
  210. package/util/murmurHash.js.flow +94 -0
  211. package/util/nullthrowsOSS.js.flow +25 -0
  212. package/util/orList.js.flow +37 -0
  213. package/util/partitionArray.js.flow +37 -0
  214. package/lib/core/GraphQLCompilerContext.js +0 -165
  215. package/lib/core/GraphQLIRPrinter.js +0 -371
  216. package/lib/core/GraphQLIRTransformer.js +0 -344
  217. package/lib/core/GraphQLIRValidator.js +0 -218
  218. package/lib/core/GraphQLIRVisitor.js +0 -46
  219. package/lib/core/RelayCompilerError.js +0 -277
  220. package/lib/transforms/ConnectionFieldTransform.js +0 -276
@@ -0,0 +1,76 @@
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
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ import type {
16
+ ArgumentDefinition,
17
+ Fragment,
18
+ FragmentSpread,
19
+ LocalArgumentDefinition,
20
+ } from '../../core/IR';
21
+
22
+ function buildFragmentSpread(fragment: Fragment): FragmentSpread {
23
+ const args = [];
24
+ for (const argDef of fragment.argumentDefinitions) {
25
+ if (argDef.kind !== 'LocalArgumentDefinition') {
26
+ continue;
27
+ }
28
+ args.push({
29
+ kind: 'Argument',
30
+ loc: {kind: 'Derived', source: argDef.loc},
31
+ name: argDef.name,
32
+ type: argDef.type,
33
+ value: {
34
+ kind: 'Variable',
35
+ loc: {kind: 'Derived', source: argDef.loc},
36
+ variableName: argDef.name,
37
+ type: argDef.type,
38
+ },
39
+ });
40
+ }
41
+ return {
42
+ args,
43
+ directives: [],
44
+ kind: 'FragmentSpread',
45
+ loc: {kind: 'Derived', source: fragment.loc},
46
+ metadata: null,
47
+ name: fragment.name,
48
+ };
49
+ }
50
+
51
+ function buildOperationArgumentDefinitions(
52
+ argumentDefinitions: $ReadOnlyArray<ArgumentDefinition>,
53
+ ): $ReadOnlyArray<LocalArgumentDefinition> {
54
+ const localArgumentDefinitions = argumentDefinitions.map(argDef => {
55
+ if (argDef.kind === 'LocalArgumentDefinition') {
56
+ return argDef;
57
+ } else {
58
+ return {
59
+ kind: 'LocalArgumentDefinition',
60
+ name: argDef.name,
61
+ type: argDef.type,
62
+ defaultValue: null,
63
+ loc: argDef.loc,
64
+ };
65
+ }
66
+ });
67
+ localArgumentDefinitions.sort((a, b) => {
68
+ return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
69
+ });
70
+ return localArgumentDefinitions;
71
+ }
72
+
73
+ module.exports = {
74
+ buildFragmentSpread,
75
+ buildOperationArgumentDefinitions,
76
+ };
@@ -0,0 +1,79 @@
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
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ /**
16
+ * Marks a string of code as code to be replaced later.
17
+ */
18
+ function moduleDependency(code: string): string {
19
+ return `@@MODULE_START@@${code}@@MODULE_END@@`;
20
+ }
21
+
22
+ /**
23
+ * After JSON.stringify'ing some code that contained parts marked with `mark()`,
24
+ * this post-processes the JSON to convert the marked code strings to raw code.
25
+ *
26
+ * Example:
27
+ * CodeMarker.postProcess(
28
+ * JSON.stringify({code: CodeMarker.mark('alert(1)')})
29
+ * )
30
+ */
31
+ function postProcess(json: string, printModule: string => string): string {
32
+ return json.replace(
33
+ /"@@MODULE_START@@(.*?)@@MODULE_END@@"/g,
34
+ (_, moduleName) => printModule(moduleName),
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Transforms a value such that any transitive CodeMarker strings are replaced
40
+ * with the value of the named module in the given module map.
41
+ */
42
+ function transform(node: mixed, moduleMap: {[string]: mixed, ...}): mixed {
43
+ if (node == null) {
44
+ return node;
45
+ } else if (Array.isArray(node)) {
46
+ return node.map(item => transform(item, moduleMap));
47
+ } else if (typeof node === 'object') {
48
+ const next = {};
49
+ Object.keys(node).forEach(key => {
50
+ next[key] = transform(node[key], moduleMap);
51
+ });
52
+ return next;
53
+ } else if (typeof node === 'string') {
54
+ const match = /^@@MODULE_START@@(.*?)@@MODULE_END@@$/.exec(node);
55
+ if (match != null) {
56
+ const moduleName = match[1];
57
+ if (moduleMap.hasOwnProperty(moduleName)) {
58
+ return moduleMap[moduleName];
59
+ } else {
60
+ throw new Error(
61
+ `Could not find a value for CodeMarker value '${moduleName}', ` +
62
+ 'make sure to supply one in the module mapping.',
63
+ );
64
+ }
65
+ } else if (node.indexOf('@@MODULE_START') >= 0) {
66
+ throw new Error(`Found unprocessed CodeMarker value '${node}'.`);
67
+ }
68
+ return node;
69
+ } else {
70
+ // mixed
71
+ return node;
72
+ }
73
+ }
74
+
75
+ module.exports = {
76
+ moduleDependency,
77
+ postProcess,
78
+ transform,
79
+ };
@@ -4,7 +4,14 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- *
7
+ * @flow strict
8
8
  * @format
9
9
  */
10
- 'use strict';
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ module.exports = {
16
+ DEFAULT_HANDLE_KEY: '',
17
+ };
@@ -0,0 +1,88 @@
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
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ const Profiler = require('../core/GraphQLCompilerProfiler');
16
+
17
+ const crypto = require('crypto');
18
+ const fs = require('fs');
19
+ const os = require('os');
20
+ const path = require('path');
21
+
22
+ /**
23
+ * A file backed cache. Values are JSON encoded on disk, so only JSON
24
+ * serializable values should be used.
25
+ */
26
+ class RelayCompilerCache<T> {
27
+ _name: string;
28
+ _cacheBreaker: string;
29
+ _dir: ?string = null;
30
+
31
+ /**
32
+ * @param name Human readable identifier for the cache
33
+ * @param cacheBreaker This should be changed in order to invalidate existing
34
+ * caches.
35
+ */
36
+ constructor(name: string, cacheBreaker: string) {
37
+ this._name = name;
38
+ this._cacheBreaker = cacheBreaker;
39
+ }
40
+
41
+ _getFile(key: string): string {
42
+ if (this._dir == null) {
43
+ // Include username in the cache dir to avoid issues with directories being
44
+ // owned by a different user.
45
+ const username = os.userInfo().username;
46
+ const cacheID = crypto
47
+ .createHash('md5')
48
+ .update(this._cacheBreaker)
49
+ .update(username)
50
+ .digest('hex');
51
+ const dir = path.join(os.tmpdir(), `${this._name}-${cacheID}`);
52
+ if (!fs.existsSync(dir)) {
53
+ try {
54
+ fs.mkdirSync(dir);
55
+ } catch (error) {
56
+ if (error.code !== 'EEXIST') {
57
+ throw error;
58
+ }
59
+ }
60
+ }
61
+ this._dir = dir;
62
+ }
63
+ return path.join(this._dir, key);
64
+ }
65
+
66
+ getOrCompute(key: string, compute: () => T): T {
67
+ return Profiler.run('RelayCompilerCache.getOrCompute', () => {
68
+ const cacheFile = this._getFile(key);
69
+ if (fs.existsSync(cacheFile)) {
70
+ try {
71
+ return JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
72
+ } catch {
73
+ // ignore
74
+ }
75
+ }
76
+ const value = compute();
77
+ try {
78
+ // $FlowFixMe[incompatible-call] JSON.stringify can return undefined
79
+ fs.writeFileSync(cacheFile, JSON.stringify(value), 'utf8');
80
+ } catch {
81
+ // ignore
82
+ }
83
+ return value;
84
+ });
85
+ }
86
+ }
87
+
88
+ module.exports = RelayCompilerCache;
@@ -0,0 +1,39 @@
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
+ * @flow strict
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ let whitelistsByProject: ?Map<string, Set<string>> = null;
16
+
17
+ /**
18
+ * This module helps gradually rolling out changes to the code generation by
19
+ * gradually enabling more buckets representing randomly distributed artifacts.
20
+ */
21
+ function set(newWhitelistsByProject: Map<string, Set<string>>) {
22
+ whitelistsByProject = newWhitelistsByProject;
23
+ }
24
+
25
+ function check(project: string, key: string): boolean {
26
+ if (whitelistsByProject == null) {
27
+ return true;
28
+ }
29
+ const whitelist = whitelistsByProject.get(project);
30
+ if (whitelist == null) {
31
+ return true;
32
+ }
33
+ return whitelist.has(key);
34
+ }
35
+
36
+ module.exports = {
37
+ set,
38
+ check,
39
+ };
@@ -0,0 +1,79 @@
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
+ * @format
8
+ * @flow strict-local
9
+ * @emails oncall+relay
10
+ */
11
+
12
+ // flowlint ambiguous-object-type:error
13
+
14
+ 'use strict';
15
+
16
+ const {isPromise} = require('relay-runtime');
17
+
18
+ import type {Reporter} from '../reporters/Reporter';
19
+
20
+ function reportTime<T>(reporter: Reporter, message: string, fn: () => T): T {
21
+ return reportAndReturnTime(reporter, message, fn)[0];
22
+ }
23
+
24
+ function reportAndReturnTime<T>(
25
+ reporter: Reporter,
26
+ message: string,
27
+ fn: () => T,
28
+ ): [T, number] {
29
+ const startTime = Date.now();
30
+ const result = fn();
31
+ if (isPromise(result)) {
32
+ throw new Error(
33
+ 'reportAndReturnTime: fn(...) returned an unexpected promise.' +
34
+ ' Please use `reportAndReturnAsyncTime` method instead.',
35
+ );
36
+ }
37
+ const elapsedTime = Date.now() - startTime;
38
+ reporter.reportTime(message, elapsedTime);
39
+ return [result, elapsedTime];
40
+ }
41
+
42
+ async function reportAndReturnAsyncTime<T>(
43
+ reporter: Reporter,
44
+ message: string,
45
+ fn: () => ?Promise<T>,
46
+ ): Promise<[T, number]> {
47
+ const startTime = Date.now();
48
+ const promise = fn();
49
+ if (!isPromise(promise)) {
50
+ throw new Error('reportAsyncTime: fn(...) expected to return a promise.');
51
+ }
52
+ const result = await promise;
53
+ const elapsedTime = Date.now() - startTime;
54
+ reporter.reportTime(message, elapsedTime);
55
+ return [result, elapsedTime];
56
+ }
57
+
58
+ async function reportAsyncTime<T>(
59
+ reporter: Reporter,
60
+ message: string,
61
+ fn: () => ?Promise<T>,
62
+ ): Promise<T> {
63
+ const startTime = Date.now();
64
+ const promise = fn();
65
+ if (!isPromise(promise)) {
66
+ throw new Error('reportAsyncTime: fn(...) expected to return a promise.');
67
+ }
68
+ const result = await promise;
69
+ const elapsedTime = Date.now() - startTime;
70
+ reporter.reportTime(message, elapsedTime);
71
+ return result;
72
+ }
73
+
74
+ module.exports = {
75
+ reportTime,
76
+ reportAndReturnTime,
77
+ reportAsyncTime,
78
+ reportAndReturnAsyncTime,
79
+ };
@@ -0,0 +1,123 @@
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
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+ 'use strict';
13
+
14
+ const aStackPool = [];
15
+ const bStackPool = [];
16
+
17
+ /**
18
+ * Checks if two values are equal. Values may be primitives, arrays, or objects.
19
+ * Returns true if both arguments have the same keys and values.
20
+ *
21
+ * @see http://underscorejs.org
22
+ * @copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
23
+ * @license MIT
24
+ */
25
+ function areEqual(a: any, b: any): boolean {
26
+ const aStack = aStackPool.length ? aStackPool.pop() : [];
27
+ const bStack = bStackPool.length ? bStackPool.pop() : [];
28
+ const result = eq(a, b, aStack, bStack);
29
+ aStack.length = 0;
30
+ bStack.length = 0;
31
+ aStackPool.push(aStack);
32
+ bStackPool.push(bStack);
33
+ return result;
34
+ }
35
+
36
+ function eq(a: any, b: any, aStack: Array<any>, bStack: Array<any>): boolean {
37
+ if (a === b) {
38
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
39
+ return a !== 0 || 1 / a === 1 / b;
40
+ }
41
+ if (a == null || b == null) {
42
+ // a or b can be `null` or `undefined`
43
+ return false;
44
+ }
45
+ if (typeof a !== 'object' || typeof b !== 'object') {
46
+ return false;
47
+ }
48
+ const objToStr = Object.prototype.toString;
49
+ const className = objToStr.call(a);
50
+ if (className !== objToStr.call(b)) {
51
+ return false;
52
+ }
53
+ switch (className) {
54
+ case '[object String]':
55
+ return a === String(b);
56
+ case '[object Number]':
57
+ return isNaN(a) || isNaN(b) ? false : a === Number(b);
58
+ case '[object Date]':
59
+ case '[object Boolean]':
60
+ return +a === +b;
61
+ case '[object RegExp]':
62
+ return (
63
+ a.source === b.source &&
64
+ a.global === b.global &&
65
+ a.multiline === b.multiline &&
66
+ a.ignoreCase === b.ignoreCase
67
+ );
68
+ }
69
+ // Assume equality for cyclic structures.
70
+ let length = aStack.length;
71
+ while (length--) {
72
+ if (aStack[length] === a) {
73
+ return bStack[length] === b;
74
+ }
75
+ }
76
+ aStack.push(a);
77
+ bStack.push(b);
78
+ let size = 0;
79
+ // Recursively compare objects and arrays.
80
+ if (className === '[object Array]') {
81
+ size = a.length;
82
+ if (size !== b.length) {
83
+ return false;
84
+ }
85
+ // Deep compare the contents, ignoring non-numeric properties.
86
+ while (size--) {
87
+ if (!eq(a[size], b[size], aStack, bStack)) {
88
+ return false;
89
+ }
90
+ }
91
+ } else {
92
+ if (a.constructor !== b.constructor) {
93
+ return false;
94
+ }
95
+ if (a.hasOwnProperty('valueOf') && b.hasOwnProperty('valueOf')) {
96
+ return a.valueOf() === b.valueOf();
97
+ }
98
+ const keys = Object.keys(a);
99
+ if (keys.length !== Object.keys(b).length) {
100
+ return false;
101
+ }
102
+ for (let i = 0; i < keys.length; i++) {
103
+ if (keys[i] === '_owner') {
104
+ // HACK: Comparing deeply nested React trees is slow since you end up
105
+ // comparing the entire tree (all ancestors and all children) and
106
+ // likely not what you want if you're comparing two elements with
107
+ // areEqual. We bail out here for now.
108
+ continue;
109
+ }
110
+ if (
111
+ !b.hasOwnProperty(keys[i]) ||
112
+ !eq(a[keys[i]], b[keys[i]], aStack, bStack)
113
+ ) {
114
+ return false;
115
+ }
116
+ }
117
+ }
118
+ aStack.pop();
119
+ bStack.pop();
120
+ return true;
121
+ }
122
+
123
+ module.exports = areEqual;
@@ -0,0 +1,38 @@
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
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ import type {ReaderArgument, NormalizationArgument} from 'relay-runtime';
16
+
17
+ function argumentContainsVariables(
18
+ arg: ?(ReaderArgument | NormalizationArgument),
19
+ ): boolean {
20
+ if (arg == null) {
21
+ return false;
22
+ }
23
+ switch (arg.kind) {
24
+ case 'Variable':
25
+ return true;
26
+ case 'Literal':
27
+ return false;
28
+ case 'ListValue':
29
+ return arg.items.some(argumentContainsVariables);
30
+ case 'ObjectValue':
31
+ return arg.fields.some(argumentContainsVariables);
32
+ default:
33
+ (arg.kind: empty);
34
+ return false;
35
+ }
36
+ }
37
+
38
+ module.exports = argumentContainsVariables;
@@ -0,0 +1,152 @@
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
+ * @flow
8
+ * @format
9
+ */
10
+
11
+ // flowlint ambiguous-object-type:error
12
+
13
+ 'use strict';
14
+
15
+ /**
16
+ * This function works similar to JSON.stringify except that for the case there
17
+ * are multiple common subtrees, it generates a string for a IIFE that re-uses
18
+ * the same objects for the duplicate subtrees.
19
+ */
20
+ function dedupeJSONStringify(jsonValue: mixed): string {
21
+ const metadataForHash = new Map();
22
+ const metadataForVal = new WeakMap();
23
+ const varDefs = [];
24
+ collectMetadata(jsonValue);
25
+ collectDuplicates(jsonValue);
26
+ const code = printJSCode(false, '', jsonValue);
27
+ return varDefs.length === 0
28
+ ? code
29
+ : `(function(){\nvar ${varDefs.join(',\n')};\nreturn ${code};\n})()`;
30
+
31
+ // Collect common metadata for each object in the value tree, ensuring that
32
+ // equivalent values have the *same reference* to the same metadata. Note that
33
+ // the hashes generated are not exactly JSON, but still identify equivalent
34
+ // values. Runs in linear time due to hashing in a bottom-up recursion.
35
+ function collectMetadata(value): string {
36
+ if (value == null || typeof value !== 'object') {
37
+ // $FlowFixMe[incompatible-return] - JSON.stringify can return undefined
38
+ return JSON.stringify(value);
39
+ }
40
+ let hash;
41
+ if (Array.isArray(value)) {
42
+ hash = '[';
43
+ for (let i = 0; i < value.length; i++) {
44
+ hash += collectMetadata(value[i]) + ',';
45
+ }
46
+ } else {
47
+ hash = '{';
48
+ for (const k in value) {
49
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
50
+ hash += k + ':' + collectMetadata(value[k]) + ',';
51
+ }
52
+ }
53
+ }
54
+ let metadata = metadataForHash.get(hash);
55
+ if (!metadata) {
56
+ metadata = ({value, hash, count: 0}: {|
57
+ value: mixed,
58
+ hash: string,
59
+ count: number,
60
+ varName?: string,
61
+ |});
62
+ metadataForHash.set(hash, metadata);
63
+ }
64
+ metadataForVal.set(value, metadata);
65
+ return hash;
66
+ }
67
+
68
+ // Using top-down recursion, linearly scan the JSON tree to determine which
69
+ // values should be deduplicated.
70
+ function collectDuplicates(value) {
71
+ if (value == null || typeof value !== 'object') {
72
+ return;
73
+ }
74
+ const metadata = metadataForVal.get(value);
75
+ // Only consider duplicates with hashes longer than 2 (excludes [] and {}).
76
+ if (metadata && metadata.hash.length > 2) {
77
+ metadata.count++;
78
+ if (metadata.count > 1) {
79
+ return;
80
+ }
81
+ }
82
+ if (Array.isArray(value)) {
83
+ for (let i = 0; i < value.length; i++) {
84
+ collectDuplicates(value[i]);
85
+ }
86
+ } else {
87
+ for (const k in value) {
88
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
89
+ collectDuplicates(value[k]);
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ // Stringify JS, replacing duplicates with variable references.
96
+ function printJSCode(isDupedVar, depth, value): string {
97
+ if (value == null || typeof value !== 'object') {
98
+ // $FlowFixMe[incompatible-return] : JSON.stringify can return undefined
99
+ return JSON.stringify(value);
100
+ }
101
+ // Only use variable references at depth beyond the top level.
102
+ if (depth !== '') {
103
+ const metadata = metadataForVal.get(value);
104
+ if (metadata && metadata.count > 1) {
105
+ let varName = metadata.varName;
106
+ if (varName == null) {
107
+ const refCode = printJSCode(true, '', value);
108
+ varName = metadata.varName = 'v' + varDefs.length;
109
+ varDefs.push(metadata.varName + ' = ' + refCode);
110
+ }
111
+ return '(' + varName + '/*: any*/)';
112
+ }
113
+ }
114
+ let str;
115
+ let isEmpty = true;
116
+ const depth2 = depth + ' ';
117
+ if (Array.isArray(value)) {
118
+ // Empty arrays can only have one inferred flow type and then conflict if
119
+ // used in different places, this is unsound if we would write to them but
120
+ // this whole module is based on the idea of a read only JSON tree.
121
+ if (isDupedVar && value.length === 0) {
122
+ return '([]/*: any*/)';
123
+ }
124
+ str = '[';
125
+ for (let i = 0; i < value.length; i++) {
126
+ str +=
127
+ (isEmpty ? '\n' : ',\n') +
128
+ depth2 +
129
+ printJSCode(isDupedVar, depth2, value[i]);
130
+ isEmpty = false;
131
+ }
132
+ str += isEmpty ? ']' : `\n${depth}]`;
133
+ } else {
134
+ str = '{';
135
+ for (const k in value) {
136
+ if (value.hasOwnProperty(k) && value[k] !== undefined) {
137
+ str +=
138
+ (isEmpty ? '\n' : ',\n') +
139
+ depth2 +
140
+ JSON.stringify(k) +
141
+ ': ' +
142
+ printJSCode(isDupedVar, depth2, value[k]);
143
+ isEmpty = false;
144
+ }
145
+ }
146
+ str += isEmpty ? '}' : `\n${depth}}`;
147
+ }
148
+ return str;
149
+ }
150
+ }
151
+
152
+ module.exports = dedupeJSONStringify;