hermes-parser 0.18.1 → 0.19.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.
@@ -478,6 +478,9 @@ function mapPropertyDefinition(node) {
478
478
  }
479
479
 
480
480
  function mapTypeofTypeAnnotation(node) {
481
+ // $FlowExpectedError[cannot-write]
482
+ delete node.typeArguments;
483
+
481
484
  if (node.argument.type !== 'GenericTypeAnnotation') {
482
485
  return nodeWith(node, {
483
486
  // $FlowExpectedError[incompatible-call] Special override for Babel
@@ -748,6 +748,8 @@ function mapPropertyDefinition(
748
748
  function mapTypeofTypeAnnotation(
749
749
  node: TypeofTypeAnnotation,
750
750
  ): TypeofTypeAnnotation {
751
+ // $FlowExpectedError[cannot-write]
752
+ delete node.typeArguments;
751
753
  if (node.argument.type !== 'GenericTypeAnnotation') {
752
754
  return nodeWith(node, {
753
755
  // $FlowExpectedError[incompatible-call] Special override for Babel
@@ -78,7 +78,7 @@ function getComponentParameterName(paramName) {
78
78
  }
79
79
  }
80
80
 
81
- function createPropsTypeAnnotation(loc, range) {
81
+ function createPropsTypeAnnotation(propTypes, spread, loc, range) {
82
82
  // Create empty loc for type annotation nodes
83
83
  const createParamsTypeLoc = () => ({
84
84
  loc: {
@@ -87,8 +87,34 @@ function createPropsTypeAnnotation(loc, range) {
87
87
  },
88
88
  range: range != null ? range : [0, 0],
89
89
  parent: EMPTY_PARENT
90
- });
90
+ }); // Optimize `{...Props}` -> `Props`
91
+
91
92
 
93
+ if (spread != null && propTypes.length === 0) {
94
+ return {
95
+ type: 'TypeAnnotation',
96
+ typeAnnotation: spread.argument,
97
+ ...createParamsTypeLoc()
98
+ };
99
+ }
100
+
101
+ const typeProperties = [...propTypes];
102
+
103
+ if (spread != null) {
104
+ // Spread needs to be the first type, as inline properties take precedence.
105
+ typeProperties.unshift(spread);
106
+ }
107
+
108
+ const propTypeObj = {
109
+ type: 'ObjectTypeAnnotation',
110
+ callProperties: [],
111
+ properties: typeProperties,
112
+ indexers: [],
113
+ internalSlots: [],
114
+ exact: false,
115
+ inexact: false,
116
+ ...createParamsTypeLoc()
117
+ };
92
118
  return {
93
119
  type: 'TypeAnnotation',
94
120
  typeAnnotation: {
@@ -102,16 +128,7 @@ function createPropsTypeAnnotation(loc, range) {
102
128
  },
103
129
  typeParameters: {
104
130
  type: 'TypeParameterInstantiation',
105
- params: [{
106
- type: 'ObjectTypeAnnotation',
107
- callProperties: [],
108
- properties: [],
109
- indexers: [],
110
- internalSlots: [],
111
- exact: false,
112
- inexact: true,
113
- ...createParamsTypeLoc()
114
- }],
131
+ params: [propTypeObj],
115
132
  ...createParamsTypeLoc()
116
133
  },
117
134
  ...createParamsTypeLoc()
@@ -130,13 +147,9 @@ function mapComponentParameters(params) {
130
147
 
131
148
 
132
149
  if (params.length === 1 && params[0].type === 'RestElement' && params[0].argument.type === 'Identifier') {
133
- var _restElementArgument$, _restElementArgument$2;
134
-
135
150
  const restElementArgument = params[0].argument;
136
151
  return {
137
- props: nodeWith(restElementArgument, {
138
- typeAnnotation: createPropsTypeAnnotation((_restElementArgument$ = restElementArgument.typeAnnotation) == null ? void 0 : _restElementArgument$.loc, (_restElementArgument$2 = restElementArgument.typeAnnotation) == null ? void 0 : _restElementArgument$2.range)
139
- }),
152
+ props: restElementArgument,
140
153
  ref: null
141
154
  };
142
155
  } // Filter out any ref param and capture it's details.
@@ -151,12 +164,30 @@ function mapComponentParameters(params) {
151
164
 
152
165
  return true;
153
166
  });
167
+ const [propTypes, spread] = paramsWithoutRef.reduce(([propTypes, spread], param) => {
168
+ switch (param.type) {
169
+ case 'RestElement':
170
+ {
171
+ if (spread != null) {
172
+ throw (0, _createSyntaxError.createSyntaxError)(param, `Invalid state, multiple rest elements found as Component Parameters`);
173
+ }
174
+
175
+ return [propTypes, mapComponentParameterRestElementType(param)];
176
+ }
177
+
178
+ case 'ComponentParameter':
179
+ {
180
+ propTypes.push(mapComponentParameterType(param));
181
+ return [propTypes, spread];
182
+ }
183
+ }
184
+ }, [[], null]);
154
185
  const propsProperties = paramsWithoutRef.flatMap(mapComponentParameter);
155
186
  let props = null;
156
187
 
157
188
  if (propsProperties.length === 0) {
158
189
  if (refParam == null) {
159
- throw new Error('TransformReactScriptForBabel: Invalid state, ref should always be set at this point if props are empty');
190
+ throw new Error('StripComponentSyntax: Invalid state, ref should always be set at this point if props are empty');
160
191
  }
161
192
 
162
193
  const emptyParamsLoc = {
@@ -169,7 +200,7 @@ function mapComponentParameters(params) {
169
200
  type: 'Identifier',
170
201
  name: '_$$empty_props_placeholder$$',
171
202
  optional: false,
172
- typeAnnotation: createPropsTypeAnnotation(emptyParamsLoc, emptyParamsRange),
203
+ typeAnnotation: createPropsTypeAnnotation([], null, emptyParamsLoc, emptyParamsRange),
173
204
  loc: emptyParamsLoc,
174
205
  range: emptyParamsRange,
175
206
  parent: EMPTY_PARENT
@@ -179,7 +210,7 @@ function mapComponentParameters(params) {
179
210
  props = {
180
211
  type: 'ObjectPattern',
181
212
  properties: propsProperties,
182
- typeAnnotation: createPropsTypeAnnotation({
213
+ typeAnnotation: createPropsTypeAnnotation(propTypes, spread, {
183
214
  start: lastPropsProperty.loc.end,
184
215
  end: lastPropsProperty.loc.end
185
216
  }, [lastPropsProperty.range[1], lastPropsProperty.range[1]]),
@@ -204,6 +235,53 @@ function mapComponentParameters(params) {
204
235
  };
205
236
  }
206
237
 
238
+ function mapComponentParameterType(param) {
239
+ var _typeAnnotation$typeA;
240
+
241
+ const typeAnnotation = param.local.type === 'AssignmentPattern' ? param.local.left.typeAnnotation : param.local.typeAnnotation;
242
+ const optional = param.local.type === 'AssignmentPattern' ? true : param.local.type === 'Identifier' ? param.local.optional : false;
243
+ return {
244
+ type: 'ObjectTypeProperty',
245
+ key: (0, _astNodeMutationHelpers.shallowCloneNode)(param.name),
246
+ value: (_typeAnnotation$typeA = typeAnnotation == null ? void 0 : typeAnnotation.typeAnnotation) != null ? _typeAnnotation$typeA : {
247
+ type: 'AnyTypeAnnotation',
248
+ loc: param.local.loc,
249
+ range: param.local.range,
250
+ parent: EMPTY_PARENT
251
+ },
252
+ kind: 'init',
253
+ optional,
254
+ method: false,
255
+ static: false,
256
+ proto: false,
257
+ variance: null,
258
+ loc: param.local.loc,
259
+ range: param.local.range,
260
+ parent: EMPTY_PARENT
261
+ };
262
+ }
263
+
264
+ function mapComponentParameterRestElementType(param) {
265
+ var _param$argument$typeA, _param$argument$typeA2;
266
+
267
+ if (param.argument.type !== 'Identifier' && param.argument.type !== 'ObjectPattern') {
268
+ throw (0, _createSyntaxError.createSyntaxError)(param, `Invalid ${param.argument.type} encountered in restParameter`);
269
+ }
270
+
271
+ return {
272
+ type: 'ObjectTypeSpreadProperty',
273
+ argument: (_param$argument$typeA = (_param$argument$typeA2 = param.argument.typeAnnotation) == null ? void 0 : _param$argument$typeA2.typeAnnotation) != null ? _param$argument$typeA : {
274
+ type: 'AnyTypeAnnotation',
275
+ loc: param.loc,
276
+ range: param.range,
277
+ parent: EMPTY_PARENT
278
+ },
279
+ loc: param.loc,
280
+ range: param.range,
281
+ parent: EMPTY_PARENT
282
+ };
283
+ }
284
+
207
285
  function mapComponentParameter(param) {
208
286
  switch (param.type) {
209
287
  case 'RestElement':
@@ -425,6 +503,60 @@ function mapComponentDeclaration(node) {
425
503
  forwardRefDetails
426
504
  };
427
505
  }
506
+
507
+ function mapDeclareHook(node) {
508
+ return {
509
+ type: 'DeclareFunction',
510
+ id: {
511
+ type: 'Identifier',
512
+ name: node.id.name,
513
+ optional: node.id.optional,
514
+ typeAnnotation: {
515
+ type: 'TypeAnnotation',
516
+ typeAnnotation: {
517
+ type: 'FunctionTypeAnnotation',
518
+ this: null,
519
+ params: node.id.typeAnnotation.typeAnnotation.params,
520
+ typeParameters: node.id.typeAnnotation.typeAnnotation.typeParameters,
521
+ rest: node.id.typeAnnotation.typeAnnotation.rest,
522
+ returnType: node.id.typeAnnotation.typeAnnotation.returnType,
523
+ loc: node.id.typeAnnotation.typeAnnotation.loc,
524
+ range: node.id.typeAnnotation.typeAnnotation.range,
525
+ parent: node.id.typeAnnotation.typeAnnotation.parent
526
+ },
527
+ loc: node.id.typeAnnotation.loc,
528
+ range: node.id.typeAnnotation.range,
529
+ parent: node.id.typeAnnotation.parent
530
+ },
531
+ loc: node.id.loc,
532
+ range: node.id.range,
533
+ parent: node.id.parent
534
+ },
535
+ loc: node.loc,
536
+ range: node.range,
537
+ parent: node.parent,
538
+ predicate: null
539
+ };
540
+ }
541
+
542
+ function mapHookDeclaration(node) {
543
+ const comp = {
544
+ type: 'FunctionDeclaration',
545
+ id: node.id && (0, _astNodeMutationHelpers.shallowCloneNode)(node.id),
546
+ __hookDeclaration: true,
547
+ typeParameters: node.typeParameters,
548
+ params: node.params,
549
+ returnType: node.returnType,
550
+ body: node.body,
551
+ async: false,
552
+ generator: false,
553
+ predicate: null,
554
+ loc: node.loc,
555
+ range: node.range,
556
+ parent: node.parent
557
+ };
558
+ return comp;
559
+ }
428
560
  /**
429
561
  * Scan a list of statements and return the position of the
430
562
  * first statement that contains a reference to a given component
@@ -502,9 +634,16 @@ function mapStatementList(stmts) {
502
634
  break;
503
635
  }
504
636
 
637
+ case 'HookDeclaration':
638
+ {
639
+ const decl = mapHookDeclaration(node);
640
+ newBody.push(decl);
641
+ break;
642
+ }
643
+
505
644
  case 'ExportNamedDeclaration':
506
645
  {
507
- var _node$declaration;
646
+ var _node$declaration, _node$declaration2;
508
647
 
509
648
  if (((_node$declaration = node.declaration) == null ? void 0 : _node$declaration.type) === 'ComponentDeclaration') {
510
649
  mapComponentDeclarationIntoList(node.declaration, newBody, componentOrRef => {
@@ -543,21 +682,33 @@ function mapStatementList(stmts) {
543
682
  break;
544
683
  }
545
684
 
685
+ if (((_node$declaration2 = node.declaration) == null ? void 0 : _node$declaration2.type) === 'HookDeclaration') {
686
+ const comp = mapHookDeclaration(node.declaration);
687
+ newBody.push(comp);
688
+ break;
689
+ }
690
+
546
691
  newBody.push(node);
547
692
  break;
548
693
  }
549
694
 
550
695
  case 'ExportDefaultDeclaration':
551
696
  {
552
- var _node$declaration2;
697
+ var _node$declaration3, _node$declaration4;
553
698
 
554
- if (((_node$declaration2 = node.declaration) == null ? void 0 : _node$declaration2.type) === 'ComponentDeclaration') {
699
+ if (((_node$declaration3 = node.declaration) == null ? void 0 : _node$declaration3.type) === 'ComponentDeclaration') {
555
700
  mapComponentDeclarationIntoList(node.declaration, newBody, componentOrRef => nodeWith(node, {
556
701
  declaration: componentOrRef
557
702
  }));
558
703
  break;
559
704
  }
560
705
 
706
+ if (((_node$declaration4 = node.declaration) == null ? void 0 : _node$declaration4.type) === 'HookDeclaration') {
707
+ const comp = mapHookDeclaration(node.declaration);
708
+ newBody.push(comp);
709
+ break;
710
+ }
711
+
561
712
  newBody.push(node);
562
713
  break;
563
714
  }
@@ -581,6 +732,11 @@ function transformProgram(program, _options) {
581
732
  return mapDeclareComponent(node);
582
733
  }
583
734
 
735
+ case 'DeclareHook':
736
+ {
737
+ return mapDeclareHook(node);
738
+ }
739
+
584
740
  case 'Program':
585
741
  case 'BlockStatement':
586
742
  {
@@ -605,6 +761,13 @@ function transformProgram(program, _options) {
605
761
  throw (0, _createSyntaxError.createSyntaxError)(node, `Components must be defined at the top level of a module or within a ` + `BlockStatement, instead got parent of "${(_node$parent = node.parent) == null ? void 0 : _node$parent.type}".`);
606
762
  }
607
763
 
764
+ case 'HookDeclaration':
765
+ {
766
+ var _node$parent2;
767
+
768
+ throw (0, _createSyntaxError.createSyntaxError)(node, `Hooks must be defined at the top level of a module or within a ` + `BlockStatement, instead got parent of "${(_node$parent2 = node.parent) == null ? void 0 : _node$parent2.type}".`);
769
+ }
770
+
608
771
  default:
609
772
  {
610
773
  return node;
@@ -37,9 +37,14 @@ import type {
37
37
  DestructuringObjectProperty,
38
38
  VariableDeclaration,
39
39
  ModuleDeclaration,
40
+ DeclareHook,
41
+ DeclareFunction,
42
+ HookDeclaration,
40
43
  Statement,
41
44
  AssignmentPattern,
42
45
  BindingName,
46
+ ObjectTypePropertySignature,
47
+ ObjectTypeSpreadProperty,
43
48
  } from 'hermes-estree';
44
49
 
45
50
  import {SimpleTransform} from '../transform/SimpleTransform';
@@ -100,6 +105,8 @@ function getComponentParameterName(
100
105
  }
101
106
 
102
107
  function createPropsTypeAnnotation(
108
+ propTypes: Array<ObjectTypePropertySignature>,
109
+ spread: ?ObjectTypeSpreadProperty,
103
110
  loc: ?SourceLocation,
104
111
  range: ?Range,
105
112
  ): TypeAnnotation {
@@ -113,6 +120,35 @@ function createPropsTypeAnnotation(
113
120
  parent: EMPTY_PARENT,
114
121
  });
115
122
 
123
+ // Optimize `{...Props}` -> `Props`
124
+ if (spread != null && propTypes.length === 0) {
125
+ return {
126
+ type: 'TypeAnnotation',
127
+ typeAnnotation: spread.argument,
128
+ ...createParamsTypeLoc(),
129
+ };
130
+ }
131
+
132
+ const typeProperties: Array<
133
+ ObjectTypePropertySignature | ObjectTypeSpreadProperty,
134
+ > = [...propTypes];
135
+
136
+ if (spread != null) {
137
+ // Spread needs to be the first type, as inline properties take precedence.
138
+ typeProperties.unshift(spread);
139
+ }
140
+
141
+ const propTypeObj = {
142
+ type: 'ObjectTypeAnnotation',
143
+ callProperties: [],
144
+ properties: typeProperties,
145
+ indexers: [],
146
+ internalSlots: [],
147
+ exact: false,
148
+ inexact: false,
149
+ ...createParamsTypeLoc(),
150
+ };
151
+
116
152
  return {
117
153
  type: 'TypeAnnotation',
118
154
  typeAnnotation: {
@@ -126,18 +162,7 @@ function createPropsTypeAnnotation(
126
162
  },
127
163
  typeParameters: {
128
164
  type: 'TypeParameterInstantiation',
129
- params: [
130
- {
131
- type: 'ObjectTypeAnnotation',
132
- callProperties: [],
133
- properties: [],
134
- indexers: [],
135
- internalSlots: [],
136
- exact: false,
137
- inexact: true,
138
- ...createParamsTypeLoc(),
139
- },
140
- ],
165
+ params: [propTypeObj],
141
166
  ...createParamsTypeLoc(),
142
167
  },
143
168
  ...createParamsTypeLoc(),
@@ -164,12 +189,7 @@ function mapComponentParameters(
164
189
  ) {
165
190
  const restElementArgument = params[0].argument;
166
191
  return {
167
- props: nodeWith(restElementArgument, {
168
- typeAnnotation: createPropsTypeAnnotation(
169
- restElementArgument.typeAnnotation?.loc,
170
- restElementArgument.typeAnnotation?.range,
171
- ),
172
- }),
192
+ props: restElementArgument,
173
193
  ref: null,
174
194
  };
175
195
  }
@@ -188,13 +208,36 @@ function mapComponentParameters(
188
208
  return true;
189
209
  });
190
210
 
211
+ const [propTypes, spread] = paramsWithoutRef.reduce<
212
+ [Array<ObjectTypePropertySignature>, ?ObjectTypeSpreadProperty],
213
+ >(
214
+ ([propTypes, spread], param) => {
215
+ switch (param.type) {
216
+ case 'RestElement': {
217
+ if (spread != null) {
218
+ throw createSyntaxError(
219
+ param,
220
+ `Invalid state, multiple rest elements found as Component Parameters`,
221
+ );
222
+ }
223
+ return [propTypes, mapComponentParameterRestElementType(param)];
224
+ }
225
+ case 'ComponentParameter': {
226
+ propTypes.push(mapComponentParameterType(param));
227
+ return [propTypes, spread];
228
+ }
229
+ }
230
+ },
231
+ [[], null],
232
+ );
233
+
191
234
  const propsProperties = paramsWithoutRef.flatMap(mapComponentParameter);
192
235
 
193
236
  let props = null;
194
237
  if (propsProperties.length === 0) {
195
238
  if (refParam == null) {
196
239
  throw new Error(
197
- 'TransformReactScriptForBabel: Invalid state, ref should always be set at this point if props are empty',
240
+ 'StripComponentSyntax: Invalid state, ref should always be set at this point if props are empty',
198
241
  );
199
242
  }
200
243
  const emptyParamsLoc = {
@@ -208,6 +251,8 @@ function mapComponentParameters(
208
251
  name: '_$$empty_props_placeholder$$',
209
252
  optional: false,
210
253
  typeAnnotation: createPropsTypeAnnotation(
254
+ [],
255
+ null,
211
256
  emptyParamsLoc,
212
257
  emptyParamsRange,
213
258
  ),
@@ -221,6 +266,8 @@ function mapComponentParameters(
221
266
  type: 'ObjectPattern',
222
267
  properties: propsProperties,
223
268
  typeAnnotation: createPropsTypeAnnotation(
269
+ propTypes,
270
+ spread,
224
271
  {
225
272
  start: lastPropsProperty.loc.end,
226
273
  end: lastPropsProperty.loc.end,
@@ -247,6 +294,67 @@ function mapComponentParameters(
247
294
  };
248
295
  }
249
296
 
297
+ function mapComponentParameterType(
298
+ param: ComponentParameter,
299
+ ): ObjectTypePropertySignature {
300
+ const typeAnnotation =
301
+ param.local.type === 'AssignmentPattern'
302
+ ? param.local.left.typeAnnotation
303
+ : param.local.typeAnnotation;
304
+ const optional =
305
+ param.local.type === 'AssignmentPattern'
306
+ ? true
307
+ : param.local.type === 'Identifier'
308
+ ? param.local.optional
309
+ : false;
310
+
311
+ return {
312
+ type: 'ObjectTypeProperty',
313
+ key: shallowCloneNode(param.name),
314
+ value: typeAnnotation?.typeAnnotation ?? {
315
+ type: 'AnyTypeAnnotation',
316
+ loc: param.local.loc,
317
+ range: param.local.range,
318
+ parent: EMPTY_PARENT,
319
+ },
320
+ kind: 'init',
321
+ optional,
322
+ method: false,
323
+ static: false,
324
+ proto: false,
325
+ variance: null,
326
+ loc: param.local.loc,
327
+ range: param.local.range,
328
+ parent: EMPTY_PARENT,
329
+ };
330
+ }
331
+
332
+ function mapComponentParameterRestElementType(
333
+ param: RestElement,
334
+ ): ObjectTypeSpreadProperty {
335
+ if (
336
+ param.argument.type !== 'Identifier' &&
337
+ param.argument.type !== 'ObjectPattern'
338
+ ) {
339
+ throw createSyntaxError(
340
+ param,
341
+ `Invalid ${param.argument.type} encountered in restParameter`,
342
+ );
343
+ }
344
+ return {
345
+ type: 'ObjectTypeSpreadProperty',
346
+ argument: param.argument.typeAnnotation?.typeAnnotation ?? {
347
+ type: 'AnyTypeAnnotation',
348
+ loc: param.loc,
349
+ range: param.range,
350
+ parent: EMPTY_PARENT,
351
+ },
352
+ loc: param.loc,
353
+ range: param.range,
354
+ parent: EMPTY_PARENT,
355
+ };
356
+ }
357
+
250
358
  function mapComponentParameter(
251
359
  param: ComponentParameter | RestElement,
252
360
  ): Array<DestructuringObjectProperty | RestElement> {
@@ -484,6 +592,61 @@ function mapComponentDeclaration(node: ComponentDeclaration): {
484
592
  return {comp, forwardRefDetails};
485
593
  }
486
594
 
595
+ function mapDeclareHook(node: DeclareHook): DeclareFunction {
596
+ return {
597
+ type: 'DeclareFunction',
598
+ id: {
599
+ type: 'Identifier',
600
+ name: node.id.name,
601
+ optional: node.id.optional,
602
+ typeAnnotation: {
603
+ type: 'TypeAnnotation',
604
+ typeAnnotation: {
605
+ type: 'FunctionTypeAnnotation',
606
+ this: null,
607
+ params: node.id.typeAnnotation.typeAnnotation.params,
608
+ typeParameters: node.id.typeAnnotation.typeAnnotation.typeParameters,
609
+ rest: node.id.typeAnnotation.typeAnnotation.rest,
610
+ returnType: node.id.typeAnnotation.typeAnnotation.returnType,
611
+ loc: node.id.typeAnnotation.typeAnnotation.loc,
612
+ range: node.id.typeAnnotation.typeAnnotation.range,
613
+ parent: node.id.typeAnnotation.typeAnnotation.parent,
614
+ },
615
+ loc: node.id.typeAnnotation.loc,
616
+ range: node.id.typeAnnotation.range,
617
+ parent: node.id.typeAnnotation.parent,
618
+ },
619
+ loc: node.id.loc,
620
+ range: node.id.range,
621
+ parent: node.id.parent,
622
+ },
623
+ loc: node.loc,
624
+ range: node.range,
625
+ parent: node.parent,
626
+ predicate: null,
627
+ };
628
+ }
629
+
630
+ function mapHookDeclaration(node: HookDeclaration): FunctionDeclaration {
631
+ const comp = {
632
+ type: 'FunctionDeclaration',
633
+ id: node.id && shallowCloneNode(node.id),
634
+ __hookDeclaration: true,
635
+ typeParameters: node.typeParameters,
636
+ params: node.params,
637
+ returnType: node.returnType,
638
+ body: node.body,
639
+ async: false,
640
+ generator: false,
641
+ predicate: null,
642
+ loc: node.loc,
643
+ range: node.range,
644
+ parent: node.parent,
645
+ };
646
+
647
+ return comp;
648
+ }
649
+
487
650
  /**
488
651
  * Scan a list of statements and return the position of the
489
652
  * first statement that contains a reference to a given component
@@ -559,6 +722,11 @@ function mapStatementList(
559
722
  mapComponentDeclarationIntoList(node, newBody);
560
723
  break;
561
724
  }
725
+ case 'HookDeclaration': {
726
+ const decl = mapHookDeclaration(node);
727
+ newBody.push(decl);
728
+ break;
729
+ }
562
730
  case 'ExportNamedDeclaration': {
563
731
  if (node.declaration?.type === 'ComponentDeclaration') {
564
732
  mapComponentDeclarationIntoList(
@@ -598,6 +766,12 @@ function mapStatementList(
598
766
  break;
599
767
  }
600
768
 
769
+ if (node.declaration?.type === 'HookDeclaration') {
770
+ const comp = mapHookDeclaration(node.declaration);
771
+ newBody.push(comp);
772
+ break;
773
+ }
774
+
601
775
  newBody.push(node);
602
776
  break;
603
777
  }
@@ -611,6 +785,12 @@ function mapStatementList(
611
785
  break;
612
786
  }
613
787
 
788
+ if (node.declaration?.type === 'HookDeclaration') {
789
+ const comp = mapHookDeclaration(node.declaration);
790
+ newBody.push(comp);
791
+ break;
792
+ }
793
+
614
794
  newBody.push(node);
615
795
  break;
616
796
  }
@@ -633,6 +813,9 @@ export function transformProgram(
633
813
  case 'DeclareComponent': {
634
814
  return mapDeclareComponent(node);
635
815
  }
816
+ case 'DeclareHook': {
817
+ return mapDeclareHook(node);
818
+ }
636
819
  case 'Program':
637
820
  case 'BlockStatement': {
638
821
  return nodeWith(node, {body: mapStatementList(node.body)});
@@ -651,6 +834,13 @@ export function transformProgram(
651
834
  `BlockStatement, instead got parent of "${node.parent?.type}".`,
652
835
  );
653
836
  }
837
+ case 'HookDeclaration': {
838
+ throw createSyntaxError(
839
+ node,
840
+ `Hooks must be defined at the top level of a module or within a ` +
841
+ `BlockStatement, instead got parent of "${node.parent?.type}".`,
842
+ );
843
+ }
654
844
  default: {
655
845
  return node;
656
846
  }
@@ -152,6 +152,7 @@ function transformProgram(program, _options) {
152
152
  case 'TupleTypeLabeledElement':
153
153
  case 'TupleTypeSpreadElement':
154
154
  case 'ComponentTypeAnnotation':
155
+ case 'HookTypeAnnotation':
155
156
  case 'TypeOperator':
156
157
  case 'TypePredicate':
157
158
  {
@@ -165,6 +165,7 @@ export function transformProgram(
165
165
  case 'TupleTypeLabeledElement':
166
166
  case 'TupleTypeSpreadElement':
167
167
  case 'ComponentTypeAnnotation':
168
+ case 'HookTypeAnnotation':
168
169
  case 'TypeOperator':
169
170
  case 'TypePredicate': {
170
171
  // Babel does not support these generic types, so convert to any