esrap 2.2.11 → 2.2.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esrap",
3
- "version": "2.2.11",
3
+ "version": "2.2.12",
4
4
  "description": "Parse in reverse",
5
5
  "repository": {
6
6
  "type": "git",
@@ -511,23 +511,11 @@ export default (options = {}) => {
511
511
  // // Avoids confusion in `for` loops initializers
512
512
  // chunks.write('(');
513
513
  // }
514
- if (needs_parens(node.left, node, false)) {
515
- context.write('(');
516
- context.visit(node.left);
517
- context.write(')');
518
- } else {
519
- context.visit(node.left);
520
- }
514
+ maybe_wrap(context, node.left, operand_needs_wrap(node.left, node, false));
521
515
 
522
516
  context.write(` ${node.operator} `);
523
517
 
524
- if (needs_parens(node.right, node, true)) {
525
- context.write('(');
526
- context.visit(node.right);
527
- context.write(')');
528
- } else {
529
- context.visit(node.right);
530
- }
518
+ maybe_wrap(context, node.right, operand_needs_wrap(node.right, node, true));
531
519
  },
532
520
 
533
521
  /**
@@ -575,17 +563,11 @@ export default (options = {}) => {
575
563
  write_keyword(context, node, 'new', ' ');
576
564
  }
577
565
 
578
- const needs_parens =
566
+ const wrap =
567
+ node.callee.type === 'ChainExpression' ||
579
568
  EXPRESSIONS_PRECEDENCE[node.callee.type] < EXPRESSIONS_PRECEDENCE.CallExpression ||
580
569
  (node.type === 'NewExpression' && has_call_expression(node.callee));
581
-
582
- if (needs_parens) {
583
- context.write('(');
584
- context.visit(node.callee);
585
- context.write(')');
586
- } else {
587
- context.visit(node.callee);
588
- }
570
+ maybe_wrap(context, node.callee, wrap);
589
571
 
590
572
  if (/** @type {TSESTree.CallExpression} */ (node).optional) {
591
573
  context.write('?.');
@@ -926,7 +908,6 @@ export default (options = {}) => {
926
908
  }
927
909
 
928
910
  context.write('(');
929
-
930
911
  sequence(
931
912
  context,
932
913
  // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
@@ -953,7 +934,6 @@ export default (options = {}) => {
953
934
  if (node.typeParameters) context.visit(node.typeParameters);
954
935
 
955
936
  context.write('(');
956
-
957
937
  sequence(
958
938
  context,
959
939
  // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
@@ -964,8 +944,9 @@ export default (options = {}) => {
964
944
  null,
965
945
  false
966
946
  );
947
+ context.write(')');
967
948
 
968
- context.write(') => ');
949
+ context.write(' => ');
969
950
 
970
951
  // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
971
952
  context.visit(node.typeAnnotation?.typeAnnotation ?? node.returnType?.typeAnnotation);
@@ -1011,13 +992,7 @@ export default (options = {}) => {
1011
992
 
1012
993
  context.write(' => ');
1013
994
 
1014
- if (arrow_concise_body_needs_wrap(node.body)) {
1015
- context.write('(');
1016
- context.visit(node.body);
1017
- context.write(')');
1018
- } else {
1019
- context.visit(node.body);
1020
- }
995
+ maybe_wrap(context, node.body, arrow_concise_body_needs_wrap(node.body));
1021
996
  },
1022
997
 
1023
998
  AssignmentExpression(node, context) {
@@ -1076,13 +1051,9 @@ export default (options = {}) => {
1076
1051
  ClassExpression: shared['ClassDeclaration|ClassExpression'],
1077
1052
 
1078
1053
  ConditionalExpression(node, context) {
1079
- if (EXPRESSIONS_PRECEDENCE[node.test.type] > EXPRESSIONS_PRECEDENCE.ConditionalExpression) {
1080
- context.visit(node.test);
1081
- } else {
1082
- context.write('(');
1083
- context.visit(node.test);
1084
- context.write(')');
1085
- }
1054
+ const wrap =
1055
+ EXPRESSIONS_PRECEDENCE[node.test.type] <= EXPRESSIONS_PRECEDENCE.ConditionalExpression;
1056
+ maybe_wrap(context, node.test, wrap);
1086
1057
 
1087
1058
  const consequent = context.new();
1088
1059
  const alternate = context.new();
@@ -1240,20 +1211,13 @@ export default (options = {}) => {
1240
1211
  },
1241
1212
 
1242
1213
  ExpressionStatement(node, context) {
1243
- if (
1214
+ // wrap when a leading `{`/`function` would otherwise be parsed as a block/declaration
1215
+ const wrap =
1244
1216
  node.expression.type === 'ObjectExpression' ||
1245
1217
  (node.expression.type === 'AssignmentExpression' &&
1246
1218
  node.expression.left.type === 'ObjectPattern') ||
1247
- node.expression.type === 'FunctionExpression'
1248
- ) {
1249
- // is an AssignmentExpression to an ObjectPattern
1250
- context.write('(');
1251
- context.visit(node.expression);
1252
- context.write(');');
1253
- return;
1254
- }
1255
-
1256
- context.visit(node.expression);
1219
+ node.expression.type === 'FunctionExpression';
1220
+ maybe_wrap(context, node.expression, wrap);
1257
1221
  context.write(';');
1258
1222
  },
1259
1223
 
@@ -1289,6 +1253,7 @@ export default (options = {}) => {
1289
1253
  let name = node.name;
1290
1254
  context.write(name, node);
1291
1255
 
1256
+ if (node.optional) context.write('?');
1292
1257
  if (node.typeAnnotation) context.visit(node.typeAnnotation);
1293
1258
  },
1294
1259
 
@@ -1436,13 +1401,10 @@ export default (options = {}) => {
1436
1401
  LogicalExpression: shared['BinaryExpression|LogicalExpression'],
1437
1402
 
1438
1403
  MemberExpression(node, context) {
1439
- if (EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression) {
1440
- context.write('(');
1441
- context.visit(node.object);
1442
- context.write(')');
1443
- } else {
1444
- context.visit(node.object);
1445
- }
1404
+ const wrap =
1405
+ node.object.type === 'ChainExpression' ||
1406
+ EXPRESSIONS_PRECEDENCE[node.object.type] < EXPRESSIONS_PRECEDENCE.MemberExpression;
1407
+ maybe_wrap(context, node.object, wrap);
1446
1408
 
1447
1409
  if (node.computed) {
1448
1410
  if (node.optional) {
@@ -1483,9 +1445,7 @@ export default (options = {}) => {
1483
1445
 
1484
1446
  // @ts-expect-error this isn't a real node type, but Acorn produces it
1485
1447
  ParenthesizedExpression(node, context) {
1486
- context.write('(');
1487
- context.visit(node.expression);
1488
- context.write(')');
1448
+ maybe_wrap(context, node.expression, true);
1489
1449
  },
1490
1450
 
1491
1451
  PrivateIdentifier(node, context) {
@@ -1634,7 +1594,7 @@ export default (options = {}) => {
1634
1594
  },
1635
1595
 
1636
1596
  TaggedTemplateExpression(node, context) {
1637
- context.visit(node.tag);
1597
+ maybe_wrap(context, node.tag, node.tag.type === 'ChainExpression');
1638
1598
  context.visit(node.quasi);
1639
1599
  },
1640
1600
 
@@ -1707,15 +1667,19 @@ export default (options = {}) => {
1707
1667
 
1708
1668
  if (node.operator.length > 1) {
1709
1669
  context.write(' ');
1670
+ } else if (
1671
+ (node.operator === '+' || node.operator === '-') &&
1672
+ ((node.argument.type === 'UnaryExpression' && node.argument.operator === node.operator) ||
1673
+ (node.argument.type === 'UpdateExpression' &&
1674
+ node.argument.prefix &&
1675
+ node.argument.operator[0] === node.operator))
1676
+ ) {
1677
+ context.write(' ');
1710
1678
  }
1711
1679
 
1712
- if (EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression) {
1713
- context.write('(');
1714
- context.visit(node.argument);
1715
- context.write(')');
1716
- } else {
1717
- context.visit(node.argument);
1718
- }
1680
+ const wrap =
1681
+ EXPRESSIONS_PRECEDENCE[node.argument.type] < EXPRESSIONS_PRECEDENCE.UnaryExpression;
1682
+ maybe_wrap(context, node.argument, wrap);
1719
1683
  },
1720
1684
 
1721
1685
  UpdateExpression(node, context) {
@@ -1951,13 +1915,9 @@ export default (options = {}) => {
1951
1915
  context.write('<');
1952
1916
  context.visit(node.typeAnnotation);
1953
1917
  context.write('>');
1954
- if (EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSTypeAssertion) {
1955
- context.write('(');
1956
- context.visit(node.expression);
1957
- context.write(')');
1958
- } else {
1959
- context.visit(node.expression);
1960
- }
1918
+ const wrap =
1919
+ EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSTypeAssertion;
1920
+ maybe_wrap(context, node.expression, wrap);
1961
1921
  },
1962
1922
 
1963
1923
  TSTypeParameterInstantiation(node, context) {
@@ -2076,7 +2036,6 @@ export default (options = {}) => {
2076
2036
  context.visit(node.key);
2077
2037
 
2078
2038
  context.write('(');
2079
-
2080
2039
  sequence(
2081
2040
  context,
2082
2041
  // @ts-expect-error `acorn-typescript` and `@typescript-eslint/types` have slightly different type definitions
@@ -2190,16 +2149,9 @@ export default (options = {}) => {
2190
2149
 
2191
2150
  TSAsExpression(node, context) {
2192
2151
  if (node.expression) {
2193
- const needs_parens =
2152
+ const wrap =
2194
2153
  EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSAsExpression;
2195
-
2196
- if (needs_parens) {
2197
- context.write('(');
2198
- context.visit(node.expression);
2199
- context.write(')');
2200
- } else {
2201
- context.visit(node.expression);
2202
- }
2154
+ maybe_wrap(context, node.expression, wrap);
2203
2155
  }
2204
2156
  context.write(' as ');
2205
2157
  context.visit(node.typeAnnotation);
@@ -2245,15 +2197,9 @@ export default (options = {}) => {
2245
2197
 
2246
2198
  TSNonNullExpression(node, context) {
2247
2199
  // operator expressions can't take a postfix `!` directly: `(0 as number)!`, `(await x)!`
2248
- if (
2249
- EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSNonNullExpression
2250
- ) {
2251
- context.write('(');
2252
- context.visit(node.expression);
2253
- context.write(')');
2254
- } else {
2255
- context.visit(node.expression);
2256
- }
2200
+ const wrap =
2201
+ EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSNonNullExpression;
2202
+ maybe_wrap(context, node.expression, wrap);
2257
2203
  context.write('!');
2258
2204
  },
2259
2205
 
@@ -2287,24 +2233,15 @@ export default (options = {}) => {
2287
2233
 
2288
2234
  //@ts-expect-error I don't know why, but this is relied upon in the tests, but doesn't exist in the TSESTree types
2289
2235
  TSParenthesizedType(node, context) {
2290
- context.write('(');
2291
- context.visit(node.typeAnnotation);
2292
- context.write(')');
2236
+ maybe_wrap(context, node.typeAnnotation, true);
2293
2237
  },
2294
2238
 
2295
2239
  TSSatisfiesExpression(node, context) {
2296
2240
  if (node.expression) {
2297
- const needs_parens =
2241
+ const wrap =
2298
2242
  EXPRESSIONS_PRECEDENCE[node.expression.type] <
2299
2243
  EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression;
2300
-
2301
- if (needs_parens) {
2302
- context.write('(');
2303
- context.visit(node.expression);
2304
- context.write(')');
2305
- } else {
2306
- context.visit(node.expression);
2307
- }
2244
+ maybe_wrap(context, node.expression, wrap);
2308
2245
  }
2309
2246
  context.write(' satisfies ');
2310
2247
  context.visit(node.typeAnnotation);
@@ -2364,7 +2301,7 @@ function arrow_concise_body_needs_wrap(body) {
2364
2301
  * @param {boolean} is_right
2365
2302
  * @returns
2366
2303
  */
2367
- function needs_parens(node, parent, is_right) {
2304
+ function operand_needs_wrap(node, parent, is_right) {
2368
2305
  if (node.type === 'PrivateIdentifier') return false;
2369
2306
 
2370
2307
  if (!is_right && (node.type === 'TSAsExpression' || node.type === 'TSSatisfiesExpression')) {
@@ -2383,42 +2320,45 @@ function needs_parens(node, parent, is_right) {
2383
2320
  return true;
2384
2321
  }
2385
2322
 
2323
+ // `**` can't take a unary/await left operand: `-2 ** 2`, `await x ** 2` are syntax errors
2324
+ const unary_base_of_pow =
2325
+ !is_right &&
2326
+ parent.operator === '**' &&
2327
+ (node.type === 'UnaryExpression' || node.type === 'AwaitExpression');
2328
+ if (unary_base_of_pow) return true;
2329
+
2386
2330
  const precedence = EXPRESSIONS_PRECEDENCE[node.type];
2387
2331
  const parent_precedence = EXPRESSIONS_PRECEDENCE[parent.type];
2332
+ if (precedence !== parent_precedence) return precedence < parent_precedence;
2388
2333
 
2389
- if (precedence !== parent_precedence) {
2390
- // Different node types
2391
- return (
2392
- (!is_right && precedence === 15 && parent_precedence === 14 && parent.operator === '**') ||
2393
- precedence < parent_precedence
2394
- );
2395
- }
2396
-
2397
- if (precedence !== 12 && precedence !== 14) {
2398
- // Not a `LogicalExpression` or `BinaryExpression`
2399
- return false;
2400
- }
2334
+ const operator = /** @type {TSESTree.BinaryExpression} */ (node).operator;
2401
2335
 
2402
- if (
2403
- /** @type {TSESTree.BinaryExpression} */ (node).operator === '**' &&
2404
- parent.operator === '**'
2405
- ) {
2406
- // Exponentiation operator has right-to-left associativity
2336
+ if (operator === '**' && parent.operator === '**') {
2337
+ // exponentiation is right-associative
2407
2338
  return !is_right;
2408
2339
  }
2409
2340
 
2410
2341
  if (is_right) {
2411
- // Parenthesis are used if both operators have the same precedence
2412
- return (
2413
- OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <=
2414
- OPERATOR_PRECEDENCE[parent.operator]
2415
- );
2342
+ // parentheses are needed when both operators have the same precedence
2343
+ return OPERATOR_PRECEDENCE[operator] <= OPERATOR_PRECEDENCE[parent.operator];
2416
2344
  }
2417
2345
 
2418
- return (
2419
- OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <
2420
- OPERATOR_PRECEDENCE[parent.operator]
2421
- );
2346
+ return OPERATOR_PRECEDENCE[operator] < OPERATOR_PRECEDENCE[parent.operator];
2347
+ }
2348
+
2349
+ /**
2350
+ * @param {Context} context
2351
+ * @param {TSESTree.Node} node
2352
+ * @param {boolean} wrap
2353
+ */
2354
+ function maybe_wrap(context, node, wrap) {
2355
+ if (wrap) {
2356
+ context.write('(');
2357
+ context.visit(node);
2358
+ context.write(')');
2359
+ } else {
2360
+ context.visit(node);
2361
+ }
2422
2362
  }
2423
2363
 
2424
2364
  /** @param {TSESTree.Node} node */
@@ -2432,6 +2372,7 @@ function has_call_expression(node) {
2432
2372
  return false;
2433
2373
  }
2434
2374
  }
2375
+ return false;
2435
2376
  }
2436
2377
 
2437
2378
  /**