vIf.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.processIf = exports.transformIf = exports.isIfElementNode = void 0;
  4. const types_1 = require("@babel/types");
  5. const compiler_core_1 = require("@vue/compiler-core");
  6. const ast_1 = require("../ast");
  7. const transform_1 = require("../transform");
  8. const transformExpression_1 = require("./transformExpression");
  9. const utils_1 = require("./utils");
  10. function isIfElementNode(node) {
  11. return !!node.vIf;
  12. }
  13. exports.isIfElementNode = isIfElementNode;
  14. exports.transformIf = (0, transform_1.createStructuralDirectiveTransform)(/^(if|else|else-if)$/, (node, dir, context) => {
  15. return processIf(node, dir, context, (ifNode, branch, isRoot) => {
  16. const { currentScope: parentScope, popScope } = context;
  17. const ifOptions = {
  18. name: dir.name,
  19. };
  20. branch.vIf = ifOptions;
  21. const condition = dir.exp ? (0, ast_1.parseExpr)(dir.exp, context) : undefined;
  22. const vIfScope = context.addVIfScope({
  23. name: dir.name,
  24. condition,
  25. });
  26. if (condition) {
  27. if (!(0, utils_1.isStaticLiteral)(condition)) {
  28. ifOptions.condition = (0, utils_1.rewriteExpression)(dir.exp, context, condition, parentScope).content;
  29. }
  30. else {
  31. ifOptions.condition = dir.exp.content;
  32. }
  33. }
  34. return () => {
  35. if (isRoot) {
  36. parentScope.properties.push((0, ast_1.createVIfSpreadElement)(vIfScope));
  37. }
  38. else {
  39. const vIfSpreadElement = findVIfSpreadElement(parentScope);
  40. if (!vIfSpreadElement) {
  41. popScope();
  42. return context.onError((0, compiler_core_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
  43. }
  44. let alternate = (0, ast_1.createObjectExpression)([]);
  45. if (dir.name === 'else-if') {
  46. alternate = (0, ast_1.createVIfConditionalExpression)(vIfScope);
  47. }
  48. else if (dir.name === 'else') {
  49. alternate = (0, ast_1.createObjectExpression)(vIfScope.properties);
  50. }
  51. findVIfConditionalExpression(vIfSpreadElement.argument).alternate = alternate;
  52. }
  53. popScope();
  54. };
  55. });
  56. });
  57. function processIf(node, dir, context, processCodegen) {
  58. if (dir.name !== 'else' &&
  59. (!dir.exp || !dir.exp.content.trim())) {
  60. const loc = dir.exp ? dir.exp.loc : node.loc;
  61. context.onError((0, compiler_core_1.createCompilerError)(28 /* ErrorCodes.X_V_IF_NO_EXPRESSION */, dir.loc));
  62. dir.exp = (0, compiler_core_1.createSimpleExpression)(`true`, false, loc);
  63. }
  64. if (context.prefixIdentifiers && dir.exp) {
  65. // dir.exp can only be simple expression because vIf transform is applied
  66. // before expression transform.
  67. dir.exp = (0, transformExpression_1.processExpression)(dir.exp, context);
  68. }
  69. if (dir.name === 'if') {
  70. const ifNode = {
  71. type: 9 /* NodeTypes.IF */,
  72. loc: node.loc,
  73. branches: [node],
  74. };
  75. context.replaceNode(ifNode);
  76. if (processCodegen) {
  77. return processCodegen(ifNode, node, true);
  78. }
  79. }
  80. else {
  81. // locate the adjacent v-if
  82. const siblings = context.parent.children;
  83. let i = siblings.indexOf(node);
  84. while (i-- >= -1) {
  85. const sibling = siblings[i];
  86. if (sibling && sibling.type === 3 /* NodeTypes.COMMENT */) {
  87. context.removeNode(sibling);
  88. continue;
  89. }
  90. if (sibling &&
  91. sibling.type === 2 /* NodeTypes.TEXT */ &&
  92. !sibling.content.trim().length) {
  93. context.removeNode(sibling);
  94. continue;
  95. }
  96. if (sibling && sibling.type === 9 /* NodeTypes.IF */) {
  97. // Check if v-else was followed by v-else-if
  98. if (dir.name === 'else-if' &&
  99. sibling.branches[sibling.branches.length - 1].vIf.condition === undefined) {
  100. context.onError((0, compiler_core_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
  101. }
  102. // move the node to the if node's branches
  103. context.removeNode();
  104. sibling.branches.push(node);
  105. const onExit = processCodegen &&
  106. processCodegen(sibling, node, false);
  107. // since the branch was removed, it will not be traversed.
  108. // make sure to traverse here.
  109. (0, transform_1.traverseNode)(node, context);
  110. // call on exit
  111. if (onExit)
  112. onExit();
  113. // make sure to reset currentNode after traversal to indicate this
  114. // node has been removed.
  115. context.currentNode = null;
  116. }
  117. else {
  118. context.onError((0, compiler_core_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
  119. }
  120. break;
  121. }
  122. }
  123. }
  124. exports.processIf = processIf;
  125. function findVIfSpreadElement({ properties }) {
  126. const len = properties.length;
  127. for (let i = len - 1; i >= 0; i--) {
  128. const prop = properties[i];
  129. if ((0, types_1.isSpreadElement)(prop)) {
  130. return prop;
  131. }
  132. }
  133. }
  134. function findVIfConditionalExpression(vIfConditionalExpression) {
  135. if ((0, types_1.isConditionalExpression)(vIfConditionalExpression.alternate)) {
  136. return findVIfConditionalExpression(vIfConditionalExpression.alternate);
  137. }
  138. return vIfConditionalExpression;
  139. }