hermes-parser 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +3 -0
  2. package/dist/HermesASTAdapter.js +1 -1
  3. package/dist/HermesASTAdapter.js.flow +1 -1
  4. package/dist/HermesParser.js +2 -2
  5. package/dist/HermesParser.js.flow +2 -0
  6. package/dist/HermesParserDeserializer.js +0 -1
  7. package/dist/HermesParserDeserializer.js.flow +0 -1
  8. package/dist/HermesParserNodeDeserializers.js +109 -5
  9. package/dist/HermesParserWASM.js +1 -1
  10. package/dist/HermesParserWASM.js.flow +11 -1
  11. package/dist/ParserOptions.js +1 -1
  12. package/dist/ParserOptions.js.flow +10 -0
  13. package/dist/babel/TransformESTreeToBabel.js +79 -3
  14. package/dist/babel/TransformESTreeToBabel.js.flow +76 -2
  15. package/dist/estree/StripFlowTypes.js +1 -1
  16. package/dist/estree/StripFlowTypes.js.flow +1 -1
  17. package/dist/estree/{StripComponentSyntax.js → TransformComponentSyntax.js} +1 -1
  18. package/dist/estree/{StripComponentSyntax.js.flow → TransformComponentSyntax.js.flow} +1 -1
  19. package/dist/estree/TransformEnumSyntax.js +106 -0
  20. package/dist/estree/TransformEnumSyntax.js.flow +125 -0
  21. package/dist/estree/TransformMatchSyntax.js +124 -56
  22. package/dist/estree/TransformMatchSyntax.js.flow +124 -46
  23. package/dist/estree/TransformRecordSyntax.js +294 -0
  24. package/dist/estree/TransformRecordSyntax.js.flow +308 -0
  25. package/dist/generated/ESTreeVisitorKeys.js +16 -4
  26. package/dist/generated/ParserVisitorKeys.js +45 -4
  27. package/dist/index.js +13 -3
  28. package/dist/index.js.flow +13 -3
  29. package/dist/src/HermesASTAdapter.js +1 -1
  30. package/dist/src/HermesParser.js +2 -2
  31. package/dist/src/HermesParserDeserializer.js +0 -1
  32. package/dist/src/HermesParserNodeDeserializers.js +109 -5
  33. package/dist/src/ParserOptions.js +1 -1
  34. package/dist/src/babel/TransformESTreeToBabel.js +79 -3
  35. package/dist/src/estree/StripFlowTypes.js +1 -1
  36. package/dist/src/estree/{StripComponentSyntax.js → TransformComponentSyntax.js} +1 -1
  37. package/dist/src/estree/TransformEnumSyntax.js +106 -0
  38. package/dist/src/estree/TransformMatchSyntax.js +124 -56
  39. package/dist/src/estree/TransformRecordSyntax.js +294 -0
  40. package/dist/src/generated/ESTreeVisitorKeys.js +16 -4
  41. package/dist/src/generated/ParserVisitorKeys.js +45 -4
  42. package/dist/src/index.js +13 -3
  43. package/dist/src/transform/SimpleTransform.js +20 -4
  44. package/dist/src/transform/astNodeMutationHelpers.js +7 -2
  45. package/dist/src/utils/GenID.js +28 -23
  46. package/dist/src/utils/isReservedWord.js +62 -0
  47. package/dist/transform/SimpleTransform.js +20 -4
  48. package/dist/transform/SimpleTransform.js.flow +34 -8
  49. package/dist/transform/astNodeMutationHelpers.js +7 -2
  50. package/dist/transform/astNodeMutationHelpers.js.flow +10 -2
  51. package/dist/utils/GenID.js +28 -23
  52. package/dist/utils/GenID.js.flow +23 -22
  53. package/dist/utils/isReservedWord.js +62 -0
  54. package/dist/utils/isReservedWord.js.flow +57 -0
  55. package/package.json +2 -2
