feat(compiler): generate patchFlags for runtime

This commit is contained in:
Evan You
2019-09-30 21:17:12 -04:00
parent da0d785d84
commit d67418002f
19 changed files with 267 additions and 70 deletions

View File

@@ -11,14 +11,14 @@ return function render() {
}, [
_toString(world.burn()),
ok
? _createVNode(\\"div\\", 0, \\"yes\\")
? _createVNode(\\"div\\", null, \\"yes\\")
: \\"no\\",
_renderList(list, (value, index) => {
return _createVNode(\\"div\\", 0, [
_createVNode(\\"span\\", 0, _toString(value + index))
return _createVNode(\\"div\\", null, [
_createVNode(\\"span\\", null, _toString(value + index))
])
})
])
], 2)
}
}"
`;
@@ -34,14 +34,14 @@ return function render() {
}, [
toString(_ctx.world.burn()),
(_ctx.ok)
? createVNode(\\"div\\", 0, \\"yes\\")
? createVNode(\\"div\\", null, \\"yes\\")
: \\"no\\",
renderList(_ctx.list, (value, index) => {
return createVNode(\\"div\\", 0, [
createVNode(\\"span\\", 0, toString(value + index))
return createVNode(\\"div\\", null, [
createVNode(\\"span\\", null, toString(value + index))
])
})
])
], 2)
}"
`;
@@ -56,13 +56,13 @@ export default function render() {
}, [
_toString(_ctx.world.burn()),
(_ctx.ok)
? createVNode(\\"div\\", 0, \\"yes\\")
? createVNode(\\"div\\", null, \\"yes\\")
: \\"no\\",
_renderList(_ctx.list, (value, index) => {
return createVNode(\\"div\\", 0, [
createVNode(\\"span\\", 0, _toString(value + index))
return createVNode(\\"div\\", null, [
createVNode(\\"span\\", null, _toString(value + index))
])
})
])
], 2)
}"
`;

View File

@@ -7,7 +7,7 @@ return function render() {
const _ctx = this
const _component_Comp = resolveComponent(\\"Comp\\")
return createVNode(_component_Comp, 0, {
return createVNode(_component_Comp, null, {
[_ctx.one]: ({ foo }) => [
toString(foo),
toString(_ctx.bar)
@@ -16,7 +16,7 @@ return function render() {
toString(_ctx.foo),
toString(bar)
]
})
}, 256)
}"
`;
@@ -27,7 +27,7 @@ return function render() {
const _ctx = this
const _component_Comp = resolveComponent(\\"Comp\\")
return createVNode(_component_Comp, 0, {
return createVNode(_component_Comp, null, {
default: ({ foo }) => [
toString(foo),
toString(_ctx.bar)
@@ -43,7 +43,7 @@ return function render() {
const _ctx = this
const _component_Comp = resolveComponent(\\"Comp\\")
return createVNode(_component_Comp, 0, {
return createVNode(_component_Comp, null, {
default: () => [
createVNode(\\"div\\")
]
@@ -58,7 +58,7 @@ return function render() {
const _ctx = this
const _component_Comp = resolveComponent(\\"Comp\\")
return createVNode(_component_Comp, 0, {
return createVNode(_component_Comp, null, {
one: ({ foo }) => [
toString(foo),
toString(_ctx.bar)
@@ -79,9 +79,9 @@ return function render() {
const _component_Comp = resolveComponent(\\"Comp\\")
const _component_Inner = resolveComponent(\\"Inner\\")
return createVNode(_component_Comp, 0, {
return createVNode(_component_Comp, null, {
default: ({ foo }) => [
createVNode(_component_Inner, 0, {
createVNode(_component_Inner, null, {
default: ({ bar }) => [
toString(foo),
toString(bar),

View File

@@ -24,6 +24,7 @@ import { transformElement } from '../../src/transforms/transformElement'
import { transformOn } from '../../src/transforms/vOn'
import { transformStyle } from '../../src/transforms/transformStyle'
import { transformBind } from '../../src/transforms/vBind'
import { PatchFlags } from '@vue/shared'
function parseWithElementTransform(
template: string,
@@ -127,7 +128,7 @@ describe('compiler: element transform', () => {
expect(node.callee).toBe(`_${CREATE_VNODE}`)
expect(node.arguments).toMatchObject([
`"div"`,
`0`,
`null`,
[
{
type: NodeTypes.ELEMENT,
@@ -351,7 +352,9 @@ describe('compiler: element transform', () => {
value: _dir!.exp
}
]
}
},
`null`,
String(PatchFlags.NEED_PATCH) // should generate appropriate flag
]
},
{
@@ -546,5 +549,121 @@ describe('compiler: element transform', () => {
})
})
test.todo('slot outlets')
test(`props merging: class`, () => {
const { node } = parseWithElementTransform(
`<div class="foo" :class="{ bar: isBar }" />`,
{
directiveTransforms: {
bind: transformBind
}
}
)
expect(node.arguments[1]).toMatchObject({
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `class`,
isStatic: true
},
value: {
type: NodeTypes.JS_ARRAY_EXPRESSION,
elements: [
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: `foo`,
isStatic: true
},
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: `{ bar: isBar }`,
isStatic: false
}
]
}
}
]
})
})
describe('patchFlag analysis', () => {
function parseWithBind(template: string) {
return parseWithElementTransform(template, {
directiveTransforms: {
bind: transformBind
}
})
}
test('CLASS', () => {
const { node } = parseWithBind(`<div :class="foo" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.CLASS))
})
test('STYLE', () => {
const { node } = parseWithBind(`<div :style="foo" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.STYLE))
})
test('PROPS', () => {
const { node } = parseWithBind(`<div id="foo" :foo="bar" :baz="qux" />`)
expect(node.arguments.length).toBe(5)
expect(node.arguments[3]).toBe(String(PatchFlags.PROPS))
expect(node.arguments[4]).toBe(`["foo", "baz"]`)
})
test('CLASS + STYLE + PROPS', () => {
const { node } = parseWithBind(
`<div id="foo" :class="cls" :style="styl" :foo="bar" :baz="qux"/>`
)
expect(node.arguments.length).toBe(5)
expect(node.arguments[3]).toBe(
String(PatchFlags.PROPS | PatchFlags.CLASS | PatchFlags.STYLE)
)
expect(node.arguments[4]).toBe(`["foo", "baz"]`)
})
test('FULL_PROPS (v-bind)', () => {
const { node } = parseWithBind(`<div v-bind="foo" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
})
test('FULL_PROPS (dynamic key)', () => {
const { node } = parseWithBind(`<div :[foo]="bar" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
})
test('FULL_PROPS (w/ others)', () => {
const { node } = parseWithBind(
`<div id="foo" v-bind="bar" :class="cls" />`
)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.FULL_PROPS))
})
test('NEED_PATCH (static ref)', () => {
const { node } = parseWithBind(`<div ref="foo" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
})
test('NEED_PATCH (dynamic ref)', () => {
const { node } = parseWithBind(`<div :ref="foo" />`)
expect(node.arguments.length).toBe(4)
expect(node.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
})
test('NEED_PATCH (custom directives)', () => {
const { node } = parseWithBind(`<div v-foo />`)
const vnodeCall = node.arguments[0] as CallExpression
expect(vnodeCall.arguments.length).toBe(4)
expect(vnodeCall.arguments[3]).toBe(String(PatchFlags.NEED_PATCH))
})
})
})

View File

@@ -260,7 +260,7 @@ describe('compiler: transform component slots', () => {
type: NodeTypes.JS_CALL_EXPRESSION,
arguments: [
`_component_Inner`,
`0`,
`null`,
createSlotMatcher({
default: {
type: NodeTypes.JS_SLOT_FUNCTION,