refactor(compiler): better constant hoist/stringify checks
This commit is contained in:
parent
acba86ef45
commit
90bdf59f4c
@ -3322,8 +3322,8 @@ Object {
|
|||||||
"children": Array [
|
"children": Array [
|
||||||
Object {
|
Object {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "a < b",
|
"content": "a < b",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6084,8 +6084,8 @@ Object {
|
|||||||
"children": Array [
|
"children": Array [
|
||||||
Object {
|
Object {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "'</div>'",
|
"content": "'</div>'",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6259,8 +6259,8 @@ Object {
|
|||||||
"props": Array [
|
"props": Array [
|
||||||
Object {
|
Object {
|
||||||
"arg": Object {
|
"arg": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "se",
|
"content": "se",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6593,8 +6593,8 @@ Object {
|
|||||||
"children": Array [
|
"children": Array [
|
||||||
Object {
|
Object {
|
||||||
"content": Object {
|
"content": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "",
|
"content": "",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6758,8 +6758,8 @@ Object {
|
|||||||
"props": Array [
|
"props": Array [
|
||||||
Object {
|
Object {
|
||||||
"arg": Object {
|
"arg": Object {
|
||||||
|
"constType": 3,
|
||||||
"content": "class",
|
"content": "class",
|
||||||
"isConstant": true,
|
|
||||||
"isStatic": true,
|
"isStatic": true,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6777,8 +6777,8 @@ Object {
|
|||||||
"type": 4,
|
"type": 4,
|
||||||
},
|
},
|
||||||
"exp": Object {
|
"exp": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "{ some: condition }",
|
"content": "{ some: condition }",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6838,8 +6838,8 @@ Object {
|
|||||||
"props": Array [
|
"props": Array [
|
||||||
Object {
|
Object {
|
||||||
"arg": Object {
|
"arg": Object {
|
||||||
|
"constType": 3,
|
||||||
"content": "style",
|
"content": "style",
|
||||||
"isConstant": true,
|
|
||||||
"isStatic": true,
|
"isStatic": true,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6857,8 +6857,8 @@ Object {
|
|||||||
"type": 4,
|
"type": 4,
|
||||||
},
|
},
|
||||||
"exp": Object {
|
"exp": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "{ color: 'red' }",
|
"content": "{ color: 'red' }",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6950,8 +6950,8 @@ Object {
|
|||||||
"props": Array [
|
"props": Array [
|
||||||
Object {
|
Object {
|
||||||
"arg": Object {
|
"arg": Object {
|
||||||
|
"constType": 3,
|
||||||
"content": "style",
|
"content": "style",
|
||||||
"isConstant": true,
|
|
||||||
"isStatic": true,
|
"isStatic": true,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -6969,8 +6969,8 @@ Object {
|
|||||||
"type": 4,
|
"type": 4,
|
||||||
},
|
},
|
||||||
"exp": Object {
|
"exp": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "{ color: 'red' }",
|
"content": "{ color: 'red' }",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -7049,8 +7049,8 @@ Object {
|
|||||||
"props": Array [
|
"props": Array [
|
||||||
Object {
|
Object {
|
||||||
"arg": Object {
|
"arg": Object {
|
||||||
|
"constType": 3,
|
||||||
"content": "class",
|
"content": "class",
|
||||||
"isConstant": true,
|
|
||||||
"isStatic": true,
|
"isStatic": true,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
@ -7068,8 +7068,8 @@ Object {
|
|||||||
"type": 4,
|
"type": 4,
|
||||||
},
|
},
|
||||||
"exp": Object {
|
"exp": Object {
|
||||||
|
"constType": 0,
|
||||||
"content": "{ some: condition }",
|
"content": "{ some: condition }",
|
||||||
"isConstant": false,
|
|
||||||
"isStatic": false,
|
"isStatic": false,
|
||||||
"loc": Object {
|
"loc": Object {
|
||||||
"end": Object {
|
"end": Object {
|
||||||
|
@ -20,7 +20,8 @@ import {
|
|||||||
IfConditionalExpression,
|
IfConditionalExpression,
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
VNodeCall,
|
VNodeCall,
|
||||||
DirectiveArguments
|
DirectiveArguments,
|
||||||
|
ConstantTypes
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import {
|
import {
|
||||||
CREATE_VNODE,
|
CREATE_VNODE,
|
||||||
@ -304,7 +305,12 @@ describe('compiler: codegen', () => {
|
|||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.FOR,
|
type: NodeTypes.FOR,
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
source: createSimpleExpression('1 + 2', false, locStub, true),
|
source: createSimpleExpression(
|
||||||
|
'1 + 2',
|
||||||
|
false,
|
||||||
|
locStub,
|
||||||
|
ConstantTypes.CAN_STRINGIFY
|
||||||
|
),
|
||||||
valueAlias: undefined,
|
valueAlias: undefined,
|
||||||
keyAlias: undefined,
|
keyAlias: undefined,
|
||||||
objectIndexAlias: undefined,
|
objectIndexAlias: undefined,
|
||||||
|
@ -9,7 +9,8 @@ import {
|
|||||||
NodeTypes,
|
NodeTypes,
|
||||||
Position,
|
Position,
|
||||||
TextNode,
|
TextNode,
|
||||||
InterpolationNode
|
InterpolationNode,
|
||||||
|
ConstantTypes
|
||||||
} from '../src/ast'
|
} from '../src/ast'
|
||||||
|
|
||||||
describe('compiler: parse', () => {
|
describe('compiler: parse', () => {
|
||||||
@ -177,7 +178,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `message`,
|
content: `message`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 2, line: 1, column: 3 },
|
start: { offset: 2, line: 1, column: 3 },
|
||||||
end: { offset: 9, line: 1, column: 10 },
|
end: { offset: 9, line: 1, column: 10 },
|
||||||
@ -202,7 +203,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `a<b`,
|
content: `a<b`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 3, line: 1, column: 4 },
|
start: { offset: 3, line: 1, column: 4 },
|
||||||
end: { offset: 6, line: 1, column: 7 },
|
end: { offset: 6, line: 1, column: 7 },
|
||||||
@ -228,7 +229,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `a<b`,
|
content: `a<b`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 3, line: 1, column: 4 },
|
start: { offset: 3, line: 1, column: 4 },
|
||||||
end: { offset: 6, line: 1, column: 7 },
|
end: { offset: 6, line: 1, column: 7 },
|
||||||
@ -247,7 +248,7 @@ describe('compiler: parse', () => {
|
|||||||
content: {
|
content: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
content: 'c>d',
|
content: 'c>d',
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 12, line: 1, column: 13 },
|
start: { offset: 12, line: 1, column: 13 },
|
||||||
@ -273,8 +274,8 @@ describe('compiler: parse', () => {
|
|||||||
content: {
|
content: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
// The `isConstant` is the default value and will be determined in `transformExpression`.
|
// The `constType` is the default value and will be determined in `transformExpression`.
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
content: '"</div>"',
|
content: '"</div>"',
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 8, line: 1, column: 9 },
|
start: { offset: 8, line: 1, column: 9 },
|
||||||
@ -303,7 +304,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `msg`,
|
content: `msg`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 4, line: 1, column: 5 },
|
start: { offset: 4, line: 1, column: 5 },
|
||||||
end: { offset: 7, line: 1, column: 8 },
|
end: { offset: 7, line: 1, column: 8 },
|
||||||
@ -1028,7 +1029,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 11, line: 1, column: 12 },
|
start: { offset: 11, line: 1, column: 12 },
|
||||||
end: { offset: 12, line: 1, column: 13 },
|
end: { offset: 12, line: 1, column: 13 },
|
||||||
@ -1054,7 +1055,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'click',
|
content: 'click',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'click',
|
source: 'click',
|
||||||
@ -1091,7 +1092,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'event',
|
content: 'event',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: '[event]',
|
source: '[event]',
|
||||||
@ -1164,7 +1165,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'click',
|
content: 'click',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'click',
|
source: 'click',
|
||||||
@ -1201,7 +1202,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a.b',
|
content: 'a.b',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: '[a.b]',
|
source: '[a.b]',
|
||||||
@ -1238,7 +1239,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'a',
|
source: 'a',
|
||||||
@ -1259,7 +1260,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'b',
|
content: 'b',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 8, line: 1, column: 9 },
|
start: { offset: 8, line: 1, column: 9 },
|
||||||
@ -1286,7 +1287,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'a',
|
source: 'a',
|
||||||
@ -1307,7 +1308,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'b',
|
content: 'b',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 13, line: 1, column: 14 },
|
start: { offset: 13, line: 1, column: 14 },
|
||||||
@ -1334,7 +1335,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'a',
|
source: 'a',
|
||||||
@ -1355,7 +1356,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'b',
|
content: 'b',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 8, line: 1, column: 9 },
|
start: { offset: 8, line: 1, column: 9 },
|
||||||
@ -1382,7 +1383,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
source: 'a',
|
source: 'a',
|
||||||
@ -1403,7 +1404,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'b',
|
content: 'b',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
|
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 14, line: 1, column: 15 },
|
start: { offset: 14, line: 1, column: 15 },
|
||||||
@ -1430,7 +1431,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'a',
|
content: 'a',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
loc: {
|
loc: {
|
||||||
source: 'a',
|
source: 'a',
|
||||||
start: {
|
start: {
|
||||||
@ -1450,8 +1451,8 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: '{ b }',
|
content: '{ b }',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
// The `isConstant` is the default value and will be determined in transformExpression
|
// The `constType` is the default value and will be determined in transformExpression
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 10, line: 1, column: 11 },
|
start: { offset: 10, line: 1, column: 11 },
|
||||||
end: { offset: 15, line: 1, column: 16 },
|
end: { offset: 15, line: 1, column: 16 },
|
||||||
@ -1478,7 +1479,7 @@ describe('compiler: parse', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'foo.bar',
|
content: 'foo.bar',
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
isConstant: true,
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
loc: {
|
loc: {
|
||||||
source: 'foo.bar',
|
source: 'foo.bar',
|
||||||
start: {
|
start: {
|
||||||
|
@ -7,7 +7,8 @@ import {
|
|||||||
VNodeCall,
|
VNodeCall,
|
||||||
IfNode,
|
IfNode,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
ForNode
|
ForNode,
|
||||||
|
ConstantTypes
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { FRAGMENT, RENDER_LIST, CREATE_TEXT } from '../../src/runtimeHelpers'
|
import { FRAGMENT, RENDER_LIST, CREATE_TEXT } from '../../src/runtimeHelpers'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
@ -469,7 +470,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
content: {
|
content: {
|
||||||
content: `1`,
|
content: `1`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: true
|
constType: ConstantTypes.CAN_STRINGIFY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,13 +506,13 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `class`,
|
content: `class`,
|
||||||
isConstant: true,
|
isStatic: true,
|
||||||
isStatic: true
|
constType: ConstantTypes.CAN_STRINGIFY
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `{ foo: true }`,
|
content: `{ foo: true }`,
|
||||||
isConstant: true,
|
isStatic: false,
|
||||||
isStatic: false
|
constType: ConstantTypes.CAN_STRINGIFY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -534,8 +535,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`,
|
content: `_ctx.bar`,
|
||||||
isConstant: false,
|
isStatic: false,
|
||||||
isStatic: false
|
constType: ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
patchFlag: `1 /* TEXT */`
|
patchFlag: `1 /* TEXT */`
|
||||||
|
@ -5,7 +5,8 @@ import {
|
|||||||
DirectiveNode,
|
DirectiveNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
CompilerOptions,
|
CompilerOptions,
|
||||||
InterpolationNode
|
InterpolationNode,
|
||||||
|
ConstantTypes
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformIf } from '../../src/transforms/vIf'
|
import { transformIf } from '../../src/transforms/vIf'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
@ -408,7 +409,7 @@ describe('compiler: expression transform', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `13000n`,
|
content: `13000n`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: true
|
constType: ConstantTypes.CAN_STRINGIFY
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ import {
|
|||||||
SimpleExpressionNode,
|
SimpleExpressionNode,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
InterpolationNode,
|
InterpolationNode,
|
||||||
ForCodegenNode
|
ForCodegenNode,
|
||||||
|
ConstantTypes
|
||||||
} from '../../src/ast'
|
} from '../../src/ast'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
import { ErrorCodes } from '../../src/errors'
|
||||||
import { CompilerOptions, generate } from '../../src'
|
import { CompilerOptions, generate } from '../../src'
|
||||||
@ -760,7 +761,7 @@ describe('compiler: v-for', () => {
|
|||||||
false /* disableTracking */
|
false /* disableTracking */
|
||||||
)
|
)
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
source: { content: `10`, isConstant: true },
|
source: { content: `10`, constType: ConstantTypes.CAN_STRINGIFY },
|
||||||
params: [{ content: `item` }],
|
params: [{ content: `item` }],
|
||||||
innerVNodeCall: {
|
innerVNodeCall: {
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
@ -772,7 +773,7 @@ describe('compiler: v-for', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'item',
|
content: 'item',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false
|
constType: ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
patchFlag: genFlagText(PatchFlags.TEXT)
|
patchFlag: genFlagText(PatchFlags.TEXT)
|
||||||
|
@ -189,11 +189,23 @@ export interface DirectiveNode extends Node {
|
|||||||
parseResult?: ForParseResult
|
parseResult?: ForParseResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static types have several levels.
|
||||||
|
* Higher levels implies lower levels. e.g. a node that can be stringified
|
||||||
|
* can always be hoisted and skipped for patch.
|
||||||
|
*/
|
||||||
|
export const enum ConstantTypes {
|
||||||
|
NOT_CONSTANT = 0,
|
||||||
|
CAN_SKIP_PATCH,
|
||||||
|
CAN_HOIST,
|
||||||
|
CAN_STRINGIFY
|
||||||
|
}
|
||||||
|
|
||||||
export interface SimpleExpressionNode extends Node {
|
export interface SimpleExpressionNode extends Node {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION
|
type: NodeTypes.SIMPLE_EXPRESSION
|
||||||
content: string
|
content: string
|
||||||
isStatic: boolean
|
isStatic: boolean
|
||||||
isConstant: boolean
|
constType: ConstantTypes
|
||||||
/**
|
/**
|
||||||
* Indicates this is an identifier for a hoist vnode call and points to the
|
* Indicates this is an identifier for a hoist vnode call and points to the
|
||||||
* hoisted node.
|
* hoisted node.
|
||||||
@ -204,11 +216,6 @@ export interface SimpleExpressionNode extends Node {
|
|||||||
* the identifiers declared inside the function body.
|
* the identifiers declared inside the function body.
|
||||||
*/
|
*/
|
||||||
identifiers?: string[]
|
identifiers?: string[]
|
||||||
/**
|
|
||||||
* some expressions (e.g. transformAssetUrls import identifiers) are constant,
|
|
||||||
* but cannot be stringified because they must be first evaluated at runtime.
|
|
||||||
*/
|
|
||||||
isRuntimeConstant?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InterpolationNode extends Node {
|
export interface InterpolationNode extends Node {
|
||||||
@ -611,14 +618,14 @@ export function createSimpleExpression(
|
|||||||
content: SimpleExpressionNode['content'],
|
content: SimpleExpressionNode['content'],
|
||||||
isStatic: SimpleExpressionNode['isStatic'],
|
isStatic: SimpleExpressionNode['isStatic'],
|
||||||
loc: SourceLocation = locStub,
|
loc: SourceLocation = locStub,
|
||||||
isConstant: boolean = false
|
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT
|
||||||
): SimpleExpressionNode {
|
): SimpleExpressionNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
isConstant,
|
|
||||||
content,
|
content,
|
||||||
isStatic
|
isStatic,
|
||||||
|
constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,8 @@ import {
|
|||||||
TextNode,
|
TextNode,
|
||||||
TemplateChildNode,
|
TemplateChildNode,
|
||||||
InterpolationNode,
|
InterpolationNode,
|
||||||
createRoot
|
createRoot,
|
||||||
|
ConstantTypes
|
||||||
} from './ast'
|
} from './ast'
|
||||||
|
|
||||||
type OptionalOptions = 'isNativeTag' | 'isBuiltInComponent'
|
type OptionalOptions = 'isNativeTag' | 'isBuiltInComponent'
|
||||||
@ -656,7 +657,9 @@ function parseAttribute(
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content,
|
content,
|
||||||
isStatic,
|
isStatic,
|
||||||
isConstant: isStatic,
|
constType: isStatic
|
||||||
|
? ConstantTypes.CAN_STRINGIFY
|
||||||
|
: ConstantTypes.NOT_CONSTANT,
|
||||||
loc
|
loc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -677,8 +680,8 @@ function parseAttribute(
|
|||||||
content: value.content,
|
content: value.content,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
// Treat as non-constant by default. This can be potentially set to
|
// Treat as non-constant by default. This can be potentially set to
|
||||||
// true by `transformExpression` to make it eligible for hoisting.
|
// other values by `transformExpression` to make it eligible for hoisting.
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: value.loc
|
loc: value.loc
|
||||||
},
|
},
|
||||||
arg,
|
arg,
|
||||||
@ -785,7 +788,7 @@ function parseInterpolation(
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
// Set `isConstant` to false by default and will decide in transformExpression
|
// Set `isConstant` to false by default and will decide in transformExpression
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
content,
|
content,
|
||||||
loc: getSelection(context, innerStart, innerEnd)
|
loc: getSelection(context, innerStart, innerEnd)
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,8 @@ import {
|
|||||||
CacheExpression,
|
CacheExpression,
|
||||||
createCacheExpression,
|
createCacheExpression,
|
||||||
TemplateLiteral,
|
TemplateLiteral,
|
||||||
createVNodeCall
|
createVNodeCall,
|
||||||
|
ConstantTypes
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import {
|
import {
|
||||||
isString,
|
isString,
|
||||||
@ -245,7 +246,7 @@ export function createTransformContext(
|
|||||||
`_hoisted_${context.hoists.length}`,
|
`_hoisted_${context.hoists.length}`,
|
||||||
false,
|
false,
|
||||||
exp.loc,
|
exp.loc,
|
||||||
true
|
ConstantTypes.CAN_HOIST
|
||||||
)
|
)
|
||||||
identifier.hoisted = exp
|
identifier.hoisted = exp
|
||||||
return identifier
|
return identifier
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ConstantTypes,
|
||||||
RootNode,
|
RootNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
TemplateChildNode,
|
TemplateChildNode,
|
||||||
@ -37,16 +38,10 @@ export function isSingleElementRoot(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const enum StaticType {
|
|
||||||
NOT_STATIC = 0,
|
|
||||||
FULL_STATIC,
|
|
||||||
HAS_RUNTIME_CONSTANT
|
|
||||||
}
|
|
||||||
|
|
||||||
function walk(
|
function walk(
|
||||||
node: ParentNode,
|
node: ParentNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
resultCache: Map<TemplateChildNode, StaticType>,
|
resultCache: Map<TemplateChildNode, ConstantTypes>,
|
||||||
doNotHoistNode: boolean = false
|
doNotHoistNode: boolean = false
|
||||||
) {
|
) {
|
||||||
let hasHoistedNode = false
|
let hasHoistedNode = false
|
||||||
@ -58,7 +53,7 @@ function walk(
|
|||||||
// @vue/compiler-dom), but doing it here allows us to perform only one full
|
// @vue/compiler-dom), but doing it here allows us to perform only one full
|
||||||
// walk of the AST and allow `stringifyStatic` to stop walking as soon as its
|
// walk of the AST and allow `stringifyStatic` to stop walking as soon as its
|
||||||
// stringficiation threshold is met.
|
// stringficiation threshold is met.
|
||||||
let hasRuntimeConstant = false
|
let canStringify = true
|
||||||
|
|
||||||
const { children } = node
|
const { children } = node
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
@ -68,20 +63,20 @@ function walk(
|
|||||||
child.type === NodeTypes.ELEMENT &&
|
child.type === NodeTypes.ELEMENT &&
|
||||||
child.tagType === ElementTypes.ELEMENT
|
child.tagType === ElementTypes.ELEMENT
|
||||||
) {
|
) {
|
||||||
let staticType
|
const constantType = doNotHoistNode
|
||||||
if (
|
? ConstantTypes.NOT_CONSTANT
|
||||||
!doNotHoistNode &&
|
: getConstantType(child, resultCache)
|
||||||
(staticType = getStaticType(child, resultCache)) > 0
|
if (constantType > ConstantTypes.NOT_CONSTANT) {
|
||||||
) {
|
if (constantType < ConstantTypes.CAN_STRINGIFY) {
|
||||||
if (staticType === StaticType.HAS_RUNTIME_CONSTANT) {
|
canStringify = false
|
||||||
hasRuntimeConstant = true
|
}
|
||||||
|
if (constantType >= ConstantTypes.CAN_HOIST) {
|
||||||
|
;(child.codegenNode as VNodeCall).patchFlag =
|
||||||
|
PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
|
||||||
|
child.codegenNode = context.hoist(child.codegenNode!)
|
||||||
|
hasHoistedNode = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// whole tree is static
|
|
||||||
;(child.codegenNode as VNodeCall).patchFlag =
|
|
||||||
PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
|
|
||||||
child.codegenNode = context.hoist(child.codegenNode!)
|
|
||||||
hasHoistedNode = true
|
|
||||||
continue
|
|
||||||
} else {
|
} else {
|
||||||
// node may contain dynamic children, but its props may be eligible for
|
// node may contain dynamic children, but its props may be eligible for
|
||||||
// hoisting.
|
// hoisting.
|
||||||
@ -92,7 +87,8 @@ function walk(
|
|||||||
(!flag ||
|
(!flag ||
|
||||||
flag === PatchFlags.NEED_PATCH ||
|
flag === PatchFlags.NEED_PATCH ||
|
||||||
flag === PatchFlags.TEXT) &&
|
flag === PatchFlags.TEXT) &&
|
||||||
!hasNonHoistableProps(child)
|
getGeneratedPropsConstantType(child, resultCache) >=
|
||||||
|
ConstantTypes.CAN_HOIST
|
||||||
) {
|
) {
|
||||||
const props = getNodeProps(child)
|
const props = getNodeProps(child)
|
||||||
if (props) {
|
if (props) {
|
||||||
@ -102,13 +98,15 @@ function walk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.type === NodeTypes.TEXT_CALL) {
|
} else if (child.type === NodeTypes.TEXT_CALL) {
|
||||||
const staticType = getStaticType(child.content, resultCache)
|
const contentType = getConstantType(child.content, resultCache)
|
||||||
if (staticType > 0) {
|
if (contentType > 0) {
|
||||||
if (staticType === StaticType.HAS_RUNTIME_CONSTANT) {
|
if (contentType < ConstantTypes.CAN_STRINGIFY) {
|
||||||
hasRuntimeConstant = true
|
canStringify = false
|
||||||
|
}
|
||||||
|
if (contentType >= ConstantTypes.CAN_HOIST) {
|
||||||
|
child.codegenNode = context.hoist(child.codegenNode)
|
||||||
|
hasHoistedNode = true
|
||||||
}
|
}
|
||||||
child.codegenNode = context.hoist(child.codegenNode)
|
|
||||||
hasHoistedNode = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,19 +129,19 @@ function walk(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasRuntimeConstant && hasHoistedNode && context.transformHoist) {
|
if (canStringify && hasHoistedNode && context.transformHoist) {
|
||||||
context.transformHoist(children, context, node)
|
context.transformHoist(children, context, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStaticType(
|
export function getConstantType(
|
||||||
node: TemplateChildNode | SimpleExpressionNode,
|
node: TemplateChildNode | SimpleExpressionNode,
|
||||||
resultCache: Map<TemplateChildNode, StaticType> = new Map()
|
resultCache: Map<TemplateChildNode, ConstantTypes> = new Map()
|
||||||
): StaticType {
|
): ConstantTypes {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case NodeTypes.ELEMENT:
|
case NodeTypes.ELEMENT:
|
||||||
if (node.tagType !== ElementTypes.ELEMENT) {
|
if (node.tagType !== ElementTypes.ELEMENT) {
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
const cached = resultCache.get(node)
|
const cached = resultCache.get(node)
|
||||||
if (cached !== undefined) {
|
if (cached !== undefined) {
|
||||||
@ -151,40 +149,64 @@ export function getStaticType(
|
|||||||
}
|
}
|
||||||
const codegenNode = node.codegenNode!
|
const codegenNode = node.codegenNode!
|
||||||
if (codegenNode.type !== NodeTypes.VNODE_CALL) {
|
if (codegenNode.type !== NodeTypes.VNODE_CALL) {
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
const flag = getPatchFlag(codegenNode)
|
const flag = getPatchFlag(codegenNode)
|
||||||
if (!flag && !hasNonHoistableProps(node)) {
|
if (!flag) {
|
||||||
// element self is static. check its children.
|
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||||
let returnType = StaticType.FULL_STATIC
|
|
||||||
|
// Element itself has no patch flag. However we still need to check:
|
||||||
|
|
||||||
|
// 1. Even for a node with no patch flag, it is possible for it to contain
|
||||||
|
// non-hoistable expressions that refers to scope variables, e.g. compiler
|
||||||
|
// injected keys or cached event handlers. Therefore we need to always
|
||||||
|
// check the codegenNode's props to be sure.
|
||||||
|
const generatedPropsType = getGeneratedPropsConstantType(
|
||||||
|
node,
|
||||||
|
resultCache
|
||||||
|
)
|
||||||
|
if (generatedPropsType === ConstantTypes.NOT_CONSTANT) {
|
||||||
|
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
|
return ConstantTypes.NOT_CONSTANT
|
||||||
|
}
|
||||||
|
if (generatedPropsType < returnType) {
|
||||||
|
returnType = generatedPropsType
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. its children.
|
||||||
for (let i = 0; i < node.children.length; i++) {
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
const childType = getStaticType(node.children[i], resultCache)
|
const childType = getConstantType(node.children[i], resultCache)
|
||||||
if (childType === StaticType.NOT_STATIC) {
|
if (childType === ConstantTypes.NOT_CONSTANT) {
|
||||||
resultCache.set(node, StaticType.NOT_STATIC)
|
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
} else if (childType === StaticType.HAS_RUNTIME_CONSTANT) {
|
}
|
||||||
returnType = StaticType.HAS_RUNTIME_CONSTANT
|
if (childType < returnType) {
|
||||||
|
returnType = childType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if any of the props contain runtime constants
|
// 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-0
|
||||||
if (returnType !== StaticType.HAS_RUNTIME_CONSTANT) {
|
// type, check if any of the props can cause the type to be lowered
|
||||||
|
// we can skip can_patch because it's guaranteed by the absence of a
|
||||||
|
// patchFlag.
|
||||||
|
if (returnType > ConstantTypes.CAN_SKIP_PATCH) {
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const p = node.props[i]
|
const p = node.props[i]
|
||||||
if (
|
if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind' && p.exp) {
|
||||||
p.type === NodeTypes.DIRECTIVE &&
|
const expType = getConstantType(p.exp, resultCache)
|
||||||
p.name === 'bind' &&
|
if (expType === ConstantTypes.NOT_CONSTANT) {
|
||||||
p.exp &&
|
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
(p.exp.type === NodeTypes.COMPOUND_EXPRESSION ||
|
return ConstantTypes.NOT_CONSTANT
|
||||||
p.exp.isRuntimeConstant)
|
}
|
||||||
) {
|
if (expType < returnType) {
|
||||||
returnType = StaticType.HAS_RUNTIME_CONSTANT
|
returnType = expType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only svg/foreignObject could be block here, however if they are
|
// only svg/foreignObject could be block here, however if they are
|
||||||
// stati then they don't need to be blocks since there will be no
|
// static then they don't need to be blocks since there will be no
|
||||||
// nested updates.
|
// nested updates.
|
||||||
if (codegenNode.isBlock) {
|
if (codegenNode.isBlock) {
|
||||||
codegenNode.isBlock = false
|
codegenNode.isBlock = false
|
||||||
@ -193,37 +215,33 @@ export function getStaticType(
|
|||||||
resultCache.set(node, returnType)
|
resultCache.set(node, returnType)
|
||||||
return returnType
|
return returnType
|
||||||
} else {
|
} else {
|
||||||
resultCache.set(node, StaticType.NOT_STATIC)
|
resultCache.set(node, ConstantTypes.NOT_CONSTANT)
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
case NodeTypes.TEXT:
|
case NodeTypes.TEXT:
|
||||||
case NodeTypes.COMMENT:
|
case NodeTypes.COMMENT:
|
||||||
return StaticType.FULL_STATIC
|
return ConstantTypes.CAN_STRINGIFY
|
||||||
case NodeTypes.IF:
|
case NodeTypes.IF:
|
||||||
case NodeTypes.FOR:
|
case NodeTypes.FOR:
|
||||||
case NodeTypes.IF_BRANCH:
|
case NodeTypes.IF_BRANCH:
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
case NodeTypes.INTERPOLATION:
|
case NodeTypes.INTERPOLATION:
|
||||||
case NodeTypes.TEXT_CALL:
|
case NodeTypes.TEXT_CALL:
|
||||||
return getStaticType(node.content, resultCache)
|
return getConstantType(node.content, resultCache)
|
||||||
case NodeTypes.SIMPLE_EXPRESSION:
|
case NodeTypes.SIMPLE_EXPRESSION:
|
||||||
return node.isRuntimeConstant
|
return node.constType
|
||||||
? StaticType.HAS_RUNTIME_CONSTANT
|
|
||||||
: node.isConstant
|
|
||||||
? StaticType.FULL_STATIC
|
|
||||||
: StaticType.NOT_STATIC
|
|
||||||
case NodeTypes.COMPOUND_EXPRESSION:
|
case NodeTypes.COMPOUND_EXPRESSION:
|
||||||
let returnType = StaticType.FULL_STATIC
|
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||||
for (let i = 0; i < node.children.length; i++) {
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
const child = node.children[i]
|
const child = node.children[i]
|
||||||
if (isString(child) || isSymbol(child)) {
|
if (isString(child) || isSymbol(child)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const childType = getStaticType(child, resultCache)
|
const childType = getConstantType(child, resultCache)
|
||||||
if (childType === StaticType.NOT_STATIC) {
|
if (childType === ConstantTypes.NOT_CONSTANT) {
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
} else if (childType === StaticType.HAS_RUNTIME_CONSTANT) {
|
} else if (childType < returnType) {
|
||||||
returnType = StaticType.HAS_RUNTIME_CONSTANT
|
returnType = childType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnType
|
return returnType
|
||||||
@ -232,33 +250,40 @@ export function getStaticType(
|
|||||||
const exhaustiveCheck: never = node
|
const exhaustiveCheck: never = node
|
||||||
exhaustiveCheck
|
exhaustiveCheck
|
||||||
}
|
}
|
||||||
return StaticType.NOT_STATIC
|
return ConstantTypes.NOT_CONSTANT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function getGeneratedPropsConstantType(
|
||||||
* Even for a node with no patch flag, it is possible for it to contain
|
node: PlainElementNode,
|
||||||
* non-hoistable expressions that refers to scope variables, e.g. compiler
|
resultCache: Map<TemplateChildNode, ConstantTypes>
|
||||||
* injected keys or cached event handlers. Therefore we need to always check the
|
): ConstantTypes {
|
||||||
* codegenNode's props to be sure.
|
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||||
*/
|
|
||||||
function hasNonHoistableProps(node: PlainElementNode): boolean {
|
|
||||||
const props = getNodeProps(node)
|
const props = getNodeProps(node)
|
||||||
if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
|
||||||
const { properties } = props
|
const { properties } = props
|
||||||
for (let i = 0; i < properties.length; i++) {
|
for (let i = 0; i < properties.length; i++) {
|
||||||
const { key, value } = properties[i]
|
const { key, value } = properties[i]
|
||||||
if (
|
const keyType = getConstantType(key, resultCache)
|
||||||
key.type !== NodeTypes.SIMPLE_EXPRESSION ||
|
if (keyType === ConstantTypes.NOT_CONSTANT) {
|
||||||
!key.isStatic ||
|
return keyType
|
||||||
(value.type !== NodeTypes.SIMPLE_EXPRESSION ||
|
}
|
||||||
(!value.isStatic && !value.isConstant))
|
if (keyType < returnType) {
|
||||||
) {
|
returnType = keyType
|
||||||
return true
|
}
|
||||||
|
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
|
||||||
|
return ConstantTypes.NOT_CONSTANT
|
||||||
|
}
|
||||||
|
const valueType = getConstantType(value, resultCache)
|
||||||
|
if (valueType === ConstantTypes.NOT_CONSTANT) {
|
||||||
|
return valueType
|
||||||
|
}
|
||||||
|
if (valueType < returnType) {
|
||||||
|
returnType = valueType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return returnType
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeProps(node: PlainElementNode) {
|
function getNodeProps(node: PlainElementNode) {
|
||||||
|
@ -18,7 +18,8 @@ import {
|
|||||||
VNodeCall,
|
VNodeCall,
|
||||||
TemplateTextChildNode,
|
TemplateTextChildNode,
|
||||||
DirectiveArguments,
|
DirectiveArguments,
|
||||||
createVNodeCall
|
createVNodeCall,
|
||||||
|
ConstantTypes
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import {
|
import {
|
||||||
PatchFlags,
|
PatchFlags,
|
||||||
@ -53,7 +54,7 @@ import {
|
|||||||
isStaticExp
|
isStaticExp
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { buildSlots } from './vSlot'
|
import { buildSlots } from './vSlot'
|
||||||
import { getStaticType } from './hoistStatic'
|
import { getConstantType } from './hoistStatic'
|
||||||
import { BindingTypes } from '../options'
|
import { BindingTypes } from '../options'
|
||||||
|
|
||||||
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
||||||
@ -166,7 +167,10 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
const hasDynamicTextChild =
|
const hasDynamicTextChild =
|
||||||
type === NodeTypes.INTERPOLATION ||
|
type === NodeTypes.INTERPOLATION ||
|
||||||
type === NodeTypes.COMPOUND_EXPRESSION
|
type === NodeTypes.COMPOUND_EXPRESSION
|
||||||
if (hasDynamicTextChild && !getStaticType(child)) {
|
if (
|
||||||
|
hasDynamicTextChild &&
|
||||||
|
getConstantType(child) === ConstantTypes.NOT_CONSTANT
|
||||||
|
) {
|
||||||
patchFlag |= PatchFlags.TEXT
|
patchFlag |= PatchFlags.TEXT
|
||||||
}
|
}
|
||||||
// pass directly if the only child is a text node
|
// pass directly if the only child is a text node
|
||||||
@ -343,7 +347,7 @@ export function buildProps(
|
|||||||
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
value.type === NodeTypes.JS_CACHE_EXPRESSION ||
|
||||||
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
((value.type === NodeTypes.SIMPLE_EXPRESSION ||
|
||||||
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
value.type === NodeTypes.COMPOUND_EXPRESSION) &&
|
||||||
getStaticType(value) > 0)
|
getConstantType(value) > 0)
|
||||||
) {
|
) {
|
||||||
// skip if the prop is a cached handler or has constant value
|
// skip if the prop is a cached handler or has constant value
|
||||||
return
|
return
|
||||||
|
@ -14,7 +14,8 @@ import {
|
|||||||
ExpressionNode,
|
ExpressionNode,
|
||||||
SimpleExpressionNode,
|
SimpleExpressionNode,
|
||||||
CompoundExpressionNode,
|
CompoundExpressionNode,
|
||||||
createCompoundExpression
|
createCompoundExpression,
|
||||||
|
ConstantTypes
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
||||||
import {
|
import {
|
||||||
@ -190,25 +191,26 @@ export function processExpression(
|
|||||||
|
|
||||||
// fast path if expression is a simple identifier.
|
// fast path if expression is a simple identifier.
|
||||||
const rawExp = node.content
|
const rawExp = node.content
|
||||||
// bail on parens to prevent any possible function invocations.
|
// bail constant on parens (function invocation) and dot (member access)
|
||||||
const bailConstant = rawExp.indexOf(`(`) > -1
|
const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0
|
||||||
|
|
||||||
if (isSimpleIdentifier(rawExp)) {
|
if (isSimpleIdentifier(rawExp)) {
|
||||||
// const bindings exposed from setup - we know they never change
|
const isScopeVarReference = context.identifiers[rawExp]
|
||||||
// marking it as runtime constant will prevent it from being listed as
|
const isAllowedGlobal = isGloballyWhitelisted(rawExp)
|
||||||
// a dynamic prop.
|
const isLiteral = isLiteralWhitelisted(rawExp)
|
||||||
if (bindingMetadata[node.content] === BindingTypes.SETUP_CONST) {
|
if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) {
|
||||||
node.isRuntimeConstant = true
|
// const bindings exposed from setup can be skipped for patching but
|
||||||
}
|
// cannot be hoisted to module scope
|
||||||
if (
|
if (bindingMetadata[node.content] === BindingTypes.SETUP_CONST) {
|
||||||
!asParams &&
|
node.constType = ConstantTypes.CAN_SKIP_PATCH
|
||||||
!context.identifiers[rawExp] &&
|
}
|
||||||
!isGloballyWhitelisted(rawExp) &&
|
|
||||||
!isLiteralWhitelisted(rawExp)
|
|
||||||
) {
|
|
||||||
node.content = rewriteIdentifier(rawExp)
|
node.content = rewriteIdentifier(rawExp)
|
||||||
} else if (!context.identifiers[rawExp] && !bailConstant) {
|
} else if (!isScopeVarReference) {
|
||||||
// mark node constant for hoisting unless it's referring a scope variable
|
if (isLiteral) {
|
||||||
node.isConstant = true
|
node.constType = ConstantTypes.CAN_STRINGIFY
|
||||||
|
} else {
|
||||||
|
node.constType = ConstantTypes.CAN_HOIST
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@ -342,7 +344,7 @@ export function processExpression(
|
|||||||
start: advancePositionWithClone(node.loc.start, source, start),
|
start: advancePositionWithClone(node.loc.start, source, start),
|
||||||
end: advancePositionWithClone(node.loc.start, source, end)
|
end: advancePositionWithClone(node.loc.start, source, end)
|
||||||
},
|
},
|
||||||
id.isConstant /* isConstant */
|
id.isConstant ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (i === ids.length - 1 && end < rawExp.length) {
|
if (i === ids.length - 1 && end < rawExp.length) {
|
||||||
@ -355,7 +357,9 @@ export function processExpression(
|
|||||||
ret = createCompoundExpression(children, node.loc)
|
ret = createCompoundExpression(children, node.loc)
|
||||||
} else {
|
} else {
|
||||||
ret = node
|
ret = node
|
||||||
ret.isConstant = !bailConstant
|
ret.constType = bailConstant
|
||||||
|
? ConstantTypes.NOT_CONSTANT
|
||||||
|
: ConstantTypes.CAN_STRINGIFY
|
||||||
}
|
}
|
||||||
ret.identifiers = Object.keys(knownIds)
|
ret.identifiers = Object.keys(knownIds)
|
||||||
return ret
|
return ret
|
||||||
|
@ -4,11 +4,13 @@ import {
|
|||||||
CompoundExpressionNode,
|
CompoundExpressionNode,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
ElementTypes
|
ElementTypes,
|
||||||
|
ConstantTypes
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { isText } from '../utils'
|
import { isText } from '../utils'
|
||||||
import { CREATE_TEXT } from '../runtimeHelpers'
|
import { CREATE_TEXT } from '../runtimeHelpers'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||||
|
import { getConstantType } from './hoistStatic'
|
||||||
|
|
||||||
// Merge adjacent text nodes and expressions into a single expression
|
// Merge adjacent text nodes and expressions into a single expression
|
||||||
// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.
|
// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.
|
||||||
@ -78,7 +80,10 @@ export const transformText: NodeTransform = (node, context) => {
|
|||||||
callArgs.push(child)
|
callArgs.push(child)
|
||||||
}
|
}
|
||||||
// mark dynamic text with flag so it gets patched inside a block
|
// mark dynamic text with flag so it gets patched inside a block
|
||||||
if (!context.ssr && child.type !== NodeTypes.TEXT) {
|
if (
|
||||||
|
!context.ssr &&
|
||||||
|
getConstantType(child) === ConstantTypes.NOT_CONSTANT
|
||||||
|
) {
|
||||||
callArgs.push(
|
callArgs.push(
|
||||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
||||||
)
|
)
|
||||||
|
@ -77,7 +77,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
|
|
||||||
const isStableFragment =
|
const isStableFragment =
|
||||||
forNode.source.type === NodeTypes.SIMPLE_EXPRESSION &&
|
forNode.source.type === NodeTypes.SIMPLE_EXPRESSION &&
|
||||||
forNode.source.isConstant
|
forNode.source.constType > 0
|
||||||
const fragmentFlag = isStableFragment
|
const fragmentFlag = isStableFragment
|
||||||
? PatchFlags.STABLE_FRAGMENT
|
? PatchFlags.STABLE_FRAGMENT
|
||||||
: keyProp
|
: keyProp
|
||||||
|
@ -21,7 +21,8 @@ import {
|
|||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
AttributeNode,
|
AttributeNode,
|
||||||
locStub,
|
locStub,
|
||||||
CacheExpression
|
CacheExpression,
|
||||||
|
ConstantTypes
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
@ -227,7 +228,12 @@ function createChildrenCodegenNode(
|
|||||||
const { helper } = context
|
const { helper } = context
|
||||||
const keyProperty = createObjectProperty(
|
const keyProperty = createObjectProperty(
|
||||||
`key`,
|
`key`,
|
||||||
createSimpleExpression(`${keyIndex}`, false, locStub, true)
|
createSimpleExpression(
|
||||||
|
`${keyIndex}`,
|
||||||
|
false,
|
||||||
|
locStub,
|
||||||
|
ConstantTypes.CAN_HOIST
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const { children } = branch
|
const { children } = branch
|
||||||
const firstChild = children[0]
|
const firstChild = children[0]
|
||||||
|
@ -6,7 +6,8 @@ import {
|
|||||||
NodeTypes,
|
NodeTypes,
|
||||||
Property,
|
Property,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ExpressionNode
|
ExpressionNode,
|
||||||
|
ConstantTypes
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import {
|
import {
|
||||||
@ -125,7 +126,12 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||||||
props.push(
|
props.push(
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
modifiersKey,
|
modifiersKey,
|
||||||
createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, true)
|
createSimpleExpression(
|
||||||
|
`{ ${modifiers} }`,
|
||||||
|
false,
|
||||||
|
dir.loc,
|
||||||
|
ConstantTypes.CAN_HOIST
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ export const transformOn: DirectiveTransform = (
|
|||||||
context.cacheHandlers &&
|
context.cacheHandlers &&
|
||||||
// runtime constants don't need to be cached
|
// runtime constants don't need to be cached
|
||||||
// (this is analyzed by compileScript in SFC <script setup>)
|
// (this is analyzed by compileScript in SFC <script setup>)
|
||||||
!(exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.isRuntimeConstant) &&
|
!(exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&
|
||||||
// #1541 bail if this is a member exp handler passed to a component -
|
// #1541 bail if this is a member exp handler passed to a component -
|
||||||
// we need to use the original function to preserve arity,
|
// we need to use the original function to preserve arity,
|
||||||
// e.g. <transition> relies on checking cb.length to determine
|
// e.g. <transition> relies on checking cb.length to determine
|
||||||
|
@ -6,7 +6,8 @@ import {
|
|||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
InterpolationNode,
|
InterpolationNode,
|
||||||
AttributeNode
|
AttributeNode,
|
||||||
|
ConstantTypes
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { parserOptions, DOMNamespaces } from '../src/parserOptions'
|
import { parserOptions, DOMNamespaces } from '../src/parserOptions'
|
||||||
|
|
||||||
@ -253,7 +254,7 @@ describe('DOM parser', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `a < b`,
|
content: `a < b`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: false,
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 8, line: 1, column: 9 },
|
start: { offset: 8, line: 1, column: 9 },
|
||||||
end: { offset: 16, line: 1, column: 17 },
|
end: { offset: 16, line: 1, column: 17 },
|
||||||
|
@ -2,7 +2,8 @@ import {
|
|||||||
compile,
|
compile,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
CREATE_STATIC,
|
CREATE_STATIC,
|
||||||
createSimpleExpression
|
createSimpleExpression,
|
||||||
|
ConstantTypes
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import {
|
import {
|
||||||
stringifyStatic,
|
stringifyStatic,
|
||||||
@ -176,9 +177,8 @@ describe('stringify static html', () => {
|
|||||||
'_imports_0_',
|
'_imports_0_',
|
||||||
false,
|
false,
|
||||||
node.loc,
|
node.loc,
|
||||||
true
|
ConstantTypes.CAN_HOIST
|
||||||
)
|
)
|
||||||
exp.isRuntimeConstant = true
|
|
||||||
node.props[0] = {
|
node.props[0] = {
|
||||||
type: NodeTypes.DIRECTIVE,
|
type: NodeTypes.DIRECTIVE,
|
||||||
name: 'bind',
|
name: 'bind',
|
||||||
|
@ -3,7 +3,8 @@ import {
|
|||||||
NodeTypes,
|
NodeTypes,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
SimpleExpressionNode,
|
SimpleExpressionNode,
|
||||||
SourceLocation
|
SourceLocation,
|
||||||
|
ConstantTypes
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { parseStringStyle } from '@vue/shared'
|
import { parseStringStyle } from '@vue/shared'
|
||||||
|
|
||||||
@ -36,5 +37,10 @@ const parseInlineCSS = (
|
|||||||
loc: SourceLocation
|
loc: SourceLocation
|
||||||
): SimpleExpressionNode => {
|
): SimpleExpressionNode => {
|
||||||
const normalized = parseStringStyle(cssText)
|
const normalized = parseStringStyle(cssText)
|
||||||
return createSimpleExpression(JSON.stringify(normalized), false, loc, true)
|
return createSimpleExpression(
|
||||||
|
JSON.stringify(normalized),
|
||||||
|
false,
|
||||||
|
loc,
|
||||||
|
ConstantTypes.CAN_STRINGIFY
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import {
|
import {
|
||||||
|
ConstantTypes,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
ExpressionNode,
|
ExpressionNode,
|
||||||
NodeTransform,
|
NodeTransform,
|
||||||
@ -159,19 +160,26 @@ function getImportsExpressionExp(
|
|||||||
return existing.exp as ExpressionNode
|
return existing.exp as ExpressionNode
|
||||||
}
|
}
|
||||||
const name = `_imports_${importsArray.length}`
|
const name = `_imports_${importsArray.length}`
|
||||||
const exp = createSimpleExpression(name, false, loc, true)
|
const exp = createSimpleExpression(
|
||||||
exp.isRuntimeConstant = true
|
name,
|
||||||
|
false,
|
||||||
|
loc,
|
||||||
|
ConstantTypes.CAN_HOIST
|
||||||
|
)
|
||||||
context.imports.add({ exp, path })
|
context.imports.add({ exp, path })
|
||||||
if (hash && path) {
|
if (hash && path) {
|
||||||
const ret = context.hoist(
|
return context.hoist(
|
||||||
createSimpleExpression(`${name} + '${hash}'`, false, loc, true)
|
createSimpleExpression(
|
||||||
|
`${name} + '${hash}'`,
|
||||||
|
false,
|
||||||
|
loc,
|
||||||
|
ConstantTypes.CAN_HOIST
|
||||||
|
)
|
||||||
)
|
)
|
||||||
ret.isRuntimeConstant = true
|
|
||||||
return ret
|
|
||||||
} else {
|
} else {
|
||||||
return exp
|
return exp
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return createSimpleExpression(`''`, false, loc, true)
|
return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_HOIST)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import {
|
import {
|
||||||
|
ConstantTypes,
|
||||||
createCompoundExpression,
|
createCompoundExpression,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
NodeTransform,
|
NodeTransform,
|
||||||
@ -107,14 +108,14 @@ export const transformSrcset: NodeTransform = (
|
|||||||
`_imports_${existingImportsIndex}`,
|
`_imports_${existingImportsIndex}`,
|
||||||
false,
|
false,
|
||||||
attr.loc,
|
attr.loc,
|
||||||
true
|
ConstantTypes.CAN_HOIST
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
exp = createSimpleExpression(
|
exp = createSimpleExpression(
|
||||||
`_imports_${importsArray.length}`,
|
`_imports_${importsArray.length}`,
|
||||||
false,
|
false,
|
||||||
attr.loc,
|
attr.loc,
|
||||||
true
|
ConstantTypes.CAN_HOIST
|
||||||
)
|
)
|
||||||
context.imports.add({ exp, path })
|
context.imports.add({ exp, path })
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ export const transformSrcset: NodeTransform = (
|
|||||||
`"${url}"`,
|
`"${url}"`,
|
||||||
false,
|
false,
|
||||||
attr.loc,
|
attr.loc,
|
||||||
true
|
ConstantTypes.CAN_HOIST
|
||||||
)
|
)
|
||||||
compoundExpression.children.push(exp)
|
compoundExpression.children.push(exp)
|
||||||
}
|
}
|
||||||
@ -140,7 +141,7 @@ export const transformSrcset: NodeTransform = (
|
|||||||
})
|
})
|
||||||
|
|
||||||
const hoisted = context.hoist(compoundExpression)
|
const hoisted = context.hoist(compoundExpression)
|
||||||
hoisted.isRuntimeConstant = true
|
hoisted.constType = ConstantTypes.CAN_HOIST
|
||||||
|
|
||||||
node.props[index] = {
|
node.props[index] = {
|
||||||
type: NodeTypes.DIRECTIVE,
|
type: NodeTypes.DIRECTIVE,
|
||||||
|
Loading…
Reference in New Issue
Block a user