scopeId.spec.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { baseCompile } from '../src/compile'
  2. import { POP_SCOPE_ID, PUSH_SCOPE_ID } from '../src/runtimeHelpers'
  3. import { PatchFlags } from '@vue/shared'
  4. import { genFlagText } from './testUtils'
  5. /**
  6. * Ensure all slot functions are wrapped with _withCtx
  7. * which sets the currentRenderingInstance and currentScopeId when rendering
  8. * the slot.
  9. */
  10. describe('scopeId compiler support', () => {
  11. test('should only work in module mode', () => {
  12. expect(() => {
  13. baseCompile(``, { scopeId: 'test' })
  14. }).toThrow(`"scopeId" option is only supported in module mode`)
  15. })
  16. test('should wrap default slot', () => {
  17. const { code } = baseCompile(`<Child><div/></Child>`, {
  18. mode: 'module',
  19. scopeId: 'test',
  20. })
  21. expect(code).toMatch(`default: _withCtx(() => [`)
  22. expect(code).toMatchSnapshot()
  23. })
  24. test('should wrap named slots', () => {
  25. const { code } = baseCompile(
  26. `<Child>
  27. <template #foo="{ msg }">{{ msg }}</template>
  28. <template #bar><div/></template>
  29. </Child>
  30. `,
  31. {
  32. mode: 'module',
  33. scopeId: 'test',
  34. },
  35. )
  36. expect(code).toMatch(`foo: _withCtx(({ msg }) => [`)
  37. expect(code).toMatch(`bar: _withCtx(() => [`)
  38. expect(code).toMatchSnapshot()
  39. })
  40. test('should wrap dynamic slots', () => {
  41. const { code } = baseCompile(
  42. `<Child>
  43. <template #foo v-if="ok"><div/></template>
  44. <template v-for="i in list" #[i]><div/></template>
  45. </Child>
  46. `,
  47. {
  48. mode: 'module',
  49. scopeId: 'test',
  50. },
  51. )
  52. expect(code).toMatch(/name: "foo",\s+fn: _withCtx\(/)
  53. expect(code).toMatch(/name: i,\s+fn: _withCtx\(/)
  54. expect(code).toMatchSnapshot()
  55. })
  56. test('should push scopeId for hoisted nodes', () => {
  57. const { ast, code } = baseCompile(
  58. `<div><div>hello</div>{{ foo }}<div>world</div></div>`,
  59. {
  60. mode: 'module',
  61. scopeId: 'test',
  62. hoistStatic: true,
  63. },
  64. )
  65. expect(ast.helpers).toContain(PUSH_SCOPE_ID)
  66. expect(ast.helpers).toContain(POP_SCOPE_ID)
  67. expect(ast.hoists.length).toBe(2)
  68. ;[
  69. `const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
  70. `const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
  71. PatchFlags.HOISTED,
  72. )}))`,
  73. `const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
  74. PatchFlags.HOISTED,
  75. )}))`,
  76. ].forEach(c => expect(code).toMatch(c))
  77. expect(code).toMatchSnapshot()
  78. })
  79. test('should push typescript-compatible scopeId for hoisted nodes', () => {
  80. const { ast, code } = baseCompile(
  81. `<div><div>hello</div>{{ foo }}<div>world</div></div>`,
  82. {
  83. mode: 'module',
  84. scopeId: 'test',
  85. hoistStatic: true,
  86. isTS: true,
  87. },
  88. )
  89. expect(ast.helpers).toContain(PUSH_SCOPE_ID)
  90. expect(ast.helpers).toContain(POP_SCOPE_ID)
  91. expect(ast.hoists.length).toBe(2)
  92. ;[
  93. `const _withScopeId = (n: any) => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
  94. `const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
  95. PatchFlags.HOISTED,
  96. )}))`,
  97. `const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
  98. PatchFlags.HOISTED,
  99. )}))`,
  100. ].forEach(c => expect(code).toMatch(c))
  101. expect(code).toMatchSnapshot()
  102. })
  103. })