From 2f3627ad464c146a1cccf566199bf23ff60a1cef Mon Sep 17 00:00:00 2001 From: Mr-ccyou <1787176370@qq.com> Date: Mon, 15 Apr 2024 17:16:29 +0800 Subject: [PATCH 1/5] feat(runtime-vapor): runtime for v-on in component --- packages/runtime-vapor/src/componentEmits.ts | 45 ++++++++++++++++---- packages/runtime-vapor/src/componentProps.ts | 4 +- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/packages/runtime-vapor/src/componentEmits.ts b/packages/runtime-vapor/src/componentEmits.ts index bbca2044c..bb848e094 100644 --- a/packages/runtime-vapor/src/componentEmits.ts +++ b/packages/runtime-vapor/src/componentEmits.ts @@ -1,7 +1,6 @@ // NOTE: runtime-core/src/componentEmits.ts // TODO WIP -// @ts-nocheck import { EMPTY_OBJ, @@ -11,6 +10,7 @@ import { hasOwn, hyphenate, isArray, + isFunction, isOn, isString, looseToNumber, @@ -18,6 +18,11 @@ import { } from '@vue/shared' import type { Component, ComponentInternalInstance } from './component' import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling' +import { + type NormalizedRawProps, + type StaticProps, + getDynamicPropValue, +} from './componentProps' export type ObjectEmitsOptions = Record< string, @@ -49,8 +54,28 @@ export function emit( ) { if (instance.isUnmounted) return // TODO - // @ts-expect-error - const { rawProps } = instance + const { rawProps, emitsOptions } = instance + const hasDynamicProps = rawProps.some(isFunction) + const events: Record any> = {} + + if (emitsOptions) { + if (hasDynamicProps) { + for (const key in emitsOptions) { + const rawKey = toHandlerKey(key) + const [handler] = getDynamicPropValue( + rawProps as NormalizedRawProps, + rawKey, + ) + events[rawKey] = handler as (...args: any[]) => any + } + } else { + for (const key in emitsOptions) { + const rawKey = toHandlerKey(key) + const handler = (rawProps[0] as StaticProps)[rawKey] + events[rawKey] = handler as (...args: any[]) => any + } + } + } let args = rawArgs const isModelListener = event.startsWith('update:') @@ -58,11 +83,13 @@ export function emit( // for v-model update:xxx events, apply modifiers on args const modelArg = isModelListener && event.slice(7) - if (modelArg && modelArg in rawProps) { + if (modelArg && modelArg in events) { const modifiersKey = `${ modelArg === 'modelValue' ? 'model' : modelArg }Modifiers` - const { number, trim } = rawProps[modifiersKey] || EMPTY_OBJ + + // @ts-expect-error: todo + const { number, trim } = events[modifiersKey] || EMPTY_OBJ if (trim) { args = rawArgs.map(a => (isString(a) ? a.trim() : a)) } @@ -75,13 +102,13 @@ export function emit( let handlerName let handler = - rawProps[(handlerName = toHandlerKey(event))] || + events[(handlerName = toHandlerKey(event))] || // also try camelCase event handler (#2249) - rawProps[(handlerName = toHandlerKey(camelize(event)))] + events[(handlerName = toHandlerKey(camelize(event)))] // for v-model update:xxx events, also trigger kebab-case equivalent // for props passed via kebab-case if (!handler && isModelListener) { - handler = rawProps[(handlerName = toHandlerKey(hyphenate(event)))] + handler = events[(handlerName = toHandlerKey(hyphenate(event)))] } if (handler) { @@ -93,7 +120,7 @@ export function emit( ) } - const onceHandler = rawProps[`${handlerName}Once`] + const onceHandler = events[`${handlerName}Once`] if (onceHandler) { if (!instance.emitted) { instance.emitted = {} diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 4745b57bb..0c13815be 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -72,7 +72,7 @@ export type NormalizedPropsOptions = | [props: NormalizedProps, needCastKeys: string[]] | [] -type StaticProps = Record unknown> +export type StaticProps = Record unknown> type DynamicProps = () => Data export type NormalizedRawProps = Array export type RawProps = NormalizedRawProps | StaticProps | null @@ -170,7 +170,7 @@ function getRawKey(obj: Data, key: string) { } type DynamicPropResult = [value: unknown, absent: boolean] -function getDynamicPropValue( +export function getDynamicPropValue( rawProps: NormalizedRawProps, key: string, ): DynamicPropResult { From cfdb0f0fa5aa437757b26791719690f63dc8f26b Mon Sep 17 00:00:00 2001 From: Mr-ccyou <1787176370@qq.com> Date: Mon, 15 Apr 2024 17:28:33 +0800 Subject: [PATCH 2/5] feat(runtime-vapor): emit function add dev warnning --- packages/runtime-vapor/src/componentEmits.ts | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/runtime-vapor/src/componentEmits.ts b/packages/runtime-vapor/src/componentEmits.ts index bb848e094..0fda83d25 100644 --- a/packages/runtime-vapor/src/componentEmits.ts +++ b/packages/runtime-vapor/src/componentEmits.ts @@ -23,6 +23,7 @@ import { type StaticProps, getDynamicPropValue, } from './componentProps' +import { warn } from './warning' export type ObjectEmitsOptions = Record< string, @@ -54,6 +55,33 @@ export function emit( ) { if (instance.isUnmounted) return // TODO + if (__DEV__) { + const { + emitsOptions, + propsOptions: [propsOptions], + } = instance + if (emitsOptions) { + if (!(event in emitsOptions)) { + if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { + warn( + `Component emitted event "${event}" but it is neither declared in ` + + `the emits option nor as an "${toHandlerKey(event)}" prop.`, + ) + } + } else { + const validator = emitsOptions[event] + if (isFunction(validator)) { + const isValid = validator(...rawArgs) + if (!isValid) { + warn( + `Invalid event arguments: event validation failed for event "${event}".`, + ) + } + } + } + } + } + const { rawProps, emitsOptions } = instance const hasDynamicProps = rawProps.some(isFunction) const events: Record any> = {} From a531201dfb0e96f453b6d28815d92868e7d8693a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Tue, 16 Apr 2024 16:28:16 +0800 Subject: [PATCH 3/5] chore: cleanup --- packages/runtime-vapor/src/componentEmits.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/runtime-vapor/src/componentEmits.ts b/packages/runtime-vapor/src/componentEmits.ts index 0fda83d25..2ebd1eb9b 100644 --- a/packages/runtime-vapor/src/componentEmits.ts +++ b/packages/runtime-vapor/src/componentEmits.ts @@ -1,7 +1,3 @@ -// NOTE: runtime-core/src/componentEmits.ts - -// TODO WIP - import { EMPTY_OBJ, type UnionToIntersection, @@ -54,7 +50,7 @@ export function emit( ...rawArgs: any[] ) { if (instance.isUnmounted) return - // TODO + if (__DEV__) { const { emitsOptions, From 546319a0aac68c1e585a2526419d9c7090dfe0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Fri, 19 Apr 2024 16:17:41 +0800 Subject: [PATCH 4/5] feat(compiler-vapor): component emits --- .../__tests__/componentEmits.spec.ts | 192 ++++++++---------- packages/runtime-vapor/src/componentEmits.ts | 94 ++++----- 2 files changed, 125 insertions(+), 161 deletions(-) diff --git a/packages/runtime-vapor/__tests__/componentEmits.spec.ts b/packages/runtime-vapor/__tests__/componentEmits.spec.ts index 6094c5120..1a7d71f95 100644 --- a/packages/runtime-vapor/__tests__/componentEmits.spec.ts +++ b/packages/runtime-vapor/__tests__/componentEmits.spec.ts @@ -3,81 +3,69 @@ // Note: emits and listener fallthrough is tested in // ./rendererAttrsFallthrough.spec.ts. -import { nextTick, onBeforeUnmount } from '../src' +import { toHandlers } from '@vue/runtime-core' +import { + createComponent, + defineComponent, + nextTick, + onBeforeUnmount, +} from '../src' import { isEmitListener } from '../src/componentEmits' import { makeRender } from './_utils' -const define = makeRender() +const define = makeRender() -describe.todo('component: emit', () => { +describe('component: emit', () => { test('trigger handlers', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('foo') emit('bar') emit('!baz') }, }) - const onfoo = vi.fn() + const onFoo = vi.fn() const onBar = vi.fn() const onBaz = vi.fn() render({ - get onfoo() { - return onfoo - }, - get onBar() { - return onBar - }, - get ['on!baz']() { - return onBaz - }, + onfoo: () => onFoo, + onBar: () => onBar, + ['on!baz']: () => onBaz, }) - expect(onfoo).not.toHaveBeenCalled() + expect(onFoo).not.toHaveBeenCalled() expect(onBar).toHaveBeenCalled() expect(onBaz).toHaveBeenCalled() }) test('trigger camelCase handler', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('test-event') }, }) const fooSpy = vi.fn() - render({ - get onTestEvent() { - return fooSpy - }, - }) + render({ onTestEvent: () => fooSpy }) expect(fooSpy).toHaveBeenCalled() }) test('trigger kebab-case handler', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('test-event') }, }) const fooSpy = vi.fn() - render({ - get ['onTest-event']() { - return fooSpy - }, - }) + render({ ['onTest-event']: () => fooSpy }) expect(fooSpy).toHaveBeenCalledTimes(1) }) // #3527 - test.todo('trigger mixed case handlers', () => { + test('trigger mixed case handlers', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('test-event') emit('testEvent') }, @@ -86,15 +74,10 @@ describe.todo('component: emit', () => { const fooSpy = vi.fn() const barSpy = vi.fn() render( - // TODO: impl `toHandlers` - { - get ['onTest-Event']() { - return fooSpy - }, - get onTestEvent() { - return barSpy - }, - }, + toHandlers({ + 'test-event': () => fooSpy, + testEvent: () => barSpy, + }), ) expect(fooSpy).toHaveBeenCalledTimes(1) expect(barSpy).toHaveBeenCalledTimes(1) @@ -103,8 +86,7 @@ describe.todo('component: emit', () => { // for v-model:foo-bar usage in DOM templates test('trigger hyphenated events for update:xxx events', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('update:fooProp') emit('update:barProp') }, @@ -113,12 +95,8 @@ describe.todo('component: emit', () => { const fooSpy = vi.fn() const barSpy = vi.fn() render({ - get ['onUpdate:fooProp']() { - return fooSpy - }, - get ['onUpdate:bar-prop']() { - return barSpy - }, + ['onUpdate:fooProp']: () => fooSpy, + ['onUpdate:bar-prop']: () => barSpy, }) expect(fooSpy).toHaveBeenCalled() @@ -127,8 +105,7 @@ describe.todo('component: emit', () => { test('should trigger array of listeners', async () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('foo', 1) }, }) @@ -136,29 +113,49 @@ describe.todo('component: emit', () => { const fn1 = vi.fn() const fn2 = vi.fn() - render({ - onFoo: () => [fn1, fn2], - }) + render({ onFoo: () => [fn1, fn2] }) expect(fn1).toHaveBeenCalledTimes(1) expect(fn1).toHaveBeenCalledWith(1) expect(fn2).toHaveBeenCalledTimes(1) expect(fn2).toHaveBeenCalledWith(1) }) - test.todo('warning for undeclared event (array)', () => { - // TODO: warning + test('warning for undeclared event (array)', () => { + const { render } = define({ + emits: ['foo'], + + setup(_, { emit }) { + emit('bar') + }, + }) + render() + expect( + `Component emitted event "bar" but it is neither declared`, + ).toHaveBeenWarned() }) - test.todo('warning for undeclared event (object)', () => { - // TODO: warning + test('warning for undeclared event (object)', () => { + const { render } = define({ + emits: { + foo: null, + }, + + setup(_, { emit }) { + emit('bar') + }, + }) + render() + expect( + `Component emitted event "bar" but it is neither declared`, + ).toHaveBeenWarned() }) test('should not warn if has equivalent onXXX prop', () => { define({ props: ['onFoo'], emits: [], - render() {}, - setup(_: any, { emit }: any) { + + setup(_, { emit }) { emit('foo') }, }).render() @@ -182,12 +179,11 @@ describe.todo('component: emit', () => { test('.once', () => { const { render } = define({ - render() {}, emits: { foo: null, bar: null, }, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('foo') emit('foo') emit('bar') @@ -197,12 +193,8 @@ describe.todo('component: emit', () => { const fn = vi.fn() const barFn = vi.fn() render({ - get onFooOnce() { - return fn - }, - get onBarOnce() { - return barFn - }, + onFooOnce: () => fn, + onBarOnce: () => barFn, }) expect(fn).toHaveBeenCalledTimes(1) expect(barFn).toHaveBeenCalledTimes(1) @@ -210,11 +202,10 @@ describe.todo('component: emit', () => { test('.once with normal listener of the same name', () => { const { render } = define({ - render() {}, emits: { foo: null, }, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('foo') emit('foo') }, @@ -222,12 +213,8 @@ describe.todo('component: emit', () => { const onFoo = vi.fn() const onFooOnce = vi.fn() render({ - get onFoo() { - return onFoo - }, - get onFooOnce() { - return onFooOnce - }, + onFoo: () => onFoo, + onFooOnce: () => onFooOnce, }) expect(onFoo).toHaveBeenCalledTimes(2) expect(onFooOnce).toHaveBeenCalledTimes(1) @@ -235,8 +222,7 @@ describe.todo('component: emit', () => { test('.number modifier should work with v-model on component', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('update:modelValue', '1') emit('update:foo', '2') }, @@ -244,24 +230,12 @@ describe.todo('component: emit', () => { const fn1 = vi.fn() const fn2 = vi.fn() render({ - modelValue() { - return null - }, - modelModifiers() { - return { number: true } - }, - ['onUpdate:modelValue']() { - return fn1 - }, - foo() { - return null - }, - fooModifiers() { - return { number: true } - }, - ['onUpdate:foo']() { - return fn2 - }, + modelValue: () => null, + modelModifiers: () => ({ number: true }), + ['onUpdate:modelValue']: () => fn1, + foo: () => null, + fooModifiers: () => ({ number: true }), + ['onUpdate:foo']: () => fn2, }) expect(fn1).toHaveBeenCalledTimes(1) expect(fn1).toHaveBeenCalledWith(1) @@ -271,8 +245,7 @@ describe.todo('component: emit', () => { test('.trim modifier should work with v-model on component', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('update:modelValue', ' one ') emit('update:foo', ' two ') }, @@ -307,8 +280,7 @@ describe.todo('component: emit', () => { test('.trim and .number modifiers should work with v-model on component', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('update:modelValue', ' +01.2 ') emit('update:foo', ' 1 ') }, @@ -343,8 +315,7 @@ describe.todo('component: emit', () => { test('only trim string parameter when work with v-model on component', () => { const { render } = define({ - render() {}, - setup(_: any, { emit }: any) { + setup(_, { emit }) { emit('update:modelValue', ' foo ', { bar: ' bar ' }) }, }) @@ -395,20 +366,21 @@ describe.todo('component: emit', () => { test('does not emit after unmount', async () => { const fn = vi.fn() - const { app } = define({ + + const Foo = defineComponent({ emits: ['closing'], - setup(_: any, { emit }: any) { + setup(_, { emit }) { onBeforeUnmount(async () => { await nextTick() emit('closing', true) }) }, - render() {}, - }).render({ - get onClosing() { - return fn - }, }) + + const { app } = define(() => + createComponent(Foo, { onClosing: () => fn }), + ).render() + await nextTick() app.unmount() await nextTick() diff --git a/packages/runtime-vapor/src/componentEmits.ts b/packages/runtime-vapor/src/componentEmits.ts index 2ebd1eb9b..70d558207 100644 --- a/packages/runtime-vapor/src/componentEmits.ts +++ b/packages/runtime-vapor/src/componentEmits.ts @@ -1,5 +1,4 @@ import { - EMPTY_OBJ, type UnionToIntersection, camelize, extend, @@ -14,11 +13,7 @@ import { } from '@vue/shared' import type { Component, ComponentInternalInstance } from './component' import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling' -import { - type NormalizedRawProps, - type StaticProps, - getDynamicPropValue, -} from './componentProps' +import type { StaticProps } from './componentProps' import { warn } from './warning' export type ObjectEmitsOptions = Record< @@ -78,42 +73,50 @@ export function emit( } } - const { rawProps, emitsOptions } = instance + const { rawProps } = instance const hasDynamicProps = rawProps.some(isFunction) - const events: Record any> = {} - - if (emitsOptions) { - if (hasDynamicProps) { - for (const key in emitsOptions) { - const rawKey = toHandlerKey(key) - const [handler] = getDynamicPropValue( - rawProps as NormalizedRawProps, - rawKey, - ) - events[rawKey] = handler as (...args: any[]) => any - } - } else { - for (const key in emitsOptions) { - const rawKey = toHandlerKey(key) - const handler = (rawProps[0] as StaticProps)[rawKey] - events[rawKey] = handler as (...args: any[]) => any - } - } - } - let args = rawArgs - const isModelListener = event.startsWith('update:') + let handlerName: string + let handler: any + let onceHandler: any - // for v-model update:xxx events, apply modifiers on args + const isModelListener = event.startsWith('update:') const modelArg = isModelListener && event.slice(7) + let modifiers: any + + // has v-bind or :[eventName] + if (hasDynamicProps) { + // TODO + // getDynamicPropValue(rawProps, 'key') + // for (const key in rawProps) { + // const getter = () => + // registerProp(instance, props, key, getter, true) + // } + } else { + const staticProps = rawProps[0] as StaticProps + tryGet(key => staticProps[key] && staticProps[key]()) + } - if (modelArg && modelArg in events) { - const modifiersKey = `${ - modelArg === 'modelValue' ? 'model' : modelArg - }Modifiers` + function tryGet(getter: (key: string) => any) { + handler = + getter((handlerName = toHandlerKey(event))) || + // also try camelCase event handler (#2249) + getter((handlerName = toHandlerKey(camelize(event)))) + // for v-model update:xxx events, also trigger kebab-case equivalent + // for props passed via kebab-case + if (!handler && isModelListener) { + handler = getter((handlerName = toHandlerKey(hyphenate(event)))) + } + onceHandler = getter(`${handlerName}Once`) + modifiers = + modelArg && + getter(`${modelArg === 'modelValue' ? 'model' : modelArg}Modifiers`) + } - // @ts-expect-error: todo - const { number, trim } = events[modifiersKey] || EMPTY_OBJ + // for v-model update:xxx events, apply modifiers on args + let args = rawArgs + if (modifiers) { + const { number, trim } = modifiers if (trim) { args = rawArgs.map(a => (isString(a) ? a.trim() : a)) } @@ -124,17 +127,6 @@ export function emit( // TODO: warn - let handlerName - let handler = - events[(handlerName = toHandlerKey(event))] || - // also try camelCase event handler (#2249) - events[(handlerName = toHandlerKey(camelize(event)))] - // for v-model update:xxx events, also trigger kebab-case equivalent - // for props passed via kebab-case - if (!handler && isModelListener) { - handler = events[(handlerName = toHandlerKey(hyphenate(event)))] - } - if (handler) { callWithAsyncErrorHandling( handler, @@ -144,14 +136,13 @@ export function emit( ) } - const onceHandler = events[`${handlerName}Once`] if (onceHandler) { if (!instance.emitted) { instance.emitted = {} - } else if (instance.emitted[handlerName]) { + } else if (instance.emitted[handlerName!]) { return } - instance.emitted[handlerName] = true + instance.emitted[handlerName!] = true callWithAsyncErrorHandling( onceHandler, instance, @@ -167,8 +158,9 @@ export function normalizeEmitsOptions( // TODO: caching? const raw = comp.emits - let normalized: ObjectEmitsOptions = {} + if (!raw) return null + let normalized: ObjectEmitsOptions = {} if (isArray(raw)) { raw.forEach(key => (normalized[key] = null)) } else { From a7ced552fd6906db30c46313ce36720e86e3fa10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Fri, 19 Apr 2024 16:47:33 +0800 Subject: [PATCH 5/5] feat: dynamic props --- .../__tests__/componentEmits.spec.ts | 22 +++++++++++++++++++ .../runtime-vapor/src/apiCreateVaporApp.ts | 7 +++--- packages/runtime-vapor/src/componentEmits.ts | 9 ++------ packages/runtime-vapor/src/componentProps.ts | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/runtime-vapor/__tests__/componentEmits.spec.ts b/packages/runtime-vapor/__tests__/componentEmits.spec.ts index 1a7d71f95..ab7fb04fb 100644 --- a/packages/runtime-vapor/__tests__/componentEmits.spec.ts +++ b/packages/runtime-vapor/__tests__/componentEmits.spec.ts @@ -38,6 +38,28 @@ describe('component: emit', () => { expect(onBaz).toHaveBeenCalled() }) + test('trigger dynamic emits', () => { + const { render } = define({ + setup(_, { emit }) { + emit('foo') + emit('bar') + emit('!baz') + }, + }) + const onFoo = vi.fn() + const onBar = vi.fn() + const onBaz = vi.fn() + render(() => ({ + onfoo: onFoo, + onBar, + ['on!baz']: onBaz, + })) + + expect(onFoo).not.toHaveBeenCalled() + expect(onBar).toHaveBeenCalled() + expect(onBaz).toHaveBeenCalled() + }) + test('trigger camelCase handler', () => { const { render } = define({ setup(_, { emit }) { diff --git a/packages/runtime-vapor/src/apiCreateVaporApp.ts b/packages/runtime-vapor/src/apiCreateVaporApp.ts index 2d07bbba3..7a5392424 100644 --- a/packages/runtime-vapor/src/apiCreateVaporApp.ts +++ b/packages/runtime-vapor/src/apiCreateVaporApp.ts @@ -1,4 +1,4 @@ -import { isObject } from '@vue/shared' +import { isFunction, isObject } from '@vue/shared' import { type Component, type ComponentInternalInstance, @@ -14,8 +14,9 @@ export function createVaporApp( rootComponent: Component, rootProps: RawProps | null = null, ): App { - if (rootProps != null && !isObject(rootProps)) { - __DEV__ && warn(`root props passed to app.mount() must be an object.`) + if (rootProps != null && !isObject(rootProps) && !isFunction(rootProps)) { + __DEV__ && + warn(`root props passed to app.mount() must be an object or function.`) rootProps = null } diff --git a/packages/runtime-vapor/src/componentEmits.ts b/packages/runtime-vapor/src/componentEmits.ts index 70d558207..0b9424eff 100644 --- a/packages/runtime-vapor/src/componentEmits.ts +++ b/packages/runtime-vapor/src/componentEmits.ts @@ -13,7 +13,7 @@ import { } from '@vue/shared' import type { Component, ComponentInternalInstance } from './component' import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling' -import type { StaticProps } from './componentProps' +import { type StaticProps, getDynamicPropValue } from './componentProps' import { warn } from './warning' export type ObjectEmitsOptions = Record< @@ -86,12 +86,7 @@ export function emit( // has v-bind or :[eventName] if (hasDynamicProps) { - // TODO - // getDynamicPropValue(rawProps, 'key') - // for (const key in rawProps) { - // const getter = () => - // registerProp(instance, props, key, getter, true) - // } + tryGet(key => getDynamicPropValue(rawProps, key)[0]) } else { const staticProps = rawProps[0] as StaticProps tryGet(key => staticProps[key] && staticProps[key]()) diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 0c13815be..997b1e6c4 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -75,7 +75,7 @@ export type NormalizedPropsOptions = export type StaticProps = Record unknown> type DynamicProps = () => Data export type NormalizedRawProps = Array -export type RawProps = NormalizedRawProps | StaticProps | null +export type RawProps = NormalizedRawProps | StaticProps | DynamicProps | null export function initProps( instance: ComponentInternalInstance,