hermes-estree 0.32.1 → 0.33.1

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 (87) hide show
  1. package/dist/generated/HermesESTreeSelectorTypes.js.flow +262 -27
  2. package/dist/generated/predicates.js +120 -0
  3. package/dist/generated/predicates.js.flow +72 -0
  4. package/dist/predicates.js +2 -4
  5. package/dist/predicates.js.flow +5 -4
  6. package/dist/src/generated/predicates.js +120 -0
  7. package/dist/src/predicates.js +2 -4
  8. package/dist/types.js.flow +103 -11
  9. package/package.json +1 -1
  10. package/dist/HermesAST.js.flow +0 -57
  11. package/dist/HermesASTAdapter.js +0 -192
  12. package/dist/HermesASTAdapter.js.flow +0 -189
  13. package/dist/HermesParser.js +0 -108
  14. package/dist/HermesParser.js.flow +0 -161
  15. package/dist/HermesParserDecodeUTF8String.js +0 -68
  16. package/dist/HermesParserDecodeUTF8String.js.flow +0 -65
  17. package/dist/HermesParserDeserializer.js +0 -242
  18. package/dist/HermesParserDeserializer.js.flow +0 -260
  19. package/dist/HermesParserNodeDeserializers.js +0 -2477
  20. package/dist/HermesParserNodeDeserializers.js.flow +0 -16
  21. package/dist/HermesParserWASM.js +0 -6
  22. package/dist/HermesParserWASM.js.flow +0 -87
  23. package/dist/HermesToESTreeAdapter.js +0 -439
  24. package/dist/HermesToESTreeAdapter.js.flow +0 -421
  25. package/dist/ParserOptions.js +0 -18
  26. package/dist/ParserOptions.js.flow +0 -41
  27. package/dist/babel/TransformESTreeToBabel.js +0 -1123
  28. package/dist/babel/TransformESTreeToBabel.js.flow +0 -1277
  29. package/dist/estree/StripFlowTypes.js +0 -175
  30. package/dist/estree/StripFlowTypes.js.flow +0 -158
  31. package/dist/estree/StripFlowTypesForBabel.js +0 -215
  32. package/dist/estree/StripFlowTypesForBabel.js.flow +0 -216
  33. package/dist/estree/TransformComponentSyntax.js +0 -788
  34. package/dist/estree/TransformComponentSyntax.js.flow +0 -864
  35. package/dist/estree/TransformEnumSyntax.js +0 -106
  36. package/dist/estree/TransformEnumSyntax.js.flow +0 -125
  37. package/dist/estree/TransformMatchSyntax.js +0 -1006
  38. package/dist/estree/TransformMatchSyntax.js.flow +0 -912
  39. package/dist/generated/ESTreeVisitorKeys.js +0 -220
  40. package/dist/generated/ESTreeVisitorKeys.js.flow +0 -15
  41. package/dist/generated/ParserVisitorKeys.js +0 -794
  42. package/dist/generated/ParserVisitorKeys.js.flow +0 -17
  43. package/dist/getModuleDocblock.js +0 -112
  44. package/dist/getModuleDocblock.js.flow +0 -118
  45. package/dist/src/HermesASTAdapter.js +0 -192
  46. package/dist/src/HermesParser.js +0 -108
  47. package/dist/src/HermesParserDecodeUTF8String.js +0 -68
  48. package/dist/src/HermesParserDeserializer.js +0 -242
  49. package/dist/src/HermesParserNodeDeserializers.js +0 -2477
  50. package/dist/src/HermesToESTreeAdapter.js +0 -439
  51. package/dist/src/ParserOptions.js +0 -18
  52. package/dist/src/babel/TransformESTreeToBabel.js +0 -1123
  53. package/dist/src/estree/StripFlowTypes.js +0 -175
  54. package/dist/src/estree/StripFlowTypesForBabel.js +0 -215
  55. package/dist/src/estree/TransformComponentSyntax.js +0 -788
  56. package/dist/src/estree/TransformEnumSyntax.js +0 -106
  57. package/dist/src/estree/TransformMatchSyntax.js +0 -1006
  58. package/dist/src/generated/ESTreeVisitorKeys.js +0 -220
  59. package/dist/src/generated/ParserVisitorKeys.js +0 -794
  60. package/dist/src/getModuleDocblock.js +0 -112
  61. package/dist/src/transform/SimpleTransform.js +0 -136
  62. package/dist/src/transform/astArrayMutationHelpers.js +0 -62
  63. package/dist/src/transform/astNodeMutationHelpers.js +0 -200
  64. package/dist/src/traverse/SimpleTraverser.js +0 -137
  65. package/dist/src/traverse/getVisitorKeys.js +0 -37
  66. package/dist/src/utils/Builders.js +0 -191
  67. package/dist/src/utils/GenID.js +0 -41
  68. package/dist/src/utils/createSyntaxError.js +0 -25
  69. package/dist/src/utils/mutateESTreeASTForPrettier.js +0 -127
  70. package/dist/transform/SimpleTransform.js +0 -136
  71. package/dist/transform/SimpleTransform.js.flow +0 -169
  72. package/dist/transform/astArrayMutationHelpers.js +0 -62
  73. package/dist/transform/astArrayMutationHelpers.js.flow +0 -71
  74. package/dist/transform/astNodeMutationHelpers.js +0 -200
  75. package/dist/transform/astNodeMutationHelpers.js.flow +0 -246
  76. package/dist/traverse/SimpleTraverser.js +0 -137
  77. package/dist/traverse/SimpleTraverser.js.flow +0 -133
  78. package/dist/traverse/getVisitorKeys.js +0 -37
  79. package/dist/traverse/getVisitorKeys.js.flow +0 -36
  80. package/dist/utils/Builders.js +0 -191
  81. package/dist/utils/Builders.js.flow +0 -218
  82. package/dist/utils/GenID.js +0 -41
  83. package/dist/utils/GenID.js.flow +0 -38
  84. package/dist/utils/createSyntaxError.js +0 -25
  85. package/dist/utils/createSyntaxError.js.flow +0 -24
  86. package/dist/utils/mutateESTreeASTForPrettier.js +0 -127
  87. package/dist/utils/mutateESTreeASTForPrettier.js.flow +0 -130
@@ -1,1006 +0,0 @@
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 match expressions and statements.
13
- */
14
-
15
- Object.defineProperty(exports, "__esModule", {
16
- value: true
17
- });
18
- exports.transformProgram = transformProgram;
19
-
20
- var _SimpleTransform = require("../transform/SimpleTransform");
21
-
22
- var _astNodeMutationHelpers = require("../transform/astNodeMutationHelpers");
23
-
24
- var _createSyntaxError = require("../utils/createSyntaxError");
25
-
26
- var _Builders = require("../utils/Builders");
27
-
28
- var _GenID = require("../utils/GenID");
29
-
30
- /**
31
- * Generated identifiers.
32
- * `GenID` is initialized in the transform.
33
- */
34
- let GenID = null;
35
-
36
- function genIdent() {
37
- if (GenID == null) {
38
- throw Error('GenID must be initialized at the start of the transform.');
39
- }
40
-
41
- return (0, _Builders.ident)(GenID.genID());
42
- }
43
- /**
44
- * A series of properties.
45
- * When combined with the match argument (the root expression), provides the
46
- * location of to be tested against, or location to be extracted to a binding.
47
- */
48
-
49
-
50
- function objKeyToString(node) {
51
- switch (node.type) {
52
- case 'Identifier':
53
- return node.name;
54
-
55
- case 'Literal':
56
- {
57
- const {
58
- value
59
- } = node;
60
-
61
- if (typeof value === 'number') {
62
- return String(value);
63
- } else if (typeof value === 'string') {
64
- return value;
65
- } else {
66
- return node.raw;
67
- }
68
- }
69
- }
70
- }
71
-
72
- function convertMemberPattern(pattern) {
73
- const {
74
- base,
75
- property,
76
- loc,
77
- range
78
- } = pattern;
79
- const object = base.type === 'MatchIdentifierPattern' ? base.id : convertMemberPattern(base);
80
-
81
- if (property.type === 'Identifier') {
82
- return {
83
- type: 'MemberExpression',
84
- object,
85
- property,
86
- computed: false,
87
- optional: false,
88
- ...(0, _Builders.etc)({
89
- loc,
90
- range
91
- })
92
- };
93
- } else {
94
- return {
95
- type: 'MemberExpression',
96
- object,
97
- property,
98
- computed: true,
99
- optional: false,
100
- ...(0, _Builders.etc)({
101
- loc,
102
- range
103
- })
104
- };
105
- }
106
- }
107
-
108
- function checkDuplicateBindingName(seenBindingNames, node, name) {
109
- if (seenBindingNames.has(name)) {
110
- throw (0, _createSyntaxError.createSyntaxError)(node, `Duplicate variable name '${name}' in match case pattern.`);
111
- }
112
-
113
- seenBindingNames.add(name);
114
- }
115
-
116
- function checkBindingKind(node, kind) {
117
- if (kind === 'var') {
118
- throw (0, _createSyntaxError.createSyntaxError)(node, `'var' bindings are not allowed. Use 'const' or 'let'.`);
119
- }
120
- }
121
- /**
122
- * Does an object property's pattern require a `prop-exists` condition added?
123
- * If the pattern is a literal like `0`, then it's not required, since the `eq`
124
- * condition implies the prop exists. However, if we could be doing an equality
125
- * check against `undefined`, then it is required, since that will be true even
126
- * if the property doesn't exist.
127
- */
128
-
129
-
130
- function needsPropExistsCond(pattern) {
131
- switch (pattern.type) {
132
- case 'MatchWildcardPattern':
133
- case 'MatchBindingPattern':
134
- case 'MatchIdentifierPattern':
135
- case 'MatchMemberPattern':
136
- return true;
137
-
138
- case 'MatchLiteralPattern':
139
- case 'MatchUnaryPattern':
140
- case 'MatchObjectPattern':
141
- case 'MatchArrayPattern':
142
- return false;
143
-
144
- case 'MatchAsPattern':
145
- {
146
- const {
147
- pattern: asPattern
148
- } = pattern;
149
- return needsPropExistsCond(asPattern);
150
- }
151
-
152
- case 'MatchOrPattern':
153
- {
154
- const {
155
- patterns
156
- } = pattern;
157
- return patterns.some(needsPropExistsCond);
158
- }
159
- }
160
- }
161
- /**
162
- * Analyzes a match pattern, and produced both the conditions and bindings
163
- * produced by that pattern.
164
- */
165
-
166
-
167
- function analyzePattern(pattern, key, seenBindingNames) {
168
- switch (pattern.type) {
169
- case 'MatchWildcardPattern':
170
- {
171
- return {
172
- conditions: [],
173
- bindings: []
174
- };
175
- }
176
-
177
- case 'MatchLiteralPattern':
178
- {
179
- const {
180
- literal
181
- } = pattern;
182
- const condition = {
183
- type: 'eq',
184
- key,
185
- arg: literal
186
- };
187
- return {
188
- conditions: [condition],
189
- bindings: []
190
- };
191
- }
192
-
193
- case 'MatchUnaryPattern':
194
- {
195
- const {
196
- operator,
197
- argument,
198
- loc,
199
- range
200
- } = pattern;
201
-
202
- if (argument.value === 0) {
203
- // We haven't decided whether we will compare these using `===` or `Object.is`
204
- throw (0, _createSyntaxError.createSyntaxError)(pattern, `'+0' and '-0' are not yet supported in match unary patterns.`);
205
- }
206
-
207
- const arg = {
208
- type: 'UnaryExpression',
209
- operator,
210
- argument,
211
- prefix: true,
212
- ...(0, _Builders.etc)({
213
- loc,
214
- range
215
- })
216
- };
217
- const condition = {
218
- type: 'eq',
219
- key,
220
- arg
221
- };
222
- return {
223
- conditions: [condition],
224
- bindings: []
225
- };
226
- }
227
-
228
- case 'MatchIdentifierPattern':
229
- {
230
- const {
231
- id
232
- } = pattern;
233
- const condition = id.name === 'NaN' ? {
234
- type: 'is-nan',
235
- key
236
- } : {
237
- type: 'eq',
238
- key,
239
- arg: id
240
- };
241
- return {
242
- conditions: [condition],
243
- bindings: []
244
- };
245
- }
246
-
247
- case 'MatchMemberPattern':
248
- {
249
- const arg = convertMemberPattern(pattern);
250
- const condition = {
251
- type: 'eq',
252
- key,
253
- arg
254
- };
255
- return {
256
- conditions: [condition],
257
- bindings: []
258
- };
259
- }
260
-
261
- case 'MatchBindingPattern':
262
- {
263
- const {
264
- id,
265
- kind
266
- } = pattern;
267
- checkDuplicateBindingName(seenBindingNames, pattern, id.name);
268
- checkBindingKind(pattern, kind);
269
- const binding = {
270
- type: 'id',
271
- key,
272
- kind,
273
- id
274
- };
275
- return {
276
- conditions: [],
277
- bindings: [binding]
278
- };
279
- }
280
-
281
- case 'MatchAsPattern':
282
- {
283
- const {
284
- pattern: asPattern,
285
- target
286
- } = pattern;
287
-
288
- if (asPattern.type === 'MatchBindingPattern') {
289
- throw (0, _createSyntaxError.createSyntaxError)(pattern, `Match 'as' patterns are not allowed directly on binding patterns.`);
290
- }
291
-
292
- const {
293
- conditions,
294
- bindings
295
- } = analyzePattern(asPattern, key, seenBindingNames);
296
- const [id, kind] = target.type === 'MatchBindingPattern' ? [target.id, target.kind] : [target, 'const'];
297
- checkDuplicateBindingName(seenBindingNames, pattern, id.name);
298
- checkBindingKind(pattern, kind);
299
- const binding = {
300
- type: 'id',
301
- key,
302
- kind,
303
- id
304
- };
305
- return {
306
- conditions,
307
- bindings: bindings.concat(binding)
308
- };
309
- }
310
-
311
- case 'MatchArrayPattern':
312
- {
313
- const {
314
- elements,
315
- rest
316
- } = pattern;
317
- const lengthOp = rest == null ? 'eq' : 'gte';
318
- const conditions = [{
319
- type: 'array',
320
- key,
321
- length: elements.length,
322
- lengthOp
323
- }];
324
- const bindings = [];
325
- elements.forEach((element, i) => {
326
- const elementKey = key.concat((0, _Builders.numberLiteral)(i));
327
- const {
328
- conditions: childConditions,
329
- bindings: childBindings
330
- } = analyzePattern(element, elementKey, seenBindingNames);
331
- conditions.push(...childConditions);
332
- bindings.push(...childBindings);
333
- });
334
-
335
- if (rest != null && rest.argument != null) {
336
- const {
337
- id,
338
- kind
339
- } = rest.argument;
340
- checkDuplicateBindingName(seenBindingNames, rest.argument, id.name);
341
- checkBindingKind(pattern, kind);
342
- bindings.push({
343
- type: 'array-rest',
344
- key,
345
- exclude: elements.length,
346
- kind,
347
- id
348
- });
349
- }
350
-
351
- return {
352
- conditions,
353
- bindings
354
- };
355
- }
356
-
357
- case 'MatchObjectPattern':
358
- {
359
- const {
360
- properties,
361
- rest
362
- } = pattern;
363
- const conditions = [{
364
- type: 'object',
365
- key
366
- }];
367
- const bindings = [];
368
- const objKeys = [];
369
- const seenNames = new Set();
370
- properties.forEach(prop => {
371
- const {
372
- key: objKey,
373
- pattern: propPattern
374
- } = prop;
375
- objKeys.push(objKey);
376
- const name = objKeyToString(objKey);
377
-
378
- if (seenNames.has(name)) {
379
- throw (0, _createSyntaxError.createSyntaxError)(propPattern, `Duplicate property name '${name}' in match object pattern.`);
380
- }
381
-
382
- seenNames.add(name);
383
- const propKey = key.concat(objKey);
384
-
385
- if (needsPropExistsCond(propPattern)) {
386
- conditions.push({
387
- type: 'prop-exists',
388
- key,
389
- propName: name
390
- });
391
- }
392
-
393
- const {
394
- conditions: childConditions,
395
- bindings: childBindings
396
- } = analyzePattern(propPattern, propKey, seenBindingNames);
397
- conditions.push(...childConditions);
398
- bindings.push(...childBindings);
399
- });
400
-
401
- if (rest != null && rest.argument != null) {
402
- const {
403
- id,
404
- kind
405
- } = rest.argument;
406
- checkDuplicateBindingName(seenBindingNames, rest.argument, id.name);
407
- checkBindingKind(pattern, kind);
408
- bindings.push({
409
- type: 'object-rest',
410
- key,
411
- exclude: objKeys,
412
- kind,
413
- id
414
- });
415
- }
416
-
417
- return {
418
- conditions,
419
- bindings
420
- };
421
- }
422
-
423
- case 'MatchOrPattern':
424
- {
425
- const {
426
- patterns
427
- } = pattern;
428
- let hasWildcard = false;
429
- const orConditions = patterns.map(subpattern => {
430
- const {
431
- conditions,
432
- bindings
433
- } = analyzePattern(subpattern, key, seenBindingNames);
434
-
435
- if (bindings.length > 0) {
436
- // We will implement this in the future.
437
- throw (0, _createSyntaxError.createSyntaxError)(pattern, `Bindings in match 'or' patterns are not yet supported.`);
438
- }
439
-
440
- if (conditions.length === 0) {
441
- hasWildcard = true;
442
- }
443
-
444
- return conditions;
445
- });
446
-
447
- if (hasWildcard) {
448
- return {
449
- conditions: [],
450
- bindings: []
451
- };
452
- }
453
-
454
- return {
455
- conditions: [{
456
- type: 'or',
457
- orConditions
458
- }],
459
- bindings: []
460
- };
461
- }
462
- }
463
- }
464
-
465
- function expressionOfKey(root, key) {
466
- return key.reduce((acc, prop) => prop.type === 'Identifier' ? {
467
- type: 'MemberExpression',
468
- object: acc,
469
- property: (0, _astNodeMutationHelpers.shallowCloneNode)(prop),
470
- computed: false,
471
- optional: false,
472
- ...(0, _Builders.etc)()
473
- } : {
474
- type: 'MemberExpression',
475
- object: acc,
476
- property: (0, _astNodeMutationHelpers.shallowCloneNode)(prop),
477
- computed: true,
478
- optional: false,
479
- ...(0, _Builders.etc)()
480
- }, (0, _astNodeMutationHelpers.deepCloneNode)(root));
481
- }
482
-
483
- function testsOfCondition(root, condition) {
484
- switch (condition.type) {
485
- case 'eq':
486
- {
487
- // <x> === <arg>
488
- const {
489
- key,
490
- arg
491
- } = condition;
492
- return [{
493
- type: 'BinaryExpression',
494
- left: expressionOfKey(root, key),
495
- right: arg,
496
- operator: '===',
497
- ...(0, _Builders.etc)()
498
- }];
499
- }
500
-
501
- case 'is-nan':
502
- {
503
- // Number.isNaN(<x>)
504
- const {
505
- key
506
- } = condition;
507
- const callee = {
508
- type: 'MemberExpression',
509
- object: (0, _Builders.ident)('Number'),
510
- property: (0, _Builders.ident)('isNaN'),
511
- computed: false,
512
- optional: false,
513
- ...(0, _Builders.etc)()
514
- };
515
- return [(0, _Builders.callExpression)(callee, [expressionOfKey(root, key)])];
516
- }
517
-
518
- case 'array':
519
- {
520
- // Array.isArray(<x>) && <x>.length === <length>
521
- const {
522
- key,
523
- length,
524
- lengthOp
525
- } = condition;
526
- const operator = lengthOp === 'eq' ? '===' : '>=';
527
- const isArray = (0, _Builders.callExpression)({
528
- type: 'MemberExpression',
529
- object: (0, _Builders.ident)('Array'),
530
- property: (0, _Builders.ident)('isArray'),
531
- computed: false,
532
- optional: false,
533
- ...(0, _Builders.etc)()
534
- }, [expressionOfKey(root, key)]);
535
- const lengthCheck = {
536
- type: 'BinaryExpression',
537
- left: {
538
- type: 'MemberExpression',
539
- object: expressionOfKey(root, key),
540
- property: (0, _Builders.ident)('length'),
541
- computed: false,
542
- optional: false,
543
- ...(0, _Builders.etc)()
544
- },
545
- right: (0, _Builders.numberLiteral)(length),
546
- operator,
547
- ...(0, _Builders.etc)()
548
- };
549
- return [isArray, lengthCheck];
550
- }
551
-
552
- case 'object':
553
- {
554
- // (typeof <x> === 'object' && <x> !== null) || typeof <x> === 'function'
555
- const {
556
- key
557
- } = condition;
558
- const typeofObject = (0, _Builders.typeofExpression)(expressionOfKey(root, key), 'object');
559
- const typeofFunction = (0, _Builders.typeofExpression)(expressionOfKey(root, key), 'function');
560
- const notNull = {
561
- type: 'BinaryExpression',
562
- left: expressionOfKey(root, key),
563
- right: (0, _Builders.nullLiteral)(),
564
- operator: '!==',
565
- ...(0, _Builders.etc)()
566
- };
567
- return [(0, _Builders.disjunction)([(0, _Builders.conjunction)([typeofObject, notNull]), typeofFunction])];
568
- }
569
-
570
- case 'prop-exists':
571
- {
572
- // <propName> in <x>
573
- const {
574
- key,
575
- propName
576
- } = condition;
577
- const inObject = {
578
- type: 'BinaryExpression',
579
- left: (0, _Builders.stringLiteral)(propName),
580
- right: expressionOfKey(root, key),
581
- operator: 'in',
582
- ...(0, _Builders.etc)()
583
- };
584
- return [inObject];
585
- }
586
-
587
- case 'or':
588
- {
589
- // <a> || <b> || ...
590
- const {
591
- orConditions
592
- } = condition;
593
- const tests = orConditions.map(conditions => (0, _Builders.conjunction)(testsOfConditions(root, conditions)));
594
- return [(0, _Builders.disjunction)(tests)];
595
- }
596
- }
597
- }
598
-
599
- function testsOfConditions(root, conditions) {
600
- return conditions.flatMap(condition => testsOfCondition(root, condition));
601
- }
602
-
603
- function statementsOfBindings(root, bindings) {
604
- return bindings.map(binding => {
605
- switch (binding.type) {
606
- case 'id':
607
- {
608
- // const <id> = <x>;
609
- const {
610
- key,
611
- kind,
612
- id
613
- } = binding;
614
- return (0, _Builders.variableDeclaration)(kind, id, expressionOfKey(root, key));
615
- }
616
-
617
- case 'array-rest':
618
- {
619
- // const <id> = <x>.slice(<exclude>);
620
- const {
621
- key,
622
- kind,
623
- id,
624
- exclude
625
- } = binding;
626
- const init = (0, _Builders.callExpression)({
627
- type: 'MemberExpression',
628
- object: expressionOfKey(root, key),
629
- property: (0, _Builders.ident)('slice'),
630
- computed: false,
631
- optional: false,
632
- ...(0, _Builders.etc)()
633
- }, [(0, _Builders.numberLiteral)(exclude)]);
634
- return (0, _Builders.variableDeclaration)(kind, id, init);
635
- }
636
-
637
- case 'object-rest':
638
- {
639
- // const {a: _, b: _, ...<id>} = <x>;
640
- const {
641
- key,
642
- kind,
643
- id,
644
- exclude
645
- } = binding;
646
- const destructuring = {
647
- type: 'ObjectPattern',
648
- properties: exclude.map(prop => prop.type === 'Identifier' ? {
649
- type: 'Property',
650
- key: (0, _astNodeMutationHelpers.shallowCloneNode)(prop),
651
- value: genIdent(),
652
- kind: 'init',
653
- computed: false,
654
- method: false,
655
- shorthand: false,
656
- ...(0, _Builders.etc)(),
657
- parent: _Builders.EMPTY_PARENT
658
- } : {
659
- type: 'Property',
660
- key: (0, _astNodeMutationHelpers.shallowCloneNode)(prop),
661
- value: genIdent(),
662
- kind: 'init',
663
- computed: true,
664
- method: false,
665
- shorthand: false,
666
- ...(0, _Builders.etc)(),
667
- parent: _Builders.EMPTY_PARENT
668
- }).concat({
669
- type: 'RestElement',
670
- argument: id,
671
- ...(0, _Builders.etc)()
672
- }),
673
- typeAnnotation: null,
674
- ...(0, _Builders.etc)()
675
- };
676
- return (0, _Builders.variableDeclaration)(kind, destructuring, expressionOfKey(root, key));
677
- }
678
- }
679
- });
680
- }
681
- /**
682
- * For throwing an error if no cases are matched.
683
- */
684
-
685
-
686
- const fallthroughErrorMsgText = `Match: No case succesfully matched. Make exhaustive or add a wildcard case using '_'.`;
687
-
688
- function fallthroughErrorMsg(value) {
689
- return {
690
- type: 'BinaryExpression',
691
- operator: '+',
692
- left: (0, _Builders.stringLiteral)(`${fallthroughErrorMsgText} Argument: `),
693
- right: value,
694
- ...(0, _Builders.etc)()
695
- };
696
- }
697
-
698
- function fallthroughError(value) {
699
- return (0, _Builders.throwStatement)(fallthroughErrorMsg(value));
700
- }
701
- /**
702
- * If the argument has no side-effects (ignoring getters). Either an identifier
703
- * or member expression with identifier root and non-computed/literal properties.
704
- */
705
-
706
-
707
- function calculateSimpleArgument(node) {
708
- switch (node.type) {
709
- case 'Identifier':
710
- case 'Super':
711
- return true;
712
-
713
- case 'MemberExpression':
714
- {
715
- const {
716
- object,
717
- property,
718
- computed
719
- } = node;
720
-
721
- if (computed && property.type !== 'Literal') {
722
- return false;
723
- }
724
-
725
- return calculateSimpleArgument(object);
726
- }
727
-
728
- default:
729
- return false;
730
- }
731
- }
732
- /**
733
- * Analyze the match cases and return information we will use to build the result.
734
- */
735
-
736
-
737
- function analyzeCases(cases) {
738
- let hasBindings = false;
739
- let hasWildcard = false;
740
- const analyses = [];
741
-
742
- for (let i = 0; i < cases.length; i++) {
743
- const {
744
- pattern,
745
- guard,
746
- body
747
- } = cases[i];
748
- const {
749
- conditions,
750
- bindings
751
- } = analyzePattern(pattern, [], new Set());
752
- hasBindings = hasBindings || bindings.length > 0;
753
- analyses.push({
754
- conditions,
755
- bindings,
756
- guard,
757
- body
758
- }); // This case catches everything, no reason to continue.
759
-
760
- if (conditions.length === 0 && guard == null) {
761
- hasWildcard = true;
762
- break;
763
- }
764
- }
765
-
766
- return {
767
- hasBindings,
768
- hasWildcard,
769
- analyses
770
- };
771
- }
772
- /**
773
- * Match expression transform entry point.
774
- */
775
-
776
-
777
- function mapMatchExpression(node) {
778
- const {
779
- argument,
780
- cases
781
- } = node;
782
- const {
783
- hasBindings,
784
- hasWildcard,
785
- analyses
786
- } = analyzeCases(cases);
787
- const isSimpleArgument = !hasBindings && calculateSimpleArgument(argument);
788
- const genRoot = !isSimpleArgument ? genIdent() : null;
789
- const root = genRoot == null ? argument : genRoot; // No bindings and a simple argument means we can use nested conditional
790
- // expressions.
791
-
792
- if (isSimpleArgument) {
793
- const wildcardAnalaysis = hasWildcard ? analyses.pop() : null;
794
- const lastBody = wildcardAnalaysis != null ? wildcardAnalaysis.body : (0, _Builders.iife)([fallthroughError((0, _astNodeMutationHelpers.shallowCloneNode)(root))]);
795
- return analyses.reverse().reduce((acc, analysis) => {
796
- const {
797
- conditions,
798
- guard,
799
- body
800
- } = analysis;
801
- const tests = testsOfConditions(root, conditions);
802
-
803
- if (guard != null) {
804
- tests.push(guard);
805
- } // <tests> ? <body> : <acc>
806
-
807
-
808
- return {
809
- type: 'ConditionalExpression',
810
- test: (0, _Builders.conjunction)(tests),
811
- consequent: body,
812
- alternate: acc,
813
- ...(0, _Builders.etc)()
814
- };
815
- }, lastBody);
816
- } // There are bindings, so we produce an immediately invoked arrow expression.
817
- // If the original argument is simple, no need for a new variable.
818
-
819
-
820
- const statements = analyses.map(({
821
- conditions,
822
- bindings,
823
- guard,
824
- body
825
- }) => {
826
- const returnNode = {
827
- type: 'ReturnStatement',
828
- argument: body,
829
- ...(0, _Builders.etc)()
830
- }; // If we have a guard, then we use a nested if statement
831
- // `if (<guard>) return <body>`
832
-
833
- const bodyNode = guard == null ? returnNode : {
834
- type: 'IfStatement',
835
- test: guard,
836
- consequent: returnNode,
837
- ...(0, _Builders.etc)()
838
- };
839
- const bindingNodes = statementsOfBindings(root, bindings);
840
- const caseBody = bindingNodes.concat(bodyNode);
841
-
842
- if (conditions.length > 0) {
843
- const tests = testsOfConditions(root, conditions);
844
- return {
845
- type: 'IfStatement',
846
- test: (0, _Builders.conjunction)(tests),
847
- consequent: {
848
- type: 'BlockStatement',
849
- body: caseBody,
850
- ...(0, _Builders.etc)()
851
- },
852
- ...(0, _Builders.etc)()
853
- };
854
- } else {
855
- // No conditions, so no if statement
856
- if (bindingNodes.length > 0) {
857
- // Bindings require a block to introduce a new scope
858
- return {
859
- type: 'BlockStatement',
860
- body: caseBody,
861
- ...(0, _Builders.etc)()
862
- };
863
- } else {
864
- return bodyNode;
865
- }
866
- }
867
- });
868
-
869
- if (!hasWildcard) {
870
- statements.push(fallthroughError((0, _astNodeMutationHelpers.shallowCloneNode)(root)));
871
- }
872
-
873
- const [params, args] = genRoot == null ? [[], []] : [[genRoot], [argument]]; // `((<params>) => { ... })(<args>)`, or
874
- // `(() => { ... })()` if is simple argument.
875
-
876
- return (0, _Builders.iife)(statements, params, args);
877
- }
878
- /**
879
- * Match statement transform entry point.
880
- */
881
-
882
-
883
- function mapMatchStatement(node) {
884
- const {
885
- argument,
886
- cases
887
- } = node;
888
- const {
889
- hasBindings,
890
- hasWildcard,
891
- analyses
892
- } = analyzeCases(cases);
893
- const topLabel = genIdent();
894
- const isSimpleArgument = !hasBindings && calculateSimpleArgument(argument);
895
- const genRoot = !isSimpleArgument ? genIdent() : null;
896
- const root = genRoot == null ? argument : genRoot;
897
- const statements = [];
898
-
899
- if (genRoot != null) {
900
- statements.push((0, _Builders.variableDeclaration)('const', genRoot, argument));
901
- }
902
-
903
- analyses.forEach(({
904
- conditions,
905
- bindings,
906
- guard,
907
- body
908
- }) => {
909
- const breakNode = {
910
- type: 'BreakStatement',
911
- label: (0, _astNodeMutationHelpers.shallowCloneNode)(topLabel),
912
- ...(0, _Builders.etc)()
913
- };
914
- const bodyStatements = body.body.concat(breakNode); // If we have a guard, then we use a nested if statement
915
- // `if (<guard>) return <body>`
916
-
917
- const guardedBodyStatements = guard == null ? bodyStatements : [{
918
- type: 'IfStatement',
919
- test: guard,
920
- consequent: {
921
- type: 'BlockStatement',
922
- body: bodyStatements,
923
- ...(0, _Builders.etc)()
924
- },
925
- ...(0, _Builders.etc)()
926
- }];
927
- const bindingNodes = statementsOfBindings(root, bindings);
928
- const caseBody = bindingNodes.concat(guardedBodyStatements);
929
-
930
- if (conditions.length > 0) {
931
- const tests = testsOfConditions(root, conditions);
932
- statements.push({
933
- type: 'IfStatement',
934
- test: (0, _Builders.conjunction)(tests),
935
- consequent: {
936
- type: 'BlockStatement',
937
- body: caseBody,
938
- ...(0, _Builders.etc)()
939
- },
940
- ...(0, _Builders.etc)()
941
- });
942
- } else {
943
- // No conditions, so no if statement
944
- statements.push({
945
- type: 'BlockStatement',
946
- body: caseBody,
947
- ...(0, _Builders.etc)()
948
- });
949
- }
950
- });
951
-
952
- if (!hasWildcard) {
953
- statements.push(fallthroughError((0, _astNodeMutationHelpers.shallowCloneNode)(root)));
954
- }
955
-
956
- return {
957
- type: 'LabeledStatement',
958
- label: topLabel,
959
- body: {
960
- type: 'BlockStatement',
961
- body: statements,
962
- ...(0, _Builders.etc)()
963
- },
964
- ...(0, _Builders.etc)()
965
- };
966
- }
967
-
968
- function transformProgram(program, _options) {
969
- // Initialize so each file transformed starts freshly incrementing the
970
- // variable name counter, and has its own usage tracking.
971
- GenID = (0, _GenID.createGenID)('m');
972
- return _SimpleTransform.SimpleTransform.transformProgram(program, {
973
- transform(node) {
974
- switch (node.type) {
975
- case 'MatchExpression':
976
- {
977
- return mapMatchExpression(node);
978
- }
979
-
980
- case 'MatchStatement':
981
- {
982
- return mapMatchStatement(node);
983
- }
984
-
985
- case 'Identifier':
986
- {
987
- // A rudimentary check to avoid some collisions with our generated
988
- // variable names. Ideally, we would have access a scope analyzer
989
- // inside the transform instead.
990
- if (GenID == null) {
991
- throw Error('GenID must be initialized at the start of the transform.');
992
- }
993
-
994
- GenID.addUsage(node.name);
995
- return node;
996
- }
997
-
998
- default:
999
- {
1000
- return node;
1001
- }
1002
- }
1003
- }
1004
-
1005
- });
1006
- }