refactor(compiler): use symbols for runtime helpers
This commit is contained in:
parent
7c4eea6048
commit
bfecf2cdce
@ -17,15 +17,15 @@ exports[`compiler: codegen Element (callExpression + objectExpression + arrayExp
|
||||
"
|
||||
return function render() {
|
||||
with (this) {
|
||||
return createVNode(\\"div\\", {
|
||||
return _createVNode(\\"div\\", {
|
||||
id: \\"foo\\",
|
||||
[prop]: bar,
|
||||
[foo + bar]: bar
|
||||
}, [
|
||||
createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" })
|
||||
_createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" })
|
||||
], [
|
||||
foo,
|
||||
createVNode(\\"p\\")
|
||||
_createVNode(\\"p\\")
|
||||
])
|
||||
}
|
||||
}"
|
||||
@ -40,6 +40,19 @@ return function render() {
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen assets 1`] = `
|
||||
"
|
||||
return function render() {
|
||||
with (this) {
|
||||
const _component_Foo = _resolveComponent(\\"Foo\\")
|
||||
const _component_barbaz = _resolveComponent(\\"bar-baz\\")
|
||||
const _directive_my_dir = _resolveDirective(\\"my_dir\\")
|
||||
|
||||
return null
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen comment 1`] = `
|
||||
"
|
||||
return function render() {
|
||||
@ -72,7 +85,7 @@ exports[`compiler: codegen function mode preamble 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { helperOne: _helperOne, helperTwo: _helperTwo } = _Vue
|
||||
const { createVNode: _createVNode, resolveDirective: _resolveDirective } = _Vue
|
||||
|
||||
return null
|
||||
}
|
||||
@ -80,7 +93,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen function mode preamble w/ prefixIdentifiers: true 1`] = `
|
||||
"const { helperOne, helperTwo } = Vue
|
||||
"const { createVNode, resolveDirective } = Vue
|
||||
|
||||
return function render() {
|
||||
const _ctx = this
|
||||
@ -119,7 +132,7 @@ return function render() {
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen module mode preamble 1`] = `
|
||||
"import { helperOne, helperTwo } from \\"vue\\"
|
||||
"import { createVNode, resolveDirective } from \\"vue\\"
|
||||
|
||||
export default function render() {
|
||||
const _ctx = this
|
||||
@ -135,18 +148,6 @@ return function render() {
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen statements 1`] = `
|
||||
"
|
||||
return function render() {
|
||||
with (this) {
|
||||
const a = 1
|
||||
const b = 2
|
||||
|
||||
return null
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen static text 1`] = `
|
||||
"
|
||||
return function render() {
|
||||
|
@ -56,13 +56,13 @@ export default function render() {
|
||||
id: \\"foo\\",
|
||||
class: _ctx.bar.baz
|
||||
}, [
|
||||
_toString(_ctx.world.burn()),
|
||||
toString(_ctx.world.burn()),
|
||||
(openBlock(), (_ctx.ok)
|
||||
? createBlock(\\"div\\", { key: 0 }, \\"yes\\")
|
||||
: createBlock(Fragment, { key: 1 }, [\\"no\\"])),
|
||||
(openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
return (openBlock(), createBlock(\\"div\\", null, [
|
||||
createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
|
||||
createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */)
|
||||
]))
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
], 2 /* CLASS */))
|
||||
|
@ -13,15 +13,23 @@ import {
|
||||
createCallExpression,
|
||||
createConditionalExpression
|
||||
} from '../src'
|
||||
import { CREATE_VNODE, COMMENT, TO_STRING } from '../src/runtimeConstants'
|
||||
import {
|
||||
CREATE_VNODE,
|
||||
COMMENT,
|
||||
TO_STRING,
|
||||
RESOLVE_DIRECTIVE,
|
||||
helperNameMap,
|
||||
RESOLVE_COMPONENT
|
||||
} from '../src/runtimeHelpers'
|
||||
import { createElementWithCodegen } from './testUtils'
|
||||
|
||||
function createRoot(options: Partial<RootNode> = {}): RootNode {
|
||||
return {
|
||||
type: NodeTypes.ROOT,
|
||||
children: [],
|
||||
imports: [],
|
||||
statements: [],
|
||||
helpers: [],
|
||||
components: [],
|
||||
directives: [],
|
||||
hoists: [],
|
||||
codegenNode: undefined,
|
||||
loc: locStub,
|
||||
@ -32,45 +40,69 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
||||
describe('compiler: codegen', () => {
|
||||
test('module mode preamble', () => {
|
||||
const root = createRoot({
|
||||
imports: [`helperOne`, `helperTwo`]
|
||||
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
||||
})
|
||||
const { code } = generate(root, { mode: 'module' })
|
||||
expect(code).toMatch(`import { helperOne, helperTwo } from "vue"`)
|
||||
expect(code).toMatch(
|
||||
`import { ${helperNameMap[CREATE_VNODE]}, ${
|
||||
helperNameMap[RESOLVE_DIRECTIVE]
|
||||
} } from "vue"`
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('function mode preamble', () => {
|
||||
const root = createRoot({
|
||||
imports: [`helperOne`, `helperTwo`]
|
||||
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
||||
})
|
||||
const { code } = generate(root, { mode: 'function' })
|
||||
expect(code).toMatch(`const _Vue = Vue`)
|
||||
expect(code).toMatch(
|
||||
`const { helperOne: _helperOne, helperTwo: _helperTwo } = _Vue`
|
||||
`const { ${helperNameMap[CREATE_VNODE]}: _${
|
||||
helperNameMap[CREATE_VNODE]
|
||||
}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${
|
||||
helperNameMap[RESOLVE_DIRECTIVE]
|
||||
} } = _Vue`
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('function mode preamble w/ prefixIdentifiers: true', () => {
|
||||
const root = createRoot({
|
||||
imports: [`helperOne`, `helperTwo`]
|
||||
helpers: [CREATE_VNODE, RESOLVE_DIRECTIVE]
|
||||
})
|
||||
const { code } = generate(root, {
|
||||
mode: 'function',
|
||||
prefixIdentifiers: true
|
||||
})
|
||||
expect(code).not.toMatch(`const _Vue = Vue`)
|
||||
expect(code).toMatch(`const { helperOne, helperTwo } = Vue`)
|
||||
expect(code).toMatch(
|
||||
`const { ${helperNameMap[CREATE_VNODE]}, ${
|
||||
helperNameMap[RESOLVE_DIRECTIVE]
|
||||
} } = Vue`
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('statements', () => {
|
||||
test('assets', () => {
|
||||
const root = createRoot({
|
||||
statements: [`const a = 1`, `const b = 2`]
|
||||
components: [`Foo`, `bar-baz`],
|
||||
directives: [`my_dir`]
|
||||
})
|
||||
const { code } = generate(root, { mode: 'function' })
|
||||
expect(code).toMatch(`const a = 1\n`)
|
||||
expect(code).toMatch(`const b = 2\n`)
|
||||
expect(code).toMatch(
|
||||
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`
|
||||
)
|
||||
expect(code).toMatch(
|
||||
`const _component_barbaz = _${
|
||||
helperNameMap[RESOLVE_COMPONENT]
|
||||
}("bar-baz")\n`
|
||||
)
|
||||
expect(code).toMatch(
|
||||
`const _directive_my_dir = _${
|
||||
helperNameMap[RESOLVE_DIRECTIVE]
|
||||
}("my_dir")\n`
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -122,7 +154,7 @@ describe('compiler: codegen', () => {
|
||||
codegenNode: createInterpolation(`hello`, locStub)
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`return _${TO_STRING}(hello)`)
|
||||
expect(code).toMatch(`return _${helperNameMap[TO_STRING]}(hello)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -136,7 +168,11 @@ describe('compiler: codegen', () => {
|
||||
}
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`return _${CREATE_VNODE}(_${COMMENT}, 0, "foo")`)
|
||||
expect(code).toMatch(
|
||||
`return _${helperNameMap[CREATE_VNODE]}(_${
|
||||
helperNameMap[COMMENT]
|
||||
}, 0, "foo")`
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -155,7 +191,7 @@ describe('compiler: codegen', () => {
|
||||
])
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`return _ctx.foo + _${TO_STRING}(bar)`)
|
||||
expect(code).toMatch(`return _ctx.foo + _${helperNameMap[TO_STRING]}(bar)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -264,15 +300,15 @@ describe('compiler: codegen', () => {
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`
|
||||
return ${CREATE_VNODE}("div", {
|
||||
return _${helperNameMap[CREATE_VNODE]}("div", {
|
||||
id: "foo",
|
||||
[prop]: bar,
|
||||
[foo + bar]: bar
|
||||
}, [
|
||||
${CREATE_VNODE}("p", { "some-key": "foo" })
|
||||
_${helperNameMap[CREATE_VNODE]}("p", { "some-key": "foo" })
|
||||
], [
|
||||
foo,
|
||||
${CREATE_VNODE}("p")
|
||||
_${helperNameMap[CREATE_VNODE]}("p")
|
||||
])`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
Namespaces,
|
||||
ElementTypes
|
||||
} from '../src'
|
||||
import { CREATE_VNODE } from '../src/runtimeConstants'
|
||||
import { CREATE_VNODE } from '../src/runtimeHelpers'
|
||||
import { isString } from '@vue/shared'
|
||||
|
||||
const leadingBracketRE = /^\[/
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
CREATE_BLOCK,
|
||||
FRAGMENT,
|
||||
RENDER_SLOT
|
||||
} from '../src/runtimeConstants'
|
||||
} from '../src/runtimeHelpers'
|
||||
import { transformIf } from '../src/transforms/vIf'
|
||||
import { transformFor } from '../src/transforms/vFor'
|
||||
import { transformElement } from '../src/transforms/transformElement'
|
||||
@ -225,14 +225,14 @@ describe('compiler: transform', () => {
|
||||
test('should inject toString helper for interpolations', () => {
|
||||
const ast = parse(`{{ foo }}`)
|
||||
transform(ast, {})
|
||||
expect(ast.imports).toContain(TO_STRING)
|
||||
expect(ast.helpers).toContain(TO_STRING)
|
||||
})
|
||||
|
||||
test('should inject createVNode and Comment for comments', () => {
|
||||
const ast = parse(`<!--foo-->`)
|
||||
transform(ast, {})
|
||||
expect(ast.imports).toContain(CREATE_VNODE)
|
||||
expect(ast.imports).toContain(COMMENT)
|
||||
expect(ast.helpers).toContain(CREATE_VNODE)
|
||||
expect(ast.helpers).toContain(COMMENT)
|
||||
})
|
||||
|
||||
describe('root codegenNode', () => {
|
||||
@ -256,11 +256,11 @@ describe('compiler: transform', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`
|
||||
callee: OPEN_BLOCK
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`,
|
||||
callee: CREATE_BLOCK,
|
||||
arguments: args
|
||||
}
|
||||
]
|
||||
@ -277,7 +277,7 @@ describe('compiler: transform', () => {
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -326,7 +326,7 @@ describe('compiler: transform', () => {
|
||||
const ast = transformWithCodegen(`<div/><div/>`)
|
||||
expect(ast.codegenNode).toMatchObject(
|
||||
createBlockMatcher([
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
`null`,
|
||||
[
|
||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
RESOLVE_DIRECTIVE,
|
||||
APPLY_DIRECTIVES,
|
||||
TO_HANDLERS
|
||||
} from '../../src/runtimeConstants'
|
||||
} from '../../src/runtimeHelpers'
|
||||
import {
|
||||
CallExpression,
|
||||
NodeTypes,
|
||||
@ -52,13 +52,13 @@ function parseWithElementTransform(
|
||||
describe('compiler: element transform', () => {
|
||||
test('import + resolve component', () => {
|
||||
const { root } = parseWithElementTransform(`<Foo/>`)
|
||||
expect(root.imports).toContain(RESOLVE_COMPONENT)
|
||||
expect(root.statements[0]).toMatch(`${RESOLVE_COMPONENT}("Foo")`)
|
||||
expect(root.helpers).toContain(RESOLVE_COMPONENT)
|
||||
expect(root.components).toContain(`Foo`)
|
||||
})
|
||||
|
||||
test('static props', () => {
|
||||
const { node } = parseWithElementTransform(`<div id="foo" class="bar" />`)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"div"`,
|
||||
createObjectMatcher({
|
||||
@ -70,7 +70,7 @@ describe('compiler: element transform', () => {
|
||||
|
||||
test('props + children', () => {
|
||||
const { node } = parseWithElementTransform(`<div id="foo"><span/></div>`)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"div"`,
|
||||
createObjectMatcher({
|
||||
@ -81,7 +81,7 @@ describe('compiler: element transform', () => {
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'span',
|
||||
codegenNode: {
|
||||
callee: `_${CREATE_VNODE}`,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"span"`]
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ describe('compiler: element transform', () => {
|
||||
|
||||
test('0 placeholder for children with no props', () => {
|
||||
const { node } = parseWithElementTransform(`<div><span/></div>`)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"div"`,
|
||||
`null`,
|
||||
@ -100,7 +100,7 @@ describe('compiler: element transform', () => {
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'span',
|
||||
codegenNode: {
|
||||
callee: `_${CREATE_VNODE}`,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"span"`]
|
||||
}
|
||||
}
|
||||
@ -111,8 +111,8 @@ describe('compiler: element transform', () => {
|
||||
test('v-bind="obj"', () => {
|
||||
const { root, node } = parseWithElementTransform(`<div v-bind="obj" />`)
|
||||
// single v-bind doesn't need mergeProps
|
||||
expect(root.imports).not.toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).not.toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
// should directly use `obj` in props position
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
@ -124,11 +124,11 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div id="foo" v-bind="obj" />`
|
||||
)
|
||||
expect(root.imports).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
@ -145,11 +145,11 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div v-bind="obj" id="foo" />`
|
||||
)
|
||||
expect(root.imports).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
@ -166,11 +166,11 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div id="foo" v-bind="obj" class="bar" />`
|
||||
)
|
||||
expect(root.imports).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
@ -190,18 +190,18 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div id="foo" v-on="obj" class="bar" />`
|
||||
)
|
||||
expect(root.imports).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${TO_HANDLERS}`,
|
||||
callee: TO_HANDLERS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
@ -220,18 +220,18 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div id="foo" v-on="handlers" v-bind="obj" />`
|
||||
)
|
||||
expect(root.imports).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(root.helpers).toContain(MERGE_PROPS)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${TO_HANDLERS}`,
|
||||
callee: TO_HANDLERS,
|
||||
arguments: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
@ -249,7 +249,7 @@ describe('compiler: element transform', () => {
|
||||
|
||||
test('should handle plain <template> as normal element', () => {
|
||||
const { node } = parseWithElementTransform(`<template id="foo" />`)
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"template"`,
|
||||
createObjectMatcher({
|
||||
@ -281,7 +281,7 @@ describe('compiler: element transform', () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(node.callee).toBe(`_${CREATE_VNODE}`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
properties: [
|
||||
@ -312,14 +312,14 @@ describe('compiler: element transform', () => {
|
||||
}
|
||||
}
|
||||
)
|
||||
expect(root.imports).toContain(RESOLVE_DIRECTIVE)
|
||||
expect(root.statements[0]).toMatch(`${RESOLVE_DIRECTIVE}("foo")`)
|
||||
expect(root.helpers).toContain(RESOLVE_DIRECTIVE)
|
||||
expect(root.directives).toContain(`foo`)
|
||||
|
||||
expect(node.callee).toBe(`_${APPLY_DIRECTIVES}`)
|
||||
expect(node.callee).toBe(APPLY_DIRECTIVES)
|
||||
expect(node.arguments).toMatchObject([
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_VNODE}`,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [
|
||||
`"div"`,
|
||||
`null`,
|
||||
@ -357,12 +357,12 @@ describe('compiler: element transform', () => {
|
||||
const { root, node } = parseWithElementTransform(
|
||||
`<div v-foo v-bar="x" v-baz:[arg].mod.mad="y" />`
|
||||
)
|
||||
expect(root.imports).toContain(RESOLVE_DIRECTIVE)
|
||||
expect(root.statements[0]).toMatch(`${RESOLVE_DIRECTIVE}("foo")`)
|
||||
expect(root.statements[1]).toMatch(`${RESOLVE_DIRECTIVE}("bar")`)
|
||||
expect(root.statements[2]).toMatch(`${RESOLVE_DIRECTIVE}("baz")`)
|
||||
expect(root.helpers).toContain(RESOLVE_DIRECTIVE)
|
||||
expect(root.directives).toContain(`foo`)
|
||||
expect(root.directives).toContain(`bar`)
|
||||
expect(root.directives).toContain(`baz`)
|
||||
|
||||
expect(node.callee).toBe(`_${APPLY_DIRECTIVES}`)
|
||||
expect(node.callee).toBe(APPLY_DIRECTIVES)
|
||||
expect(node.arguments).toMatchObject([
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION
|
||||
|
@ -10,7 +10,7 @@ import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
import { transformBind } from '../../src/transforms/vBind'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
import { RENDER_SLOT } from '../../src/runtimeConstants'
|
||||
import { RENDER_SLOT } from '../../src/runtimeHelpers'
|
||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||
|
||||
function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||
@ -35,7 +35,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot/>`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [`$slots`, `"default"`]
|
||||
})
|
||||
})
|
||||
@ -44,7 +44,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot name="foo" />`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [`$slots`, `"foo"`]
|
||||
})
|
||||
})
|
||||
@ -53,7 +53,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot :name="foo" />`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
{
|
||||
@ -98,7 +98,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot foo="bar" :baz="qux" />`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"default"`,
|
||||
@ -135,7 +135,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot name="foo" foo="bar" :baz="qux" />`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"foo"`,
|
||||
@ -173,7 +173,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot :name="foo" foo="bar" :baz="qux" />`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
{ content: `foo`, isStatic: false },
|
||||
@ -211,7 +211,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot><div/></slot>`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"default"`,
|
||||
@ -230,7 +230,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot name="foo"><div/></slot>`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"foo"`,
|
||||
@ -249,7 +249,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot :foo="bar"><div/></slot>`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"default"`,
|
||||
@ -282,7 +282,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||
const ast = parseWithSlots(`<slot name="foo" :foo="bar"><div/></slot>`)
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [
|
||||
`$slots`,
|
||||
`"foo"`,
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from '../../src'
|
||||
import { transformBind } from '../../src/transforms/vBind'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { CAMELIZE } from '../../src/runtimeConstants'
|
||||
import { CAMELIZE, helperNameMap } from '../../src/runtimeHelpers'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
|
||||
function parseWithVBind(
|
||||
@ -123,7 +123,7 @@ describe('compiler: transform v-bind', () => {
|
||||
.arguments[1] as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `_${CAMELIZE}(foo)`,
|
||||
content: `_${helperNameMap[CAMELIZE]}(foo)`,
|
||||
isStatic: false
|
||||
},
|
||||
value: {
|
||||
@ -142,7 +142,7 @@ describe('compiler: transform v-bind', () => {
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
children: [
|
||||
`${CAMELIZE}(`,
|
||||
`${helperNameMap[CAMELIZE]}(`,
|
||||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
{ content: `_ctx.bar` },
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
FRAGMENT,
|
||||
RENDER_LIST,
|
||||
RENDER_SLOT
|
||||
} from '../../src/runtimeConstants'
|
||||
} from '../../src/runtimeHelpers'
|
||||
import { PatchFlags } from '@vue/runtime-dom'
|
||||
import { PatchFlagNames } from '@vue/shared'
|
||||
import { createObjectMatcher } from '../testUtils'
|
||||
@ -575,17 +575,17 @@ describe('compiler: v-for', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`
|
||||
callee: OPEN_BLOCK
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`,
|
||||
callee: CREATE_BLOCK,
|
||||
arguments: [
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
`null`,
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_LIST}`,
|
||||
callee: RENDER_LIST,
|
||||
arguments: [
|
||||
{}, // to be asserted by each test
|
||||
{
|
||||
@ -597,11 +597,11 @@ describe('compiler: v-for', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`
|
||||
callee: OPEN_BLOCK
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`
|
||||
callee: CREATE_BLOCK
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -703,7 +703,7 @@ describe('compiler: v-for', () => {
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }],
|
||||
blockArgs: [
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
`null`,
|
||||
[
|
||||
{ type: NodeTypes.TEXT, content: `hello` },
|
||||
@ -728,7 +728,7 @@ describe('compiler: v-for', () => {
|
||||
params: [{ content: `item` }],
|
||||
returns: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
@ -746,7 +746,7 @@ describe('compiler: v-for', () => {
|
||||
params: [{ content: `item` }],
|
||||
returns: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
@ -781,7 +781,7 @@ describe('compiler: v-for', () => {
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }],
|
||||
blockArgs: [
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
createObjectMatcher({
|
||||
key: `[item]`
|
||||
}),
|
||||
@ -804,7 +804,7 @@ describe('compiler: v-for', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`,
|
||||
callee: OPEN_BLOCK,
|
||||
arguments: []
|
||||
},
|
||||
{
|
||||
@ -812,14 +812,14 @@ describe('compiler: v-for', () => {
|
||||
test: { content: `ok` },
|
||||
consequent: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`,
|
||||
callee: CREATE_BLOCK,
|
||||
// should optimize v-if + v-for into a single Fragment block
|
||||
arguments: [
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
createObjectMatcher({ key: `[0]` }),
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_LIST}`,
|
||||
callee: RENDER_LIST,
|
||||
arguments: [
|
||||
{ content: `list` },
|
||||
{
|
||||
@ -830,11 +830,11 @@ describe('compiler: v-for', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`
|
||||
callee: OPEN_BLOCK
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`,
|
||||
callee: CREATE_BLOCK,
|
||||
arguments: [`"div"`]
|
||||
}
|
||||
]
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
MERGE_PROPS,
|
||||
APPLY_DIRECTIVES,
|
||||
RENDER_SLOT
|
||||
} from '../../src/runtimeConstants'
|
||||
} from '../../src/runtimeHelpers'
|
||||
import { createObjectMatcher } from '../testUtils'
|
||||
|
||||
function parseWithIfTransform(
|
||||
@ -271,7 +271,7 @@ describe('compiler: v-if', () => {
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${OPEN_BLOCK}`,
|
||||
callee: OPEN_BLOCK,
|
||||
arguments: []
|
||||
},
|
||||
{
|
||||
@ -281,13 +281,13 @@ describe('compiler: v-if', () => {
|
||||
},
|
||||
consequent: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`
|
||||
callee: CREATE_BLOCK
|
||||
},
|
||||
alternate:
|
||||
depth < 1
|
||||
? {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`
|
||||
callee: CREATE_BLOCK
|
||||
}
|
||||
: {
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
@ -296,11 +296,11 @@ describe('compiler: v-if', () => {
|
||||
},
|
||||
consequent: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`
|
||||
callee: CREATE_BLOCK
|
||||
},
|
||||
alternate: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`
|
||||
callee: CREATE_BLOCK
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,7 +322,7 @@ describe('compiler: v-if', () => {
|
||||
])
|
||||
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
|
||||
.alternate as CallExpression
|
||||
expect(branch2.arguments).toMatchObject([`_${EMPTY}`])
|
||||
expect(branch2.arguments).toMatchObject([EMPTY])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -335,7 +335,7 @@ describe('compiler: v-if', () => {
|
||||
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
|
||||
.consequent as CallExpression
|
||||
expect(branch1.arguments).toMatchObject([
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
createObjectMatcher({ key: `[0]` }),
|
||||
[
|
||||
{ type: NodeTypes.ELEMENT, tag: 'div' },
|
||||
@ -345,7 +345,7 @@ describe('compiler: v-if', () => {
|
||||
])
|
||||
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
|
||||
.alternate as CallExpression
|
||||
expect(branch2.arguments).toMatchObject([`_${EMPTY}`])
|
||||
expect(branch2.arguments).toMatchObject([EMPTY])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -359,7 +359,7 @@ describe('compiler: v-if', () => {
|
||||
.consequent as CallExpression
|
||||
expect(branch1).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
@ -375,7 +375,7 @@ describe('compiler: v-if', () => {
|
||||
.consequent as CallExpression
|
||||
expect(branch1).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${RENDER_SLOT}`,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
@ -444,7 +444,7 @@ describe('compiler: v-if', () => {
|
||||
createObjectMatcher({ key: `[1]` })
|
||||
])
|
||||
expect((branch2.alternate as CallExpression).arguments).toMatchObject([
|
||||
`_${FRAGMENT}`,
|
||||
FRAGMENT,
|
||||
createObjectMatcher({ key: `[2]` }),
|
||||
[
|
||||
{
|
||||
@ -464,7 +464,7 @@ describe('compiler: v-if', () => {
|
||||
.consequent as CallExpression
|
||||
expect(branch1.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [createObjectMatcher({ key: `[0]` }), { content: `obj` }]
|
||||
})
|
||||
})
|
||||
@ -477,7 +477,7 @@ describe('compiler: v-if', () => {
|
||||
.consequent as CallExpression
|
||||
expect(branch1.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
key: '[0]',
|
||||
@ -496,7 +496,7 @@ describe('compiler: v-if', () => {
|
||||
.consequent as CallExpression
|
||||
expect(branch1.arguments[1]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${MERGE_PROPS}`,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({ key: `[0]` }),
|
||||
{ content: `obj` },
|
||||
@ -513,7 +513,7 @@ describe('compiler: v-if', () => {
|
||||
} = parseWithIfTransform(`<div v-if="ok" v-foo />`)
|
||||
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
|
||||
.consequent as CallExpression
|
||||
expect(branch1.callee).toBe(`_${APPLY_DIRECTIVES}`)
|
||||
expect(branch1.callee).toBe(APPLY_DIRECTIVES)
|
||||
const realBranch = branch1.arguments[0] as CallExpression
|
||||
expect(realBranch.arguments[1]).toMatchObject(
|
||||
createObjectMatcher({ key: `[0]` })
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
trackSlotScopes,
|
||||
trackVForSlotScopes
|
||||
} from '../../src/transforms/vSlot'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeConstants'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers'
|
||||
import { createObjectMatcher } from '../testUtils'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
import { transformFor } from '../../src/transforms/vFor'
|
||||
@ -360,7 +360,7 @@ describe('compiler: transform component slots', () => {
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_SLOTS}`,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_compiled: `[true]`
|
||||
@ -451,7 +451,7 @@ describe('compiler: transform component slots', () => {
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_SLOTS}`,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_compiled: `[true]`
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { isString } from '@vue/shared'
|
||||
import { ForParseResult } from './transforms/vFor'
|
||||
import { CREATE_VNODE, RuntimeHelper } from './runtimeHelpers'
|
||||
|
||||
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
||||
// More namespaces like SVG and MathML are declared by platform specific
|
||||
@ -76,8 +77,9 @@ export type TemplateChildNode =
|
||||
export interface RootNode extends Node {
|
||||
type: NodeTypes.ROOT
|
||||
children: TemplateChildNode[]
|
||||
imports: string[]
|
||||
statements: string[]
|
||||
helpers: RuntimeHelper[]
|
||||
components: string[]
|
||||
directives: string[]
|
||||
hoists: JSChildNode[]
|
||||
codegenNode: TemplateChildNode | JSChildNode | undefined
|
||||
}
|
||||
@ -93,6 +95,29 @@ export interface ElementNode extends Node {
|
||||
codegenNode: CallExpression | SimpleExpressionNode | undefined
|
||||
}
|
||||
|
||||
export interface PlainElementNode extends ElementNode {
|
||||
tagType: ElementTypes.ELEMENT
|
||||
codegenNode: VNodeCodegenNode | VNodeWithDirectiveCodegenNode
|
||||
}
|
||||
|
||||
export interface ComponentNode extends ElementNode {
|
||||
tagType: ElementTypes.COMPONENT
|
||||
codegenNode: VNodeCodegenNode | VNodeWithDirectiveCodegenNode
|
||||
}
|
||||
|
||||
export interface SlotOutletNode extends ElementNode {
|
||||
tagType: ElementTypes.SLOT
|
||||
codegenNode: SlotOutletCodegenNode
|
||||
}
|
||||
|
||||
export interface VNodeCodegenNode extends CallExpression {
|
||||
callee: typeof CREATE_VNODE
|
||||
}
|
||||
|
||||
export interface VNodeWithDirectiveCodegenNode extends CallExpression {}
|
||||
|
||||
export interface SlotOutletCodegenNode extends CallExpression {}
|
||||
|
||||
export interface TextNode extends Node {
|
||||
type: NodeTypes.TEXT
|
||||
content: string
|
||||
@ -137,7 +162,12 @@ export interface InterpolationNode extends Node {
|
||||
// always dynamic
|
||||
export interface CompoundExpressionNode extends Node {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION
|
||||
children: (SimpleExpressionNode | InterpolationNode | TextNode | string)[]
|
||||
children: (
|
||||
| SimpleExpressionNode
|
||||
| InterpolationNode
|
||||
| TextNode
|
||||
| string
|
||||
| RuntimeHelper)[]
|
||||
// an expression parsed as the params of a function will track
|
||||
// the identifiers declared inside the function body.
|
||||
identifiers?: string[]
|
||||
@ -146,9 +176,11 @@ export interface CompoundExpressionNode extends Node {
|
||||
export interface IfNode extends Node {
|
||||
type: NodeTypes.IF
|
||||
branches: IfBranchNode[]
|
||||
codegenNode: SequenceExpression
|
||||
codegenNode: IfCodegenNode
|
||||
}
|
||||
|
||||
export interface IfCodegenNode extends SequenceExpression {}
|
||||
|
||||
export interface IfBranchNode extends Node {
|
||||
type: NodeTypes.IF_BRANCH
|
||||
condition: ExpressionNode | undefined // else
|
||||
@ -162,9 +194,11 @@ export interface ForNode extends Node {
|
||||
keyAlias: ExpressionNode | undefined
|
||||
objectIndexAlias: ExpressionNode | undefined
|
||||
children: TemplateChildNode[]
|
||||
codegenNode: SequenceExpression
|
||||
codegenNode: ForCodegenNode
|
||||
}
|
||||
|
||||
export interface ForCodegenNode extends SequenceExpression {}
|
||||
|
||||
// We also include a number of JavaScript AST nodes for code generation.
|
||||
// The AST is an intentionally minimal subset just to meet the exact needs of
|
||||
// Vue render function generation.
|
||||
@ -179,8 +213,13 @@ export type JSChildNode =
|
||||
|
||||
export interface CallExpression extends Node {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION
|
||||
callee: string
|
||||
arguments: (string | JSChildNode | TemplateChildNode | TemplateChildNode[])[]
|
||||
callee: string | RuntimeHelper
|
||||
arguments: (
|
||||
| string
|
||||
| RuntimeHelper
|
||||
| JSChildNode
|
||||
| TemplateChildNode
|
||||
| TemplateChildNode[])[]
|
||||
}
|
||||
|
||||
export interface ObjectExpression extends Node {
|
||||
|
@ -23,10 +23,19 @@ import {
|
||||
advancePositionWithMutation,
|
||||
assert,
|
||||
isSimpleIdentifier,
|
||||
loadDep
|
||||
loadDep,
|
||||
toValidAssetId
|
||||
} from './utils'
|
||||
import { isString, isArray } from '@vue/shared'
|
||||
import { TO_STRING, CREATE_VNODE, COMMENT } from './runtimeConstants'
|
||||
import { isString, isArray, isSymbol } from '@vue/shared'
|
||||
import {
|
||||
TO_STRING,
|
||||
CREATE_VNODE,
|
||||
COMMENT,
|
||||
helperNameMap,
|
||||
RESOLVE_COMPONENT,
|
||||
RESOLVE_DIRECTIVE,
|
||||
RuntimeHelper
|
||||
} from './runtimeHelpers'
|
||||
|
||||
type CodegenNode = TemplateChildNode | JSChildNode
|
||||
|
||||
@ -65,7 +74,7 @@ export interface CodegenContext extends Required<CodegenOptions> {
|
||||
offset: number
|
||||
indentLevel: number
|
||||
map?: SourceMapGenerator
|
||||
helper(name: string): string
|
||||
helper(key: RuntimeHelper): string
|
||||
push(code: string, node?: CodegenNode, openOnly?: boolean): void
|
||||
resetMapping(loc: SourceLocation): void
|
||||
indent(): void
|
||||
@ -77,7 +86,7 @@ function createCodegenContext(
|
||||
ast: RootNode,
|
||||
{
|
||||
mode = 'function',
|
||||
prefixIdentifiers = false,
|
||||
prefixIdentifiers = mode === 'module',
|
||||
sourceMap = false,
|
||||
filename = `template.vue.html`
|
||||
}: CodegenOptions
|
||||
@ -100,7 +109,8 @@ function createCodegenContext(
|
||||
? undefined
|
||||
: new (loadDep('source-map')).SourceMapGenerator(),
|
||||
|
||||
helper(name) {
|
||||
helper(key) {
|
||||
const name = helperNameMap[key]
|
||||
return prefixIdentifiers ? name : `_${name}`
|
||||
},
|
||||
push(code, node, openOnly) {
|
||||
@ -172,8 +182,16 @@ export function generate(
|
||||
options: CodegenOptions = {}
|
||||
): CodegenResult {
|
||||
const context = createCodegenContext(ast, options)
|
||||
const { mode, push, prefixIdentifiers, indent, deindent, newline } = context
|
||||
const hasImports = ast.imports.length
|
||||
const {
|
||||
mode,
|
||||
push,
|
||||
helper,
|
||||
prefixIdentifiers,
|
||||
indent,
|
||||
deindent,
|
||||
newline
|
||||
} = context
|
||||
const hasHelpers = ast.helpers.length > 0
|
||||
const useWithBlock = !prefixIdentifiers && mode !== 'module'
|
||||
|
||||
// preambles
|
||||
@ -182,9 +200,9 @@ export function generate(
|
||||
// In prefix mode, we place the const declaration at top so it's done
|
||||
// only once; But if we not prefixing, we place the declaration inside the
|
||||
// with block so it doesn't incur the `in` check cost for every helper access.
|
||||
if (hasImports) {
|
||||
if (hasHelpers) {
|
||||
if (prefixIdentifiers) {
|
||||
push(`const { ${ast.imports.join(', ')} } = Vue\n`)
|
||||
push(`const { ${ast.helpers.map(helper).join(', ')} } = Vue\n`)
|
||||
} else {
|
||||
// "with" mode.
|
||||
// save Vue in a separate variable to avoid collision
|
||||
@ -193,7 +211,7 @@ export function generate(
|
||||
// has check cost, but hoists are lifted out of the function - we need
|
||||
// to provide the helper here.
|
||||
if (ast.hoists.length) {
|
||||
push(`const _${CREATE_VNODE} = Vue.createVNode\n`)
|
||||
push(`const _${helperNameMap[CREATE_VNODE]} = Vue.createVNode\n`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,8 +220,8 @@ export function generate(
|
||||
push(`return `)
|
||||
} else {
|
||||
// generate import statements for helpers
|
||||
if (hasImports) {
|
||||
push(`import { ${ast.imports.join(', ')} } from "vue"\n`)
|
||||
if (hasHelpers) {
|
||||
push(`import { ${ast.helpers.map(helper).join(', ')} } from "vue"\n`)
|
||||
}
|
||||
genHoists(ast.hoists, context)
|
||||
context.newline()
|
||||
@ -219,8 +237,12 @@ export function generate(
|
||||
indent()
|
||||
// function mode const declarations should be inside with block
|
||||
// also they should be renamed to avoid collision with user properties
|
||||
if (hasImports) {
|
||||
push(`const { ${ast.imports.map(n => `${n}: _${n}`).join(', ')} } = _Vue`)
|
||||
if (hasHelpers) {
|
||||
push(
|
||||
`const { ${ast.helpers
|
||||
.map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)
|
||||
.join(', ')} } = _Vue`
|
||||
)
|
||||
newline()
|
||||
newline()
|
||||
}
|
||||
@ -230,11 +252,13 @@ export function generate(
|
||||
}
|
||||
|
||||
// generate asset resolution statements
|
||||
if (ast.statements.length) {
|
||||
ast.statements.forEach(s => {
|
||||
push(s)
|
||||
newline()
|
||||
})
|
||||
if (ast.components.length) {
|
||||
genAssets(ast.components, 'component', context)
|
||||
}
|
||||
if (ast.directives.length) {
|
||||
genAssets(ast.directives, 'directive', context)
|
||||
}
|
||||
if (ast.components.length || ast.directives.length) {
|
||||
newline()
|
||||
}
|
||||
|
||||
@ -260,6 +284,23 @@ export function generate(
|
||||
}
|
||||
}
|
||||
|
||||
function genAssets(
|
||||
assets: string[],
|
||||
type: 'component' | 'directive',
|
||||
context: CodegenContext
|
||||
) {
|
||||
const resolver = context.helper(
|
||||
type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE
|
||||
)
|
||||
for (let i = 0; i < assets.length; i++) {
|
||||
const id = assets[i]
|
||||
context.push(
|
||||
`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)})`
|
||||
)
|
||||
context.newline()
|
||||
}
|
||||
}
|
||||
|
||||
function genHoists(hoists: JSChildNode[], context: CodegenContext) {
|
||||
if (!hoists.length) {
|
||||
return
|
||||
@ -297,7 +338,7 @@ function genNodeListAsArray(
|
||||
}
|
||||
|
||||
function genNodeList(
|
||||
nodes: (string | CodegenNode | TemplateChildNode[])[],
|
||||
nodes: (string | RuntimeHelper | CodegenNode | TemplateChildNode[])[],
|
||||
context: CodegenContext,
|
||||
multilines: boolean = false
|
||||
) {
|
||||
@ -322,11 +363,18 @@ function genNodeList(
|
||||
}
|
||||
}
|
||||
|
||||
function genNode(node: CodegenNode | string, context: CodegenContext) {
|
||||
function genNode(
|
||||
node: CodegenNode | RuntimeHelper | string,
|
||||
context: CodegenContext
|
||||
) {
|
||||
if (isString(node)) {
|
||||
context.push(node)
|
||||
return
|
||||
}
|
||||
if (isSymbol(node)) {
|
||||
context.push(context.helper(node))
|
||||
return
|
||||
}
|
||||
switch (node.type) {
|
||||
case NodeTypes.ELEMENT:
|
||||
case NodeTypes.IF:
|
||||
@ -450,7 +498,10 @@ function genComment(node: CommentNode, context: CodegenContext) {
|
||||
|
||||
// JavaScript
|
||||
function genCallExpression(node: CallExpression, context: CodegenContext) {
|
||||
context.push(node.callee + `(`, node, true)
|
||||
const callee = isString(node.callee)
|
||||
? node.callee
|
||||
: context.helper(node.callee)
|
||||
context.push(callee + `(`, node, true)
|
||||
genNodeList(node.arguments, context)
|
||||
context.push(`)`)
|
||||
}
|
||||
|
@ -64,7 +64,10 @@ export function baseCompile(
|
||||
}
|
||||
})
|
||||
|
||||
return generate(ast, options)
|
||||
return generate(ast, {
|
||||
...options,
|
||||
prefixIdentifiers
|
||||
})
|
||||
}
|
||||
|
||||
// Also expose lower level APIs & types
|
||||
|
@ -1,21 +0,0 @@
|
||||
// Name mapping constants for runtime helpers that need to be imported in
|
||||
// generated code. Make sure these are correctly exported in the runtime!
|
||||
export const FRAGMENT = `Fragment`
|
||||
export const PORTAL = `Portal`
|
||||
export const COMMENT = `Comment`
|
||||
export const TEXT = `Text`
|
||||
export const SUSPENSE = `Suspense`
|
||||
export const EMPTY = `Empty`
|
||||
export const OPEN_BLOCK = `openBlock`
|
||||
export const CREATE_BLOCK = `createBlock`
|
||||
export const CREATE_VNODE = `createVNode`
|
||||
export const RESOLVE_COMPONENT = `resolveComponent`
|
||||
export const RESOLVE_DIRECTIVE = `resolveDirective`
|
||||
export const APPLY_DIRECTIVES = `applyDirectives`
|
||||
export const RENDER_LIST = `renderList`
|
||||
export const RENDER_SLOT = `renderSlot`
|
||||
export const CREATE_SLOTS = `createSlots`
|
||||
export const TO_STRING = `toString`
|
||||
export const MERGE_PROPS = `mergeProps`
|
||||
export const TO_HANDLERS = `toHandlers`
|
||||
export const CAMELIZE = `camelize`
|
64
packages/compiler-core/src/runtimeHelpers.ts
Normal file
64
packages/compiler-core/src/runtimeHelpers.ts
Normal file
@ -0,0 +1,64 @@
|
||||
export const FRAGMENT = Symbol()
|
||||
export const PORTAL = Symbol()
|
||||
export const COMMENT = Symbol()
|
||||
export const TEXT = Symbol()
|
||||
export const SUSPENSE = Symbol()
|
||||
export const EMPTY = Symbol()
|
||||
export const OPEN_BLOCK = Symbol()
|
||||
export const CREATE_BLOCK = Symbol()
|
||||
export const CREATE_VNODE = Symbol()
|
||||
export const RESOLVE_COMPONENT = Symbol()
|
||||
export const RESOLVE_DIRECTIVE = Symbol()
|
||||
export const APPLY_DIRECTIVES = Symbol()
|
||||
export const RENDER_LIST = Symbol()
|
||||
export const RENDER_SLOT = Symbol()
|
||||
export const CREATE_SLOTS = Symbol()
|
||||
export const TO_STRING = Symbol()
|
||||
export const MERGE_PROPS = Symbol()
|
||||
export const TO_HANDLERS = Symbol()
|
||||
export const CAMELIZE = Symbol()
|
||||
|
||||
export type RuntimeHelper =
|
||||
| typeof FRAGMENT
|
||||
| typeof PORTAL
|
||||
| typeof COMMENT
|
||||
| typeof TEXT
|
||||
| typeof SUSPENSE
|
||||
| typeof EMPTY
|
||||
| typeof OPEN_BLOCK
|
||||
| typeof CREATE_BLOCK
|
||||
| typeof CREATE_VNODE
|
||||
| typeof RESOLVE_COMPONENT
|
||||
| typeof RESOLVE_DIRECTIVE
|
||||
| typeof APPLY_DIRECTIVES
|
||||
| typeof RENDER_LIST
|
||||
| typeof RENDER_SLOT
|
||||
| typeof CREATE_SLOTS
|
||||
| typeof TO_STRING
|
||||
| typeof MERGE_PROPS
|
||||
| typeof TO_HANDLERS
|
||||
| typeof CAMELIZE
|
||||
|
||||
// Name mapping for runtime helpers that need to be imported from 'vue' in
|
||||
// generated code. Make sure these are correctly exported in the runtime!
|
||||
export const helperNameMap = {
|
||||
[FRAGMENT]: `Fragment`,
|
||||
[PORTAL]: `Portal`,
|
||||
[COMMENT]: `Comment`,
|
||||
[TEXT]: `Text`,
|
||||
[SUSPENSE]: `Suspense`,
|
||||
[EMPTY]: `Empty`,
|
||||
[OPEN_BLOCK]: `openBlock`,
|
||||
[CREATE_BLOCK]: `createBlock`,
|
||||
[CREATE_VNODE]: `createVNode`,
|
||||
[RESOLVE_COMPONENT]: `resolveComponent`,
|
||||
[RESOLVE_DIRECTIVE]: `resolveDirective`,
|
||||
[APPLY_DIRECTIVES]: `applyDirectives`,
|
||||
[RENDER_LIST]: `renderList`,
|
||||
[RENDER_SLOT]: `renderSlot`,
|
||||
[CREATE_SLOTS]: `createSlots`,
|
||||
[TO_STRING]: `toString`,
|
||||
[MERGE_PROPS]: `mergeProps`,
|
||||
[TO_HANDLERS]: `toHandlers`,
|
||||
[CAMELIZE]: `camelize`
|
||||
}
|
@ -14,7 +14,14 @@ import {
|
||||
} from './ast'
|
||||
import { isString, isArray } from '@vue/shared'
|
||||
import { CompilerError, defaultOnError } from './errors'
|
||||
import { TO_STRING, COMMENT, CREATE_VNODE, FRAGMENT } from './runtimeConstants'
|
||||
import {
|
||||
TO_STRING,
|
||||
COMMENT,
|
||||
CREATE_VNODE,
|
||||
FRAGMENT,
|
||||
RuntimeHelper,
|
||||
helperNameMap
|
||||
} from './runtimeHelpers'
|
||||
import { isVSlot, createBlockExpression, isSlotOutlet } from './utils'
|
||||
import { hoistStatic } from './transforms/hoistStatic'
|
||||
|
||||
@ -57,8 +64,9 @@ export interface TransformOptions {
|
||||
|
||||
export interface TransformContext extends Required<TransformOptions> {
|
||||
root: RootNode
|
||||
imports: Set<string>
|
||||
statements: Set<string>
|
||||
helpers: Set<RuntimeHelper>
|
||||
components: Set<string>
|
||||
directives: Set<string>
|
||||
hoists: JSChildNode[]
|
||||
identifiers: { [name: string]: number | undefined }
|
||||
scopes: {
|
||||
@ -70,7 +78,8 @@ export interface TransformContext extends Required<TransformOptions> {
|
||||
parent: ParentNode | null
|
||||
childIndex: number
|
||||
currentNode: RootNode | TemplateChildNode | null
|
||||
helper(name: string): string
|
||||
helper<T extends RuntimeHelper>(name: T): T
|
||||
helperString(name: RuntimeHelper): string
|
||||
replaceNode(node: TemplateChildNode): void
|
||||
removeNode(node?: TemplateChildNode): void
|
||||
onNodeRemoved: () => void
|
||||
@ -91,8 +100,9 @@ function createTransformContext(
|
||||
): TransformContext {
|
||||
const context: TransformContext = {
|
||||
root,
|
||||
imports: new Set(),
|
||||
statements: new Set(),
|
||||
helpers: new Set(),
|
||||
components: new Set(),
|
||||
directives: new Set(),
|
||||
hoists: [],
|
||||
identifiers: {},
|
||||
scopes: {
|
||||
@ -110,8 +120,14 @@ function createTransformContext(
|
||||
currentNode: root,
|
||||
childIndex: 0,
|
||||
helper(name) {
|
||||
context.imports.add(name)
|
||||
return prefixIdentifiers ? name : `_${name}`
|
||||
context.helpers.add(name)
|
||||
return name
|
||||
},
|
||||
helperString(name) {
|
||||
return (
|
||||
(context.prefixIdentifiers ? `` : `_`) +
|
||||
helperNameMap[context.helper(name)]
|
||||
)
|
||||
},
|
||||
replaceNode(node) {
|
||||
/* istanbul ignore if */
|
||||
@ -242,8 +258,9 @@ function finalizeRoot(root: RootNode, context: TransformContext) {
|
||||
}
|
||||
|
||||
// finalize meta information
|
||||
root.imports = [...context.imports]
|
||||
root.statements = [...context.statements]
|
||||
root.helpers = [...context.helpers]
|
||||
root.components = [...context.components]
|
||||
root.directives = [...context.directives]
|
||||
root.hoists = context.hoists
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
ElementTypes
|
||||
} from '../ast'
|
||||
import { TransformContext } from '../transform'
|
||||
import { APPLY_DIRECTIVES } from '../runtimeConstants'
|
||||
import { APPLY_DIRECTIVES } from '../runtimeHelpers'
|
||||
import { PropsExpression } from './transformElement'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
|
||||
@ -41,7 +41,7 @@ function walk(
|
||||
flag === PatchFlags.TEXT
|
||||
) {
|
||||
let codegenNode = child.codegenNode as CallExpression
|
||||
if (codegenNode.callee.includes(APPLY_DIRECTIVES)) {
|
||||
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||
codegenNode = codegenNode.arguments[0] as CallExpression
|
||||
}
|
||||
const props = codegenNode.arguments[1] as
|
||||
@ -68,7 +68,7 @@ function walk(
|
||||
|
||||
function getPatchFlag(node: ElementNode): number | undefined {
|
||||
let codegenNode = node.codegenNode as CallExpression
|
||||
if (codegenNode.callee.includes(APPLY_DIRECTIVES)) {
|
||||
if (codegenNode.callee === APPLY_DIRECTIVES) {
|
||||
codegenNode = codegenNode.arguments[0] as CallExpression
|
||||
}
|
||||
const flag = codegenNode.arguments[3]
|
||||
|
@ -25,12 +25,10 @@ import {
|
||||
RESOLVE_COMPONENT,
|
||||
MERGE_PROPS,
|
||||
TO_HANDLERS
|
||||
} from '../runtimeConstants'
|
||||
import { getInnerRange, isVSlot } from '../utils'
|
||||
} from '../runtimeHelpers'
|
||||
import { getInnerRange, isVSlot, toValidAssetId } from '../utils'
|
||||
import { buildSlots } from './vSlot'
|
||||
|
||||
const toValidId = (str: string): string => str.replace(/[^\w]/g, '')
|
||||
|
||||
// generate a JavaScript AST for this element's codegen
|
||||
export const transformElement: NodeTransform = (node, context) => {
|
||||
if (node.type === NodeTypes.ELEMENT) {
|
||||
@ -50,19 +48,14 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||
let patchFlag: number = 0
|
||||
let runtimeDirectives: DirectiveNode[] | undefined
|
||||
let dynamicPropNames: string[] | undefined
|
||||
let componentIdentifier: string | undefined
|
||||
|
||||
if (isComponent) {
|
||||
componentIdentifier = `_component_${toValidId(node.tag)}`
|
||||
context.statements.add(
|
||||
`const ${componentIdentifier} = ${context.helper(
|
||||
RESOLVE_COMPONENT
|
||||
)}(${JSON.stringify(node.tag)})`
|
||||
)
|
||||
context.helper(RESOLVE_COMPONENT)
|
||||
context.components.add(node.tag)
|
||||
}
|
||||
|
||||
const args: CallExpression['arguments'] = [
|
||||
isComponent ? componentIdentifier! : `"${node.tag}"`
|
||||
isComponent ? toValidAssetId(node.tag, `component`) : `"${node.tag}"`
|
||||
]
|
||||
// props
|
||||
if (hasProps) {
|
||||
@ -402,13 +395,11 @@ function createDirectiveArgs(
|
||||
context: TransformContext
|
||||
): ArrayExpression {
|
||||
// inject statement for resolving directive
|
||||
const dirIdentifier = `_directive_${toValidId(dir.name)}`
|
||||
context.statements.add(
|
||||
`const ${dirIdentifier} = ${context.helper(
|
||||
RESOLVE_DIRECTIVE
|
||||
)}(${JSON.stringify(dir.name)})`
|
||||
)
|
||||
const dirArgs: ArrayExpression['elements'] = [dirIdentifier]
|
||||
context.helper(RESOLVE_DIRECTIVE)
|
||||
context.directives.add(dir.name)
|
||||
const dirArgs: ArrayExpression['elements'] = [
|
||||
toValidAssetId(dir.name, `directive`)
|
||||
]
|
||||
const { loc } = dir
|
||||
if (dir.exp) dirArgs.push(dir.exp)
|
||||
if (dir.arg) dirArgs.push(dir.arg)
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
import { isSlotOutlet } from '../utils'
|
||||
import { buildProps } from './transformElement'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { RENDER_SLOT } from '../runtimeConstants'
|
||||
import { RENDER_SLOT } from '../runtimeHelpers'
|
||||
|
||||
export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||
if (isSlotOutlet(node)) {
|
||||
|
@ -2,7 +2,7 @@ import { DirectiveTransform } from '../transform'
|
||||
import { createObjectProperty, createSimpleExpression, NodeTypes } from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { camelize } from '@vue/shared'
|
||||
import { CAMELIZE } from '../runtimeConstants'
|
||||
import { CAMELIZE } from '../runtimeHelpers'
|
||||
|
||||
// v-bind without arg is handled directly in ./element.ts due to it affecting
|
||||
// codegen for the entire props object. This transform here is only for v-bind
|
||||
@ -20,10 +20,10 @@ export const transformBind: DirectiveTransform = (dir, context) => {
|
||||
if (arg.isStatic) {
|
||||
arg.content = camelize(arg.content)
|
||||
} else {
|
||||
arg.content = `${context.helper(CAMELIZE)}(${arg.content})`
|
||||
arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`
|
||||
}
|
||||
} else {
|
||||
arg.children.unshift(`${context.helper(CAMELIZE)}(`)
|
||||
arg.children.unshift(`${context.helperString(CAMELIZE)}(`)
|
||||
arg.children.push(`)`)
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import {
|
||||
OPEN_BLOCK,
|
||||
CREATE_BLOCK,
|
||||
FRAGMENT
|
||||
} from '../runtimeConstants'
|
||||
} from '../runtimeHelpers'
|
||||
import { processExpression } from './transformExpression'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
import { PropsExpression } from './transformElement'
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
APPLY_DIRECTIVES,
|
||||
CREATE_VNODE,
|
||||
RENDER_SLOT
|
||||
} from '../runtimeConstants'
|
||||
} from '../runtimeHelpers'
|
||||
import { injectProp } from '../utils'
|
||||
import { PropsExpression } from './transformElement'
|
||||
|
||||
@ -184,18 +184,18 @@ function createChildrenCodegenNode(
|
||||
const childCodegen = (child as ElementNode).codegenNode as CallExpression
|
||||
let vnodeCall = childCodegen
|
||||
// Element with custom directives. Locate the actual createVNode() call.
|
||||
if (vnodeCall.callee.includes(APPLY_DIRECTIVES)) {
|
||||
if (vnodeCall.callee === APPLY_DIRECTIVES) {
|
||||
vnodeCall = vnodeCall.arguments[0] as CallExpression
|
||||
}
|
||||
// Change createVNode to createBlock.
|
||||
if (vnodeCall.callee.includes(CREATE_VNODE)) {
|
||||
if (vnodeCall.callee === CREATE_VNODE) {
|
||||
vnodeCall.callee = helper(CREATE_BLOCK)
|
||||
}
|
||||
// It's possible to have renderSlot() here as well - which already produces
|
||||
// a block, so no need to change the callee. However it accepts props at
|
||||
// a different arg index so make sure to check for so that the key injection
|
||||
// logic below works for it too.
|
||||
const propsIndex = vnodeCall.callee.includes(RENDER_SLOT) ? 2 : 1
|
||||
const propsIndex = vnodeCall.callee === RENDER_SLOT ? 2 : 1
|
||||
// inject branch key
|
||||
const existingProps = vnodeCall.arguments[propsIndex] as
|
||||
| PropsExpression
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
import { TransformContext, NodeTransform } from '../transform'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { findDir, isTemplateNode, assert, isVSlot } from '../utils'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../runtimeConstants'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../runtimeHelpers'
|
||||
import { parseForExpression, createForLoopParams } from './vFor'
|
||||
|
||||
const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
import { parse } from 'acorn'
|
||||
import { walk } from 'estree-walker'
|
||||
import { TransformContext } from './transform'
|
||||
import { OPEN_BLOCK, CREATE_BLOCK, MERGE_PROPS } from './runtimeConstants'
|
||||
import { OPEN_BLOCK, CREATE_BLOCK, MERGE_PROPS } from './runtimeHelpers'
|
||||
import { isString, isFunction } from '@vue/shared'
|
||||
import { PropsExpression } from './transforms/transformElement'
|
||||
|
||||
@ -217,3 +217,10 @@ export function injectProp(
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
export function toValidAssetId(
|
||||
name: string,
|
||||
type: 'component' | 'directive'
|
||||
): string {
|
||||
return `_${type}_${name.replace(/[^\w]/g, '')}`
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ export const isArray = Array.isArray
|
||||
export const isFunction = (val: any): val is Function =>
|
||||
typeof val === 'function'
|
||||
export const isString = (val: any): val is string => typeof val === 'string'
|
||||
export const isSymbol = (val: any): val is symbol => typeof val === 'symbol'
|
||||
export const isObject = (val: any): val is Record<any, any> =>
|
||||
val !== null && typeof val === 'object'
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user