Program,
} from '@babel/types'
import { walk } from 'estree-walker'
+import { type BindingMetadata, BindingTypes } from './options'
/**
* Return value indicates whether the AST walked can be a constant
case 'BooleanLiteral':
case 'NullLiteral':
case 'BigIntLiteral':
+ case 'RegExpLiteral':
return true
}
return false
}
-export function isConstantNode(
- node: Node,
- onIdentifier: (name: string) => boolean,
-): boolean {
+export function isConstantNode(node: Node, bindings: BindingMetadata): boolean {
if (isStaticNode(node)) return true
node = unwrapTSNode(node)
switch (node.type) {
case 'Identifier':
- return onIdentifier(node.name)
- case 'RegExpLiteral':
- return true
+ const type = bindings[node.name]
+ return type === BindingTypes.LITERAL_CONST
case 'ObjectExpression':
return node.properties.every(prop => {
// { bar() {} } object methods are not considered static nodes
if (prop.type === 'ObjectMethod') return false
// { ...{ foo: 1 } }
if (prop.type === 'SpreadElement')
- return isConstantNode(prop.argument, onIdentifier)
+ return isConstantNode(prop.argument, bindings)
// { foo: 1 }
return (
- (!prop.computed || isConstantNode(prop.key, onIdentifier)) &&
- isConstantNode(prop.value, onIdentifier)
+ (!prop.computed || isConstantNode(prop.key, bindings)) &&
+ isConstantNode(prop.value, bindings)
)
})
case 'ArrayExpression':
if (element === null) return true
// [1, ...[2, 3]]
if (element.type === 'SpreadElement')
- return isConstantNode(element.argument, onIdentifier)
+ return isConstantNode(element.argument, bindings)
// [1, 2]
- return isConstantNode(element, onIdentifier)
+ return isConstantNode(element, bindings)
})
}
return false
const n2 = t0()
_setTemplateRef(n2, "foo", void 0, true)
return n2
- })
+ }, null, null, true)
return n0
}"
`;
if (
this.inVOnce ||
expressions.length === 0 ||
- isStaticExpression(this.root, expressions)
+ expressions.every(e =>
+ isStaticExpression(e, this.root.options.bindingMetadata),
+ )
) {
return this.registerOperation(...operations)
}
const nonConstantExps = values.filter(v => !isConstantExpression(v))
const isStatic =
!nonConstantExps.length ||
- isStaticExpression(context, nonConstantExps) ||
+ nonConstantExps.every(e =>
+ isStaticExpression(e, context.options.bindingMetadata),
+ ) ||
context.inVOnce
context.registerOperation({
IRNodeTypes,
type VaporDirectiveNode,
} from '../ir'
-import { findProp, propToExpression } from '../utils'
+import { findProp, isStaticExpression, propToExpression } from '../utils'
import { newBlock, wrapTemplate } from './utils'
export const transformVFor: NodeTransform = createStructuralDirectiveTransform(
index: index as SimpleExpressionNode | undefined,
keyProp: keyProperty,
render,
- once: context.inVOnce,
+ once:
+ context.inVOnce ||
+ isStaticExpression(
+ source as SimpleExpressionNode,
+ context.options.bindingMetadata,
+ ),
component: isComponent,
onlyChild: !!isOnlyChild,
})
import { extend } from '@vue/shared'
import { newBlock, wrapTemplate } from './utils'
import { getSiblingIf } from './transformComment'
+import { isStaticExpression } from '../utils'
export const transformVIf: NodeTransform = createStructuralDirectiveTransform(
['if', 'else', 'else-if'],
id,
condition: dir.exp!,
positive: branch,
- once: context.inVOnce,
+ once:
+ context.inVOnce ||
+ isStaticExpression(dir.exp!, context.options.bindingMetadata),
})
}
} else {
import { isGloballyAllowed } from '@vue/shared'
import {
type AttributeNode,
+ type BindingMetadata,
BindingTypes,
type ElementNode,
NodeTypes,
} from '@vue/compiler-dom'
import type { VaporDirectiveNode } from './ir'
import { EMPTY_EXPRESSION } from './transforms/utils'
-import type { TransformContext } from './transform'
export const findProp = _findProp as (
node: ElementNode,
}
export function isStaticExpression(
- context: TransformContext,
- expressions: SimpleExpressionNode[],
+ node: SimpleExpressionNode,
+ bindings: BindingMetadata,
): boolean {
- const {
- options: { bindingMetadata },
- } = context
- const isLiteralConst = (name: string) =>
- bindingMetadata[name] === BindingTypes.LITERAL_CONST
- return expressions.every(node => {
- if (node.ast) {
- return isConstantNode(node.ast, isLiteralConst)
- } else if (node.ast === null) {
- return isLiteralConst(node.content)
- }
- })
+ if (node.ast) {
+ return isConstantNode(node.ast, bindings)
+ } else if (node.ast === null) {
+ const type = bindings[node.content]
+ return type === BindingTypes.LITERAL_CONST
+ }
+ return false
}
export function resolveExpression(