parent
fbaf52ae9f
commit
9b5d13e598
@ -1,4 +1,4 @@
|
|||||||
import { ElementNode, Namespace, TemplateChildNode } from './ast'
|
import { ElementNode, Namespace, TemplateChildNode, ParentNode } from './ast'
|
||||||
import { TextModes } from './parse'
|
import { TextModes } from './parse'
|
||||||
import { CompilerError } from './errors'
|
import { CompilerError } from './errors'
|
||||||
import {
|
import {
|
||||||
@ -53,7 +53,8 @@ export interface ParserOptions {
|
|||||||
|
|
||||||
export type HoistTransform = (
|
export type HoistTransform = (
|
||||||
children: TemplateChildNode[],
|
children: TemplateChildNode[],
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
|
parent: ParentNode
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export interface TransformOptions {
|
export interface TransformOptions {
|
||||||
|
@ -8,7 +8,8 @@ import {
|
|||||||
ComponentNode,
|
ComponentNode,
|
||||||
TemplateNode,
|
TemplateNode,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
VNodeCall
|
VNodeCall,
|
||||||
|
ParentNode
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { TransformContext } from '../transform'
|
import { TransformContext } from '../transform'
|
||||||
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
import { PatchFlags, isString, isSymbol } from '@vue/shared'
|
||||||
@ -16,7 +17,7 @@ import { isSlotOutlet, findProp } from '../utils'
|
|||||||
|
|
||||||
export function hoistStatic(root: RootNode, context: TransformContext) {
|
export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||||
walk(
|
walk(
|
||||||
root.children,
|
root,
|
||||||
context,
|
context,
|
||||||
new Map(),
|
new Map(),
|
||||||
// Root node is unfortunately non-hoistable due to potential parent
|
// Root node is unfortunately non-hoistable due to potential parent
|
||||||
@ -44,7 +45,7 @@ const enum StaticType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function walk(
|
function walk(
|
||||||
children: TemplateChildNode[],
|
node: ParentNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
resultCache: Map<TemplateChildNode, StaticType>,
|
resultCache: Map<TemplateChildNode, StaticType>,
|
||||||
doNotHoistNode: boolean = false
|
doNotHoistNode: boolean = false
|
||||||
@ -60,6 +61,7 @@ function walk(
|
|||||||
// stringficiation threshold is met.
|
// stringficiation threshold is met.
|
||||||
let hasRuntimeConstant = false
|
let hasRuntimeConstant = false
|
||||||
|
|
||||||
|
const { children } = node
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
const child = children[i]
|
const child = children[i]
|
||||||
// only plain elements & text calls are eligible for hoisting.
|
// only plain elements & text calls are eligible for hoisting.
|
||||||
@ -114,21 +116,25 @@ function walk(
|
|||||||
|
|
||||||
// walk further
|
// walk further
|
||||||
if (child.type === NodeTypes.ELEMENT) {
|
if (child.type === NodeTypes.ELEMENT) {
|
||||||
walk(child.children, context, resultCache)
|
walk(child, context, resultCache)
|
||||||
} else if (child.type === NodeTypes.FOR) {
|
} else if (child.type === NodeTypes.FOR) {
|
||||||
// Do not hoist v-for single child because it has to be a block
|
// Do not hoist v-for single child because it has to be a block
|
||||||
walk(child.children, context, resultCache, child.children.length === 1)
|
walk(child, context, resultCache, child.children.length === 1)
|
||||||
} else if (child.type === NodeTypes.IF) {
|
} else if (child.type === NodeTypes.IF) {
|
||||||
for (let i = 0; i < child.branches.length; i++) {
|
for (let i = 0; i < child.branches.length; i++) {
|
||||||
const branchChildren = child.branches[i].children
|
|
||||||
// Do not hoist v-if single child because it has to be a block
|
// Do not hoist v-if single child because it has to be a block
|
||||||
walk(branchChildren, context, resultCache, branchChildren.length === 1)
|
walk(
|
||||||
|
child.branches[i],
|
||||||
|
context,
|
||||||
|
resultCache,
|
||||||
|
child.branches[i].children.length === 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasRuntimeConstant && hasHoistedNode && context.transformHoist) {
|
if (!hasRuntimeConstant && hasHoistedNode && context.transformHoist) {
|
||||||
context.transformHoist(children, context)
|
context.transformHoist(children, context, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ describe('stringify static html', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should bail on break content with innerHTML (eg.tables related tags)', () => {
|
test('should bail on tags that has placement constraints (eg.tables related tags)', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<table><tbody>${repeat(
|
`<table><tbody>${repeat(
|
||||||
`<tr class="foo"><td>foo</td></tr>`,
|
`<tr class="foo"><td>foo</td></tr>`,
|
||||||
@ -262,4 +262,36 @@ describe('stringify static html', () => {
|
|||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should bail inside slots', () => {
|
||||||
|
const { ast } = compileWithStringify(
|
||||||
|
`<foo>${repeat(
|
||||||
|
`<div class="foo"></div>`,
|
||||||
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||||
|
)}</foo>`
|
||||||
|
)
|
||||||
|
expect(ast.hoists.length).toBe(
|
||||||
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||||
|
)
|
||||||
|
ast.hoists.forEach(node => {
|
||||||
|
expect(node).toMatchObject({
|
||||||
|
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const { ast: ast2 } = compileWithStringify(
|
||||||
|
`<foo><template #foo>${repeat(
|
||||||
|
`<div class="foo"></div>`,
|
||||||
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||||
|
)}</template></foo>`
|
||||||
|
)
|
||||||
|
expect(ast2.hoists.length).toBe(
|
||||||
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||||
|
)
|
||||||
|
ast2.hoists.forEach(node => {
|
||||||
|
expect(node).toMatchObject({
|
||||||
|
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -59,7 +59,15 @@ type StringifiableNode = PlainElementNode | TextCallNode
|
|||||||
*
|
*
|
||||||
* This optimization is only performed in Node.js.
|
* This optimization is only performed in Node.js.
|
||||||
*/
|
*/
|
||||||
export const stringifyStatic: HoistTransform = (children, context) => {
|
export const stringifyStatic: HoistTransform = (children, context, parent) => {
|
||||||
|
if (
|
||||||
|
parent.type === NodeTypes.ELEMENT &&
|
||||||
|
(parent.tagType === ElementTypes.COMPONENT ||
|
||||||
|
parent.tagType === ElementTypes.TEMPLATE)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let nc = 0 // current node count
|
let nc = 0 // current node count
|
||||||
let ec = 0 // current element with binding count
|
let ec = 0 // current element with binding count
|
||||||
const currentChunk: StringifiableNode[] = []
|
const currentChunk: StringifiableNode[] = []
|
||||||
|
Loading…
Reference in New Issue
Block a user