diff --git a/src/core/util/options.js b/src/core/util/options.js index fc7826dc01d..5e28a408efc 100644 --- a/src/core/util/options.js +++ b/src/core/util/options.js @@ -4,6 +4,7 @@ import config from '../config' import { warn } from './debug' import { nativeWatch } from './env' import { set } from '../observer/index' +import { hasSymbol } from '../util/index' import { ASSET_TYPES, @@ -48,9 +49,15 @@ if (process.env.NODE_ENV !== 'production') { function mergeData (to: Object, from: ?Object): Object { if (!from) return to let key, toVal, fromVal - const keys = Object.keys(from) + + const keys = hasSymbol + ? Reflect.ownKeys(from) + : Object.keys(from) + for (let i = 0; i < keys.length; i++) { key = keys[i] + // in case the object is already observed... + if (key === '__ob__') continue toVal = to[key] fromVal = from[key] if (!hasOwn(to, key)) { diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js index 53f55e1ecf2..3b47ef566f0 100644 --- a/test/unit/features/options/inject.spec.js +++ b/test/unit/features/options/inject.spec.js @@ -188,6 +188,32 @@ describe('Options provide/inject', () => { }).$mount() expect(vm.$el.textContent).toBe('123') }) + + it('should merge symbol provide from mixins (functions)', () => { + const keyA = Symbol('foo') + const keyB = Symbol('bar') + + const mixinA = { provide: () => ({ [keyA]: 'foo' }) } + const mixinB = { provide: () => ({ [keyB]: 'bar' }) } + const child = { + inject: { + foo: keyA, + bar: keyB + }, + template: ``, + created () { + injected = [this.foo, this.bar] + } + } + new Vue({ + mixins: [mixinA, mixinB], + render (h) { + return h(child) + } + }).$mount() + + expect(injected).toEqual(['foo', 'bar']) + }) } // GitHub issue #5223