test(compiler): tests for v-for codegen w/ block optimization
This commit is contained in:
parent
65661b5ec0
commit
07955e6c96
@ -0,0 +1,104 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen basic v-for 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||||
|
return _createVNode(\\"span\\")
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen skipped key 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (value, __, index) => {
|
||||||
|
return _createVNode(\\"span\\")
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen skipped value & key 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, __, index) => {
|
||||||
|
return _createVNode(\\"span\\")
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen skipped value 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, key, index) => {
|
||||||
|
return _createVNode(\\"span\\")
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen template v-for 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||||
|
return [
|
||||||
|
\\"hello\\",
|
||||||
|
_createVNode(\\"span\\")
|
||||||
|
]
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen v-if + v-for 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList, Empty: _Empty } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), ok
|
||||||
|
? _createBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {
|
||||||
|
return _createVNode(\\"div\\")
|
||||||
|
}))
|
||||||
|
: _createBlock(_Empty))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: v-for codegen value + key + index 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item, key, index) => {
|
||||||
|
return _createVNode(\\"span\\")
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
@ -1,38 +1,53 @@
|
|||||||
import { parse } from '../../src/parse'
|
import { parse } from '../../src/parse'
|
||||||
import { transform } from '../../src/transform'
|
import { transform } from '../../src/transform'
|
||||||
|
import { transformIf } from '../../src/transforms/vIf'
|
||||||
import { transformFor } from '../../src/transforms/vFor'
|
import { transformFor } from '../../src/transforms/vFor'
|
||||||
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import {
|
import {
|
||||||
ForNode,
|
ForNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
SimpleExpressionNode,
|
SimpleExpressionNode,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
InterpolationNode
|
InterpolationNode,
|
||||||
|
SequenceExpression,
|
||||||
|
CallExpression
|
||||||
} from '../../src/ast'
|
} from '../../src/ast'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
import { ErrorCodes } from '../../src/errors'
|
||||||
import { CompilerOptions } from '../../src'
|
import { CompilerOptions, generate } from '../../src'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
|
import {
|
||||||
|
OPEN_BLOCK,
|
||||||
|
CREATE_BLOCK,
|
||||||
|
FRAGMENT,
|
||||||
|
RENDER_LIST
|
||||||
|
} from '../../src/runtimeConstants'
|
||||||
|
|
||||||
function parseWithForTransform(
|
function parseWithForTransform(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {}
|
||||||
) {
|
) {
|
||||||
const node = parse(template, options)
|
const ast = parse(template, options)
|
||||||
transform(node, {
|
transform(ast, {
|
||||||
nodeTransforms: [
|
nodeTransforms: [
|
||||||
|
transformIf,
|
||||||
transformFor,
|
transformFor,
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : [])
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
|
transformElement
|
||||||
],
|
],
|
||||||
...options
|
...options
|
||||||
})
|
})
|
||||||
return node.children[0]
|
return {
|
||||||
|
root: ast,
|
||||||
|
node: ast.children[0] as ForNode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('compiler: v-for', () => {
|
describe('compiler: v-for', () => {
|
||||||
describe('transform', () => {
|
describe('transform', () => {
|
||||||
test('number expression', () => {
|
test('number expression', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="index in 5" />'
|
'<span v-for="index in 5" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('index')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('index')
|
||||||
@ -40,9 +55,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('value', () => {
|
test('value', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(item) in items" />'
|
'<span v-for="(item) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')
|
||||||
@ -50,9 +65,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('object de-structured value', () => {
|
test('object de-structured value', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="({ id, value }) in items" />'
|
'<span v-for="({ id, value }) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -62,9 +77,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('array de-structured value', () => {
|
test('array de-structured value', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="([ id, value ]) in items" />'
|
'<span v-for="([ id, value ]) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -74,9 +89,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('value and key', () => {
|
test('value and key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(item, key) in items" />'
|
'<span v-for="(item, key) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
@ -85,9 +100,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('value, key and index', () => {
|
test('value, key and index', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(value, key, index) in items" />'
|
'<span v-for="(value, key, index) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
@ -99,9 +114,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('skipped key', () => {
|
test('skipped key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(value,,index) in items" />'
|
'<span v-for="(value,,index) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -112,9 +127,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('skipped value and key', () => {
|
test('skipped value and key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(,,index) in items" />'
|
'<span v-for="(,,index) in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -125,9 +140,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unbracketed value', () => {
|
test('unbracketed value', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="item in items" />'
|
'<span v-for="item in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')
|
||||||
@ -135,9 +150,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unbracketed value and key', () => {
|
test('unbracketed value and key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="item, key in items" />'
|
'<span v-for="item, key in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
@ -146,9 +161,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unbracketed value, key and index', () => {
|
test('unbracketed value, key and index', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="value, key, index in items" />'
|
'<span v-for="value, key, index in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
@ -160,9 +175,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unbracketed skipped key', () => {
|
test('unbracketed skipped key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="value, , index in items" />'
|
'<span v-for="value, , index in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -173,9 +188,9 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unbracketed skipped value and key', () => {
|
test('unbracketed skipped value and key', () => {
|
||||||
const forNode = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for=", , index in items" />'
|
'<span v-for=", , index in items" />'
|
||||||
) as ForNode
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
@ -251,7 +266,7 @@ describe('compiler: v-for', () => {
|
|||||||
describe('source location', () => {
|
describe('source location', () => {
|
||||||
test('value & source', () => {
|
test('value & source', () => {
|
||||||
const source = '<span v-for="item in items" />'
|
const source = '<span v-for="item in items" />'
|
||||||
const forNode = parseWithForTransform(source) as ForNode
|
const { node: forNode } = parseWithForTransform(source)
|
||||||
|
|
||||||
const itemOffset = source.indexOf('item')
|
const itemOffset = source.indexOf('item')
|
||||||
const value = forNode.valueAlias as SimpleExpressionNode
|
const value = forNode.valueAlias as SimpleExpressionNode
|
||||||
@ -275,7 +290,7 @@ describe('compiler: v-for', () => {
|
|||||||
|
|
||||||
test('bracketed value', () => {
|
test('bracketed value', () => {
|
||||||
const source = '<span v-for="( item ) in items" />'
|
const source = '<span v-for="( item ) in items" />'
|
||||||
const forNode = parseWithForTransform(source) as ForNode
|
const { node: forNode } = parseWithForTransform(source)
|
||||||
|
|
||||||
const itemOffset = source.indexOf('item')
|
const itemOffset = source.indexOf('item')
|
||||||
const value = forNode.valueAlias as SimpleExpressionNode
|
const value = forNode.valueAlias as SimpleExpressionNode
|
||||||
@ -299,7 +314,7 @@ describe('compiler: v-for', () => {
|
|||||||
|
|
||||||
test('de-structured value', () => {
|
test('de-structured value', () => {
|
||||||
const source = '<span v-for="( { id, key }) in items" />'
|
const source = '<span v-for="( { id, key }) in items" />'
|
||||||
const forNode = parseWithForTransform(source) as ForNode
|
const { node: forNode } = parseWithForTransform(source)
|
||||||
|
|
||||||
const value = forNode.valueAlias as SimpleExpressionNode
|
const value = forNode.valueAlias as SimpleExpressionNode
|
||||||
const valueIndex = source.indexOf('{ id, key }')
|
const valueIndex = source.indexOf('{ id, key }')
|
||||||
@ -323,7 +338,7 @@ describe('compiler: v-for', () => {
|
|||||||
|
|
||||||
test('bracketed value, key, index', () => {
|
test('bracketed value, key, index', () => {
|
||||||
const source = '<span v-for="( item, key, index ) in items" />'
|
const source = '<span v-for="( item, key, index ) in items" />'
|
||||||
const forNode = parseWithForTransform(source) as ForNode
|
const { node: forNode } = parseWithForTransform(source)
|
||||||
|
|
||||||
const itemOffset = source.indexOf('item')
|
const itemOffset = source.indexOf('item')
|
||||||
const value = forNode.valueAlias as SimpleExpressionNode
|
const value = forNode.valueAlias as SimpleExpressionNode
|
||||||
@ -365,7 +380,7 @@ describe('compiler: v-for', () => {
|
|||||||
|
|
||||||
test('skipped key', () => {
|
test('skipped key', () => {
|
||||||
const source = '<span v-for="( item,, index ) in items" />'
|
const source = '<span v-for="( item,, index ) in items" />'
|
||||||
const forNode = parseWithForTransform(source) as ForNode
|
const { node: forNode } = parseWithForTransform(source)
|
||||||
|
|
||||||
const itemOffset = source.indexOf('item')
|
const itemOffset = source.indexOf('item')
|
||||||
const value = forNode.valueAlias as SimpleExpressionNode
|
const value = forNode.valueAlias as SimpleExpressionNode
|
||||||
@ -399,9 +414,9 @@ describe('compiler: v-for', () => {
|
|||||||
|
|
||||||
describe('prefixIdentifiers: true', () => {
|
describe('prefixIdentifiers: true', () => {
|
||||||
test('should prefix v-for source', () => {
|
test('should prefix v-for source', () => {
|
||||||
const node = parseWithForTransform(`<div v-for="i in list"/>`, {
|
const { node } = parseWithForTransform(`<div v-for="i in list"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true
|
||||||
}) as ForNode
|
})
|
||||||
expect(node.source).toMatchObject({
|
expect(node.source).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.list`
|
content: `_ctx.list`
|
||||||
@ -409,10 +424,10 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix v-for source w/ complex expression', () => {
|
test('should prefix v-for source w/ complex expression', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="i in list.concat([foo])"/>`,
|
`<div v-for="i in list.concat([foo])"/>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ForNode
|
)
|
||||||
expect(node.source).toMatchObject({
|
expect(node.source).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [
|
children: [
|
||||||
@ -427,10 +442,10 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix v-for alias', () => {
|
test('should not prefix v-for alias', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="i in list">{{ i }}{{ j }}</div>`,
|
`<div v-for="i in list">{{ i }}{{ j }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ForNode
|
)
|
||||||
const div = node.children[0] as ElementNode
|
const div = node.children[0] as ElementNode
|
||||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
@ -443,10 +458,10 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix v-for aliases (multiple)', () => {
|
test('should not prefix v-for aliases (multiple)', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`,
|
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ForNode
|
)
|
||||||
const div = node.children[0] as ElementNode
|
const div = node.children[0] as ElementNode
|
||||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
@ -465,10 +480,10 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix id outside of v-for', () => {
|
test('should prefix id outside of v-for', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div><div v-for="i in list" />{{ i }}</div>`,
|
`<div><div v-for="i in list" />{{ i }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ElementNode
|
)
|
||||||
expect((node.children[1] as InterpolationNode).content).toMatchObject({
|
expect((node.children[1] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.i`
|
content: `_ctx.i`
|
||||||
@ -476,12 +491,12 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('nested v-for', () => {
|
test('nested v-for', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<div v-for="i in list">{{ i + j }}</div>{{ i }}
|
<div v-for="i in list">{{ i + j }}</div>{{ i }}
|
||||||
</div>`,
|
</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ForNode
|
)
|
||||||
const outerDiv = node.children[0] as ElementNode
|
const outerDiv = node.children[0] as ElementNode
|
||||||
const innerFor = outerDiv.children[0] as ForNode
|
const innerFor = outerDiv.children[0] as ForNode
|
||||||
const innerExp = (innerFor.children[0] as ElementNode)
|
const innerExp = (innerFor.children[0] as ElementNode)
|
||||||
@ -501,12 +516,12 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('v-for aliases w/ complex expressions', () => {
|
test('v-for aliases w/ complex expressions', () => {
|
||||||
const node = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="({ foo = bar, baz: [qux = quux] }) in list">
|
`<div v-for="({ foo = bar, baz: [qux = quux] }) in list">
|
||||||
{{ foo + bar + baz + qux + quux }}
|
{{ foo + bar + baz + qux + quux }}
|
||||||
</div>`,
|
</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true }
|
||||||
) as ForNode
|
)
|
||||||
expect(node.valueAlias!).toMatchObject({
|
expect(node.valueAlias!).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [
|
children: [
|
||||||
@ -540,8 +555,185 @@ describe('compiler: v-for', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('codegen', () => {
|
describe('codegen', () => {
|
||||||
test('basic v-for', () => {})
|
function assertSharedCodegen(node: SequenceExpression) {
|
||||||
|
expect(node).toMatchObject({
|
||||||
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||||
|
expressions: [
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${OPEN_BLOCK}`,
|
||||||
|
arguments: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${CREATE_BLOCK}`,
|
||||||
|
arguments: [
|
||||||
|
`_${FRAGMENT}`,
|
||||||
|
`null`,
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${RENDER_LIST}`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
return (node.expressions[1] as CallExpression)
|
||||||
|
.arguments[2] as CallExpression
|
||||||
|
}
|
||||||
|
|
||||||
test('', () => {})
|
test('basic v-for', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform('<span v-for="(item) in items" />')
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [{ content: `item` }],
|
||||||
|
returns: {
|
||||||
|
type: NodeTypes.ELEMENT,
|
||||||
|
tag: `span`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('value + key + index', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform('<span v-for="(item, key, index) in items" />')
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [
|
||||||
|
{ content: `item` },
|
||||||
|
{ content: `key` },
|
||||||
|
{ content: `index` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('skipped value', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform('<span v-for="(,key,index) in items" />')
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [{ content: `_` }, { content: `key` }, { content: `index` }]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('skipped key', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform('<span v-for="(value,,index) in items" />')
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [
|
||||||
|
{ content: `value` },
|
||||||
|
{ content: `__` },
|
||||||
|
{ content: `index` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('skipped value & key', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform('<span v-for="(,,index) in items" />')
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [{ content: `_` }, { content: `__` }, { content: `index` }]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('template v-for', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform(
|
||||||
|
'<template v-for="item in items">hello<span/></template>'
|
||||||
|
)
|
||||||
|
expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([
|
||||||
|
{ content: `items` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [{ content: `item` }],
|
||||||
|
returns: [
|
||||||
|
{ type: NodeTypes.TEXT, content: `hello` },
|
||||||
|
{ type: NodeTypes.ELEMENT, tag: `span` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('v-if + v-for', () => {
|
||||||
|
const {
|
||||||
|
root,
|
||||||
|
node: { codegenNode }
|
||||||
|
} = parseWithForTransform(`<div v-if="ok" v-for="i in list"/>`)
|
||||||
|
expect(codegenNode).toMatchObject({
|
||||||
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||||
|
expressions: [
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${OPEN_BLOCK}`,
|
||||||
|
arguments: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
|
test: { content: `ok` },
|
||||||
|
consequent: {
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${CREATE_BLOCK}`,
|
||||||
|
// should optimize v-if + v-for into a single Fragment block
|
||||||
|
arguments: [
|
||||||
|
`_${FRAGMENT}`,
|
||||||
|
`{ key: 0 }`,
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: `_${RENDER_LIST}`,
|
||||||
|
arguments: [
|
||||||
|
{ content: `list` },
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
params: [{ content: `i` }],
|
||||||
|
returns: {
|
||||||
|
type: NodeTypes.ELEMENT,
|
||||||
|
tag: `div`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -54,7 +54,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
codegenNode
|
codegenNode
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!__BROWSER__) {
|
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||||
// scope management
|
// scope management
|
||||||
// inject identifiers to context
|
// inject identifiers to context
|
||||||
value && addIdentifiers(value)
|
value && addIdentifiers(value)
|
||||||
@ -75,6 +75,9 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
}
|
}
|
||||||
if (index) {
|
if (index) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
|
if (!value) {
|
||||||
|
params.push(createSimpleExpression(`_`, false))
|
||||||
|
}
|
||||||
params.push(createSimpleExpression(`__`, false))
|
params.push(createSimpleExpression(`__`, false))
|
||||||
}
|
}
|
||||||
params.push(index)
|
params.push(index)
|
||||||
@ -95,7 +98,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!__BROWSER__) {
|
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||||
value && removeIdentifiers(value)
|
value && removeIdentifiers(value)
|
||||||
key && removeIdentifiers(key)
|
key && removeIdentifiers(key)
|
||||||
index && removeIdentifiers(index)
|
index && removeIdentifiers(index)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user