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 +181 -26
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +181 -26
- package/package.json +9 -9
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: "
|
|
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
|
|
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 `
|
|
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 (
|
|
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
|
-
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
7
|
+
* @returns {PluginObject} The Babel plugin object.
|
|
8
8
|
*/
|
|
9
|
-
declare function export_default():
|
|
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 {
|
|
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 {
|
|
7
|
+
* @returns {PluginObject} The Babel plugin object.
|
|
8
8
|
*/
|
|
9
|
-
declare function export_default():
|
|
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: "
|
|
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
|
|
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 `
|
|
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 (
|
|
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
|
-
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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.
|
|
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": "^
|
|
36
|
-
"@babel/generator": "^
|
|
37
|
-
"@estjs/shared": "0.0.17-beta.
|
|
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": "^
|
|
41
|
-
"@babel/types": "^
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
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",
|