Skip to content

Commit b0aa234

Browse files
authoredJul 15, 2024··
fix(runtime-core): use separate prop caches for components and mixins (#11350)
Co-authored-by: Red Huang <gcaaa31928@gmail.com> close #7998
1 parent c8b9794 commit b0aa234

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed
 

‎packages/runtime-core/__tests__/componentProps.spec.ts

+90
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,96 @@ describe('component props', () => {
538538
expect(renderProxy.$props).toMatchObject(props)
539539
})
540540

541+
test('merging props from global mixins and extends', () => {
542+
let renderProxy: any
543+
let extendedRenderProxy: any
544+
545+
const defaultProp = ' from global'
546+
const props = {
547+
globalProp: {
548+
type: String,
549+
default: defaultProp,
550+
},
551+
}
552+
const globalMixin = {
553+
props,
554+
}
555+
const Comp = {
556+
render(this: any) {
557+
renderProxy = this
558+
return h('div', ['Comp', this.globalProp])
559+
},
560+
}
561+
const ExtendedComp = {
562+
extends: Comp,
563+
render(this: any) {
564+
extendedRenderProxy = this
565+
return h('div', ['ExtendedComp', this.globalProp])
566+
},
567+
}
568+
569+
const app = createApp(
570+
{
571+
render: () => [h(ExtendedComp), h(Comp)],
572+
},
573+
{},
574+
)
575+
app.mixin(globalMixin)
576+
577+
const root = nodeOps.createElement('div')
578+
app.mount(root)
579+
580+
expect(serializeInner(root)).toMatch(
581+
`<div>ExtendedComp from global</div><div>Comp from global</div>`,
582+
)
583+
expect(renderProxy.$props).toMatchObject({ globalProp: defaultProp })
584+
expect(extendedRenderProxy.$props).toMatchObject({
585+
globalProp: defaultProp,
586+
})
587+
})
588+
589+
test('merging props for a component that is also used as a mixin', () => {
590+
const CompA = {
591+
render(this: any) {
592+
return this.foo
593+
},
594+
}
595+
596+
const mixin = {
597+
props: {
598+
foo: {
599+
default: 'from mixin',
600+
},
601+
},
602+
}
603+
604+
const CompB = {
605+
mixins: [mixin, CompA],
606+
render(this: any) {
607+
return this.foo
608+
},
609+
}
610+
611+
const app = createApp({
612+
render() {
613+
return [h(CompA), ', ', h(CompB)]
614+
},
615+
})
616+
617+
app.mixin({
618+
props: {
619+
foo: {
620+
default: 'from global mixin',
621+
},
622+
},
623+
})
624+
625+
const root = nodeOps.createElement('div')
626+
app.mount(root)
627+
628+
expect(serializeInner(root)).toMatch(`from global mixin, from mixin`)
629+
})
630+
541631
test('props type support BigInt', () => {
542632
const Comp = {
543633
props: {

‎packages/runtime-core/src/componentProps.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,15 @@ function resolvePropValue(
496496
return value
497497
}
498498

499+
const mixinPropsCache = new WeakMap<ConcreteComponent, NormalizedPropsOptions>()
500+
499501
export function normalizePropsOptions(
500502
comp: ConcreteComponent,
501503
appContext: AppContext,
502504
asMixin = false,
503505
): NormalizedPropsOptions {
504-
const cache = appContext.propsCache
506+
const cache =
507+
__FEATURE_OPTIONS_API__ && asMixin ? mixinPropsCache : appContext.propsCache
505508
const cached = cache.get(comp)
506509
if (cached) {
507510
return cached

0 commit comments

Comments
 (0)
Please sign in to comment.