@vobs/compiler 1.2.1 → 1.3.0

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.js CHANGED
@@ -1,8 +1,9 @@
1
- import ts from 'typescript';
2
- import { VobsError } from '@vobs/runtime/error';
3
-
4
1
  var __defProp = Object.defineProperty;
5
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // packages/compiler/src/compile.ts
5
+ import ts from "typescript";
6
+ import { VobsError } from "@vobs/runtime/error";
6
7
  function createCompiler(options = {}) {
7
8
  const basePlugins = options.plugins ?? [];
8
9
  return {
@@ -57,7 +58,8 @@ function compileWithSourceMap(code, options = {}) {
57
58
  sourceLocation: options.sourceLocation ?? true,
58
59
  stateAliases: collectStateAliases(sourceFile),
59
60
  localBindings: collectLocallyDeclaredNames(sourceFile),
60
- diagnostics: []
61
+ diagnostics: [],
62
+ hmrModuleId: options.hmrModuleId ?? null
61
63
  };
62
64
  const cleanFilename = filename.split(/[?#]/u, 1)[0] || filename;
63
65
  const diagnostics = ts.transpileModule(code, {
@@ -83,14 +85,15 @@ function compileWithSourceMap(code, options = {}) {
83
85
  }
84
86
  for (const plugin of plugins) sourceFile = transformPluginNodes(sourceFile, plugin, context);
85
87
  const statements = sourceFile.statements.map(
86
- (statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement)
88
+ (statement) => ts.isImportDeclaration(statement) ? rebuildImport(state, statement) : transformStatement(state, statement, true)
87
89
  );
88
90
  const templateDeclarations = createTemplateDeclarations(state);
89
- const resultFile = ts.factory.updateSourceFile(sourceFile, [
91
+ let resultFile = ts.factory.updateSourceFile(sourceFile, [
90
92
  ...createRuntimeImports(state),
91
93
  ...templateDeclarations,
92
94
  ...statements
93
95
  ]);
96
+ resultFile = transformResidualJsx(state, resultFile);
94
97
  const generated = ts.createPrinter().printFile(resultFile);
95
98
  return {
96
99
  code: generated,
@@ -372,7 +375,7 @@ function rebuildImport(state, node) {
372
375
  ), node);
373
376
  }
374
377
  __name(rebuildImport, "rebuildImport");
375
- function transformStatement(state, node) {
378
+ function transformStatement(state, node, moduleScope = false) {
376
379
  if (ts.isFunctionDeclaration(node) && node.body) {
377
380
  return tagStatement(state, ts.factory.updateFunctionDeclaration(
378
381
  node,
@@ -385,7 +388,7 @@ function transformStatement(state, node) {
385
388
  transformBlock(state, node.body)
386
389
  ), node);
387
390
  }
388
- if (ts.isVariableStatement(node)) return transformVariableStatement(state, node);
391
+ if (ts.isVariableStatement(node)) return transformVariableStatement(state, node, moduleScope);
389
392
  if (ts.isExportAssignment(node) && containsJsx(node.expression)) {
390
393
  return tagStatement(state, ts.factory.updateExportAssignment(node, node.modifiers, transformEmbeddedExpression(state, node.expression)), node);
391
394
  }
@@ -398,7 +401,7 @@ function transformStatement(state, node) {
398
401
  return node;
399
402
  }
400
403
  __name(transformStatement, "transformStatement");
401
- function transformVariableStatement(state, node) {
404
+ function transformVariableStatement(state, node, moduleScope = false) {
402
405
  let changed = false;
403
406
  const declarations = node.declarationList.declarations.map((declaration) => {
404
407
  const initializer = declaration.initializer;
@@ -406,6 +409,8 @@ function transformVariableStatement(state, node) {
406
409
  let nextInitializer = inferStateDebugName(state, declaration, initializer) ?? initializer;
407
410
  if (containsJsx(nextInitializer)) {
408
411
  nextInitializer = transformEmbeddedExpression(state, nextInitializer);
412
+ } else if (moduleScope && state.hmrModuleId !== null) {
413
+ nextInitializer = wrapStateWithHmrRef(state, declaration, nextInitializer) ?? nextInitializer;
409
414
  }
410
415
  if (nextInitializer === initializer) return declaration;
411
416
  changed = true;
@@ -443,6 +448,29 @@ function inferStateDebugName(state, declaration, initializer) {
443
448
  ]);
444
449
  }
445
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");
446
474
  function containsJsx(expression) {
447
475
  let found = false;
448
476
  const visit = /* @__PURE__ */ __name((node) => {
@@ -703,6 +731,27 @@ function transformEmbeddedExpression(state, expression) {
703
731
  }
704
732
  }
705
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");
706
755
  function isStaticElement(tagName, attributes, children) {
707
756
  if (!ts.isIdentifier(tagName) || !/^[a-z]/.test(tagName.text)) return false;
708
757
  for (const attribute of attributes.properties) {
@@ -955,36 +1004,52 @@ function createSourceLocation(node) {
955
1004
  }
956
1005
  __name(createSourceLocation, "createSourceLocation");
957
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) {
958
1012
  if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
959
1013
  const right = unwrapExpression(expression.right);
960
- if (!isJsxExpression(right)) return null;
961
- return createGetter(ts.factory.createConditionalExpression(
962
- expression.left,
963
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
964
- transformJsxExpression(state, right),
965
- ts.factory.createToken(ts.SyntaxKind.ColonToken),
966
- ts.factory.createNull()
967
- ));
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;
968
1020
  }
969
1021
  if (ts.isConditionalExpression(expression)) {
970
1022
  const whenTrue = transformDynamicBranch(state, expression.whenTrue);
971
1023
  const whenFalse = transformDynamicBranch(state, expression.whenFalse);
972
1024
  if (!whenTrue && !whenFalse) return null;
973
- return createGetter(ts.factory.createConditionalExpression(
1025
+ return ts.factory.createConditionalExpression(
974
1026
  expression.condition,
975
1027
  ts.factory.createToken(ts.SyntaxKind.QuestionToken),
976
1028
  whenTrue ?? ts.factory.createNull(),
977
1029
  ts.factory.createToken(ts.SyntaxKind.ColonToken),
978
1030
  whenFalse ?? ts.factory.createNull()
979
- ));
1031
+ );
980
1032
  }
981
1033
  return null;
982
1034
  }
983
- __name(transformDynamicExpression, "transformDynamicExpression");
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");
984
1046
  function transformDynamicBranch(state, expression) {
985
1047
  const branch = unwrapExpression(expression);
986
1048
  if (isJsxExpression(branch)) return transformJsxExpression(state, branch);
987
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
+ }
988
1053
  return null;
989
1054
  }
990
1055
  __name(transformDynamicBranch, "transformDynamicBranch");
@@ -1135,7 +1200,9 @@ function nextIdentifier(state, prefix) {
1135
1200
  return ts.factory.createIdentifier(name);
1136
1201
  }
1137
1202
  __name(nextIdentifier, "nextIdentifier");
1138
-
1139
- export { compile, compileWithSourceMap, createCompiler };
1140
- //# sourceMappingURL=compile.js.map
1203
+ export {
1204
+ compile,
1205
+ compileWithSourceMap,
1206
+ createCompiler
1207
+ };
1141
1208
  //# sourceMappingURL=compile.js.map