babel-plugin-essor 0.0.17-beta.5 → 0.0.17-beta.7

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/dist/index.cjs CHANGED
@@ -101,7 +101,8 @@ var IMPORTS_MAPS = [
101
101
  "nthChild"
102
102
  ];
103
103
  var SERVER_IMPORT_REMAPS = {
104
- createComponent: "createSSRComponent",
104
+ createComponent: "ssrComponent",
105
+ render: "ssr",
105
106
  patchAttr: "ssrAttrDynamic"
106
107
  };
107
108
  var HYDRATE_IMPORT_REMAPS = {
@@ -609,6 +610,8 @@ function checkHasJSXReturn(path) {
609
610
  var HMR_COMPONENT_NAME = "__$createHMRComponent$__";
610
611
  var WHITESPACE_REGEX = /\s+/g;
611
612
  var PATH_SEPARATOR_REGEX = /[/\\]/;
613
+ var ESSOR_IMPORT = "essor";
614
+ var HMR_IMPORTS = /* @__PURE__ */ new Set(["createApp", "hydrate", "createComponent"]);
612
615
  function getFileBasename(ctx) {
613
616
  const filename = ctx.options.filename;
614
617
  const segments = filename.split(PATH_SEPARATOR_REGEX);
@@ -675,6 +678,65 @@ function collectFromStatement(statementPath, ctx) {
675
678
  }
676
679
  }
677
680
  }
681
+ function isComponentDeclarationExport(statementPath) {
682
+ const declarationPath = unwrapTopLevelDeclaration(statementPath);
683
+ if (!declarationPath) {
684
+ return false;
685
+ }
686
+ if (declarationPath.isFunctionDeclaration()) {
687
+ return checkHasJSXReturn(declarationPath);
688
+ }
689
+ if (!declarationPath.isVariableDeclaration()) {
690
+ return false;
691
+ }
692
+ const declarations = declarationPath.get("declarations");
693
+ if (declarations.length === 0) {
694
+ return false;
695
+ }
696
+ return declarations.every((variablePath) => {
697
+ const initPath = variablePath.get("init");
698
+ return isFunctionLikeExpressionPath(initPath) && checkHasJSXReturn(initPath);
699
+ });
700
+ }
701
+ function hasOnlyComponentSpecifiers(statementPath, componentNames) {
702
+ const { node } = statementPath;
703
+ if (node.declaration || node.source || node.specifiers.length === 0) {
704
+ return false;
705
+ }
706
+ return node.specifiers.every((specifier) => {
707
+ return core.types.isExportSpecifier(specifier) && core.types.isIdentifier(specifier.local) && componentNames.has(specifier.local.name);
708
+ });
709
+ }
710
+ function hasNonComponentExport(programPath, componentNames) {
711
+ for (const statementPath of programPath.get("body")) {
712
+ if (!statementPath.isExportNamedDeclaration() && !statementPath.isExportDefaultDeclaration()) {
713
+ continue;
714
+ }
715
+ if (isTypeOnlyExport(statementPath)) {
716
+ continue;
717
+ }
718
+ if (statementPath.isExportNamedDeclaration() && hasOnlyComponentSpecifiers(statementPath, componentNames)) {
719
+ continue;
720
+ }
721
+ if (!isComponentDeclarationExport(statementPath)) {
722
+ return true;
723
+ }
724
+ }
725
+ return false;
726
+ }
727
+ function isTypeOnlyExport(statementPath) {
728
+ if (!statementPath.isExportNamedDeclaration()) {
729
+ return false;
730
+ }
731
+ const { declaration, exportKind, specifiers } = statementPath.node;
732
+ if (exportKind === "type") {
733
+ return true;
734
+ }
735
+ if (core.types.isTSTypeAliasDeclaration(declaration) || core.types.isTSInterfaceDeclaration(declaration)) {
736
+ return true;
737
+ }
738
+ return specifiers.length > 0 && specifiers.every((specifier) => "exportKind" in specifier && specifier.exportKind === "type");
739
+ }
678
740
  function getMetadataTargets(statementPath, ctx) {
679
741
  const declarationPath = unwrapTopLevelDeclaration(statementPath);
680
742
  if (!declarationPath) {
@@ -747,22 +809,101 @@ function isCreateHMRComponentCall(value) {
747
809
  function canWrapArgument(value) {
748
810
  return !!value && !core.types.isSpreadElement(value) && !core.types.isArgumentPlaceholder(value);
749
811
  }
750
- function wrapComponentCreationCalls(programPath, ctx) {
812
+ function getEssorHmrBindings(programPath) {
813
+ const bindings = {
814
+ createComponent: /* @__PURE__ */ new Map(),
815
+ mount: /* @__PURE__ */ new Map()
816
+ };
817
+ for (const statementPath of programPath.get("body")) {
818
+ if (!statementPath.isImportDeclaration() || statementPath.node.source.value !== ESSOR_IMPORT) {
819
+ continue;
820
+ }
821
+ for (const specifier of statementPath.node.specifiers) {
822
+ if (!core.types.isImportSpecifier(specifier)) {
823
+ continue;
824
+ }
825
+ const imported = specifier.imported;
826
+ const name = core.types.isIdentifier(imported) ? imported.name : imported.value;
827
+ if (!HMR_IMPORTS.has(name)) {
828
+ continue;
829
+ }
830
+ if (name === "createComponent") {
831
+ const binding = statementPath.scope.getBinding(specifier.local.name);
832
+ if (binding) {
833
+ bindings.createComponent.set(specifier.local.name, binding);
834
+ }
835
+ } else {
836
+ const binding = statementPath.scope.getBinding(specifier.local.name);
837
+ if (binding) {
838
+ bindings.mount.set(specifier.local.name, binding);
839
+ }
840
+ }
841
+ }
842
+ }
843
+ return bindings;
844
+ }
845
+ function hasImportBinding(path, name, bindings) {
846
+ return bindings.has(name) && path.scope.getBinding(name) === bindings.get(name);
847
+ }
848
+ function isMountCallee(callPath, bindings) {
849
+ const { callee } = callPath.node;
850
+ return core.types.isIdentifier(callee) && hasImportBinding(callPath, callee.name, bindings.mount);
851
+ }
852
+ function createImportMetaHot() {
853
+ return core.types.memberExpression(
854
+ core.types.metaProperty(core.types.identifier("import"), core.types.identifier("meta")),
855
+ core.types.identifier("hot")
856
+ );
857
+ }
858
+ function createDisposeStatement(appId) {
859
+ const dispose = core.types.optionalMemberExpression(
860
+ createImportMetaHot(),
861
+ core.types.identifier("dispose"),
862
+ false,
863
+ true
864
+ );
865
+ const unmount = core.types.optionalCallExpression(
866
+ core.types.optionalMemberExpression(appId, core.types.identifier("unmount"), false, true),
867
+ [],
868
+ true
869
+ );
870
+ return core.types.expressionStatement(
871
+ core.types.optionalCallExpression(dispose, [core.types.arrowFunctionExpression([], unmount)], false)
872
+ );
873
+ }
874
+ function wrapTopLevelMountDisposals(programPath, bindings) {
875
+ const nextBody = [];
876
+ for (const statementPath of programPath.get("body")) {
877
+ const statement = statementPath.node;
878
+ const expressionPath = statementPath.isExpressionStatement() ? statementPath.get("expression") : null;
879
+ if ((expressionPath == null ? void 0 : expressionPath.isCallExpression()) && isMountCallee(expressionPath, bindings)) {
880
+ const appId = programPath.scope.generateUidIdentifier("app");
881
+ nextBody.push(
882
+ core.types.variableDeclaration("const", [core.types.variableDeclarator(appId, expressionPath.node)])
883
+ );
884
+ nextBody.push(createDisposeStatement(appId));
885
+ continue;
886
+ }
887
+ nextBody.push(statement);
888
+ }
889
+ programPath.node.body = nextBody;
890
+ }
891
+ function wrapComponentCreationCalls(programPath, ctx, bindings) {
751
892
  programPath.traverse({
752
893
  /**
753
- * Rewrites `createComponent` and `createApp` calls for HMR tracking.
894
+ * Rewrites `createComponent`, `createApp`, and `hydrate` calls for HMR tracking.
754
895
  */
755
896
  CallExpression(callPath) {
756
897
  const { callee } = callPath.node;
757
898
  if (!core.types.isIdentifier(callee)) return;
758
- if (callee.name === ctx.importIdentifiers.createComponent.name) {
899
+ if (callee.name === ctx.importIdentifiers.createComponent.name || hasImportBinding(callPath, callee.name, bindings.createComponent)) {
759
900
  const firstArg = callPath.node.arguments[0];
760
901
  if (canWrapArgument(firstArg)) {
761
902
  callPath.node.callee = core.types.identifier(HMR_COMPONENT_NAME);
762
903
  }
763
904
  return;
764
905
  }
765
- if (callee.name === "createApp") {
906
+ if (isMountCallee(callPath, bindings)) {
766
907
  const args = callPath.node.arguments;
767
908
  if (args.length === 0) return;
768
909
  if (isCreateHMRComponentCall(args[0])) {
@@ -782,6 +923,10 @@ function collectTopLevelHmrComponents(programPath, ctx) {
782
923
  for (const statementPath of programPath.get("body")) {
783
924
  collectFromStatement(statementPath, ctx);
784
925
  }
926
+ if (hasNonComponentExport(programPath, ctx.hmrComponents)) {
927
+ ctx.hmrComponents.clear();
928
+ ctx.hmrSignatures.clear();
929
+ }
785
930
  }
786
931
  function applyHmr(programPath, ctx) {
787
932
  if (!ctx.options.hmr || !ctx.options.bundler) {
@@ -790,10 +935,12 @@ function applyHmr(programPath, ctx) {
790
935
  if (ctx.hmrComponents.size > 0) {
791
936
  injectComponentMetadata(programPath, ctx);
792
937
  }
793
- wrapComponentCreationCalls(programPath, ctx);
938
+ const bindings = getEssorHmrBindings(programPath);
939
+ wrapComponentCreationCalls(programPath, ctx, bindings);
794
940
  if (ctx.hmrComponents.size === 0) {
795
941
  return;
796
942
  }
943
+ wrapTopLevelMountDisposals(programPath, bindings);
797
944
  programPath.node.body.push(
798
945
  core.types.variableDeclaration("const", [
799
946
  core.types.variableDeclarator(
@@ -927,7 +1074,7 @@ function bindObjectPattern(pattern, base) {
927
1074
  }
928
1075
  function resolveObjectProp(prop) {
929
1076
  const target = prop.value;
930
- const shorthandId = core.types.isAssignmentPattern(target) ? target.left : target;
1077
+ const shorthandId = unwrapBindingTarget(core.types.isAssignmentPattern(target) ? target.left : target);
931
1078
  if (prop.shorthand && core.types.isIdentifier(shorthandId) && isSignal(shorthandId.name)) {
932
1079
  return { keyExpr: core.types.identifier(stripSignalPrefix(shorthandId.name)), computed: false, target };
933
1080
  }
@@ -947,7 +1094,9 @@ function bindArrayPattern(pattern, base) {
947
1094
  out.push(...bindTarget(el.argument, slice));
948
1095
  return;
949
1096
  }
950
- out.push(...bindTarget(el, core.types.memberExpression(clone(base), core.types.numericLiteral(i2), true)));
1097
+ out.push(
1098
+ ...bindTarget(el, core.types.memberExpression(clone(base), core.types.numericLiteral(i2), true))
1099
+ );
951
1100
  });
952
1101
  return out;
953
1102
  }
@@ -955,14 +1104,28 @@ function bindTarget(target, access) {
955
1104
  if (core.types.isAssignmentPattern(target)) {
956
1105
  return bindTarget(target.left, applyDefault(access, target.right));
957
1106
  }
1107
+ if (isTSWrappedBindingTarget(target)) {
1108
+ return bindTarget(unwrapBindingTarget(target), access);
1109
+ }
958
1110
  if (core.types.isIdentifier(target)) {
959
1111
  const value = isSignal(target.name) ? makeComputed(access) : access;
960
1112
  return [core.types.variableDeclarator(core.types.identifier(target.name), value)];
961
1113
  }
962
1114
  if (core.types.isObjectPattern(target)) return bindObjectPattern(target, access);
963
1115
  if (core.types.isArrayPattern(target)) return bindArrayPattern(target, access);
1116
+ if (core.types.isMemberExpression(target)) return [];
964
1117
  return [core.types.variableDeclarator(target, access)];
965
1118
  }
1119
+ function isTSWrappedBindingTarget(target) {
1120
+ return core.types.isTSAsExpression(target) || core.types.isTSSatisfiesExpression(target) || core.types.isTSTypeAssertion(target) || core.types.isTSNonNullExpression(target);
1121
+ }
1122
+ function unwrapBindingTarget(target) {
1123
+ let current = target;
1124
+ while (isTSWrappedBindingTarget(current)) {
1125
+ current = current.expression;
1126
+ }
1127
+ return current;
1128
+ }
966
1129
  function applyDefault(access, def) {
967
1130
  return core.types.conditionalExpression(
968
1131
  core.types.binaryExpression("===", clone(access), core.types.identifier("undefined")),
@@ -1761,7 +1924,7 @@ function renderChildExpressions(children, render, options = {}) {
1761
1924
  }
1762
1925
  function buildComponentInvocation(tag, node, options) {
1763
1926
  const createComponentId = options.wrap ? useImport("createComponent") : null;
1764
- const callee = resolveComponentCallee(tag, core.types.identifier(tag));
1927
+ const callee = resolveComponentCallee(tag, buildComponentTagExpression(tag));
1765
1928
  const props = buildComponentPropsExpression(node, {
1766
1929
  dynamicPropsAsGetters: options.dynamicPropsAsGetters,
1767
1930
  cloneValues: options.cloneValues,
@@ -1774,6 +1937,13 @@ function buildComponentInvocation(tag, node, options) {
1774
1937
  }
1775
1938
  return core.types.callExpression(callee, [props]);
1776
1939
  }
1940
+ function buildComponentTagExpression(tag) {
1941
+ const [head, ...parts] = tag.split(".");
1942
+ return parts.reduce(
1943
+ (expr, part) => core.types.memberExpression(expr, core.types.identifier(part)),
1944
+ core.types.identifier(head)
1945
+ );
1946
+ }
1777
1947
 
1778
1948
  // src/jsx/server.ts
1779
1949
  var SERVER_TEXT_ESCAPES = {
@@ -1876,28 +2046,13 @@ function escapeChildExpression(expr) {
1876
2046
  if (isSafeServerHtml(expr)) {
1877
2047
  return expr;
1878
2048
  }
1879
- if (core.types.isParenthesizedExpression(expr)) {
1880
- expr.expression = escapeChildExpression(expr.expression);
1881
- return expr;
1882
- }
1883
2049
  if (core.types.isLogicalExpression(expr)) {
1884
2050
  if (expr.operator === "&&") {
1885
2051
  expr.right = escapeChildExpression(expr.right);
2052
+ return expr;
1886
2053
  } else {
1887
- expr.left = escapeChildExpression(expr.left);
1888
- expr.right = escapeChildExpression(expr.right);
2054
+ return core.types.callExpression(useImport("escape"), [expr]);
1889
2055
  }
1890
- return expr;
1891
- }
1892
- if (core.types.isConditionalExpression(expr)) {
1893
- expr.consequent = escapeChildExpression(expr.consequent);
1894
- expr.alternate = escapeChildExpression(expr.alternate);
1895
- return expr;
1896
- }
1897
- if (core.types.isSequenceExpression(expr) && expr.expressions.length > 0) {
1898
- const last = expr.expressions.length - 1;
1899
- expr.expressions[last] = escapeChildExpression(expr.expressions[last]);
1900
- return expr;
1901
2056
  }
1902
2057
  return core.types.callExpression(useImport("escape"), [expr]);
1903
2058
  }
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { PluginObj } from '@babel/core';
1
+ import { PluginObject } from '@babel/core';
2
2
 
3
3
  /**
4
4
  * Babel plugin for Essor framework.
5
5
  * Transforms Essor JSX and reactivity syntax into runtime calls.
6
6
  *
7
- * @returns {PluginObj} The Babel plugin object.
7
+ * @returns {PluginObject} The Babel plugin object.
8
8
  */
9
- declare function export_default(): PluginObj;
9
+ declare function export_default(): PluginObject;
10
10
 
11
11
  export { export_default as default };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { PluginObj } from '@babel/core';
1
+ import { PluginObject } from '@babel/core';
2
2
 
3
3
  /**
4
4
  * Babel plugin for Essor framework.
5
5
  * Transforms Essor JSX and reactivity syntax into runtime calls.
6
6
  *
7
- * @returns {PluginObj} The Babel plugin object.
7
+ * @returns {PluginObject} The Babel plugin object.
8
8
  */
9
- declare function export_default(): PluginObj;
9
+ declare function export_default(): PluginObject;
10
10
 
11
11
  export { export_default as default };
package/dist/index.js CHANGED
@@ -99,7 +99,8 @@ var IMPORTS_MAPS = [
99
99
  "nthChild"
100
100
  ];
101
101
  var SERVER_IMPORT_REMAPS = {
102
- createComponent: "createSSRComponent",
102
+ createComponent: "ssrComponent",
103
+ render: "ssr",
103
104
  patchAttr: "ssrAttrDynamic"
104
105
  };
105
106
  var HYDRATE_IMPORT_REMAPS = {
@@ -607,6 +608,8 @@ function checkHasJSXReturn(path) {
607
608
  var HMR_COMPONENT_NAME = "__$createHMRComponent$__";
608
609
  var WHITESPACE_REGEX = /\s+/g;
609
610
  var PATH_SEPARATOR_REGEX = /[/\\]/;
611
+ var ESSOR_IMPORT = "essor";
612
+ var HMR_IMPORTS = /* @__PURE__ */ new Set(["createApp", "hydrate", "createComponent"]);
610
613
  function getFileBasename(ctx) {
611
614
  const filename = ctx.options.filename;
612
615
  const segments = filename.split(PATH_SEPARATOR_REGEX);
@@ -673,6 +676,65 @@ function collectFromStatement(statementPath, ctx) {
673
676
  }
674
677
  }
675
678
  }
679
+ function isComponentDeclarationExport(statementPath) {
680
+ const declarationPath = unwrapTopLevelDeclaration(statementPath);
681
+ if (!declarationPath) {
682
+ return false;
683
+ }
684
+ if (declarationPath.isFunctionDeclaration()) {
685
+ return checkHasJSXReturn(declarationPath);
686
+ }
687
+ if (!declarationPath.isVariableDeclaration()) {
688
+ return false;
689
+ }
690
+ const declarations = declarationPath.get("declarations");
691
+ if (declarations.length === 0) {
692
+ return false;
693
+ }
694
+ return declarations.every((variablePath) => {
695
+ const initPath = variablePath.get("init");
696
+ return isFunctionLikeExpressionPath(initPath) && checkHasJSXReturn(initPath);
697
+ });
698
+ }
699
+ function hasOnlyComponentSpecifiers(statementPath, componentNames) {
700
+ const { node } = statementPath;
701
+ if (node.declaration || node.source || node.specifiers.length === 0) {
702
+ return false;
703
+ }
704
+ return node.specifiers.every((specifier) => {
705
+ return types.isExportSpecifier(specifier) && types.isIdentifier(specifier.local) && componentNames.has(specifier.local.name);
706
+ });
707
+ }
708
+ function hasNonComponentExport(programPath, componentNames) {
709
+ for (const statementPath of programPath.get("body")) {
710
+ if (!statementPath.isExportNamedDeclaration() && !statementPath.isExportDefaultDeclaration()) {
711
+ continue;
712
+ }
713
+ if (isTypeOnlyExport(statementPath)) {
714
+ continue;
715
+ }
716
+ if (statementPath.isExportNamedDeclaration() && hasOnlyComponentSpecifiers(statementPath, componentNames)) {
717
+ continue;
718
+ }
719
+ if (!isComponentDeclarationExport(statementPath)) {
720
+ return true;
721
+ }
722
+ }
723
+ return false;
724
+ }
725
+ function isTypeOnlyExport(statementPath) {
726
+ if (!statementPath.isExportNamedDeclaration()) {
727
+ return false;
728
+ }
729
+ const { declaration, exportKind, specifiers } = statementPath.node;
730
+ if (exportKind === "type") {
731
+ return true;
732
+ }
733
+ if (types.isTSTypeAliasDeclaration(declaration) || types.isTSInterfaceDeclaration(declaration)) {
734
+ return true;
735
+ }
736
+ return specifiers.length > 0 && specifiers.every((specifier) => "exportKind" in specifier && specifier.exportKind === "type");
737
+ }
676
738
  function getMetadataTargets(statementPath, ctx) {
677
739
  const declarationPath = unwrapTopLevelDeclaration(statementPath);
678
740
  if (!declarationPath) {
@@ -745,22 +807,101 @@ function isCreateHMRComponentCall(value) {
745
807
  function canWrapArgument(value) {
746
808
  return !!value && !types.isSpreadElement(value) && !types.isArgumentPlaceholder(value);
747
809
  }
748
- function wrapComponentCreationCalls(programPath, ctx) {
810
+ function getEssorHmrBindings(programPath) {
811
+ const bindings = {
812
+ createComponent: /* @__PURE__ */ new Map(),
813
+ mount: /* @__PURE__ */ new Map()
814
+ };
815
+ for (const statementPath of programPath.get("body")) {
816
+ if (!statementPath.isImportDeclaration() || statementPath.node.source.value !== ESSOR_IMPORT) {
817
+ continue;
818
+ }
819
+ for (const specifier of statementPath.node.specifiers) {
820
+ if (!types.isImportSpecifier(specifier)) {
821
+ continue;
822
+ }
823
+ const imported = specifier.imported;
824
+ const name = types.isIdentifier(imported) ? imported.name : imported.value;
825
+ if (!HMR_IMPORTS.has(name)) {
826
+ continue;
827
+ }
828
+ if (name === "createComponent") {
829
+ const binding = statementPath.scope.getBinding(specifier.local.name);
830
+ if (binding) {
831
+ bindings.createComponent.set(specifier.local.name, binding);
832
+ }
833
+ } else {
834
+ const binding = statementPath.scope.getBinding(specifier.local.name);
835
+ if (binding) {
836
+ bindings.mount.set(specifier.local.name, binding);
837
+ }
838
+ }
839
+ }
840
+ }
841
+ return bindings;
842
+ }
843
+ function hasImportBinding(path, name, bindings) {
844
+ return bindings.has(name) && path.scope.getBinding(name) === bindings.get(name);
845
+ }
846
+ function isMountCallee(callPath, bindings) {
847
+ const { callee } = callPath.node;
848
+ return types.isIdentifier(callee) && hasImportBinding(callPath, callee.name, bindings.mount);
849
+ }
850
+ function createImportMetaHot() {
851
+ return types.memberExpression(
852
+ types.metaProperty(types.identifier("import"), types.identifier("meta")),
853
+ types.identifier("hot")
854
+ );
855
+ }
856
+ function createDisposeStatement(appId) {
857
+ const dispose = types.optionalMemberExpression(
858
+ createImportMetaHot(),
859
+ types.identifier("dispose"),
860
+ false,
861
+ true
862
+ );
863
+ const unmount = types.optionalCallExpression(
864
+ types.optionalMemberExpression(appId, types.identifier("unmount"), false, true),
865
+ [],
866
+ true
867
+ );
868
+ return types.expressionStatement(
869
+ types.optionalCallExpression(dispose, [types.arrowFunctionExpression([], unmount)], false)
870
+ );
871
+ }
872
+ function wrapTopLevelMountDisposals(programPath, bindings) {
873
+ const nextBody = [];
874
+ for (const statementPath of programPath.get("body")) {
875
+ const statement = statementPath.node;
876
+ const expressionPath = statementPath.isExpressionStatement() ? statementPath.get("expression") : null;
877
+ if ((expressionPath == null ? void 0 : expressionPath.isCallExpression()) && isMountCallee(expressionPath, bindings)) {
878
+ const appId = programPath.scope.generateUidIdentifier("app");
879
+ nextBody.push(
880
+ types.variableDeclaration("const", [types.variableDeclarator(appId, expressionPath.node)])
881
+ );
882
+ nextBody.push(createDisposeStatement(appId));
883
+ continue;
884
+ }
885
+ nextBody.push(statement);
886
+ }
887
+ programPath.node.body = nextBody;
888
+ }
889
+ function wrapComponentCreationCalls(programPath, ctx, bindings) {
749
890
  programPath.traverse({
750
891
  /**
751
- * Rewrites `createComponent` and `createApp` calls for HMR tracking.
892
+ * Rewrites `createComponent`, `createApp`, and `hydrate` calls for HMR tracking.
752
893
  */
753
894
  CallExpression(callPath) {
754
895
  const { callee } = callPath.node;
755
896
  if (!types.isIdentifier(callee)) return;
756
- if (callee.name === ctx.importIdentifiers.createComponent.name) {
897
+ if (callee.name === ctx.importIdentifiers.createComponent.name || hasImportBinding(callPath, callee.name, bindings.createComponent)) {
757
898
  const firstArg = callPath.node.arguments[0];
758
899
  if (canWrapArgument(firstArg)) {
759
900
  callPath.node.callee = types.identifier(HMR_COMPONENT_NAME);
760
901
  }
761
902
  return;
762
903
  }
763
- if (callee.name === "createApp") {
904
+ if (isMountCallee(callPath, bindings)) {
764
905
  const args = callPath.node.arguments;
765
906
  if (args.length === 0) return;
766
907
  if (isCreateHMRComponentCall(args[0])) {
@@ -780,6 +921,10 @@ function collectTopLevelHmrComponents(programPath, ctx) {
780
921
  for (const statementPath of programPath.get("body")) {
781
922
  collectFromStatement(statementPath, ctx);
782
923
  }
924
+ if (hasNonComponentExport(programPath, ctx.hmrComponents)) {
925
+ ctx.hmrComponents.clear();
926
+ ctx.hmrSignatures.clear();
927
+ }
783
928
  }
784
929
  function applyHmr(programPath, ctx) {
785
930
  if (!ctx.options.hmr || !ctx.options.bundler) {
@@ -788,10 +933,12 @@ function applyHmr(programPath, ctx) {
788
933
  if (ctx.hmrComponents.size > 0) {
789
934
  injectComponentMetadata(programPath, ctx);
790
935
  }
791
- wrapComponentCreationCalls(programPath, ctx);
936
+ const bindings = getEssorHmrBindings(programPath);
937
+ wrapComponentCreationCalls(programPath, ctx, bindings);
792
938
  if (ctx.hmrComponents.size === 0) {
793
939
  return;
794
940
  }
941
+ wrapTopLevelMountDisposals(programPath, bindings);
795
942
  programPath.node.body.push(
796
943
  types.variableDeclaration("const", [
797
944
  types.variableDeclarator(
@@ -925,7 +1072,7 @@ function bindObjectPattern(pattern, base) {
925
1072
  }
926
1073
  function resolveObjectProp(prop) {
927
1074
  const target = prop.value;
928
- const shorthandId = types.isAssignmentPattern(target) ? target.left : target;
1075
+ const shorthandId = unwrapBindingTarget(types.isAssignmentPattern(target) ? target.left : target);
929
1076
  if (prop.shorthand && types.isIdentifier(shorthandId) && isSignal(shorthandId.name)) {
930
1077
  return { keyExpr: types.identifier(stripSignalPrefix(shorthandId.name)), computed: false, target };
931
1078
  }
@@ -945,7 +1092,9 @@ function bindArrayPattern(pattern, base) {
945
1092
  out.push(...bindTarget(el.argument, slice));
946
1093
  return;
947
1094
  }
948
- out.push(...bindTarget(el, types.memberExpression(clone(base), types.numericLiteral(i2), true)));
1095
+ out.push(
1096
+ ...bindTarget(el, types.memberExpression(clone(base), types.numericLiteral(i2), true))
1097
+ );
949
1098
  });
950
1099
  return out;
951
1100
  }
@@ -953,14 +1102,28 @@ function bindTarget(target, access) {
953
1102
  if (types.isAssignmentPattern(target)) {
954
1103
  return bindTarget(target.left, applyDefault(access, target.right));
955
1104
  }
1105
+ if (isTSWrappedBindingTarget(target)) {
1106
+ return bindTarget(unwrapBindingTarget(target), access);
1107
+ }
956
1108
  if (types.isIdentifier(target)) {
957
1109
  const value = isSignal(target.name) ? makeComputed(access) : access;
958
1110
  return [types.variableDeclarator(types.identifier(target.name), value)];
959
1111
  }
960
1112
  if (types.isObjectPattern(target)) return bindObjectPattern(target, access);
961
1113
  if (types.isArrayPattern(target)) return bindArrayPattern(target, access);
1114
+ if (types.isMemberExpression(target)) return [];
962
1115
  return [types.variableDeclarator(target, access)];
963
1116
  }
1117
+ function isTSWrappedBindingTarget(target) {
1118
+ return types.isTSAsExpression(target) || types.isTSSatisfiesExpression(target) || types.isTSTypeAssertion(target) || types.isTSNonNullExpression(target);
1119
+ }
1120
+ function unwrapBindingTarget(target) {
1121
+ let current = target;
1122
+ while (isTSWrappedBindingTarget(current)) {
1123
+ current = current.expression;
1124
+ }
1125
+ return current;
1126
+ }
964
1127
  function applyDefault(access, def) {
965
1128
  return types.conditionalExpression(
966
1129
  types.binaryExpression("===", clone(access), types.identifier("undefined")),
@@ -1759,7 +1922,7 @@ function renderChildExpressions(children, render, options = {}) {
1759
1922
  }
1760
1923
  function buildComponentInvocation(tag, node, options) {
1761
1924
  const createComponentId = options.wrap ? useImport("createComponent") : null;
1762
- const callee = resolveComponentCallee(tag, types.identifier(tag));
1925
+ const callee = resolveComponentCallee(tag, buildComponentTagExpression(tag));
1763
1926
  const props = buildComponentPropsExpression(node, {
1764
1927
  dynamicPropsAsGetters: options.dynamicPropsAsGetters,
1765
1928
  cloneValues: options.cloneValues,
@@ -1772,6 +1935,13 @@ function buildComponentInvocation(tag, node, options) {
1772
1935
  }
1773
1936
  return types.callExpression(callee, [props]);
1774
1937
  }
1938
+ function buildComponentTagExpression(tag) {
1939
+ const [head, ...parts] = tag.split(".");
1940
+ return parts.reduce(
1941
+ (expr, part) => types.memberExpression(expr, types.identifier(part)),
1942
+ types.identifier(head)
1943
+ );
1944
+ }
1775
1945
 
1776
1946
  // src/jsx/server.ts
1777
1947
  var SERVER_TEXT_ESCAPES = {
@@ -1874,28 +2044,13 @@ function escapeChildExpression(expr) {
1874
2044
  if (isSafeServerHtml(expr)) {
1875
2045
  return expr;
1876
2046
  }
1877
- if (types.isParenthesizedExpression(expr)) {
1878
- expr.expression = escapeChildExpression(expr.expression);
1879
- return expr;
1880
- }
1881
2047
  if (types.isLogicalExpression(expr)) {
1882
2048
  if (expr.operator === "&&") {
1883
2049
  expr.right = escapeChildExpression(expr.right);
2050
+ return expr;
1884
2051
  } else {
1885
- expr.left = escapeChildExpression(expr.left);
1886
- expr.right = escapeChildExpression(expr.right);
2052
+ return types.callExpression(useImport("escape"), [expr]);
1887
2053
  }
1888
- return expr;
1889
- }
1890
- if (types.isConditionalExpression(expr)) {
1891
- expr.consequent = escapeChildExpression(expr.consequent);
1892
- expr.alternate = escapeChildExpression(expr.alternate);
1893
- return expr;
1894
- }
1895
- if (types.isSequenceExpression(expr) && expr.expressions.length > 0) {
1896
- const last = expr.expressions.length - 1;
1897
- expr.expressions[last] = escapeChildExpression(expr.expressions[last]);
1898
- return expr;
1899
2054
  }
1900
2055
  return types.callExpression(useImport("escape"), [expr]);
1901
2056
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-plugin-essor",
3
- "version": "0.0.17-beta.5",
3
+ "version": "0.0.17-beta.7",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -32,16 +32,16 @@
32
32
  },
33
33
  "sideEffects": false,
34
34
  "dependencies": {
35
- "@babel/core": "^7.29.7",
36
- "@babel/generator": "^7.29.7",
37
- "@estjs/shared": "0.0.17-beta.5"
35
+ "@babel/core": "^8.0.1",
36
+ "@babel/generator": "^8.0.0",
37
+ "@estjs/shared": "0.0.17-beta.7"
38
38
  },
39
39
  "devDependencies": {
40
- "@babel/traverse": "^7.29.7",
41
- "@babel/types": "^7.29.7",
42
- "@types/babel__core": "^7.20.5",
43
- "@types/babel__generator": "^7.27.0",
44
- "@types/babel__traverse": "^7.28.0"
40
+ "@babel/traverse": "^8.0.0",
41
+ "@babel/types": "^8.0.0"
42
+ },
43
+ "engines": {
44
+ "node": "^22.18.0 || >=24.11.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsup",