Browse Source

fix(inject): use hasOwn instead of 'in' for provideKey check (#7460)

fix #7284

* fix(Injection with Symbol polyfill): hasOwn instead of 'in'

Symbol polyfill adds a setter on the Object prototype so the 'in' check evaluated to true on every
object

* test(Injected properties): Ensures prototype properties aren't injected

Prototype properties were being injected, so injecting 'constructor' would have hit the first
provide-layer and not yield expected results.
Hiroki Osame 8 years ago
parent
commit
733c1be7f5
2 changed files with 14 additions and 1 deletions
  1. 2 1
      src/core/instance/inject.js
  2. 12 0
      test/unit/features/options/inject.spec.js

+ 2 - 1
src/core/instance/inject.js

@@ -3,6 +3,7 @@
 import { warn } from '../util/index'
 import { hasSymbol } from 'core/util/env'
 import { defineReactive, observerState } from '../observer/index'
+import { hasOwn } from 'shared/util'
 
 export function initProvide (vm: Component) {
   const provide = vm.$options.provide
@@ -52,7 +53,7 @@ export function resolveInject (inject: any, vm: Component): ?Object {
       const provideKey = inject[key].from
       let source = vm
       while (source) {
-        if (source._provided && provideKey in source._provided) {
+        if (source._provided && hasOwn(source._provided, provideKey)) {
           result[key] = source._provided[provideKey]
           break
         }

+ 12 - 0
test/unit/features/options/inject.spec.js

@@ -635,4 +635,16 @@ describe('Options provide/inject', () => {
 
     expect(injected).toEqual('foo')
   })
+
+  // #7284
+  it('should not inject prototype properties', () => {
+    const vm = new Vue({
+      provide: {}
+    })
+    new Vue({
+      parent: vm,
+      inject: ['constructor']
+    })
+    expect(`Injection "constructor" not found`).toHaveBeenWarned()
+  })
 })