@vobs/compiler 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compile.cjs +81 -17
- package/dist/compile.cjs.map +1 -1
- package/dist/compile.js +81 -17
- package/dist/compile.js.map +1 -1
- package/dist/index.cjs +81 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +81 -17
- package/dist/index.js.map +1 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +6 -0
- package/dist/plugin.d.ts +6 -0
- package/package.json +2 -2
- package/src/compile.test.ts +74 -0
- package/src/compile.ts +113 -17
- package/src/plugin.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -58,7 +58,8 @@ function compileWithSourceMap(code, options = {}) {
|
|
|
58
58
|
sourceLocation: options.sourceLocation ?? true,
|
|
59
59
|
stateAliases: collectStateAliases(sourceFile),
|
|
60
60
|
localBindings: collectLocallyDeclaredNames(sourceFile),
|
|
61
|
-
diagnostics: []
|
|
61
|
+
diagnostics: [],
|
|
62
|
+
hmrModuleId: options.hmrModuleId ?? null
|
|
62
63
|
};
|
|
63
64
|
const cleanFilename = filename.split(/[?#]/u, 1)[0] || filename;
|
|
64
65
|
const diagnostics = ts.transpileModule(code, {
|
|
@@ -84,14 +85,15 @@ function compileWithSourceMap(code, options = {}) {
|
|
|
84
85
|
}
|
|
85
86
|
for (const plugin of plugins) sourceFile = transformPluginNodes(sourceFile, plugin, context);
|
|
86
87
|
const statements = sourceFile.statements.map(
|
|
87
|
-
(statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement)
|
|
88
|
+
(statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement, true)
|
|
88
89
|
);
|
|
89
90
|
const templateDeclarations = createTemplateDeclarations(state);
|
|
90
|
-
|
|
91
|
+
let resultFile = ts.factory.updateSourceFile(sourceFile, [
|
|
91
92
|
...createRuntimeImports(state),
|
|
92
93
|
...templateDeclarations,
|
|
93
94
|
...statements
|
|
94
95
|
]);
|
|
96
|
+
resultFile = transformResidualJsx(state, resultFile);
|
|
95
97
|
const generated = ts.createPrinter().printFile(resultFile);
|
|
96
98
|
return {
|
|
97
99
|
code: generated,
|
|
@@ -373,7 +375,7 @@ function rebuildImport(state, node) {
|
|
|
373
375
|
), node);
|
|
374
376
|
}
|
|
375
377
|
__name(rebuildImport, "rebuildImport");
|
|
376
|
-
function transformStatement(state, node) {
|
|
378
|
+
function transformStatement(state, node, moduleScope = false) {
|
|
377
379
|
if (ts.isFunctionDeclaration(node) && node.body) {
|
|
378
380
|
return tagStatement(state, ts.factory.updateFunctionDeclaration(
|
|
379
381
|
node,
|
|
@@ -386,7 +388,7 @@ function transformStatement(state, node) {
|
|
|
386
388
|
transformBlock(state, node.body)
|
|
387
389
|
), node);
|
|
388
390
|
}
|
|
389
|
-
if (ts.isVariableStatement(node)) return transformVariableStatement(state, node);
|
|
391
|
+
if (ts.isVariableStatement(node)) return transformVariableStatement(state, node, moduleScope);
|
|
390
392
|
if (ts.isExportAssignment(node) && containsJsx(node.expression)) {
|
|
391
393
|
return tagStatement(state, ts.factory.updateExportAssignment(node, node.modifiers, transformEmbeddedExpression(state, node.expression)), node);
|
|
392
394
|
}
|
|
@@ -399,7 +401,7 @@ function transformStatement(state, node) {
|
|
|
399
401
|
return node;
|
|
400
402
|
}
|
|
401
403
|
__name(transformStatement, "transformStatement");
|
|
402
|
-
function transformVariableStatement(state, node) {
|
|
404
|
+
function transformVariableStatement(state, node, moduleScope = false) {
|
|
403
405
|
let changed = false;
|
|
404
406
|
const declarations = node.declarationList.declarations.map((declaration) => {
|
|
405
407
|
const initializer = declaration.initializer;
|
|
@@ -407,6 +409,8 @@ function transformVariableStatement(state, node) {
|
|
|
407
409
|
let nextInitializer = inferStateDebugName(state, declaration, initializer) ?? initializer;
|
|
408
410
|
if (containsJsx(nextInitializer)) {
|
|
409
411
|
nextInitializer = transformEmbeddedExpression(state, nextInitializer);
|
|
412
|
+
} else if (moduleScope && state.hmrModuleId !== null) {
|
|
413
|
+
nextInitializer = wrapStateWithHmrRef(state, declaration, nextInitializer) ?? nextInitializer;
|
|
410
414
|
}
|
|
411
415
|
if (nextInitializer === initializer) return declaration;
|
|
412
416
|
changed = true;
|
|
@@ -444,6 +448,29 @@ function inferStateDebugName(state, declaration, initializer) {
|
|
|
444
448
|
]);
|
|
445
449
|
}
|
|
446
450
|
__name(inferStateDebugName, "inferStateDebugName");
|
|
451
|
+
function wrapStateWithHmrRef(state, declaration, initializer) {
|
|
452
|
+
let call = initializer;
|
|
453
|
+
while (ts.isParenthesizedExpression(call) || ts.isAsExpression(call) || ts.isTypeAssertionExpression(call) || ts.isSatisfiesExpression(call)) {
|
|
454
|
+
call = call.expression;
|
|
455
|
+
}
|
|
456
|
+
if (!ts.isCallExpression(call)) return void 0;
|
|
457
|
+
const callee = call.expression;
|
|
458
|
+
if (!ts.isIdentifier(callee) || !state.stateAliases.has(callee.text)) return void 0;
|
|
459
|
+
if (state.localBindings.has(callee.text)) return void 0;
|
|
460
|
+
if (!ts.isIdentifier(declaration.name)) return void 0;
|
|
461
|
+
return ts.factory.createCallExpression(helperRef(state, "hmrStateRef"), void 0, [
|
|
462
|
+
ts.factory.createStringLiteral(`${state.hmrModuleId}#${declaration.name.text}`),
|
|
463
|
+
ts.factory.createArrowFunction(
|
|
464
|
+
void 0,
|
|
465
|
+
void 0,
|
|
466
|
+
[],
|
|
467
|
+
void 0,
|
|
468
|
+
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
|
469
|
+
initializer
|
|
470
|
+
)
|
|
471
|
+
]);
|
|
472
|
+
}
|
|
473
|
+
__name(wrapStateWithHmrRef, "wrapStateWithHmrRef");
|
|
447
474
|
function containsJsx(expression) {
|
|
448
475
|
let found = false;
|
|
449
476
|
const visit = /* @__PURE__ */ __name((node) => {
|
|
@@ -704,6 +731,27 @@ function transformEmbeddedExpression(state, expression) {
|
|
|
704
731
|
}
|
|
705
732
|
}
|
|
706
733
|
__name(transformEmbeddedExpression, "transformEmbeddedExpression");
|
|
734
|
+
function transformResidualJsx(state, sourceFile) {
|
|
735
|
+
if (!containsJsx(sourceFile)) return sourceFile;
|
|
736
|
+
const result = ts.transform(sourceFile, [(context) => (root) => {
|
|
737
|
+
const visit = /* @__PURE__ */ __name((node) => {
|
|
738
|
+
if (ts.isReturnStatement(node) && node.expression && containsJsx(node.expression)) {
|
|
739
|
+
return ts.factory.updateReturnStatement(node, transformEmbeddedExpression(state, node.expression));
|
|
740
|
+
}
|
|
741
|
+
if (isJsxExpression(node)) {
|
|
742
|
+
return transformJsxExpression(state, node);
|
|
743
|
+
}
|
|
744
|
+
return ts.visitEachChild(node, visit, context);
|
|
745
|
+
}, "visit");
|
|
746
|
+
return ts.visitNode(root, visit);
|
|
747
|
+
}]);
|
|
748
|
+
try {
|
|
749
|
+
return result.transformed[0];
|
|
750
|
+
} finally {
|
|
751
|
+
result.dispose();
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
__name(transformResidualJsx, "transformResidualJsx");
|
|
707
755
|
function isStaticElement(tagName, attributes, children) {
|
|
708
756
|
if (!ts.isIdentifier(tagName) || !/^[a-z]/.test(tagName.text)) return false;
|
|
709
757
|
for (const attribute of attributes.properties) {
|
|
@@ -956,36 +1004,52 @@ function createSourceLocation(node) {
|
|
|
956
1004
|
}
|
|
957
1005
|
__name(createSourceLocation, "createSourceLocation");
|
|
958
1006
|
function transformDynamicExpression(state, expression) {
|
|
1007
|
+
const converted = convertDynamicNodeExpression(state, expression);
|
|
1008
|
+
return converted ? createGetter(converted) : null;
|
|
1009
|
+
}
|
|
1010
|
+
__name(transformDynamicExpression, "transformDynamicExpression");
|
|
1011
|
+
function convertDynamicNodeExpression(state, expression) {
|
|
959
1012
|
if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
960
1013
|
const right = unwrapExpression(expression.right);
|
|
961
|
-
if (
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
ts.factory.createNull()
|
|
968
|
-
));
|
|
1014
|
+
if (isJsxExpression(right)) {
|
|
1015
|
+
return createNodeConditional(expression.left, transformJsxExpression(state, right), null);
|
|
1016
|
+
}
|
|
1017
|
+
const convertedRight = convertDynamicNodeExpression(state, right);
|
|
1018
|
+
if (convertedRight) return createNodeConditional(expression.left, convertedRight, null);
|
|
1019
|
+
return null;
|
|
969
1020
|
}
|
|
970
1021
|
if (ts.isConditionalExpression(expression)) {
|
|
971
1022
|
const whenTrue = transformDynamicBranch(state, expression.whenTrue);
|
|
972
1023
|
const whenFalse = transformDynamicBranch(state, expression.whenFalse);
|
|
973
1024
|
if (!whenTrue && !whenFalse) return null;
|
|
974
|
-
return
|
|
1025
|
+
return ts.factory.createConditionalExpression(
|
|
975
1026
|
expression.condition,
|
|
976
1027
|
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
977
1028
|
whenTrue ?? ts.factory.createNull(),
|
|
978
1029
|
ts.factory.createToken(ts.SyntaxKind.ColonToken),
|
|
979
1030
|
whenFalse ?? ts.factory.createNull()
|
|
980
|
-
)
|
|
1031
|
+
);
|
|
981
1032
|
}
|
|
982
1033
|
return null;
|
|
983
1034
|
}
|
|
984
|
-
__name(
|
|
1035
|
+
__name(convertDynamicNodeExpression, "convertDynamicNodeExpression");
|
|
1036
|
+
function createNodeConditional(condition, whenTrue, whenFalse) {
|
|
1037
|
+
return ts.factory.createConditionalExpression(
|
|
1038
|
+
condition,
|
|
1039
|
+
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
1040
|
+
whenTrue,
|
|
1041
|
+
ts.factory.createToken(ts.SyntaxKind.ColonToken),
|
|
1042
|
+
whenFalse ?? ts.factory.createNull()
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
__name(createNodeConditional, "createNodeConditional");
|
|
985
1046
|
function transformDynamicBranch(state, expression) {
|
|
986
1047
|
const branch = unwrapExpression(expression);
|
|
987
1048
|
if (isJsxExpression(branch)) return transformJsxExpression(state, branch);
|
|
988
1049
|
if (branch.kind === ts.SyntaxKind.NullKeyword || branch.kind === ts.SyntaxKind.FalseKeyword) return branch;
|
|
1050
|
+
if (ts.isConditionalExpression(branch) || ts.isBinaryExpression(branch) && branch.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
1051
|
+
return convertDynamicNodeExpression(state, branch);
|
|
1052
|
+
}
|
|
989
1053
|
return null;
|
|
990
1054
|
}
|
|
991
1055
|
__name(transformDynamicBranch, "transformDynamicBranch");
|