diff --git a/BACKERS.md b/BACKERS.md index fa66d206698..631bcb91120 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -1,6 +1,6 @@

Sponsors & Backers

-Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of the awesome sponsors and backers listed in this file. If you'd like to join them, please consider [ sponsor Vue's development](https://vuejs.org/sponsor/). +Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of the awesome sponsors and backers listed in this file. If you'd like to join them, please consider [ sponsoring Vue's development](https://vuejs.org/sponsor/).

diff --git a/README.md b/README.md index 8d2342c1ea0..17d9abc6bae 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Please follow the documentation at [vuejs.org](https://vuejs.org/)! ## Sponsors -Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://github.com/vuejs/core/blob/main/BACKERS.md). If you'd like to join them, please consider [ sponsor Vue's development](https://vuejs.org/sponsor/). +Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://github.com/vuejs/core/blob/main/BACKERS.md). If you'd like to join them, please consider [ sponsoring Vue's development](https://vuejs.org/sponsor/).

Special Sponsor

diff --git a/packages/runtime-core/__tests__/componentProps.spec.ts b/packages/runtime-core/__tests__/componentProps.spec.ts index cdb77838e31..195f352154c 100644 --- a/packages/runtime-core/__tests__/componentProps.spec.ts +++ b/packages/runtime-core/__tests__/componentProps.spec.ts @@ -321,6 +321,42 @@ describe('component props', () => { expect(`Missing required prop: "num"`).toHaveBeenWarned() }) + test('warn on type mismatch', () => { + class MyClass { + + } + const Comp = { + props: { + bool: { type: Boolean }, + str: { type: String }, + num: { type: Number }, + arr: { type: Array }, + obj: { type: Object }, + cls: { type: MyClass }, + fn: { type: Function }, + }, + setup() { + return () => null + } + } + render(h(Comp, { + bool: 'true', + str: 100, + num: '100', + arr: {}, + obj: 'false', + cls: {}, + fn: true, + }), nodeOps.createElement('div')) + expect(`Invalid prop: type check failed for prop "bool". Expected Boolean, got String`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "str". Expected String with value "100", got Number with value 100.`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "num". Expected Number with value 100, got String with value "100".`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "arr". Expected Array, got Object`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "obj". Expected Object, got String with value "false"`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "fn". Expected Function, got Boolean with value true.`).toHaveBeenWarned() + expect(`Invalid prop: type check failed for prop "cls". Expected MyClass, got Object`).toHaveBeenWarned() + }) + // #3495 test('should not warn required props using kebab-case', async () => { const Comp = { diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index d59a4e94699..fa756fa32f2 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -557,8 +557,8 @@ function validatePropName(key: string) { // use function string name to check type constructors // so that it works across vms / iframes. function getType(ctor: Prop): string { - const match = ctor && ctor.toString().match(/^\s*function (\w+)/) - return match ? match[1] : ctor === null ? 'null' : '' + const match = ctor && ctor.toString().match(/^\s*(function|class) (\w+)/) + return match ? match[2] : ctor === null ? 'null' : '' } function isSameType(a: Prop, b: Prop): boolean { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 7d873f5a125..83eedc4ccef 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -672,7 +672,8 @@ export function cloneVNode( ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback), el: vnode.el, anchor: vnode.anchor, - ctx: vnode.ctx + ctx: vnode.ctx, + ce: vnode.ce } if (__COMPAT__) { defineLegacyVNodeProperties(cloned as VNode) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 7826f438300..f4199192278 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -384,6 +384,25 @@ describe('defineCustomElement', () => { detail: [1] }) }) + // #7293 + test('emit in an async component wrapper with properties bound', async () => { + const E = defineCustomElement( + defineAsyncComponent( + () => new Promise(res => res(CompDef as any)) + ) + ) + customElements.define('my-async-el-props-emits', E) + container.innerHTML = `` + const e = container.childNodes[0] as VueElement + const spy = jest.fn() + e.addEventListener('my-click', spy) + await customElements.whenDefined('my-async-el-props-emits') + e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click')) + expect(spy).toHaveBeenCalled() + expect(spy.mock.calls[0][0]).toMatchObject({ + detail: [1] + }) + }) }) describe('slots', () => {