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', () => {
|
test('should not prefix an object property key', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { foo: bar } }}`
|
`{{ { foo: bar } }}`
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
createCompoundExpression
|
createCompoundExpression
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { Node, Function, Identifier, Property } from 'estree'
|
import { Node, Function, Identifier, Property } from 'estree'
|
||||||
import { advancePositionWithClone } from '../utils'
|
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
||||||
|
|
||||||
export const transformExpression: NodeTransform = (node, context) => {
|
export const transformExpression: NodeTransform = (node, context) => {
|
||||||
if (node.type === NodeTypes.INTERPOLATION) {
|
if (node.type === NodeTypes.INTERPOLATION) {
|
||||||
@ -31,19 +31,19 @@ export const transformExpression: NodeTransform = (node, context) => {
|
|||||||
} else if (node.type === NodeTypes.ELEMENT) {
|
} else if (node.type === NodeTypes.ELEMENT) {
|
||||||
// handle directives on element
|
// handle directives on element
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const prop = node.props[i]
|
const dir = node.props[i]
|
||||||
if (prop.type === NodeTypes.DIRECTIVE) {
|
if (dir.type === NodeTypes.DIRECTIVE) {
|
||||||
const exp = prop.exp as SimpleExpressionNode | undefined
|
const exp = dir.exp as SimpleExpressionNode | undefined
|
||||||
const arg = prop.arg as SimpleExpressionNode | undefined
|
const arg = dir.arg as SimpleExpressionNode | undefined
|
||||||
if (exp) {
|
if (exp) {
|
||||||
prop.exp = processExpression(exp, context)
|
dir.exp = processExpression(exp, context, dir.name === 'slot')
|
||||||
}
|
}
|
||||||
if (arg && !arg.isStatic) {
|
if (arg && !arg.isStatic) {
|
||||||
if (prop.name === 'class') {
|
if (dir.name === 'class') {
|
||||||
// TODO special expression optimization for classes
|
// TODO special expression optimization for classes
|
||||||
prop.arg = processExpression(arg, context)
|
dir.arg = processExpression(arg, context)
|
||||||
} else {
|
} 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
|
// cache node requires
|
||||||
let _parseScript: typeof parseScript
|
let _parseScript: typeof parseScript
|
||||||
let _walk: typeof walk
|
let _walk: typeof walk
|
||||||
@ -74,14 +66,15 @@ interface PrefixMeta {
|
|||||||
// tree-shaken from the browser build.
|
// tree-shaken from the browser build.
|
||||||
export function processExpression(
|
export function processExpression(
|
||||||
node: SimpleExpressionNode,
|
node: SimpleExpressionNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
|
asParams: boolean = false
|
||||||
): ExpressionNode {
|
): ExpressionNode {
|
||||||
if (!context.prefixIdentifiers) {
|
if (!context.prefixIdentifiers) {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
// fast path if expression is a simple identifier.
|
// fast path if expression is a simple identifier.
|
||||||
if (simpleIdRE.test(node.content)) {
|
if (isSimpleIdentifier(node.content)) {
|
||||||
if (!context.identifiers[node.content]) {
|
if (!context.identifiers[node.content]) {
|
||||||
node.content = `_ctx.${node.content}`
|
node.content = `_ctx.${node.content}`
|
||||||
}
|
}
|
||||||
@ -95,8 +88,11 @@ export function processExpression(
|
|||||||
const walk = _walk || (_walk = require('estree-walker').walk)
|
const walk = _walk || (_walk = require('estree-walker').walk)
|
||||||
|
|
||||||
let ast
|
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 {
|
try {
|
||||||
ast = parseScript(`(${node.content})`, { ranges: true }) as any
|
ast = parseScript(source, { ranges: true }) as any
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.onError(e)
|
context.onError(e)
|
||||||
return node
|
return node
|
||||||
@ -132,8 +128,17 @@ export function processExpression(
|
|||||||
// so that we don't prefix them
|
// so that we don't prefix them
|
||||||
node.params.forEach(p =>
|
node.params.forEach(p =>
|
||||||
walk(p, {
|
walk(p, {
|
||||||
enter(child) {
|
enter(child, parent) {
|
||||||
if (child.type === 'Identifier') {
|
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
|
knownIds[child.name] = true
|
||||||
;(
|
;(
|
||||||
(node as any)._scopeIds ||
|
(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(
|
const globals = new Set(
|
||||||
(
|
(
|
||||||
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
||||||
|
Loading…
Reference in New Issue
Block a user