diff --git a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts index 0b68b42d..885bdc01 100644 --- a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts @@ -1,8 +1,93 @@ -import { compile } from '../../src' +import { + parse, + transform, + ExpressionNode, + ElementNode, + DirectiveNode +} from '../../src' +import { transformFor } from '../..//src/transforms/vFor' +import { transformExpression } from '../../src/transforms/transformExpression' -test(`should work`, () => { - const { code } = compile(`
{{ foo }} bar
`, { - prefixIdentifiers: true +function parseWithExpressionTransform(template: string) { + const ast = parse(template) + transform(ast, { + prefixIdentifiers: true, + nodeTransforms: [transformFor, transformExpression] }) - expect(code).toContain(`foo`) + return ast.children[0] +} + +describe('compiler: expression transform', () => { + test('interpolation (root)', () => { + const node = parseWithExpressionTransform(`{{ foo }}`) as ExpressionNode + expect(node.content).toBe(`_ctx.foo`) + }) + + test('interpolation (children)', () => { + const node = parseWithExpressionTransform( + `
{{ foo }}
` + ) as ElementNode + expect((node.children[0] as ExpressionNode).content).toBe(`_ctx.foo`) + }) + + test('directive value', () => { + const node = parseWithExpressionTransform( + `
` + ) as ElementNode + expect((node.props[0] as DirectiveNode).arg!.content).toBe(`arg`) + expect((node.props[0] as DirectiveNode).exp!.content).toBe(`_ctx.baz`) + }) + + test('dynamic directive arg', () => { + const node = parseWithExpressionTransform( + `
` + ) as ElementNode + expect((node.props[0] as DirectiveNode).arg!.content).toBe(`_ctx.arg`) + expect((node.props[0] as DirectiveNode).exp!.content).toBe(`_ctx.baz`) + }) + + test('should prefix complex expressions', () => { + const node = parseWithExpressionTransform( + `{{ foo(baz + 1, { key: kuz }) }}` + ) as ExpressionNode + // should parse into compound expression + expect(node.children).toMatchObject([ + { content: `_ctx.foo` }, + `(`, + { content: `_ctx.baz` }, + ` + 1, { key: `, + { content: `_ctx.kuz` }, + ` })` + ]) + }) + + // TODO FIXME + test('should not prefix v-for aliases', () => { + // const node = parseWithExpressionTransform(`{{ { foo } }}`) as ExpressionNode + // expect(node.children).toMatchObject([ + // `{ foo: `, + // { content: `_ctx.foo` }, + // ` }` + // ]) + }) + + test('should prefix id outside of v-for', () => {}) + + test('nested v-for', () => {}) + + test('should not prefix whitelisted globals', () => {}) + + test('should not prefix id of a function declaration', () => {}) + + test('should not prefix params of a function expression', () => { + // also test object + array destructure + }) + + test('should not prefix an object property key', () => {}) + + test('should prefix a computed object property key', () => {}) + + test('should prefix object property shorthand value', () => {}) + + test('should not prefix id in a member expression', () => {}) }) diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 0259c3bb..e07a20f7 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -294,17 +294,18 @@ function genExpressionAsPropertyKey( node: ExpressionNode, context: CodegenContext ) { - if (node.children) { - return genCompoundExpression(node, context) - } - if (node.isStatic) { + const { push } = context + const { content, children, isStatic } = node + if (children) { + push(`[`) + genCompoundExpression(node, context) + push(`]`) + } else if (isStatic) { // only quote keys if necessary - const text = /^\d|[^\w]/.test(node.content) - ? JSON.stringify(node.content) - : node.content - context.push(text, node) + const text = /^\d|[^\w]/.test(content) ? JSON.stringify(content) : content + push(text, node) } else { - context.push(`[${node.content}]`, node) + push(`[${content}]`, node) } } diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index adc9ee1c..55c24b53 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -74,11 +74,13 @@ export function processExpression( walk(ast, { enter(node, parent) { if (node.type === 'Identifier') { - if (ids.indexOf(node) === -1) { + if ( + ids.indexOf(node) === -1 && + !knownIds[node.name] && + shouldPrefix(node, parent) + ) { + node.name = `_ctx.${node.name}` ids.push(node) - if (!knownIds[node.name] && shouldPrefix(node, parent)) { - node.name = `_ctx.${node.name}` - } } } else if (isFunction(node)) { node.params.forEach(p => @@ -123,11 +125,13 @@ export function processExpression( }) ) if (i === ids.length - 1 && id.end < full.length - 1) { - children.push(full.slice(id.end)) + children.push(full.slice(id.end - 1)) } }) - node.children = children + if (children.length) { + node.children = children + } } const globals = new Set(