diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts
index 72a595258..db717f84e 100644
--- a/packages/runtime-core/src/component.ts
+++ b/packages/runtime-core/src/component.ts
@@ -785,6 +785,9 @@ export function createComponentInstance(
return instance
}
+/**
+ * @internal
+ */
export function validateComponentName(
name: string,
{ isNativeTag }: AppConfig,
diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts
index 00bc68573..0a0313e1d 100644
--- a/packages/runtime-core/src/index.ts
+++ b/packages/runtime-core/src/index.ts
@@ -500,6 +500,7 @@ export {
type GenericComponentInstance,
type LifecycleHook,
nextUid,
+ validateComponentName,
} from './component'
export { pushWarningContext, popWarningContext } from './warning'
export {
@@ -512,3 +513,4 @@ export {
simpleSetCurrentInstance,
} from './componentCurrentInstance'
export { registerHMR, unregisterHMR } from './hmr'
+export { startMeasure, endMeasure } from './profiling'
diff --git a/packages/runtime-core/src/profiling.ts b/packages/runtime-core/src/profiling.ts
index 1984f5a21..ec789de72 100644
--- a/packages/runtime-core/src/profiling.ts
+++ b/packages/runtime-core/src/profiling.ts
@@ -1,15 +1,15 @@
/* eslint-disable no-restricted-globals */
-import {
- type ComponentInternalInstance,
- formatComponentName,
-} from './component'
+import { type GenericComponentInstance, formatComponentName } from './component'
import { devtoolsPerfEnd, devtoolsPerfStart } from './devtools'
let supported: boolean
let perf: Performance
+/**
+ * @internal
+ */
export function startMeasure(
- instance: ComponentInternalInstance,
+ instance: GenericComponentInstance,
type: string,
): void {
if (instance.appContext.config.performance && isSupported()) {
@@ -21,8 +21,11 @@ export function startMeasure(
}
}
+/**
+ * @internal
+ */
export function endMeasure(
- instance: ComponentInternalInstance,
+ instance: GenericComponentInstance,
type: string,
): void {
if (instance.appContext.config.performance && isSupported()) {
diff --git a/packages/runtime-core/src/warning.ts b/packages/runtime-core/src/warning.ts
index 222a576c2..c261bf602 100644
--- a/packages/runtime-core/src/warning.ts
+++ b/packages/runtime-core/src/warning.ts
@@ -57,7 +57,7 @@ export function warn(msg: string, ...args: any[]): void {
[
// eslint-disable-next-line no-restricted-syntax
msg + args.map(a => a.toString?.() ?? JSON.stringify(a)).join(''),
- instance && instance.proxy,
+ (instance && instance.proxy) || instance,
trace
.map(
({ ctx }) =>
diff --git a/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts b/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
index 87dbf5aba..05f95bf08 100644
--- a/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiCreateSelector.spec.ts
@@ -1,6 +1,8 @@
import { ref } from '@vue/reactivity'
import { makeRender } from './_utils'
-// import { createFor, createSelector, nextTick, renderEffect } from '../src'
+// @ts-expect-error
+import { createFor, createSelector, renderEffect } from '../src'
+import { nextTick } from '@vue/runtime-dom'
const define = makeRender()
@@ -16,6 +18,7 @@ describe.todo('api: createSelector', () => {
const isSleected = createSelector(index)
return createFor(
() => list.value,
+ // @ts-expect-error
([item]) => {
const span = document.createElement('li')
renderEffect(() => {
@@ -25,6 +28,7 @@ describe.todo('api: createSelector', () => {
})
return span
},
+ // @ts-expect-error
item => item.id,
)
}).render()
@@ -66,10 +70,12 @@ describe.todo('api: createSelector', () => {
const { host } = define(() => {
const isSleected = createSelector(
index,
+ // @ts-expect-error
(key, value) => key === value + 1,
)
return createFor(
() => list.value,
+ // @ts-expect-error
([item]) => {
const span = document.createElement('li')
renderEffect(() => {
@@ -79,6 +85,7 @@ describe.todo('api: createSelector', () => {
})
return span
},
+ // @ts-expect-error
item => item.id,
)
}).render()
diff --git a/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts b/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
index faa760675..a8bbd96a9 100644
--- a/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiCreateVaporApp.spec.ts
@@ -1,25 +1,29 @@
import {
- type ComponentInternalInstance,
- type Plugin,
createComponent,
createTextNode,
createVaporApp,
- defineComponent,
- getCurrentInstance,
+ defineVaporComponent,
+ // @ts-expect-error
+ withDirectives,
+} from '../src'
+import {
+ type GenericComponentInstance,
+ type Plugin,
+ currentInstance,
inject,
provide,
resolveComponent,
resolveDirective,
- withDirectives,
-} from '../src'
-import { warn } from '@vue/runtime-dom'
+ warn,
+} from '@vue/runtime-dom'
import { makeRender } from './_utils'
+import type { VaporComponent } from '../src/component'
const define = makeRender()
-describe.todo('api: createVaporApp', () => {
+describe('api: createVaporApp', () => {
test('mount', () => {
- const Comp = defineComponent({
+ const Comp = defineVaporComponent({
props: {
count: { default: 0 },
},
@@ -51,7 +55,7 @@ describe.todo('api: createVaporApp', () => {
})
test('unmount', () => {
- const Comp = defineComponent({
+ const Comp = defineVaporComponent({
props: {
count: { default: 0 },
},
@@ -82,22 +86,22 @@ describe.todo('api: createVaporApp', () => {
},
})
- const Child = defineComponent({
+ const Child = defineVaporComponent({
setup() {
const foo = inject('foo')
const bar = inject('bar')
try {
inject('__proto__')
} catch (e: any) {}
- return createTextNode(() => [`${foo},${bar}`])
+ return createTextNode([`${foo},${bar}`])
},
})
- const { app, mount, create, host } = Root.create(null)
+ const { app, mount, create, html } = Root.create()
app.provide('foo', 1)
app.provide('bar', 2)
mount()
- expect(host.innerHTML).toBe(`3,2`)
+ expect(html()).toBe(`3,2`)
expect('[Vue warn]: injection "__proto__" not found.').toHaveBeenWarned()
const { app: app2 } = create()
@@ -132,8 +136,8 @@ describe.todo('api: createVaporApp', () => {
test('component', () => {
const { app, mount, host } = define({
setup() {
- const FooBar = resolveComponent('foo-bar')
- const BarBaz = resolveComponent('bar-baz')
+ const FooBar = resolveComponent('foo-bar') as VaporComponent
+ const BarBaz = resolveComponent('bar-baz') as VaporComponent
return [createComponent(FooBar), createComponent(BarBaz)]
},
}).create()
@@ -152,7 +156,7 @@ describe.todo('api: createVaporApp', () => {
expect(host.innerHTML).toBe(`foobar!barbaz!`)
})
- test('directive', () => {
+ test.todo('directive', () => {
const spy1 = vi.fn()
const spy2 = vi.fn()
@@ -229,7 +233,7 @@ describe.todo('api: createVaporApp', () => {
test('config.errorHandler', () => {
const error = new Error()
- let instance: ComponentInternalInstance
+ let instance: GenericComponentInstance
const handler = vi.fn((err, _instance, info) => {
expect(err).toBe(error)
@@ -239,7 +243,8 @@ describe.todo('api: createVaporApp', () => {
const { app, mount } = define({
setup() {
- instance = getCurrentInstance()!
+ instance = currentInstance!
+ return {}
},
render() {
throw error
@@ -251,7 +256,7 @@ describe.todo('api: createVaporApp', () => {
})
test('config.warnHandler', () => {
- let instance: ComponentInternalInstance
+ let instance: GenericComponentInstance
const handler = vi.fn((msg, _instance, trace) => {
expect(msg).toMatch(`warn message`)
@@ -262,8 +267,9 @@ describe.todo('api: createVaporApp', () => {
const { app, mount } = define({
name: 'Hello',
setup() {
- instance = getCurrentInstance()!
+ instance = currentInstance!
warn('warn message')
+ return []
},
}).create()
@@ -275,22 +281,23 @@ describe.todo('api: createVaporApp', () => {
describe('config.isNativeTag', () => {
const isNativeTag = vi.fn(tag => tag === 'div')
- test('Component.name', () => {
- const { app, mount } = define({
- name: 'div',
- render(): any {},
- }).create()
+ // Not relevant for vapor
+ // test('Component.name', () => {
+ // const { app, mount } = define({
+ // name: 'div',
+ // render(): any {},
+ // }).create()
- Object.defineProperty(app.config, 'isNativeTag', {
- value: isNativeTag,
- writable: false,
- })
+ // Object.defineProperty(app.config, 'isNativeTag', {
+ // value: isNativeTag,
+ // writable: false,
+ // })
- mount()
- expect(
- `Do not use built-in or reserved HTML elements as component id: div`,
- ).toHaveBeenWarned()
- })
+ // mount()
+ // expect(
+ // `Do not use built-in or reserved HTML elements as component id: div`,
+ // ).toHaveBeenWarned()
+ // })
test('register using app.component', () => {
const { app, mount } = define({
@@ -316,7 +323,7 @@ describe.todo('api: createVaporApp', () => {
})
test('with performance enabled', () => {
- const { app, mount } = define({}).create()
+ const { app, mount } = define({ setup: () => [] }).create()
app.config.performance = true
mount()
@@ -324,7 +331,7 @@ describe.todo('api: createVaporApp', () => {
})
test('with performance disabled', () => {
- const { app, mount } = define({}).create()
+ const { app, mount } = define({ setup: () => [] }).create()
app.config.performance = false
mount()
@@ -333,14 +340,16 @@ describe.todo('api: createVaporApp', () => {
})
test('config.globalProperty', () => {
- const { app, mount, html } = define({
- render() {
- const instance = getCurrentInstance()!
- return createTextNode([instance.appContext.config.globalProperties.msg])
+ const { app } = define({
+ setup() {
+ return []
},
}).create()
- app.config.globalProperties.msg = 'hello world'
- mount()
- expect(html()).toBe('hello world')
+ try {
+ app.config.globalProperties.msg = 'hello world'
+ } catch (e) {}
+ expect(
+ `app.config.globalProperties is not supported in vapor mode`,
+ ).toHaveBeenWarned()
})
})
diff --git a/packages/runtime-vapor/__tests__/apiExpose.spec.ts b/packages/runtime-vapor/__tests__/apiExpose.spec.ts
index e5b482c5f..91f2b76af 100644
--- a/packages/runtime-vapor/__tests__/apiExpose.spec.ts
+++ b/packages/runtime-vapor/__tests__/apiExpose.spec.ts
@@ -1,11 +1,8 @@
import { ref, shallowRef } from '@vue/reactivity'
-import { createComponent } from '../src/component'
+import { type VaporComponentInstance, createComponent } from '../src/component'
import { setRef } from '../src/dom/templateRef'
import { makeRender } from './_utils'
-import {
- type ComponentInternalInstance,
- getCurrentInstance,
-} from '../src/component'
+import { currentInstance } from '@vue/runtime-dom'
import { defineVaporComponent } from '../src/apiDefineComponent'
const define = makeRender()
@@ -39,10 +36,11 @@ describe.todo('api: expose', () => {
})
test('via setup context (expose empty)', () => {
- let childInstance: ComponentInternalInstance | null = null
+ let childInstance: VaporComponentInstance | null = null
const Child = defineVaporComponent({
setup(_) {
- childInstance = getCurrentInstance()
+ childInstance = currentInstance as VaporComponentInstance
+ return []
},
})
const childRef = shallowRef()
@@ -77,6 +75,7 @@ describe.todo('api: expose', () => {
define({
setup(_, { expose }) {
expose(ref(1))
+ return []
},
}).render()
@@ -89,6 +88,7 @@ describe.todo('api: expose', () => {
define({
setup(_, { expose }) {
expose(['focus'])
+ return []
},
}).render()
@@ -101,6 +101,7 @@ describe.todo('api: expose', () => {
define({
setup(_, { expose }) {
expose(() => null)
+ return []
},
}).render()
diff --git a/packages/runtime-vapor/__tests__/dom/templateRef.spec.ts b/packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
index 16bd6403c..f4fb1d077 100644
--- a/packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
+++ b/packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
@@ -1,19 +1,23 @@
import type { NodeRef } from '../../src/dom/templateRef'
import {
+ // @ts-expect-error
createFor,
+ // @ts-expect-error
createIf,
- getCurrentInstance,
insert,
- nextTick,
- reactive,
- ref,
renderEffect,
setRef,
setText,
template,
- watchEffect,
} from '../../src'
import { makeRender } from '../_utils'
+import {
+ currentInstance,
+ nextTick,
+ reactive,
+ ref,
+ watchEffect,
+} from '@vue/runtime-dom'
const define = makeRender()
@@ -257,7 +261,7 @@ describe.todo('api: template ref', () => {
const t1 = template('')
const { render } = define({
render() {
- const instance = getCurrentInstance()!
+ const instance = currentInstance!
const n0 = t0()
const n1 = t1()
let r0: NodeRef | undefined
@@ -303,7 +307,7 @@ describe.todo('api: template ref', () => {
const t1 = template('')
const { render } = define({
render() {
- const instance = getCurrentInstance()!
+ const instance = currentInstance!
const n0 = createIf(
() => refToggle.value,
() => {
@@ -355,6 +359,7 @@ describe.todo('api: template ref', () => {
const n1 = t0()
const n2 = createFor(
() => list,
+ // @ts-expect-error
state => {
const n1 = t1()
setRef(n1 as Element, listRefs, undefined, true)
@@ -413,6 +418,7 @@ describe.todo('api: template ref', () => {
const n1 = t0()
const n2 = createFor(
() => list,
+ // @ts-expect-error
state => {
const n1 = t1()
setRef(n1 as Element, 'listRefs', undefined, true)
@@ -469,6 +475,7 @@ describe.todo('api: template ref', () => {
const n2 = n1!.nextSibling!
const n3 = createFor(
() => list.value,
+ // @ts-expect-error
state => {
const n4 = t1()
setRef(n4 as Element, 'listRefs', undefined, true)
diff --git a/packages/runtime-vapor/src/apiCreateApp.ts b/packages/runtime-vapor/src/apiCreateApp.ts
index fc976f7b5..7c4db8961 100644
--- a/packages/runtime-vapor/src/apiCreateApp.ts
+++ b/packages/runtime-vapor/src/apiCreateApp.ts
@@ -11,6 +11,7 @@ import {
type CreateAppFunction,
createAppAPI,
normalizeContainer,
+ warn,
} from '@vue/runtime-dom'
import type { RawProps } from './componentProps'
@@ -21,7 +22,13 @@ const mountApp: AppMountFn = (app, container) => {
if (container.nodeType === 1 /* Node.ELEMENT_NODE */) {
container.textContent = ''
}
- const instance = createComponent(app._component, app._props as RawProps)
+ const instance = createComponent(
+ app._component,
+ app._props as RawProps,
+ null,
+ false,
+ app._context,
+ )
mountComponent(instance, container)
return instance
}
@@ -36,6 +43,19 @@ export const createVaporApp: CreateAppFunction = (
) => {
if (!_createApp) _createApp = createAppAPI(mountApp, unmountApp, i => i)
const app = _createApp(comp, props)
+
+ if (__DEV__) {
+ app.config.globalProperties = new Proxy(
+ {},
+ {
+ set() {
+ warn(`app.config.globalProperties is not supported in vapor mode.`)
+ return false
+ },
+ },
+ )
+ }
+
const mount = app.mount
app.mount = (container, ...args: any[]) => {
container = normalizeContainer(container) as ParentNode
diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts
index 033b2fa6a..f544809b7 100644
--- a/packages/runtime-vapor/src/component.ts
+++ b/packages/runtime-vapor/src/component.ts
@@ -13,11 +13,13 @@ import {
type SuspenseBoundary,
callWithErrorHandling,
currentInstance,
+ endMeasure,
nextUid,
popWarningContext,
pushWarningContext,
registerHMR,
simpleSetCurrentInstance,
+ startMeasure,
unregisterHMR,
warn,
} from '@vue/runtime-dom'
@@ -100,6 +102,7 @@ export function createComponent(
rawProps?: RawProps | null,
rawSlots?: RawSlots | null,
isSingleRoot?: boolean,
+ appContext?: GenericAppContext,
): VaporComponentInstance {
// check if we are the single root of the parent
// if yes, inject parent attrs as dynamic props source
@@ -117,15 +120,22 @@ export function createComponent(
}
}
- const instance = new VaporComponentInstance(component, rawProps, rawSlots)
- const prev = currentInstance
- simpleSetCurrentInstance(instance)
+ const instance = new VaporComponentInstance(
+ component,
+ rawProps,
+ rawSlots,
+ appContext,
+ )
- pauseTracking()
if (__DEV__) {
pushWarningContext(instance)
+ startMeasure(instance, `init`)
}
+ const prev = currentInstance
+ simpleSetCurrentInstance(instance)
+ pauseTracking()
+
const setupFn = isFunction(component) ? component : component.setup
const setupContext = (instance.setupContext =
setupFn && setupFn.length > 1 ? new SetupContext(instance) : null)
@@ -177,12 +187,14 @@ export function createComponent(
})
}
- if (__DEV__) {
- popWarningContext()
- }
resetTracking()
simpleSetCurrentInstance(prev, instance)
+ if (__DEV__) {
+ popWarningContext()
+ endMeasure(instance, 'init')
+ }
+
return instance
}
@@ -280,6 +292,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
comp: VaporComponent,
rawProps?: RawProps | null,
rawSlots?: RawSlots | null,
+ appContext?: GenericAppContext,
) {
this.vapor = true
this.uid = nextUid()
@@ -295,7 +308,7 @@ export class VaporComponentInstance implements GenericComponentInstance {
this.provides = currentInstance.provides
this.ids = currentInstance.ids
} else {
- this.appContext = emptyContext
+ this.appContext = appContext || emptyContext
this.provides = Object.create(this.appContext.provides)
this.ids = ['', 0, 0]
}
@@ -417,6 +430,9 @@ export function mountComponent(
parent: ParentNode,
anchor?: Node | null | 0,
): void {
+ if (__DEV__) {
+ startMeasure(instance, `mount`)
+ }
if (!instance.isMounted) {
if (instance.bm) invokeArrayFns(instance.bm)
insert(instance.block, parent, anchor)
@@ -427,6 +443,9 @@ export function mountComponent(
} else {
insert(instance.block, parent, anchor)
}
+ if (__DEV__) {
+ endMeasure(instance, `mount`)
+ }
}
export function unmountComponent(
diff --git a/packages/runtime-vapor/src/renderEffect.ts b/packages/runtime-vapor/src/renderEffect.ts
index 6dec684b0..b3d10b758 100644
--- a/packages/runtime-vapor/src/renderEffect.ts
+++ b/packages/runtime-vapor/src/renderEffect.ts
@@ -5,13 +5,14 @@ import {
queueJob,
queuePostFlushCb,
simpleSetCurrentInstance,
+ startMeasure,
warn,
} from '@vue/runtime-dom'
import { type VaporComponentInstance, isVaporComponent } from './component'
import { invokeArrayFns } from '@vue/shared'
export function renderEffect(fn: () => void, noLifecycle = false): void {
- const instance = currentInstance as VaporComponentInstance
+ const instance = currentInstance as VaporComponentInstance | null
const scope = getCurrentScope()
if (__DEV__ && !__TEST__ && !isVaporComponent(instance)) {
warn('renderEffect called without active vapor instance.')
@@ -20,6 +21,9 @@ export function renderEffect(fn: () => void, noLifecycle = false): void {
const renderEffectFn = noLifecycle
? fn
: () => {
+ if (__DEV__ && instance) {
+ startMeasure(instance, `renderEffect`)
+ }
const prev = currentInstance
simpleSetCurrentInstance(instance)
if (scope) scope.on()
@@ -41,6 +45,9 @@ export function renderEffect(fn: () => void, noLifecycle = false): void {
}
if (scope) scope.off()
simpleSetCurrentInstance(prev, instance)
+ if (__DEV__ && instance) {
+ startMeasure(instance, `renderEffect`)
+ }
}
const effect = new ReactiveEffect(renderEffectFn)