vue3-core/packages/compiler-sfc/__tests__/compileScriptHoistStatic.sp...

191 lines
4.8 KiB
TypeScript

import { BindingTypes } from '@vue/compiler-core'
import { SFCScriptCompileOptions } from '../src'
import { compileSFCScript, assertCode } from './utils'
describe('sfc hoist static', () => {
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
return compileSFCScript(src, {
inlineTemplate: true,
hoistStatic: true,
...options
})
}
test('should hoist literal value', () => {
const code = `
const string = 'default value'
const number = 123
const boolean = false
const nil = null
const bigint = 100n
const template = \`str\`
const regex = /.*/g
`.trim()
const { content, bindings } = compile(`
<script setup>
${code}
</script>
`)
// should hoist to first line
expect(content.startsWith(code)).toBe(true)
expect(bindings).toStrictEqual({
string: BindingTypes.LITERAL_CONST,
number: BindingTypes.LITERAL_CONST,
boolean: BindingTypes.LITERAL_CONST,
nil: BindingTypes.LITERAL_CONST,
bigint: BindingTypes.LITERAL_CONST,
template: BindingTypes.LITERAL_CONST,
regex: BindingTypes.LITERAL_CONST
})
assertCode(content)
})
test('should hoist expressions', () => {
const code = `
const unary = !false
const binary = 1 + 2
const conditional = 1 ? 2 : 3
const sequence = (1, true, 'foo', 1)
`.trim()
const { content, bindings } = compile(`
<script setup>
${code}
</script>
`)
// should hoist to first line
expect(content.startsWith(code)).toBe(true)
expect(bindings).toStrictEqual({
binary: BindingTypes.LITERAL_CONST,
conditional: BindingTypes.LITERAL_CONST,
unary: BindingTypes.LITERAL_CONST,
sequence: BindingTypes.LITERAL_CONST
})
assertCode(content)
})
test('should hoist w/ defineProps/Emits', () => {
const hoistCode = `const defaultValue = 'default value'`
const { content, bindings } = compile(`
<script setup>
${hoistCode}
defineProps({
foo: {
default: defaultValue
}
})
</script>
`)
// should hoist to first line
expect(content.startsWith(hoistCode)).toBe(true)
expect(bindings).toStrictEqual({
foo: BindingTypes.PROPS,
defaultValue: BindingTypes.LITERAL_CONST
})
assertCode(content)
})
test('should not hoist a variable', () => {
const code = `
let KEY1 = 'default value'
var KEY2 = 123
`.trim()
const { content, bindings } = compile(`
<script setup>
${code}
</script>
`)
expect(bindings).toStrictEqual({
KEY1: BindingTypes.SETUP_LET,
KEY2: BindingTypes.SETUP_LET
})
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
assertCode(content)
})
test('should not hoist a constant initialized to a reference value', () => {
const code = `
const KEY1 = Boolean
const KEY2 = [Boolean]
const KEY3 = [getCurrentInstance()]
let i = 0;
const KEY4 = (i++, 'foo')
enum KEY5 {
FOO = 1,
BAR = getCurrentInstance(),
}
const KEY6 = \`template\${i}\`
`.trim()
const { content, bindings } = compile(`
<script setup lang="ts">
${code}
</script>
`)
expect(bindings).toStrictEqual({
KEY1: BindingTypes.SETUP_MAYBE_REF,
KEY2: BindingTypes.SETUP_CONST,
KEY3: BindingTypes.SETUP_CONST,
KEY4: BindingTypes.SETUP_CONST,
KEY5: BindingTypes.SETUP_CONST,
KEY6: BindingTypes.SETUP_CONST,
i: BindingTypes.SETUP_LET
})
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
assertCode(content)
})
test('should not hoist a object or array', () => {
const code = `
const obj = { foo: 'bar' }
const arr = [1, 2, 3]
`.trim()
const { content, bindings } = compile(`
<script setup>
${code}
</script>
`)
expect(bindings).toStrictEqual({
arr: BindingTypes.SETUP_CONST,
obj: BindingTypes.SETUP_CONST
})
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
assertCode(content)
})
test('should not hoist a function or class', () => {
const code = `
const fn = () => {}
function fn2() {}
class Foo {}
`.trim()
const { content, bindings } = compile(`
<script setup>
${code}
</script>
`)
expect(bindings).toStrictEqual({
Foo: BindingTypes.SETUP_CONST,
fn: BindingTypes.SETUP_CONST,
fn2: BindingTypes.SETUP_CONST
})
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
assertCode(content)
})
test('should enable when only script setup', () => {
const { content, bindings } = compile(`
<script>
const foo = 'bar'
</script>
<script setup>
const foo = 'bar'
</script>
`)
expect(bindings).toStrictEqual({
foo: BindingTypes.LITERAL_CONST
})
assertCode(content)
})
})