hoistStatic.spec.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import { BindingTypes } from '@vue/compiler-core'
  2. import { SFCScriptCompileOptions } from '../../src'
  3. import { compileSFCScript, assertCode } from '../utils'
  4. describe('sfc hoist static', () => {
  5. function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
  6. return compileSFCScript(src, {
  7. inlineTemplate: true,
  8. hoistStatic: true,
  9. ...options
  10. })
  11. }
  12. test('should hoist literal value', () => {
  13. const code = `
  14. const string = 'default value'
  15. const number = 123
  16. const boolean = false
  17. const nil = null
  18. const bigint = 100n
  19. const template = \`str\`
  20. const regex = /.*/g
  21. `.trim()
  22. const { content, bindings } = compile(`
  23. <script setup>
  24. ${code}
  25. </script>
  26. `)
  27. // should hoist to first line
  28. expect(content.startsWith(code)).toBe(true)
  29. expect(bindings).toStrictEqual({
  30. string: BindingTypes.LITERAL_CONST,
  31. number: BindingTypes.LITERAL_CONST,
  32. boolean: BindingTypes.LITERAL_CONST,
  33. nil: BindingTypes.LITERAL_CONST,
  34. bigint: BindingTypes.LITERAL_CONST,
  35. template: BindingTypes.LITERAL_CONST,
  36. regex: BindingTypes.LITERAL_CONST
  37. })
  38. assertCode(content)
  39. })
  40. test('should hoist expressions', () => {
  41. const code = `
  42. const unary = !false
  43. const binary = 1 + 2
  44. const conditional = 1 ? 2 : 3
  45. const sequence = (1, true, 'foo', 1)
  46. `.trim()
  47. const { content, bindings } = compile(`
  48. <script setup>
  49. ${code}
  50. </script>
  51. `)
  52. // should hoist to first line
  53. expect(content.startsWith(code)).toBe(true)
  54. expect(bindings).toStrictEqual({
  55. binary: BindingTypes.LITERAL_CONST,
  56. conditional: BindingTypes.LITERAL_CONST,
  57. unary: BindingTypes.LITERAL_CONST,
  58. sequence: BindingTypes.LITERAL_CONST
  59. })
  60. assertCode(content)
  61. })
  62. test('should hoist w/ defineProps/Emits', () => {
  63. const hoistCode = `const defaultValue = 'default value'`
  64. const { content, bindings } = compile(`
  65. <script setup>
  66. ${hoistCode}
  67. defineProps({
  68. foo: {
  69. default: defaultValue
  70. }
  71. })
  72. </script>
  73. `)
  74. // should hoist to first line
  75. expect(content.startsWith(hoistCode)).toBe(true)
  76. expect(bindings).toStrictEqual({
  77. foo: BindingTypes.PROPS,
  78. defaultValue: BindingTypes.LITERAL_CONST
  79. })
  80. assertCode(content)
  81. })
  82. test('should not hoist a variable', () => {
  83. const code = `
  84. let KEY1 = 'default value'
  85. var KEY2 = 123
  86. `.trim()
  87. const { content, bindings } = compile(`
  88. <script setup>
  89. ${code}
  90. </script>
  91. `)
  92. expect(bindings).toStrictEqual({
  93. KEY1: BindingTypes.SETUP_LET,
  94. KEY2: BindingTypes.SETUP_LET
  95. })
  96. expect(content).toMatch(`setup(__props) {\n\n ${code}`)
  97. assertCode(content)
  98. })
  99. test('should not hoist a constant initialized to a reference value', () => {
  100. const code = `
  101. const KEY1 = Boolean
  102. const KEY2 = [Boolean]
  103. const KEY3 = [getCurrentInstance()]
  104. let i = 0;
  105. const KEY4 = (i++, 'foo')
  106. enum KEY5 {
  107. FOO = 1,
  108. BAR = getCurrentInstance(),
  109. }
  110. const KEY6 = \`template\${i}\`
  111. `.trim()
  112. const { content, bindings } = compile(`
  113. <script setup lang="ts">
  114. ${code}
  115. </script>
  116. `)
  117. expect(bindings).toStrictEqual({
  118. KEY1: BindingTypes.SETUP_MAYBE_REF,
  119. KEY2: BindingTypes.SETUP_CONST,
  120. KEY3: BindingTypes.SETUP_CONST,
  121. KEY4: BindingTypes.SETUP_CONST,
  122. KEY5: BindingTypes.SETUP_CONST,
  123. KEY6: BindingTypes.SETUP_CONST,
  124. i: BindingTypes.SETUP_LET
  125. })
  126. expect(content).toMatch(`setup(__props) {\n\n ${code}`)
  127. assertCode(content)
  128. })
  129. test('should not hoist a object or array', () => {
  130. const code = `
  131. const obj = { foo: 'bar' }
  132. const arr = [1, 2, 3]
  133. `.trim()
  134. const { content, bindings } = compile(`
  135. <script setup>
  136. ${code}
  137. </script>
  138. `)
  139. expect(bindings).toStrictEqual({
  140. arr: BindingTypes.SETUP_CONST,
  141. obj: BindingTypes.SETUP_CONST
  142. })
  143. expect(content).toMatch(`setup(__props) {\n\n ${code}`)
  144. assertCode(content)
  145. })
  146. test('should not hoist a function or class', () => {
  147. const code = `
  148. const fn = () => {}
  149. function fn2() {}
  150. class Foo {}
  151. `.trim()
  152. const { content, bindings } = compile(`
  153. <script setup>
  154. ${code}
  155. </script>
  156. `)
  157. expect(bindings).toStrictEqual({
  158. Foo: BindingTypes.SETUP_CONST,
  159. fn: BindingTypes.SETUP_CONST,
  160. fn2: BindingTypes.SETUP_CONST
  161. })
  162. expect(content).toMatch(`setup(__props) {\n\n ${code}`)
  163. assertCode(content)
  164. })
  165. test('should enable when only script setup', () => {
  166. const { content, bindings } = compile(`
  167. <script>
  168. const foo = 'bar'
  169. </script>
  170. <script setup>
  171. const foo = 'bar'
  172. </script>
  173. `)
  174. expect(bindings).toStrictEqual({
  175. foo: BindingTypes.SETUP_CONST
  176. })
  177. assertCode(content)
  178. })
  179. test('should not hoist when disabled', () => {
  180. const { content, bindings } = compile(
  181. `
  182. <script setup>
  183. const foo = 'bar'
  184. </script>
  185. `,
  186. { hoistStatic: false }
  187. )
  188. expect(bindings).toStrictEqual({
  189. foo: BindingTypes.SETUP_CONST
  190. })
  191. assertCode(content)
  192. })
  193. })