Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions packages/compiler-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
type MemoExpression,
NodeTypes,
type ObjectExpression,
type ParentNode,
type Position,
type Property,
type RenderSlotCall,
Expand Down Expand Up @@ -568,4 +569,36 @@ export function getMemoedVNodeCall(
}
}

export function filterCommentChildren(node: ParentNode): TemplateChildNode[] {
return node.children.filter(n => n.type !== NodeTypes.COMMENT)
}

export function hasSingleChild(node: ParentNode): boolean {
return filterCommentChildren(node).length === 1
}

export function isSingleIfBlock(parent: ParentNode): boolean {
// detect cases where the parent v-if is not the only root level node
let hasEncounteredIf = false
for (const c of filterCommentChildren(parent)) {
if (
c.type === NodeTypes.IF ||
(c.type === NodeTypes.ELEMENT && findDir(c, 'if'))
) {
// multiple root v-if
if (hasEncounteredIf) return false
hasEncounteredIf = true
} else if (
// node before v-if
!hasEncounteredIf ||
// non else nodes
!(c.type === NodeTypes.ELEMENT && findDir(c, /^else(-if)?$/, true))
) {
return false
}
}

return true
}

export const forAliasRE: RegExp = /([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/
33 changes: 6 additions & 27 deletions packages/compiler-ssr/src/transforms/ssrInjectFallthroughAttrs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@ import {
ElementTypes,
type NodeTransform,
NodeTypes,
type ParentNode,
type RootNode,
type TemplateChildNode,
createSimpleExpression,
filterCommentChildren,
findDir,
hasSingleChild,
isSingleIfBlock,
locStub,
} from '@vue/compiler-dom'

const filterChild = (node: ParentNode) =>
node.children.filter(n => n.type !== NodeTypes.COMMENT)

const hasSingleChild = (node: ParentNode): boolean =>
filterChild(node).length === 1

export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
// _attrs is provided as a function argument.
// mark it as a known identifier so that it doesn't get prefixed by
Expand All @@ -32,7 +28,7 @@ export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
node.tag === 'KeepAlive' ||
node.tag === 'keep-alive')
) {
const rootChildren = filterChild(context.root)
const rootChildren = filterCommentChildren(context.root)
if (rootChildren.length === 1 && rootChildren[0] === node) {
if (hasSingleChild(node)) {
injectFallthroughAttrs(node.children[0])
Expand All @@ -47,26 +43,9 @@ export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
}

if (node.type === NodeTypes.IF_BRANCH && hasSingleChild(node)) {
// detect cases where the parent v-if is not the only root level node
let hasEncounteredIf = false
for (const c of filterChild(parent)) {
if (
c.type === NodeTypes.IF ||
(c.type === NodeTypes.ELEMENT && findDir(c, 'if'))
) {
// multiple root v-if
if (hasEncounteredIf) return
hasEncounteredIf = true
} else if (
// node before v-if
!hasEncounteredIf ||
// non else nodes
!(c.type === NodeTypes.ELEMENT && findDir(c, /else/, true))
) {
return
}
if (isSingleIfBlock(parent)) {
injectFallthroughAttrs(node.children[0])
}
injectFallthroughAttrs(node.children[0])
} else if (hasSingleChild(parent)) {
injectFallthroughAttrs(node)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ exports[`compile > expression parsing > v-bind 1`] = `
const n0 = t0()
_renderEffect(() => {
const _key = key.value
_setDynamicProps(n0, [{ [_key+1]: _unref(foo)[_key+1]() }], true)
_setDynamicProps(n0, [{ [_key+1]: _unref(foo)[_key+1]() }])
})
return n0
"
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-vapor/__tests__/compile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ describe('compile', () => {
expect(code).contains('const _key = key.value')
expect(code).contains('_key+1')
expect(code).contains(
'_setDynamicProps(n0, [{ [_key+1]: _unref(foo)[_key+1]() }], true)',
'_setDynamicProps(n0, [{ [_key+1]: _unref(foo)[_key+1]() }])',
)
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj], true))
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj]))
return n0
}"
`;
Expand All @@ -424,7 +424,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj], true))
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj]))
return n0
}"
`;
Expand All @@ -435,7 +435,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj, { id: "foo" }], true))
_renderEffect(() => _setDynamicProps(n0, [_ctx.obj, { id: "foo" }]))
return n0
}"
`;
Expand All @@ -446,7 +446,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }], true))
_renderEffect(() => _setDynamicProps(n0, [{ id: "foo" }, _ctx.obj, { class: "bar" }]))
return n0
}"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function render(_ctx) {

