From 80f17fa498f5df0388412877799dbd7573c44b2d Mon Sep 17 00:00:00 2001 From: Kael Date: Sat, 1 Dec 2018 09:54:16 +1100 Subject: [PATCH] fix(core): skip mixins and extends if child is already merged (#8870) fix #8865 --- src/core/util/options.js | 21 +++++++++++++------- test/unit/features/global-api/extend.spec.js | 19 ++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/core/util/options.js b/src/core/util/options.js index 5f0d10d3361..2906ddd1910 100644 --- a/src/core/util/options.js +++ b/src/core/util/options.js @@ -378,15 +378,22 @@ export function mergeOptions ( normalizeProps(child, vm) normalizeInject(child, vm) normalizeDirectives(child) - const extendsFrom = child.extends - if (extendsFrom) { - parent = mergeOptions(parent, extendsFrom, vm) - } - if (child.mixins) { - for (let i = 0, l = child.mixins.length; i < l; i++) { - parent = mergeOptions(parent, child.mixins[i], vm) + + // Apply extends and mixins on the child options, + // but only if it is a raw options object that isn't + // the result of another mergeOptions call. + // Only merged options has the _base property. + if (!child._base) { + if (child.extends) { + parent = mergeOptions(parent, child.extends, vm) + } + if (child.mixins) { + for (let i = 0, l = child.mixins.length; i < l; i++) { + parent = mergeOptions(parent, child.mixins[i], vm) + } } } + const options = {} let key for (key in parent) { diff --git a/test/unit/features/global-api/extend.spec.js b/test/unit/features/global-api/extend.spec.js index 4a4a73505b9..f0867ac1b5a 100644 --- a/test/unit/features/global-api/extend.spec.js +++ b/test/unit/features/global-api/extend.spec.js @@ -71,6 +71,25 @@ describe('Global API: extend', () => { expect(calls).toEqual([1, 2, 3]) }) + it('should not merge nested mixins created with Vue.extend', () => { + const A = Vue.extend({ + created: () => {} + }) + const B = Vue.extend({ + mixins: [A], + created: () => {} + }) + const C = Vue.extend({ + extends: B, + created: () => {} + }) + const D = Vue.extend({ + mixins: [C], + created: () => {} + }) + expect(D.options.created.length).toBe(4) + }) + it('should merge methods', () => { const A = Vue.extend({ methods: {