babel-plugin-jsx-dom-expressions 0.35.0-beta.0 → 0.35.0-beta.2

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 (2) hide show
  1. package/index.js +195 -92
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -57,24 +57,36 @@ const booleans = [
57
57
 
58
58
  const BooleanAttributes = /*#__PURE__*/ new Set(booleans);
59
59
 
60
- const Properties = /*#__PURE__*/ new Set(["className", "value", "readOnly", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]);
60
+ const Properties = /*#__PURE__*/ new Set([
61
+ "className",
62
+ "value",
63
+ "readOnly",
64
+ "formNoValidate",
65
+ "isMap",
66
+ "noModule",
67
+ "playsInline",
68
+ ...booleans
69
+ ]);
61
70
 
62
- const ChildProperties = /*#__PURE__*/ new Set(["innerHTML", "textContent", "innerText", "children"]);
71
+ const ChildProperties = /*#__PURE__*/ new Set([
72
+ "innerHTML",
73
+ "textContent",
74
+ "innerText",
75
+ "children"
76
+ ]);
63
77
 
64
78
  // React Compat
65
- const Aliases = {
66
- className: "class",
67
- htmlFor: "for"
68
- };
69
-
70
- const PropAliases = {
71
- class: "className",
72
- formnovalidate: "formNoValidate",
73
- ismap: "isMap",
74
- nomodule: "noModule",
75
- playsinline: "playsInline",
76
- readonly: "readOnly"
77
- };
79
+ const Aliases = Object.create(null);
80
+ Aliases.className = "class";
81
+ Aliases.htmlFor = "for";
82
+
83
+ const PropAliases = Object.create(null);
84
+ PropAliases.class = "className";
85
+ PropAliases.formnovalidate = "formNoValidate";
86
+ PropAliases.ismap = "isMap";
87
+ PropAliases.nomodule = "noModule";
88
+ PropAliases.playsinline = "playsInline";
89
+ PropAliases.readonly = "readOnly";
78
90
 
79
91
  // list of Element events that will be delegated
80
92
  const DelegatedEvents = /*#__PURE__*/ new Set([
@@ -419,7 +431,7 @@ function wrappedByText(list, startIndex) {
419
431
  return false;
420
432
  }
421
433
 
422
- function transformCondition(path, inline, deep) {
434
+ function transformCondition$1(path, inline, deep) {
423
435
  const config = getConfig(path);
424
436
  const expr = path.node;
425
437
  const memo = registerImportMethod(path, config.memoWrapper);
@@ -441,10 +453,10 @@ function transformCondition(path, inline, deep) {
441
453
  : path.scope.generateUidIdentifier("_c$");
442
454
  expr.test = t__namespace.callExpression(id, []);
443
455
  if (t__namespace.isConditionalExpression(expr.consequent) || t__namespace.isLogicalExpression(expr.consequent)) {
444
- expr.consequent = transformCondition(path.get("consequent"), inline, true);
456
+ expr.consequent = transformCondition$1(path.get("consequent"), inline, true);
445
457
  }
446
458
  if (t__namespace.isConditionalExpression(expr.alternate) || t__namespace.isLogicalExpression(expr.alternate)) {
447
- expr.alternate = transformCondition(path.get("alternate"), inline, true);
459
+ expr.alternate = transformCondition$1(path.get("alternate"), inline, true);
448
460
  }
449
461
  }
450
462
  } else if (t__namespace.isLogicalExpression(expr)) {
@@ -542,6 +554,25 @@ function escapeHTML(s, attr) {
542
554
  return left < s.length ? out + s.substring(left) : out;
543
555
  }
544
556
 
557
+ function convertJSXIdentifier(node) {
558
+ if (t__namespace.isJSXIdentifier(node)) {
559
+ if (t__namespace.isValidIdentifier(node.name)) {
560
+ node.type = "Identifier";
561
+ } else {
562
+ return t__namespace.stringLiteral(node.name);
563
+ }
564
+ } else if (t__namespace.isJSXMemberExpression(node)) {
565
+ return t__namespace.memberExpression(
566
+ convertJSXIdentifier(node.object),
567
+ convertJSXIdentifier(node.property)
568
+ );
569
+ } else if (t__namespace.isJSXNamespacedName(node)) {
570
+ return t__namespace.stringLiteral(`${node.namespace.name}:${node.name.name}`);
571
+ }
572
+
573
+ return node;
574
+ }
575
+
545
576
  function canNativeSpread(key, { checkNameSpaces } = {}) {
546
577
  if (checkNameSpaces && key.includes(":") && nonSpreadNameSpaces.has(key.split(":")[0])) return false;
547
578
  // TODO: figure out how to detect definitely function ref
@@ -566,8 +597,27 @@ function transformElement$3(path, info) {
566
597
  tagName,
567
598
  renderer: "dom"
568
599
  };
569
- if (config.hydratable && (tagName === "html" || tagName === "head" || tagName === "body"))
600
+ if (config.hydratable && (tagName === "html" || tagName === "head" || tagName === "body")) {
570
601
  results.skipTemplate = true;
602
+ if (tagName === "head" && info.topLevel) {
603
+ const createComponent = registerImportMethod(
604
+ path,
605
+ "createComponent",
606
+ getRendererConfig(path, "dom").moduleName
607
+ );
608
+ const NoHydration = registerImportMethod(
609
+ path,
610
+ "NoHydration",
611
+ getRendererConfig(path, "dom").moduleName
612
+ );
613
+ results.exprs.push(
614
+ t__namespace.expressionStatement(
615
+ t__namespace.callExpression(createComponent, [NoHydration, t__namespace.objectExpression([])])
616
+ )
617
+ );
618
+ return results;
619
+ }
620
+ }
571
621
  if (wrapSVG) results.template = "<svg>" + results.template;
572
622
  if (!info.skipId) results.id = path.scope.generateUidIdentifier("el$");
573
623
  transformAttributes$2(path, results);
@@ -706,7 +756,12 @@ function transformAttributes$2(path, results) {
706
756
 
707
757
  // preprocess spreads
708
758
  if (attributes.some(attribute => t__namespace.isJSXSpreadAttribute(attribute.node))) {
709
- [attributes, spreadExpr] = processSpreads$1(path, attributes, { elem, isSVG, hasChildren });
759
+ [attributes, spreadExpr] = processSpreads$1(path, attributes, {
760
+ elem,
761
+ isSVG,
762
+ hasChildren,
763
+ wrapConditionals: config.wrapConditionals
764
+ });
710
765
  path.get("openingElement").set(
711
766
  "attributes",
712
767
  attributes.map(a => a.node)
@@ -1173,7 +1228,26 @@ function transformChildren$2(path, results, config) {
1173
1228
 
1174
1229
  results.template += child.template;
1175
1230
  if (child.id) {
1176
- if (child.tagName === "head") return;
1231
+ if (child.tagName === "head") {
1232
+ if (config.hydratable) {
1233
+ const createComponent = registerImportMethod(
1234
+ path,
1235
+ "createComponent",
1236
+ getRendererConfig(path, "dom").moduleName
1237
+ );
1238
+ const NoHydration = registerImportMethod(
1239
+ path,
1240
+ "NoHydration",
1241
+ getRendererConfig(path, "dom").moduleName
1242
+ );
1243
+ results.exprs.push(
1244
+ t__namespace.expressionStatement(
1245
+ t__namespace.callExpression(createComponent, [NoHydration, t__namespace.objectExpression([])])
1246
+ )
1247
+ );
1248
+ }
1249
+ return;
1250
+ }
1177
1251
 
1178
1252
  let getNextMatch;
1179
1253
  if (config.hydratable && tagName === "html") {
@@ -1339,12 +1413,11 @@ function contextToCustomElement(path, results) {
1339
1413
  );
1340
1414
  }
1341
1415
 
1342
- function processSpreads$1(path, attributes, { elem, isSVG, hasChildren }) {
1416
+ function processSpreads$1(path, attributes, { elem, isSVG, hasChildren, wrapConditionals }) {
1343
1417
  // TODO: skip but collect the names of any properties after the last spread to not overwrite them
1344
1418
  const filteredAttributes = [];
1345
1419
  const spreadArgs = [];
1346
1420
  let runningObject = [];
1347
- let runningDynamic = false;
1348
1421
  let dynamicSpread = false;
1349
1422
  let firstSpread = false;
1350
1423
  attributes.forEach(attribute => {
@@ -1357,12 +1430,7 @@ function processSpreads$1(path, attributes, { elem, isSVG, hasChildren }) {
1357
1430
  if (t__namespace.isJSXSpreadAttribute(node)) {
1358
1431
  firstSpread = true;
1359
1432
  if (runningObject.length) {
1360
- spreadArgs.push(
1361
- runningDynamic
1362
- ? t__namespace.arrowFunctionExpression([], t__namespace.objectExpression(runningObject))
1363
- : t__namespace.objectExpression(runningObject)
1364
- );
1365
- runningDynamic = false;
1433
+ spreadArgs.push(t__namespace.objectExpression(runningObject));
1366
1434
  runningObject = [];
1367
1435
  }
1368
1436
  spreadArgs.push(
@@ -1384,24 +1452,38 @@ function processSpreads$1(path, attributes, { elem, isSVG, hasChildren }) {
1384
1452
  canNativeSpread(key, { checkNameSpaces: true })
1385
1453
  ) {
1386
1454
  const isContainer = t__namespace.isJSXExpressionContainer(node.value);
1387
- runningDynamic =
1388
- runningDynamic ||
1389
- (isContainer && isDynamic(attribute.get("value").get("expression"), { checkMember: true }));
1390
- runningObject.push(
1391
- t__namespace.objectProperty(
1392
- t__namespace.stringLiteral(key),
1393
- isContainer ? node.value.expression : node.value || t__namespace.stringLiteral("")
1394
- )
1395
- );
1455
+ const dynamic =
1456
+ isContainer && isDynamic(attribute.get("value").get("expression"), { checkMember: true });
1457
+ if (dynamic) {
1458
+ const id = convertJSXIdentifier(node.name);
1459
+ let expr =
1460
+ wrapConditionals &&
1461
+ (t__namespace.isLogicalExpression(node.value.expression) ||
1462
+ t__namespace.isConditionalExpression(node.value.expression))
1463
+ ? transformCondition(attribute.get("value").get("expression"), true)
1464
+ : t__namespace.arrowFunctionExpression([], node.value.expression);
1465
+ runningObject.push(
1466
+ t__namespace.objectMethod(
1467
+ "get",
1468
+ id,
1469
+ [],
1470
+ t__namespace.blockStatement([t__namespace.returnStatement(expr.body)]),
1471
+ !t__namespace.isValidIdentifier(key)
1472
+ )
1473
+ );
1474
+ } else {
1475
+ runningObject.push(
1476
+ t__namespace.objectProperty(
1477
+ t__namespace.stringLiteral(key),
1478
+ isContainer ? node.value.expression : node.value || t__namespace.stringLiteral("")
1479
+ )
1480
+ );
1481
+ }
1396
1482
  } else filteredAttributes.push(attribute);
1397
1483
  });
1398
1484
 
1399
1485
  if (runningObject.length) {
1400
- spreadArgs.push(
1401
- runningDynamic
1402
- ? t__namespace.arrowFunctionExpression([], t__namespace.objectExpression(runningObject))
1403
- : t__namespace.objectExpression(runningObject)
1404
- );
1486
+ spreadArgs.push(t__namespace.objectExpression(runningObject));
1405
1487
  }
1406
1488
 
1407
1489
  const props =
@@ -1654,7 +1736,7 @@ function createTemplate$1(path, result) {
1654
1736
 
1655
1737
  return t__namespace.callExpression(
1656
1738
  registerImportMethod(path, "ssr"),
1657
- result.template.length > 1 ? [id, ...result.templateValues] : [id]
1739
+ Array.isArray(result.template) && result.template.length > 1 ? [id, ...result.templateValues] : [id]
1658
1740
  );
1659
1741
  }
1660
1742
 
@@ -1693,6 +1775,26 @@ function transformElement$2(path, info) {
1693
1775
  };
1694
1776
 
1695
1777
  if (info.topLevel && config.hydratable) {
1778
+ if (tagName === "head") {
1779
+ registerImportMethod(path, "NoHydration");
1780
+ registerImportMethod(path, "createComponent");
1781
+ const child = transformElement$2(path, { ...info, topLevel: false });
1782
+ results.template = "";
1783
+ results.exprs.push(
1784
+ t__namespace.callExpression(t__namespace.identifier("_$createComponent"), [
1785
+ t__namespace.identifier("_$NoHydration"),
1786
+ t__namespace.objectExpression([
1787
+ t__namespace.objectMethod(
1788
+ "get",
1789
+ t__namespace.identifier("children"),
1790
+ [],
1791
+ t__namespace.blockStatement([t__namespace.returnStatement(createTemplate$1(path, child))])
1792
+ )
1793
+ ])
1794
+ ])
1795
+ );
1796
+ return results;
1797
+ }
1696
1798
  results.template.push("");
1697
1799
  results.templateValues.push(
1698
1800
  t__namespace.callExpression(registerImportMethod(path, "ssrHydrationKey"), [])
@@ -2039,12 +2141,20 @@ function transformChildren$1(path, results, { hydratable }) {
2039
2141
  filteredChildren.forEach(node => {
2040
2142
  if (t__namespace.isJSXElement(node.node) && getTagName(node.node) === "head") {
2041
2143
  const child = transformNode(node, { doNotEscape, hydratable: false });
2042
- registerImportMethod(path, "setHydratable");
2144
+ registerImportMethod(path, "NoHydration");
2145
+ registerImportMethod(path, "createComponent");
2043
2146
  results.template.push("");
2044
2147
  results.templateValues.push(
2045
- t__namespace.callExpression(t__namespace.identifier("_$setHydratable"), [
2046
- t__namespace.arrowFunctionExpression([], createTemplate$1(path, child)),
2047
- t__namespace.booleanLiteral(false)
2148
+ t__namespace.callExpression(t__namespace.identifier("_$createComponent"), [
2149
+ t__namespace.identifier("_$NoHydration"),
2150
+ t__namespace.objectExpression([
2151
+ t__namespace.objectMethod(
2152
+ "get",
2153
+ t__namespace.identifier("children"),
2154
+ [],
2155
+ t__namespace.blockStatement([t__namespace.returnStatement(createTemplate$1(path, child))])
2156
+ )
2157
+ ])
2048
2158
  ])
2049
2159
  );
2050
2160
  return;
@@ -2086,6 +2196,7 @@ function createElement(path, { topLevel, hydratable }) {
2086
2196
  } else {
2087
2197
  const child = transformNode(path);
2088
2198
  if (markers && child.exprs.length) memo.push(t__namespace.stringLiteral("<!--#-->"));
2199
+ if (child.exprs.length && !child.spreadElement) child.exprs[0] = escapeExpression(path, child.exprs[0]);
2089
2200
  memo.push(getCreateTemplate(config, path, child)(path, child, true));
2090
2201
  if (markers && child.exprs.length) memo.push(t__namespace.stringLiteral("<!--/-->"));
2091
2202
  }
@@ -2209,7 +2320,11 @@ function transformAttributes(path, results) {
2209
2320
 
2210
2321
  // preprocess spreads
2211
2322
  if (attributes.some(attribute => t__namespace.isJSXSpreadAttribute(attribute.node))) {
2212
- [attributes, spreadExpr] = processSpreads(path, attributes, { elem, hasChildren });
2323
+ [attributes, spreadExpr] = processSpreads(path, attributes, {
2324
+ elem,
2325
+ hasChildren,
2326
+ wrapConditionals: config.wrapConditionals
2327
+ });
2213
2328
  path.get("openingElement").set(
2214
2329
  "attributes",
2215
2330
  attributes.map(a => a.node)
@@ -2439,12 +2554,11 @@ function nextChild(children, index) {
2439
2554
  return children[index + 1] && (children[index + 1].id || nextChild(children, index + 1));
2440
2555
  }
2441
2556
 
2442
- function processSpreads(path, attributes, { elem, hasChildren }) {
2557
+ function processSpreads(path, attributes, { elem, hasChildren, wrapConditionals }) {
2443
2558
  // TODO: skip but collect the names of any properties after the last spread to not overwrite them
2444
2559
  const filteredAttributes = [];
2445
2560
  const spreadArgs = [];
2446
2561
  let runningObject = [];
2447
- let runningDynamic = false;
2448
2562
  let dynamicSpread = false;
2449
2563
  let firstSpread = false;
2450
2564
  attributes.forEach(attribute => {
@@ -2457,12 +2571,7 @@ function processSpreads(path, attributes, { elem, hasChildren }) {
2457
2571
  if (t__namespace.isJSXSpreadAttribute(node)) {
2458
2572
  firstSpread = true;
2459
2573
  if (runningObject.length) {
2460
- spreadArgs.push(
2461
- runningDynamic
2462
- ? t__namespace.arrowFunctionExpression([], t__namespace.objectExpression(runningObject))
2463
- : t__namespace.objectExpression(runningObject)
2464
- );
2465
- runningDynamic = false;
2574
+ spreadArgs.push(t__namespace.objectExpression(runningObject));
2466
2575
  runningObject = [];
2467
2576
  }
2468
2577
  spreadArgs.push(
@@ -2484,24 +2593,37 @@ function processSpreads(path, attributes, { elem, hasChildren }) {
2484
2593
  canNativeSpread(key)
2485
2594
  ) {
2486
2595
  const isContainer = t__namespace.isJSXExpressionContainer(node.value);
2487
- runningDynamic =
2488
- runningDynamic ||
2489
- (isContainer && isDynamic(attribute.get("value").get("expression"), { checkMember: true }));
2490
- runningObject.push(
2491
- t__namespace.objectProperty(
2492
- t__namespace.stringLiteral(key),
2493
- isContainer ? node.value.expression : node.value || t__namespace.stringLiteral("")
2494
- )
2495
- );
2596
+ const dynamic =
2597
+ isContainer && isDynamic(attribute.get("value").get("expression"), { checkMember: true });
2598
+ if (dynamic) {
2599
+ const id = convertJSXIdentifier(node.name);
2600
+ let expr =
2601
+ wrapConditionals &&
2602
+ (t__namespace.isLogicalExpression(node.value.expression) || t__namespace.isConditionalExpression(node.value.expression))
2603
+ ? transformCondition(attribute.get("value").get("expression"), true)
2604
+ : t__namespace.arrowFunctionExpression([], node.value.expression);
2605
+ runningObject.push(
2606
+ t__namespace.objectMethod(
2607
+ "get",
2608
+ id,
2609
+ [],
2610
+ t__namespace.blockStatement([t__namespace.returnStatement(expr.body)]),
2611
+ !t__namespace.isValidIdentifier(key)
2612
+ )
2613
+ );
2614
+ } else {
2615
+ runningObject.push(
2616
+ t__namespace.objectProperty(
2617
+ t__namespace.stringLiteral(key),
2618
+ isContainer ? node.value.expression : node.value || t__namespace.stringLiteral("")
2619
+ )
2620
+ );
2621
+ }
2496
2622
  } else filteredAttributes.push(attribute);
2497
2623
  });
2498
2624
 
2499
2625
  if (runningObject.length) {
2500
- spreadArgs.push(
2501
- runningDynamic
2502
- ? t__namespace.arrowFunctionExpression([], t__namespace.objectExpression(runningObject))
2503
- : t__namespace.objectExpression(runningObject)
2504
- );
2626
+ spreadArgs.push(t__namespace.objectExpression(runningObject));
2505
2627
  }
2506
2628
 
2507
2629
  const props =
@@ -2627,25 +2749,6 @@ function convertComponentIdentifier(node) {
2627
2749
  return node;
2628
2750
  }
2629
2751
 
2630
- function convertJSXIdentifier(node) {
2631
- if (t__namespace.isJSXIdentifier(node)) {
2632
- if (t__namespace.isValidIdentifier(node.name)) {
2633
- node.type = "Identifier";
2634
- } else {
2635
- return t__namespace.stringLiteral(node.name);
2636
- }
2637
- } else if (t__namespace.isJSXMemberExpression(node)) {
2638
- return t__namespace.memberExpression(
2639
- convertJSXIdentifier(node.object),
2640
- convertJSXIdentifier(node.property)
2641
- );
2642
- } else if (t__namespace.isJSXNamespacedName(node)) {
2643
- return t__namespace.stringLiteral(`${node.namespace.name}:${node.name.name}`);
2644
- }
2645
-
2646
- return node;
2647
- }
2648
-
2649
2752
  function transformComponent(path) {
2650
2753
  let exprs = [],
2651
2754
  config = getConfig(path),
@@ -2766,7 +2869,7 @@ function transformComponent(path) {
2766
2869
  config.generate !== "ssr" &&
2767
2870
  (t__namespace.isLogicalExpression(value.expression) ||
2768
2871
  t__namespace.isConditionalExpression(value.expression))
2769
- ? transformCondition(attribute.get("value").get("expression"), true)
2872
+ ? transformCondition$1(attribute.get("value").get("expression"), true)
2770
2873
  : t__namespace.arrowFunctionExpression([], value.expression);
2771
2874
  runningObject.push(
2772
2875
  t__namespace.objectMethod(
@@ -2967,7 +3070,7 @@ function transformNode(path, info = {}) {
2967
3070
  config.wrapConditionals &&
2968
3071
  config.generate !== "ssr" &&
2969
3072
  (t__namespace.isLogicalExpression(node.expression) || t__namespace.isConditionalExpression(node.expression))
2970
- ? transformCondition(path.get("expression"), info.componentChild)
3073
+ ? transformCondition$1(path.get("expression"), info.componentChild)
2971
3074
  : !info.componentChild &&
2972
3075
  (config.generate !== "ssr" || info.fragmentChild) &&
2973
3076
  t__namespace.isCallExpression(node.expression) &&
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "babel-plugin-jsx-dom-expressions",
3
3
  "description": "A JSX to DOM plugin that wraps expressions for fine grained change detection",
4
- "version": "0.35.0-beta.0",
4
+ "version": "0.35.0-beta.2",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -27,5 +27,5 @@
27
27
  "peerDependencies": {
28
28
  "@babel/core": "^7.0.0"
29
29
  },
30
- "gitHead": "a4e7a727b92834f6f2550ff7314fe2e57715cadb"
30
+ "gitHead": "b059481668f4ec2e47b01bd7ab421102b0ff18b0"
31
31
  }