From: daiwei Date: Fri, 18 Jul 2025 03:48:22 +0000 (+0800) Subject: chore: Merge branch 'minor' into edison/feat/vaporHydration X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb7779b0d9893c23e5158a8f170f3906fc0a9d72;p=thirdparty%2Fvuejs%2Fcore.git chore: Merge branch 'minor' into edison/feat/vaporHydration --- cb7779b0d9893c23e5158a8f170f3906fc0a9d72 diff --cc packages/compiler-ssr/__tests__/ssrVModel.spec.ts index c88f6ba318,8a439dbf4b..f7b7a3241b --- a/packages/compiler-ssr/__tests__/ssrVModel.spec.ts +++ b/packages/compiler-ssr/__tests__/ssrVModel.spec.ts @@@ -167,6 -166,132 +167,135 @@@ describe('ssr: v-model', () => _push(\`\`) }" `) + + expect( + compileWithWrapper(` + `).code, + ).toMatchInlineSnapshot(` + "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) ++ _push(\`\`) + }" + `) + + expect( + compileWithWrapper(` + `).code, + ).toMatchInlineSnapshot(` + "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require("vue/server-renderer") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) + }" + `) + + expect( + compileWithWrapper(` + `).code, + ).toMatchInlineSnapshot(` + "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) + }" + `) + + expect( + compileWithWrapper(` + `).code, + ).toMatchInlineSnapshot(` + "const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require("vue/server-renderer") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) ++ _push(\`\`) + }" + `) }) test('', () => { diff --cc packages/runtime-core/src/hydration.ts index 62bcb76867,15b3c7512b..5db9a3bdd5 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@@ -32,8 -31,8 +32,9 @@@ import isRenderableAttrValue, isReservedProp, isString, + isVaporAnchors, normalizeClass, + normalizeCssVarValue, normalizeStyle, stringifyStyle, } from '@vue/shared' diff --cc packages/runtime-vapor/src/apiCreateFor.ts index 19346f6f5d,426a5c56b5..c6adfccb04 --- a/packages/runtime-vapor/src/apiCreateFor.ts +++ b/packages/runtime-vapor/src/apiCreateFor.ts @@@ -10,14 -9,9 +9,9 @@@ import shallowRef, toReactive, toReadonly, + watch, } from '@vue/reactivity' - import { - FOR_ANCHOR_LABEL, - getSequence, - isArray, - isObject, - isString, - } from '@vue/shared' -import { isArray, isObject, isString } from '@vue/shared' ++import { FOR_ANCHOR_LABEL, isArray, isObject, isString } from '@vue/shared' import { createComment, createTextNode } from './dom/node' import { type Block, @@@ -98,24 -87,18 +92,30 @@@ export const createFor = let oldBlocks: ForBlock[] = [] let newBlocks: ForBlock[] let parent: ParentNode | undefined | null + // useSelector only + let currentKey: any - // TODO handle this in hydration - const parentAnchor = __DEV__ ? createComment('for') : createTextNode() + let parentAnchor: Node + if (isHydrating) { + parentAnchor = locateVaporFragmentAnchor( + currentHydrationNode!, + FOR_ANCHOR_LABEL, + )! + if (__DEV__ && !parentAnchor) { + // this should not happen + throw new Error(`v-for fragment anchor node was not found.`) + } + } else { + parentAnchor = __DEV__ ? createComment('for') : createTextNode() + } + const frag = new VaporFragment(oldBlocks) const instance = currentInstance! - const canUseFastRemove = flags & VaporVForFlags.FAST_REMOVE - const isComponent = flags & VaporVForFlags.IS_COMPONENT + const canUseFastRemove = !!(flags & VaporVForFlags.FAST_REMOVE) + const isComponent = !!(flags & VaporVForFlags.IS_COMPONENT) + const selectors: { + deregister: (key: any) => void + cleanup: () => void + }[] = [] if (__DEV__ && !instance) { warn('createFor() can only be used inside setup()') diff --cc packages/runtime-vapor/src/block.ts index f501e6f5d2,e021ce84b0..b1eaaf4968 --- a/packages/runtime-vapor/src/block.ts +++ b/packages/runtime-vapor/src/block.ts @@@ -6,14 -6,8 +6,14 @@@ import unmountComponent, } from './component' import { createComment, createTextNode } from './dom/node' - import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity' + import { EffectScope, setActiveSub } from '@vue/reactivity' -import { isHydrating } from './dom/hydration' +import { + currentHydrationNode, + isComment, + isHydrating, + locateHydrationNode, + locateVaporFragmentAnchor, +} from './dom/hydration' export type Block = | Node @@@ -84,24 -73,8 +84,24 @@@ export class DynamicFragment extends Va parent && insert(this.nodes, parent, this.anchor) } - resetTracking() + setActiveSub(prevSub) } + + hydrate(label: string): void { + // for `v-if="false"` the node will be an empty comment, use it as the anchor. + // otherwise, find next sibling vapor fragment anchor + if (isComment(currentHydrationNode!, '')) { + this.anchor = currentHydrationNode + } else { + const anchor = locateVaporFragmentAnchor(currentHydrationNode!, label)! + if (anchor) { + this.anchor = anchor + } else if (__DEV__) { + // this should not happen + throw new Error(`${label} fragment anchor node was not found.`) + } + } + } } export function isFragment(val: NonNullable): val is VaporFragment { diff --cc packages/runtime-vapor/src/vdomInterop.ts index fe23dcc262,1573a30692..a330a56f04 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@@ -38,15 -36,9 +38,17 @@@ import type { RawSlots, VaporSlot } fro import { renderEffect } from './renderEffect' import { createTextNode } from './dom/node' import { optimizePropertyLookup } from './dom/prop' +import { + currentHydrationNode, + isHydrating, + locateHydrationNode, + locateVaporFragmentAnchor, + setCurrentHydrationNode, + hydrateNode as vaporHydrateNode, +} from './dom/hydration' + export const interopKey: unique symbol = Symbol(`interop`) + // mounting vapor components and slots in vdom const vaporInteropImpl: Omit< VaporInteropInterface, diff --cc packages/shared/src/index.ts index 674bcdf96c,0c38d640ba..9372b8e1a9 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@@ -13,4 -13,4 +13,5 @@@ export * from './looseEqual export * from './toDisplayString' export * from './typeUtils' export * from './subSequence' +export * from './domAnchors' + export * from './cssVars'