11import {
2+ type App ,
23 type Component ,
34 type ComponentCustomElementInterface ,
45 type ComponentInjectOptions ,
@@ -10,6 +11,7 @@ import {
1011 type ComponentProvideOptions ,
1112 type ComputedOptions ,
1213 type ConcreteComponent ,
14+ type CreateAppFunction ,
1315 type CreateComponentPublicInstanceWithMixins ,
1416 type DefineComponent ,
1517 type Directive ,
@@ -18,7 +20,6 @@ import {
1820 type ExtractPropTypes ,
1921 type MethodOptions ,
2022 type RenderFunction ,
21- type RootHydrateFunction ,
2223 type SetupContext ,
2324 type SlotsType ,
2425 type VNode ,
@@ -39,7 +40,7 @@ import {
3940 isPlainObject ,
4041 toNumber ,
4142} from '@vue/shared'
42- import { hydrate , render } from '.'
43+ import { createApp , createSSRApp , render } from '.'
4344
4445export type VueElementConstructor < P = { } > = {
4546 new ( initialProps ?: Record < string , any > ) : VueElement & P
@@ -49,6 +50,7 @@ export interface CustomElementOptions {
4950 styles ?: string [ ]
5051 shadowRoot ?: boolean
5152 nonce ?: string
53+ configureApp ?: ( app : App ) => void
5254}
5355
5456// defineCustomElement provides the same type inference as defineComponent
@@ -165,14 +167,14 @@ export function defineCustomElement(
165167 /**
166168 * @internal
167169 */
168- hydrate ?: RootHydrateFunction ,
170+ _createApp ?: CreateAppFunction < Element > ,
169171) : VueElementConstructor {
170172 const Comp = defineComponent ( options , extraOptions ) as any
171173 if ( isPlainObject ( Comp ) ) extend ( Comp , extraOptions )
172174 class VueCustomElement extends VueElement {
173175 static def = Comp
174176 constructor ( initialProps ?: Record < string , any > ) {
175- super ( Comp , initialProps , hydrate )
177+ super ( Comp , initialProps , _createApp )
176178 }
177179 }
178180
@@ -185,7 +187,7 @@ export const defineSSRCustomElement = ((
185187 extraOptions ?: ComponentOptions ,
186188) => {
187189 // @ts -expect-error
188- return defineCustomElement ( options , extraOptions , hydrate )
190+ return defineCustomElement ( options , extraOptions , createSSRApp )
189191} ) as typeof defineCustomElement
190192
191193const BaseClass = (
@@ -202,6 +204,14 @@ export class VueElement
202204 * @internal
203205 */
204206 _instance : ComponentInternalInstance | null = null
207+ /**
208+ * @internal
209+ */
210+ _app : App | null = null
211+ /**
212+ * @internal
213+ */
214+ _nonce = this . _def . nonce
205215
206216 private _connected = false
207217 private _resolved = false
@@ -225,15 +235,19 @@ export class VueElement
225235 private _slots ?: Record < string , Node [ ] >
226236
227237 constructor (
238+ /**
239+ * Component def - note this may be an AsyncWrapper, and this._def will
240+ * be overwritten by the inner component when resolved.
241+ */
228242 private _def : InnerComponentDef ,
229243 private _props : Record < string , any > = { } ,
230- hydrate ?: RootHydrateFunction ,
244+ private _createApp : CreateAppFunction < Element > = createApp ,
231245 ) {
232246 super ( )
233- // TODO handle non-shadowRoot hydration
234- if ( this . shadowRoot && hydrate ) {
235- hydrate ( this . _createVNode ( ) , this . shadowRoot )
247+ if ( this . shadowRoot && _createApp !== createApp ) {
236248 this . _root = this . shadowRoot
249+ // TODO hydration needs to be reworked
250+ this . _mount ( _def )
237251 } else {
238252 if ( __DEV__ && this . shadowRoot ) {
239253 warn (
@@ -303,9 +317,10 @@ export class VueElement
303317 this . _ob . disconnect ( )
304318 this . _ob = null
305319 }
306- render ( null , this . _root )
320+ // unmount
321+ this . _app && this . _app . unmount ( )
307322 this . _instance ! . ce = undefined
308- this . _instance = null
323+ this . _app = this . _instance = null
309324 }
310325 } )
311326 }
@@ -371,11 +386,8 @@ export class VueElement
371386 )
372387 }
373388
374- // initial render
375- this . _update ( )
376-
377- // apply expose
378- this . _applyExpose ( )
389+ // initial mount
390+ this . _mount ( def )
379391 }
380392
381393 const asyncDef = ( this . _def as ComponentOptions ) . __asyncLoader
@@ -388,6 +400,34 @@ export class VueElement
388400 }
389401 }
390402
403+ private _mount ( def : InnerComponentDef ) {
404+ if ( ( __DEV__ || __FEATURE_PROD_DEVTOOLS__ ) && ! def . name ) {
405+ // @ts -expect-error
406+ def . name = 'VueElement'
407+ }
408+ this . _app = this . _createApp ( def )
409+ if ( def . configureApp ) {
410+ def . configureApp ( this . _app )
411+ }
412+ this . _app . _ceVNode = this . _createVNode ( )
413+ this . _app . mount ( this . _root )
414+
415+ // apply expose after mount
416+ const exposed = this . _instance && this . _instance . exposed
417+ if ( ! exposed ) return
418+ for ( const key in exposed ) {
419+ if ( ! hasOwn ( this , key ) ) {
420+ // exposed properties are readonly
421+ Object . defineProperty ( this , key , {
422+ // unwrap ref to be consistent with public instance behavior
423+ get : ( ) => unref ( exposed [ key ] ) ,
424+ } )
425+ } else if ( __DEV__ ) {
426+ warn ( `Exposed property "${ key } " already exists on custom element.` )
427+ }
428+ }
429+ }
430+
391431 private _resolveProps ( def : InnerComponentDef ) {
392432 const { props } = def
393433 const declaredPropKeys = isArray ( props ) ? props : Object . keys ( props || { } )
@@ -412,22 +452,6 @@ export class VueElement
412452 }
413453 }
414454
415- private _applyExpose ( ) {
416- const exposed = this . _instance && this . _instance . exposed
417- if ( ! exposed ) return
418- for ( const key in exposed ) {
419- if ( ! hasOwn ( this , key ) ) {
420- // exposed properties are readonly
421- Object . defineProperty ( this , key , {
422- // unwrap ref to be consistent with public instance behavior
423- get : ( ) => unref ( exposed [ key ] ) ,
424- } )
425- } else if ( __DEV__ ) {
426- warn ( `Exposed property "${ key } " already exists on custom element.` )
427- }
428- }
429- }
430-
431455 protected _setAttr ( key : string ) {
432456 if ( key . startsWith ( 'data-v-' ) ) return
433457 let value = this . hasAttribute ( key ) ? this . getAttribute ( key ) : undefined
@@ -534,7 +558,7 @@ export class VueElement
534558 }
535559 this . _styleChildren . add ( owner )
536560 }
537- const nonce = this . _def . nonce
561+ const nonce = this . _nonce
538562 for ( let i = styles . length - 1 ; i >= 0 ; i -- ) {
539563 const s = document . createElement ( 'style' )
540564 if ( nonce ) s . setAttribute ( 'nonce' , nonce )
0 commit comments