Skip to content

Commit

Permalink
wip: reuse check logic
Browse files Browse the repository at this point in the history
  • Loading branch information
edison1105 committed Jan 23, 2025
1 parent 4dbcd89 commit 7a6f1cb
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 81 deletions.
1 change: 1 addition & 0 deletions packages/compiler-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export { transformBind } from './transforms/vBind'
export { noopDirectiveTransform } from './transforms/noopDirectiveTransform'
export { processIf } from './transforms/vIf'
export { processFor, createForLoopParams } from './transforms/vFor'
export { processSkip } from './transforms/vSkip'
export {
transformExpression,
processExpression,
Expand Down
155 changes: 84 additions & 71 deletions packages/compiler-core/src/transforms/vSkip.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import {
type DirectiveNode,
type ElementNode,
ElementTypes,
type IfBranchNode,
NodeTypes,
type SimpleExpressionNode,
type SlotsExpression,
type SourceLocation,
type TemplateChildNode,
createConditionalExpression,
createSimpleExpression,
} from '../ast'
import {
type NodeTransform,
type TransformContext,
createStructuralDirectiveTransform,
} from '../transform'
import {
Expand All @@ -27,82 +31,91 @@ import { validateBrowserExpression } from '../validateExpression'
export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
'skip',
(node, dir, context) => {
const loc = dir.exp ? dir.exp.loc : node.loc
if (isTemplateNode(node) || isSlotOutlet(node)) {
context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
return
}

if (findDir(node, 'for')) {
context.onWarn(createCompilerError(ErrorCodes.X_V_SKIP_WITH_V_FOR, loc))
}

if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
context.onError(
createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc),
)
dir.exp = createSimpleExpression(`true`, false, loc)
}

if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
}

if (__DEV__ && __BROWSER__ && dir.exp) {
validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
}

return () => {
let children: TemplateChildNode[] = []
// for components, extract default slot without props
// if not found, throw an error
if (node.tagType === ElementTypes.COMPONENT) {
const codegenNode = node.codegenNode!
if (codegenNode.type === NodeTypes.VNODE_CALL) {
const genChildren = codegenNode.children! as SlotsExpression
if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
const prop = genChildren.properties.find(
p =>
p.type === NodeTypes.JS_PROPERTY &&
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
p.key.content === 'default' &&
p.value.params === undefined,
)
if (prop) {
children = prop.value.returns as TemplateChildNode[]
} else {
context.onError(
createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
return processSkip(node, dir, context, loc => {
return () => {
let children: TemplateChildNode[] = []
// for components, extract default slot without props
// if not found, throw an error
if (node.tagType === ElementTypes.COMPONENT) {
const codegenNode = node.codegenNode!
if (codegenNode.type === NodeTypes.VNODE_CALL) {
const genChildren = codegenNode.children! as SlotsExpression
if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
const prop = genChildren.properties.find(
p =>
p.type === NodeTypes.JS_PROPERTY &&
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
p.key.content === 'default' &&
p.value.params === undefined,
)
if (prop) {
children = prop.value.returns as TemplateChildNode[]
} else {
context.onError(
createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
)
}
}
}
}
}
// for plain elements, take all children
else {
children = node.children
}
const consequent: IfBranchNode = {
type: NodeTypes.IF_BRANCH,
loc: node.loc,
condition: undefined,
children,
userKey: findProp(node, `key`),
}
// for plain elements, take all children
else {
children = node.children
}
const consequent: IfBranchNode = {
type: NodeTypes.IF_BRANCH,
loc: node.loc,
condition: undefined,
children,
userKey: findProp(node, `key`),
}

const alternate: IfBranchNode = {
type: NodeTypes.IF_BRANCH,
loc: node.loc,
condition: undefined,
children: [node],
userKey: findProp(node, `key`),
}
const alternate: IfBranchNode = {
type: NodeTypes.IF_BRANCH,
loc: node.loc,
condition: undefined,
children: [node],
userKey: findProp(node, `key`),
}

node.codegenNode = createConditionalExpression(
dir.exp!,
createCodegenNodeForBranch(consequent, 0, context),
createCodegenNodeForBranch(alternate, 1, context),
)
}
node.codegenNode = createConditionalExpression(
dir.exp!,
createCodegenNodeForBranch(consequent, 0, context),
createCodegenNodeForBranch(alternate, 1, context),
)
}
})
},
)

export function processSkip(
node: ElementNode,
dir: DirectiveNode,
context: TransformContext,
processCodegen?: (loc: SourceLocation) => () => void,
): (() => void) | undefined {
const loc = dir.exp ? dir.exp.loc : node.loc
if (isTemplateNode(node) || isSlotOutlet(node)) {
context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
return
}

if (findDir(node, 'for')) {
context.onError(createCompilerError(ErrorCodes.X_V_SKIP_WITH_V_FOR, loc))
}

if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
context.onError(createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc))
dir.exp = createSimpleExpression(`true`, false, loc)
}

if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
}

if (__DEV__ && __BROWSER__ && dir.exp) {
validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
}

if (processCodegen) return processCodegen(loc)
}
2 changes: 2 additions & 0 deletions packages/compiler-ssr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ssrTransformModel } from './transforms/ssrVModel'
import { ssrTransformShow } from './transforms/ssrVShow'
import { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs'
import { ssrInjectCssVars } from './transforms/ssrInjectCssVars'
import { ssrTransformSkip } from './transforms/ssrVSkip'

export function compile(
source: string | RootNode,
Expand Down Expand Up @@ -56,6 +57,7 @@ export function compile(
hoistStatic: false,
nodeTransforms: [
ssrTransformIf,
ssrTransformSkip,
ssrTransformFor,
trackVForSlotScopes,
transformExpression,
Expand Down
16 changes: 6 additions & 10 deletions packages/compiler-ssr/src/transforms/ssrVSkip.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import {
type ComponentNode,
type DirectiveNode,
ErrorCodes,
type IfBranchNode,
type NodeTransform,
NodeTypes,
type PlainElementNode,
type SimpleExpressionNode,
createCompilerError,
createIfStatement,
createSimpleExpression,
createStructuralDirectiveTransform,
processSkip,
} from '@vue/compiler-core'
import { processIfBranch } from './ssrVIf'
import type { SSRTransformContext } from '../ssrCodegenTransform'

export const ssrTransformSkip: NodeTransform =
createStructuralDirectiveTransform('skip', processSkip)

export function ssrProcessSkip(
node: PlainElementNode | ComponentNode,
dir: DirectiveNode,
context: SSRTransformContext,
): void {
if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
const loc = dir.exp ? dir.exp.loc : node.loc
context.onError(createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc))
dir.exp = createSimpleExpression(`true`, false, loc)
}

node.props = node.props.filter(x => x.name !== 'skip')
const consequent: IfBranchNode = {
type: NodeTypes.IF_BRANCH,
Expand Down

0 comments on commit 7a6f1cb

Please sign in to comment.