// for v-model update:xxx events, apply modifiers on args
// it's ok to use static get because modelModifiers can only be in the static
// part of the props
- const modifiers = isModelListener && getModelModifiers(props, event.slice(7))
+ const modifiers =
+ isModelListener && getModelModifiers(props, event.slice(7), getter)
if (modifiers) {
if (modifiers.trim) {
args = rawArgs.map(a => (isString(a) ? a.trim() : a))
)
}
- const onceHandler = props[handlerName + `Once`]
+ const onceHandler = getter(props, handlerName + `Once`)
if (onceHandler) {
if (!instance.emitted) {
instance.emitted = {}
}
instance.emitted[handlerName] = true
callWithAsyncErrorHandling(
- onceHandler,
+ onceHandler as Function | Function[],
instance,
ErrorCodes.COMPONENT_EVENT_HANDLER,
args,
}
}
-function defaultPropGetter(props: Record<string, any>, key: string): unknown {
+export function defaultPropGetter(
+ props: Record<string, any>,
+ key: string,
+): unknown {
return props[key]
}
import { warn } from '../warning'
import type { NormalizedProps } from '../componentProps'
import { watchSyncEffect } from '../apiWatch'
+import { defaultPropGetter } from '../componentEmits'
export function useModel<
M extends PropertyKey,
}
const hyphenatedName = hyphenate(name)
- const modifiers = getModelModifiers(props, camelizedName)
+ const modifiers = getModelModifiers(props, camelizedName, defaultPropGetter)
const res = customRef((track, trigger) => {
let localValue: any
export const getModelModifiers = (
props: Record<string, any>,
modelName: string,
+ getter: (props: Record<string, any>, key: string) => any,
): Record<string, boolean> | undefined => {
return modelName === 'modelValue' || modelName === 'model-value'
- ? props.modelModifiers
- : props[`${modelName}Modifiers`] ||
- props[`${camelize(modelName)}Modifiers`] ||
- props[`${hyphenate(modelName)}Modifiers`]
+ ? getter(props, 'modelModifiers')
+ : getter(props, `${modelName}Modifiers`) ||
+ getter(props, `${camelize(modelName)}Modifiers`) ||
+ getter(props, `${hyphenate(modelName)}Modifiers`)
}
const define = makeRender<any>()
+// TODO: port more tests from rendererAttrsFallthrough.spec.ts
+
describe('attribute fallthrough', () => {
it('should allow attrs to fallthrough', async () => {
const t0 = template('<div>')
// Note: emits and listener fallthrough is tested in
// ./rendererAttrsFallthrough.spec.ts.
-import { toHandlers } from '@vue/runtime-core'
import {
- createComponent,
- defineComponent,
+ isEmitListener,
nextTick,
onBeforeUnmount,
-} from '../src'
-import { isEmitListener } from '../src/componentEmits'
+ toHandlers,
+} from '@vue/runtime-dom'
+import { createComponent, defineVaporComponent } from '../src'
import { makeRender } from './_utils'
const define = makeRender()
-describe.todo('component: emit', () => {
+describe('component: emit', () => {
test('trigger handlers', () => {
const { render } = define({
setup(_, { emit }) {
emit('foo')
emit('bar')
emit('!baz')
+ return []
},
})
const onFoo = vi.fn()
emit('foo')
emit('bar')
emit('!baz')
+ return []
},
})
const onFoo = vi.fn()
const onBar = vi.fn()
const onBaz = vi.fn()
- render(() => ({
- onfoo: onFoo,
- onBar,
- ['on!baz']: onBaz,
- }))
+ render({
+ onfoo: () => onFoo,
+ onBar: () => onBar,
+ ['on!baz']: () => onBaz,
+ })
expect(onFoo).not.toHaveBeenCalled()
expect(onBar).toHaveBeenCalled()
const { render } = define({
setup(_, { emit }) {
emit('test-event')
+ return []
},
})
const { render } = define({
setup(_, { emit }) {
emit('test-event')
+ return []
},
})
setup(_, { emit }) {
emit('test-event')
emit('testEvent')
+ return []
},
})
setup(_, { emit }) {
emit('update:fooProp')
emit('update:barProp')
+ return []
},
})
const { render } = define({
setup(_, { emit }) {
emit('foo', 1)
+ return []
},
})
setup(_, { emit }) {
emit('bar')
+ return []
},
})
render()
setup(_, { emit }) {
emit('bar')
+ return []
},
})
render()
setup(_, { emit }) {
emit('foo')
+ return []
},
}).render()
expect(
// TODO: warning validator
})
- // NOTE: not supported mixins
- // test.todo('merging from mixins', () => {})
-
- // #2651
- // test.todo(
- // 'should not attach normalized object when mixins do not contain emits',
- // () => {},
- // )
-
test('.once', () => {
const { render } = define({
emits: {
emit('foo')
emit('bar')
emit('bar')
+ return []
},
})
const fn = vi.fn()
setup(_, { emit }) {
emit('foo')
emit('foo')
+ return []
},
})
const onFoo = vi.fn()
setup(_, { emit }) {
emit('update:modelValue', '1')
emit('update:foo', '2')
+ return []
},
})
const fn1 = vi.fn()
setup(_, { emit }) {
emit('update:modelValue', ' one ')
emit('update:foo', ' two ')
+ return []
},
})
const fn1 = vi.fn()
setup(_, { emit }) {
emit('update:modelValue', ' +01.2 ')
emit('update:foo', ' 1 ')
+ return []
},
})
const fn1 = vi.fn()
const { render } = define({
setup(_, { emit }) {
emit('update:modelValue', ' foo ', { bar: ' bar ' })
+ return []
},
})
const fn = vi.fn()
test('does not emit after unmount', async () => {
const fn = vi.fn()
- const Foo = defineComponent({
+ const Foo = defineVaporComponent({
emits: ['closing'],
setup(_, { emit }) {
onBeforeUnmount(async () => {
await nextTick()
emit('closing', true)
})
+ return []
},
})
+++ /dev/null
-import { describe, expect } from 'vitest'
-import { makeRender } from './_utils'
-import { type Ref, ref } from '@vue/reactivity'
-
-const define = makeRender()
-
-describe.todo('component expose', () => {
- test('should work', async () => {
- const expxosedObj = { foo: 1 }
- const { render } = define({
- setup(_, { expose }) {
- expose(expxosedObj)
- },
- })
- const { instance } = render()
- expect(instance?.exposed).toEqual(expxosedObj)
- })
-
- test('should warn when called multiple times', async () => {
- const { render } = define({
- setup(_, { expose }) {
- expose()
- expose()
- },
- })
- render()
- expect(
- 'expose() should be called only once per setup().',
- ).toHaveBeenWarned()
- })
-
- test('should warn when passed non-object', async () => {
- const exposedRef = ref<number[] | Ref>([1, 2, 3])
- const { render } = define({
- setup(_, { expose }) {
- expose(exposedRef.value)
- },
- })
- render()
- expect(
- 'expose() should be passed a plain object, received array.',
- ).toHaveBeenWarned()
- exposedRef.value = ref(1)
- render()
- expect(
- 'expose() should be passed a plain object, received ref.',
- ).toHaveBeenWarned()
- })
-})