refactor(compiler-core): follow up on #276
This commit is contained in:
parent
68a3879b88
commit
4cee06ddab
@ -173,7 +173,7 @@ exports[`compiler: hoistStatic transform prefixIdentifiers hoist nested static t
|
|||||||
"const _Vue = Vue
|
"const _Vue = Vue
|
||||||
const _createVNode = Vue.createVNode
|
const _createVNode = Vue.createVNode
|
||||||
|
|
||||||
const _hoisted_1 = _createVNode(\\"span\\", null, [\\"foo \\", _toString(1), _toString(2)])
|
const _hoisted_1 = _createVNode(\\"span\\", null, [\\"foo \\", _toString(1), _toString(true)])
|
||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
with (this) {
|
with (this) {
|
||||||
@ -203,7 +203,7 @@ return function render() {
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that with scope variable (2) 1`] = `
|
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables (2) 1`] = `
|
||||||
"const _Vue = Vue
|
"const _Vue = Vue
|
||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
@ -221,7 +221,24 @@ return function render() {
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that with scope variable 1`] = `
|
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables (v-slot) 1`] = `
|
||||||
|
"const _Vue = Vue
|
||||||
|
|
||||||
|
return function render() {
|
||||||
|
with (this) {
|
||||||
|
const { toString: _toString, resolveComponent: _resolveComponent, createVNode: _createVNode, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||||
|
|
||||||
|
const _component_Comp = _resolveComponent(\\"Comp\\")
|
||||||
|
|
||||||
|
return (_openBlock(), _createBlock(_component_Comp, null, {
|
||||||
|
default: ({ foo }) => [_toString(_ctx.foo)],
|
||||||
|
_compiled: true
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: hoistStatic transform prefixIdentifiers should NOT hoist expressions that refer scope variables 1`] = `
|
||||||
"const _Vue = Vue
|
"const _Vue = Vue
|
||||||
|
|
||||||
return function render() {
|
return function render() {
|
||||||
|
@ -446,7 +446,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
describe('prefixIdentifiers', () => {
|
describe('prefixIdentifiers', () => {
|
||||||
test('hoist nested static tree with static interpolation', () => {
|
test('hoist nested static tree with static interpolation', () => {
|
||||||
const { root, args } = transformWithHoist(
|
const { root, args } = transformWithHoist(
|
||||||
`<div><span>foo {{ 1 }} {{ 2 }}</span></div>`,
|
`<div><span>foo {{ 1 }} {{ true }}</span></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true
|
||||||
}
|
}
|
||||||
@ -474,7 +474,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `2`,
|
content: `true`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
isConstant: true
|
isConstant: true
|
||||||
}
|
}
|
||||||
@ -600,7 +600,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should NOT hoist expressions that with scope variable', () => {
|
test('should NOT hoist expressions that refer scope variables', () => {
|
||||||
const { root } = transformWithHoist(
|
const { root } = transformWithHoist(
|
||||||
`<div><p v-for="o in list"><span>{{ o }}</span></p></div>`,
|
`<div><p v-for="o in list"><span>{{ o }}</span></p></div>`,
|
||||||
{
|
{
|
||||||
@ -612,7 +612,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should NOT hoist expressions that with scope variable (2)', () => {
|
test('should NOT hoist expressions that refer scope variables (2)', () => {
|
||||||
const { root } = transformWithHoist(
|
const { root } = transformWithHoist(
|
||||||
`<div><p v-for="o in list"><span>{{ o + 'foo' }}</span></p></div>`,
|
`<div><p v-for="o in list"><span>{{ o + 'foo' }}</span></p></div>`,
|
||||||
{
|
{
|
||||||
@ -623,5 +623,17 @@ describe('compiler: hoistStatic transform', () => {
|
|||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should NOT hoist expressions that refer scope variables (v-slot)', () => {
|
||||||
|
const { root } = transformWithHoist(
|
||||||
|
`<Comp v-slot="{ foo }">{{ foo }}</Comp>`,
|
||||||
|
{
|
||||||
|
prefixIdentifiers: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(root.hoists.length).toBe(0)
|
||||||
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -564,12 +564,9 @@ function parseAttribute(
|
|||||||
)
|
)
|
||||||
let content = match[2]
|
let content = match[2]
|
||||||
let isStatic = true
|
let isStatic = true
|
||||||
// Non-dynamic arg is a constant.
|
|
||||||
let isConstant = true
|
|
||||||
|
|
||||||
if (content.startsWith('[')) {
|
if (content.startsWith('[')) {
|
||||||
isStatic = false
|
isStatic = false
|
||||||
isConstant = false
|
|
||||||
|
|
||||||
if (!content.endsWith(']')) {
|
if (!content.endsWith(']')) {
|
||||||
emitError(
|
emitError(
|
||||||
@ -585,7 +582,7 @@ function parseAttribute(
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content,
|
content,
|
||||||
isStatic,
|
isStatic,
|
||||||
isConstant,
|
isConstant: isStatic,
|
||||||
loc
|
loc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,7 +608,8 @@ function parseAttribute(
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: value.content,
|
content: value.content,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
// Set `isConstant` to false by default and will decide in transformExpression
|
// Treat as non-constant by default. This can be potentially set to
|
||||||
|
// true by `transformExpression` to make it eligible for hoisting.
|
||||||
isConstant: false,
|
isConstant: false,
|
||||||
loc: value.loc
|
loc: value.loc
|
||||||
},
|
},
|
||||||
|
@ -91,6 +91,9 @@ export function processExpression(
|
|||||||
!literalsWhitelist.has(rawExp)
|
!literalsWhitelist.has(rawExp)
|
||||||
) {
|
) {
|
||||||
node.content = `_ctx.${rawExp}`
|
node.content = `_ctx.${rawExp}`
|
||||||
|
} else if (!context.identifiers[rawExp]) {
|
||||||
|
// mark node constant for hoisting unless it's referring a scope variable
|
||||||
|
node.isConstant = true
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@ -109,13 +112,13 @@ export function processExpression(
|
|||||||
const ids: (Identifier & PrefixMeta)[] = []
|
const ids: (Identifier & PrefixMeta)[] = []
|
||||||
const knownIds = Object.create(context.identifiers)
|
const knownIds = Object.create(context.identifiers)
|
||||||
|
|
||||||
let isConstant = true
|
|
||||||
// walk the AST and look for identifiers that need to be prefixed with `_ctx.`.
|
// walk the AST and look for identifiers that need to be prefixed with `_ctx.`.
|
||||||
walkJS(ast, {
|
walkJS(ast, {
|
||||||
enter(node: Node & PrefixMeta, parent) {
|
enter(node: Node & PrefixMeta, parent) {
|
||||||
if (node.type === 'Identifier') {
|
if (node.type === 'Identifier') {
|
||||||
if (!ids.includes(node)) {
|
if (!ids.includes(node)) {
|
||||||
if (!knownIds[node.name] && shouldPrefix(node, parent)) {
|
const needPrefix = shouldPrefix(node, parent)
|
||||||
|
if (!knownIds[node.name] && needPrefix) {
|
||||||
if (isPropertyShorthand(node, parent)) {
|
if (isPropertyShorthand(node, parent)) {
|
||||||
// property shorthand like { foo }, we need to add the key since we
|
// property shorthand like { foo }, we need to add the key since we
|
||||||
// rewrite the value
|
// rewrite the value
|
||||||
@ -123,14 +126,11 @@ export function processExpression(
|
|||||||
}
|
}
|
||||||
node.name = `_ctx.${node.name}`
|
node.name = `_ctx.${node.name}`
|
||||||
node.isConstant = false
|
node.isConstant = false
|
||||||
isConstant = false
|
|
||||||
ids.push(node)
|
ids.push(node)
|
||||||
} else if (!isStaticPropertyKey(node, parent)) {
|
} else if (!isStaticPropertyKey(node, parent)) {
|
||||||
// This means this identifier is pointing to a scope variable (a v-for alias, or a v-slot prop)
|
// The identifier is considered constant unless it's pointing to a
|
||||||
// which is also dynamic and cannot be hoisted.
|
// scope variable (a v-for alias, or a v-slot prop)
|
||||||
node.isConstant = !(
|
node.isConstant = !(needPrefix && knownIds[node.name])
|
||||||
knownIds[node.name] && shouldPrefix(node, parent)
|
|
||||||
)
|
|
||||||
// also generate sub-expressions for other identifiers for better
|
// also generate sub-expressions for other identifiers for better
|
||||||
// source map support. (except for property keys which are static)
|
// source map support. (except for property keys which are static)
|
||||||
ids.push(node)
|
ids.push(node)
|
||||||
@ -220,7 +220,7 @@ export function processExpression(
|
|||||||
ret = createCompoundExpression(children, node.loc)
|
ret = createCompoundExpression(children, node.loc)
|
||||||
} else {
|
} else {
|
||||||
ret = node
|
ret = node
|
||||||
ret.isConstant = isConstant
|
ret.isConstant = true
|
||||||
}
|
}
|
||||||
ret.identifiers = Object.keys(knownIds)
|
ret.identifiers = Object.keys(knownIds)
|
||||||
return ret
|
return ret
|
||||||
|
Loading…
Reference in New Issue
Block a user