block.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import type { BlockIRNode, CoreHelper } from '../ir'
  2. import {
  3. type CodeFragment,
  4. DELIMITERS_ARRAY,
  5. INDENT_END,
  6. INDENT_START,
  7. NEWLINE,
  8. buildCodeFragment,
  9. genCall,
  10. genMulti,
  11. } from './utils'
  12. import type { CodegenContext } from '../generate'
  13. import { genEffects, genOperations } from './operation'
  14. import { genChildren, genSelf } from './template'
  15. import { toValidAssetId } from '@vue/compiler-dom'
  16. export function genBlock(
  17. oper: BlockIRNode,
  18. context: CodegenContext,
  19. args: CodeFragment[] = [],
  20. root?: boolean,
  21. ): CodeFragment[] {
  22. return [
  23. '(',
  24. ...args,
  25. ') => {',
  26. INDENT_START,
  27. ...genBlockContent(oper, context, root),
  28. INDENT_END,
  29. NEWLINE,
  30. '}',
  31. ]
  32. }
  33. export function genBlockContent(
  34. block: BlockIRNode,
  35. context: CodegenContext,
  36. root?: boolean,
  37. genEffectsExtraFrag?: () => CodeFragment[],
  38. ): CodeFragment[] {
  39. const [frag, push] = buildCodeFragment()
  40. const { dynamic, effect, operation, returns } = block
  41. const resetBlock = context.enterBlock(block)
  42. if (root) {
  43. for (let name of context.ir.component) {
  44. const id = toValidAssetId(name, 'component')
  45. const maybeSelfReference = name.endsWith('__self')
  46. if (maybeSelfReference) name = name.slice(0, -6)
  47. push(
  48. NEWLINE,
  49. `const ${id} = `,
  50. ...genCall(
  51. context.helper('resolveComponent'),
  52. JSON.stringify(name),
  53. // pass additional `maybeSelfReference` flag
  54. maybeSelfReference ? 'true' : undefined,
  55. ),
  56. )
  57. }
  58. genResolveAssets('directive', 'resolveDirective')
  59. }
  60. for (const child of dynamic.children) {
  61. push(...genSelf(child, context))
  62. }
  63. for (const child of dynamic.children) {
  64. if (!child.hasDynamicChild) {
  65. push(...genChildren(child, context, push, `n${child.id!}`))
  66. }
  67. }
  68. push(...genOperations(operation, context))
  69. push(...genEffects(effect, context, genEffectsExtraFrag))
  70. if (root && context.ir.hasDeferredVShow) {
  71. push(NEWLINE, `deferredApplyVShows.forEach(fn => fn())`)
  72. }
  73. push(NEWLINE, `return `)
  74. const returnNodes = returns.map(n => `n${n}`)
  75. const returnsCode: CodeFragment[] =
  76. returnNodes.length > 1
  77. ? genMulti(DELIMITERS_ARRAY, ...returnNodes)
  78. : [returnNodes[0] || 'null']
  79. push(...returnsCode)
  80. resetBlock()
  81. return frag
  82. function genResolveAssets(
  83. kind: 'component' | 'directive',
  84. helper: CoreHelper,
  85. ) {
  86. for (const name of context.ir[kind]) {
  87. push(
  88. NEWLINE,
  89. `const ${toValidAssetId(name, kind)} = `,
  90. ...genCall(context.helper(helper), JSON.stringify(name)),
  91. )
  92. }
  93. }
  94. }