Skip to content

Commit 769c4dc

Browse files
committed
ensure mutating extended constructor options does not affect parent (fix #4767)
1 parent b1e66b4 commit 769c4dc

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

Diff for: src/core/instance/state.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ const isReservedProp = { key: 1, ref: 1, slot: 1 }
3939

4040
function initProps (vm: Component, props: Object) {
4141
const propsData = vm.$options.propsData || {}
42-
const keys = vm.$options._propKeys = Object.keys(props)
42+
// cache prop keys so that future props updates can iterate using Array
43+
// instead of dyanmic object key enumeration.
44+
const keys = vm.$options._propKeys = []
4345
const isRoot = !vm.$parent
4446
// root instance props should be converted
4547
observerState.shouldConvert = isRoot
46-
for (let i = 0; i < keys.length; i++) {
47-
const key = keys[i]
48+
for (const key in props) {
49+
keys.push(key)
4850
/* istanbul ignore else */
4951
if (process.env.NODE_ENV !== 'production') {
5052
if (isReservedProp[key]) {

Diff for: src/core/util/options.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ strats.data = function (
110110
}
111111

112112
/**
113-
* Hooks and param attributes are merged as arrays.
113+
* Hooks and props are merged as arrays.
114114
*/
115115
function mergeHook (
116116
parentVal: ?Array<Function>,
@@ -155,7 +155,7 @@ config._assetTypes.forEach(function (type) {
155155
*/
156156
strats.watch = function (parentVal: ?Object, childVal: ?Object): ?Object {
157157
/* istanbul ignore if */
158-
if (!childVal) return parentVal
158+
if (!childVal) return Object.create(parentVal || null)
159159
if (!parentVal) return childVal
160160
const ret = {}
161161
extend(ret, parentVal)
@@ -178,7 +178,7 @@ strats.watch = function (parentVal: ?Object, childVal: ?Object): ?Object {
178178
strats.props =
179179
strats.methods =
180180
strats.computed = function (parentVal: ?Object, childVal: ?Object): ?Object {
181-
if (!childVal) return parentVal
181+
if (!childVal) return Object.create(parentVal || null)
182182
if (!parentVal) return childVal
183183
const ret = Object.create(null)
184184
extend(ret, parentVal)

Diff for: test/unit/features/global-api/extend.spec.js

+9
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,13 @@ describe('Global API: extend', () => {
122122
const B = Vue.extend(options)
123123
expect(A).toBe(B)
124124
})
125+
126+
// #4767
127+
it('extended options should use different identitfy from parent', () => {
128+
const A = Vue.extend({ computed: {}})
129+
const B = A.extend()
130+
B.options.computed.b = () => 'foo'
131+
expect(B.options.computed).not.toBe(A.options.computed)
132+
expect(A.options.computed.b).toBeUndefined()
133+
})
125134
})

0 commit comments

Comments
 (0)