refactor(compiler): separate Interpolation, SimpleExpression & CompoundExpression types

This commit is contained in:
Evan You
2019-09-27 11:42:02 -04:00
parent d491a022a7
commit d900c13efb
25 changed files with 947 additions and 650 deletions

View File

@@ -232,7 +232,7 @@ Object {
},
},
"name": "attr",
"type": 5,
"type": 6,
"value": Object {
"content": "c",
"isEmpty": false,
@@ -315,7 +315,7 @@ Object {
},
},
"name": "attr",
"type": 5,
"type": 6,
"value": Object {
"content": "&#a;",
"isEmpty": false,
@@ -398,7 +398,7 @@ Object {
},
},
"name": "attr",
"type": 5,
"type": 6,
"value": Object {
"content": "ÿ",
"isEmpty": false,
@@ -481,7 +481,7 @@ Object {
},
},
"name": "attr",
"type": 5,
"type": 6,
"value": Object {
"content": "&#xg;",
"isEmpty": false,
@@ -1183,7 +1183,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "",
"isEmpty": true,
@@ -1218,7 +1218,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "",
"isEmpty": true,
@@ -2359,7 +2359,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -2449,7 +2449,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -2539,7 +2539,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -2629,7 +2629,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -2736,7 +2736,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -2843,7 +2843,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -2950,7 +2950,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -3057,7 +3057,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -3164,7 +3164,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -3271,7 +3271,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -3378,7 +3378,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "abc",
"isEmpty": false,
@@ -3884,23 +3884,38 @@ Object {
Object {
"children": Array [
Object {
"content": "a < b",
"isInterpolation": true,
"isStatic": false,
"content": Object {
"content": "a < b",
"isStatic": false,
"loc": Object {
"end": Object {
"column": 18,
"line": 1,
"offset": 17,
},
"source": "a < b",
"start": Object {
"column": 13,
"line": 1,
"offset": 12,
},
},
"type": 4,
},
"loc": Object {
"end": Object {
"column": 18,
"column": 20,
"line": 1,
"offset": 17,
"offset": 19,
},
"source": "a < b",
"source": "{{a < b}}",
"start": Object {
"column": 13,
"column": 11,
"line": 1,
"offset": 12,
"offset": 10,
},
},
"type": 4,
"type": 5,
},
],
"codegenNode": undefined,
@@ -4133,7 +4148,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "/",
"isEmpty": false,
@@ -4240,7 +4255,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -4330,7 +4345,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -4666,7 +4681,7 @@ class=\\"bar\\"></div>",
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "foo",
"isEmpty": false,
@@ -4701,7 +4716,7 @@ class=\\"bar\\"></div>",
},
},
"name": "class",
"type": 5,
"type": 6,
"value": Object {
"content": "bar",
"isEmpty": false,
@@ -4810,7 +4825,7 @@ Object {
},
},
"name": "id",
"type": 5,
"type": 6,
"value": Object {
"content": "foo",
"isEmpty": false,
@@ -4845,7 +4860,7 @@ Object {
},
},
"name": "class",
"type": 5,
"type": 6,
"value": Object {
"content": "bar",
"isEmpty": false,
@@ -5476,7 +5491,7 @@ Object {
},
},
"name": "a\\"bc",
"type": 5,
"type": 6,
"value": Object {
"content": "",
"isEmpty": true,
@@ -5583,7 +5598,7 @@ Object {
},
},
"name": "a'bc",
"type": 5,
"type": 6,
"value": Object {
"content": "",
"isEmpty": true,
@@ -5690,7 +5705,7 @@ Object {
},
},
"name": "a<bc",
"type": 5,
"type": 6,
"value": Object {
"content": "",
"isEmpty": true,
@@ -5797,7 +5812,7 @@ Object {
},
},
"name": "foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar\\"",
"isEmpty": false,
@@ -5904,7 +5919,7 @@ Object {
},
},
"name": "foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar'",
"isEmpty": false,
@@ -6011,7 +6026,7 @@ Object {
},
},
"name": "foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar<div",
"isEmpty": false,
@@ -6118,7 +6133,7 @@ Object {
},
},
"name": "foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar=baz",
"isEmpty": false,
@@ -6225,7 +6240,7 @@ Object {
},
},
"name": "foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar\`",
"isEmpty": false,
@@ -6332,7 +6347,7 @@ Object {
},
},
"name": "=",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -6422,7 +6437,7 @@ Object {
},
},
"name": "=foo",
"type": 5,
"type": 6,
"value": Object {
"content": "bar",
"isEmpty": false,
@@ -6594,7 +6609,7 @@ Object {
},
},
"name": "a",
"type": 5,
"type": 6,
"value": undefined,
},
Object {
@@ -6612,7 +6627,7 @@ Object {
},
},
"name": "b",
"type": 5,
"type": 6,
"value": undefined,
},
],
@@ -6960,23 +6975,38 @@ Object {
Object {
"children": Array [
Object {
"content": "'</div>'",
"isInterpolation": true,
"isStatic": false,
"content": Object {
"content": "'</div>'",
"isStatic": false,
"loc": Object {
"end": Object {
"column": 21,
"line": 1,
"offset": 20,
},
"source": "'</div>'",
"start": Object {
"column": 13,
"line": 1,
"offset": 12,
},
},
"type": 4,
},
"loc": Object {
"end": Object {
"column": 21,
"column": 23,
"line": 1,
"offset": 20,
"offset": 22,
},
"source": "'</div>'",
"source": "{{'</div>'}}",
"start": Object {
"column": 13,
"column": 11,
"line": 1,
"offset": 12,
"offset": 10,
},
},
"type": 4,
"type": 5,
},
],
"codegenNode": undefined,
@@ -7317,23 +7347,38 @@ exports[`compiler: parse Errors X_MISSING_INTERPOLATION_END {{}} 1`] = `
Object {
"children": Array [
Object {
"content": "",
"isInterpolation": true,
"isStatic": true,
"content": Object {
"content": "",
"isStatic": false,
"loc": Object {
"end": Object {
"column": 3,
"line": 1,
"offset": 2,
},
"source": "",
"start": Object {
"column": 3,
"line": 1,
"offset": 2,
},
},
"type": 4,
},
"loc": Object {
"end": Object {
"column": 3,
"column": 5,
"line": 1,
"offset": 2,
"offset": 4,
},
"source": "",
"source": "{{}}",
"start": Object {
"column": 3,
"column": 1,
"line": 1,
"offset": 2,
"offset": 0,
},
},
"type": 4,
"type": 5,
},
],
"hoists": Array [],
@@ -7458,7 +7503,6 @@ Object {
Object {
"arg": Object {
"content": "class",
"isInterpolation": false,
"isStatic": true,
"loc": Object {
"end": Object {
@@ -7477,7 +7521,6 @@ Object {
},
"exp": Object {
"content": "{ some: condition }",
"isInterpolation": false,
"isStatic": false,
"loc": Object {
"end": Object {
@@ -7509,7 +7552,7 @@ Object {
},
"modifiers": Array [],
"name": "bind",
"type": 6,
"type": 7,
},
],
"tag": "div",
@@ -7538,7 +7581,6 @@ Object {
Object {
"arg": Object {
"content": "style",
"isInterpolation": false,
"isStatic": true,
"loc": Object {
"end": Object {
@@ -7557,7 +7599,6 @@ Object {
},
"exp": Object {
"content": "{ color: 'red' }",
"isInterpolation": false,
"isStatic": false,
"loc": Object {
"end": Object {
@@ -7589,7 +7630,7 @@ Object {
},
"modifiers": Array [],
"name": "bind",
"type": 6,
"type": 7,
},
],
"tag": "p",
@@ -7645,7 +7686,6 @@ Object {
Object {
"arg": Object {
"content": "style",
"isInterpolation": false,
"isStatic": true,
"loc": Object {
"end": Object {
@@ -7664,7 +7704,6 @@ Object {
},
"exp": Object {
"content": "{ color: 'red' }",
"isInterpolation": false,
"isStatic": false,
"loc": Object {
"end": Object {
@@ -7696,7 +7735,7 @@ Object {
},
"modifiers": Array [],
"name": "bind",
"type": 6,
"type": 7,
},
],
"tag": "p",
@@ -7744,7 +7783,6 @@ Object {
Object {
"arg": Object {
"content": "class",
"isInterpolation": false,
"isStatic": true,
"loc": Object {
"end": Object {
@@ -7763,7 +7801,6 @@ Object {
},
"exp": Object {
"content": "{ some: condition }",
"isInterpolation": false,
"isStatic": false,
"loc": Object {
"end": Object {
@@ -7795,7 +7832,7 @@ Object {
},
"modifiers": Array [],
"name": "bind",
"type": 6,
"type": 7,
},
],
"tag": "div",

View File

@@ -3,14 +3,16 @@ import {
NodeTypes,
RootNode,
SourceLocation,
createExpression,
createSimpleExpression,
Namespaces,
ElementTypes,
CallExpression,
createObjectExpression,
createObjectProperty,
createArrayExpression,
ElementNode
ElementNode,
createCompoundExpression,
createInterpolation
} from '../src'
import {
CREATE_VNODE,
@@ -93,12 +95,12 @@ describe('compiler: codegen', () => {
test('hoists', () => {
const root = createRoot({
hoists: [
createExpression(`hello`, false, mockLoc),
createSimpleExpression(`hello`, false, mockLoc),
createObjectExpression(
[
createObjectProperty(
createExpression(`id`, true, mockLoc),
createExpression(`foo`, true, mockLoc),
createSimpleExpression(`id`, true, mockLoc),
createSimpleExpression(`foo`, true, mockLoc),
mockLoc
)
],
@@ -138,7 +140,7 @@ describe('compiler: codegen', () => {
test('interpolation', () => {
const { code } = generate(
createRoot({
children: [createExpression(`hello`, false, mockLoc, true)]
children: [createInterpolation(`hello`, mockLoc)]
})
)
expect(code).toMatch(`return _${TO_STRING}(hello)`)
@@ -171,7 +173,7 @@ describe('compiler: codegen', () => {
isEmpty: false,
loc: mockLoc
},
createExpression(`hello`, false, mockLoc, true),
createInterpolation(`hello`, mockLoc),
{
type: NodeTypes.COMMENT,
content: 'foo',
@@ -199,7 +201,7 @@ describe('compiler: codegen', () => {
isEmpty: false,
loc: mockLoc
},
createExpression(`hello`, false, mockLoc, true),
createInterpolation(`hello`, mockLoc),
{
type: NodeTypes.COMMENT,
content: 'foo',
@@ -224,14 +226,13 @@ describe('compiler: codegen', () => {
const { code } = generate(
createRoot({
children: [
{
type: NodeTypes.EXPRESSION,
content: 'foo',
isStatic: false,
isInterpolation: true,
loc: mockLoc,
children: [`_ctx.`, createExpression(`foo`, false, mockLoc)]
}
createInterpolation(
createCompoundExpression(
[`_ctx.`, createSimpleExpression(`foo`, false, mockLoc)],
mockLoc
),
mockLoc
)
]
})
)
@@ -249,7 +250,7 @@ describe('compiler: codegen', () => {
branches: [
{
type: NodeTypes.IF_BRANCH,
condition: createExpression('foo', false, mockLoc),
condition: createSimpleExpression('foo', false, mockLoc),
loc: mockLoc,
children: [
{
@@ -262,9 +263,9 @@ describe('compiler: codegen', () => {
},
{
type: NodeTypes.IF_BRANCH,
condition: createExpression('a + b', false, mockLoc),
condition: createSimpleExpression('a + b', false, mockLoc),
loc: mockLoc,
children: [createExpression(`bye`, false, mockLoc, true)]
children: [createInterpolation(`bye`, mockLoc)]
},
{
type: NodeTypes.IF_BRANCH,
@@ -302,7 +303,7 @@ describe('compiler: codegen', () => {
branches: [
{
type: NodeTypes.IF_BRANCH,
condition: createExpression('foo', false, mockLoc),
condition: createSimpleExpression('foo', false, mockLoc),
loc: mockLoc,
children: [
{
@@ -315,9 +316,9 @@ describe('compiler: codegen', () => {
},
{
type: NodeTypes.IF_BRANCH,
condition: createExpression('a + b', false, mockLoc),
condition: createSimpleExpression('a + b', false, mockLoc),
loc: mockLoc,
children: [createExpression(`bye`, false, mockLoc, true)]
children: [createInterpolation(`bye`, mockLoc)]
}
]
}
@@ -340,11 +341,11 @@ describe('compiler: codegen', () => {
{
type: NodeTypes.FOR,
loc: mockLoc,
source: createExpression(`list`, false, mockLoc),
valueAlias: createExpression(`v`, false, mockLoc),
keyAlias: createExpression(`k`, false, mockLoc),
objectIndexAlias: createExpression(`i`, false, mockLoc),
children: [createExpression(`v`, false, mockLoc, true)]
source: createSimpleExpression(`list`, false, mockLoc),
valueAlias: createSimpleExpression(`v`, false, mockLoc),
keyAlias: createSimpleExpression(`k`, false, mockLoc),
objectIndexAlias: createSimpleExpression(`i`, false, mockLoc),
children: [createInterpolation(`v`, mockLoc)]
}
]
})
@@ -364,11 +365,11 @@ describe('compiler: codegen', () => {
{
type: NodeTypes.FOR,
loc: mockLoc,
source: createExpression(`list`, false, mockLoc),
valueAlias: createExpression(`v`, false, mockLoc),
keyAlias: createExpression(`k`, false, mockLoc),
objectIndexAlias: createExpression(`i`, false, mockLoc),
children: [createExpression(`v`, false, mockLoc, true)]
source: createSimpleExpression(`list`, false, mockLoc),
valueAlias: createSimpleExpression(`v`, false, mockLoc),
keyAlias: createSimpleExpression(`k`, false, mockLoc),
objectIndexAlias: createSimpleExpression(`i`, false, mockLoc),
children: [createInterpolation(`v`, mockLoc)]
}
]
}),
@@ -391,11 +392,11 @@ describe('compiler: codegen', () => {
{
type: NodeTypes.FOR,
loc: mockLoc,
source: createExpression(`list`, false, mockLoc),
source: createSimpleExpression(`list`, false, mockLoc),
valueAlias: undefined,
keyAlias: createExpression(`k`, false, mockLoc),
objectIndexAlias: createExpression(`i`, false, mockLoc),
children: [createExpression(`v`, false, mockLoc, true)]
keyAlias: createSimpleExpression(`k`, false, mockLoc),
objectIndexAlias: createSimpleExpression(`i`, false, mockLoc),
children: [createInterpolation(`v`, mockLoc)]
}
]
})
@@ -415,11 +416,11 @@ describe('compiler: codegen', () => {
{
type: NodeTypes.FOR,
loc: mockLoc,
source: createExpression(`list`, false, mockLoc),
valueAlias: createExpression(`v`, false, mockLoc),
source: createSimpleExpression(`list`, false, mockLoc),
valueAlias: createSimpleExpression(`v`, false, mockLoc),
keyAlias: undefined,
objectIndexAlias: createExpression(`i`, false, mockLoc),
children: [createExpression(`v`, false, mockLoc, true)]
objectIndexAlias: createSimpleExpression(`i`, false, mockLoc),
children: [createInterpolation(`v`, mockLoc)]
}
]
})
@@ -439,11 +440,11 @@ describe('compiler: codegen', () => {
{
type: NodeTypes.FOR,
loc: mockLoc,
source: createExpression(`list`, false, mockLoc),
source: createSimpleExpression(`list`, false, mockLoc),
valueAlias: undefined,
keyAlias: undefined,
objectIndexAlias: createExpression(`i`, false, mockLoc),
children: [createExpression(`v`, false, mockLoc, true)]
objectIndexAlias: createSimpleExpression(`i`, false, mockLoc),
children: [createInterpolation(`v`, mockLoc)]
}
]
})
@@ -488,29 +489,26 @@ describe('compiler: codegen', () => {
createObjectExpression(
[
createObjectProperty(
createExpression(`id`, true, mockLoc),
createExpression(`foo`, true, mockLoc),
createSimpleExpression(`id`, true, mockLoc),
createSimpleExpression(`foo`, true, mockLoc),
mockLoc
),
createObjectProperty(
createExpression(`prop`, false, mockLoc),
createExpression(`bar`, false, mockLoc),
createSimpleExpression(`prop`, false, mockLoc),
createSimpleExpression(`bar`, false, mockLoc),
mockLoc
),
// compound expression as computed key
createObjectProperty(
{
type: NodeTypes.EXPRESSION,
content: ``,
type: NodeTypes.COMPOUND_EXPRESSION,
loc: mockLoc,
isStatic: false,
isInterpolation: false,
children: [
`foo + `,
createExpression(`bar`, false, mockLoc)
createSimpleExpression(`bar`, false, mockLoc)
]
},
createExpression(`bar`, false, mockLoc),
createSimpleExpression(`bar`, false, mockLoc),
mockLoc
)
],
@@ -524,8 +522,8 @@ describe('compiler: codegen', () => {
[
createObjectProperty(
// should quote the key!
createExpression(`some-key`, true, mockLoc),
createExpression(`foo`, true, mockLoc),
createSimpleExpression(`some-key`, true, mockLoc),
createSimpleExpression(`foo`, true, mockLoc),
mockLoc
)
],

View File

@@ -4,12 +4,12 @@ import {
CommentNode,
ElementNode,
ElementTypes,
ExpressionNode,
Namespaces,
NodeTypes,
Position,
TextNode,
AttributeNode
AttributeNode,
InterpolationNode
} from '../src/ast'
describe('compiler: parse', () => {
@@ -290,63 +290,92 @@ describe('compiler: parse', () => {
describe('Interpolation', () => {
test('simple interpolation', () => {
const ast = parse('{{message}}')
const interpolation = ast.children[0] as ExpressionNode
const interpolation = ast.children[0] as InterpolationNode
expect(interpolation).toStrictEqual({
type: NodeTypes.EXPRESSION,
content: 'message',
isStatic: false,
isInterpolation: true,
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `message`,
isStatic: false,
loc: {
start: { offset: 2, line: 1, column: 3 },
end: { offset: 9, line: 1, column: 10 },
source: `message`
}
},
loc: {
start: { offset: 2, line: 1, column: 3 },
end: { offset: 9, line: 1, column: 10 },
source: 'message'
start: { offset: 0, line: 1, column: 1 },
end: { offset: 11, line: 1, column: 12 },
source: '{{message}}'
}
})
})
test('it can have tag-like notation', () => {
const ast = parse('{{ a<b }}')
const interpolation = ast.children[0] as ExpressionNode
const interpolation = ast.children[0] as InterpolationNode
expect(interpolation).toStrictEqual({
type: NodeTypes.EXPRESSION,
content: 'a<b',
isStatic: false,
isInterpolation: true,
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `a<b`,
isStatic: false,
loc: {
start: { offset: 3, line: 1, column: 4 },
end: { offset: 6, line: 1, column: 7 },
source: 'a<b'
}
},
loc: {
start: { offset: 3, line: 1, column: 4 },
end: { offset: 6, line: 1, column: 7 },
source: 'a<b'
start: { offset: 0, line: 1, column: 1 },
end: { offset: 9, line: 1, column: 10 },
source: '{{ a<b }}'
}
})
})
test('it can have tag-like notation (2)', () => {
const ast = parse('{{ a<b }}{{ c>d }}')
const interpolation1 = ast.children[0] as ExpressionNode
const interpolation2 = ast.children[1] as ExpressionNode
const interpolation1 = ast.children[0] as InterpolationNode
const interpolation2 = ast.children[1] as InterpolationNode
expect(interpolation1).toStrictEqual({
type: NodeTypes.EXPRESSION,
content: 'a<b',
isStatic: false,
isInterpolation: true,
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `a<b`,
isStatic: false,
loc: {
start: { offset: 3, line: 1, column: 4 },
end: { offset: 6, line: 1, column: 7 },
source: 'a<b'
}
},
loc: {
start: { offset: 3, line: 1, column: 4 },
end: { offset: 6, line: 1, column: 7 },
source: 'a<b'
start: { offset: 0, line: 1, column: 1 },
end: { offset: 9, line: 1, column: 10 },
source: '{{ a<b }}'
}
})
expect(interpolation2).toStrictEqual({
type: NodeTypes.EXPRESSION,
content: 'c>d',
isStatic: false,
isInterpolation: true,
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
isStatic: false,
content: 'c>d',
loc: {
start: { offset: 12, line: 1, column: 13 },
end: { offset: 15, line: 1, column: 16 },
source: 'c>d'
}
},
loc: {
start: { offset: 12, line: 1, column: 13 },
end: { offset: 15, line: 1, column: 16 },
source: 'c>d'
start: { offset: 9, line: 1, column: 10 },
end: { offset: 18, line: 1, column: 19 },
source: '{{ c>d }}'
}
})
})
@@ -354,17 +383,24 @@ describe('compiler: parse', () => {
test('it can have tag-like notation (3)', () => {
const ast = parse('<div>{{ "</div>" }}</div>')
const element = ast.children[0] as ElementNode
const interpolation = element.children[0] as ExpressionNode
const interpolation = element.children[0] as InterpolationNode
expect(interpolation).toStrictEqual({
type: NodeTypes.EXPRESSION,
content: '"</div>"',
isStatic: false,
isInterpolation: true,
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
isStatic: false,
content: '"</div>"',
loc: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 16, line: 1, column: 17 },
source: '"</div>"'
}
},
loc: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 16, line: 1, column: 17 },
source: '"</div>"'
start: { offset: 5, line: 1, column: 6 },
end: { offset: 19, line: 1, column: 20 },
source: '{{ "</div>" }}'
}
})
})
@@ -889,10 +925,9 @@ describe('compiler: parse', () => {
arg: undefined,
modifiers: [],
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'a',
isStatic: false,
isInterpolation: false,
loc: {
start: { offset: 11, line: 1, column: 12 },
end: { offset: 12, line: 1, column: 13 },
@@ -915,10 +950,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'on',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'click',
isStatic: true,
isInterpolation: false,
loc: {
source: 'click',
start: {
@@ -987,10 +1022,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'on',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'click',
isStatic: true,
isInterpolation: false,
loc: {
source: 'click',
start: {
@@ -1023,10 +1058,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'bind',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'a',
isStatic: true,
isInterpolation: false,
loc: {
source: 'a',
start: {
@@ -1043,10 +1078,10 @@ describe('compiler: parse', () => {
},
modifiers: [],
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b',
isStatic: false,
isInterpolation: false,
loc: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 9, line: 1, column: 10 },
@@ -1069,10 +1104,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'bind',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'a',
isStatic: true,
isInterpolation: false,
loc: {
source: 'a',
start: {
@@ -1089,10 +1124,10 @@ describe('compiler: parse', () => {
},
modifiers: ['sync'],
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b',
isStatic: false,
isInterpolation: false,
loc: {
start: { offset: 13, line: 1, column: 14 },
end: { offset: 14, line: 1, column: 15 },
@@ -1115,10 +1150,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'on',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'a',
isStatic: true,
isInterpolation: false,
loc: {
source: 'a',
start: {
@@ -1135,10 +1170,10 @@ describe('compiler: parse', () => {
},
modifiers: [],
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b',
isStatic: false,
isInterpolation: false,
loc: {
start: { offset: 8, line: 1, column: 9 },
end: { offset: 9, line: 1, column: 10 },
@@ -1161,10 +1196,10 @@ describe('compiler: parse', () => {
type: NodeTypes.DIRECTIVE,
name: 'on',
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'a',
isStatic: true,
isInterpolation: false,
loc: {
source: 'a',
start: {
@@ -1181,10 +1216,10 @@ describe('compiler: parse', () => {
},
modifiers: ['enter'],
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b',
isStatic: false,
isInterpolation: false,
loc: {
start: { offset: 14, line: 1, column: 15 },
end: { offset: 15, line: 1, column: 16 },
@@ -1313,20 +1348,27 @@ foo
offset += foo.loc.source.length
expect(foo.loc.end).toEqual({ line: 2, column: 5, offset })
expect(bar.loc.start).toEqual({ line: 2, column: 5, offset })
const barInner = (bar as InterpolationNode).content
offset += 3
expect(bar.loc.start).toEqual({ line: 2, column: 8, offset })
offset += bar.loc.source.length
expect(bar.loc.end).toEqual({ line: 2, column: 11, offset })
expect(barInner.loc.start).toEqual({ line: 2, column: 8, offset })
offset += barInner.loc.source.length
expect(barInner.loc.end).toEqual({ line: 2, column: 11, offset })
offset += 3
expect(bar.loc.end).toEqual({ line: 2, column: 14, offset })
expect(but.loc.start).toEqual({ line: 2, column: 14, offset })
offset += but.loc.source.length
expect(but.loc.end).toEqual({ line: 2, column: 19, offset })
expect(baz.loc.start).toEqual({ line: 2, column: 19, offset })
const bazInner = (baz as InterpolationNode).content
offset += 3
expect(baz.loc.start).toEqual({ line: 2, column: 22, offset })
offset += baz.loc.source.length
expect(baz.loc.end).toEqual({ line: 2, column: 25, offset })
expect(bazInner.loc.start).toEqual({ line: 2, column: 22, offset })
offset += bazInner.loc.source.length
expect(bazInner.loc.end).toEqual({ line: 2, column: 25, offset })
offset += 3
expect(baz.loc.end).toEqual({ line: 2, column: 28, offset })
})
describe('namedCharacterReferences option', () => {

View File

@@ -52,12 +52,12 @@ function createStaticObjectMatcher(obj: any) {
properties: Object.keys(obj).map(key => ({
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: key,
isStatic: true
},
value: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: obj[key],
isStatic: true
}
@@ -87,7 +87,7 @@ describe('compiler: element transform', () => {
expect(node.arguments).toMatchObject([
`"div"`,
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`
}
])
@@ -106,7 +106,7 @@ describe('compiler: element transform', () => {
expect(node.arguments).toMatchObject([
`"div"`,
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`
},
[
@@ -148,7 +148,7 @@ describe('compiler: element transform', () => {
expect(node.callee).toBe(`_${CREATE_VNODE}`)
// should directly use `obj` in props position
expect(node.arguments[1]).toMatchObject({
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
})
})
@@ -167,7 +167,7 @@ describe('compiler: element transform', () => {
id: 'foo'
}),
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
}
]
@@ -185,7 +185,7 @@ describe('compiler: element transform', () => {
callee: `_${MERGE_PROPS}`,
arguments: [
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
},
createStaticObjectMatcher({
@@ -209,7 +209,7 @@ describe('compiler: element transform', () => {
id: 'foo'
}),
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
},
createStaticObjectMatcher({
@@ -237,7 +237,7 @@ describe('compiler: element transform', () => {
callee: `_${TO_HANDLERS}`,
arguments: [
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
}
]
@@ -267,13 +267,13 @@ describe('compiler: element transform', () => {
callee: `_${TO_HANDLERS}`,
arguments: [
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `handlers`
}
]
},
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `obj`
}
]
@@ -363,14 +363,13 @@ describe('compiler: element transform', () => {
`_directive_foo`,
// exp
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `hello`,
isStatic: false,
isInterpolation: false
isStatic: false
},
// arg
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `bar`,
isStatic: true
}
@@ -408,7 +407,7 @@ describe('compiler: element transform', () => {
`_directive_bar`,
// exp
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `x`
}
]
@@ -419,14 +418,13 @@ describe('compiler: element transform', () => {
`_directive_baz`,
// exp
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `y`,
isStatic: false,
isInterpolation: false
isStatic: false
},
// arg
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `arg`,
isStatic: false
},
@@ -437,12 +435,12 @@ describe('compiler: element transform', () => {
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `mod`,
isStatic: true
},
value: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `true`,
isStatic: false
}
@@ -450,12 +448,12 @@ describe('compiler: element transform', () => {
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `mad`,
isStatic: true
},
value: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `true`,
isStatic: false
}
@@ -484,7 +482,7 @@ describe('compiler: element transform', () => {
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `onClick`,
isStatic: true
},
@@ -492,12 +490,12 @@ describe('compiler: element transform', () => {
type: NodeTypes.JS_ARRAY_EXPRESSION,
elements: [
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `a`,
isStatic: false
},
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `b`,
isStatic: false
}
@@ -524,7 +522,7 @@ describe('compiler: element transform', () => {
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `style`,
isStatic: true
},
@@ -532,12 +530,12 @@ describe('compiler: element transform', () => {
type: NodeTypes.JS_ARRAY_EXPRESSION,
elements: [
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`,
isStatic: false
},
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `{ color: 'red' }`,
isStatic: false
}

View File

@@ -1,13 +1,13 @@
import {
parse,
transform,
ExpressionNode,
ElementNode,
DirectiveNode,
NodeTypes,
ForNode,
CompilerOptions,
IfNode
IfNode,
InterpolationNode
} from '../../src'
import { transformIf } from '../../src/transforms/vIf'
import { transformFor } from '../../src/transforms/vFor'
@@ -28,28 +28,58 @@ function parseWithExpressionTransform(
describe('compiler: expression transform', () => {
test('interpolation (root)', () => {
const node = parseWithExpressionTransform(`{{ foo }}`) as ExpressionNode
expect(node.children).toBeUndefined()
expect(node.content).toBe(`_ctx.foo`)
const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.foo`
})
})
test('interpolation (children)', () => {
const el = parseWithExpressionTransform(
`<div>{{ foo }}</div>`
) as ElementNode
const node = el.children[0] as ExpressionNode
expect(node.children).toBeUndefined()
expect(node.content).toBe(`_ctx.foo`)
const node = el.children[0] as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.foo`
})
})
test('interpolation (complex)', () => {
const el = parseWithExpressionTransform(
`<div>{{ foo + bar(baz.qux) }}</div>`
) as ElementNode
const node = el.children[0] as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `_ctx.foo` },
` + `,
{ content: `_ctx.bar` },
`(`,
{ content: `_ctx.baz` },
`.`,
{ content: `qux` },
`)`
]
})
})
test('directive value', () => {
const node = parseWithExpressionTransform(
`<div v-foo:arg="baz"/>`
) as ElementNode
expect((node.props[0] as DirectiveNode).arg!.children).toBeUndefined()
const arg = (node.props[0] as DirectiveNode).arg!
expect(arg).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `arg`
})
const exp = (node.props[0] as DirectiveNode).exp!
expect(exp.children).toBeUndefined()
expect(exp.content).toBe(`_ctx.baz`)
expect(exp).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.baz`
})
})
test('dynamic directive arg', () => {
@@ -57,85 +87,113 @@ describe('compiler: expression transform', () => {
`<div v-foo:[arg]="baz"/>`
) as ElementNode
const arg = (node.props[0] as DirectiveNode).arg!
expect(arg).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.arg`
})
const exp = (node.props[0] as DirectiveNode).exp!
expect(arg.children).toBeUndefined()
expect(arg.content).toBe(`_ctx.arg`)
expect(exp.children).toBeUndefined()
expect(exp.content).toBe(`_ctx.baz`)
expect(exp).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.baz`
})
})
test('should prefix complex expressions', () => {
const node = parseWithExpressionTransform(
`{{ foo(baz + 1, { key: kuz }) }}`
) as ExpressionNode
) as InterpolationNode
// should parse into compound expression
expect(node.children).toMatchObject([
{
content: `_ctx.foo`,
loc: {
source: `foo`,
start: {
offset: 3,
line: 1,
column: 4
},
end: {
offset: 6,
line: 1,
column: 7
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{
content: `_ctx.foo`,
loc: {
source: `foo`,
start: {
offset: 3,
line: 1,
column: 4
},
end: {
offset: 6,
line: 1,
column: 7
}
}
}
},
`(`,
{
content: `_ctx.baz`,
loc: {
source: `baz`,
start: {
offset: 7,
line: 1,
column: 8
},
end: {
offset: 10,
line: 1,
column: 11
},
`(`,
{
content: `_ctx.baz`,
loc: {
source: `baz`,
start: {
offset: 7,
line: 1,
column: 8
},
end: {
offset: 10,
line: 1,
column: 11
}
}
}
},
` + 1, { key: `,
{
content: `_ctx.kuz`,
loc: {
source: `kuz`,
start: {
offset: 23,
line: 1,
column: 24
},
end: {
offset: 26,
line: 1,
column: 27
},
` + 1, { key: `,
{
content: `_ctx.kuz`,
loc: {
source: `kuz`,
start: {
offset: 23,
line: 1,
column: 24
},
end: {
offset: 26,
line: 1,
column: 27
}
}
}
},
` })`
])
},
` })`
]
})
})
test('should prefix v-if condition', () => {
const node = parseWithExpressionTransform(`<div v-if="ok"/>`) as IfNode
expect(node.branches[0].condition!.children).toBeUndefined()
expect(node.branches[0].condition!.content).toBe(`_ctx.ok`)
expect(node.branches[0].condition).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.ok`
})
})
test('should prefix v-for source', () => {
const node = parseWithExpressionTransform(
`<div v-for="i in list"/>`
) as ForNode
expect(node.source.children).toBeUndefined()
expect(node.source.content).toBe(`_ctx.list`)
expect(node.source).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.list`
})
})
test('should prefix v-for source w/ complex expression', () => {
const node = parseWithExpressionTransform(
`<div v-for="i in list.concat([foo])"/>`
) as ForNode
expect(node.source).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `_ctx.list` },
`.`,
{ content: `concat` },
`([`,
{ content: `_ctx.foo` },
`])`
]
})
})
test('should not prefix v-for alias', () => {
@@ -143,16 +201,14 @@ describe('compiler: expression transform', () => {
`<div v-for="i in list">{{ i }}{{ j }}</div>`
) as ForNode
const div = node.children[0] as ElementNode
const i = div.children[0] as ExpressionNode
expect(i.type).toBe(NodeTypes.EXPRESSION)
expect(i.content).toBe(`i`)
expect(i.children).toBeUndefined()
const j = div.children[1] as ExpressionNode
expect(j.type).toBe(NodeTypes.EXPRESSION)
expect(j.children).toBeUndefined()
expect(j.content).toBe(`_ctx.j`)
expect((div.children[0] as InterpolationNode).content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `i`
})
expect((div.children[1] as InterpolationNode).content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.j`
})
})
test('should not prefix v-for aliases (multiple)', () => {
@@ -160,32 +216,30 @@ describe('compiler: expression transform', () => {
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`
) as ForNode
const div = node.children[0] as ElementNode
const exp = div.children[0] as ExpressionNode
expect(exp.type).toBe(NodeTypes.EXPRESSION)
// parsed for better source-map support
expect(exp.children).toMatchObject([
{ content: `i` },
` + `,
{ content: `j` },
` + `,
{ content: `k` }
])
const l = div.children[1] as ExpressionNode
expect(l.type).toBe(NodeTypes.EXPRESSION)
expect(l.children).toBeUndefined()
expect(l.content).toBe(`_ctx.l`)
expect((div.children[0] as InterpolationNode).content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `i` },
` + `,
{ content: `j` },
` + `,
{ content: `k` }
]
})
expect((div.children[1] as InterpolationNode).content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.l`
})
})
test('should prefix id outside of v-for', () => {
const node = parseWithExpressionTransform(
`<div><div v-for="i in list" />{{ i }}</div>`
) as ElementNode
const exp = node.children[1] as ExpressionNode
expect(exp.type).toBe(NodeTypes.EXPRESSION)
expect(exp.children).toBeUndefined()
expect(exp.content).toBe(`_ctx.i`)
expect((node.children[1] as InterpolationNode).content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.i`
})
})
test('nested v-for', () => {
@@ -197,123 +251,130 @@ describe('compiler: expression transform', () => {
const outerDiv = node.children[0] as ElementNode
const innerFor = outerDiv.children[0] as ForNode
const innerExp = (innerFor.children[0] as ElementNode)
.children[0] as ExpressionNode
expect(innerExp.type).toBe(NodeTypes.EXPRESSION)
expect(innerExp.children).toMatchObject([
{ content: 'i' },
` + `,
{ content: `_ctx.j` }
])
.children[0] as InterpolationNode
expect(innerExp.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [{ content: 'i' }, ` + `, { content: `_ctx.j` }]
})
// when an inner v-for shadows a variable of an outer v-for and exit,
// it should not cause the outer v-for's alias to be removed from known ids
const outerExp = outerDiv.children[1] as ExpressionNode
expect(outerExp.type).toBe(NodeTypes.EXPRESSION)
expect(outerExp.content).toBe(`i`)
expect(outerExp.children).toBeUndefined()
const outerExp = outerDiv.children[1] as InterpolationNode
expect(outerExp.content).toMatchObject({
type: NodeTypes.SIMPLE_EXPRESSION,
content: `i`
})
})
test('should not prefix whitelisted globals', () => {
const node = parseWithExpressionTransform(
`{{ Math.max(1, 2) }}`
) as ExpressionNode
expect(node.type).toBe(NodeTypes.EXPRESSION)
expect(node.children).toMatchObject([
{ content: `Math` },
`.`,
{ content: `max` },
`(1, 2)`
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`]
})
})
test('should not prefix id of a function declaration', () => {
const node = parseWithExpressionTransform(
`{{ function foo() { return bar } }}`
) as ExpressionNode
expect(node.type).toBe(NodeTypes.EXPRESSION)
expect(node.children).toMatchObject([
`function `,
{ content: `foo` },
`() { return `,
{ content: `_ctx.bar` },
` }`
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
`function `,
{ content: `foo` },
`() { return `,
{ content: `_ctx.bar` },
` }`
]
})
})
test('should not prefix params of a function expression', () => {
const node = parseWithExpressionTransform(
`{{ foo => foo + bar }}`
) as ExpressionNode
expect(node.type).toBe(NodeTypes.EXPRESSION)
expect(node.children).toMatchObject([
{ content: `foo` },
` => `,
{ content: `foo` },
` + `,
{ content: `_ctx.bar` }
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `foo` },
` => `,
{ content: `foo` },
` + `,
{ content: `_ctx.bar` }
]
})
})
test('should not prefix an object property key', () => {
const node = parseWithExpressionTransform(
`{{ { foo: bar } }}`
) as ExpressionNode
expect(node.type).toBe(NodeTypes.EXPRESSION)
expect(node.children).toMatchObject([
`{ foo: `,
{ content: `_ctx.bar` },
` }`
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [`{ foo: `, { content: `_ctx.bar` }, ` }`]
})
})
test('should prefix a computed object property key', () => {
const node = parseWithExpressionTransform(
`{{ { [foo]: bar } }}`
) as ExpressionNode
expect(node.type).toBe(NodeTypes.EXPRESSION)
expect(node.children).toMatchObject([
`{ [`,
{ content: `_ctx.foo` },
`]: `,
{ content: `_ctx.bar` },
` }`
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
`{ [`,
{ content: `_ctx.foo` },
`]: `,
{ content: `_ctx.bar` },
` }`
]
})
})
test('should prefix object property shorthand value', () => {
const node = parseWithExpressionTransform(`{{ { foo } }}`) as ExpressionNode
expect(node.children).toMatchObject([
`{ foo: `,
{ content: `_ctx.foo` },
` }`
])
const node = parseWithExpressionTransform(
`{{ { foo } }}`
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`]
})
})
test('should not prefix id in a member expression', () => {
const node = parseWithExpressionTransform(
`{{ foo.bar.baz }}`
) as ExpressionNode
expect(node.children).toMatchObject([
{ content: `_ctx.foo` },
`.`,
{ content: `bar` },
`.`,
{ content: `baz` }
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `_ctx.foo` },
`.`,
{ content: `bar` },
`.`,
{ content: `baz` }
]
})
})
test('should prefix computed id in a member expression', () => {
const node = parseWithExpressionTransform(
`{{ foo[bar][baz] }}`
) as ExpressionNode
expect(node.children).toMatchObject([
{ content: `_ctx.foo` },
`[`,
{ content: `_ctx.bar` },
`][`,
{ content: '_ctx.baz' },
`]`
])
) as InterpolationNode
expect(node.content).toMatchObject({
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
{ content: `_ctx.foo` },
`[`,
{ content: `_ctx.bar` },
`][`,
{ content: '_ctx.baz' },
`]`
]
})
})
test('should handle parse error', () => {

View File

@@ -31,7 +31,7 @@ describe('compiler: style transform', () => {
)
expect(root.hoists).toMatchObject([
{
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `{"color":"red"}`,
isStatic: false
}
@@ -40,12 +40,12 @@ describe('compiler: style transform', () => {
type: NodeTypes.DIRECTIVE,
name: `bind`,
arg: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `style`,
isStatic: true
},
exp: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`,
isStatic: false
}
@@ -64,12 +64,12 @@ describe('compiler: style transform', () => {
properties: [
{
key: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `style`,
isStatic: true
},
value: {
type: NodeTypes.EXPRESSION,
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_hoisted_1`,
isStatic: false
}

View File

@@ -8,6 +8,8 @@ import {
} from '../../src'
import { transformBind } from '../../src/transforms/vBind'
import { transformElement } from '../../src/transforms/transformElement'
import { CAMELIZE } from '../../src/runtimeConstants'
import { transformExpression } from '../../src/transforms/transformExpression'
function parseWithVBind(
template: string,
@@ -15,7 +17,10 @@ function parseWithVBind(
): ElementNode {
const ast = parse(template)
transform(ast, {
nodeTransforms: [transformElement],
nodeTransforms: [
...(options.prefixIdentifiers ? [transformExpression] : []),
transformElement
],
directiveTransforms: {
bind: transformBind
},
@@ -117,4 +122,42 @@ describe('compiler: transform v-bind', () => {
}
})
})
test('.camel modifier w/ dynamic arg', () => {
const node = parseWithVBind(`<div v-bind:[foo].camel="id"/>`)
const props = node.codegenNode!.arguments[1] as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
content: `_${CAMELIZE}(foo)`,
isStatic: false
},
value: {
content: `id`,
isStatic: false
}
})
})
test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => {
const node = parseWithVBind(`<div v-bind:[foo(bar)].camel="id"/>`, {
prefixIdentifiers: true
})
const props = node.codegenNode!.arguments[1] as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
children: [
`${CAMELIZE}(`,
{ content: `_ctx.foo` },
`(`,
{ content: `_ctx.bar` },
`)`,
`)`
]
},
value: {
content: `_ctx.id`,
isStatic: false
}
})
})
})

View File

@@ -1,7 +1,7 @@
import { parse } from '../../src/parse'
import { transform } from '../../src/transform'
import { transformFor } from '../../src/transforms/vFor'
import { ForNode, NodeTypes } from '../../src/ast'
import { ForNode, NodeTypes, SimpleExpressionNode } from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
import { CompilerOptions } from '../../src'
@@ -24,7 +24,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('index')
expect(forNode.source.content).toBe('5')
expect((forNode.source as SimpleExpressionNode).content).toBe('5')
})
test('value', () => {
@@ -32,7 +32,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('object de-structured value', () => {
@@ -42,7 +42,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('{ id, value }')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('array de-structured value', () => {
@@ -52,7 +52,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('[ id, value ]')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('value and key', () => {
@@ -63,7 +63,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('value, key and index', () => {
@@ -75,7 +75,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('skipped key', () => {
@@ -86,7 +86,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('skipped value and key', () => {
@@ -95,7 +95,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('unbracketed value', () => {
@@ -103,7 +103,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('unbracketed value and key', () => {
@@ -112,7 +112,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('unbracketed value, key and index', () => {
@@ -124,7 +124,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('unbracketed skipped key', () => {
@@ -135,7 +135,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('unbracketed skipped value and key', () => {
@@ -144,7 +144,7 @@ describe('compiler: transform v-for', () => {
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
})
test('missing expression', () => {
@@ -223,7 +223,7 @@ describe('compiler: transform v-for', () => {
)
const itemsOffset = source.indexOf('items')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(itemsOffset)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
@@ -248,7 +248,7 @@ describe('compiler: transform v-for', () => {
)
const itemsOffset = source.indexOf('items')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(itemsOffset)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
@@ -273,7 +273,7 @@ describe('compiler: transform v-for', () => {
)
const itemsOffset = source.indexOf('items')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(itemsOffset)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
@@ -318,7 +318,7 @@ describe('compiler: transform v-for', () => {
)
const itemsOffset = source.indexOf('items')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(itemsOffset)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
@@ -353,7 +353,7 @@ describe('compiler: transform v-for', () => {
)
const itemsOffset = source.indexOf('items')
expect(forNode.source.content).toBe('items')
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(itemsOffset)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)

View File

@@ -6,7 +6,8 @@ import {
NodeTypes,
ElementNode,
TextNode,
CommentNode
CommentNode,
SimpleExpressionNode
} from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
import { CompilerOptions } from '../../src'
@@ -30,7 +31,9 @@ describe('compiler: transform v-if', () => {
const node = parseWithIfTransform(`<div v-if="ok"/>`)
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
`ok`
)
expect(node.branches[0].children.length).toBe(1)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
@@ -42,7 +45,9 @@ describe('compiler: transform v-if', () => {
)
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
`ok`
)
expect(node.branches[0].children.length).toBe(3)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
@@ -58,7 +63,7 @@ describe('compiler: transform v-if', () => {
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
@@ -76,13 +81,13 @@ describe('compiler: transform v-if', () => {
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
@@ -96,13 +101,13 @@ describe('compiler: transform v-if', () => {
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
@@ -126,13 +131,13 @@ describe('compiler: transform v-if', () => {
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)
expect(b2.children.length).toBe(2)
expect(b2.children[0].type).toBe(NodeTypes.COMMENT)
expect((b2.children[0] as CommentNode).content).toBe(`foo`)

View File

@@ -4,7 +4,8 @@ import {
ElementNode,
ObjectExpression,
CompilerOptions,
ErrorCodes
ErrorCodes,
NodeTypes
} from '../../src'
import { transformOn } from '../../src/transforms/vOn'
import { transformElement } from '../../src/transforms/transformElement'
@@ -76,10 +77,11 @@ describe('compiler: transform v-on', () => {
const props = node.codegenNode!.arguments[1] as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
isStatic: false,
children: [`"on" + `, { content: `event` }]
type: NodeTypes.COMPOUND_EXPRESSION,
children: [`"on" + (`, { content: `event` }, `)`]
},
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `handler`,
isStatic: false
}
@@ -93,10 +95,36 @@ describe('compiler: transform v-on', () => {
const props = node.codegenNode!.arguments[1] as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
isStatic: false,
children: [`"on" + `, { content: `_ctx.event` }]
type: NodeTypes.COMPOUND_EXPRESSION,
children: [`"on" + (`, { content: `_ctx.event` }, `)`]
},
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.handler`,
isStatic: false
}
})
})
test('dynamic arg with complex exp prefixing', () => {
const node = parseWithVOn(`<div v-on:[event(foo)]="handler"/>`, {
prefixIdentifiers: true
})
const props = node.codegenNode!.arguments[1] as ObjectExpression
expect(props.properties[0]).toMatchObject({
key: {
type: NodeTypes.COMPOUND_EXPRESSION,
children: [
`"on" + (`,
{ content: `_ctx.event` },
`(`,
{ content: `_ctx.foo` },
`)`,
`)`
]
},
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.handler`,
isStatic: false
}