From: daiwei Date: Wed, 16 Jul 2025 12:57:21 +0000 (+0800) Subject: chore: Merge branch 'minor' into edison/fix/setRefVdomInterop X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57726651e2d230aa2def357d18d079cfde7e2b61;p=thirdparty%2Fvuejs%2Fcore.git chore: Merge branch 'minor' into edison/fix/setRefVdomInterop --- 57726651e2d230aa2def357d18d079cfde7e2b61 diff --cc packages/runtime-vapor/__tests__/_utils.ts index 729d42de78,d1ede2a6c9..dac4049338 --- a/packages/runtime-vapor/__tests__/_utils.ts +++ b/packages/runtime-vapor/__tests__/_utils.ts @@@ -1,11 -1,7 +1,11 @@@ - import { createVaporApp } from '../src' - import type { App } from '@vue/runtime-dom' + import { createVaporApp, vaporInteropPlugin } from '../src' + import { type App, type Component, createApp } from '@vue/runtime-dom' import type { VaporComponent, VaporComponentInstance } from '../src/component' import type { RawProps } from '../src/componentProps' +import { compileScript, parse } from '@vue/compiler-sfc' +import * as runtimeVapor from '../src' +import * as runtimeDom from '@vue/runtime-dom' +import * as VueServerRenderer from '@vue/server-renderer' export interface RenderContext { component: VaporComponent @@@ -87,49 -83,55 +87,102 @@@ export function makeRender InteropRenderContext + render: ( + props?: RawProps, + container?: string | ParentNode, + ) => InteropRenderContext + host: HTMLElement + html: () => string + } + + export function makeInteropRender(): (comp: Component) => InteropRenderContext { + let host: HTMLElement + beforeEach(() => { + host = document.createElement('div') + }) + afterEach(() => { + host.remove() + }) + + function define(comp: Component) { + let app: App + function render( + props: RawProps | undefined = undefined, + container: string | ParentNode = host, + ) { + app?.unmount() + app = createApp(comp, props) + app.use(vaporInteropPlugin) + return mount(container) + } + + function mount(container: string | ParentNode = host) { + app.mount(container) + return res() + } + + function html() { + return host.innerHTML + } + + const res = () => ({ + host, + mount, + render, + html, + }) + + return res() + } + + return define + } ++ +export { runtimeDom, runtimeVapor, VueServerRenderer } +export function compile( + sfc: string, + data: runtimeDom.Ref, + components: Record = {}, + { + vapor = true, + ssr = false, + }: { + vapor?: boolean | undefined + ssr?: boolean | undefined + } = {}, +): any { + if (!sfc.includes(`const data = _data; const components = _components;` + + sfc + } + const descriptor = parse(sfc).descriptor + + const script = compileScript(descriptor, { + id: 'x', + isProd: true, + inlineTemplate: true, + genDefaultAs: '__sfc__', + vapor, + templateOptions: { + ssr, + }, + }) + + const code = + script.content + .replace(/\bimport {/g, 'const {') + .replace(/ as _/g, ': _') + .replace(/} from ['"]vue['"]/g, `} = Vue`) + .replace(/} from "vue\/server-renderer"/g, '} = VueServerRenderer') + + '\nreturn __sfc__' + + return new Function('Vue', 'VueServerRenderer', '_data', '_components', code)( + { ...runtimeDom, ...runtimeVapor }, + VueServerRenderer, + data, + components, + ) +} diff --cc packages/runtime-vapor/src/block.ts index f27cb5b59e,e021ce84b0..564b56d5b7 --- a/packages/runtime-vapor/src/block.ts +++ b/packages/runtime-vapor/src/block.ts @@@ -6,9 -6,8 +6,9 @@@ 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 type { NodeRef } from './apiTemplateRef' export type Block = | Node diff --cc packages/runtime-vapor/src/vdomInterop.ts index 02409df686,1573a30692..22b20af476 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@@ -15,12 -14,11 +15,13 @@@ import currentInstance, ensureRenderer, isEmitListener, + normalizeRef, onScopeDispose, renderSlot, + shallowReactive, shallowRef, simpleSetCurrentInstance, + setRef as vdomSetRef, } from '@vue/runtime-dom' import { type LooseRawProps, @@@ -38,8 -36,9 +39,10 @@@ import type { RawSlots, VaporSlot } fro import { renderEffect } from './renderEffect' import { createTextNode } from './dom/node' import { optimizePropertyLookup } from './dom/prop' +import type { NodeRef } from './apiTemplateRef' + export const interopKey: unique symbol = Symbol(`interop`) + // mounting vapor components and slots in vdom const vaporInteropImpl: Omit< VaporInteropInterface, @@@ -51,17 -50,14 +54,22 @@@ const prev = currentInstance simpleSetCurrentInstance(parentComponent) - const propsRef = shallowRef(vnode.props) + // filter out reserved props + const props: VNode['props'] = {} + for (const key in vnode.props) { + if (!isReservedProp(key)) { + props[key] = vnode.props[key] + } + } + + const propsRef = shallowRef(props) const slotsRef = shallowRef(vnode.children) + const dynamicPropSource: (() => any)[] & { [interopKey]?: boolean } = [ + () => propsRef.value, + ] + // mark as interop props + dynamicPropSource[interopKey] = true // @ts-expect-error const instance = (vnode.component = createComponent( vnode.type as any as VaporComponent,