* avoid unnecessary watcher trigger
* @internal
*/
- propsDefaults: Data
+ propsDefaults: Data | null
/**
* setup related
* @internal
emitted: null,
// props default value
- propsDefaults: EMPTY_OBJ,
+ propsDefaults: null,
// inheritAttrs
inheritAttrs: type.inheritAttrs,
const camelizedKey = camelize(key)
props[camelizedKey] = resolvePropValue(
options,
- rawCurrentProps,
camelizedKey,
value,
instance,
- false /* isAbsent */,
+ baseResolveDefault,
)
}
} else {
) {
props[key] = resolvePropValue(
options,
- rawCurrentProps,
key,
undefined,
instance,
+ baseResolveDefault,
true /* isAbsent */,
)
}
}
if (needCastKeys) {
- const rawCurrentProps = toRaw(props)
const castValues = rawCastValues || EMPTY_OBJ
for (let i = 0; i < needCastKeys.length; i++) {
const key = needCastKeys[i]
props[key] = resolvePropValue(
options!,
- rawCurrentProps,
key,
castValues[key],
instance,
+ baseResolveDefault,
!hasOwn(castValues, key),
)
}
return hasAttrsChanged
}
-function resolvePropValue(
+/**
+ * A type that allows both vdom and vapor instances
+ */
+type CommonInstance = Pick<
+ ComponentInternalInstance,
+ 'props' | 'propsDefaults' | 'ce'
+>
+
+/**
+ * @internal for runtime-vapor
+ */
+export function resolvePropValue<T extends CommonInstance>(
options: NormalizedProps,
- props: Data,
key: string,
value: unknown,
- instance: ComponentInternalInstance,
- isAbsent: boolean,
-) {
+ instance: T,
+ /**
+ * Allow runtime-specific default resolution logic
+ */
+ resolveDefault: (
+ factory: (props: Data) => unknown,
+ instance: T,
+ key: string,
+ ) => unknown,
+ isAbsent = false,
+): unknown {
const opt = options[key]
if (opt != null) {
const hasDefault = hasOwn(opt, 'default')
!opt.skipFactory &&
isFunction(defaultValue)
) {
- const { propsDefaults } = instance
- if (key in propsDefaults) {
- value = propsDefaults[key]
+ const cachedDefaults =
+ instance.propsDefaults || (instance.propsDefaults = {})
+ if (hasOwn(cachedDefaults, key)) {
+ value = cachedDefaults[key]
} else {
- const reset = setCurrentInstance(instance)
- value = propsDefaults[key] = defaultValue.call(
- __COMPAT__ &&
- isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS, instance)
- ? createPropsDefaultThis(instance, props, key)
- : null,
- props,
+ value = cachedDefaults[key] = resolveDefault(
+ defaultValue,
+ instance,
+ key,
)
- reset()
}
} else {
value = defaultValue
return value
}
+/**
+ * runtime-dom-specific default resolving logic
+ */
+function baseResolveDefault(
+ factory: (props: Data) => unknown,
+ instance: ComponentInternalInstance,
+ key: string,
+) {
+ let value
+ const reset = setCurrentInstance(instance)
+ const props = toRaw(instance.props)
+ value = factory.call(
+ __COMPAT__ && isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS, instance)
+ ? createPropsDefaultThis(instance, props, key)
+ : null,
+ props,
+ )
+ reset()
+ return value
+}
+
const mixinPropsCache = new WeakMap<ConcreteComponent, NormalizedPropsOptions>()
export function normalizePropsOptions(
return EMPTY_ARR as any
}
+ baseNormalizePropsOptions(raw, normalized, needCastKeys)
+ const res: NormalizedPropsOptions = [normalized, needCastKeys]
+ if (isObject(comp)) {
+ cache.set(comp, res)
+ }
+ return res
+}
+
+/**
+ * @internal for runtime-vapor only
+ */
+export function baseNormalizePropsOptions(
+ raw: ComponentPropsOptions | undefined,
+ normalized: NonNullable<NormalizedPropsOptions[0]>,
+ needCastKeys: NonNullable<NormalizedPropsOptions[1]>,
+): void {
if (isArray(raw)) {
for (let i = 0; i < raw.length; i++) {
if (__DEV__ && !isString(raw[i])) {
}
}
}
-
- const res: NormalizedPropsOptions = [normalized, needCastKeys]
- if (isObject(comp)) {
- cache.set(comp, res)
- }
- return res
}
function validatePropName(key: string) {
ExtractPropTypes,
ExtractPublicPropTypes,
ExtractDefaultPropTypes,
+ NormalizedPropsOptions,
} from './componentProps'
export type {
Directive,
export const DeprecationTypes = (
__COMPAT__ ? _DeprecationTypes : null
) as typeof _DeprecationTypes
+
+// VAPOR -----------------------------------------------------------------------
+
+// **IMPORTANT** These APIs are exposed solely for @vue/runtime-vapor and may
+// change without notice between versions. User code should never rely on them.
+
+export { baseNormalizePropsOptions, resolvePropValue } from './componentProps'
--- /dev/null
+import { normalizeContainer } from '../apiRender'
+import { insert } from '../dom/element'
+import { type Component, createComponent } from './component'
+
+export function createVaporApp(comp: Component): any {
+ return {
+ mount(container: string | ParentNode) {
+ container = normalizeContainer(container)
+ // clear content before mounting
+ if (container.nodeType === 1 /* Node.ELEMENT_NODE */) {
+ container.textContent = ''
+ }
+ const instance = createComponent(comp)
+ insert(instance.block, container)
+ return instance
+ },
+ }
+}
--- /dev/null
+import {
+ type ComponentPropsOptions,
+ EffectScope,
+ type EmitsOptions,
+ type NormalizedPropsOptions,
+} from '@vue/runtime-core'
+import type { Block } from '../block'
+import type { Data } from '@vue/runtime-shared'
+import { pauseTracking, resetTracking } from '@vue/reactivity'
+import { isFunction } from '@vue/shared'
+import {
+ type RawProps,
+ getDynamicPropsHandlers,
+ initStaticProps,
+} from './componentProps'
+import { setDynamicProp } from '../dom/prop'
+import { renderEffect } from './renderEffect'
+
+export type Component = FunctionalComponent | ObjectComponent
+
+export type SetupFn = (
+ props: any,
+ ctx: SetupContext,
+) => Block | Data | undefined
+
+export type FunctionalComponent = SetupFn &
+ Omit<ObjectComponent, 'setup'> & {
+ displayName?: string
+ } & SharedInternalOptions
+
+export interface ObjectComponent
+ extends ComponentInternalOptions,
+ SharedInternalOptions {
+ setup?: SetupFn
+ inheritAttrs?: boolean
+ props?: ComponentPropsOptions
+ emits?: EmitsOptions
+ render?(ctx: any): Block
+
+ name?: string
+ vapor?: boolean
+}
+
+interface SharedInternalOptions {
+ __propsOptions?: NormalizedPropsOptions
+ __propsHandlers?: [ProxyHandler<any>, ProxyHandler<any>]
+}
+
+// Note: can't mark this whole interface internal because some public interfaces
+// extend it.
+interface ComponentInternalOptions {
+ /**
+ * @internal
+ */
+ __scopeId?: string
+ /**
+ * @internal
+ */
+ __cssModules?: Data
+ /**
+ * @internal
+ */
+ __hmrId?: string
+ /**
+ * Compat build only, for bailing out of certain compatibility behavior
+ */
+ __isBuiltIn?: boolean
+ /**
+ * This one should be exposed so that devtools can make use of it
+ */
+ __file?: string
+ /**
+ * name inferred from filename
+ */
+ __name?: string
+}
+
+export function createComponent(
+ component: Component,
+ rawProps?: RawProps,
+ isSingleRoot?: boolean,
+): ComponentInstance {
+ // check if we are the single root of the parent
+ // if yes, inject parent attrs as dynamic props source
+ if (isSingleRoot && currentInstance && currentInstance.hasFallthrough) {
+ if (rawProps) {
+ ;(rawProps.$ || (rawProps.$ = [])).push(currentInstance.attrs)
+ } else {
+ rawProps = { $: [currentInstance.attrs] }
+ }
+ }
+
+ const instance = new ComponentInstance(component, rawProps)
+
+ pauseTracking()
+ let prevInstance = currentInstance
+ currentInstance = instance
+ instance.scope.on()
+
+ const setupFn = isFunction(component) ? component : component.setup
+ const setupContext = setupFn!.length > 1 ? new SetupContext(instance) : null
+ instance.block = setupFn!(
+ instance.props,
+ // @ts-expect-error
+ setupContext,
+ ) as Block // TODO handle return object
+
+ // single root, inherit attrs
+ if (
+ instance.hasFallthrough &&
+ component.inheritAttrs !== false &&
+ instance.block instanceof Element &&
+ Object.keys(instance.attrs).length
+ ) {
+ renderEffect(() => {
+ for (const key in instance.attrs) {
+ setDynamicProp(instance.block as Element, key, instance.attrs[key])
+ }
+ })
+ }
+
+ instance.scope.off()
+ currentInstance = prevInstance
+ resetTracking()
+ return instance
+}
+
+let uid = 0
+export let currentInstance: ComponentInstance | null = null
+
+export class ComponentInstance {
+ type: Component
+ uid: number = uid++
+ scope: EffectScope = new EffectScope(true)
+ props: Record<string, any>
+ propsDefaults: Record<string, any> | null
+ attrs: Record<string, any>
+ block: Block
+ exposed?: Record<string, any>
+ hasFallthrough: boolean
+
+ constructor(comp: Component, rawProps?: RawProps) {
+ this.type = comp
+ this.block = null! // to be set
+
+ // init props
+ this.propsDefaults = null
+ this.hasFallthrough = false
+ if (comp.props && rawProps && rawProps.$) {
+ // has dynamic props, use proxy
+ const handlers = getDynamicPropsHandlers(comp, this)
+ this.props = new Proxy(rawProps, handlers[0])
+ this.attrs = new Proxy(rawProps, handlers[1])
+ this.hasFallthrough = true
+ } else {
+ this.props = {}
+ this.attrs = {}
+ this.hasFallthrough = initStaticProps(comp, rawProps, this)
+ }
+
+ // TODO validate props
+ // TODO init slots
+ }
+}
+
+export function isVaporComponent(value: unknown): value is ComponentInstance {
+ return value instanceof ComponentInstance
+}
+
+export class SetupContext<E = EmitsOptions> {
+ attrs: Record<string, any>
+ // emit: EmitFn<E>
+ // slots: Readonly<StaticSlots>
+ expose: (exposed?: Record<string, any>) => void
+
+ constructor(instance: ComponentInstance) {
+ this.attrs = instance.attrs
+ // this.emit = instance.emit as EmitFn<E>
+ // this.slots = instance.slots
+ this.expose = (exposed = {}) => {
+ instance.exposed = exposed
+ }
+ }
+}
--- /dev/null
+import { EMPTY_ARR, NO, camelize, hasOwn, isFunction } from '@vue/shared'
+import type { Component, ComponentInstance } from './component'
+import {
+ type NormalizedPropsOptions,
+ baseNormalizePropsOptions,
+ resolvePropValue,
+} from '@vue/runtime-core'
+
+export interface RawProps {
+ [key: string]: PropSource
+ $?: DynamicPropsSource[]
+}
+
+type PropSource<T = any> = T | (() => T)
+
+type DynamicPropsSource = PropSource<Record<string, any>>
+
+export function initStaticProps(
+ comp: Component,
+ rawProps: RawProps | undefined,
+ instance: ComponentInstance,
+): boolean {
+ let hasAttrs = false
+ const { props, attrs } = instance
+ const [propsOptions, needCastKeys] = normalizePropsOptions(comp)
+ // TODO emits filtering
+ for (const key in rawProps) {
+ const normalizedKey = camelize(key)
+ const needCast = needCastKeys && needCastKeys.includes(normalizedKey)
+ const source = rawProps[key]
+ if (propsOptions && normalizedKey in propsOptions) {
+ if (isFunction(source)) {
+ Object.defineProperty(props, normalizedKey, {
+ enumerable: true,
+ get: needCast
+ ? () =>
+ resolvePropValue(
+ propsOptions,
+ normalizedKey,
+ source(),
+ instance,
+ resolveDefault,
+ )
+ : source,
+ })
+ } else {
+ props[normalizedKey] = needCast
+ ? resolvePropValue(
+ propsOptions,
+ normalizedKey,
+ source,
+ instance,
+ resolveDefault,
+ )
+ : source
+ }
+ } else {
+ if (isFunction(source)) {
+ Object.defineProperty(attrs, key, {
+ enumerable: true,
+ get: source,
+ })
+ } else {
+ attrs[normalizedKey] = source
+ }
+ hasAttrs = true
+ }
+ }
+ for (const key in propsOptions) {
+ if (!(key in props)) {
+ props[key] = resolvePropValue(
+ propsOptions,
+ key,
+ undefined,
+ instance,
+ resolveDefault,
+ true,
+ )
+ }
+ }
+ return hasAttrs
+}
+
+function resolveDefault(
+ factory: (props: Record<string, any>) => unknown,
+ instance: ComponentInstance,
+) {
+ return factory.call(null, instance.props)
+}
+
+// TODO optimization: maybe convert functions into computeds
+function resolveSource(source: PropSource): Record<string, any> {
+ return isFunction(source) ? source() : source
+}
+
+export function getDynamicPropsHandlers(
+ comp: Component,
+ instance: ComponentInstance,
+): [ProxyHandler<RawProps>, ProxyHandler<RawProps>] {
+ if (comp.__propsHandlers) {
+ return comp.__propsHandlers
+ }
+ let normalizedKeys: string[] | undefined
+ const propsOptions = normalizePropsOptions(comp)[0]!
+ const isProp = (key: string | symbol) => hasOwn(propsOptions, key)
+
+ const getProp = (target: RawProps, key: string | symbol, asProp: boolean) => {
+ if (key !== '$' && (asProp ? isProp(key) : !isProp(key))) {
+ const castProp = (value: any, isAbsent = false) =>
+ asProp
+ ? resolvePropValue(
+ propsOptions,
+ key as string,
+ value,
+ instance,
+ resolveDefault,
+ isAbsent,
+ )
+ : value
+
+ if (key in target) {
+ // TODO default value, casting, etc.
+ return castProp(resolveSource(target[key as string]))
+ }
+ if (target.$) {
+ let i = target.$.length
+ let source
+ while (i--) {
+ source = resolveSource(target.$[i])
+ if (hasOwn(source, key)) {
+ return castProp(source[key])
+ }
+ }
+ }
+ return castProp(undefined, true)
+ }
+ }
+
+ const propsHandlers = {
+ get: (target, key) => getProp(target, key, true),
+ has: (_, key) => isProp(key),
+ getOwnPropertyDescriptor(target, key) {
+ if (isProp(key)) {
+ return {
+ configurable: true,
+ enumerable: true,
+ get: () => getProp(target, key, true),
+ }
+ }
+ },
+ ownKeys: () =>
+ normalizedKeys || (normalizedKeys = Object.keys(propsOptions)),
+ set: NO,
+ deleteProperty: NO,
+ } satisfies ProxyHandler<RawProps>
+
+ const hasAttr = (target: RawProps, key: string | symbol) => {
+ if (key === '$' || isProp(key)) return false
+ if (hasOwn(target, key)) return true
+ if (target.$) {
+ let i = target.$.length
+ while (i--) {
+ if (hasOwn(resolveSource(target.$[i]), key)) {
+ return true
+ }
+ }
+ }
+ return false
+ }
+
+ const attrsHandlers = {
+ get: (target, key) => getProp(target, key, false),
+ has: hasAttr,
+ getOwnPropertyDescriptor(target, key) {
+ if (hasAttr(target, key)) {
+ return {
+ configurable: true,
+ enumerable: true,
+ get: () => getProp(target, key, false),
+ }
+ }
+ },
+ ownKeys(target) {
+ const staticKeys = Object.keys(target).filter(
+ key => key !== '$' && !isProp(key),
+ )
+ if (target.$) {
+ let i = target.$.length
+ while (i--) {
+ staticKeys.push(...Object.keys(resolveSource(target.$[i])))
+ }
+ }
+ return staticKeys
+ },
+ set: NO,
+ deleteProperty: NO,
+ } satisfies ProxyHandler<RawProps>
+
+ return (comp.__propsHandlers = [propsHandlers, attrsHandlers])
+}
+
+function normalizePropsOptions(comp: Component): NormalizedPropsOptions {
+ const cached = comp.__propsOptions
+ if (cached) return cached
+
+ const raw = comp.props
+ if (!raw) return EMPTY_ARR as []
+
+ const normalized: NormalizedPropsOptions[0] = {}
+ const needCastKeys: NormalizedPropsOptions[1] = []
+ baseNormalizePropsOptions(raw, normalized, needCastKeys)
+
+ return (comp.__propsOptions = [normalized, needCastKeys])
+}
--- /dev/null
+export { createComponent as createComponentSimple } from './component'
+export { renderEffect as renderEffectSimple } from './renderEffect'
+export { createVaporApp as createVaporAppSimple } from './apiCreateApp'
--- /dev/null
+import { ReactiveEffect } from '@vue/reactivity'
+import {
+ type SchedulerJob,
+ queueJob,
+} from '../../../runtime-core/src/scheduler'
+import { currentInstance } from './component'
+
+export function renderEffect(fn: () => void): void {
+ const updateFn = () => {
+ fn()
+ }
+ const effect = new ReactiveEffect(updateFn)
+ const job: SchedulerJob = effect.runIfDirty.bind(effect)
+ job.i = currentInstance as any
+ job.id = currentInstance!.uid
+ effect.scheduler = () => queueJob(job)
+ effect.run()
+
+ // TODO lifecycle
+ // TODO recurse handling
+ // TODO measure
+}
+++ /dev/null
-import {
- EffectScope,
- ReactiveEffect,
- pauseTracking,
- resetTracking,
-} from '@vue/reactivity'
-import type { Component } from './component'
-import { NO, camelize, hasOwn, isFunction } from '@vue/shared'
-import { type SchedulerJob, queueJob } from '../../runtime-core/src/scheduler'
-import { insert } from './dom/element'
-import { normalizeContainer } from './apiRender'
-import { normalizePropsOptions, resolvePropValue } from './componentProps'
-import type { Block } from './block'
-import { EmitFn, type EmitsOptions } from './componentEmits'
-import { StaticSlots } from './componentSlots'
-import { setDynamicProp } from './dom/prop'
-
-interface RawProps {
- [key: string]: PropSource
- $?: DynamicPropsSource[]
-}
-
-type PropSource<T = any> = T | (() => T)
-
-type DynamicPropsSource = PropSource<Record<string, any>>
-
-export function createComponentSimple(
- component: Component,
- rawProps?: RawProps,
- isSingleRoot?: boolean,
-): ComponentInstance {
- // check if we are the single root of the parent
- // if yes, inject parent attrs as dynamic props source
- if (isSingleRoot && currentInstance && currentInstance.hasFallthrough) {
- if (rawProps) {
- ;(rawProps.$ || (rawProps.$ = [])).push(currentInstance.attrs)
- } else {
- rawProps = { $: [currentInstance.attrs] }
- }
- }
-
- const instance = new ComponentInstance(component, rawProps)
-
- pauseTracking()
- let prevInstance = currentInstance
- currentInstance = instance
- instance.scope.on()
-
- const setupFn = isFunction(component) ? component : component.setup
- const setupContext = setupFn!.length > 1 ? new SetupContext(instance) : null
- instance.block = setupFn!(
- instance.props,
- // @ts-expect-error
- setupContext,
- ) as Block // TODO handle return object
-
- // single root, inherit attrs
- if (
- instance.hasFallthrough &&
- component.inheritAttrs !== false &&
- instance.block instanceof Element &&
- Object.keys(instance.attrs).length
- ) {
- renderEffectSimple(() => {
- for (const key in instance.attrs) {
- setDynamicProp(instance.block as Element, key, instance.attrs[key])
- }
- })
- }
-
- instance.scope.off()
- currentInstance = prevInstance
- resetTracking()
- return instance
-}
-
-class SetupContext<E = EmitsOptions> {
- attrs: Record<string, any>
- // emit: EmitFn<E>
- // slots: Readonly<StaticSlots>
- expose: (exposed?: Record<string, any>) => void
-
- constructor(instance: ComponentInstance) {
- this.attrs = instance.attrs
- // this.emit = instance.emit as EmitFn<E>
- // this.slots = instance.slots
- this.expose = (exposed = {}) => {
- instance.exposed = exposed
- }
- }
-}
-
-let uid = 0
-let currentInstance: ComponentInstance | null = null
-
-export class ComponentInstance {
- type: Component
- uid: number = uid++
- scope: EffectScope = new EffectScope(true)
- props: Record<string, any>
- attrs: Record<string, any>
- block: Block
- exposed?: Record<string, any>
- hasFallthrough: boolean
-
- constructor(comp: Component, rawProps?: RawProps) {
- this.type = comp
- this.block = null! // to be set
-
- // init props
- this.hasFallthrough = false
- if (comp.props && rawProps && rawProps.$) {
- // has dynamic props, use proxy
- const handlers = getDynamicPropsHandlers(comp, this)
- this.props = new Proxy(rawProps, handlers[0])
- this.attrs = new Proxy(rawProps, handlers[1])
- this.hasFallthrough = true
- } else {
- this.hasFallthrough = initStaticProps(
- comp,
- rawProps,
- (this.props = {}),
- (this.attrs = {}),
- )
- }
-
- // TODO validate props
- // TODO init slots
- }
-}
-
-export function isVaporComponent(value: unknown): value is ComponentInstance {
- return value instanceof ComponentInstance
-}
-
-function initStaticProps(
- comp: Component,
- rawProps: RawProps | undefined,
- props: any,
- attrs: any,
-): boolean {
- let hasAttrs = false
- const [propsOptions, needCastKeys] = normalizePropsOptions(comp)
- for (const key in rawProps) {
- const normalizedKey = camelize(key)
- const needCast = needCastKeys && needCastKeys.includes(normalizedKey)
- const source = rawProps[key]
- if (propsOptions && normalizedKey in propsOptions) {
- if (isFunction(source)) {
- Object.defineProperty(props, normalizedKey, {
- enumerable: true,
- get: needCast
- ? () =>
- resolvePropValue(propsOptions, props, normalizedKey, source())
- : source,
- })
- } else {
- props[normalizedKey] = needCast
- ? resolvePropValue(propsOptions, props, normalizedKey, source)
- : source
- }
- } else {
- if (isFunction(source)) {
- Object.defineProperty(attrs, key, {
- enumerable: true,
- get: source,
- })
- } else {
- attrs[normalizedKey] = source
- }
- hasAttrs = true
- }
- }
- for (const key in propsOptions) {
- if (!(key in props)) {
- props[key] = resolvePropValue(propsOptions, props, key, undefined, true)
- }
- }
- return hasAttrs
-}
-
-// TODO optimization: maybe convert functions into computeds
-function resolveSource(source: PropSource): Record<string, any> {
- return isFunction(source) ? source() : source
-}
-
-function getDynamicPropsHandlers(
- comp: Component,
- instance: ComponentInstance,
-): [ProxyHandler<RawProps>, ProxyHandler<RawProps>] {
- if (comp.__propsHandlers) {
- return comp.__propsHandlers
- }
- let normalizedKeys: string[] | undefined
- const propsOptions = normalizePropsOptions(comp)[0]!
- const isProp = (key: string | symbol) => hasOwn(propsOptions, key)
-
- const getProp = (target: RawProps, key: string | symbol, asProp: boolean) => {
- if (key !== '$' && (asProp ? isProp(key) : !isProp(key))) {
- const castProp = (value: any, isAbsent?: boolean) =>
- asProp
- ? resolvePropValue(
- propsOptions,
- instance.props,
- key as string,
- value,
- isAbsent,
- )
- : value
-
- if (key in target) {
- // TODO default value, casting, etc.
- return castProp(resolveSource(target[key as string]))
- }
- if (target.$) {
- let i = target.$.length
- let source
- while (i--) {
- source = resolveSource(target.$[i])
- if (hasOwn(source, key)) {
- return castProp(source[key])
- }
- }
- }
- return castProp(undefined, true)
- }
- }
-
- const propsHandlers = {
- get: (target, key) => getProp(target, key, true),
- has: (_, key) => isProp(key),
- getOwnPropertyDescriptor(target, key) {
- if (isProp(key)) {
- return {
- configurable: true,
- enumerable: true,
- get: () => getProp(target, key, true),
- }
- }
- },
- ownKeys: () =>
- normalizedKeys || (normalizedKeys = Object.keys(propsOptions)),
- set: NO,
- deleteProperty: NO,
- } satisfies ProxyHandler<RawProps>
-
- const hasAttr = (target: RawProps, key: string | symbol) => {
- if (key === '$' || isProp(key)) return false
- if (hasOwn(target, key)) return true
- if (target.$) {
- let i = target.$.length
- while (i--) {
- if (hasOwn(resolveSource(target.$[i]), key)) {
- return true
- }
- }
- }
- return false
- }
-
- const attrsHandlers = {
- get: (target, key) => getProp(target, key, false),
- has: hasAttr,
- getOwnPropertyDescriptor(target, key) {
- if (hasAttr(target, key)) {
- return {
- configurable: true,
- enumerable: true,
- get: () => getProp(target, key, false),
- }
- }
- },
- ownKeys(target) {
- const staticKeys = Object.keys(target).filter(
- key => key !== '$' && !isProp(key),
- )
- if (target.$) {
- let i = target.$.length
- while (i--) {
- staticKeys.push(...Object.keys(resolveSource(target.$[i])))
- }
- }
- return staticKeys
- },
- set: NO,
- deleteProperty: NO,
- } satisfies ProxyHandler<RawProps>
-
- return (comp.__propsHandlers = [propsHandlers, attrsHandlers])
-}
-
-export function renderEffectSimple(fn: () => void): void {
- const updateFn = () => {
- fn()
- }
- const effect = new ReactiveEffect(updateFn)
- const job: SchedulerJob = effect.runIfDirty.bind(effect)
- job.i = currentInstance as any
- job.id = currentInstance!.uid
- effect.scheduler = () => queueJob(job)
- effect.run()
-
- // TODO lifecycle
- // TODO recurse handling
- // TODO measure
-}
-
-// vapor app can be a subset of main app APIs
-// TODO refactor core createApp for reuse
-export function createVaporAppSimple(comp: Component): any {
- return {
- mount(container: string | ParentNode) {
- container = normalizeContainer(container)
- // clear content before mounting
- if (container.nodeType === 1 /* Node.ELEMENT_NODE */) {
- container.textContent = ''
- }
- const rootBlock = createComponentSimple(comp)
- insert(rootBlock, container)
- },
- }
-}
import { isArray } from '@vue/shared'
-import {
- type ComponentInstance,
- isVaporComponent,
-} from './apiCreateComponentSimple'
+import { type ComponentInstance, isVaporComponent } from './_new/component'
export const fragmentKey: unique symbol = Symbol(__DEV__ ? `fragmentKey` : ``)
import { renderEffect } from '../renderEffect'
import { setText } from './prop'
import { type Block, normalizeBlock } from '../block'
-import { isVaporComponent } from '../apiCreateComponentSimple'
+import { isVaporComponent } from '../_new/component'
// export function insert(
// block: Block,
export { createBranch, createIf } from './apiCreateIf'
export { createFor, createForSlots } from './apiCreateFor'
export { createComponent } from './apiCreateComponent'
-export {
- createComponentSimple,
- renderEffectSimple,
- createVaporAppSimple,
-} from './apiCreateComponentSimple'
export { createSelector } from './apiCreateSelector'
export { setInheritAttrs } from './componentAttrs'
export const setDevtoolsHook = (
__DEV__ || __ESM_BUNDLER__ ? _setDevtoolsHook : NOOP
) as typeof _setDevtoolsHook
+
+export * from './_new'