Skip to content

Commit

Permalink
fix(runtime-core): use separate prop caches for components and mixins (
Browse files Browse the repository at this point in the history
…#11350)

Co-authored-by: Red Huang <gcaaa31928@gmail.com>

close #7998
  • Loading branch information
skirtles-code committed Jul 15, 2024
1 parent c8b9794 commit b0aa234
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
90 changes: 90 additions & 0 deletions packages/runtime-core/__tests__/componentProps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
`<div>ExtendedComp from global</div><div>Comp from global</div>`,
)
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: {
Expand Down
5 changes: 4 additions & 1 deletion packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,12 +496,15 @@ function resolvePropValue(
return value
}

const mixinPropsCache = new WeakMap<ConcreteComponent, NormalizedPropsOptions>()

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
Expand Down

0 comments on commit b0aa234

Please sign in to comment.