2019-09-25 03:49:02 +08:00
|
|
|
import {
|
2019-10-02 03:43:59 +08:00
|
|
|
locStub,
|
2019-09-25 03:49:02 +08:00
|
|
|
generate,
|
|
|
|
NodeTypes,
|
|
|
|
RootNode,
|
2019-09-27 23:42:02 +08:00
|
|
|
createSimpleExpression,
|
2019-09-25 03:49:02 +08:00
|
|
|
createObjectExpression,
|
|
|
|
createObjectProperty,
|
2019-09-25 04:35:01 +08:00
|
|
|
createArrayExpression,
|
2019-09-27 23:42:02 +08:00
|
|
|
createCompoundExpression,
|
2019-10-02 00:25:13 +08:00
|
|
|
createInterpolation,
|
2019-10-02 03:43:59 +08:00
|
|
|
createCallExpression,
|
2019-10-06 10:47:20 +08:00
|
|
|
createConditionalExpression,
|
2019-10-19 09:51:34 +08:00
|
|
|
ForCodegenNode,
|
2020-02-03 10:35:28 +08:00
|
|
|
createCacheExpression,
|
|
|
|
createTemplateLiteral,
|
|
|
|
createBlockStatement,
|
2020-02-05 11:49:47 +08:00
|
|
|
createIfStatement,
|
2020-02-12 07:40:21 +08:00
|
|
|
createAssignmentExpression,
|
|
|
|
IfConditionalExpression,
|
|
|
|
createVNodeCall,
|
|
|
|
VNodeCall,
|
|
|
|
DirectiveArguments
|
2019-09-25 03:49:02 +08:00
|
|
|
} from '../src'
|
2019-10-06 05:18:25 +08:00
|
|
|
import {
|
|
|
|
CREATE_VNODE,
|
2020-01-27 06:35:21 +08:00
|
|
|
TO_DISPLAY_STRING,
|
2019-10-06 05:18:25 +08:00
|
|
|
RESOLVE_DIRECTIVE,
|
|
|
|
helperNameMap,
|
2019-10-25 05:55:00 +08:00
|
|
|
RESOLVE_COMPONENT,
|
2020-02-12 07:40:21 +08:00
|
|
|
CREATE_COMMENT,
|
|
|
|
FRAGMENT,
|
|
|
|
RENDER_LIST
|
2019-10-06 05:18:25 +08:00
|
|
|
} from '../src/runtimeHelpers'
|
2020-06-18 04:13:14 +08:00
|
|
|
import { createElementWithCodegen, genFlagText } from './testUtils'
|
2019-10-06 11:20:02 +08:00
|
|
|
import { PatchFlags } from '@vue/shared'
|
2019-09-25 03:49:02 +08:00
|
|
|
|
|
|
|
function createRoot(options: Partial<RootNode> = {}): RootNode {
|
|
|
|
return {
|
|
|
|
type: NodeTypes.ROOT,
|
|
|
|
children: [],
|
2019-10-06 05:18:25 +08:00
|
|
|
helpers: [],
|
|
|
|
components: [],
|
|
|
|
directives: [],
|
2019-12-02 01:02:53 +08:00
|
|
|
imports: [],
|
2019-09-26 02:13:33 +08:00
|
|
|
hoists: [],
|
2019-10-19 09:51:34 +08:00
|
|
|
cached: 0,
|
2020-02-05 11:49:47 +08:00
|
|
|
temps: 0,
|
2019-10-08 22:50:00 +08:00
|
|
|
codegenNode: createSimpleExpression(`null`, false),
|
2019-10-02 03:43:59 +08:00
|
|
|
loc: locStub,
|
2019-09-25 03:49:02 +08:00
|
|
|
...options
|
|
|
|
}
|
|
|
|
}
|
2019-09-20 11:05:51 +08:00
|
|
|
|
|
|
|
describe('compiler: codegen', () => {
|
2019-09-25 03:49:02 +08:00
|
|
|
test('module mode preamble', () => {
|
|
|
|
const root = createRoot({
|
2019-10-06 05:18:25 +08:00
|
|
|
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
const { code } = generate(root, { mode: 'module' })
|
2020-02-08 08:04:55 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`import { ${helperNameMap[CREATE_VNODE]} as _${
|
|
|
|
helperNameMap[CREATE_VNODE]
|
|
|
|
}, ${helperNameMap[RESOLVE_DIRECTIVE]} as _${
|
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
} } from "vue"`
|
|
|
|
)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('module mode preamble w/ optimizeBindings: true', () => {
|
|
|
|
const root = createRoot({
|
|
|
|
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
|
|
|
})
|
|
|
|
const { code } = generate(root, { mode: 'module', optimizeBindings: true })
|
2019-10-06 05:18:25 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`import { ${helperNameMap[CREATE_VNODE]}, ${
|
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
} } from "vue"`
|
|
|
|
)
|
2020-02-08 08:04:55 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`const _${helperNameMap[CREATE_VNODE]} = ${
|
|
|
|
helperNameMap[CREATE_VNODE]
|
|
|
|
}, _${helperNameMap[RESOLVE_DIRECTIVE]} = ${
|
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
}`
|
|
|
|
)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('function mode preamble', () => {
|
|
|
|
const root = createRoot({
|
2019-10-06 05:18:25 +08:00
|
|
|
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
const { code } = generate(root, { mode: 'function' })
|
2019-09-26 03:09:58 +08:00
|
|
|
expect(code).toMatch(`const _Vue = Vue`)
|
2019-09-26 07:17:45 +08:00
|
|
|
expect(code).toMatch(
|
2019-10-06 05:18:25 +08:00
|
|
|
`const { ${helperNameMap[CREATE_VNODE]}: _${
|
|
|
|
helperNameMap[CREATE_VNODE]
|
|
|
|
}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${
|
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
} } = _Vue`
|
2019-09-26 07:17:45 +08:00
|
|
|
)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('function mode preamble w/ prefixIdentifiers: true', () => {
|
|
|
|
const root = createRoot({
|
2019-10-06 05:18:25 +08:00
|
|
|
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
2019-09-26 07:17:45 +08:00
|
|
|
})
|
|
|
|
const { code } = generate(root, {
|
|
|
|
mode: 'function',
|
|
|
|
prefixIdentifiers: true
|
|
|
|
})
|
|
|
|
expect(code).not.toMatch(`const _Vue = Vue`)
|
2019-10-06 05:18:25 +08:00
|
|
|
expect(code).toMatch(
|
2020-02-08 08:04:55 +08:00
|
|
|
`const { ${helperNameMap[CREATE_VNODE]}: _${
|
|
|
|
helperNameMap[CREATE_VNODE]
|
|
|
|
}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${
|
2019-10-06 05:18:25 +08:00
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
} } = Vue`
|
|
|
|
)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2020-02-10 22:33:04 +08:00
|
|
|
test('assets + temps', () => {
|
2019-09-25 03:49:02 +08:00
|
|
|
const root = createRoot({
|
2019-10-11 01:55:26 +08:00
|
|
|
components: [`Foo`, `bar-baz`, `barbaz`],
|
2020-02-10 22:33:04 +08:00
|
|
|
directives: [`my_dir_0`, `my_dir_1`],
|
|
|
|
temps: 3
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
const { code } = generate(root, { mode: 'function' })
|
2019-10-06 05:18:25 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`
|
|
|
|
)
|
|
|
|
expect(code).toMatch(
|
2019-10-11 01:55:26 +08:00
|
|
|
`const _component_bar_baz = _${
|
2019-10-06 05:18:25 +08:00
|
|
|
helperNameMap[RESOLVE_COMPONENT]
|
|
|
|
}("bar-baz")\n`
|
|
|
|
)
|
2019-10-11 01:55:26 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`const _component_barbaz = _${
|
|
|
|
helperNameMap[RESOLVE_COMPONENT]
|
|
|
|
}("barbaz")\n`
|
|
|
|
)
|
2019-10-06 05:18:25 +08:00
|
|
|
expect(code).toMatch(
|
2020-02-10 22:33:04 +08:00
|
|
|
`const _directive_my_dir_0 = _${
|
2019-10-06 05:18:25 +08:00
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
2020-02-10 22:33:04 +08:00
|
|
|
}("my_dir_0")\n`
|
2019-10-06 05:18:25 +08:00
|
|
|
)
|
2020-02-10 22:33:04 +08:00
|
|
|
expect(code).toMatch(
|
|
|
|
`const _directive_my_dir_1 = _${
|
|
|
|
helperNameMap[RESOLVE_DIRECTIVE]
|
|
|
|
}("my_dir_1")\n`
|
|
|
|
)
|
|
|
|
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-09-26 02:13:33 +08:00
|
|
|
test('hoists', () => {
|
|
|
|
const root = createRoot({
|
|
|
|
hoists: [
|
2019-10-02 03:43:59 +08:00
|
|
|
createSimpleExpression(`hello`, false, locStub),
|
2019-09-26 02:13:33 +08:00
|
|
|
createObjectExpression(
|
|
|
|
[
|
|
|
|
createObjectProperty(
|
2019-10-02 03:43:59 +08:00
|
|
|
createSimpleExpression(`id`, true, locStub),
|
|
|
|
createSimpleExpression(`foo`, true, locStub)
|
2019-09-26 02:13:33 +08:00
|
|
|
)
|
|
|
|
],
|
2019-10-02 03:43:59 +08:00
|
|
|
locStub
|
2019-09-26 02:13:33 +08:00
|
|
|
)
|
|
|
|
]
|
|
|
|
})
|
|
|
|
const { code } = generate(root)
|
|
|
|
expect(code).toMatch(`const _hoisted_1 = hello`)
|
|
|
|
expect(code).toMatch(`const _hoisted_2 = { id: "foo" }`)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2020-02-05 11:49:47 +08:00
|
|
|
test('temps', () => {
|
|
|
|
const root = createRoot({
|
|
|
|
temps: 3
|
|
|
|
})
|
|
|
|
const { code } = generate(root)
|
|
|
|
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-09-25 03:49:02 +08:00
|
|
|
test('static text', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.TEXT,
|
|
|
|
content: 'hello',
|
|
|
|
loc: locStub
|
|
|
|
}
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatch(`return "hello"`)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('interpolation', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: createInterpolation(`hello`, locStub)
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
2020-01-27 06:35:21 +08:00
|
|
|
expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('comment', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.COMMENT,
|
|
|
|
content: 'foo',
|
|
|
|
loc: locStub
|
|
|
|
}
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
2019-10-25 05:55:00 +08:00
|
|
|
expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}("foo")`)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-10-03 01:11:07 +08:00
|
|
|
test('compound expression', () => {
|
2019-09-25 03:49:02 +08:00
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: createCompoundExpression([
|
|
|
|
`_ctx.`,
|
|
|
|
createSimpleExpression(`foo`, false, locStub),
|
|
|
|
` + `,
|
2019-09-25 03:49:02 +08:00
|
|
|
{
|
2019-10-03 01:11:07 +08:00
|
|
|
type: NodeTypes.INTERPOLATION,
|
|
|
|
loc: locStub,
|
|
|
|
content: createSimpleExpression(`bar`, false, locStub)
|
2020-02-06 03:30:34 +08:00
|
|
|
},
|
|
|
|
// nested compound
|
|
|
|
createCompoundExpression([` + `, `nested`])
|
2019-10-03 01:11:07 +08:00
|
|
|
])
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
2020-01-27 06:35:21 +08:00
|
|
|
expect(code).toMatch(
|
2020-02-06 03:30:34 +08:00
|
|
|
`return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`
|
2020-01-27 06:35:21 +08:00
|
|
|
)
|
2019-09-26 07:17:45 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-10-03 01:11:07 +08:00
|
|
|
test('ifNode', () => {
|
2019-09-25 04:35:01 +08:00
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.IF,
|
|
|
|
loc: locStub,
|
|
|
|
branches: [],
|
2020-02-12 07:40:21 +08:00
|
|
|
codegenNode: createConditionalExpression(
|
2019-10-03 01:11:07 +08:00
|
|
|
createSimpleExpression('foo', false),
|
2020-02-12 07:40:21 +08:00
|
|
|
createSimpleExpression('bar', false),
|
|
|
|
createSimpleExpression('baz', false)
|
|
|
|
) as IfConditionalExpression
|
2019-10-03 01:11:07 +08:00
|
|
|
}
|
2019-09-25 04:35:01 +08:00
|
|
|
})
|
|
|
|
)
|
2020-02-12 07:40:21 +08:00
|
|
|
expect(code).toMatch(/return foo\s+\? bar\s+: baz/)
|
2019-09-25 04:35:01 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-10-03 01:11:07 +08:00
|
|
|
test('forNode', () => {
|
2019-09-25 03:49:02 +08:00
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.FOR,
|
|
|
|
loc: locStub,
|
|
|
|
source: createSimpleExpression('foo', false),
|
|
|
|
valueAlias: undefined,
|
|
|
|
keyAlias: undefined,
|
|
|
|
objectIndexAlias: undefined,
|
|
|
|
children: [],
|
2020-02-04 11:21:45 +08:00
|
|
|
parseResult: {} as any,
|
2020-02-12 07:40:21 +08:00
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.VNODE_CALL,
|
|
|
|
tag: FRAGMENT,
|
|
|
|
isBlock: true,
|
2020-06-18 04:13:14 +08:00
|
|
|
disableTracking: true,
|
2020-02-12 07:40:21 +08:00
|
|
|
props: undefined,
|
|
|
|
children: createCallExpression(RENDER_LIST),
|
|
|
|
patchFlag: '1',
|
|
|
|
dynamicProps: undefined,
|
|
|
|
directives: undefined,
|
|
|
|
loc: locStub
|
|
|
|
} as ForCodegenNode
|
2019-10-03 01:11:07 +08:00
|
|
|
}
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
2020-02-12 07:40:21 +08:00
|
|
|
expect(code).toMatch(`openBlock(true)`)
|
2019-09-25 04:35:01 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2020-06-18 04:13:14 +08:00
|
|
|
test('forNode with constant expression', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.FOR,
|
|
|
|
loc: locStub,
|
|
|
|
source: createSimpleExpression('1 + 2', false, locStub, true),
|
|
|
|
valueAlias: undefined,
|
|
|
|
keyAlias: undefined,
|
|
|
|
objectIndexAlias: undefined,
|
|
|
|
children: [],
|
|
|
|
parseResult: {} as any,
|
|
|
|
codegenNode: {
|
|
|
|
type: NodeTypes.VNODE_CALL,
|
|
|
|
tag: FRAGMENT,
|
|
|
|
isBlock: true,
|
|
|
|
disableTracking: false,
|
|
|
|
props: undefined,
|
|
|
|
children: createCallExpression(RENDER_LIST),
|
|
|
|
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
|
|
|
dynamicProps: undefined,
|
|
|
|
directives: undefined,
|
|
|
|
loc: locStub
|
|
|
|
} as ForCodegenNode
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatch(`openBlock()`)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-10-06 10:47:20 +08:00
|
|
|
test('Element (callExpression + objectExpression + TemplateChildNode[])', () => {
|
2019-09-25 04:35:01 +08:00
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2020-02-12 07:40:21 +08:00
|
|
|
codegenNode: createElementWithCodegen(
|
2019-10-03 01:11:07 +08:00
|
|
|
// string
|
|
|
|
`"div"`,
|
|
|
|
// ObjectExpression
|
|
|
|
createObjectExpression(
|
2019-09-25 04:35:01 +08:00
|
|
|
[
|
2019-10-03 01:11:07 +08:00
|
|
|
createObjectProperty(
|
|
|
|
createSimpleExpression(`id`, true, locStub),
|
|
|
|
createSimpleExpression(`foo`, true, locStub)
|
|
|
|
),
|
|
|
|
createObjectProperty(
|
|
|
|
createSimpleExpression(`prop`, false, locStub),
|
|
|
|
createSimpleExpression(`bar`, false, locStub)
|
|
|
|
),
|
|
|
|
// compound expression as computed key
|
|
|
|
createObjectProperty(
|
2019-09-25 04:35:01 +08:00
|
|
|
{
|
2019-10-03 01:11:07 +08:00
|
|
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
2019-10-02 03:43:59 +08:00
|
|
|
loc: locStub,
|
2019-10-03 01:11:07 +08:00
|
|
|
children: [
|
|
|
|
`foo + `,
|
|
|
|
createSimpleExpression(`bar`, false, locStub)
|
|
|
|
]
|
|
|
|
},
|
|
|
|
createSimpleExpression(`bar`, false, locStub)
|
|
|
|
)
|
|
|
|
],
|
|
|
|
locStub
|
|
|
|
),
|
|
|
|
// ChildNode[]
|
|
|
|
[
|
2020-02-12 07:40:21 +08:00
|
|
|
createElementWithCodegen(
|
2019-10-03 01:11:07 +08:00
|
|
|
`"p"`,
|
|
|
|
createObjectExpression(
|
|
|
|
[
|
|
|
|
createObjectProperty(
|
|
|
|
// should quote the key!
|
|
|
|
createSimpleExpression(`some-key`, true, locStub),
|
|
|
|
createSimpleExpression(`foo`, true, locStub)
|
|
|
|
)
|
|
|
|
],
|
|
|
|
locStub
|
|
|
|
)
|
2020-02-12 07:40:21 +08:00
|
|
|
)
|
2019-10-03 01:11:07 +08:00
|
|
|
],
|
2019-10-06 10:47:20 +08:00
|
|
|
// flag
|
|
|
|
PatchFlags.FULL_PROPS + ''
|
2020-02-12 07:40:21 +08:00
|
|
|
)
|
2019-09-25 03:49:02 +08:00
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatch(`
|
2019-10-06 05:18:25 +08:00
|
|
|
return _${helperNameMap[CREATE_VNODE]}("div", {
|
2019-09-25 03:49:02 +08:00
|
|
|
id: "foo",
|
2019-09-25 04:35:01 +08:00
|
|
|
[prop]: bar,
|
|
|
|
[foo + bar]: bar
|
2019-09-28 12:19:24 +08:00
|
|
|
}, [
|
2019-10-06 05:18:25 +08:00
|
|
|
_${helperNameMap[CREATE_VNODE]}("p", { "some-key": "foo" })
|
2019-10-06 10:47:20 +08:00
|
|
|
], ${PatchFlags.FULL_PROPS})`)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test('ArrayExpression', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createArrayExpression([
|
|
|
|
createSimpleExpression(`foo`, false),
|
|
|
|
createCallExpression(`bar`, [`baz`])
|
|
|
|
])
|
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatch(`return [
|
2019-09-25 03:49:02 +08:00
|
|
|
foo,
|
2019-10-06 10:47:20 +08:00
|
|
|
bar(baz)
|
|
|
|
]`)
|
2019-09-25 03:49:02 +08:00
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
2019-10-02 00:25:13 +08:00
|
|
|
|
2019-10-02 03:43:59 +08:00
|
|
|
test('ConditionalExpression', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-03 01:11:07 +08:00
|
|
|
codegenNode: createConditionalExpression(
|
|
|
|
createSimpleExpression(`ok`, false),
|
|
|
|
createCallExpression(`foo`),
|
|
|
|
createConditionalExpression(
|
|
|
|
createSimpleExpression(`orNot`, false),
|
|
|
|
createCallExpression(`bar`),
|
|
|
|
createCallExpression(`baz`)
|
|
|
|
)
|
|
|
|
)
|
2019-10-02 03:43:59 +08:00
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatch(
|
2019-10-03 01:11:07 +08:00
|
|
|
`return ok
|
2019-10-02 03:43:59 +08:00
|
|
|
? foo()
|
|
|
|
: orNot
|
|
|
|
? bar()
|
2019-10-03 01:11:07 +08:00
|
|
|
: baz()`
|
2019-10-02 03:43:59 +08:00
|
|
|
)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
2019-10-19 09:51:34 +08:00
|
|
|
|
|
|
|
test('CacheExpression', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
2019-10-21 05:00:11 +08:00
|
|
|
cached: 1,
|
2019-10-19 09:51:34 +08:00
|
|
|
codegenNode: createCacheExpression(
|
|
|
|
1,
|
|
|
|
createSimpleExpression(`foo`, false)
|
|
|
|
)
|
2019-10-21 05:00:11 +08:00
|
|
|
}),
|
|
|
|
{
|
|
|
|
mode: 'module',
|
|
|
|
prefixIdentifiers: true
|
|
|
|
}
|
2019-10-19 09:51:34 +08:00
|
|
|
)
|
2019-10-21 05:00:11 +08:00
|
|
|
expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)
|
|
|
|
expect(code).toMatchSnapshot()
|
2019-10-19 09:51:34 +08:00
|
|
|
})
|
2019-10-24 05:57:40 +08:00
|
|
|
|
|
|
|
test('CacheExpression w/ isVNode: true', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
cached: 1,
|
|
|
|
codegenNode: createCacheExpression(
|
|
|
|
1,
|
|
|
|
createSimpleExpression(`foo`, false),
|
|
|
|
true
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
mode: 'module',
|
|
|
|
prefixIdentifiers: true
|
|
|
|
}
|
|
|
|
)
|
|
|
|
expect(code).toMatch(
|
|
|
|
`
|
|
|
|
_cache[1] || (
|
2020-02-08 08:04:55 +08:00
|
|
|
_setBlockTracking(-1),
|
2019-10-24 05:57:40 +08:00
|
|
|
_cache[1] = foo,
|
2020-02-08 08:04:55 +08:00
|
|
|
_setBlockTracking(1),
|
2019-10-24 05:57:40 +08:00
|
|
|
_cache[1]
|
|
|
|
)
|
|
|
|
`.trim()
|
|
|
|
)
|
|
|
|
expect(code).toMatchSnapshot()
|
|
|
|
})
|
2020-02-03 10:35:28 +08:00
|
|
|
|
|
|
|
test('TemplateLiteral', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createCallExpression(`_push`, [
|
|
|
|
createTemplateLiteral([
|
|
|
|
`foo`,
|
|
|
|
createCallExpression(`_renderAttr`, ['id', 'foo']),
|
|
|
|
`bar`
|
|
|
|
])
|
|
|
|
])
|
|
|
|
}),
|
|
|
|
{ ssr: true, mode: 'module' }
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
|
|
|
export function ssrRender(_ctx, _push, _parent) {
|
|
|
|
_push(\`foo\${_renderAttr(id, foo)}bar\`)
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('IfStatement', () => {
|
|
|
|
test('if', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createBlockStatement([
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('foo', false),
|
|
|
|
createBlockStatement([createCallExpression(`ok`)])
|
|
|
|
)
|
|
|
|
])
|
|
|
|
}),
|
|
|
|
{ ssr: true, mode: 'module' }
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
|
|
|
export function ssrRender(_ctx, _push, _parent) {
|
|
|
|
if (foo) {
|
|
|
|
ok()
|
|
|
|
}
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('if/else', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createBlockStatement([
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('foo', false),
|
|
|
|
createBlockStatement([createCallExpression(`foo`)]),
|
|
|
|
createBlockStatement([createCallExpression('bar')])
|
|
|
|
)
|
|
|
|
])
|
|
|
|
}),
|
|
|
|
{ ssr: true, mode: 'module' }
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
|
|
|
export function ssrRender(_ctx, _push, _parent) {
|
|
|
|
if (foo) {
|
|
|
|
foo()
|
|
|
|
} else {
|
|
|
|
bar()
|
|
|
|
}
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('if/else-if', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createBlockStatement([
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('foo', false),
|
|
|
|
createBlockStatement([createCallExpression(`foo`)]),
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('bar', false),
|
|
|
|
createBlockStatement([createCallExpression(`bar`)])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
])
|
|
|
|
}),
|
|
|
|
{ ssr: true, mode: 'module' }
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
|
|
|
export function ssrRender(_ctx, _push, _parent) {
|
|
|
|
if (foo) {
|
|
|
|
foo()
|
|
|
|
} else if (bar) {
|
|
|
|
bar()
|
|
|
|
}
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('if/else-if/else', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createBlockStatement([
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('foo', false),
|
|
|
|
createBlockStatement([createCallExpression(`foo`)]),
|
|
|
|
createIfStatement(
|
|
|
|
createSimpleExpression('bar', false),
|
|
|
|
createBlockStatement([createCallExpression(`bar`)]),
|
|
|
|
createBlockStatement([createCallExpression('baz')])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
])
|
|
|
|
}),
|
|
|
|
{ ssr: true, mode: 'module' }
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
|
|
|
export function ssrRender(_ctx, _push, _parent) {
|
|
|
|
if (foo) {
|
|
|
|
foo()
|
|
|
|
} else if (bar) {
|
|
|
|
bar()
|
|
|
|
} else {
|
|
|
|
baz()
|
|
|
|
}
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
})
|
2020-02-05 11:49:47 +08:00
|
|
|
|
|
|
|
test('AssignmentExpression', () => {
|
|
|
|
const { code } = generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: createAssignmentExpression(
|
|
|
|
createSimpleExpression(`foo`, false),
|
|
|
|
createSimpleExpression(`bar`, false)
|
|
|
|
)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
expect(code).toMatchInlineSnapshot(`
|
|
|
|
"
|
2020-02-11 06:29:12 +08:00
|
|
|
return function render(_ctx, _cache) {
|
2020-02-14 07:28:40 +08:00
|
|
|
with (_ctx) {
|
2020-02-05 11:56:53 +08:00
|
|
|
return foo = bar
|
2020-02-05 11:49:47 +08:00
|
|
|
}
|
|
|
|
}"
|
|
|
|
`)
|
|
|
|
})
|
2020-02-12 07:40:21 +08:00
|
|
|
|
|
|
|
describe('VNodeCall', () => {
|
|
|
|
function genCode(node: VNodeCall) {
|
|
|
|
return generate(
|
|
|
|
createRoot({
|
|
|
|
codegenNode: node
|
|
|
|
})
|
2020-02-14 07:28:40 +08:00
|
|
|
).code.match(/with \(_ctx\) \{\s+([^]+)\s+\}\s+\}$/)![1]
|
2020-02-12 07:40:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const mockProps = createObjectExpression([
|
|
|
|
createObjectProperty(`foo`, createSimpleExpression(`bar`, true))
|
|
|
|
])
|
|
|
|
const mockChildren = createCompoundExpression(['children'])
|
|
|
|
const mockDirs = createArrayExpression([
|
|
|
|
createArrayExpression([`foo`, createSimpleExpression(`bar`, false)])
|
|
|
|
]) as DirectiveArguments
|
|
|
|
|
|
|
|
test('tag only', () => {
|
|
|
|
expect(genCode(createVNodeCall(null, `"div"`))).toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(\\"div\\")
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
expect(genCode(createVNodeCall(null, FRAGMENT))).toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(_Fragment)
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('with props', () => {
|
|
|
|
expect(genCode(createVNodeCall(null, `"div"`, mockProps)))
|
|
|
|
.toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(\\"div\\", { foo: \\"bar\\" })
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('with children, no props', () => {
|
|
|
|
expect(genCode(createVNodeCall(null, `"div"`, undefined, mockChildren)))
|
|
|
|
.toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(\\"div\\", null, children)
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('with children + props', () => {
|
|
|
|
expect(genCode(createVNodeCall(null, `"div"`, mockProps, mockChildren)))
|
|
|
|
.toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(\\"div\\", { foo: \\"bar\\" }, children)
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('with patchFlag and no children/props', () => {
|
|
|
|
expect(genCode(createVNodeCall(null, `"div"`, undefined, undefined, '1')))
|
|
|
|
.toMatchInlineSnapshot(`
|
|
|
|
"return _createVNode(\\"div\\", null, null, 1)
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('as block', () => {
|
|
|
|
expect(
|
|
|
|
genCode(
|
|
|
|
createVNodeCall(
|
|
|
|
null,
|
|
|
|
`"div"`,
|
|
|
|
mockProps,
|
|
|
|
mockChildren,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
true
|
|
|
|
)
|
|
|
|
)
|
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
"return (_openBlock(), _createBlock(\\"div\\", { foo: \\"bar\\" }, children))
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('as for block', () => {
|
|
|
|
expect(
|
|
|
|
genCode(
|
|
|
|
createVNodeCall(
|
|
|
|
null,
|
|
|
|
`"div"`,
|
|
|
|
mockProps,
|
|
|
|
mockChildren,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
true,
|
|
|
|
true
|
|
|
|
)
|
|
|
|
)
|
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
"return (_openBlock(true), _createBlock(\\"div\\", { foo: \\"bar\\" }, children))
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('with directives', () => {
|
|
|
|
expect(
|
|
|
|
genCode(
|
|
|
|
createVNodeCall(
|
|
|
|
null,
|
|
|
|
`"div"`,
|
|
|
|
mockProps,
|
|
|
|
mockChildren,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
mockDirs
|
|
|
|
)
|
|
|
|
)
|
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
"return _withDirectives(_createVNode(\\"div\\", { foo: \\"bar\\" }, children), [
|
|
|
|
[foo, bar]
|
|
|
|
])
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
test('block + directives', () => {
|
|
|
|
expect(
|
|
|
|
genCode(
|
|
|
|
createVNodeCall(
|
|
|
|
null,
|
|
|
|
`"div"`,
|
|
|
|
mockProps,
|
|
|
|
mockChildren,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
mockDirs,
|
|
|
|
true
|
|
|
|
)
|
|
|
|
)
|
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
"return _withDirectives((_openBlock(), _createBlock(\\"div\\", { foo: \\"bar\\" }, children)), [
|
|
|
|
[foo, bar]
|
|
|
|
])
|
|
|
|
"
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
})
|
2019-09-20 11:05:51 +08:00
|
|
|
})
|