diff --git a/packages/runtime-core/__tests__/componentProps.spec.ts b/packages/runtime-core/__tests__/componentProps.spec.ts
index 824458000..8c9c38b3c 100644
--- a/packages/runtime-core/__tests__/componentProps.spec.ts
+++ b/packages/runtime-core/__tests__/componentProps.spec.ts
@@ -538,6 +538,96 @@ describe('component props', () => {
expect(renderProxy.$props).toMatchObject(props)
})
+ test('merging props from global mixins and extends', () => {
+ let renderProxy: any
+ let extendedRenderProxy: any
+
+ const defaultProp = ' from global'
+ const props = {
+ globalProp: {
+ type: String,
+ default: defaultProp,
+ },
+ }
+ const globalMixin = {
+ props,
+ }
+ const Comp = {
+ render(this: any) {
+ renderProxy = this
+ return h('div', ['Comp', this.globalProp])
+ },
+ }
+ const ExtendedComp = {
+ extends: Comp,
+ render(this: any) {
+ extendedRenderProxy = this
+ return h('div', ['ExtendedComp', this.globalProp])
+ },
+ }
+
+ const app = createApp(
+ {
+ render: () => [h(ExtendedComp), h(Comp)],
+ },
+ {},
+ )
+ app.mixin(globalMixin)
+
+ const root = nodeOps.createElement('div')
+ app.mount(root)
+
+ expect(serializeInner(root)).toMatch(
+ `
ExtendedComp from global
Comp from global
`,
+ )
+ expect(renderProxy.$props).toMatchObject({ globalProp: defaultProp })
+ expect(extendedRenderProxy.$props).toMatchObject({
+ globalProp: defaultProp,
+ })
+ })
+
+ test('merging props for a component that is also used as a mixin', () => {
+ const CompA = {
+ render(this: any) {
+ return this.foo
+ },
+ }
+
+ const mixin = {
+ props: {
+ foo: {
+ default: 'from mixin',
+ },
+ },
+ }
+
+ const CompB = {
+ mixins: [mixin, CompA],
+ render(this: any) {
+ return this.foo
+ },
+ }
+
+ const app = createApp({
+ render() {
+ return [h(CompA), ', ', h(CompB)]
+ },
+ })
+
+ app.mixin({
+ props: {
+ foo: {
+ default: 'from global mixin',
+ },
+ },
+ })
+
+ const root = nodeOps.createElement('div')
+ app.mount(root)
+
+ expect(serializeInner(root)).toMatch(`from global mixin, from mixin`)
+ })
+
test('props type support BigInt', () => {
const Comp = {
props: {
diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts
index 5a4292b6f..9d7b7f0e4 100644
--- a/packages/runtime-core/src/componentProps.ts
+++ b/packages/runtime-core/src/componentProps.ts
@@ -496,12 +496,15 @@ function resolvePropValue(
return value
}
+const mixinPropsCache = new WeakMap()
+
export function normalizePropsOptions(
comp: ConcreteComponent,
appContext: AppContext,
asMixin = false,
): NormalizedPropsOptions {
- const cache = appContext.propsCache
+ const cache =
+ __FEATURE_OPTIONS_API__ && asMixin ? mixinPropsCache : appContext.propsCache
const cached = cache.get(comp)
if (cached) {
return cached