codegen.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.generate = void 0;
  4. const source_map_js_1 = require("source-map-js");
  5. const compiler_core_1 = require("@vue/compiler-core");
  6. const shared_1 = require("@vue/shared");
  7. const parser_1 = require("@babel/parser");
  8. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  9. const utils_1 = require("./utils");
  10. const runtimeHelpers_1 = require("./runtimeHelpers");
  11. const transformExpression_1 = require("./transforms/transformExpression");
  12. const types_1 = require("@babel/types");
  13. const transformSlotPropsDestructuring_1 = require("./transforms/transformSlotPropsDestructuring");
  14. function createCodegenContext(ast, { rootDir = '', targetLanguage = 'kotlin', mode = 'default', prefixIdentifiers = mode === 'module', bindingMetadata = {}, inline = false, sourceMap = false, filename = '', matchEasyCom = shared_1.NOOP, parseUTSComponent = shared_1.NOOP, originalLineOffset = 0, generatedLineOffset = 0, }) {
  15. const context = {
  16. rootDir,
  17. targetLanguage,
  18. mode,
  19. prefixIdentifiers,
  20. bindingMetadata,
  21. inline,
  22. sourceMap,
  23. filename,
  24. source: ast.loc.source,
  25. code: ``,
  26. easyComponentAutoImports: {},
  27. importEasyComponents: [],
  28. importUTSComponents: [],
  29. importUTSElements: [],
  30. column: 1,
  31. line: 1,
  32. offset: 0,
  33. indentLevel: 0,
  34. map: undefined,
  35. expressionPlugins: ['typescript'],
  36. matchEasyCom,
  37. parseUTSComponent,
  38. helper(key) {
  39. return `${compiler_core_1.helperNameMap[key]}`;
  40. },
  41. push(code, node) {
  42. context.code += code;
  43. if (context.map) {
  44. if (node) {
  45. let name;
  46. if (node.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
  47. const content = node.content.replace(/^_ctx\./, '');
  48. if (content !== node.content && (0, compiler_core_1.isSimpleIdentifier)(content)) {
  49. name = content;
  50. }
  51. }
  52. addMapping(node.loc.start, name);
  53. }
  54. (0, compiler_core_1.advancePositionWithMutation)(context, code);
  55. if (node && node.loc !== compiler_core_1.locStub) {
  56. addMapping(node.loc.end);
  57. }
  58. }
  59. },
  60. indent() {
  61. newline(++context.indentLevel);
  62. },
  63. deindent(withoutNewLine = false) {
  64. if (withoutNewLine) {
  65. --context.indentLevel;
  66. }
  67. else {
  68. newline(--context.indentLevel);
  69. }
  70. },
  71. newline() {
  72. newline(context.indentLevel);
  73. },
  74. };
  75. function newline(n) {
  76. context.push('\n' + ` `.repeat(n));
  77. }
  78. function addMapping(loc, name) {
  79. context.map.addMapping({
  80. name,
  81. source: context.filename,
  82. original: {
  83. line: loc.line + originalLineOffset,
  84. column: loc.column - 1, // source-map column is 0 based
  85. },
  86. generated: {
  87. line: context.line + generatedLineOffset,
  88. column: context.column - 1,
  89. },
  90. });
  91. }
  92. if (sourceMap) {
  93. // lazy require source-map implementation, only in non-browser builds
  94. context.map = new source_map_js_1.SourceMapGenerator();
  95. context.map.setSourceContent(filename, context.source);
  96. }
  97. return context;
  98. }
  99. const UTS_COMPONENT_ELEMENT_IMPORTS = `/*UTS-COMPONENTS-IMPORTS*/`;
  100. function generate(ast, options = {}) {
  101. const context = createCodegenContext(ast, options);
  102. const { mode, deindent, indent, push, newline } = context;
  103. const isSetupInlined = !!options.inline;
  104. // preambles
  105. // in setup() inline mode, the preamble is generated in a sub context
  106. // and returned separately.
  107. // const preambleContext = isSetupInlined
  108. // ? createCodegenContext(ast, options)
  109. // : context
  110. // 目前不分割
  111. const preambleContext = context;
  112. if (mode === 'module') {
  113. preambleContext.push(UTS_COMPONENT_ELEMENT_IMPORTS);
  114. newline();
  115. genEasyComImports(ast.components, preambleContext);
  116. if (ast.imports.length) {
  117. genImports(ast.imports, preambleContext);
  118. newline();
  119. }
  120. push((0, utils_1.genRenderFunctionDecl)(options) + ` {`);
  121. newline();
  122. if (!isSetupInlined) {
  123. push(`const _ctx = this`);
  124. newline();
  125. push(`const _cache = this.$.renderCache`);
  126. }
  127. // generate asset resolution statements
  128. if (ast.components.length) {
  129. newline();
  130. genAssets(ast.components, 'component', context);
  131. if (ast.directives.length || ast.temps > 0) {
  132. newline();
  133. }
  134. }
  135. if (ast.directives.length) {
  136. genAssets(ast.directives, 'directive', context);
  137. if (ast.temps > 0) {
  138. newline();
  139. }
  140. }
  141. if (ast.components.length || ast.directives.length || ast.temps) {
  142. newline();
  143. }
  144. indent();
  145. push(`return `);
  146. }
  147. if (ast.codegenNode) {
  148. genNode(ast.codegenNode, context);
  149. }
  150. else {
  151. push(`null`);
  152. }
  153. if (mode === 'module') {
  154. deindent();
  155. push(`}`);
  156. }
  157. preambleContext.code = preambleContext.code.replace(UTS_COMPONENT_ELEMENT_IMPORTS, context.importUTSElements.length
  158. ? context.importUTSElements.join(';') + ';'
  159. : '');
  160. return {
  161. ast,
  162. code: context.code,
  163. // preamble: isSetupInlined ? preambleContext.code : ``,
  164. easyComponentAutoImports: context.easyComponentAutoImports,
  165. importEasyComponents: context.importEasyComponents,
  166. importUTSComponents: context.importUTSComponents,
  167. imports: ast.imports.map((item) => `import '${item.path}'`),
  168. // SourceMapGenerator does have toJSON() method but it's not in the types
  169. map: context.map ? context.map.toJSON() : undefined,
  170. // @ts-ignore
  171. elements: ast.elements,
  172. };
  173. }
  174. exports.generate = generate;
  175. function genImports(importsOptions, context) {
  176. if (!importsOptions.length) {
  177. return;
  178. }
  179. importsOptions.forEach((imports) => {
  180. if ((0, shared_1.isString)(imports.exp)) {
  181. context.push(`import ${imports.exp} from '${imports.path}'`);
  182. }
  183. else if ((0, uni_cli_shared_1.isSimpleExpressionNode)(imports.exp)) {
  184. // 解决静态资源导入 sourcemap 映射问题
  185. context.push(`import ${imports.exp.content} from '${imports.path}'`, imports.exp);
  186. }
  187. else {
  188. context.push(`import `);
  189. genNode(imports.exp, context);
  190. context.push(` from '${imports.path}'`);
  191. }
  192. context.newline();
  193. });
  194. }
  195. function genEasyComImports(components, { push, newline, matchEasyCom, rootDir }) {
  196. for (let i = 0; i < components.length; i++) {
  197. let id = components[i];
  198. const maybeSelfReference = id.endsWith('__self');
  199. if (maybeSelfReference) {
  200. id = id.slice(0, -6);
  201. }
  202. const source = matchEasyCom(id, true);
  203. if (source) {
  204. const componentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
  205. push(`import ${componentId} from '${source}'`);
  206. newline();
  207. }
  208. }
  209. }
  210. function genAssets(assets, type, { helper, push, newline, importEasyComponents, easyComponentAutoImports, matchEasyCom, rootDir, }) {
  211. const resolver = helper(type === 'component' ? runtimeHelpers_1.RESOLVE_COMPONENT : runtimeHelpers_1.RESOLVE_DIRECTIVE);
  212. for (let i = 0; i < assets.length; i++) {
  213. let id = assets[i];
  214. // potential component implicit self-reference inferred from SFC filename
  215. const maybeSelfReference = id.endsWith('__self');
  216. if (maybeSelfReference) {
  217. id = id.slice(0, -6);
  218. }
  219. let assetCode = '';
  220. if (type === 'component') {
  221. const source = matchEasyCom(id, false);
  222. if (source) {
  223. const easyComponentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
  224. const componentId = (0, compiler_core_1.toValidAssetId)(id, type);
  225. assetCode = `const ${componentId} = ${helper(runtimeHelpers_1.RESOLVE_EASY_COMPONENT)}(${JSON.stringify(id)},${easyComponentId})`;
  226. const importCode = `import ${easyComponentId} from '${source}';`;
  227. if (!importEasyComponents.includes(importCode)) {
  228. importEasyComponents.push(importCode);
  229. (0, utils_1.addEasyComponentAutoImports)(easyComponentAutoImports, rootDir, id, source);
  230. }
  231. }
  232. }
  233. if (!assetCode) {
  234. assetCode = `const ${(0, compiler_core_1.toValidAssetId)(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`;
  235. }
  236. push(assetCode);
  237. if (i < assets.length - 1) {
  238. newline();
  239. }
  240. }
  241. }
  242. function isText(n) {
  243. return ((0, shared_1.isString)(n) ||
  244. n.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
  245. n.type === 2 /* NodeTypes.TEXT */ ||
  246. n.type === 5 /* NodeTypes.INTERPOLATION */ ||
  247. n.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */);
  248. }
  249. function genNodeListAsArray(nodes, context) {
  250. const multilines = nodes.length > 3 || nodes.some((n) => (0, shared_1.isArray)(n) || !isText(n));
  251. context.push(`[`);
  252. multilines && context.indent();
  253. genNodeList(nodes, context, multilines);
  254. multilines && context.deindent();
  255. context.push(`]`);
  256. }
  257. function genNodeList(nodes, context, multilines = false, comma = true) {
  258. const { push, newline } = context;
  259. for (let i = 0; i < nodes.length; i++) {
  260. const node = nodes[i];
  261. if ((0, shared_1.isString)(node)) {
  262. push(node);
  263. }
  264. else if ((0, shared_1.isArray)(node)) {
  265. genNodeListAsArray(node, context);
  266. }
  267. else {
  268. genNode(node, context);
  269. }
  270. if (i < nodes.length - 1) {
  271. if (multilines) {
  272. comma && push(',');
  273. newline();
  274. }
  275. else {
  276. comma && push(', ');
  277. }
  278. }
  279. }
  280. }
  281. function genNode(node, context) {
  282. if ((0, shared_1.isString)(node)) {
  283. context.push(node);
  284. return;
  285. }
  286. if ((0, shared_1.isSymbol)(node)) {
  287. context.push(context.helper(node));
  288. return;
  289. }
  290. switch (node.type) {
  291. case 1 /* NodeTypes.ELEMENT */:
  292. case 9 /* NodeTypes.IF */:
  293. case 11 /* NodeTypes.FOR */:
  294. genNode(node.codegenNode, context);
  295. break;
  296. case 2 /* NodeTypes.TEXT */:
  297. genText(node, context);
  298. break;
  299. case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
  300. genExpression(node, context);
  301. break;
  302. case 5 /* NodeTypes.INTERPOLATION */:
  303. genInterpolation(node, context);
  304. break;
  305. case 12 /* NodeTypes.TEXT_CALL */:
  306. genNode(node.codegenNode, context);
  307. break;
  308. case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
  309. genCompoundExpression(node, context);
  310. break;
  311. case 3 /* NodeTypes.COMMENT */:
  312. genComment(node, context);
  313. break;
  314. case 13 /* NodeTypes.VNODE_CALL */:
  315. genVNodeCall(node, context);
  316. break;
  317. case 14 /* NodeTypes.JS_CALL_EXPRESSION */:
  318. genCallExpression(node, context);
  319. break;
  320. case 15 /* NodeTypes.JS_OBJECT_EXPRESSION */:
  321. genObjectExpression(node, context);
  322. break;
  323. case 17 /* NodeTypes.JS_ARRAY_EXPRESSION */:
  324. genArrayExpression(node, context);
  325. break;
  326. case 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */:
  327. genFunctionExpression(node, context);
  328. break;
  329. case 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */:
  330. genConditionalExpression(node, context);
  331. break;
  332. case 20 /* NodeTypes.JS_CACHE_EXPRESSION */:
  333. genCacheExpression(node, context);
  334. break;
  335. case 21 /* NodeTypes.JS_BLOCK_STATEMENT */:
  336. genNodeList(node.body, context, true, false);
  337. break;
  338. /* istanbul ignore next */
  339. case 10 /* NodeTypes.IF_BRANCH */:
  340. // noop
  341. break;
  342. default:
  343. }
  344. }
  345. function genText(node, context) {
  346. context.push(JSON.stringify(node.content), node);
  347. }
  348. function genExpression(node, context) {
  349. const { content, isStatic } = node;
  350. context.push(isStatic ? JSON.stringify(content) : content, node);
  351. }
  352. function genInterpolation(node, context) {
  353. const { push, helper } = context;
  354. push(`${helper(compiler_core_1.TO_DISPLAY_STRING)}(`);
  355. genNode(node.content, context);
  356. push(`)`);
  357. }
  358. function genCompoundExpression(node, context) {
  359. for (let i = 0; i < node.children.length; i++) {
  360. const child = node.children[i];
  361. if ((0, shared_1.isString)(child)) {
  362. context.push(child);
  363. }
  364. else {
  365. genNode(child, context);
  366. }
  367. }
  368. }
  369. function genExpressionAsPropertyKey(node, context) {
  370. const { push } = context;
  371. if (node.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
  372. push(`[`);
  373. genCompoundExpression(node, context);
  374. push(`]`);
  375. }
  376. else if (node.isStatic) {
  377. // only quote keys if necessary
  378. const text = (0, compiler_core_1.isSimpleIdentifier)(node.content)
  379. ? node.content
  380. : JSON.stringify(node.content);
  381. push(text, node);
  382. }
  383. else {
  384. push(`[${node.content}]`, node);
  385. }
  386. }
  387. function genComment(node, context) {
  388. const { push, helper } = context;
  389. push(`${helper(compiler_core_1.CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);
  390. }
  391. function parseTag(tag, curNode, { parseUTSComponent, targetLanguage, importUTSComponents, importUTSElements, }) {
  392. if ((0, shared_1.isString)(tag)) {
  393. // 原生UTS组件
  394. const utsComponentOptions = parseUTSComponent(tag.slice(1, -1), targetLanguage);
  395. if (utsComponentOptions) {
  396. const importCode = `import '${utsComponentOptions.source}';`;
  397. if (!importUTSComponents.includes(importCode)) {
  398. importUTSComponents.push(importCode);
  399. }
  400. const importElementCode = `import { ${utsComponentOptions.className.replace(/Component$/, 'Element')} } from '${utsComponentOptions.namespace}'`;
  401. if (!importUTSElements.includes(importElementCode)) {
  402. importUTSElements.push(importElementCode);
  403. }
  404. return (0, compiler_core_1.createSimpleExpression)(utsComponentOptions.namespace +
  405. '.' +
  406. utsComponentOptions.className +
  407. '.name', false, curNode.loc);
  408. }
  409. }
  410. return tag;
  411. }
  412. function genVNodeCall(node, context) {
  413. const { push, helper } = context;
  414. const { tag, props, children, patchFlag, dynamicProps, directives,
  415. // isBlock,
  416. disableTracking, isComponent, } = node;
  417. if (directives) {
  418. push(helper(compiler_core_1.WITH_DIRECTIVES) + `(`);
  419. }
  420. const isBlock = false;
  421. if (isBlock) {
  422. push(`(${helper(compiler_core_1.OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);
  423. }
  424. const callHelper = isBlock
  425. ? (0, compiler_core_1.getVNodeBlockHelper)(false, isComponent)
  426. : (0, compiler_core_1.getVNodeHelper)(false, isComponent);
  427. push(helper(callHelper) + `(`, node);
  428. genNodeList(genNullableArgs([
  429. parseTag(tag, node, context),
  430. props,
  431. children,
  432. patchFlag,
  433. dynamicProps,
  434. ]), context);
  435. push(`)`);
  436. if (isBlock) {
  437. push(`)`);
  438. }
  439. if (directives) {
  440. push(`, `);
  441. genNode(directives, context);
  442. push(`)`);
  443. }
  444. }
  445. function genNullableArgs(args) {
  446. let i = args.length;
  447. while (i--) {
  448. if (args[i] != null)
  449. break;
  450. }
  451. return args.slice(0, i + 1).map((arg) => arg || `null`);
  452. }
  453. // JavaScript
  454. function genCallExpression(node, context) {
  455. const { push, helper } = context;
  456. const callee = (0, shared_1.isString)(node.callee) ? node.callee : helper(node.callee);
  457. push(callee + `(`, node);
  458. if (callee === helper(runtimeHelpers_1.RENDER_LIST)) {
  459. genRenderList(node);
  460. }
  461. genNodeList(node.arguments, context);
  462. push(`)`);
  463. }
  464. function genRenderList(node) {
  465. node.arguments.forEach((argument) => {
  466. if (argument.type === 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */) {
  467. argument.returnType = 'VNode';
  468. }
  469. });
  470. }
  471. function genObjectExpression(node, context) {
  472. const { push, indent, deindent, newline } = context;
  473. const { properties } = node;
  474. if (!properties.length) {
  475. push(`utsMapOf()`, node);
  476. return;
  477. }
  478. push(`utsMapOf(`);
  479. const multilines = properties.length > 1 ||
  480. properties.some((p) => p.value.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */);
  481. push(multilines ? `{` : `{ `);
  482. multilines && indent();
  483. for (let i = 0; i < properties.length; i++) {
  484. const { key, value } = properties[i];
  485. // key
  486. genExpressionAsPropertyKey(key, context);
  487. push(`: `);
  488. // value
  489. genNode(value, context);
  490. if (i < properties.length - 1) {
  491. // will only reach this if it's multilines
  492. push(`,`);
  493. newline();
  494. }
  495. }
  496. multilines && deindent();
  497. push(multilines ? `}` : ` }`);
  498. push(`)`);
  499. }
  500. function genArrayExpression(node, context) {
  501. genNodeListAsArray(node.elements, context);
  502. }
  503. function genFunctionExpression(node, context) {
  504. const { push, indent, deindent } = context;
  505. const { params, returns, body, newline, isSlot } = node;
  506. if (isSlot) {
  507. // wrap slot functions with owner context
  508. push(`${compiler_core_1.helperNameMap[params ? runtimeHelpers_1.WITH_SCOPED_SLOT_CTX : runtimeHelpers_1.WITH_SLOT_CTX]}(`);
  509. }
  510. push(`(`, node);
  511. if ((0, shared_1.isArray)(params)) {
  512. genNodeList(params, context);
  513. }
  514. else if (params) {
  515. if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params) ||
  516. params?.content === '{}') {
  517. push(transformSlotPropsDestructuring_1.SLOT_PROPS_NAME);
  518. }
  519. else {
  520. genNode(params, context);
  521. }
  522. }
  523. if (node.returnType) {
  524. push(`): ${node.returnType} => `);
  525. }
  526. else {
  527. if (isSlot) {
  528. if (params) {
  529. push(`: Map<string, any | null>): any[] => `);
  530. if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params)) {
  531. push('{');
  532. (0, transformSlotPropsDestructuring_1.createDestructuringSlotProps)(params, context);
  533. context.newline();
  534. push('return ');
  535. }
  536. }
  537. else {
  538. push(`): any[] => `);
  539. }
  540. }
  541. else {
  542. push(`) => `);
  543. }
  544. }
  545. if (newline || body) {
  546. push(`{`);
  547. indent();
  548. }
  549. if (returns) {
  550. if (newline) {
  551. push(`return `);
  552. }
  553. if ((0, shared_1.isArray)(returns)) {
  554. genNodeListAsArray(returns, context);
  555. }
  556. else {
  557. genNode(returns, context);
  558. }
  559. }
  560. else if (body) {
  561. genNode(body, context);
  562. }
  563. if (newline || body) {
  564. deindent();
  565. push(`}`);
  566. }
  567. if (isSlot) {
  568. if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params)) {
  569. push('}');
  570. }
  571. push(`)`);
  572. }
  573. }
  574. const booleanBinExprOperators = ['==', '===', '!=', '!==', '<', '>', '<=', '>='];
  575. function shouldWrapperConditionalTest(test, context) {
  576. const isSimpleExpr = (0, uni_cli_shared_1.isSimpleExpressionNode)(test);
  577. if (isSimpleExpr) {
  578. const { content } = test;
  579. if (content === 'true' || content === 'false') {
  580. return false;
  581. }
  582. }
  583. if (isSimpleExpr || (0, uni_cli_shared_1.isCompoundExpressionNode)(test)) {
  584. const code = (0, transformExpression_1.stringifyExpression)(test);
  585. const ast = (0, parser_1.parseExpression)(code, {
  586. plugins: context.expressionPlugins,
  587. });
  588. if ((0, types_1.isBinaryExpression)(ast)) {
  589. // 先简易解析
  590. if (booleanBinExprOperators.includes(ast.operator)) {
  591. return false;
  592. }
  593. }
  594. }
  595. return true;
  596. }
  597. function genConditionalExpression(node, context) {
  598. const { test, consequent, alternate, newline: needNewline } = node;
  599. const { push, indent, deindent, newline } = context;
  600. const wrapper = shouldWrapperConditionalTest(test, context);
  601. wrapper && push(`${context.helper(runtimeHelpers_1.IS_TRUE)}(`);
  602. if (test.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
  603. genExpression(test, context);
  604. }
  605. else {
  606. genNode(test, context);
  607. }
  608. wrapper && push(`)`);
  609. needNewline && indent();
  610. context.indentLevel++;
  611. needNewline || push(` `);
  612. push(`? `);
  613. genNode(consequent, context);
  614. context.indentLevel--;
  615. needNewline && newline();
  616. needNewline || push(` `);
  617. push(`: `);
  618. const isNested = alternate.type === 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */;
  619. if (!isNested) {
  620. context.indentLevel++;
  621. }
  622. genNode(alternate, context);
  623. if (!isNested) {
  624. context.indentLevel--;
  625. }
  626. needNewline && deindent(true /* without newline */);
  627. }
  628. function genCacheExpression(node, context) {
  629. const { push, helper, indent, deindent, newline } = context;
  630. push(`${compiler_core_1.helperNameMap[runtimeHelpers_1.RESOLVE_CACHE]}(_cache, ${node.index}, (): VNode => {`);
  631. if (node.isVNode) {
  632. indent();
  633. push(`${helper(compiler_core_1.SET_BLOCK_TRACKING)}(-1)`);
  634. newline();
  635. }
  636. push(`_cache[${node.index}] = `);
  637. genNode(node.value, context);
  638. if (node.isVNode) {
  639. newline();
  640. push(`${helper(compiler_core_1.SET_BLOCK_TRACKING)}(1)`);
  641. newline();
  642. push(`return _cache[${node.index}] as VNode`);
  643. deindent();
  644. }
  645. push(`})`);
  646. }