exports[`compiler: template ref transform > ref + v-for 1`] = `
"import { createTemplateRefSetter as _createTemplateRefSetter, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div></div>", true)
const t0 = _template("<div></div>")

export function render(_ctx) {
const _setTemplateRef = _createTemplateRefSetter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
const _key = _ctx.key
_setDynamicProps(n0, [{ [_key+1]: _ctx.foo[_key+1]() }], true)
_setDynamicProps(n0, [{ [_key+1]: _ctx.foo[_key+1]() }])
})
return n0
}"
Expand Down Expand Up @@ -80,7 +80,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [{ foo: bar => _ctx.foo = bar }], true))
_renderEffect(() => _setDynamicProps(n0, [{ foo: bar => _ctx.foo = bar }]))
return n0
}"
`;
Expand Down Expand Up @@ -306,7 +306,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }], true))
_renderEffect(() => _setDynamicProps(n0, [{ [_camelize(_ctx.foo)]: _ctx.id }]))
return n0
}"
`;
Expand Down Expand Up @@ -405,7 +405,7 @@ const t0 = _template("<div></div>", true)

export function render(_ctx) {
const n0 = t0()
_renderEffect(() => _setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }], true))
_renderEffect(() => _setDynamicProps(n0, [{ ["." + _ctx.fooBar]: _ctx.id }]))
return n0
}"
`;
Expand Down Expand Up @@ -569,7 +569,7 @@ export function render(_ctx) {
_renderEffect(() => {
const _id = _ctx.id
const _title = _ctx.title
_setDynamicProps(n0, [{ [_id]: _id, [_title]: _title }], true)
_setDynamicProps(n0, [{ [_id]: _id, [_title]: _title }])
})
return n0
}"
Expand All @@ -583,7 +583,7 @@ export function render(_ctx) {
const n0 = t0()
_renderEffect(() => {
const _id = _ctx.id
_setDynamicProps(n0, [{ [_id]: _id, foo: "bar", checked: "" }], true)
_setDynamicProps(n0, [{ [_id]: _id, foo: "bar", checked: "" }])
})
return n0
}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`compiler: v-for > array de-structured value (with rest) 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0, _for_key0) => {
Expand All @@ -17,7 +17,7 @@ export function render(_ctx) {

exports[`compiler: v-for > array de-structured value 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0, _for_key0) => {
Expand All @@ -32,7 +32,7 @@ export function render(_ctx) {

exports[`compiler: v-for > basic v-for 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, delegateEvents as _delegateEvents, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")
_delegateEvents("click")

export function render(_ctx) {
Expand All @@ -49,7 +49,7 @@ export function render(_ctx) {

exports[`compiler: v-for > key only binding pattern 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<tr> </tr>", true)
const t0 = _template("<tr> </tr>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.rows), (_for_item0) => {
Expand All @@ -64,7 +64,7 @@ export function render(_ctx) {

exports[`compiler: v-for > multi effect 1`] = `
"import { setProp as _setProp, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div></div>", true)
const t0 = _template("<div></div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.items), (_for_item0, _for_key0) => {
Expand All @@ -82,7 +82,7 @@ export function render(_ctx) {
exports[`compiler: v-for > nested v-for 1`] = `
"import { setInsertionState as _setInsertionState, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<span> </span>")
const t1 = _template("<div></div>", true)
const t1 = _template("<div></div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
Expand All @@ -102,7 +102,7 @@ export function render(_ctx) {

exports[`compiler: v-for > object de-structured value (with rest) 1`] = `
"import { getRestElement as _getRestElement, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0, _for_key0) => {
Expand All @@ -117,7 +117,7 @@ export function render(_ctx) {

exports[`compiler: v-for > object de-structured value 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<span> </span>", true)
const t0 = _template("<span> </span>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.items), (_for_item0) => {
Expand All @@ -132,7 +132,7 @@ export function render(_ctx) {

exports[`compiler: v-for > object value, key and index 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0, _for_key0, _for_index0) => {
Expand All @@ -147,7 +147,7 @@ export function render(_ctx) {

exports[`compiler: v-for > selector pattern 1`] = `
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<tr> </tr>", true)
const t0 = _template("<tr> </tr>")

export function render(_ctx) {
let _selector0_0
Expand All @@ -167,7 +167,7 @@ export function render(_ctx) {

exports[`compiler: v-for > selector pattern 2`] = `
"import { setClass as _setClass, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<tr></tr>", true)
const t0 = _template("<tr></tr>")

export function render(_ctx) {
let _selector0_0
Expand All @@ -186,7 +186,7 @@ export function render(_ctx) {

exports[`compiler: v-for > selector pattern 3`] = `
"import { setClass as _setClass, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<tr></tr>", true)
const t0 = _template("<tr></tr>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.rows), (_for_item0) => {
Expand All @@ -203,7 +203,7 @@ export function render(_ctx) {

exports[`compiler: v-for > selector pattern 4`] = `
"import { setClass as _setClass, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<tr></tr>", true)
const t0 = _template("<tr></tr>")

export function render(_ctx) {
let _selector0_0
Expand All @@ -222,7 +222,7 @@ export function render(_ctx) {

exports[`compiler: v-for > v-for aliases w/ complex expressions 1`] = `
"import { getDefaultValue as _getDefaultValue, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div> </div>", true)
const t0 = _template("<div> </div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
Expand Down Expand Up @@ -269,7 +269,7 @@ export function render(_ctx) {

exports[`compiler: v-for > w/o value 1`] = `
"import { createFor as _createFor, template as _template } from 'vue';
const t0 = _template("<div>item</div>", true)
const t0 = _template("<div>item</div>")

export function render(_ctx) {
const n0 = _createFor(() => (_ctx.items), (_for_item0) => {
Expand Down
Loading
Loading