Skip to content

Commit d1899ca

Browse files
committed
fix(provide/inject): do not mutate original provide options during merge
fix #12854
1 parent 5e3d4e9 commit d1899ca

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/core/util/options.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ if (__DEV__) {
5151
*/
5252
function mergeData(
5353
to: Record<string | symbol, any>,
54-
from: Record<string | symbol, any> | null
54+
from: Record<string | symbol, any> | null,
55+
recursive = true
5556
): Record<PropertyKey, any> {
5657
if (!from) return to
5758
let key, toVal, fromVal
@@ -66,7 +67,7 @@ function mergeData(
6667
if (key === '__ob__') continue
6768
toVal = to[key]
6869
fromVal = from[key]
69-
if (!hasOwn(to, key)) {
70+
if (!recursive || !hasOwn(to, key)) {
7071
set(to, key, fromVal)
7172
} else if (
7273
toVal !== fromVal &&
@@ -262,7 +263,22 @@ strats.props =
262263
if (childVal) extend(ret, childVal)
263264
return ret
264265
}
265-
strats.provide = mergeDataOrFn
266+
267+
strats.provide = function (parentVal: Object | null, childVal: Object | null) {
268+
if (!parentVal) return childVal
269+
return function () {
270+
const ret = Object.create(null)
271+
mergeData(ret, isFunction(parentVal) ? parentVal.call(this) : parentVal)
272+
if (childVal) {
273+
mergeData(
274+
ret,
275+
isFunction(childVal) ? childVal.call(this) : childVal,
276+
false // non-recursive
277+
)
278+
}
279+
return ret
280+
}
281+
}
266282

267283
/**
268284
* Default strategy.

test/unit/features/options/inject.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -712,4 +712,12 @@ describe('Options provide/inject', () => {
712712
await nextTick()
713713
expect(spy).toHaveBeenCalledWith(2)
714714
})
715+
716+
// #12854
717+
test('should not mutate original provide options', () => {
718+
const hairMixin = { provide: { hair: 'red' } }
719+
const eyesMixin = { provide: { eyes: 'brown' } }
720+
new Vue({ mixins: [hairMixin, eyesMixin], render() {} }).$mount()
721+
expect(eyesMixin.provide).toStrictEqual({ eyes: 'brown' })
722+
})
715723
})

0 commit comments

Comments
 (0)