diff --git a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap index 2bdb4afa4..a9591f922 100644 --- a/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap @@ -54,7 +54,7 @@ return function render(_ctx, _cache) { [foo + bar]: bar }, [ _createElementVNode("p", { "some-key": "foo" }) - ], 16) + ], 16 /* FULL_PROPS */) } }" `; @@ -98,7 +98,7 @@ exports[`compiler: codegen > forNode 1`] = ` " return function render(_ctx, _cache) { with (_ctx) { - return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(), 1)) + return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(), 1 /* TEXT */)) } }" `; diff --git a/packages/compiler-core/__tests__/codegen.spec.ts b/packages/compiler-core/__tests__/codegen.spec.ts index 9c9230756..4a5ba7d5c 100644 --- a/packages/compiler-core/__tests__/codegen.spec.ts +++ b/packages/compiler-core/__tests__/codegen.spec.ts @@ -267,7 +267,7 @@ describe('compiler: codegen', () => { disableTracking: true, props: undefined, children: createCallExpression(RENDER_LIST), - patchFlag: '1', + patchFlag: PatchFlags.TEXT, dynamicProps: undefined, directives: undefined, loc: locStub, @@ -303,7 +303,7 @@ describe('compiler: codegen', () => { disableTracking: false, props: undefined, children: createCallExpression(RENDER_LIST), - patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT), + patchFlag: PatchFlags.STABLE_FRAGMENT, dynamicProps: undefined, directives: undefined, loc: locStub, @@ -364,7 +364,7 @@ describe('compiler: codegen', () => { ), ], // flag - PatchFlags.FULL_PROPS + '', + PatchFlags.FULL_PROPS, ), }), ) @@ -375,7 +375,7 @@ describe('compiler: codegen', () => { [foo + bar]: bar }, [ _${helperNameMap[CREATE_ELEMENT_VNODE]}("p", { "some-key": "foo" }) - ], ${PatchFlags.FULL_PROPS})`) + ], ${genFlagText(PatchFlags.FULL_PROPS)})`) expect(code).toMatchSnapshot() }) @@ -666,11 +666,14 @@ describe('compiler: codegen', () => { }) test('with patchFlag and no children/props', () => { - expect(genCode(createVNodeCall(null, `"div"`, undefined, undefined, '1'))) - .toMatchInlineSnapshot(` - "return _createElementVNode("div", null, null, 1) - " - `) + expect( + genCode( + createVNodeCall(null, `"div"`, undefined, undefined, PatchFlags.TEXT), + ), + ).toMatchInlineSnapshot(` + "return _createElementVNode("div", null, null, 1 /* TEXT */) + " + `) }) test('as block', () => { diff --git a/packages/compiler-core/__tests__/transform.spec.ts b/packages/compiler-core/__tests__/transform.spec.ts index a56be51bc..0946d3648 100644 --- a/packages/compiler-core/__tests__/transform.spec.ts +++ b/packages/compiler-core/__tests__/transform.spec.ts @@ -19,7 +19,6 @@ import { transformFor } from '../src/transforms/vFor' import { transformElement } from '../src/transforms/transformElement' import { transformSlotOutlet } from '../src/transforms/transformSlotOutlet' import { transformText } from '../src/transforms/transformText' -import { genFlagText } from './testUtils' import { PatchFlags } from '@vue/shared' describe('compiler: transform', () => { @@ -358,7 +357,7 @@ describe('compiler: transform', () => { { type: NodeTypes.ELEMENT, tag: `div` }, { type: NodeTypes.ELEMENT, tag: `div` }, ] as any, - genFlagText(PatchFlags.STABLE_FRAGMENT), + PatchFlags.STABLE_FRAGMENT, ), ) }) @@ -374,10 +373,7 @@ describe('compiler: transform', () => { { type: NodeTypes.ELEMENT, tag: `div` }, { type: NodeTypes.COMMENT }, ] as any, - genFlagText([ - PatchFlags.STABLE_FRAGMENT, - PatchFlags.DEV_ROOT_FRAGMENT, - ]), + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, ), ) }) diff --git a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts index d6c46b52e..d5a34243b 100644 --- a/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts +++ b/packages/compiler-core/__tests__/transforms/hoistStatic.spec.ts @@ -21,7 +21,7 @@ import { transformIf } from '../../src/transforms/vIf' import { transformFor } from '../../src/transforms/vFor' import { transformBind } from '../../src/transforms/vBind' import { transformOn } from '../../src/transforms/vOn' -import { createObjectMatcher, genFlagText } from '../testUtils' +import { createObjectMatcher } from '../testUtils' import { transformText } from '../../src/transforms/transformText' import { PatchFlags } from '@vue/shared' @@ -180,7 +180,7 @@ describe('compiler: hoistStatic transform', () => { id: `[foo]`, }), children: undefined, - patchFlag: genFlagText(PatchFlags.PROPS), + patchFlag: PatchFlags.PROPS, dynamicProps: { type: NodeTypes.SIMPLE_EXPRESSION, content: `_hoisted_1`, @@ -242,7 +242,7 @@ describe('compiler: hoistStatic transform', () => { ref: `[foo]`, }), children: undefined, - patchFlag: genFlagText(PatchFlags.NEED_PATCH), + patchFlag: PatchFlags.NEED_PATCH, }, }, ]) @@ -263,7 +263,7 @@ describe('compiler: hoistStatic transform', () => { content: `_hoisted_1`, }, children: undefined, - patchFlag: genFlagText(PatchFlags.NEED_PATCH), + patchFlag: PatchFlags.NEED_PATCH, directives: { type: NodeTypes.JS_ARRAY_EXPRESSION, }, @@ -286,7 +286,7 @@ describe('compiler: hoistStatic transform', () => { tag: `"div"`, props: { content: `_hoisted_1` }, children: { type: NodeTypes.INTERPOLATION }, - patchFlag: genFlagText(PatchFlags.TEXT), + patchFlag: PatchFlags.TEXT, }, }, ]) @@ -365,7 +365,7 @@ describe('compiler: hoistStatic transform', () => { type: NodeTypes.JS_CALL_EXPRESSION, callee: RENDER_LIST, }, - patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT), + patchFlag: PatchFlags.UNKEYED_FRAGMENT, }) const innerBlockCodegen = forBlockCodegen!.children.arguments[1] expect(innerBlockCodegen.returns).toMatchObject({ @@ -496,7 +496,7 @@ describe('compiler: hoistStatic transform', () => { constType: ConstantTypes.NOT_CONSTANT, }, }, - patchFlag: `1 /* TEXT */`, + patchFlag: PatchFlags.TEXT, }, }, ], diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index 10b9747d1..bf3510a05 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -37,7 +37,7 @@ import { transformStyle } from '../../../compiler-dom/src/transforms/transformSt import { transformOn } from '../../src/transforms/vOn' import { transformBind } from '../../src/transforms/vBind' import { PatchFlags } from '@vue/shared' -import { createObjectMatcher, genFlagText } from '../testUtils' +import { createObjectMatcher } from '../testUtils' import { transformText } from '../../src/transforms/transformText' import { parseWithForTransform } from './vFor.spec' @@ -521,7 +521,7 @@ describe('compiler: element transform', () => { // keep-alive should not compile content to slots children: [{ type: NodeTypes.ELEMENT, tag: 'span' }], // should get a dynamic slots flag to force updates - patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS), + patchFlag: PatchFlags.DYNAMIC_SLOTS, }) } @@ -588,7 +588,7 @@ describe('compiler: element transform', () => { }) // should factor in props returned by custom directive transforms // in patchFlag analysis - expect(node.patchFlag).toMatch(PatchFlags.PROPS + '') + expect(node.patchFlag).toBe(PatchFlags.PROPS) expect(node.dynamicProps).toMatch(`"bar"`) }) @@ -612,7 +612,7 @@ describe('compiler: element transform', () => { tag: `"div"`, props: undefined, children: undefined, - patchFlag: genFlagText(PatchFlags.NEED_PATCH), // should generate appropriate flag + patchFlag: PatchFlags.NEED_PATCH, // should generate appropriate flag directives: { type: NodeTypes.JS_ARRAY_EXPRESSION, elements: [ @@ -945,26 +945,26 @@ describe('compiler: element transform', () => { expect(node.patchFlag).toBeUndefined() const { node: node2 } = parseWithBind(`
{{ foo }}
`) - expect(node2.patchFlag).toBe(genFlagText(PatchFlags.TEXT)) + expect(node2.patchFlag).toBe(PatchFlags.TEXT) // multiple nodes, merged with optimize text const { node: node3 } = parseWithBind(`
foo {{ bar }} baz
`) - expect(node3.patchFlag).toBe(genFlagText(PatchFlags.TEXT)) + expect(node3.patchFlag).toBe(PatchFlags.TEXT) }) test('CLASS', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.CLASS)) + expect(node.patchFlag).toBe(PatchFlags.CLASS) }) test('STYLE', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.STYLE)) + expect(node.patchFlag).toBe(PatchFlags.STYLE) }) test('PROPS', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.PROPS)) + expect(node.patchFlag).toBe(PatchFlags.PROPS) expect(node.dynamicProps).toBe(`["foo", "baz"]`) }) @@ -973,7 +973,7 @@ describe('compiler: element transform', () => { `
`, ) expect(node.patchFlag).toBe( - genFlagText([PatchFlags.CLASS, PatchFlags.STYLE, PatchFlags.PROPS]), + PatchFlags.CLASS | PatchFlags.STYLE | PatchFlags.PROPS, ) expect(node.dynamicProps).toBe(`["foo", "baz"]`) }) @@ -983,40 +983,40 @@ describe('compiler: element transform', () => { const { node } = parseWithBind( ``, ) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.PROPS)) + expect(node.patchFlag).toBe(PatchFlags.PROPS) expect(node.dynamicProps).toBe(`["id", "class", "style"]`) }) test('FULL_PROPS (v-bind)', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.FULL_PROPS)) + expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS) }) test('FULL_PROPS (dynamic key)', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.FULL_PROPS)) + expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS) }) test('FULL_PROPS (w/ others)', () => { const { node } = parseWithBind( `
`, ) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.FULL_PROPS)) + expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS) }) test('NEED_PATCH (static ref)', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH)) + expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH) }) test('NEED_PATCH (dynamic ref)', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH)) + expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH) }) test('NEED_PATCH (custom directives)', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH)) + expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH) }) test('NEED_PATCH (vnode hooks)', () => { @@ -1025,7 +1025,7 @@ describe('compiler: element transform', () => { cacheHandlers: true, }).ast const node = (root as any).children[0].codegenNode - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH)) + expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH) }) test('script setup inline mode template ref (binding exists)', () => { @@ -1120,7 +1120,7 @@ describe('compiler: element transform', () => { }, }) // should only have props flag - expect(node.patchFlag).toBe(genFlagText(PatchFlags.PROPS)) + expect(node.patchFlag).toBe(PatchFlags.PROPS) const { node: node2 } = parseWithElementTransform( `
`, @@ -1130,21 +1130,15 @@ describe('compiler: element transform', () => { }, }, ) - expect(node2.patchFlag).toBe( - genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION]), - ) + expect(node2.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION) }) test('NEED_HYDRATION for v-bind.prop', () => { const { node } = parseWithBind(`
`) - expect(node.patchFlag).toBe( - genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION]), - ) + expect(node.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION) const { node: node2 } = parseWithBind(`
`) - expect(node2.patchFlag).toBe( - genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION]), - ) + expect(node2.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION) }) // #5870 @@ -1157,9 +1151,7 @@ describe('compiler: element transform', () => { }, }, ) - expect(node.patchFlag).toBe( - genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION]), - ) + expect(node.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION) }) test('should not have PROPS patchflag for constant v-on handlers', () => { @@ -1173,7 +1165,7 @@ describe('compiler: element transform', () => { }, }) // should only have hydration flag - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION)) + expect(node.patchFlag).toBe(PatchFlags.NEED_HYDRATION) }) }) diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts index 94f75f2a6..d0e95fcbc 100644 --- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts @@ -18,8 +18,8 @@ import { import { ErrorCodes } from '../../src/errors' import { type CompilerOptions, generate } from '../../src' import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers' -import { PatchFlagNames, PatchFlags } from '@vue/shared' -import { createObjectMatcher, genFlagText } from '../testUtils' +import { PatchFlags } from '@vue/shared' +import { createObjectMatcher } from '../testUtils' export function parseWithForTransform( template: string, @@ -696,10 +696,10 @@ describe('compiler: v-for', () => { tag: FRAGMENT, disableTracking, patchFlag: !disableTracking - ? genFlagText(PatchFlags.STABLE_FRAGMENT) + ? PatchFlags.STABLE_FRAGMENT : keyed - ? genFlagText(PatchFlags.KEYED_FRAGMENT) - : genFlagText(PatchFlags.UNKEYED_FRAGMENT), + ? PatchFlags.KEYED_FRAGMENT + : PatchFlags.UNKEYED_FRAGMENT, children: { type: NodeTypes.JS_CALL_EXPRESSION, callee: RENDER_LIST, @@ -822,7 +822,7 @@ describe('compiler: v-for', () => { constType: ConstantTypes.NOT_CONSTANT, }, }, - patchFlag: genFlagText(PatchFlags.TEXT), + patchFlag: PatchFlags.TEXT, }, }) expect(generate(root).code).toMatchSnapshot() @@ -846,7 +846,7 @@ describe('compiler: v-for', () => { { type: NodeTypes.TEXT, content: `hello` }, { type: NodeTypes.ELEMENT, tag: `span` }, ], - patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT), + patchFlag: PatchFlags.STABLE_FRAGMENT, }, }) expect(generate(root).code).toMatchSnapshot() @@ -950,7 +950,7 @@ describe('compiler: v-for', () => { { type: NodeTypes.TEXT, content: `hello` }, { type: NodeTypes.ELEMENT, tag: `span` }, ], - patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT), + patchFlag: PatchFlags.STABLE_FRAGMENT, }, }) expect(generate(root).code).toMatchSnapshot() @@ -971,7 +971,7 @@ describe('compiler: v-for', () => { }), isBlock: true, disableTracking: true, - patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT), + patchFlag: PatchFlags.UNKEYED_FRAGMENT, children: { type: NodeTypes.JS_CALL_EXPRESSION, callee: RENDER_LIST, @@ -1009,7 +1009,7 @@ describe('compiler: v-for', () => { }), isBlock: true, disableTracking: true, - patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT), + patchFlag: PatchFlags.UNKEYED_FRAGMENT, children: { type: NodeTypes.JS_CALL_EXPRESSION, callee: RENDER_LIST, @@ -1048,9 +1048,7 @@ describe('compiler: v-for', () => { const { node: { codegenNode }, } = parseWithForTransform('
test
') - expect(codegenNode.patchFlag).toBe( - `${PatchFlags.KEYED_FRAGMENT} /* ${PatchFlagNames[PatchFlags.KEYED_FRAGMENT]} */`, - ) + expect(codegenNode.patchFlag).toBe(PatchFlags.KEYED_FRAGMENT) }) test('template v-for key w/ :key shorthand on template injected to the child', () => { diff --git a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts index 3afcf0fc0..4766c2ca9 100644 --- a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts @@ -24,7 +24,7 @@ import { trackVForSlotScopes, } from '../../src/transforms/vSlot' import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers' -import { createObjectMatcher, genFlagText } from '../testUtils' +import { createObjectMatcher } from '../testUtils' import { PatchFlags } from '@vue/shared' import { transformFor } from '../../src/transforms/vFor' import { transformIf } from '../../src/transforms/vIf' @@ -432,7 +432,7 @@ describe('compiler: transform component slots', () => { ), // nested slot should be forced dynamic, since scope variables // are not tracked as dependencies of the slot. - patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS), + patchFlag: PatchFlags.DYNAMIC_SLOTS, }, }, // test scope @@ -474,9 +474,7 @@ describe('compiler: transform component slots', () => { const div = ((root.children[0] as ForNode).children[0] as ElementNode) .codegenNode as any const comp = div.children[0] - expect(comp.codegenNode.patchFlag).toBe( - genFlagText(PatchFlags.DYNAMIC_SLOTS), - ) + expect(comp.codegenNode.patchFlag).toBe(PatchFlags.DYNAMIC_SLOTS) }) test('should only force dynamic slots when actually using scope vars w/ prefixIdentifiers: true', () => { @@ -494,7 +492,7 @@ describe('compiler: transform component slots', () => { flag = (innerComp.codegenNode as VNodeCall).patchFlag } if (shouldForce) { - expect(flag).toBe(genFlagText(PatchFlags.DYNAMIC_SLOTS)) + expect(flag).toBe(PatchFlags.DYNAMIC_SLOTS) } else { expect(flag).toBeUndefined() } @@ -581,8 +579,8 @@ describe('compiler: transform component slots', () => { }, ], }) - expect((root as any).children[0].codegenNode.patchFlag).toMatch( - PatchFlags.DYNAMIC_SLOTS + '', + expect((root as any).children[0].codegenNode.patchFlag).toBe( + PatchFlags.DYNAMIC_SLOTS, ) expect(generate(root).code).toMatchSnapshot() }) @@ -630,8 +628,8 @@ describe('compiler: transform component slots', () => { }, ], }) - expect((root as any).children[0].codegenNode.patchFlag).toMatch( - PatchFlags.DYNAMIC_SLOTS + '', + expect((root as any).children[0].codegenNode.patchFlag).toBe( + PatchFlags.DYNAMIC_SLOTS, ) expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot() }) @@ -693,8 +691,8 @@ describe('compiler: transform component slots', () => { }, ], }) - expect((root as any).children[0].codegenNode.patchFlag).toMatch( - PatchFlags.DYNAMIC_SLOTS + '', + expect((root as any).children[0].codegenNode.patchFlag).toBe( + PatchFlags.DYNAMIC_SLOTS, ) expect((root as any).children[0].children.length).toBe(3) expect(generate(root).code).toMatchSnapshot() @@ -744,8 +742,8 @@ describe('compiler: transform component slots', () => { }, ], }) - expect((root as any).children[0].codegenNode.patchFlag).toMatch( - PatchFlags.DYNAMIC_SLOTS + '', + expect((root as any).children[0].codegenNode.patchFlag).toBe( + PatchFlags.DYNAMIC_SLOTS, ) expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot() }) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 91354b1b4..562e24e72 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -1,4 +1,4 @@ -import { isString } from '@vue/shared' +import { type PatchFlags, isString } from '@vue/shared' import { CREATE_BLOCK, CREATE_ELEMENT_BLOCK, @@ -331,7 +331,7 @@ export interface VNodeCall extends Node { | ForRenderListExpression // v-for fragment call | SimpleExpressionNode // hoisted | undefined - patchFlag: string | undefined + patchFlag: PatchFlags | undefined dynamicProps: string | SimpleExpressionNode | undefined directives: DirectiveArguments | undefined isBlock: boolean @@ -561,7 +561,7 @@ export interface ForCodegenNode extends VNodeCall { tag: typeof FRAGMENT props: undefined children: ForRenderListExpression - patchFlag: string + patchFlag: PatchFlags disableTracking: boolean } diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 39170bac5..4dd51133c 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -35,7 +35,13 @@ import { isSimpleIdentifier, toValidAssetId, } from './utils' -import { isArray, isString, isSymbol } from '@vue/shared' +import { + PatchFlagNames, + type PatchFlags, + isArray, + isString, + isSymbol, +} from '@vue/shared' import { CREATE_COMMENT, CREATE_ELEMENT_VNODE, @@ -843,6 +849,28 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) { disableTracking, isComponent, } = node + + // add dev annotations to patch flags + let patchFlagString + if (patchFlag) { + if (__DEV__) { + if (patchFlag < 0) { + // special flags (negative and mutually exclusive) + patchFlagString = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */` + } else { + // bitwise flags + const flagNames = Object.keys(PatchFlagNames) + .map(Number) + .filter(n => n > 0 && patchFlag & n) + .map(n => PatchFlagNames[n as PatchFlags]) + .join(`, `) + patchFlagString = patchFlag + ` /* ${flagNames} */` + } + } else { + patchFlagString = String(patchFlag) + } + } + if (directives) { push(helper(WITH_DIRECTIVES) + `(`) } @@ -857,7 +885,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) { : getVNodeHelper(context.inSSR, isComponent) push(helper(callHelper) + `(`, NewlineType.None, node) genNodeList( - genNullableArgs([tag, props, children, patchFlag, dynamicProps]), + genNullableArgs([tag, props, children, patchFlagString, dynamicProps]), context, ) push(`)`) diff --git a/packages/compiler-core/src/transform.ts b/packages/compiler-core/src/transform.ts index 69821f7f8..83ed8a920 100644 --- a/packages/compiler-core/src/transform.ts +++ b/packages/compiler-core/src/transform.ts @@ -382,7 +382,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) { helper(FRAGMENT), undefined, root.children, - patchFlag + (__DEV__ ? ` /* ${patchFlagText} */` : ``), + patchFlag, undefined, undefined, true, diff --git a/packages/compiler-core/src/transforms/hoistStatic.ts b/packages/compiler-core/src/transforms/hoistStatic.ts index 67bdaa887..5942b7309 100644 --- a/packages/compiler-core/src/transforms/hoistStatic.ts +++ b/packages/compiler-core/src/transforms/hoistStatic.ts @@ -70,8 +70,7 @@ function walk( : getConstantType(child, context) if (constantType > ConstantTypes.NOT_CONSTANT) { if (constantType >= ConstantTypes.CAN_HOIST) { - ;(child.codegenNode as VNodeCall).patchFlag = - PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``) + ;(child.codegenNode as VNodeCall).patchFlag = PatchFlags.HOISTED child.codegenNode = context.hoist(child.codegenNode!) hoistedCount++ continue @@ -81,9 +80,9 @@ function walk( // hoisting. const codegenNode = child.codegenNode! if (codegenNode.type === NodeTypes.VNODE_CALL) { - const flag = getPatchFlag(codegenNode) + const flag = codegenNode.patchFlag if ( - (!flag || + (flag === undefined || flag === PatchFlags.NEED_PATCH || flag === PatchFlags.TEXT) && getGeneratedPropsConstantType(child, context) >= @@ -179,8 +178,7 @@ export function getConstantType( ) { return ConstantTypes.NOT_CONSTANT } - const flag = getPatchFlag(codegenNode) - if (!flag) { + if (codegenNode.patchFlag === undefined) { let returnType = ConstantTypes.CAN_STRINGIFY // Element itself has no patch flag. However we still need to check: @@ -365,8 +363,3 @@ function getNodeProps(node: PlainElementNode) { return codegenNode.props } } - -function getPatchFlag(node: VNodeCall): number | undefined { - const flag = node.patchFlag - return flag ? parseInt(flag, 10) : undefined -} diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index b1be06db7..ebaf08375 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -23,7 +23,6 @@ import { createVNodeCall, } from '../ast' import { - PatchFlagNames, PatchFlags, camelize, capitalize, @@ -101,8 +100,7 @@ export const transformElement: NodeTransform = (node, context) => { let vnodeProps: VNodeCall['props'] let vnodeChildren: VNodeCall['children'] - let vnodePatchFlag: VNodeCall['patchFlag'] - let patchFlag: number = 0 + let patchFlag: VNodeCall['patchFlag'] | 0 = 0 let vnodeDynamicProps: VNodeCall['dynamicProps'] let dynamicPropNames: string[] | undefined let vnodeDirectives: VNodeCall['directives'] @@ -206,27 +204,8 @@ export const transformElement: NodeTransform = (node, context) => { } // patchFlag & dynamicPropNames - if (patchFlag !== 0) { - if (__DEV__) { - if (patchFlag < 0) { - // special flags (negative and mutually exclusive) - vnodePatchFlag = - patchFlag + ` /* ${PatchFlagNames[patchFlag as PatchFlags]} */` - } else { - // bitwise flags - const flagNames = Object.keys(PatchFlagNames) - .map(Number) - .filter(n => n > 0 && patchFlag & n) - .map(n => PatchFlagNames[n as PatchFlags]) - .join(`, `) - vnodePatchFlag = patchFlag + ` /* ${flagNames} */` - } - } else { - vnodePatchFlag = String(patchFlag) - } - if (dynamicPropNames && dynamicPropNames.length) { - vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames) - } + if (dynamicPropNames && dynamicPropNames.length) { + vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames) } node.codegenNode = createVNodeCall( @@ -234,7 +213,7 @@ export const transformElement: NodeTransform = (node, context) => { vnodeTag, vnodeProps, vnodeChildren, - vnodePatchFlag, + patchFlag === 0 ? undefined : patchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts index 16c48ede0..0db961528 100644 --- a/packages/compiler-core/src/transforms/vFor.ts +++ b/packages/compiler-core/src/transforms/vFor.ts @@ -46,7 +46,7 @@ import { } from '../runtimeHelpers' import { processExpression } from './transformExpression' import { validateBrowserExpression } from '../validateExpression' -import { PatchFlagNames, PatchFlags } from '@vue/shared' +import { PatchFlags } from '@vue/shared' import { transformBindShorthand } from './vBind' export const transformFor = createStructuralDirectiveTransform( @@ -109,8 +109,7 @@ export const transformFor = createStructuralDirectiveTransform( helper(FRAGMENT), undefined, renderExp, - fragmentFlag + - (__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``), + fragmentFlag, undefined, undefined, true /* isBlock */, @@ -169,10 +168,7 @@ export const transformFor = createStructuralDirectiveTransform( helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, - PatchFlags.STABLE_FRAGMENT + - (__DEV__ - ? ` /* ${PatchFlagNames[PatchFlags.STABLE_FRAGMENT]} */` - : ``), + PatchFlags.STABLE_FRAGMENT, undefined, undefined, true, diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts index a6437f89c..06255b25f 100644 --- a/packages/compiler-core/src/transforms/vIf.ts +++ b/packages/compiler-core/src/transforms/vIf.ts @@ -280,7 +280,7 @@ function createChildrenCodegenNode( helper(FRAGMENT), createObjectExpression([keyProperty]), children, - patchFlag + (__DEV__ ? ` /* ${patchFlagText} */` : ``), + patchFlag, undefined, undefined, true, diff --git a/packages/compiler-dom/__tests__/transforms/vHtml.spec.ts b/packages/compiler-dom/__tests__/transforms/vHtml.spec.ts index a59a7a40a..bca2fdf95 100644 --- a/packages/compiler-dom/__tests__/transforms/vHtml.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vHtml.spec.ts @@ -6,10 +6,7 @@ import { } from '@vue/compiler-core' import { transformVHtml } from '../../src/transforms/vHtml' import { transformElement } from '../../../compiler-core/src/transforms/transformElement' -import { - createObjectMatcher, - genFlagText, -} from '../../../compiler-core/__tests__/testUtils' +import { createObjectMatcher } from '../../../compiler-core/__tests__/testUtils' import { PatchFlags } from '@vue/shared' import { DOMErrorCodes } from '../../src/errors' @@ -34,7 +31,7 @@ describe('compiler: v-html transform', () => { innerHTML: `[test]`, }), children: undefined, - patchFlag: genFlagText(PatchFlags.PROPS), + patchFlag: PatchFlags.PROPS, dynamicProps: `["innerHTML"]`, }) }) @@ -53,7 +50,7 @@ describe('compiler: v-html transform', () => { innerHTML: `[test]`, }), children: undefined, // <-- children should have been removed - patchFlag: genFlagText(PatchFlags.PROPS), + patchFlag: PatchFlags.PROPS, dynamicProps: `["innerHTML"]`, }) }) diff --git a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts index 2e8072911..f53fbb69b 100644 --- a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts @@ -14,7 +14,6 @@ import { transformOn } from '../../src/transforms/vOn' import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers' import { transformElement } from '../../../compiler-core/src/transforms/transformElement' import { transformExpression } from '../../../compiler-core/src/transforms/transformExpression' -import { genFlagText } from '../../../compiler-core/__tests__/testUtils' import { PatchFlags } from '@vue/shared' function parseWithVOn(template: string, options: CompilerOptions = {}) { @@ -272,7 +271,7 @@ describe('compiler-dom: transform v-on', () => { // should not treat cached handler as dynamicProp, so it should have no // dynamicProps flags and only the hydration flag expect((root as any).children[0].codegenNode.patchFlag).toBe( - genFlagText(PatchFlags.NEED_HYDRATION), + PatchFlags.NEED_HYDRATION, ) expect(prop).toMatchObject({ key: { @@ -300,6 +299,6 @@ describe('compiler-dom: transform v-on', () => { }, }) // should only have hydration flag - expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION)) + expect(node.patchFlag).toBe(PatchFlags.NEED_HYDRATION) }) }) diff --git a/packages/compiler-dom/__tests__/transforms/vText.spec.ts b/packages/compiler-dom/__tests__/transforms/vText.spec.ts index 1b717e833..e96ab2972 100644 --- a/packages/compiler-dom/__tests__/transforms/vText.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vText.spec.ts @@ -6,10 +6,7 @@ import { } from '@vue/compiler-core' import { transformVText } from '../../src/transforms/vText' import { transformElement } from '../../../compiler-core/src/transforms/transformElement' -import { - createObjectMatcher, - genFlagText, -} from '../../../compiler-core/__tests__/testUtils' +import { createObjectMatcher } from '../../../compiler-core/__tests__/testUtils' import { PatchFlags } from '@vue/shared' import { DOMErrorCodes } from '../../src/errors' @@ -36,7 +33,7 @@ describe('compiler: v-text transform', () => { }, }), children: undefined, - patchFlag: genFlagText(PatchFlags.PROPS), + patchFlag: PatchFlags.PROPS, dynamicProps: `["textContent"]`, }) }) @@ -57,7 +54,7 @@ describe('compiler: v-text transform', () => { }, }), children: undefined, // <-- children should have been removed - patchFlag: genFlagText(PatchFlags.PROPS), + patchFlag: PatchFlags.PROPS, dynamicProps: `["textContent"]`, }) }) diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 53974bc93..60941d036 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -1317,76 +1317,83 @@ describe('SSR hydration', () => { // #10607 test('update component stable slot (prod + optimized mode)', async () => { __DEV__ = false - const container = document.createElement('div') - container.innerHTML = `` - const Comp = { - render(this: any) { - return ( - openBlock(), - createElementBlock('div', null, [renderSlot(this.$slots, 'default')]) - ) - }, - } - const show = ref(false) - const clicked = ref(false) - - const Wrapper = { - setup() { - const items = ref([]) - onMounted(() => { - items.value = [1] - }) - return () => { + try { + const container = document.createElement('div') + container.innerHTML = `` + const Comp = { + render(this: any) { return ( openBlock(), - createBlock(Comp, null, { - default: withCtx(() => [ - createElementVNode('div', null, [ - createElementVNode('div', null, [ - clicked.value - ? (openBlock(), - createElementBlock('div', { key: 0 }, 'foo')) - : createCommentVNode('v-if', true), - ]), - ]), - createElementVNode( - 'div', - null, - items.value.length, - 1 /* TEXT */, - ), - ]), - _: 1 /* STABLE */, - }) + createElementBlock('div', null, [ + renderSlot(this.$slots, 'default'), + ]) ) - } - }, - } - createSSRApp({ - components: { Wrapper }, - data() { - return { show } - }, - template: ``, - }).mount(container) + }, + } + const show = ref(false) + const clicked = ref(false) - await nextTick() - expect(container.innerHTML).toBe( - `
1
`, - ) + const Wrapper = { + setup() { + const items = ref([]) + onMounted(() => { + items.value = [1] + }) + return () => { + return ( + openBlock(), + createBlock(Comp, null, { + default: withCtx(() => [ + createElementVNode('div', null, [ + createElementVNode('div', null, [ + clicked.value + ? (openBlock(), + createElementBlock('div', { key: 0 }, 'foo')) + : createCommentVNode('v-if', true), + ]), + ]), + createElementVNode( + 'div', + null, + items.value.length, + 1 /* TEXT */, + ), + ]), + _: 1 /* STABLE */, + }) + ) + } + }, + } + createSSRApp({ + components: { Wrapper }, + data() { + return { show } + }, + template: ``, + }).mount(container) - show.value = true - await nextTick() - expect(async () => { - clicked.value = true await nextTick() - }).not.toThrow("Cannot read properties of null (reading 'insertBefore')") + expect(container.innerHTML).toBe( + `
1
`, + ) - await nextTick() - expect(container.innerHTML).toBe( - `
foo
1
`, - ) - __DEV__ = true + show.value = true + await nextTick() + expect(async () => { + clicked.value = true + await nextTick() + }).not.toThrow("Cannot read properties of null (reading 'insertBefore')") + + await nextTick() + expect(container.innerHTML).toBe( + `
foo
1
`, + ) + } catch (e) { + throw e + } finally { + __DEV__ = true + } }) describe('mismatch handling', () => {