@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/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
- const resultFile = ts.factory.updateSourceFile(sourceFile, [
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 (!isJsxExpression(right)) return null;
962
- return createGetter(ts.factory.createConditionalExpression(
963
- expression.left,
964
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
965
- transformJsxExpression(state, right),
966
- ts.factory.createToken(ts.SyntaxKind.ColonToken),
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 createGetter(ts.factory.createConditionalExpression(
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(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");
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");