fix(compiler): improve auto prefixing cases
This commit is contained in:
parent
262be6733c
commit
6377af483b
@ -308,6 +308,59 @@ describe('compiler: expression transform', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix default value of a function expression param', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ (foo = baz) => foo + bar }}`
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [
|
||||
`(`,
|
||||
{ content: `foo` },
|
||||
` = `,
|
||||
{ content: `_ctx.baz` },
|
||||
`) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix function param destructuring', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ ({ foo }) => foo + bar }}`
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [
|
||||
`({ foo }) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix default value of function param destructuring', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ ({ foo = bar }) => foo + bar }}`
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [
|
||||
`({ `,
|
||||
{ content: `foo` },
|
||||
` = `,
|
||||
{ content: `_ctx.bar` },
|
||||
` }) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix an object property key', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { foo: bar } }}`
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
createCompoundExpression
|
||||
} from '../ast'
|
||||
import { Node, Function, Identifier, Property } from 'estree'
|
||||
import { advancePositionWithClone } from '../utils'
|
||||
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
||||
|
||||
export const transformExpression: NodeTransform = (node, context) => {
|
||||
if (node.type === NodeTypes.INTERPOLATION) {
|
||||
@ -31,19 +31,19 @@ export const transformExpression: NodeTransform = (node, context) => {
|
||||
} else if (node.type === NodeTypes.ELEMENT) {
|
||||
// handle directives on element
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const prop = node.props[i]
|
||||
if (prop.type === NodeTypes.DIRECTIVE) {
|
||||
const exp = prop.exp as SimpleExpressionNode | undefined
|
||||
const arg = prop.arg as SimpleExpressionNode | undefined
|
||||
const dir = node.props[i]
|
||||
if (dir.type === NodeTypes.DIRECTIVE) {
|
||||
const exp = dir.exp as SimpleExpressionNode | undefined
|
||||
const arg = dir.arg as SimpleExpressionNode | undefined
|
||||
if (exp) {
|
||||
prop.exp = processExpression(exp, context)
|
||||
dir.exp = processExpression(exp, context, dir.name === 'slot')
|
||||
}
|
||||
if (arg && !arg.isStatic) {
|
||||
if (prop.name === 'class') {
|
||||
if (dir.name === 'class') {
|
||||
// TODO special expression optimization for classes
|
||||
prop.arg = processExpression(arg, context)
|
||||
dir.arg = processExpression(arg, context)
|
||||
} else {
|
||||
prop.arg = processExpression(arg, context)
|
||||
dir.arg = processExpression(arg, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,14 +51,6 @@ export const transformExpression: NodeTransform = (node, context) => {
|
||||
}
|
||||
}
|
||||
|
||||
const simpleIdRE = /^[a-zA-Z$_][\w$]*$/
|
||||
|
||||
const isFunction = (node: Node): node is Function =>
|
||||
/Function(Expression|Declaration)$/.test(node.type)
|
||||
|
||||
const isPropertyKey = (node: Node, parent: Node) =>
|
||||
parent.type === 'Property' && parent.key === node && !parent.computed
|
||||
|
||||
// cache node requires
|
||||
let _parseScript: typeof parseScript
|
||||
let _walk: typeof walk
|
||||
@ -74,14 +66,15 @@ interface PrefixMeta {
|
||||
// tree-shaken from the browser build.
|
||||
export function processExpression(
|
||||
node: SimpleExpressionNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
asParams: boolean = false
|
||||
): ExpressionNode {
|
||||
if (!context.prefixIdentifiers) {
|
||||
return node
|
||||
}
|
||||
|
||||
// fast path if expression is a simple identifier.
|
||||
if (simpleIdRE.test(node.content)) {
|
||||
if (isSimpleIdentifier(node.content)) {
|
||||
if (!context.identifiers[node.content]) {
|
||||
node.content = `_ctx.${node.content}`
|
||||
}
|
||||
@ -95,8 +88,11 @@ export function processExpression(
|
||||
const walk = _walk || (_walk = require('estree-walker').walk)
|
||||
|
||||
let ast
|
||||
// if the expression is supposed to be used in a function params position
|
||||
// we need to parse it differently.
|
||||
const source = `(${node.content})${asParams ? `=>{}` : ``}`
|
||||
try {
|
||||
ast = parseScript(`(${node.content})`, { ranges: true }) as any
|
||||
ast = parseScript(source, { ranges: true }) as any
|
||||
} catch (e) {
|
||||
context.onError(e)
|
||||
return node
|
||||
@ -132,8 +128,17 @@ export function processExpression(
|
||||
// so that we don't prefix them
|
||||
node.params.forEach(p =>
|
||||
walk(p, {
|
||||
enter(child) {
|
||||
if (child.type === 'Identifier') {
|
||||
enter(child, parent) {
|
||||
if (
|
||||
child.type === 'Identifier' &&
|
||||
!// do not keep as scope variable if this is a default value
|
||||
// assignment of a param
|
||||
(
|
||||
parent &&
|
||||
parent.type === 'AssignmentPattern' &&
|
||||
parent.right === child
|
||||
)
|
||||
) {
|
||||
knownIds[child.name] = true
|
||||
;(
|
||||
(node as any)._scopeIds ||
|
||||
@ -187,6 +192,12 @@ export function processExpression(
|
||||
}
|
||||
}
|
||||
|
||||
const isFunction = (node: Node): node is Function =>
|
||||
/Function(Expression|Declaration)$/.test(node.type)
|
||||
|
||||
const isPropertyKey = (node: Node, parent: Node) =>
|
||||
parent.type === 'Property' && parent.key === node && !parent.computed
|
||||
|
||||
const globals = new Set(
|
||||
(
|
||||
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
||||
|
Loading…
Reference in New Issue
Block a user