diff --git a/packages/runtime-core/__tests__/apiExpose.spec.ts b/packages/runtime-core/__tests__/apiExpose.spec.ts index 1bfd513943b..b912db00521 100644 --- a/packages/runtime-core/__tests__/apiExpose.spec.ts +++ b/packages/runtime-core/__tests__/apiExpose.spec.ts @@ -225,4 +225,43 @@ describe('api: expose', () => { expect(grandChildRef.value.$parent).toBe(childRef.value) expect(grandChildRef.value.$parent.$parent).toBe(grandChildRef.value.$root) }) + + test('warning for ref', () => { + const Comp = defineComponent({ + setup(_, { expose }) { + expose(ref(1)) + return () => null + } + }) + render(h(Comp), nodeOps.createElement('div')) + expect( + 'expose() should be passed a plain object, received ref' + ).toHaveBeenWarned() + }) + + test('warning for array', () => { + const Comp = defineComponent({ + setup(_, { expose }) { + expose(['focus']) + return () => null + } + }) + render(h(Comp), nodeOps.createElement('div')) + expect( + 'expose() should be passed a plain object, received array' + ).toHaveBeenWarned() + }) + + test('warning for function', () => { + const Comp = defineComponent({ + setup(_, { expose }) { + expose(() => null) + return () => null + } + }) + render(h(Comp), nodeOps.createElement('div')) + expect( + 'expose() should be passed a plain object, received function' + ).toHaveBeenWarned() + }) }) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 786e3f3a030..0bc718f1b50 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -1,5 +1,6 @@ import { VNode, VNodeChild, isVNode } from './vnode' import { + isRef, pauseTracking, resetTracking, shallowReadonly, @@ -47,6 +48,7 @@ import { } from './componentEmits' import { EMPTY_OBJ, + isArray, isFunction, NOOP, isObject, @@ -913,8 +915,25 @@ export function createSetupContext( instance: ComponentInternalInstance ): SetupContext { const expose: SetupContext['expose'] = exposed => { - if (__DEV__ && instance.exposed) { - warn(`expose() should be called only once per setup().`) + if (__DEV__) { + if (instance.exposed) { + warn(`expose() should be called only once per setup().`) + } + if (exposed != null) { + let exposedType: string = typeof exposed + if (exposedType === 'object') { + if (isArray(exposed)) { + exposedType = 'array' + } else if (isRef(exposed)) { + exposedType = 'ref' + } + } + if (exposedType !== 'object') { + warn( + `expose() should be passed a plain object, received ${exposedType}.` + ) + } + } } instance.exposed = exposed || {} }