]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
chore: Merge branch 'minor' into edison/fix/setRefVdomInterop
authordaiwei <daiwei521@126.com>
Wed, 16 Jul 2025 12:57:21 +0000 (20:57 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 16 Jul 2025 12:57:21 +0000 (20:57 +0800)
1  2 
packages/runtime-core/src/index.ts
packages/runtime-core/src/rendererTemplateRef.ts
packages/runtime-vapor/__tests__/_utils.ts
packages/runtime-vapor/src/apiTemplateRef.ts
packages/runtime-vapor/src/block.ts
packages/runtime-vapor/src/vdomInterop.ts

Simple merge
index 729d42de78c27ea602b9cdbbb72a988b9b92f224,d1ede2a6c9a49546f6ab313fdfd63c9a1b9c77e9..dac404933817f71d7244b951e0c22e3ae18fc1c4
@@@ -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<C = VaporCom
    return define
  }
  
+ export interface InteropRenderContext {
+   mount: (container?: string | ParentNode) => 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<any>,
 +  components: Record<string, any> = {},
 +  {
 +    vapor = true,
 +    ssr = false,
 +  }: {
 +    vapor?: boolean | undefined
 +    ssr?: boolean | undefined
 +  } = {},
 +): any {
 +  if (!sfc.includes(`<script`)) {
 +    sfc =
 +      `<script vapor>const data = _data; const components = _components;</script>` +
 +      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,
 +  )
 +}
index f27cb5b59e5dd790c8b088e89bb0a945d3323096,e021ce84b051432f5bda391d9459f04453ac9a13..564b56d5b7355048fa778ef19824eaa11ff67805
@@@ -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
index 02409df68653a18d1e1702cd50fb185e7f049d3e,1573a306922aacd6813fc8cdfe8f7c7a84ec4f4a..22b20af476477c1b239c2f1b4c5a6a043a2acbb8
@@@ -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,
      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,