From 9c2de6244cd44bc5fbfd82b5850c710ce725044f Mon Sep 17 00:00:00 2001 From: edison Date: Mon, 29 Apr 2024 11:47:40 +0800 Subject: [PATCH 1/2] fix(runtime-core): ensure slot compiler marker writable (#10825) close #10818 --- packages/runtime-core/src/componentSlots.ts | 2 +- packages/shared/src/general.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index aeba4d5c6b0..2bc3466c459 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -171,7 +171,7 @@ export const initSlots = ( if (type) { extend(slots, children as InternalSlots) // make compiler marker non-enumerable - def(slots, '_', type) + def(slots, '_', type, true) } else { normalizeObjectSlots(children as RawSlots, slots, instance) } diff --git a/packages/shared/src/general.ts b/packages/shared/src/general.ts index 47ab0229255..fb884695d33 100644 --- a/packages/shared/src/general.ts +++ b/packages/shared/src/general.ts @@ -139,10 +139,16 @@ export const invokeArrayFns = (fns: Function[], arg?: any) => { } } -export const def = (obj: object, key: string | symbol, value: any) => { +export const def = ( + obj: object, + key: string | symbol, + value: any, + writable = false, +) => { Object.defineProperty(obj, key, { configurable: true, enumerable: false, + writable, value, }) } From 09b4df809e59ef5f4bc91acfc56dc8f82a8e243a Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 29 Apr 2024 12:21:24 +0800 Subject: [PATCH 2/2] fix(compiler-core): remove unnecessary constant bail check member expressions and call expressions can only happen when there are identifiers close #10807 --- .../transforms/transformExpressions.spec.ts | 10 ++++++++++ packages/compiler-core/src/babelUtils.ts | 3 +++ .../src/transforms/transformExpression.ts | 12 ++---------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts index 4f08aeb9b22..8ecc2fb0fb8 100644 --- a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts @@ -421,6 +421,16 @@ describe('compiler: expression transform', () => { }) }) + // #10807 + test('should not bail constant on strings w/ ()', () => { + const node = parseWithExpressionTransform( + `{{ { foo: 'ok()' } }}`, + ) as InterpolationNode + expect(node.content).toMatchObject({ + constType: ConstantTypes.CAN_STRINGIFY, + }) + }) + describe('ES Proposals support', () => { test('bigInt', () => { const node = parseWithExpressionTransform( diff --git a/packages/compiler-core/src/babelUtils.ts b/packages/compiler-core/src/babelUtils.ts index b12a6d9b47f..d3812f84ce6 100644 --- a/packages/compiler-core/src/babelUtils.ts +++ b/packages/compiler-core/src/babelUtils.ts @@ -10,6 +10,9 @@ import type { } from '@babel/types' import { walk } from 'estree-walker' +/** + * Return value indicates whether the AST walked can be a constant + */ export function walkIdentifiers( root: Node, onIdentifier: ( diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index 53a4bc5925f..2d8dc8bc850 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -46,10 +46,6 @@ import { BindingTypes } from '../options' const isLiteralWhitelisted = /*#__PURE__*/ makeMap('true,false,null,this') -// a heuristic safeguard to bail constant expressions on presence of -// likely function invocation and member access -const constantBailRE = /\w\s*\(|\.[^\d]/ - export const transformExpression: NodeTransform = (node, context) => { if (node.type === NodeTypes.INTERPOLATION) { node.content = processExpression( @@ -226,8 +222,6 @@ export function processExpression( // fast path if expression is a simple identifier. const rawExp = node.content - // bail constant on parens (function invocation) and dot (member access) - const bailConstant = constantBailRE.test(rawExp) let ast = node.ast @@ -317,7 +311,7 @@ export function processExpression( } else { // The identifier is considered constant unless it's pointing to a // local scope variable (a v-for alias, or a v-slot prop) - if (!(needPrefix && isLocal) && !bailConstant) { + if (!(needPrefix && isLocal)) { ;(node as QualifiedId).isConstant = true } // also generate sub-expressions for other identifiers for better @@ -371,9 +365,7 @@ export function processExpression( ret.ast = ast } else { ret = node - ret.constType = bailConstant - ? ConstantTypes.NOT_CONSTANT - : ConstantTypes.CAN_STRINGIFY + ret.constType = ConstantTypes.CAN_STRINGIFY } ret.identifiers = Object.keys(knownIds) return ret