@@ -44,7 +44,16 @@ export type HermesParserWASM = $ReadOnly<{
44
44
  (
45
45
  'hermesParse',
46
46
  'number',
47
- ['number', 'number', 'number', 'number', 'number', 'number', 'number'],
47
+ [
48
+ 'number',
49
+ 'number',
50
+ 'number',
51
+ 'number',
52
+ 'number',
53
+ 'number',
54
+ 'number',
55
+ 'number',
56
+ ],
48
57
  ): (
49
58
  number,
50
59
  number,
@@ -53,6 +62,7 @@ export type HermesParserWASM = $ReadOnly<{
53
62
  CBoolean,
54
63
  CBoolean,
55
64
  CBoolean,
65
+ CBoolean,
56
66
  ) => number,
57
67
  ('hermesParseResult_free', 'void', ['number']): number => void,
58
68
  ('hermesParseResult_getError', 'string', ['number']): number => string,
@@ -14,5 +14,5 @@ exports.ParserOptionsKeys = void 0;
14
14
  *
15
15
  * @format
16
16
  */
17
- const ParserOptionsKeys = new Set(['allowReturnOutsideFunction', 'babel', 'flow', 'enableExperimentalComponentSyntax', 'enableExperimentalFlowMatchSyntax', 'reactRuntimeTarget', 'sourceFilename', 'sourceType', 'tokens']);
17
+ const ParserOptionsKeys = new Set(['allowReturnOutsideFunction', 'babel', 'flow', 'enableExperimentalComponentSyntax', 'enableExperimentalFlowMatchSyntax', 'enableExperimentalFlowRecordSyntax', 'reactRuntimeTarget', 'sourceFilename', 'sourceType', 'tokens', 'transformOptions']);
18
18
  exports.ParserOptionsKeys = ParserOptionsKeys;
@@ -8,16 +8,24 @@
8
8
  * @format
9
9
  */
10
10
 
11
+ import type {Expression} from 'hermes-estree';
12
+
11
13
  export type ParserOptions = {
12
14
  allowReturnOutsideFunction?: boolean,
13
15
  babel?: boolean,
14
16
  flow?: 'all' | 'detect',
15
17
  enableExperimentalComponentSyntax?: boolean,
16
18
  enableExperimentalFlowMatchSyntax?: boolean,
19
+ enableExperimentalFlowRecordSyntax?: boolean,
17
20
  reactRuntimeTarget?: '18' | '19',
18
21
  sourceFilename?: string,
19
22
  sourceType?: 'module' | 'script' | 'unambiguous',
20
23
  tokens?: boolean,
24
+ transformOptions?: {
25
+ +TransformEnumSyntax?: {
26
+ +getRuntime: () => Expression,
27
+ },
28
+ },
21
29
  };
22
30
 
23
31
  export const ParserOptionsKeys: $ReadOnlySet<$Keys<ParserOptions>> = new Set([
@@ -26,8 +34,10 @@ export const ParserOptionsKeys: $ReadOnlySet<$Keys<ParserOptions>> = new Set([
26
34
  'flow',
27
35
  'enableExperimentalComponentSyntax',
28
36
  'enableExperimentalFlowMatchSyntax',
37
+ 'enableExperimentalFlowRecordSyntax',
29
38
  'reactRuntimeTarget',
30
39
  'sourceFilename',
31
40
  'sourceType',
32
41
  'tokens',
42
+ 'transformOptions',
33
43
  ]);
@@ -30,6 +30,8 @@ const FlowESTreeAndBabelVisitorKeys = { ..._ESTreeVisitorKeys.default,
30
30
  BigIntLiteral: [],
31
31
  BlockStatement: ['directives', ..._ESTreeVisitorKeys.default.BlockStatement],
32
32
  BooleanLiteral: [],
33
+ ClassExpression: ['superTypeParameters', ..._ESTreeVisitorKeys.default.ClassExpression],
34
+ ClassDeclaration: ['superTypeParameters', ..._ESTreeVisitorKeys.default.ClassDeclaration],
33
35
  ClassMethod: ['key', 'params', 'body', 'returnType', 'typeParameters'],
34
36
  ClassPrivateMethod: ['key', 'params', 'body', 'returnType', 'typeParameters'],
35
37
  ClassProperty: ['key', 'value', 'typeAnnotation', 'variance'],
@@ -50,6 +52,7 @@ const FlowESTreeAndBabelVisitorKeys = { ..._ESTreeVisitorKeys.default,
50
52
  RegExpLiteral: [],
51
53
  RestElement: [..._ESTreeVisitorKeys.default.RestElement, 'typeAnnotation'],
52
54
  StringLiteral: [],
55
+ TupleTypeAnnotation: ['types'],
53
56
  CommentBlock: [],
54
57
  CommentLine: []
55
58
  };
@@ -480,6 +483,7 @@ function mapPropertyDefinition(node) {
480
483
  function mapTypeofTypeAnnotation(node) {
481
484
  // $FlowExpectedError[cannot-write]
482
485
  delete node.typeArguments; // $FlowFixMe[incompatible-type]
486
+ // $FlowFixMe[invalid-compare]
483
487
 
484
488
  if (node.argument.type !== 'GenericTypeAnnotation') {
485
489
  return nodeWith(node, {
@@ -656,6 +660,7 @@ function transformNode(node) {
656
660
 
657
661
  // Check if we have already processed this node.
658
662
  // $FlowFixMe[incompatible-type]
663
+ // $FlowFixMe[invalid-compare]
659
664
  if (((_node$parent = node.parent) == null ? void 0 : _node$parent.type) === 'File') {
660
665
  return node;
661
666
  }
@@ -819,10 +824,74 @@ function transformNode(node) {
819
824
  case 'TupleTypeAnnotation':
820
825
  {
821
826
  // $FlowExpectedError[cannot-write]
822
- delete node.inexact;
827
+ delete node.inexact; // $FlowExpectedError[prop-missing]
828
+
829
+ node.types = node.elementTypes; // $FlowExpectedError[cannot-write]
830
+
831
+ delete node.elementTypes;
823
832
  return node;
824
833
  }
825
834
 
835
+ case 'UnknownTypeAnnotation':
836
+ {
837
+ return {
838
+ type: 'GenericTypeAnnotation',
839
+ id: {
840
+ type: 'Identifier',
841
+ name: 'unknown',
842
+ optional: false,
843
+ typeAnnotation: null,
844
+ loc: node.loc,
845
+ range: node.range,
846
+ parent: EMPTY_PARENT
847
+ },
848
+ typeParameters: null,
849
+ loc: node.loc,
850
+ range: node.range,
851
+ parent: EMPTY_PARENT
852
+ };
853
+ }
854
+
855
+ case 'NeverTypeAnnotation':
856
+ {
857
+ return {
858
+ type: 'GenericTypeAnnotation',
859
+ id: {
860
+ type: 'Identifier',
861
+ name: 'never',
862
+ optional: false,
863
+ typeAnnotation: null,
864
+ loc: node.loc,
865
+ range: node.range,
866
+ parent: EMPTY_PARENT
867
+ },
868
+ typeParameters: null,
869
+ loc: node.loc,
870
+ range: node.range,
871
+ parent: EMPTY_PARENT
872
+ };
873
+ }
874
+
875
+ case 'UndefinedTypeAnnotation':
876
+ {
877
+ return {
878
+ type: 'GenericTypeAnnotation',
879
+ id: {
880
+ type: 'Identifier',
881
+ name: 'undefined',
882
+ optional: false,
883
+ typeAnnotation: null,
884
+ loc: node.loc,
885
+ range: node.range,
886
+ parent: EMPTY_PARENT
887
+ },
888
+ typeParameters: null,
889
+ loc: node.loc,
890
+ range: node.range,
891
+ parent: EMPTY_PARENT
892
+ };
893
+ }
894
+
826
895
  case 'JSXText':
827
896
  {
828
897
  // $FlowExpectedError[prop-missing]
@@ -985,9 +1054,15 @@ function transformNode(node) {
985
1054
  delete node.implements;
986
1055
  }
987
1056
 
988
- if (node.superTypeParameters == null) {
1057
+ if (node.superTypeArguments == null) {
1058
+ // $FlowExpectedError[cannot-write]
1059
+ delete node.superTypeArguments;
1060
+ } else {
989
1061
  // $FlowExpectedError[cannot-write]
990
- delete node.superTypeParameters;
1062
+ // $FlowExpectedError[prop-missing]
1063
+ node.superTypeParameters = node.superTypeArguments; // $FlowExpectedError[cannot-write]
1064
+
1065
+ delete node.superTypeArguments;
991
1066
  }
992
1067
 
993
1068
  if (node.typeParameters == null) {
@@ -1110,6 +1185,7 @@ function transformProgram(program, options) {
1110
1185
 
1111
1186
  visitorKeys: FlowESTreeAndBabelVisitorKeys
1112
1187
  }); // $FlowFixMe[incompatible-type]
1188
+ // $FlowFixMe[invalid-compare]
1113
1189
 
1114
1190
 
1115
1191
  if ((resultNode == null ? void 0 : resultNode.type) === 'File') {
@@ -59,6 +59,11 @@ const FlowESTreeAndBabelVisitorKeys: VisitorKeys = {
59
59
  BigIntLiteral: [],
60
60
  BlockStatement: ['directives', ...FlowVisitorKeys.BlockStatement],
61
61
  BooleanLiteral: [],
62
+ ClassExpression: ['superTypeParameters', ...FlowVisitorKeys.ClassExpression],
63
+ ClassDeclaration: [
64
+ 'superTypeParameters',
65
+ ...FlowVisitorKeys.ClassDeclaration,
66
+ ],
62
67
  ClassMethod: ['key', 'params', 'body', 'returnType', 'typeParameters'],
63
68
  ClassPrivateMethod: ['key', 'params', 'body', 'returnType', 'typeParameters'],
64
69
  ClassProperty: ['key', 'value', 'typeAnnotation', 'variance'],
@@ -85,6 +90,7 @@ const FlowESTreeAndBabelVisitorKeys: VisitorKeys = {
85
90
  RegExpLiteral: [],
86
91
  RestElement: [...FlowVisitorKeys.RestElement, 'typeAnnotation'],
87
92
  StringLiteral: [],
93
+ TupleTypeAnnotation: ['types'],
88
94
  CommentBlock: [],
89
95
  CommentLine: [],
90
96
  };
@@ -753,6 +759,7 @@ function mapTypeofTypeAnnotation(
753
759
  // $FlowExpectedError[cannot-write]
754
760
  delete node.typeArguments;
755
761
  // $FlowFixMe[incompatible-type]
762
+ // $FlowFixMe[invalid-compare]
756
763
  if (node.argument.type !== 'GenericTypeAnnotation') {
757
764
  return nodeWith(node, {
758
765
  // $FlowExpectedError[incompatible-type] Special override for Babel
@@ -920,6 +927,7 @@ function transformNode(node: ESNodeOrBabelNode): ESNodeOrBabelNode | null {
920
927
  case 'Program': {
921
928
  // Check if we have already processed this node.
922
929
  // $FlowFixMe[incompatible-type]
930
+ // $FlowFixMe[invalid-compare]
923
931
  if (node.parent?.type === 'File') {
924
932
  return node;
925
933
  }
@@ -1038,9 +1046,68 @@ function transformNode(node: ESNodeOrBabelNode): ESNodeOrBabelNode | null {
1038
1046
  case 'TupleTypeAnnotation': {
1039
1047
  // $FlowExpectedError[cannot-write]
1040
1048
  delete node.inexact;
1049
+ // $FlowExpectedError[prop-missing]
1050
+ node.types = node.elementTypes;
1051
+ // $FlowExpectedError[cannot-write]
1052
+ delete node.elementTypes;
1041
1053
  return node;
1042
1054
  }
1043
1055
 
1056
+ case 'UnknownTypeAnnotation': {
1057
+ return {
1058
+ type: 'GenericTypeAnnotation',
1059
+ id: {
1060
+ type: 'Identifier',
1061
+ name: 'unknown',
1062
+ optional: false,
1063
+ typeAnnotation: null,
1064
+ loc: node.loc,
1065
+ range: node.range,
1066
+ parent: EMPTY_PARENT,
1067
+ },
1068
+ typeParameters: null,
1069
+ loc: node.loc,
1070
+ range: node.range,
1071
+ parent: EMPTY_PARENT,
1072
+ };
1073
+ }
1074
+ case 'NeverTypeAnnotation': {
1075
+ return {
1076
+ type: 'GenericTypeAnnotation',
1077
+ id: {
1078
+ type: 'Identifier',
1079
+ name: 'never',
1080
+ optional: false,
1081
+ typeAnnotation: null,
1082
+ loc: node.loc,
1083
+ range: node.range,
1084
+ parent: EMPTY_PARENT,
1085
+ },
1086
+ typeParameters: null,
1087
+ loc: node.loc,
1088
+ range: node.range,
1089
+ parent: EMPTY_PARENT,
1090
+ };
1091
+ }
1092
+ case 'UndefinedTypeAnnotation': {
1093
+ return {
1094
+ type: 'GenericTypeAnnotation',
1095
+ id: {
1096
+ type: 'Identifier',
1097
+ name: 'undefined',
1098
+ optional: false,
1099
+ typeAnnotation: null,
1100
+ loc: node.loc,
1101
+ range: node.range,
1102
+ parent: EMPTY_PARENT,
1103
+ },
1104
+ typeParameters: null,
1105
+ loc: node.loc,
1106
+ range: node.range,
1107
+ parent: EMPTY_PARENT,
1108
+ };
1109
+ }
1110
+
1044
1111
  case 'JSXText': {
1045
1112
  // $FlowExpectedError[prop-missing]
1046
1113
  node.extra = {
@@ -1165,9 +1232,15 @@ function transformNode(node: ESNodeOrBabelNode): ESNodeOrBabelNode | null {
1165
1232
  // $FlowExpectedError[cannot-write]
1166
1233
  delete node.implements;
1167
1234
  }
1168
- if (node.superTypeParameters == null) {
1235
+ if (node.superTypeArguments == null) {
1236
+ // $FlowExpectedError[cannot-write]
1237
+ delete node.superTypeArguments;
1238
+ } else {
1239
+ // $FlowExpectedError[cannot-write]
1240
+ // $FlowExpectedError[prop-missing]
1241
+ node.superTypeParameters = node.superTypeArguments;
1169
1242
  // $FlowExpectedError[cannot-write]
1170
- delete node.superTypeParameters;
1243
+ delete node.superTypeArguments;
1171
1244
  }
1172
1245
  if (node.typeParameters == null) {
1173
1246
  // $FlowExpectedError[cannot-write]
@@ -1263,6 +1336,7 @@ export function transformProgram(
1263
1336
  });
1264
1337
 
1265
1338
  // $FlowFixMe[incompatible-type]
1339
+ // $FlowFixMe[invalid-compare]
1266
1340
  if (resultNode?.type === 'File') {
1267
1341
  return resultNode;
1268
1342
  }
@@ -117,7 +117,7 @@ function transformProgram(program, _options) {
117
117
  {
118
118
  return nodeWith(node, {
119
119
  typeParameters: null,
120
- superTypeParameters: null,
120
+ superTypeArguments: null,
121
121
  implements: [],
122
122
  decorators: []
123
123
  });
@@ -105,7 +105,7 @@ export function transformProgram(
105
105
  case 'ClassExpression': {
106
106
  return nodeWith(node, {
107
107
  typeParameters: null,
108
- superTypeParameters: null,
108
+ superTypeArguments: null,
109
109
  implements: [],
110
110
  decorators: [],
111
111
  });
@@ -191,7 +191,7 @@ function mapComponentParameters(params, options) {
191
191
 
192
192
  if (propsProperties.length === 0) {
193
193
  if (refParam == null) {
194
- throw new Error('StripComponentSyntax: Invalid state, ref should always be set at this point if props are empty');
194
+ throw new Error('TransformComponentSyntax: Invalid state, ref should always be set at this point if props are empty');
195
195
  }
196
196
 
197
197
  const emptyParamsLoc = {
@@ -243,7 +243,7 @@ function mapComponentParameters(
243
243
  if (propsProperties.length === 0) {
244
244
  if (refParam == null) {
245
245
  throw new Error(
246
- 'StripComponentSyntax: Invalid state, ref should always be set at this point if props are empty',
246
+ 'TransformComponentSyntax: Invalid state, ref should always be set at this point if props are empty',
247
247
  );
248
248
  }
249
249
  const emptyParamsLoc = {
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and 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
+ *
8
+ * @format
9
+ */
10
+ 'use strict';
11
+ /**
12
+ * Transform Flow Enum declarations (https://flow.org/en/docs/enums/).
13
+ */
14
+
15
+ Object.defineProperty(exports, "__esModule", {
16
+ value: true
17
+ });
18
+ exports.transformProgram = transformProgram;
19
+
20
+ var _hermesEstree = require("hermes-estree");
21
+
22
+ var _SimpleTransform = require("../transform/SimpleTransform");
23
+
24
+ var _Builders = require("../utils/Builders");
25
+
26
+ function mapEnumDeclaration(node, options) {
27
+ var _options$transformOpt, _options$transformOpt2;
28
+
29
+ const {
30
+ body
31
+ } = node;
32
+ const {
33
+ members
34
+ } = body;
35
+ const getRuntime = (_options$transformOpt = options.transformOptions) == null ? void 0 : (_options$transformOpt2 = _options$transformOpt.TransformEnumSyntax) == null ? void 0 : _options$transformOpt2.getRuntime;
36
+ const enumModule = typeof getRuntime === 'function' ? getRuntime() : (0, _Builders.callExpression)((0, _Builders.ident)('require'), [(0, _Builders.stringLiteral)('flow-enums-runtime')]);
37
+ const mirrored = body.type === 'EnumStringBody' && (!members.length || members[0].type === 'EnumDefaultedMember');
38
+ const enumExpression = mirrored ? (0, _Builders.callExpression)({
39
+ type: 'MemberExpression',
40
+ object: enumModule,
41
+ property: (0, _Builders.ident)('Mirrored'),
42
+ computed: false,
43
+ optional: false,
44
+ ...(0, _Builders.etc)()
45
+ }, [{
46
+ type: 'ArrayExpression',
47
+ elements: members.map(member => (0, _Builders.stringLiteral)(member.id.name)),
48
+ trailingComma: false,
49
+ ...(0, _Builders.etc)()
50
+ }]) : (0, _Builders.callExpression)(enumModule, [{
51
+ type: 'ObjectExpression',
52
+ properties: members.map(member => ({
53
+ type: 'Property',
54
+ key: member.id,
55
+ value: // String enums with `EnumDefaultedMember` are handled above by
56
+ // calculation of `mirrored`.
57
+ member.type === 'EnumDefaultedMember' ? (0, _Builders.callExpression)((0, _Builders.ident)('Symbol'), [(0, _Builders.stringLiteral)(member.id.name)]) : member.init,
58
+ kind: 'init',
59
+ method: false,
60
+ shorthand: false,
61
+ computed: false,
62
+ ...(0, _Builders.etc)(),
63
+ parent: _Builders.EMPTY_PARENT
64
+ })),
65
+ ...(0, _Builders.etc)()
66
+ }]);
67
+ return (0, _Builders.variableDeclaration)('const', node.id, enumExpression);
68
+ }
69
+
70
+ function transformProgram(program, options) {
71
+ return _SimpleTransform.SimpleTransform.transformProgram(program, {
72
+ transform(node) {
73
+ switch (node.type) {
74
+ case 'EnumDeclaration':
75
+ {
76
+ return mapEnumDeclaration(node, options);
77
+ }
78
+
79
+ case 'ExportDefaultDeclaration':
80
+ {
81
+ const {
82
+ declaration
83
+ } = node;
84
+
85
+ if ((0, _hermesEstree.isEnumDeclaration)(declaration)) {
86
+ const enumDeclaration = mapEnumDeclaration(declaration, options);
87
+
88
+ const exportDefault = _SimpleTransform.SimpleTransform.nodeWith(node, {
89
+ declaration: (0, _Builders.ident)(declaration.id.name)
90
+ });
91
+
92
+ return [enumDeclaration, exportDefault];
93
+ } else {
94
+ return node;
95
+ }
96
+ }
97
+
98
+ default:
99
+ {
100
+ return node;
101
+ }
102
+ }
103
+ }
104
+
105
+ });
106
+ }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and 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
+ 'use strict';
12
+
13
+ /**
14
+ * Transform Flow Enum declarations (https://flow.org/en/docs/enums/).
15
+ */
16
+
17
+ import type {ParserOptions} from '../ParserOptions';
18
+ import type {
19
+ ESNode,
20
+ EnumDeclaration,
21
+ ExportDefaultDeclaration,
22
+ ObjectPropertyWithNonShorthandStaticName,
23
+ Program,
24
+ } from 'hermes-estree';
25
+
26
+ import {isEnumDeclaration} from 'hermes-estree';
27
+ import {SimpleTransform} from '../transform/SimpleTransform';
28
+ import {
29
+ EMPTY_PARENT,
30
+ callExpression,
31
+ etc,
32
+ ident,
33
+ stringLiteral,
34
+ variableDeclaration,
35
+ } from '../utils/Builders';
36
+
37
+ function mapEnumDeclaration(node: EnumDeclaration, options: ParserOptions) {
38
+ const {body} = node;
39
+ const {members} = body;
40
+ const getRuntime = options.transformOptions?.TransformEnumSyntax?.getRuntime;
41
+ const enumModule =
42
+ typeof getRuntime === 'function'
43
+ ? getRuntime()
44
+ : callExpression(ident('require'), [stringLiteral('flow-enums-runtime')]);
45
+ const mirrored =
46
+ body.type === 'EnumStringBody' &&
47
+ (!members.length || members[0].type === 'EnumDefaultedMember');
48
+ const enumExpression = mirrored
49
+ ? callExpression(
50
+ {
51
+ type: 'MemberExpression',
52
+ object: enumModule,
53
+ property: ident('Mirrored'),
54
+ computed: false,
55
+ optional: false,
56
+ ...etc(),
57
+ },
58
+ [
59
+ {
60
+ type: 'ArrayExpression',
61
+ elements: members.map(member => stringLiteral(member.id.name)),
62
+ trailingComma: false,
63
+ ...etc(),
64
+ },
65
+ ],
66
+ )
67
+ : callExpression(enumModule, [
68
+ {
69
+ type: 'ObjectExpression',
70
+ properties: members.map(
71
+ (member): ObjectPropertyWithNonShorthandStaticName => ({
72
+ type: 'Property',
73
+ key: member.id,
74
+ value:
75
+ // String enums with `EnumDefaultedMember` are handled above by
76
+ // calculation of `mirrored`.
77
+ member.type === 'EnumDefaultedMember'
78
+ ? callExpression(ident('Symbol'), [
79
+ stringLiteral(member.id.name),
80
+ ])
81
+ : member.init,
82
+ kind: 'init',
83
+ method: false,
84
+ shorthand: false,
85
+ computed: false,
86
+ ...etc(),
87
+ parent: EMPTY_PARENT,
88
+ }),
89
+ ),
90
+ ...etc(),
91
+ },
92
+ ]);
93
+ return variableDeclaration('const', node.id, enumExpression);
94
+ }
95
+
96
+ export function transformProgram(
97
+ program: Program,
98
+ options: ParserOptions,
99
+ ): Program {
100
+ return SimpleTransform.transformProgram(program, {
101
+ transform(node: ESNode): ESNode | $ReadOnlyArray<ESNode> {
102
+ switch (node.type) {
103
+ case 'EnumDeclaration': {
104
+ return mapEnumDeclaration(node, options);
105
+ }
106
+ case 'ExportDefaultDeclaration': {
107
+ const {declaration} = node;
108
+ if (isEnumDeclaration(declaration)) {
109
+ const enumDeclaration = mapEnumDeclaration(declaration, options);
110
+ const exportDefault: ExportDefaultDeclaration =
111
+ SimpleTransform.nodeWith(node, {
112
+ declaration: ident(declaration.id.name),
113
+ });
114
+ return [enumDeclaration, exportDefault];
115
+ } else {
116
+ return node;
117
+ }
118
+ }
119
+ default: {
120
+ return node;
121
+ }
122
+ }
123
+ },
124
+ });
125
+ }