transformElement.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.processProps = exports.transformElement = void 0;
  4. const shared_1 = require("@vue/shared");
  5. const compiler_core_1 = require("@vue/compiler-core");
  6. const uni_shared_1 = require("@dcloudio/uni-shared");
  7. const errors_1 = require("../errors");
  8. const vModel_1 = require("./vModel");
  9. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  10. const transformElement = (node, context) => {
  11. return function postTransformElement() {
  12. node = context.currentNode;
  13. if (!(node.type === 1 /* NodeTypes.ELEMENT */ &&
  14. (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
  15. node.tagType === 1 /* ElementTypes.COMPONENT */))) {
  16. return;
  17. }
  18. if (node.tagType === 1 /* ElementTypes.COMPONENT */) {
  19. processComponent(node, context);
  20. }
  21. if (context.scopeId) {
  22. addScopeId(node, context.scopeId);
  23. }
  24. const { props } = node;
  25. if (props.length > 0) {
  26. processProps(node, context);
  27. }
  28. };
  29. };
  30. exports.transformElement = transformElement;
  31. function addScopeId(node, scopeId) {
  32. return (0, uni_cli_shared_1.addStaticClass)(node, scopeId);
  33. }
  34. function processComponent(node, context) {
  35. const { tag } = node;
  36. if (context.bindingComponents[tag]) {
  37. return;
  38. }
  39. // 1. dynamic component
  40. if ((0, uni_shared_1.isComponentTag)(tag)) {
  41. return context.onError((0, errors_1.createMPCompilerError)(8 /* MPErrorCodes.X_DYNAMIC_COMPONENT_NOT_SUPPORTED */, node.loc));
  42. }
  43. if ((0, compiler_core_1.findDir)(node, 'is')) {
  44. return context.onError((0, errors_1.createMPCompilerError)(6 /* MPErrorCodes.X_V_IS_NOT_SUPPORTED */, node.loc));
  45. }
  46. // TODO not supported
  47. // const isProp = findProp(node, 'is')
  48. // if (isProp) {
  49. // }
  50. // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
  51. const builtIn = (0, compiler_core_1.isCoreComponent)(tag) || context.isBuiltInComponent(tag);
  52. if (builtIn) {
  53. return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
  54. }
  55. // 3. user component (from setup bindings)
  56. const fromSetup = resolveSetupReference(tag, context);
  57. if (fromSetup) {
  58. return (context.bindingComponents[tag] = {
  59. name: fromSetup,
  60. type: "setup" /* BindingComponentTypes.SETUP */,
  61. });
  62. }
  63. const dotIndex = tag.indexOf('.');
  64. if (dotIndex > 0) {
  65. return context.onError((0, errors_1.createMPCompilerError)(7 /* MPErrorCodes.X_NOT_SUPPORTED */, node.loc, tag));
  66. }
  67. // 4. Self referencing component (inferred from filename)
  68. if (context.selfName && (0, shared_1.capitalize)((0, shared_1.camelize)(tag)) === context.selfName) {
  69. return (context.bindingComponents[tag] = {
  70. name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
  71. type: "self" /* BindingComponentTypes.SELF */,
  72. });
  73. }
  74. // 5. user component (resolve)
  75. context.bindingComponents[tag] = {
  76. name: (0, compiler_core_1.toValidAssetId)(tag, `component`),
  77. type: "unknown" /* BindingComponentTypes.UNKNOWN */,
  78. };
  79. context.helper(compiler_core_1.RESOLVE_COMPONENT);
  80. }
  81. function resolveSetupReference(name, context) {
  82. const bindings = context.bindingMetadata;
  83. if (!bindings || bindings.__isScriptSetup === false) {
  84. return;
  85. }
  86. const camelName = (0, shared_1.camelize)(name);
  87. const PascalName = (0, shared_1.capitalize)(camelName);
  88. const checkType = (type) => {
  89. if (bindings[name] === type) {
  90. return name;
  91. }
  92. if (bindings[camelName] === type) {
  93. return camelName;
  94. }
  95. if (bindings[PascalName] === type) {
  96. return PascalName;
  97. }
  98. };
  99. const fromConst = checkType("setup-const" /* BindingTypes.SETUP_CONST */) ||
  100. checkType("setup-reactive-const" /* BindingTypes.SETUP_REACTIVE_CONST */);
  101. if (fromConst) {
  102. return context.inline
  103. ? // in inline mode, const setup bindings (e.g. imports) can be used as-is
  104. fromConst
  105. : `$setup[${JSON.stringify(fromConst)}]`;
  106. }
  107. const fromMaybeRef = checkType("setup-let" /* BindingTypes.SETUP_LET */) ||
  108. checkType("setup-ref" /* BindingTypes.SETUP_REF */) ||
  109. checkType("setup-maybe-ref" /* BindingTypes.SETUP_MAYBE_REF */);
  110. if (fromMaybeRef) {
  111. return context.inline
  112. ? // setup scope bindings that may be refs need to be unrefed
  113. `${context.helperString(compiler_core_1.UNREF)}(${fromMaybeRef})`
  114. : `$setup[${JSON.stringify(fromMaybeRef)}]`;
  115. }
  116. }
  117. function processProps(node, context, props = node.props) {
  118. const { tag } = node;
  119. const isComponent = node.tagType === 1 /* ElementTypes.COMPONENT */;
  120. const isPluginComponent = isComponent && context.isMiniProgramComponent(node.tag) === 'plugin';
  121. for (let i = 0; i < props.length; i++) {
  122. const prop = props[i];
  123. if (prop.type === 7 /* NodeTypes.DIRECTIVE */) {
  124. // directives
  125. const { name, arg, loc } = prop;
  126. const isVBind = name === 'bind';
  127. const isVOn = name === 'on';
  128. // skip v-slot - it is handled by its dedicated transform.
  129. if (name === 'slot') {
  130. if (!isComponent) {
  131. context.onError((0, compiler_core_1.createCompilerError)(40 /* ErrorCodes.X_V_SLOT_MISPLACED */, loc));
  132. }
  133. continue;
  134. }
  135. // skip v-once/v-memo - they are handled by dedicated transforms.
  136. if (name === 'once' || name === 'memo') {
  137. continue;
  138. }
  139. // skip v-is and :is on <component>
  140. if (name === 'is' ||
  141. (isVBind && (0, compiler_core_1.isStaticArgOf)(arg, 'is') && (0, uni_shared_1.isComponentTag)(tag))) {
  142. continue;
  143. }
  144. if (isVBind || isVOn) {
  145. // v-on=""
  146. // v-bind=""
  147. if (!arg) {
  148. if (isVOn) {
  149. context.onError((0, errors_1.createMPCompilerError)(0 /* MPErrorCodes.X_V_ON_NO_ARGUMENT */, loc));
  150. }
  151. if (isVBind && (!isComponent || isPluginComponent)) {
  152. context.onError((0, errors_1.createMPCompilerError)(2 /* MPErrorCodes.X_V_BIND_NO_ARGUMENT */, loc));
  153. }
  154. continue;
  155. }
  156. // v-on:[a]=""
  157. // v-on:[a.b]=""
  158. // v-bind:[a]=""
  159. // v-bind:[a.b]=""
  160. if (!(arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && arg.isStatic)) {
  161. if (isVOn) {
  162. context.onError((0, errors_1.createMPCompilerError)(1 /* MPErrorCodes.X_V_ON_DYNAMIC_EVENT */, loc));
  163. }
  164. if (isVBind && (!isComponent || isPluginComponent)) {
  165. context.onError((0, errors_1.createMPCompilerError)(3 /* MPErrorCodes.X_V_BIND_DYNAMIC_ARGUMENT */, loc));
  166. }
  167. continue;
  168. }
  169. }
  170. const directiveTransform = context.directiveTransforms[name];
  171. if (name !== 'model' && directiveTransform) {
  172. const { props } = directiveTransform(prop, node, context);
  173. if (props.length) {
  174. prop.exp = props[0].value;
  175. }
  176. }
  177. }
  178. }
  179. const transformVModel = (context.directiveTransforms.model ||
  180. vModel_1.transformModel);
  181. processVModel(node, transformVModel, context);
  182. }
  183. exports.processProps = processProps;
  184. function processVModel(node, transformVModel, context) {
  185. const { props } = node;
  186. const dirs = [];
  187. for (let i = 0; i < props.length; i++) {
  188. const prop = props[i];
  189. if (prop.type === 7 /* NodeTypes.DIRECTIVE */ && prop.name === 'model') {
  190. dirs.push(...transformVModel(prop, node, context)
  191. .props);
  192. props.splice(i, 1);
  193. i--;
  194. }
  195. }
  196. if (dirs.length) {
  197. props.push(...dirs);
  198. }
  199. }